做信号处理这些年,我最大的体会是:只要信号是非平稳的,傅里叶变换就有力使不上劲。频率成分随时间变化,噪声把瞬态特征埋得死死的,频谱图上一团糊,你根本不知道某个冲击是什么时候发生的。直到我把小波变换用上,这套自带时间-频率定位能力的分析工具才把我从泥潭里拽了出来。
小波变换(Wavelet Transform)本质上是一种自带变焦能力的分解工具:低频成分用大尺度慢慢看,高频成分用小尺度精细看,时间和频率信息能同时保留。它不挑信号的平稳性,专门处理非平稳、瞬态、突变信号,所以机械故障诊断、地震勘探、图像去噪、金融时序分析这些领域都在重度使用它。我最早接触它是在处理一段振动信号的时候——电机启动过程转速不断爬升,故障特征频率跟着漂移,频谱完全糊成一片,换用小波按尺度拆开,问题立刻清晰了。
这篇不是教科书式的推导,而是我实际用下来的理解、踩过的坑,以及一条可以直接照抄的信号分析流程。如果你正在被FFT解决不了的问题折磨,或者想搞懂小波是什么、怎么选、怎么落地,这篇应该对胃口。
1. 从傅里叶到小波:它到底补上了什么短板
1.1 傅里叶变换的"时间盲区"
傅里叶变换的核心操作,是把一段信号分解成无数个不同频率的正弦波之和,输出频谱里每个峰代表一个频率成分的强度。问题在于,正弦波的时间范围是负无穷到正无穷,等于默认信号从头到尾都由这些频率组成。对平稳信号这个假设成立,但现实世界的信号几乎都不平稳。
举个我处理过的例子:一台电机启动过程中采集振动加速度,转速从几百转爬升到三千转,转频、倍频全部跟着往上漂,同时轴承还叠加着周期性的冲击。把整段数据做FFT,频谱上是糊成一片的宽带,你根本分不清哪个频段的能量对应启动过程中的哪一段。更麻烦的是,一次短暂的轴承冲击在频域里会被摊平到整个频带上,时间信息完全丢失。这不是FFT算错了,而是它的模型假设和实际信号不匹配。
1.2 短时傅里叶的"一刀切"困局
为了拿回时间信息,工程界引入了短时傅里叶变换(STFT):用固定长度的窗口把信号切成一段一段,再对每段做FFT,得到"时间-频率"二维谱图。听起来很美好,可窗口一旦选定,所有频率都用同一个时间分辨率去看。窗口短,频率分辨率差;窗口长,时间分辨率差。海森堡测不准原理直接锁死了这个矛盾,你只能在两者之间妥协。
我做声音分析时对此体会特别深:一段语音里有持续的低频元音,也有突然的辅音爆发。用长窗看不清楚辅音发生的精确时刻,用短窗又分不开两个接近的元音频率。无论怎么调窗长,总有一部分信息是糊的。STFT的"一刀切"源于窗口函数只有一个尺度,而真实信号里的成分,频率越低越需要长时间观察,频率越高越需要短时间定位,两者天然需要不同的透镜。
1.3 小波的想法:用"可变焦透镜"拆信号
小波的思路其实很朴素:不拿无限长的正弦波当基函数,改用一族有限长、会衰减的波形,这就是"小波"名字的由来——它真的是个小小的波。这族波形由同一个母小波通过缩放和平移得到:缩放改变波的长短和频率,平移改变波在时间轴上的位置。拿不同尺度的波去和信号做内积,就能同时知道某个频率成分在哪个时间段出现、强度有多大。
用生活类比:FFT像固定焦距的望远镜,STFT像定了几个焦段的镜头,小波则是一支真正的变焦头——看低频就把镜头拉长,看高频就把镜头缩短,而且焦段还能连续变化。这种自适应能力,就是小波处理非平稳信号的核心优势。
2. 核心概念拆解:母小波、尺度与多分辨率分析
2.1 母小波与缩放平移机制
母小波 ψ(t) 是一个均值为零、时域快速衰减的波形,它必须满足容许条件,简单理解就是"上下波形抵消、总积分为零",这样才能保证变换结果不受信号直流偏置干扰。用母小波生成整个分析基族的方式是:
ψ_{a,b}(t) = (1/√a) · ψ((t-b)/a)
其中 a 是尺度参数,控制伸缩;b 是平移参数,控制沿时间轴的移动。a 越大波形拉得越长、频率越低,a 越小波形缩得越短、频率越高。连续小波变换(CWT)让 a、b 连续变化,计算信号 f(t) 与每个基波的积分,输出一个以时间和尺度为坐标的二维平面——这就是常说的尺度图。
我第一次看到尺度图时有种豁然开朗的感觉:一段混着噪声的冲击信号,FFT只能告诉你"有高频成分",尺度图却能把每一个冲击脉冲的准确时刻、持续宽度和频带范围都标出来,相当于给信号做了一张二维X光片。做故障诊断的人为什么痴迷小波?因为轴承故障信号本来就是"时间上周期性出现、频率上宽频带衰减"的东西,这套工具几乎是照着这个模型设计的。
2.2 离散小波变换与Mallat塔式分解
连续小波变换算起来太慢,实际工程里用的是离散小波变换(DWT)。它把尺度按2的幂次离散化,a=2^j,b=k·2^j,每次把频率范围对半切。Mallat算法把这套数学变成了"高通滤波+低通滤波+隔点抽稀"的塔式结构:每一层先对信号做一对滤波器处理,低通滤波结果得到近似系数(低频轮廓),高通滤波结果得到细节系数(高频细节),然后隔一个点抽一个,进入下一层只拿上一层的近似系数继续分解。
跑三层分解,就相当于把频带切成 0~Fs/16、Fs/16~Fs/8、Fs/8~Fs/4、Fs/4~Fs/2 这样逐级细分的小块,天然形成多分辨率。注意DWT里频率分辨率随层数加深会变好,时间分辨率却变差,这正好对应"低频看趋势、高频看突变"的需求。实际数据里低频往往结构缓慢、需要长时间观察,高频往往是瞬态跳动、需要精准定位,多分辨率分析和信号的物理本质是对得上的。
2.3 小波包变换:高频细分不够用时的解法
DWT有个习惯:每层只对低频近似系数继续分解,高频细节系数基本放那儿不动。可有些场景关心的高频细节恰恰需要继续拆分,比如轴承早期故障的某个高频共振频带,能量微弱但特征明显,被藏在高频细节层里,细看才有意义。小波包变换(WPT)就是把每一层的近似系数和细节系数都继续往下分解,把整个频带分割成任意指定的窄带,再逐个算能量。
代价是系数数量翻倍,计算量和存储量都上去了,而且容易把噪声也拆出"规律感"。我的经验是:先跑一遍DWT,如果目标特征落在某个高频频带上且需要更细的定位,再对小波包做频带筛选,而不是一上来就把全部频带都算一遍。三种常见形式的关键差异我整理成了下面的表:
| 变换形式 | 时间分辨率 | 频率分辨率 | 计算成本 | 适合场景 |
|---|---|---|---|---|
| CWT | 高频好、低频差 | 低频好、高频差 | 高 | 时频可视化、瞬态定位 |
| DWT | 随层数逐级变化 | 随层数逐级变化 | 低 | 去噪、压缩、特征提取 |
| STFT | 固定(由窗长决定) | 固定(由窗长决定) | 中 | 稳态分析、语谱图 |
3. 小波函数怎么选:不同母小波的性格差异
3.1 主流小波家族与各自"性格"
选小波基没有绝对正确答案,就像选螺丝刀一样,得看要拧什么螺丝。我把常见家族整理成了一个速查表:
| 小波家族 | 特点 | 典型场景 | 备注 |
|---|---|---|---|
| Haar | 最简单,像台阶,不光滑 | 理论教学、快速原型 | 对平滑信号会引入锯齿 |
| Daubechies (dbN) | 最常用,N越大消失矩越高、越平滑 | 故障诊断、通用去噪 | 没有解析表达式,用滤波器实现 |
| Symlets | 近似对称,相位畸变小 | 生物信号、图像 | 比同阶db更接近线性相位 |
| Coiflets | 对称性更好,消失矩兼顾 | 图像处理 | 滤波器更长,计算量稍高 |
| Morlet | 复值,连续小波常用 | 时频分析、CWT尺度图 | 无正交基,不能精确重构 |
| Mexican Hat | 实值,形状像墨西哥帽 | 边缘检测、瞬态检测 | 无正交基 |
刚接触小波的人容易犯一个错误:看到有小波叫"最优小波",就直接拿来套自己的数据。实际上不同小波的消失矩、支撑长度、对称性差别很大,直接决定了重构误差和时频定位精度。消失矩高的小波对平滑信号的逼近更准,但滤波器长、边界效应明显;支撑短的小波定位精准,但对振荡信号的描述又不够细腻。选型本质是在这几组矛盾里找平衡点。
3.2 三条选型准则
我自己选型不靠玄学,主要看三点。
第一看目的。做去噪、压缩这类"先分解再重构"的任务,必须用支持正交重构的小波,比如 Daubechies、Symlets、Coiflets;做时频展示、特征定位这种"只看不还原"的任务,Morlet 这类连续小波更合适,因为它的频率定位更直观。
第二看信号形态。信号是突变、冲击主导,选择短支撑的小波,定位更精确;信号是平滑振荡,选消失矩高的长支撑小波,减少波形失真。实测里轴承故障冲击信号用 db4~db8 效果就很好;心电、肌电这类生物信号,我倾向用 sym5 附近,重构波形更自然,不会出现让人误判的伪振荡。
第三看成本。滤波器越长,边界效应越明显、计算越慢,对短信号尤其不友好。数据只有几百个点的话,别硬上 db20 这类长滤波器,用 Haar 或 db2 先搭通流程再说。计算量翻倍带来的收益微乎其微时,果断退回低阶。
3.3 一个实用的兜底选型方法
实在拿不准用什么小波时,我的做法是:先用 db4 跑通全流程,再换 db8、sym5 对比结果,观察重构误差和关键特征是否稳定。如果三种选择结果差别很大,说明信号里存在和小波基相关的伪分量,先回头看看边界处理和数据长度,问题往往不在小波本身上。
另外说句实在话,所谓"最优小波基"在工程上通常以任务指标为准——去噪信噪比高、诊断特征可分性强,就是好小波。别被理论上的最优纠缠住,我见过不少人在选型上纠结几个星期,其实拿 db4 先把流程跑起来,后面优化的收益大得多。
4. 完整实操流程:一个可以照抄的信号去噪与分析Demo
4.1 构造混合测试信号
为了把原理讲透,我构造一个模拟混合信号:50Hz正弦作为平稳背景,200Hz左右的短时脉冲作为瞬态事件,再加一点高斯白噪声。这是典型的"低幅值瞬态埋在高噪声里"场景,FFT很难直接看出来,小波正好派上用场。
import numpy as np import matplotlib.pyplot as plt fs = 1000 # 采样率 1kHz t = np.linspace(0, 2, 2 * fs, endpoint=False) background = 0.5 * np.sin(2 * np.pi * 50 * t) # 平稳背景 pulse = np.zeros_like(t) for idx in [300, 700, 1200, 1600]: # 四个瞬态脉冲 pulse[idx:idx+15] = np.sin(2 * np.pi * 200 * np.arange(15) / fs) noise = 0.3 * np.random.randn(len(t)) # 高斯白噪声 sig = background + pulse + noise随机噪声每次跑结果不同,建议生成后先画一下时域波形,确认脉冲确实被噪声淹没了,再继续后面的分析。
4.2 小波分解:层数怎么定
先做五层DWT分解,这里用db4:
import pywt coeffs = pywt.wavedec(sig, 'db4', level=5) cA5, cD5, cD4, cD3, cD2, cD1 = coeffs分解层数不是越多越好。信号长度对应能分解的最大层数是 log2(N),但工程上更合理的选法是让最后一层近似系数的频带覆盖你关心的"趋势"范围。以采样率1kHz、5层分解为例,每层频带对半切:D1 对应 250~500Hz,D2 对应 125~250Hz,D3 对应 62.5~125Hz,D4 对应 31.25~62.5Hz,D5 对应 15.625~31.25Hz,cA5 则是 0~15.625Hz。
我关心的是200Hz脉冲,它落在 D2 频带里,5层足够,再深没必要。分解完第一步不是急着去噪,而是先把每一层细节系数画出来看看。这一步信息量极大:D2 系数的非零位置正好标出脉冲的时刻,D4 里能看到平稳的背景正弦,D1 基本都是噪声和脉冲的高频边缘。用眼睛确认完分布,再决定阈值怎么加。
4.3 阈值去噪:三步走
小波去噪的套路是"分解—阈值—重构",核心假设是:真实信号在小波域的系数大而稀疏,噪声系数小而均匀。把小的系数压掉,大的留下,再重构就能得到干净信号。
# 噪声标准差估计:用最高频细节系数D1的绝对中位差换算 sigma = np.median(np.abs(cD1)) / 0.6745 thr = sigma * np.sqrt(2 * np.log(len(sig))) # 软阈值处理各层细节系数,重构时把处理后的细节系数装回去 coeffs_clean = [cA5] for d in [cD5, cD4, cD3, cD2, cD1]: coeffs_clean.append(pywt.threshold(d, thr, mode='soft')) clean = pywt.waverec(coeffs_clean, 'db4')注意区分软阈值和硬阈值:硬阈值是把小于阈值的系数直接置零,简单粗暴但会在突变点附近产生振荡;软阈值是把系数值向零收缩,连续性更好、重构波形更平滑,代价是幅值会被压小一点。我日常更常用软阈值,尤其在信号还要做进一步定量分析的场景,宁可幅值偏小也不要引入伪振荡。
还有一个容易被忽略的点:阈值不该对所有层统一。噪声在不同层里的能量分布不同,越往高频,噪声占比越高。低频层阈值应该放宽,高频层可以压得狠一些。通用公式算出来的阈值乘以一个0.6~0.9的系数是常见的做法,具体系数可以用一段已知无故障的参考信号来标定,这是工程上最实用的路子。
4.4 用尺度图定位瞬态事件
去噪只是小波的入门用法,它更大的威力在时频定位。对原始信号做连续小波变换,然后画尺度图,能直接看到200Hz脉冲在时间轴上出现在哪几个位置:
scales = np.arange(1, 64) cwtmatr, freqs = pywt.cwt(sig, scales, 'morl', sampling_period=1/fs) plt.figure(figsize=(10, 4)) plt.imshow(np.abs(cwtmatr), extent=[t[0], t[-1], scales[0], scales[-1]], aspect='auto', origin='lower', cmap='jet') plt.xlabel('时间 (s)') plt.ylabel('尺度 (小尺度对应高频)') plt.colorbar() plt.show()尺度图里,横轴是时间,纵轴是尺度(换算成频率),颜色亮的位置就是能量集中处。噪声在整幅图里像细碎的雪花,而真实的脉冲是一个个竖直的高亮区域,时刻位置精确到采样点。把尺度图里有明显脉冲的时刻和实际设定时刻对比,误差基本在一个采样间隔内。这一步做完,小波的实际价值你就亲身体会到了。
5. 小波变换在典型场景中的落地经验
5.1 机械故障诊断:从小波包能量到故障特征
机械故障诊断是小波最成熟的工业应用之一。滚动轴承出现局部缺陷时,每次滚珠滚过缺陷都会激起一个短暂的高频冲击,冲击以轴承固有频率衰减振荡,而冲击重复频率等于故障特征频率。问题是这个冲击幅值很小、埋没在齿轮啮合等强背景噪声里,FFT几乎无能为力。
工程做法是把信号做三层小波包分解,得到八个频带的系数,分别计算每个频带的能量占比,构成一个特征向量。不同故障类型下,特征向量的分布模式明显不同:内圈故障的特征频带和滚动体故障的特征频带错开,拿这个特征向量喂给分类模型就能做自动诊断。这里我的经验是,先算频谱确认关注频带在哪个范围,再决定小波包的层数,否则频带切分和故障频带错位,能量特征就废了。
5.2 图像去噪与压缩
图像本质上是二维信号,二维DWT对每一行每一列做一维分解,每层把图像分成四个子带:LL(低频近似)、LH(水平细节)、HL(垂直细节)、HH(对角细节)。能量天然集中到LL子带,其余子带系数大部分接近零。
所以图像去噪就变成了对各细节子带做阈值处理,再逆变换;图像压缩就是对小系数做量化舍入,大幅减少存储。JPEG2000标准就是基于离散小波变换的,相比DCT的块状伪影,小波压缩的边缘保留更好,块效应也少。实际处理照片时我的建议是:先观察三个细节子带的系数分布,如果某一方向细节很少,可以对该方向用更狠的阈值,比统一阈值效果明显更好。
5.3 金融时间序列的多尺度分析
金融数据这类非平稳时间序列,用小波拆开也很有价值。用DWT把价格序列分解成近似层(中长期趋势)和多层细节(不同周期的波动),再分别建模,可以避免"趋势和噪声混在一起互相干扰"的问题。
但这里有一个大坑必须提醒:如果用整段序列做分解后再用各分量去"预测"未来,训练时已经用到了未来的信息,属于典型的泄漏,得到的指标再好都不可信。正确做法是流式或分段因果分解——每次只基于当前时刻之前的数据完成分解,再做预测,逐步滚动。这样实现复杂一些,但结果真实可用。这个坑我见过很多团队踩进去,模型训练指标漂亮得离谱,一上实盘就垮掉,根子多半在这。
6. 常见问题与排查技巧实录
6.1 边界效应怎么处理
滤波器在信号两端处理不到完整数据时,需要延拓补齐。常用延拓方式有零填充、周期延拓、对称延拓:周期延拓适合本身周期特征明显的信号,对称延拓对大多数实测数据更自然,零填充会在边界引入突变,需要慎用。
我的实操习惯是:分解前先看一眼信号两端是否为有效数据。如果两端本来就是噪声段,可以直接截掉一段再分析;如果两端是有效信号,用对称延拓,并把结论性判断放在信号中间段,别拿边界系数下结论。边界系数受延拓方式影响很大,同样一段数据换一种延拓,边界重构可能有明显差异,中间段基本不变。
6.2 分解层数到底怎么选
这个问题被问得最多。我看三样东西:一是数据长度,最大层数不超过 log2(N);二是采样率与目标频带,每层频带对半切,一直切到你关心的最低频带那一层就停;三是每层剩余系数的数量,最后几层如果系数只剩十几个,统计意义就很弱了。
顺带提一个工程经验:宁可每层频带宽一点、层数少一点,也别硬切太深。后几层系数少且受边界影响大,特征往往不稳定。我见过有人为了追求"更细的频率分辨率"硬上十层分解,最后低层系数就剩几个非零值,完全没法做统计分析,这就是典型过犹不及。
6.3 阈值去噪效果差的原因
阈值去噪效果差,先排查几个环节。一是噪声类型:很多实测噪声不是白噪声,而是有色噪声,在小波域分布不平均,统一阈值会放走低频段噪声。二是阈值模式:软阈值压幅值,如果信号本身幅值很重要,可以考虑用自适应阈值或加系数补偿。三是信号重构时忘了检查边界的伪振荡,误以为去噪引入的假波形是真实信号。
排查顺序我通常建议:先画各层系数图,看噪声在哪些层占比高,再逐层定阈值,最后对比重构误差和特征幅值变化。别一上来就调参数,盲目调参很难收敛到正确方向。
6.4 用起来太慢怎么办
CWT计算量远高于DWT,这是正常的,工程上要有所取舍。需要实时处理时优先用DWT或小波包,把系数算完直接做特征提取;只有做离线分析、需要漂亮时频图时才跑CWT。如果CWT确实慢,可以缩小尺度范围或者对尺度做对数间隔采样,输出的图几乎一样,但计算量大降。
批量处理时尽量用矩阵运算,把多段数据打包成二维数组一起处理,比循环快一个数量级以上。如果你在代码里发现自己的CWT是逐点积分实现的,别犹豫,换成现成的滤波器组实现,速度能提升几十倍。
最后分享一个我自己的固定动作。拿到任何一段需要分析的信号,我不会直接上小波,而是先画时域波形,再画频谱,然后画一版尺度图,三张图都看完才决定用什么工具。时域图告诉我有没有瞬态和冲击,频谱告诉我主要频率成分在哪里,尺度图告诉我这些成分何时出现。很多时候光靠第三张图就能定位问题,根本不需要复杂的后续处理。小波很强大,但它是螺丝刀不是万能胶,先看清信号再选工具,这比选哪一族小波本身重要得多。