多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

小波包变换与SVM在电机故障诊断中的应用实战

小波包变换与SVM在电机故障诊断中的应用实战 简介面向电机故障诊断研究与应用场景该代码包以希尔伯特黄变换HHT为核心提供针对非平稳、非线性故障信号的分析工具可用于识别电机内外圈故障特征。压缩包共6个.m文件大小仅3KB覆盖经验模态分解、希尔伯特谱分析、FFT辅助分析等关键步骤脚本轻量且功能聚焦适合学习与复现。已有231人学习尤其适合电力电子、机械故障诊断方向的学生快速上手时频分析与非平稳信号处理方法。通过内置的绘图与分析脚本可直观观察瞬时频率和幅值变化定位内外圈故障引起的异常频率成分借助分解与峰值检测工具能系统梳理“EMD分解—Hilbert谱绘制—故障特征判读”的完整流程帮助读者掌握HHT在电机故障诊断中的工程应用为后续预防性维护和健康管理奠定基础。1. 电机故障诊断绕不开「变换」为什么原始波形看不出毛病电机故障诊断最坑人的地方在于你把加速度传感器贴在外壳上采到的原始振动信号肉眼看起来和正常运转时几乎没有区别。轴承外圈剥落、转子断条、齿轮点蚀这些故障的冲击成分会被大振动淹没时域波形上只有偶尔冒出来的一丁点毛刺谁也不敢凭这个下结论。所以电机故障诊断一定要做「变换」——把时间信号映射到频域或其他空间让故障特征从背景噪声里显形。本文要讲的这套方案核心是把「程序.zip」这类变换诊断代码链路彻底跑通从振动信号采集与滑窗切分、小波包变换提频带能量特征到分类器识别电机故障类型。里面涉及采样率设置、小波基选择、分解层数权衡、特征归一化时机等一堆参数参数错了再花哨的算法也是纸上谈兵。这套思路适合正在做电机故障诊断落地、被特征提取折磨或者在选型阶段犹豫该用傅立叶还是小波包的从业者照着做能少走不少弯路。2. 从傅立叶到小波包故障信号变换到底在变什么2.1 傅立叶变换的局限稳态假设让电机故障信号丢信息电机故障诊断里最经典的变换一定是傅立叶变换它的作用是把时域信号拆成不同频率的正弦波叠加。对平稳信号来说这个变换非常漂亮频谱上几条清晰的谱线哪里有问题一目了然。但电机实际运转时的振动信号根本不是平稳的轴承故障会产生周期性冲击转子的负载波动会让幅值忽大忽小启动过程中转速还在持续变化。傅立叶变换默认信号在整个时间轴上统计特性不变这一刀切下去瞬态冲击的能量被平均摊到整个频段上看起来什么都像又什么都看不清。短时傅立叶变换试图补救这个问题用一个固定宽度的时间窗去滑扫信号把信号切成一小段一小段分别做傅立叶变换。可窗口宽度一固定时域分辨率和频率分辨率就成了跷跷板窗太窄时间定位准了但频率模糊窗太宽频率准了但时间上又分不清故障冲击发生在哪一刻。这个矛盾在数学上是硬约束换什么窗函数都躲不过去。有人会在傅立叶变换结果上做细化处理比如用 chirp-z 变换对关注的频段做局部放大比直接补零插值更精细但它解决不了非平稳信号的时频兼顾问题。电机故障诊断需要的变换是既能像傅立叶一样看清频率成分又能保留「这个频率成分出现在什么时候」的信息。这正是从傅立叶变换这一系数学工具走向小波包变换的理由。小波包变换本质上还是滤波器组那一套数学地基来自复变函数与积分变换里的卷积与频域分析只是它换了一种构造方式用一组可伸缩平移的小波基去匹配信号的局部形态低频段拿宽窗看趋势高频段拿窄窗抓冲击天然适配非平稳信号。2.2 小波包变换同时拆解低频与高频电机故障信号的主力变换小波变换大家听得比较多它每一层只把上一层的低频部分继续分解高频细节不再往下拆。频率分辨率在高频段越来越粗这对语音、图像这类能量集中在低频的信号够用。但电机故障信号恰恰相反轴承外圈故障激起的是高频共振响应齿轮啮合故障的频率也远高于转频。如果只用小波变换高频段的故障信息永远只有一个笼统的细节系数等于把最重要的证据扔掉了。小波包变换在这一点上做了关键改进每一层同时分解低频和高频两部分第四层可以拿到 16 个频带第五层 32 个频带高频区域被均匀细化。这是我能放心把它当作电机故障诊断主力变换的根本原因。用一个小波包分解替代一组带通滤波器一次性把信号拆成多个等宽频带每个频带对应一个窄带信号。轴承故障的冲击能量会集中落在某几个频带里频带之间的能量分布差异就成为故障指纹。实际处理时我们通常不直接看小波包系数的波形而是把每个频带系数的平方和除以后长度得到平均能量再对所有频带能量做归一化得到能量占比。这本质上做了两件事一是把高维的波形数据压缩成一个低维特征向量二是通过归一化消除传感器灵敏度和信号绝对幅值的影响。同一个电机在不同测点、不同采集时刻的绝对能量会变但能量分布的相对比例是稳定的这个稳定性就是后面分类器能做文章的基础。2.3 小波基与分解层数选定变换后必须回答的两个问题确定用某个变换做诊断不是丢进函数库就跑它绑着两个必须当场拍板的参数小波基函数选谁、分解到第几层。这两个参数直接决定特征向量里装的是故障细节还是噪声。先看小波基。小波函数有很多族dbN、symN、coifN、bior 等等工程上 90% 的场景用 daubechies 族就够了。dbN 后面的数字 N 是消失矩阶数N 越大小波越光滑频率局部性越好但支撑长度变长计算量上升对短促冲击的时间定位反而变差。电机振动信号里既有转子转频这种低频稳态成分又有轴承冲击这种短时瞬态成分一般建议在 db4 到 db10 之间试后面章节会细说挑选方法。其次是分解层数层数太少频带太宽故障特征混在一起分不开层数太多每个频带里能量被摊薄噪声的占比被抬升。以 12.8kHz 采样率为例三层分解对应每个频带 1.6kHz 带宽对多数轴承故障够用了五层虽然得到 32 个频带但很多频带里只有噪声没有信号反而干扰分类器判断。这套选择逻辑没有绝对最优解都是对着频谱图反复试出来的。理论上说小波基越匹配信号形态越好实际操作里就一句话谁让故障样本之间类内距离小、类间距离大谁就是当前数据下的好参数。接下来要做的是把这套变换思路落成能跑的代码也就是打开「程序.zip」之后真正动手的那一步。3. 把「程序.zip」跑起来故障诊断的标准代码链路3.1 信号读取与滑窗切分诊断的第一道工序这类故障诊断代码包核心文件一般离不开三块数据预处理、特征提取、分类器。拿到压缩包解压后先把数据管线理清楚因为后面所有操作都建立在「样本怎么切」上面。常见做法是采集卡直接导出 CSV 或 NPZ 文件每行一个采样点第一列时间戳、后面的列是各通道幅值。电机故障诊断大多用振动加速度信号也有用电流信号的电流信号对转子断条和偏心故障敏感但需要交流采集变换电路先把大电流转成电压信号再进 ADC采集链路比振动通道多一道硬件变换相位误差的坑也更多。振动信号直出预处理负担小这也是它成为入门首选的原因。下面是读取与切窗的标准写法import numpy as np import pandas as pd # 读取采集卡导出的振动信号一列是时间一列是加速度幅值 df pd.read_csv(motor_vibration.csv) signal df[acc].values.astype(np.float64) fs 12800 # 采样率单位 Hz来自采集卡配置 # 滑窗切分每个样本取 4096 个点对应 0.32 秒 window_len 4096 stride 1024 # 相邻窗口重叠 75%做数据增强 samples [] for start in range(0, len(signal) - window_len, stride): samples.append(signal[start:start window_len]) samples np.array(samples) # 形状: (样本数, 4096)窗口长度取 4096 点是采样率和最小关注频率的折中0.32 秒的窗能分辨到约 3Hz 的频率间隔足以区分转频附近的边频带如果采样率降到 6400Hz窗口点数不变意味着时长翻倍到 0.64 秒低频分辨率提高但对瞬态冲击的时间敏感度变差。步长取 1024 点让相邻窗口重叠 75%这是诊断里的常见做法——故障冲击不一定落在窗口起点重叠切窗把冲击包含进窗口的概率放大等效于做了数据增强。采样率这一栏务必确认它直接决定用小波包分解后每个频带的实际频率范围。如果采集卡配置里写的是 12.8kHz但代码里写成 12800 就得到不同的频带宽度差一个数量级后续所有特征都会错位。3.2 小波包分解与频带能量特征从信号到特征向量信号切好窗之后进入核心环节对每个窗口做小波包变换把时域波形变成特征向量。这里用到 PyWavelets 库函数名是WaveletPacket。需要注意一个细节get_level(level)拿到的节点顺序不是按频率从低到高排列的这个坑后面会专门讲先按节点自然顺序取能量占比特征提取代码长这样import pywt import numpy as np def wpd_energy_features(samples, waveletdb4, level3): 对一批样本做小波包分解返回各频带能量占比特征。 参数: samples: (样本数, 窗口长度) 的二维数组 wavelet: 小波基名称电机信号常用 db4 / db10 level: 分解层数3 层得到 8 个频带 返回: (样本数, 2**level) 的能量占比矩阵 features [] for sample in samples: # modesymmetric 是对称延拓避免边界突变 wp pywt.WaveletPacket(datasample, waveletwavelet, modesymmetric) nodes wp.get_level(level) # 第 level 层共 2**level 个节点 energies [] for node in nodes: coeffs np.asarray(node.data) # 频带平均能量系数平方和除以点数消除样本长度影响 energies.append(np.sum(coeffs ** 2) / len(coeffs)) total np.sum(energies) features.append(energies / total) # 能量占比归一化到 [0,1] return np.array(features)mode参数很容易被忽略但它是真实数据里绕不开的细节。信号两端在边界处会被滤波器补值补法不对会在低频带上造出假能量。symmetric延拓对振动信号最稳妥它把边界镜像翻转不会像零延拓那样硬生生造出阶跃periodic要求信号严格周期电机振动满足不了。实际跑数据时可以分别用两种 mode 提取特征对比频谱边界段的差异多数时候symmetric的类间距更干净。能量占比归一化是整个特征提取里最重要的一步它把「信号有多大」这个绝对信息丢掉只保留「能量相对分布在哪些频带」。不同负载下电机振动幅值差几倍但故障引起的能量分布偏移是稳定的这个归一化让特征天然抵抗工况变化。但注意这里的分母用当前样本自身总能量跟后面分类器里的标准化是两码事两个归一化别混在一起。3.3 特征矩阵与 SVM 分类让机器替你认故障特征提取完得到的是形状为「样本数 × 8」的特征矩阵这个矩阵就是分类器的输入。电机故障诊断里用得最多的分类器是 SVM原因很实际样本量不大、特征维度不高时SVM 比深度学习稳定不用调一堆网络结构超参换一台电机重新训练的成本也低。随机森林也常用训练更快、调参更省但外推能力不如 SVM识别未见过的工况时 SVM 的泛化通常更好一点。下面是把特征矩阵喂给 SVM 的标准流程注意训练测试划分和标准化的顺序from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler # X_all: (样本数, 8) 小波包能量占比特征 # y_all: 0正常, 1轴承外圈故障, 2轴承内圈故障, 3滚动体故障 X_train, X_test, y_train, y_test train_test_split( X_all, y_all, test_size0.3, stratifyy_all, random_state42 ) # 标准化只允许在训练集上 fit再 transform 测试集 # 这是避开数据泄漏的关键详见第 5 章 scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # RBF 核 SVMC 控制对误分类的惩罚适度取 10 clf SVC(kernelrbf, C10, gammascale) clf.fit(X_train_scaled, y_train) train_acc clf.score(X_train_scaled, y_train) test_acc clf.score(X_test_scaled, y_test) print(ftrain_acc{train_acc:.3f} test_acc{test_acc:.3f})stratifyy_all这个参数强烈建议保留它保证训练集和测试集里每类故障的比例一致。即使你不做严格的数据增强分层抽样也能防止某一类故障样本太少、全被分到测试集导致训练集里没有它的悲剧。gammascale让 sklearn 根据特征方差自动设置 RBF 核的宽度比自己手设一个 0.1 或 0.01 要稳得多初次跑通时可以无脑用这个默认值。这段代码跑通之后你会看到训练准确率和测试准确率两组数字。如果训练高得吓人、测试低得离谱别急着调 SVM 参数十有八九是特征提取或数据划分环节出了问题下一章把参数体系讲清楚第五章专门列出我踩过的坑。4. 参数怎么调采样率、小波基、分解层数的搭配逻辑4.1 采样率先算故障特征频率再定不是越高越好采样率的选定在诊断方案里前置且关键它决定你能看到多高频率的故障特征。轴承故障特征频率不是拍脑袋出来的有明确公式外圈故障特征频率 BPFO 约等于0.4 × n × fr内圈约0.6 × n × fr其中 n 是滚动体个数fr 是转频。以一台 4 极电机、转速 1450rpm 为例fr ≈ 24.2Hz假设轴承有 9 个滚动体BPFO ≈ 0.4 × 9 × 24.2 ≈ 87Hz。看着频率不高但轴承故障会激起结构共振振动能量在几百赫兹到几千赫兹的频段被放大所以只用 1kHz 采样率肯定不行。工程上的经验法则是采样率至少取最高关注频率的 10 倍以上再留一点抗混叠滤波的裕量。电机诊断里 12.8kHz 和 25.6kHz 是采集卡最常见的两档前者够覆盖绝大多数轴承故障的共振频段后者适合高速电机或齿轮箱早期点蚀。如果你的诊断对象是感应电机转子断条特征频率是(1-2s)f的边频带离工频只有 1~2Hz这要求的是频率分辨率而不是采样率需要加长窗长而不是提高采样率两者方向正好相反。采集中还有一个通道选择问题。振动传感器贴在外壳上能捕捉轴承和齿轮故障但转子断条这种磁不对称故障对负载转矩波动更敏感用电流信号配合交流采集变换电路时采样率要求比振动低但在工频附近需要很高的频率分辨率。这就是第 3 章提到过的不同故障类型对「采样率 窗长」的要求组合不同做方案设计的第一个动作是先用频谱仪或快速傅立叶变换扫一版原始数据看看关注频段到底在哪里再定采样率。跳过这一步直接按采集卡最高档采样只会把大量噪声和高频无关成分一起采进来特征里全是噪声的占比会明显抬升。4.2 db4 还是 db10小波基选择的两个评判维度小波基选择的纠结本质上是在两个指标里找平衡消失矩阶数和支撑长度。db4 的消失矩阶数是 4波形短、紧支撑好对冲击信号的时间定位准计算量小db10 消失矩阶数更高频率响应的带外衰减更快每个频带之间的能量泄漏更少。放在电机故障诊断的语境里轴承故障是短促冲击db4 能更准地抓住冲击出现的时刻转子断条是持续窄带信号db10 能更干净地把边频带分离出来。实操层面我建议两条路都试不用凭感觉选。先跑一段对比用同一批数据分别提取 db4 和 db10 的特征送进同一个分类器做交叉验证看哪个测试准确率高顺便观察特征可视化里类间距离的大小。没有明显差距时优先 db4计算量小、内存占用少在线监测系统里每个样本少算几毫秒累计起来很可观。还有一个和消失矩相关的细节db4 和 db10 的支撑长度不同边界效应影响的点数也不同。db10 支撑更长边界延拓引入的假成分在低频带上更明显。窗口长度只有 1024 点时边界效应占比会放大这时候 sym5 或 coif3 这类对称性更好的小波基可能比 db 族表现更好。调参时以「类内方差小、类间距离大」为唯一标准小波基的名字不是信仰谁效果好就用谁。4.3 分解层数与特征维度的平衡三层是最常用的起点分解层数决定特征向量的维度。3 层分解得到 8 个频带特征向量是 8 维5 层分解得到 32 个频带特征向量跳到 32 维。维度变高不一定带来更好的分类效果反而有两层风险一是每个频带能量被摊薄故障冲击的能量分散到多个频带里每个单独看都不显著二是特征维度逼近样本数量时分类器开始过拟合训练集上表现漂亮真实数据上一塌糊涂。三层分解作为起点几乎不会错12.8kHz 采样率下每个频带带宽 1.6kHz轴承故障的共振频段正好落在其中一两个频带内能量占比形成明显峰值对转子断条这类低频故障第一二个频带就覆盖了边频区域信息不会丢。如果原始信号里高频段的故障特征和噪声混在一起考虑提升到 4 层让 3.2kHz 以上的频带被进一步切细故障频带和噪声频带分开但 5 层以上的收益通常趋近于零调参时间却成倍增加。样本量对层数的制约最容易被忽视。假设你只有 400 个有效样本做训练特征维度从 8 升到 32SVM 在高维空间找分类超平面时可用样本密度下降过拟合风险显著上升。所以特征维度与样本数量的配比大约控制在 1:10 以上样本越少越要用低层分解。这个权衡没法用某个公式一刀切但 3 层起步、缺数据保 3 层、数据充足试 4 层是不容易翻车的策略。5. 电机故障诊断的 5 个翻车现场现象、原因与解法5.1 训练准确率 99%测试集却崩了现象小波包能量特征提取完SVM 在训练集上准确率接近满分一换到测试集直接滑到 60% 出头怎么调 C 和 gamma 都无济于事。原因数据泄漏标准化环节用全量数据算了均值和方差。特征标准化时如果先对整批 X_all 做fit_transform再划分训练测试测试集的信息早就混进了训练过程分类器等于开卷考试分数虚高。更隐蔽的泄漏来自滑窗切分相邻窗口高度重叠同一段故障冲击被切进多个窗口这些窗口同时出现在训练集和测试集里相当于用自己考自己。解决标准化严格遵循「先划分、后 fit、再 transform」的顺序训练集上 fit测试集只做 transform。滑窗切分后按时间顺序划分数据集用前 70% 的时间段做训练、后 30% 做测试而不是随机打乱切窗样本如果要随机划分务必保证同一个原始数据段产生的重叠窗口全部进同一侧。这是诊断类项目里最值得花十分钟排查的环节。5.2 小波包频带顺序不是频率顺序现象用小波包分解提取频带能量画出来的特征条形图里故障样本和正常样本在某些「频带」上能量分布混乱换 db10 重新提取后完全对不上。原因PyWavelets 的节点编号是格雷码顺序不是自然频率递增顺序。3 层分解的 8 个节点编号顺序为 0, 1, 3, 2, 6, 7, 5, 4其中第 5 个节点对应的是第 4 高频频带而不是直觉上的第 5 频带。直接用节点顺序做特征拼接相当于把频带标签全部打乱分类器学到的映射关系在不同小波基、不同分解层数之间不一致。解决拿到第 level 层的节点后按频率顺序重排。PyWavelets 提供了freq_orderTrue参数直接让wp.get_level(level, freq_orderTrue)按频率从低到高返回节点如果用旧接口手动排序节点名或者按每个节点对应的频率范围重排。重排之后用第 1 个频带代表最低频、第 8 个代表最高频这样特征向量每个维度有明确的物理含义后面做频谱对照时也不会找错频带。5.3 换了电机型号模型直接失效现象A 型号电机上训出来的模型搬到同厂房的 B 型号电机上准确率从 90% 掉到 50% 以下甚至不如瞎猜。原因不同电机的轴承型号、转速、安装刚度、负载率都不一样故障特征频率和共振频段全体偏移。小波包能量特征虽然做了归一化但频带是固定的等宽划分故障能量从第 3 频带挪到第 4 频带模型按 A 电机学到的频带边界自然失效。解决按工况分组建模或者做转速归一化。工程上最常见的做法是采集时同步记录转速信号把振动信号做阶次跟踪重采样让每个样本的转频对齐到同一基准再用阶次域切分频带特征就和转速解耦了。没有转速通道时至少按负载和转速区间分别建模型一个诊断系统维护多个小模型比一个万能大模型可靠得多。跨电机泛化这件事别指望 SVM 或神经网络硬扛数据层面把工况变量控制住才是正解。5.4 采样率过高特征里全是噪声现象采集卡开到最高档数据文件大得吓人小波包提取的特征却看不出明显类别差异分类器准确率一直上不去。原因采样率不是越高越好。轴承故障特征频率和共振频段都在数 kHz 内过高的采样率把大量高频机械噪声和电气噪声一并采进来这些小波包分解后落在高频频带里能量占比被噪声摊薄真正的故障频带反而被稀释了。更糟的是样本点数不变时采样率翻倍意味着窗长减半低频分辨率变差转子断条的特征边频直接被抹平。解决先用快速傅立叶变换扫一版功率谱找到故障特征频率和共振峰所在频段采样率取最高关注频率的 5 到 10 倍即可。诊断对象是转子断条时采样率不用高但要加长窗长诊断对象是轴承早期故障时采样率要高但窗口点数要同时调大保证时长远超一个转频周期。采集之前想清楚对象比采集之后反复滤波省钱得多。5.5 内存被连续采集数据撑爆现象程序跑了几小时后内存占用持续爬升最终进程被杀前面采集的故障样本全部白费时间成本全打水漂。原因采集程序把原始信号全部累积在内存里等到程序结束再一次性写入文件。电机诊断往往要连续采集数小时甚至一整天12.8kHz 的单通道 float64 数据一小时就占约 368MB多通道直接吃掉好几个 GB。小波包特征提取是流式操作根本不需要同时加载长时段全量数据。解决边采边存、按小时落盘分文件特征提取改为流式地读一段、处理一段、丢弃原始数据。如果数据文件已经很大用np.memmap做内存映射按需读取或者用 pandas 的迭代分块读取避免read_csv()一次加载全部行。无论哪种方案保持「只保留特征向量、不保留原始波形」的习惯原始信号留一份备份即可诊断程序全跑压缩后的特征。6. 进阶验证用混淆矩阵和 t-SNE 给诊断模型做体检调完参数、避开常见坑之后别急着拿准确率交差。准确率只是一个笼统的数字它不告诉你模型到底在哪些故障类别之间犯迷糊。我一般先把测试集的混淆矩阵打出来重点看对角线上哪些类别互相串。比如外圈故障总是被误判成正常那不是分类器的问题是小波包分解后外圈故障的特征频带能量不够突出回去检查频带划分和滤波参数而不是盲目换分类器。混淆矩阵之外t-SNE 可视化是我必做的体检项。把测试集的特征向量投射到二维平面染色显示如果同色样本聚成明显的簇、不同颜色之间分界清晰说明特征提取是成功的分类器只是把特征空间里本来就存在的间隙描了出来如果所有颜色糊成一团那问题出在特征端分类器再强也白搭。t-SNE 的困惑度参数从 5 到 50 都试一遍选一个类簇看起来最稳定的结果避免单个参数下偶然的视觉假象。确诊模型没问题之后再考虑部署形态。离线诊断用滑窗切好样本批量预测就行在线监测要改用流式逻辑每采满一个窗口长度就提取一次特征、送一次分类器窗口之间重叠率建议降到 50% 以下兼顾计算频率和报警延迟。故障报警不要只信单次预测连续三个窗口预测为同一故障才触发报警这一条经验能帮你过滤掉大量偶发的误报。报警阈值和确认窗口长度按现场可接受的漏报率调整宁可阈值稍迟钝也尽量不要频繁误报警现场人员对狼来了式的报警会产生习惯性忽略。这套方法跟了我很多年每次换新数据、新故障类型都靠这几步兜底先看混淆矩阵再上 t-SNE最后才调分类器。不管「程序.zip」里原本装着什么花哨的深度学习模型我都要求自己先跑通这三步体检再谈部署因为特征和数据的质量永远比模型结构重要。希望这些经验在你自己的电机故障诊断项目里帮到你。本文还有配套的精品资源点击获取
返回列表