电机故障诊断:小波包变换特征提取与分类实战
发布时间:2026/10/1 5:40:43来源:尧图网络
简介这是一份面向电机故障诊断方向的MATLAB程序集核心围绕希尔伯特黄变换HHT方法设计适用于处理非线性、非平稳的电机电流/电压信号帮助识别定子绕组内外圈绝缘损坏、局部短路等早期故障特征。压缩包内共6个M文件整体仅3KB包含经验模态分解EMD、希尔伯特谱分析、峰值查找等核心脚本可独立运行也可嵌入现有诊断流程便于快速验证HHT算法在故障信号处理中的效果。已有231人学习关注。借助该程序读者可观察故障信号在希尔伯特谱中的频率突变与谐波增强对比正常与异常状态下的时频差异从而掌握从信号分解到故障特征定位的完整分析链路。对于正在研究电机故障诊断、振动分析或非线性信号处理的高校学生与工程师这套轻量级代码提供了可直接复用的算法实现和调试基础配合自身数据即可开展实验。1. 电机故障诊断里那个「程序.zip_变换」到底在解决什么问题做电机故障诊断的人手里最不缺的就是振动信号和电流信号最缺的却是能把故障从信号里「抠」出来的那一步。原始波形看一眼全是噪声直接拿去做分类器输入十有八九精度上不去。标题里那个「变换」指的就是这一层信号处理把时域里纠缠在一起的故障特征搬到频域、时频域让轴承磨损、转子断条、气隙偏心各自留下能区分的痕迹。我见过不少工程师对着采集卡导出的几十兆数据发愁其实问题不在数据量而在变换这一步没选对、参数没调好。这篇笔记就按我自己做电机故障诊断的路径来写先讲清楚各类变换怎么选再给一套能抄的小波包变换特征提取与故障分类流程最后把参数设置和容易翻车的地方一次说透。适合刚接手故障诊断项目、被频谱图逼疯的电气工程师也适合想把自己的算法从仿真搬到实测数据上跑通的研究生。2. 从傅立叶到小波包五种变换的适用边界与选型逻辑2.1 傅立叶变换稳态故障分析的起点电机故障诊断里傅立叶变换是绕不开的起点。它的核心作用是把时域信号拆成一系列正弦波的叠加输出频谱后我们可以直接看某个频率处的幅值是否异常。比如转子断条的特征频率是 (1±2s)f1s是转差率f1是供电频率轴承外圈故障的特征频率是 0.4×fr×nfr是转频n是滚动体个数这些频率在频谱上会以边带的形式出现在基频附近。用Python的scipy.fft就能快速得到频谱代码量不超过十行。但傅立叶变换有个天生缺陷它对非平稳信号无能为力。电机启动过程、负载突变、转速波动时故障特征频率会随时间漂移频谱上表现为一片模糊的宽带隆起根本分辨不出具体特征。我见过有人拿FFT分析启动过程的电流信号折腾了一周也没找到断条边带原因就在这。另外频谱泄漏和栅栏效应也让幅值精度受限需要用窗函数和插值来补救。提示只有电机稳定运行、转速波动小于0.5%时FFT的结果才值得作为诊断依据。启动过程或变载工况请直接往下看小波包变换。2.2 短时傅立叶变换与chirp-z变换时频折中与局部细化短时傅立叶变换STFT是对FFT的简单扩展把信号切成一段段加窗数据分别做FFT再按时间拼成二维时频谱。它的窗口宽度决定了时间分辨率和频率分辨率的取舍——窗越长频率越准、时间越模糊窗越短时间越准、频率越模糊。这个矛盾是固定的没有自由调节的余地。对于转速缓慢变化的工况STFT还能应付转速快速变化时频谱会拖出明显的斜线需要配合转速信号做重采样才能修正好。chirp-z变换则解决另一个问题频率细化。FFT的输出频点均匀分布在整个频带如果我们要精确分析某个窄带附近的频谱细节直接做FFT会浪费大量频点在无关区域。chirp-z变换允许在感兴趣的频率范围比如转子断条特征频率附近±5Hz内加密计算等效于一个高倍放大镜。它的计算量比FFT大但比在整段数据上做超长FFT要划算得多。实际项目里我一般先用FFT粗看全局频谱再用chirp-z精确定位故障特征频率的峰值和边带结构。2.3 小波变换与小波包变换非平稳信号的故障特征提取主力小波变换的出现补上了FFT和STFT的短板它用一组可缩放和平移的小波基函数去匹配信号局部特征在高频处时间窗自动变窄、在低频处频率窗自动变窄。这个自适应特性让它对瞬态冲击轴承点蚀、齿轮断齿特别敏感。但经典小波变换每一层只分解低频逼近部分高频细节不再细分这导致高频段往往是早期故障信息最丰富的区域频率分辨率很差。小波包变换修正了这个缺陷它在每一层同时分解低频和高频分支形成一个完整的二叉树。分解层数为n时得到2^n个等带宽的频带每个频带都能独立重构时域信号。这意味着你可以从重构后的某个频带信号里提取RMS、峰值因子、峭度等时域指标也可以对每个频带信号再做包络谱定位调制频率。对电机故障来说轴承早期故障的冲击能量通常集中在几千赫兹的高频共振带小波包能把这段信号完整分离出来再做包络解调SNR比原始信号直接处理高出一个量级。提示实际项目中小波包变换包络谱是轴承故障诊断的主流组合FFT功率谱更适合转子断条和不对中类故障。两者不是替代关系是协同关系。2.4 拉普拉斯变换与复变函数视角理论铺垫与识别陷阱拉普拉斯变换在故障诊断里不常用作直接工具但它提供了一根理论拐杖把微分方程描述的电机动态模型变换到复频域可以分析系统的极点分布进而解释为什么某些故障会激励出特定频率成分。复变函数与积分变换课程里讲的留数定理、解析延拓在做传递函数分析和闭环系统稳定性判断时是底层支撑。我做控制器参数整定时常借助拉普拉斯域分析但做信号特征提取时不会直接拿它处理实测数据。新手容易掉进一个陷阱觉得变换工具越多越好把拉普拉斯、z变换、希尔伯特变换全堆上去结果特征维度爆炸分类器表现反而更差。特征提取的目标不是做数学表演而是找到物理意义明确、对不同故障区分度高的少数几个频带指标。我在项目评审时看到过一份报告列了40多个特征最后一问半数特征连物理含义都解释不清这种方案到了现场肯定过不了。2.5 交流采集变换电路与信号链路的匹配问题信号变换不只是算法层面的事采集链路本身也会「变换」信号。交流采集变换电路里面传感器输出、隔离放大器、抗混叠滤波器、ADC采样每一级都会引入幅度畸变和相位偏移。常见问题是采样率不够高导致的混叠如果采样率只有10kHz而传感器在20kHz处有共振峰那这个共振峰的能量会被折叠到低频段形成假故障特征。另一个常见问题是滤波器相位失真导致各频率成分的时序错位影响包络分析的精度。我一般会先做一次链路自检给采集系统输入一个已知幅值和频率的正弦校准信号从软件端读取谱峰位置和幅值偏差超过2%就要排查硬件。ADC的位数也很关键16位和24位采集卡在微弱早期故障特征上的差异不是一星半点24位卡能分辨的微小冲击16位卡可能就埋在量化噪声里了。3. 用Python实现「小波包分解→特征提取→故障分类」完整流程3.1 最小可运行的诊断代码从信号到分类结果先把完整流程跑通再逐个拆解参数含义。下面这段代码用一个模拟的轴承外圈故障信号做演示实际使用时把数据读取部分换成你的采集文件即可。依赖库只需要numpy、scipy、pywt和scikit-learn。import numpy as np import pywt from scipy.fft import fft, fftfreq from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score def simulate_bearing_signal(n_samples4096, fs12000, fault_freq96.5): 生成带外圈故障的轴承振动信号模拟数据 实际项目中此函数替换为 data np.loadtxt(your_signal.csv) t np.arange(n_samples) / fs # 转轴旋转基频 30Hz外圈故障特征频率 96.5Hz shaft_freq 30.0 # 故障冲击引起的共振衰减振荡在故障频率处产生周期冲击 resonance 2800.0 # 传感器/轴承结构共振频率Hz damping 0.08 # 衰减系数 signal np.sin(2 * np.pi * shaft_freq * t) * 0.8 # 转频成分 for k in range(int(n_samples / fs * fault_freq)): t_k k / fault_freq idx int(t_k * fs) if idx n_samples: n np.arange(n_samples - idx) # 共振衰减冲击实际故障特征即是这类瞬态冲击的叠加 signal[idx:] 1.5 * np.exp(-damping * 2 * np.pi * resonance * n / fs) * \ np.sin(2 * np.pi * resonance * n / fs) signal 0.15 * np.random.randn(n_samples) # 模拟噪声 return signal def extract_wpt_features(signal, waveletdb4, level3): 小波包分解并提取能量特征 返回各频带能量占比向量长度为 2^level wp pywt.WaveletPacket(datasignal, waveletwavelet, maxlevellevel) energy_list [] # 遍历最底层的所有频带节点节点名称如 aaa, aad, ada, add... for node in wp.get_level(levellevel, orderfreq): coeff node.data energy np.sum(np.square(coeff)) # 频带能量 energy_list.append(energy) energy_list np.array(energy_list) total_energy np.sum(energy_list) 1e-12 # 防止除零 return energy_list / total_energy # ---- 主流程 ---- fs 12000 # 生成两类信号正常信号 和 故障信号 normal_signal np.sin(2 * np.pi * 30 * np.arange(4096) / fs) 0.15 * np.random.randn(4096) fault_signals [simulate_bearing_signal() for _ in range(20)] normal_signals [normal_signal 0.1 * np.random.randn(4096) for _ in range(20)] X, y [], [] for sig in normal_signals: X.append(extract_wpt_features(sig, level3)) y.append(0) # 标签正常 for sig in fault_signals: X.append(extract_wpt_features(sig, level3)) y.append(1) # 标签故障 X np.array(X) y np.array(y) # 划分训练集与测试集 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42) # 随机森林分类器特征维度低树的数量设50即可 clf RandomForestClassifier(n_estimators50, max_depth5, random_state42) clf.fit(X_train, y_train) y_pred clf.predict(X_test) print(f测试集准确率{accuracy_score(y_test, y_pred):.2%})这段代码的逻辑分四层。第一层simulate_bearing_signal模拟了轴承故障的物理特征周期性冲击激励起结构共振产生衰减振荡这是滚动轴承故障最典型的振动形态。第二层extract_wpt_features对信号做3层小波包分解得到8个等宽频带的能量占比。第三层用能量占比组成特征向量训练随机森林分类器第四层输出准确率。参数说明waveletdb4是Daubechies族4阶小波它在时间和频率分辨率之间比较均衡是故障诊断默认起步选择level3把奈奎斯特频带分成8段对12000Hz采样率对应每段750Hz带宽足以把2800Hz共振频带单独分开。random_state42固定随机种子保证复现一致性。能量占比特征的好处是对信号幅值不敏感——传感器灵敏度差异、放大倍数不同都不会影响特征分布。3.2 实际数据接入文件读取与预处理真实项目里的数据文件通常是CSV或二进制格式信号里还混着直流分量、趋势项和工频干扰。预处理步骤直接影响后续分析效果。下面是一个通用的数据接入和预处理片段def load_and_preprocess(filepath, fs12000, cutoff_low5.0, cutoff_high4000.0): 加载原始信号并做基本预处理 :param filepath: 采集文件路径假设第一列为时间第二列为振动幅值 :param fs: 采样率 :param cutoff_low: 去除趋势项的高通截止频率 :param cutoff_high: anti-aliasing低通截止频率 import pandas as pd from scipy.signal import butter, filtfilt df pd.read_csv(filepath) raw df.iloc[:, 1].values.astype(np.float64) n len(raw) # 1. 去均值消除直流分量 raw raw - np.mean(raw) # 2. 高通滤波去掉转频以下的趋势性漂移 b_high, a_high butter(4, cutoff_low / (fs / 2), btypehigh) raw filtfilt(b_high, a_high, raw) # 3. 低通滤波去掉传感器共振频带以外的无关噪声防止混叠 b_low, a_low butter(4, cutoff_high / (fs / 2), btypelow) raw filtfilt(b_low, a_low, raw) return raw这段预处理有几个容易出错的地方。filtfilt是零相位滤波它通过对信号正反各滤一次消除了相位偏移代价是计算量翻倍但对诊断分析来说值得。butter滤波器阶数选4不是拍脑袋——阶数太低过渡带太宽容易把目标频率边缘削掉阶数太高则数值不稳定甚至出现滤波后的信号尾巴上翘。高通5Hz是为了去除电机安装底座的热漂移和直流偏置这个值要低于电机最低转频否则会把真实转频能量也滤掉。低通4000Hz则根据共振频带位置来定如果你的传感器共振频带在更高处需要相应拉高。3.3 多故障类型扩展从二分类到多分类上面的代码只做了正常/故障二分类实际电机诊断至少要对轴承内圈故障、外圈故障、滚动体故障、转子断条做区分。多分类的改动很小为每种故障生成训练样本给不同标签分类器换成多分类版本但这中间有一个关键点——特征维度可能会不够用。3层小波包只有8个频带能量特征对4种故障区分度可能不够需要增加层数或补充时域特征。def extract_hybrid_features(signal, waveletsym8, level4): 小波包能量特征 时域统计特征混合 energy_feat extract_wpt_features(signal, waveletwavelet, levellevel) # 补充时域特征峭度、峰值因子、波形因子 rms np.sqrt(np.mean(np.square(signal))) peak np.max(np.abs(signal)) kurt np.mean((signal - np.mean(signal))**4) / (rms**4) if rms 0 else 0 # 注意峭度对冲击类故障敏感但对幅值scale不敏感 crest peak / (rms 1e-12) return np.concatenate([energy_feat, [kurt, crest]])waveletsym8是Symlets族8阶小波相比db4它的相位更接近线性对冲击特征的时域波形保真度更高。level4产生16个频带配合两个时域特征共18维对大多数电机故障足够。注意峭度指标对单点毛刺特别敏感如果传感器接头松动会产生虚假冲击峭度特征会让分类器误判所以信号接入前务必检查接头和屏蔽层。4. 参数怎么定采样率、小波基、分解层数与窗口长度的取舍逻辑4.1 采样率与抗混叠先定物理上限再谈算法采样率是故障诊断的「宪法」后面所有参数都要服从它。根据奈奎斯特采样定理采样率必须大于最高关注频率的两倍。但工程上建议留出2.56倍以上的余量因为抗混叠滤波器不可能做到理想的陡峭截止。以轴承故障诊断为例传感器共振频带通常在2kHz到10kHz之间想完整捕捉这个频带的能量包络采样率至少要20kHz如果做电流信号分析关注的是供电频率附近的边带10kHz采样率绰绰有余。设置采样率时还要注意一个坑采集卡的采样率上限和存储深度之间的矛盾。采样率提到50kHz一小时的数据量就是50k×3600×4字节≈720MB长期监测场景根本存不住。常见的做法是双通道并行采集一路低采样率做全局趋势监测如2kHz一路高采样率手动触发做精密诊断如48kHz。这个思路和故障诊断的分层策略是一致的——先发现异常再定位原因。4.2 小波基的选择不同故障类型的最佳匹配小波基函数没有绝对的好坏只有匹配度的高低。诊断轴承故障瞬态冲击为主时我一般优先选db10或sym8因为它们有足够的消失矩vanishing moments能有效压制信号中的多项式趋势成分让冲击特征更突出。诊断转子断条时故障特征表现为持续的谐波边带而非瞬态冲击此时需要频率分辨率更好的小波推荐db4或dmey离散Meyer小波时间分辨率不用太高。判断小波基选没选对有一个简单方法分解后重构每个频带信号计算各频带能量占比的集中度。好的基函数会让故障特征能量集中在1到2个频带里而不是均匀铺开。如果各频带能量占比都很接近说明小波基与信号形态不匹配换一个再试。我在调参时会把db2、db4、db8、db10、sym8这五个基都跑一遍画能量分布热力图五分钟就能看出哪个分离度最高。提示小波基的切换对最终分类准确率的影响通常在5到15个百分点之间。项目里如果分类精度卡在90%上不去先查小波基再查分解层数。4.3 分解层数与频带宽度从诊断对象反推分解层数n决定了末端频带数量2^n和每个频带的宽度fs/2^n。层数太少故障特征和转频成分混在同一个频带里分离不开层数太多单个频带过窄能量分散导致特征不稳定还会显著增加计算量。实际项目中3到5层是常用区间。具体怎么选看你的目标频带宽度需求。例如采样率12000Hz开关频率附近有一个2800Hz的共振峰3层分解后每个频带宽度是12000/81500Hz实际有效到奈奎斯特6000Hz2800Hz落在第三个频带1500到3000Hz内能完整包含但带外噪声有点多。想要更精细用4层分解频带宽度750Hz2800Hz会被拆到多个相邻频带这时可以在特征提取时把相邻几个优势频带合并成一个特征既保留了频率选择性地又避免了能量分散。4.4 窗口长度与重叠率短时处理的时序敏感性小波包变换可以对整段信号做一次分解也可以加滑动窗口分段处理。分段处理能捕捉故障特征随时间的变化趋势——比如故障早期特征间歇性出现分段后可以看到特征参数的时间序列波形这对趋势预测非常有价值。窗口长度直接决定特征的时间分辨率窗短则特征随时间变化清晰但每个窗内的谱估计方差大窗长则估计稳定但突变被平均掉。轴承故障诊断我习惯用4096或8192点窗口在12kHz采样率下对应0.34秒或0.68秒这个长度既能保证每个窗口内有足够多的冲击脉冲又不会把转速波动引起的特征漂移平均掉。重叠率设50%保证相邻窗口之间特征平滑过渡也避免冲击恰好落在窗口边界被截断丢失。计算量允许的话重叠率可以提高到75%特征时序曲线会更光滑代价是特征数量变成原来的两倍。4.5 转速波动下的变换修正阶比跟踪与角域重采样电机负载变化或供电频率波动时转速不再恒定所有与转频相关的故障特征频率都在漂移。这时直接从等时间间隔采样数据里做FFT或小波包变换特征峰会比理论值宽好几倍严重时直接消失。工程上的标准解法是阶比跟踪同时采集转速脉冲信号把等时间间隔的数据重采样到等角度间隔的角域数据再在角域做FFT故障特征频率就从「Hz」变成了「阶次」不再受转速波动影响。角域重采样的实现常见做法是用转速脉冲的过零时刻拟合转速曲线再对原始信号做三次样条插值。这块代码写起来有二三十行建议直接用scipy.interpolate.CubicSpline。没有转速脉冲通道时可以用短时傅立叶变换估计瞬时频率再以瞬时转频为基准做重采样精度稍差但也能用。需注意角域重采样之后原来的采样率概念失效下文所有小波包频带的物理频率标注都变成阶次标注读图习惯要相应调整。5. 电机故障诊断避坑五个让算法工程师头疼的典型事故5.1 频谱泄漏假峰把健康电机诊断成故障现象对一段正常电机的振动数据分析时频谱上在转频边带出现异常峰值按公式推断的故障特征频率和理论值几乎重合一度以为真的坏了。原因FFT要求分析窗口内是整数个信号周期实际数据几乎不可能满足。窗函数截断造成的频谱泄漏让能量从主瓣扩散到旁瓣旁瓣在特定频率处叠加形成假峰。解决第一改用Hanning窗或Blackman-Harris窗主瓣宽度增加但旁瓣衰减加快第二增加采样点数做更长FFT频率分辨率提高后假峰会被摊薄第三做加窗FFT前先对信号做去均值直流分量泄漏到低频段的能量会掩盖真实故障信息。我现在做初步分析一律用汉宁窗只有做精确幅值测量时才换平顶窗。5.2 包络分析方向错误高频共振频带没找对包络谱一片模糊现象对轴承振动信号做包络谱分析理论上的故障特征频率完全看不到谱图上只有一片低频噪声。原因包络分析的原理是对高频共振带做带通滤波后再解调。如果带通滤波的频带设置偏离真实共振区解调出来的包络信号里故障冲击成分极少自然看不到特征峰。解决先用功率谱找出共振频带的位置。轴承故障的共振频带通常在1kHz到10kHz之间表现为一个明显隆起的高频平台。带通滤波器的中心频率设在这个平台中央带宽覆盖平台主要区域。不同转速不同负载下共振频带会偏移几个百分点项目上线前要在每个工况下各采集一段样本重新标定。注意每次更换传感器或改变安装位置后共振频带可能整体平移。5.3 训练集与测试集发生数据泄露准确率虚高到99%现象同一批采集数据切出一部分做训练一部分做测试分类准确率99%但换上现场新采集的数据准确率直接掉到70%。原因数据切分用了train_test_split默认的随机划分同一段连续信号的前后半段被分到训练集和测试集两边的噪声水平和工况状态高度相似相当于「开卷考试」。模型记住的是数据分段特性而非故障本身的模式。解决按时间段切分——前70%时间窗口的数据做训练后30%时间窗口的数据做测试。更严谨的做法是每台电机单独留出几天数据做测试集确保训练集和测试集来自不同时间段和不同工况。我判断一个诊断模型是否可靠会额外要求「跨电机验证」用A电机的数据训练B电机数据测试准确率不低于85%才敢上现场。5.4 采样不同步导致电流与振动特征相位错乱现象同时采集电流信号和振动信号做联合诊断发现两个通道的特征频率数值都对得上但相位关系随机变化无法做复合特征提取。原因采集卡各通道之间存在启动时间差或电流互感器与加速度传感器的群延迟不同。两路信号的采样时刻没有对齐相位差是不确定量。某些高级特征如电流与振动的相干函数对相位极度敏感一个通道几个毫秒的偏差就会毁掉全部计算结果。解决采集前用一个方波测试信号同时输入所有通道在软件里计算通道间的时延差并补偿。常见做法是在采集程序里设定统一的触发源让所有通道在同一时钟沿开始采样。如果硬件不支持就在算法里用互相关函数做事后对齐先估计时延再对信号做整数点平移。注意时延估计需要足够的信噪比信号太干净反而估计不准。5.5 低频干扰淹没故障边带FFT一片红看不到细节现象对电机振动频谱做对数幅度显示低频区域所有频点都很高转频边带结构完全看不出来。原因电机机座振动、地脚松动、基座共振等低频干扰能量远大于轴承故障信号动态范围过大时故障边带的幅度细节被压缩到看不见。解决先用高通滤波器滤掉50Hz以下成分或者用包络分析把分析频带搬到高频共振区。此外对数频谱的动态范围调小也能帮忙用线性幅度显示更有利于观察边带细节。我在看频谱时习惯同时开三张图全频带线性幅度、0到500Hz细节频谱、包络谱三张图配合才能快速定位问题。6. 把诊断模型推进到现场验证方法与一个实用技巧模型在测试集上跑出高准确率只是第一步现场部署前我会固定执行一套验证流程。第一关是混淆矩阵和特征可视化把每类故障的特征向量做t-SNE降维画到二维平面能看到不同类别聚成清晰但间距合理的类簇才算通过——如果类簇重叠严重说明特征本身分离度不够调参数没用了。第二关是工况泛化验证用50%负载训练验证25%、75%、100%负载数据上的表现准确率落差超过10%就说明模型过拟合了某个负载点的特征需要加入多工况训练数据。第三关是抗噪声测试向信号里加不同信噪比的白噪声观察准确率的下降曲线SNR从40dB降到10dB准确率下跌不超过15%才算皮实。最后一个实用技巧我一直在用把故障特征的历史时序曲线做成趋势报表。对同一台电机每天固定采集一个窗口数据提取小波包能量特征后画成时间序列。早期故障的特征值不是突然变化而是持续的小幅漂移。我处理过一个大型电机案例轴承外圈特征频带的能量占比在六周内从0.08缓慢升到0.14幅度不大但趋势明确提前两周判断出轴承磨损利用计划停机完成了更换。单次诊断只能回答「有没有故障」趋势诊断才能回答「故障发展到什么阶段了」——后者才是预测性维护真正值钱的地方。现场部署那段时间我也翻过车最深的教训是换一个传感器、换一根电缆、甚至改动接地方式特征基线就可能偏移20%以上原来调的阈值全部作废。所以我现在每台设备上线后先跑一周采集基线数据之后的报警阈值都相对自己的基线设定而不是用实验室或相邻设备的参考值。希望这些经验能帮你在自己的诊断项目里少走一段弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网