ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于VMD排列熵与ELM的滚动轴承故障诊断Python实现

基于VMD排列熵与ELM的滚动轴承故障诊断Python实现 简介这份资源面向机械故障诊断方向的研究人员、工程师及学生提供基于VMD排列熵与ELM的滚动轴承故障诊断完整Python实现。项目将变分模态分解用于非平稳振动信号处理分离故障特征频率再以排列熵量化各模态分量的复杂度最后用极限学习机完成健康状态分类形成从信号分解、特征提取到模式识别的闭环流程适合作为课程设计、论文复现或工程验证的参考方案。压缩包共407个文件以404个txt振动数据样本为主另含2个Python脚本和1个csv特征文件整体约4.8MB数据与代码配套齐全可直接运行体验完整诊断链路。目前已有633人学习下载。读者可据此掌握VMD参数设置、排列熵计算与ELM训练评估的实现细节并借助现成数据集快速验证方法有效性降低从零搭建故障诊断系统的门槛。1. 从一段轴承振动信号说起这套 VMD排列熵ELM 的 Python 实现到底能干什么手上拿到一段滚动轴承的振动信号采样率不低时域波形看着乱糟糟频谱上又混着转频、谐波和噪声想判断它到底是内圈故障、外圈故障还是正常靠肉眼看波形基本没戏。这套「基于 VMD 排列熵和 ELM 的滚动轴承故障诊断 Python 实现」解决的正是这个场景先用 VMD 把非平稳振动信号拆成若干个相对平稳的模态分量再对每个分量算排列熵把熵值拼成特征向量最后丢给 ELM 做分类输出轴承的健康状态。它适合做设备健康管理、状态监测的工程师也适合拿它当信号处理加机器学习的练手项目。资源包里给了vmd-pailieshang.py、ELM.py两个主脚本一份pailieshang.csv特征数据还有inner0.txt、inner3.txt、inner25.txt、inner47.txt、inner60.txt、inner61.txt、inner62.txt这些按故障类型和程度命名的原始信号文件拿到手就能跑通整条链路。2. VMD 分解与排列熵特征提取从原始信号到特征向量2.1 为什么先做 VMD 而不是直接上 FFT滚动轴承的振动信号本质上是非平稳的尤其是故障早期冲击成分很弱直接做 FFT 会把整个时间轴上的频率成分平均掉故障特征频率容易被转频和谐波淹没。VMD变分模态分解的思路是把信号分解问题写成一个变分约束问题假设信号由若干个中心频率不同的本征模态函数IMF组成通过交替方向乘子法迭代求解让每个模态围绕自己的中心频率窄带聚集。相比经验模态分解EMDVMD 的模态数和中心频率是可控的不会出现模态混叠那种玄学现象这对后面提取稳定的排列熵特征很关键。常见做法是先把原始信号归一化再设定模态数 K 和惩罚因子 alpha。K 太小会欠分解故障冲击和背景噪声混在一个模态里K 太大则过分解同一个物理成分被拆到多个模态排列熵反而失去区分度。我一般会先试 K4 到 K6看分解后各模态的中心频率是否分得开再定下来。2.2 排列熵怎么算参数怎么设排列熵衡量的是时间序列的复杂度和随机性。做法是把序列做相空间重构取嵌入维数 m 和时间延迟 tau把每个长度为 m 的窗口内的值排序得到一个排列模式统计所有排列模式出现的概率再算香农熵并归一化。轴承正常时振动相对规则排列熵偏低出现故障冲击后信号的随机性上升排列熵会变大。所以每个 VMD 模态算一个排列熵K 个模态就得到 K 维特征。参数上m 通常取 3 到 7m 越大对细微变化越敏感但计算量也越大工程上 m4 或 m5 比较稳tau 一般取 1采样率足够高时不用刻意延迟。下面这段代码是 VMD 分解加排列熵提取的核心逻辑我按资源里的vmd-pailieshang.py结构整理过import numpy as np from vmdpy import VMD from entropy import permutation_entropy # 常见做法用现成的排列熵实现 def vmd_pe_feature(signal, K5, alpha2000, tau0, m4, delay1): # signal: 一维振动信号 # K: 模态数, alpha: 带宽约束, tau: 噪声容限(0表示无噪声) u, u_hat, omega VMD(signal, alpha, tau, K, DC0, init1, tol1e-7) # u 的形状是 (K, N)每一行是一个模态分量 feats [] for k in range(K): pe permutation_entropy(u[k], mm, delaydelay, normalizeTrue) feats.append(pe) return np.array(feats), u # 读取一个原始信号文件 sig np.loadtxt(inner3.txt) feat_vec, modes vmd_pe_feature(sig, K5, alpha2000, m4) print(特征向量:, feat_vec)逻辑说明VMD返回的u是分解后的 K 个模态按中心频率从低到高排列对每个模态调用排列熵函数normalizeTrue把熵值归一到 0 到 1 之间避免不同长度信号量纲不一致。参数alpha控制带宽取值越大每个模态越窄一般 1000 到 3000 之间试tol是收敛容差太小会迭代很久1e-7 够用。跑完这段每个原始信号文件就变成一个 K 维特征向量多个文件拼起来就是pailieshang.csv那种特征表。2.3 批量处理多个信号文件并落成 CSV资源里给了 7 个 txt 信号文件手工一个个跑不现实得写个循环批量提特征把标签一起写进 CSV。标签可以从文件名解析比如inner0代表内圈故障程度 0inner60代表程度 60正常信号可以单独标一类。import os, glob import pandas as pd files sorted(glob.glob(inner*.txt)) rows [] for f in files: sig np.loadtxt(f) feat, _ vmd_pe_feature(sig, K5, alpha2000, m4) label os.path.basename(f).replace(.txt, ) # 用文件名当标签 rows.append(list(feat) [label]) df pd.DataFrame(rows, columns[fPE{i1} for i in range(5)] [label]) df.to_csv(pailieshang.csv, indexFalse) print(df.head())这段跑完得到的pailieshang.csv就是 ELM 的输入。注意列名要和后面 ELM 脚本读取时对齐否则会报 KeyError这是最常见的翻车点之一。特征列数等于模态数 K改 K 的时候两边要同步改。3. ELM 分类器训练与评估把特征向量变成故障标签3.1 ELM 为什么适合这个场景ELM极端学习机是单隐藏层前馈网络和 BP 网络最大的区别在于隐藏层的输入权重和偏置随机生成后就不再调整只需要用最小二乘法一次性求解输出层权重。这意味着训练过程没有反向传播的迭代速度极快也不会陷入局部极小值。对于轴承故障诊断这种特征维度不高K 维排列熵、样本量中等的任务ELM 几秒钟就能训完比反复调 BP 网络省心得多。代价是随机权重带来一定的不稳定性通常做法是多次运行取平均或者固定随机种子保证可复现。3.2 训练脚本与关键参数资源里的ELM.py是分类主程序核心是读 CSV、划分训练测试集、训练 ELM、输出准确率。下面是我整理后的可运行版本import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from elm import ELM # 常见做法用开源 ELM 实现或自己写 # 读取特征 df pd.read_csv(pailieshang.csv) X df.drop(label, axis1).values y df[label].values # 标签编码 le LabelEncoder() y_enc le.fit_transform(y) # 划分数据集固定随机种子保证可复现 X_train, X_test, y_train, y_test train_test_split( X, y_enc, test_size0.3, random_state42, stratifyy_enc) # 训练 ELM隐藏层节点数设为 50 model ELM(hidden_units50, activationsigmoid, random_state42) model.fit(X_train, y_train) y_pred model.predict(X_test) acc np.mean(y_pred y_test) print(f测试准确率: {acc:.4f})逻辑说明hidden_units是隐藏层节点数太小欠拟合太大容易过拟合特征维度是 5 时取 30 到 100 比较合适可以网格搜一下。activation常用 sigmoid 或 sinesigmoid 更稳。stratifyy_enc保证训练测试集里各类比例一致样本不均衡时很重要。random_state固定后结果可复现不然每次跑准确率都在跳没法对比。3.3 评估指标不只看准确率轴承故障诊断里各类样本往往不均衡正常样本多、故障样本少只看准确率会被多数类带偏。常见做法是同时看混淆矩阵和每类的召回率。如果某一类故障召回率明显低说明特征对该故障不敏感得回头调 VMD 的 K 或排列熵的 m。from sklearn.metrics import classification_report, confusion_matrix print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred, target_namesle.classes_))跑完看报告如果某类召回率低于 0.8优先怀疑两点一是该类信号在 VMD 分解时模态数不合适故障冲击被分到了不稳定的模态二是排列熵的 m 太小捕捉不到该故障的复杂度变化。这两个参数是联动的调的时候一次只动一个。4. 避坑与排查这套流程里最容易翻车的几个地方4.1 现象VMD 分解报错或模态全糊在一起原因alpha设得太小带宽约束不够各模态中心频率挤在一起或者信号没归一化幅值量级差异大导致迭代不收敛。解决先把信号除以最大值归一化到 [-1, 1]再把alpha调到 2000 左右K从 4 开始试观察omega输出的中心频率是否单调分开。4.2 现象排列熵值全部接近 1 或全部接近 0原因m设得过大而信号长度不够相空间重构后排列模式太少熵值失真或者normalize没开不同长度信号没法比。解决保证信号长度远大于 m 的阶乘m4 时至少几百个点开启归一化让熵值落在 0 到 1。4.3 现象ELM 准确率忽高忽低每次跑都不一样原因ELM 隐藏层权重随机初始化没固定随机种子或者训练测试集划分没固定。解决random_state在 ELM 和train_test_split里都设成同一个值跑多次取平均时记录每次的种子别用默认的随机状态。4.4 现象CSV 读取报 KeyError 或特征列对不上原因VMD 脚本输出的列名和 ELM 脚本读取的列名不一致改了 K 之后只改了一边。解决把特征列名和 K 绑定生成比如[fPE{i1} for i in range(K)]两个脚本共用同一个 K 变量或者干脆把 K 写进 CSV 文件名。4.5 现象测试准确率很高但换一批数据就崩原因训练集和测试集来自同一段信号的不同片段数据泄漏了模型记住的是片段而不是故障特征。解决按信号文件划分训练测试集同一个文件的所有片段只能出现在一边别用随机切分把同一段信号切散。5. 进阶玩法把单次分类做成可复现的对比实验跑通单次分类只是起点真正做工程验证时需要对比不同 K、不同 m 下的准确率才能说明参数选得合理。我一般会写个网格搜索的小循环把 VMD 的 K 和排列熵的 m 组合起来跑记录每组参数下的准确率和召回率最后挑一组稳定且可解释的。results [] for K in [4, 5, 6]: for m in [3, 4, 5]: # 重新提特征 feats [] for f in files: sig np.loadtxt(f) feat, _ vmd_pe_feature(sig, KK, mm) feats.append(feat) X np.array(feats) # 训练评估 ELM X_tr, X_te, y_tr, y_te train_test_split( X, y_enc, test_size0.3, random_state42, stratifyy_enc) model ELM(hidden_units50, random_state42) model.fit(X_tr, y_tr) acc np.mean(model.predict(X_te) y_te) results.append({K: K, m: m, acc: acc}) res_df pd.DataFrame(results) print(res_df.pivot(indexK, columnsm, valuesacc))这段跑完会得到一张 K 乘 m 的准确率表一眼能看出哪组参数最稳。注意每次换 K 都要重新提特征不能拿旧特征凑合因为特征维度变了。另外 ELM 的隐藏层节点数也可以一起搜但维度一多组合爆炸建议先定 K 和 m再单独调隐藏层节点。验证方法上除了看准确率我习惯把混淆矩阵画出来存成图对比不同参数下哪类故障容易被误判。如果某组参数下正常和早期故障混在一起说明排列熵对早期微弱冲击不敏感这时候可以考虑对 VMD 模态做加权或者换用多尺度排列熵。这些扩展资源里没直接给但主流程跑通后加进去不难。从那以后我每次做这类信号加机器学习的项目都强制先把数据划分方式固定下来再动任何参数不然调了半天都不知道是参数起作用还是划分变了。希望帮到你。本文还有配套的精品资源点击获取
返回列表