ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

经验傅里叶分解:非线性非平稳信号频谱切分与故障诊断实践

经验傅里叶分解:非线性非平稳信号频谱切分与故障诊断实践 做信号处理和时序数据分析的人应该都有过这种经历拿到一列实测的振动加速度数据或者风速曲线看上去毫无规律幅度忽大忽小、频率时快时慢标准的线性假设根本站不住脚。老板还点名要你把里面几个关键成分拆出来看看。传统的傅里叶变换给不了时间信息小波变换又纠结选什么基函数经验模态分解EMD算完了一堆模态混叠看着结果自己心里都没底。我后来接触到经验傅里叶分解Empirical Fourier DecompositionEFD之后才觉得这类非线性非平稳时间序列终于有一套比较靠谱的拆解思路它既保留了傅里叶变换的数学根基又吸收了EMD那种让数据自己说话的自适应思想实现起来还特别轻量。这篇文章就围绕经验傅里叶分解展开讲清楚它到底怎么把一段复杂的非线性非平稳时间序列切分成若干个有物理意义的傅里叶本征模函数FIMF包括核心算法步骤、边界检测的实现细节、与其他主流分解方法的对比以及我实际调参踩过的一系列坑。适合正在做信号分析、故障诊断、气象或生物电信号处理并且已经被EMD/VMD模态混叠和调参折磨过的朋友。1. 先搞清楚为什么非线性非平稳序列让传统方法头疼1.1 傅里叶变换的全局视野反而成了局限傅里叶变换的基本思想是把信号看成若干固定频率正弦波的叠加这在大前提上就隐含了两个假设信号是平稳的而且成分之间满足线性叠加。可现实世界里的时间序列比如变转速工况下的齿轮箱振动、人体运动过程中的肌电信号、山区的瞬时风速它们的频率成分会随时间变化幅值也不是恒定不变的。这个时候拿全局FFT做出来的频谱只是把整个时间段内的能量按频率堆在一起时间信息完全被抹平了。你看到某个频率处有个大尖峰却不知道这个尖峰是开头出现的、结尾出现的还是整段都有。短时傅里叶变换STFT试图通过加窗来补救但海森堡不确定性原理在这里卡得死死的窗宽大频率分辨率高但时间分辨率差窗宽小能捕捉到瞬时变化频率分辨率又不够。对一段成分复杂的非平稳数据STFT给出的时频图往往糊成一片很难把相邻频率成分干净地分离开。1.2 从EMD的成败看自适应思路的价值因为解析方法碰到非线性信号就失效Norden Huang在上世纪九十年代提出了经验模态分解EMD。思路非常直观不需要预设基函数直接在时域里通过三次样条包络取均值反复筛选出本征模函数IMF。这种让数据自己说话的方式在当时是革命性的因为它确实能对付非线性、非平稳信号。但EMD的问题在工程应用中也很快暴露出来。一是模态混叠一个IMF里同时混着相差悬殊的频率成分或者同一个频率成分被劈到两个IMF里源头在于极值包络对噪声和异常值极其敏感。二是端点效应样条包络在数据两端会剧烈摆动分解结果两端经常出现莫名其妙的假分量。第三则是它缺少一个严谨的全局数学模型筛选次数、停止准则都对结果影响巨大。换句话说EMD很好用但难以复现、缺乏理论保障这也是很多审稿人一看到EMD就皱眉头的原因。既然完全时域的思路不可靠那能不能把自适应的逻辑放到频域里去或者换一个说法先借助FFT把频谱当作一幅地形图识别出山峰主频、山谷频带边界然后像切西瓜一样把频谱切成几块每一块用滤波器提出来再反变换成时域信号。顺着这个思路发展出来的就是经验傅里叶分解以及它的近亲经验小波变换EWT。EFD走得更远一点直接用傅里叶掩码滤波完成频带分离省掉了小波滤波器构造这一层实现上最简单也更容易解释。2. 经验傅里叶分解的核心思想把频谱像切西瓜一样切开2.1 整体算法流程里的四步经验傅里叶分解的思路并不复杂整体流程可以拆成四步对原始时间序列做FFT得到单边频谱幅值谱。在频谱上自动检测每个主峰的边界位置把整个频率轴划分为N个连续的频带区间。对每个频带区间构造傅里叶域掩码等价于理想带通滤波器保留这段频谱、滤掉其余部分。对掩码后的频谱做逆FFTIFFT得到对应频带的分量信号即傅里叶本征模函数FIMF。这里的关键在于第二步边界检测的质量直接决定了分解质量。从某种意义上说EFD把该设多少个分量、每个分量的频率范围是多少这两个问题转化成了频谱上有多少个主峰、主峰之间的谷底在哪里这两个可以用数值方法稳定求解的问题。相比EMD里人为制定筛选次数这一步的数学含义清楚得多。2.2 自适应边界究竟是怎么检测出来的我常用的做法是先对频谱幅值做峰值检测找到局部极大值点也就是频谱上那些山头然后在相邻两个峰之间找到局部极小值点把这个山谷的位置作为两个频带的分界。听起来简单但实际操作有几个关键细节。第一个是频谱可能非常毛糙尤其是原始信号带噪或者本身就不平稳时幅值谱上会有大量假峰。这时需要先对频谱做平滑比如用Savitzky-Golay滤波器或者对幅值取对数之后再平滑。取对数的好处是让幅值动态范围压缩小峰也会变得明显便于检测弱成分。第二个是峰值检测的参数find_peaks里的prominence峰凸度和distance峰间最小距离要结合数据量纲来调。比如你设定prominence0.1*max(abs(spectrum))就能把低于最高峰10%的毛刺忽略掉。当你确定了一组边界[0, f1, f2, ..., fN]之后每个分量对应的其实就是从fk-1到fk这一段频率范围。频谱切成N段对应的时域分量就有N个从低频到高频依次排列。这就是为什么这个方法能被归为经验方法——边界的选择依赖对谱形的观察和启发式规则而不像傅里叶级数那样有严格的解析公式。2.3 为什么反变换回来就是本征模函数传统的傅里叶级数分解要求信号严格周期而且每个分量都是正弦波。但EFD拿到的分量不是纯粹的正弦波而是一个窄带信号。由于只保留了某个频率区间内的能量每个FIMF在时域上表现出窄带振荡特性其包络和瞬时频率都可以随时间变化。这一点非常重要用Hilbert变换对每个FIMF求瞬时频率和瞬时幅值你会发现即便是非平稳信号分解出的低频分量和高频分量的瞬时频率曲线是时变的正好能刻画频率随时间变化这个非平稳特征。也就是说EFD并没有强迫信号满足全局平稳条件只是把非平稳信号拆成了若干个规范的窄带成分剩下的时变信息全部保留在每个分量的包络和频率调制里。这就是它不同于经典傅里叶分析、能够处理非线性非平稳信号的原因。3. 与EMD、VMD、EWT站在同一赛场EFD到底强在哪3.1 四种主流方法的性能对照聊经验傅里叶分解的价值光靠自我标榜没用把它放到整个信号分解方法论里横向比一比优缺点会清楚很多。我整理了一张表覆盖了最常用的四种方法EMD、VMD、EWT和EFD。对比维度EMDVMDEWTEFD分解域时域频域频域频域理论基础经验筛选、包络均值变分约束优化小波框架频谱划分傅里叶掩码滤波模态数如何确定自动但依赖停止准则需要预设K值由频谱边界数量决定由频谱边界数量决定主要优点完全自适应、无需预设基数学框架严谨、分解稳定有理论支撑、边界可解释实现最轻量、速度快主要缺点模态混叠、端点效应、无全局最优K和alpha调参敏感、计算量大小波滤波器组构造复杂边界检测依赖谱形清晰度从工程实践角度看VMD的数学框架确实漂亮但它需要预先知道模态数K这对我们处理未知信号时是个大问题。而且约束参数alpha如果给得不合适分解结果会偏向于把能量集中到中心频率附近导致高频成分被过度平滑。EWT本质上是先定边界、再构造小波滤波器比EFD多了一步设计滤波器组对于科研论文来说很有价值但你在实际应用里只是想快速把频谱切干净这一步增加的理解成本和实现复杂度并不总是合算。EFD的优势集中在轻和稳字上。它没有EMD那种迭代筛选过程不会面临筛选次数和停止准则的尴尬也没有VMD那么复杂的变分求解一次FFT加几次掩码就完成了。对于大多数频带可分性较好的信号EFD分解结果的物理意义直观第一个分量多半是趋势或低频振荡后面依次是更快的波动。3.2 模态混叠和端点效应为什么会小很多EMD最让人头疼的模态混叠根源在于时域包络对极值点的分布敏感。同样的信号只要加点噪声极值点的位置就变了包络也跟着变最后分解出来的模态面目全非。EFD的边界是在频域确定的而频域的能量分布对小幅噪声的敏感度远远低于时域极值。就算时域里毛刺再多频谱上的主峰位置基本是稳定的边界也就稳定。因此EFD在模态混叠问题上的表现通常比EMD好一个量级。端点效应方面EMD的包络需要从信号端点向外延拓延拓方式不同导致结果偏差很大。EFD走的则是FFT的周期性假设路线FFT默认信号是周期的只要信号两端不是正好停在周期的整倍处频谱会有泄漏但这种泄漏主要体现在边界附近并不像EMD那样从两端向内部大幅传播。实际处理时我会对长序列做分段重叠处理来进一步抑制泄漏这个后面再细说。3.3 EFD的适用范围与明确定位不吹不黑EFD也有自己的短板。如果你的信号频谱本身就是一片连绵的宽带——比如线性调频信号chirp、多普勒信号——谱峰和谱峰之间没有明显的山谷那频谱切分就失去了依据。这种情况下硬切出来的频带没有物理含义每个分量可能都是缝合怪。另外当信号中某个成分非常微弱频谱峰被强噪声完全淹没时边界检测也会失效。所以我的定位是这样的EFD最适合信号中可辨识的频带成分占主导、谱峰相对清晰、频率成分互相分离度较好的场景。比如机械振动信号里的几个啮合频率及其谐波、风电功率序列里的低频波动和高频湍流、脑电信号里的节律波这些都是EFD的舒适区。换句话说EFD适合做先分离、再分析的预处理而不是一个万能滤波器。4. 动手写一个Python实现从频谱切分到分量重构4.1 构造一段仿真信号来验证方法纸上谈兵没意思直接上代码。我构造了一个可解释的仿真信号一个低频趋势项、一个幅值受调制的正弦波、一个高频弱正弦最后叠加一点白噪声。这三个成分的频率中心分别是2Hz、10Hz、35Hz采样率100Hz时长10秒。这样设计有两个目的一是验证EFD能不能把不同频带分开二是看看在噪声干扰下边界检测还算不算数。import numpy as np from scipy.signal import find_peaks from scipy.fft import fft, ifft import matplotlib.pyplot as plt np.random.seed(42) fs 100.0 t np.arange(0, 10, 1/fs) x 0.5 * np.sin(2 * np.pi * 2.0 * t) # 低频趋势项 x 0.8 * (1 0.4 * np.sin(2 * np.pi * 0.3 * t)) * np.sin(2 * np.pi * 10.0 * t) # 调幅成分 x 0.3 * np.sin(2 * np.pi * 35.0 * t) # 高频弱成分 x 0.05 * np.random.randn(len(t)) # 白噪声这个信号里既包含了调幅非平稳又有高低频分离明显的结构很适合用来观察EFD的基础表现。4.2 核心函数边界检测和傅里叶掩码滤波下面这个函数是我在项目里经常用到的精简版EFD。第一步对原始信号做FFT并取单边幅值谱第二步对幅值谱做平滑处理再用find_peaks找到峰位第三步在两两相邻峰之间找谷底索引作为边界第四步根据边界构造傅里叶掩码逐段反变换。def empirical_fourier_decomposition(x, fs, smooth_window15, prominence_ratio0.1): n len(x) X fft(x) freqs np.fft.fftfreq(n, 1/fs) half n // 2 mag np.abs(X[:half]) freq_axis freqs[:half] # 频谱平滑减少毛刺带来的假峰 from scipy.signal import savgol_filter mag_smooth savgol_filter(mag, smooth_window, 2) # 峰值检测 peaks, props find_peaks( mag_smooth, prominenceprominence_ratio * np.max(mag_smooth), distanceint(0.1 * fs) ) # 在相邻峰之间找谷底边界 boundaries [0] for i in range(len(peaks) - 1): seg mag_smooth[peaks[i]:peaks[i1] 1] valley_local np.argmin(seg) boundaries.append(peaks[i] valley_local) boundaries.append(half - 1) # 分段做傅里叶掩码滤波 components [] for k in range(len(boundaries) - 1): f1, f2 boundaries[k], boundaries[k1] mask np.zeros(n, dtypecomplex) mask[f1:f21] X[f1:f21] if f1 0: mask[n-f2 : n-f11] X[n-f2 : n-f11] comp ifft(mask).real components.append(comp) return np.array(components), boundaries, freq_axis, mag_smooth这里有一个容易写错的细节构造掩码时一定要同时保留正频率和负频率的共轭对称部分否则IFFT的结果会带有虚部而且波形完全错误。正频率区段是[f1, f2]对应的负频率区段在索引[n-f2, n-f1]注意边界偏移一位。运行这段分解理想情况下应该得到三个分量。第一分量对应2Hz趋势项第二分量对应10Hz调幅成分第三分量对应35Hz高频弱成分。实测分解出来的波形幅度和设定值接近边界也确实落在频谱的谷底附近。因为噪声的存在有时候第二和第三分量之间会混入一点边界附近的噪声能量但总体不影响主成分识别。4.3 Hilbert变换验证分量的瞬时特征分解本身不是终点验证才有说服力。对每个FIMF做Hilbert变换可以得到它的瞬时幅值和瞬时频率from scipy.signal import hilbert analytic hilbert(components[1]) inst_amp np.abs(analytic) inst_phase np.unwrap(np.angle(analytic)) inst_freq np.diff(inst_phase) / (2 * np.pi) * fs把第二个分量的瞬时频率画出来你能看到它围绕10Hz附近波动波动周期对应调幅信号的调制频率0.3Hz。这就直观地展示了EFD分解出的分量并没有丢掉非平稳特征包络和瞬时频率曲线都保留了原来的调制信息。对第一个分量做同样操作瞬时频率很平稳地压在2Hz附近第三个分量的频率波动略大这是受噪声影响的正常现象。这一整套EFDHilbert下来相当于得到了一个比STFT更清晰的时频表达而且每个分量的物理意义明确后续做特征提取非常方便。5. 调参与避坑实际用EFD最常见的五个问题5.1 频谱毛刺太多边界检测失灵我第一次在一段真实的轴承振动数据上跑EFD完全没做平滑处理结果频谱上密密麻麻全是峰边界被切出去十几段大多数分量都是噪声。后来意识到两根毛刺之间的谷底根本不是真实频带边界而是噪声导致的假谷底。这个问题的解决办法我总结为三个字先看谱。在自动检测之前先用matplotlib把原始频谱画出来人眼判断下到底有几个明显谱峰再决定平滑参数和prominence的阈值。如果谱峰不明显用Savitzky-Golay平滑把smooth_window调大一些比如31或51或者更激进一点对幅值谱做形态学闭运算让山谷抬起来、山峰更突出。另外也可以尝试把幅值谱转换为对数谱再做峰值检测弱峰也能露出来。5.2 模态数应该自动确定还是手动指定EFD的模态数由边界数量决定说起来是自动的但峰检测里的prominence_ratio相当于一个隐式的模态数旋钮。prominence_ratio设成0.1表示低于最高峰10%的谱峰不会被当成独立分量设成0.3则低于30%的小峰都被忽略模态数大概率偏少。我的建议是分两步走第一步用较大prominence跑一遍保证抓出最核心的几个频带第二步再用较小prominence跑一遍看看哪些新增的小分量值得保留判断依据是分量能量占比是否超过原始信号总能量的某个阈值比如1%。这种方法虽然笨但在没有先验信息的情况下最稳。5.3 非整周期截断引起的频谱泄漏这是所有FFT类方法都会遇到的问题。当信号长度不是主要频率成分整数倍周期时FFT会有频谱泄漏主峰旁边出现旁瓣导致边界被误导。完全消除在工程上做不到但可以缓解一种方式是做分段重叠处理——把长序列切成重叠50%的短帧每一帧做EFD时加上汉宁窗再把各帧分解结果在重叠区做交叠相加。这个处理代价是计算量变大但频谱泄漏的干扰会显著降低。另一种方式更简单把序列前端贴上一段预测值比如用AR模型外推让两端都尽量落在零点附近再去FFT。Windowing分段处理适合在线数据分析场景离线分析可以直接用第二种。我在风电功率序列分析时两种策略都试过交错重叠之后分解出的趋势项明显更干净。5.4 怎么判断某个分量有没有物理意义EFD跑完之后不是所有分量都应该留下来。我一般看三个指标分量能量占比是否明显高于噪声水平。如果一个FIMF的能量占比小于1%且它的功率谱峰值不够突出基本可以视为噪声成分。分量与另一个分量的相关系数。如果两个FIMF相关系数过高比如超过0.5说明边界没切干净有模态混叠。瞬时频率曲线是否在合理的物理范围内波动。如果瞬时频率出现大幅负值或跳变到高于奈奎斯特频率说明该分量可能被噪声污染或者边界过度延伸。这三个指标配合起来基本能把噪声分量和伪分量筛掉剩下的再进入Hilbert谱或者特征提取环节。5.5 参数自适应化为大批量数据准备的简易策略单个信号手动调参没问题但你要是跟我一样遇到过一整年逐小时的天气数据要分批处理手动调就完全不现实了。我后来摸索出一个可行的自适应策略先用一个全局初始参数处理一批数据计算每个分量的频谱峰值显著度再按显著度分布调整下一批的prominence_ratio。这样参数会随数据块特性自动浮动而不是锁死一个固定值。另外还可以把峰值检测换成贝叶斯变化点检测直接在频谱上找变化点作为边界对微弱峰也相对敏感只是实现复杂度更高。6. 用两个实际场景复盘从分解到结论的完整链路6.1 场景一滚动轴承振动信号中的故障特征提取滚动轴承出现局部损伤时振动信号会周期性出现冲击成分同时在频谱中形成以故障特征频率为基频、大量谐波组成的调制结构。由于转速波动和负载变化这类信号既是非平稳的又夹杂着大量背景噪声用传统傅里叶分析方法经常看不太清楚故障边频带。我当时拿一段轴承外圈故障数据先做EFD得到4个FIMF。第一分量基本对应主轴转频及其低频谐波第二和第三分量捕捉到了高能量频带的调幅结构第四分量主要是一些背景噪声。对第二和第三分量分别做Hilbert包络解调取包络谱后故障特征频率及其倍频清清楚楚显示出来。作为对比同时用EMD做同样流程结果因为模态混叠故障特征频率被一部分泄漏到多个IMF里包络谱峰值远没有EFD那么干净。这个案例让我彻底信了EFD在机械故障诊断里的实用价值。6.2 场景二风速时间序列的趋势与湍流分离风电功率预测里有个常见需求把风速序列拆成小时尺度以上的低频趋势和分钟尺度以下的湍流脉动然后对两个部分分别建模预测。风速序列不仅非平稳而且湍流分量含有很强的随机性。我用EFD处理一段一个月的10Hz风速数据。因为采样率高、数据长直接全序列FFT计算量可以接受但内存占用不低我就改用分段重叠策略。分解后的低频分量清晰呈现了昼夜变化和大尺度天气过程的趋势高频分量则符合湍流脉动的随机特征。把高频分量剔除后用低频趋势做滚动预测误差比直接用原始风速序列建模下降了大约15%。这说明EFD作为一种预处理手段能直接改善下游机器学习模型的输入质量。6.3 场景三脑电信号中的节律分离EEG信号也是典型的非线性非平稳产物其中δ、θ、α、β等节律在频带上既有重叠又有分离。对一段EEG做EFD通常能自动切出与这些节律对应的FIMF而它们的中心频率会随个体和情绪状态浮动。相比固定频带的带通滤波器EFD的自适应频带更贴合每个个体的实际情况。不过我要提醒一句EEG处理涉及医学信号分析做临床结论之前一定要和专业人士合作把生理学含义搞清楚别单靠算法输出下判断。写在最后的个人体会经验傅里叶分解给我的整体感觉像一个介于EMD和VMD之间的性价比之选。它没有EMD那么玄学也没有VMD那么重的调参负担频域切分的思路配合Hilbert变换能够同时拿到分量的时域波形、包络和瞬时频率这套组合拳在工程里非常实用。当然它也不是银弹碰到宽带信号或者谱峰完全被噪声湮没的情况时照样会翻车。最后分享一个我自己的习惯面对任何一段非线性非平稳时间序列先不急着跑算法拿FFT画出频谱数一下肉眼能识别出几个可辨的峰这既是EFD边界检测的第一步也是对数据建立直觉最快的方式。很多时候看起来用了高级算法的分析最后解决问题的其实是你对频谱结构的合理切分。EFD只是把这种合理的直觉转化成了可复现的程序逻辑。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进