多尺度样本熵MSE在轴承故障诊断中的原理、参数选择与Python实现

发布时间:2026/9/8 9:25:33
多尺度样本熵MSE在轴承故障诊断中的原理、参数选择与Python实现 简介面向轴承故障诊断与信号处理研究者这份MATLAB工具包实现了多尺度样本熵MSE算法用于分析非线性时间序列的复杂度特征。通过将传统样本熵扩展到多个时间尺度可有效捕捉不同分辨率下的信号规律适用于机械健康监测等场景。压缩包共3个文件包含2个.m脚本和1个.mat数据文件整体约1.03MB一个函数文件封装多尺度样本熵计算逻辑一个示例脚本演示读取294.mat轴承振动数据并输出熵值方便直接运行学习。目前已有536人学习下载。借助该工具读者能快速上手多尺度熵的编程实现理解样本熵参数窗口长度m、容差r对结果的影响并直接套用至自有故障数据的特征提取与状态识别为后续故障分类或趋势预测提供量化指标。 做轴承故障诊断的人十有八九都绕不过“熵”这一类特征。样本熵、排列熵、模糊熵名字听着玄本质都是拿一个数值去衡量振动信号的复杂程度。我今天想重点聊的是多尺度样本熵Multiscale Sample EntropyMSE一句话概括就是把信号在不同时间尺度上粗粒化再分别计算样本熵得到一条“熵值随尺度变化”的曲线。这条曲线对轴承的内圈故障、外圈故障、滚动体故障以及正常状态往往能拉开非常明显的差异比只看单个尺度的样本熵靠谱得多。这篇文章适合谁刚接触故障特征提取的研究生、想做设备健康管理的现场工程师或者单纯想拿公开数据集练手的朋友。我会把MSE的公式逻辑、参数怎么定、代码怎么写、踩过的坑全部摊开讲不光讲原理还会把完整可复现的流程给出来。看完之后你完全可以从零开始搭建一套“MSE特征提取 故障分类”的实验流程。写这篇文章的起因是我最近用凯斯西储大学CWRU轴承数据集复现了几个经典方法发现MSE是一个看起来简单、实际上细节极多的特征很多教程只说公式不说坑导致新手跑出来的结果和论文对不上。1. 为什么轴承故障诊断需要多尺度样本熵1.1 从时域指标到样本熵单尺度特征不够用轴承振动信号有一个明显特点非平稳、非线性。正常运行时信号接近随机噪声一旦出现局部损伤比如内圈剥落、外圈点蚀、滚动体裂纹振动信号里就会出现周期性冲击成分同时叠加大量噪声和转频谐波。早期做故障诊断习惯用均方根值、峰值、峭度这类时域统计量指标计算简单设备有明显剧烈故障时也有一定效果但有个很现实的问题不同的故障类型可能产生相似的时域幅度特征比如内圈故障和滚动体故障都出现周期性冲击光靠RMS或者峭度很难把它们分开。样本熵是Richman和Moorman在2000年前后提出的算法它衡量的是时间序列中产生新模式的可能性。一个序列越复杂、越不可预测样本熵越大序列越规律、越有周期成分样本熵越小。这个特性正好可以捕捉轴承故障带来的信号规律性变化。问题是单一尺度下的样本熵只反映了一个时间分辨率下的复杂度。轴承故障的冲击周期、故障特征频率、共振响应各自的频带和时间尺度完全不一样如果把所有信息压缩成一个熵值不同故障模式可能仍然会重叠在一起区分度不够稳定。1.2 多尺度熵到底在看什么信号Costa等人提出多尺度熵的初衷是发现人体生理信号在不同时间尺度上表现出不同的复杂度结构单纯算一个熵值会丢掉很多信息。轴承振动信号也是一样。对信号做不同尺度的粗粒化相当于在不同“放大倍数”下观察信号小尺度保留细节冲击特征大尺度滤掉高频细节、突显趋势性成分。正常轴承和故障轴承在这些尺度上的复杂度变化规律差异很大连成的MSE曲线往往是分类器最容易利用的特征形态。我见过很多人直接把原始信号算一个样本熵就丢给分类器效果不稳定换一段数据准确率就掉。引入MSE之后特征从标量变成了向量信息量大得多。在CWRU数据集上正常轴承信号与各类故障的MSE曲线形态差异非常明显有的故障在小尺度熵值明显下降有的故障在中高尺度出现回升这比单点熵值的区分度要强很多。多尺度熵的深层价值是给信号复杂度分析增加了一个“尺度维度”这也是它在故障诊断、生物医学信号处理、金融时间序列分析里都被广泛使用的原因。2. 多尺度样本熵的计算原理与参数选型2.1 粗粒化把信号切片求平均MSE的第一步是粗粒化coarse-graining。给定长度为N的时间序列设定尺度因子τ把序列划分成若干个长度为τ的连续且不重叠的窗口对每个窗口内的点求平均得到新的粗粒化序列[ y_j^{(\tau)} \frac{1}{\tau} \sum_{i(j-1)\tau1}^{j\tau} x_i, \quad j1,2,\dots,\lfloor N/\tau \rfloor ]当τ1时粗粒化序列就是原始序列MSE退化成为普通的样本熵。随着τ增大序列长度缩短为N/τ细节被平均掉留下的是更宏观的信号变化模式。这个过程理解起来很简单但容易踩坑的地方在于窗口对齐方式。经典做法是从第一个点开始直接切分窗口边界是固定的。如果故障冲击恰好被切碎分到两个窗口里粗粒化结果就会产生偏差这也是后面复合多尺度熵CMSE出现的原因。CMSE通过平移起始点把τ种可能的切分方式都算一遍再取平均能显著提升稳定性。这个细节我后面还会再强调。2.2 样本熵匹配对数与负对数概率样本熵的计算流程是用一组模板向量去匹配信号中的重复模式。给定嵌入维数m和相似容差r过程如下构造m维向量X(i) [x_i, x_{i1}, ..., x_{im-1}]其中i从1取到N-m1。统计所有不重复的向量对(i, j, i≠j)中切比雪夫距离小于r的个数记为B。同样构造m1维向量统计匹配对数记为A。计算样本熵SampEn -ln(A/B)。这里的直觉是B是长度为m的模式互相匹配的数量A是在m模式匹配的基础上再多比一个点仍然匹配的数量。A/B反映的是“序列已经匹配了m个点接下来一个点依然匹配”的条件概率。条件概率越大说明信号越规律、越可预测熵值越小。如果信号的冲击成分强、周期性强样本熵就会明显下降这就是它能反映轴承故障状态的根本原因。这里必须提一个重要注意点如果B0或者A0样本熵是无定义的返回值就是NaN。实际运行中r取得太小会频繁出现这个情况r取得太大所有向量都匹配A/B接近1熵值趋近于0信息就被抹平了。常规经验是取r 0.1~0.25倍的序列标准差m取2或3。我绝大多数场景用的是m2、r0.15倍标准差稳定性和区分度都比较好。2.3 参数搭配经验m、r、τ到底怎么定MSE的参数有三组嵌入维数m、相似容差r、最大尺度因子τmax。组合起来情况很多但真正需要反复调整的主要是r和τmax。先说一个容易翻车的地方在多尺度样本熵中r通常固定用原始时间序列的标准差来计算而不是用每个粗粒化后新序列各自的标准差。这一点非常关键。如果每个尺度都用该尺度序列自己的std来算r相当于对每个尺度做了归一化会把跨尺度的绝对复杂度差异抹平MSE曲线形态会完全变样。很多人复现论文复现不出来多半是栽在这里。具体该用哪个取决于你想保留什么信息。如果要保留“信号在不同尺度上绝对复杂度变化”必须用原始std如果只是想做尺度内的相对比较各自std也有它的道理。但从Costa原始方法和大多数故障诊断文献的做法来看用原始序列std更常见也更稳。τmax的选择一般取5~20。我在CWRU数据上常用τmax15或20。尺度取得过大粗粒化后的序列长度只有N/τ样本熵估计方差迅速增大生成的熵值不可信尺度取得太小又看不到足够的尺度变化趋势。通常建议粗粒化后的最短序列长度不要低于几十个点最好在数百点以上。样本长度2048点时τmax取20差不多是上限。如果序列长度很大比如10000点以上τmax可以适当增加但要结合计算成本考虑。3. 基于公开轴承数据集的MSE特征提取全流程3.1 数据集准备与样本划分方法我以最常用的CWRU轴承数据集为例。这个数据集是美国凯斯西储大学轴承数据中心提供的公开数据包含正常状态、内圈故障、外圈故障、滚动体故障等故障直径有0.007英寸、0.014英寸、0.021英寸等规格采样频率有12kHz和48kHz两档是故障诊断领域最常用的基准数据集。实操时我一般按下面的流程做从.mat文件中读取驱动端加速度信号DE通道先做z-score标准化消除幅值量纲差异。把每个工况的长信号切成固定长度的样本样本点数取2048或4096。给每个样本打标签normal、inner、outer、ball。对每个样本计算MSE得到一个长度为τmax的特征向量。所有样本的特征向量组成特征矩阵X标签为y。划分训练集和测试集用SVM或随机森林分类统计准确率和混淆矩阵。这里有个经验值得反复强调划分训练集和测试集时尽量不要把同一个数据文件里连续截取出来的样本既放进训练集又放进测试集否则相邻样本高度相似会严重高估模型性能。正确做法是按数据文件或按不同工况划分模拟真实场景下的跨工况诊断。我在实验中发现很多论文报告接近100%的准确率其中一部分原因就是随机划分样本时数据泄漏了。做对比实验这条一定要讲清楚。3.2 代码实现从样本熵到多尺度熵下面是我常用的一个简化版Python实现。为了逻辑清晰我先把样本熵单独写成函数再做粗粒化循环。这种实现不是最快的但特别适合理解原理和调参。import numpy as np def sample_entropy(x, m, r): 计算时间序列的样本熵 x: 一维时间序列 m: 嵌入维数 r: 相似容差 N len(x) def match_count(mm): n_vectors N - mm 1 cnt 0 for i in range(n_vectors): for j in range(i 1, n_vectors): d np.max(np.abs(x[i:i mm] - x[j:j mm])) if d r: cnt 1 return cnt, n_vectors B, _ match_count(m) A, _ match_count(m 1) if B 0 or A 0: return np.nan return -np.log(A / B) def mse_curve(x, max_scale, m2, rNone): 计算多尺度样本熵曲线 x: 一维时间序列 max_scale: 最大尺度因子 tau m: 嵌入维数 r: 相似容差默认为 0.15 * 原始序列标准差 if r is None: r 0.15 * np.std(x) entropies [] for tau in range(1, max_scale 1): num len(x) // tau # 粗粒化把序列重塑为 (num, tau)按行求平均 coarse np.mean(x[:num * tau].reshape(num, tau), axis1) se sample_entropy(coarse, m, r) entropies.append(se) return np.array(entropies)这段代码里有几个细节。粗粒化时我用了x[:num * tau].reshape(num, tau)也就是先把序列截断到num*tau个点再按行切分成窗口每行长度为τ然后沿axis1求均值。如果忘记截断reshape会直接报错。另外r的默认值用的是整个原始序列的std这是MSE的标准做法千万不要在循环里对每个coarse序列重新算std除非你有明确的理由。实际项目里样本数量多、样本点长上面的双层循环在Python里会非常慢。我一般会在确认逻辑没问题后换成更高效的实现要么用numpy广播一次性构造距离矩阵要么直接用现成的开源库。EntropyHub这个Python库实现了SampEn、MSE、CMSE、RCMSE等方法底层是C/Cython写的速度比纯Python自写快很多。理解原理用自写代码做批量实验用库这是我认为效率最高的组合。3.3 从特征向量到故障识别模型拿到MSE特征矩阵后接下来的流水线很标准。我先做特征标准化然后训练SVM分类器最后输出准确率和混淆矩阵。from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, confusion_matrix # X: shape (n_samples, max_scale) # y: shape (n_samples,) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) scaler StandardScaler() X_train_s scaler.fit_transform(X_train) X_test_s scaler.transform(X_test) clf SVC(kernelrbf, C10, gammascale, class_weightbalanced) clf.fit(X_train_s, y_train) y_pred clf.predict(X_test_s) print(Accuracy:, accuracy_score(y_test, y_pred)) print(Confusion Matrix:\n, confusion_matrix(y_test, y_pred))在CWRU数据上如果工况固定、样本充足MSE特征配合SVM准确率可以做到95%以上。但我建议不要只看准确率要多看看混淆矩阵搞清楚是哪两类故障最容易互相混。我实际跑的时候内圈和滚动体故障在某些负载下会出现少量互相误判这是正常的。如果发现某两类严重混淆可以返回去看它们的MSE曲线在哪几个尺度上重合考虑增加特征维度比如加上排列熵、模糊熵或者用特征选择筛掉区分度差的尺度。特征工程的目的不是堆数量而是让每个特征都提供互补信息。4. 实操中常见的坑与排查技巧4.1 熵值出现NaN一查一大片这是MSE最常遇到的问题。样本熵计算时如果B或A为0返回值就是NaN。出现这个情况主要有两个原因一是容差r取得太小匹配条件太苛刻二是粗粒化后序列太短样本数不足以产生匹配对。排查时我一般先打印每个尺度的匹配对数看看是哪些尺度出了问题。如果是小尺度就出现NaN基本是r过小可以依次尝试0.18、0.2、0.25倍的std如果是大尺度才出现NaN说明τmax设得过大粗粒化后序列长度不足要么增加样本点数要么减小τmax。还有一种更彻底的解决办法改用复合多尺度熵或精细复合多尺度熵它们在多个粗粒化结果上取平均能有效避免单一次粗粒化操作导致熵值无定义的情况。4.2 计算太慢批量实验跑不动样本熵本身的时间复杂度大约是O(N²)MSE再把所有尺度叠上来计算量会成倍增长。4096个点的样本τmax20用纯Python循环算一条MSE曲线可能要好几秒几百个样本就是半小时起步非常耽误调参。我的经验是分三层优化。第一层能用库就用库EntropyHub的MSE实现用了大量向量化和底层优化同样样本数时长缩短几十倍都很正常第二层如果必须自己写可以用numpy广播一次性比较所有向量对避免Python内层循环第三层批量实验时可以用RCMSE代替经典MSE它对所有粗粒化序列先汇总匹配对数再统一取负对数不需要对每个尺度单独重复计算样本熵尺度越大节省越明显。我实际用下来RCMSE不仅快稳定性也更好这也是现在很多研究优先考虑它的原因。4.3 参数敏感、结果不稳定怎么办MSE的结果对参数组合很敏感尤其是r和τmax。我不建议凭感觉拍一组参数就完事而是用一个简单网格搜索来确定m固定为2少数情况试一下m3。τmax在10到20之间选。r在0.1、0.12、0.15、0.18、0.2倍std之间遍历。评估标准不要只挑准确率最高的那组而是看参数小范围扰动下准确率是否稳定。参数稳定比参数“最优”更重要。实际项目里换一段工况、换一台设备最优参数就会漂移如果算法对参数极敏感部署到现场很容易翻车。另外分类器之前的特征标准化一定要做否则SVM这类距离型分类器会被数值较大的尺度维主导尺度较小但区分度很好的维就白算了。我把常见问题和解决思路整理成了一张速查表方便大家对照排查。问题现象可能原因解决建议熵值出现大量NaN容差r过小或粗粒化序列过短增大r至0.18~0.25倍std减小τmax改用RCMSEMSE曲线和论文对不上r用了每个尺度自己的std改用原始序列的std计算r不同故障类别区分度低τmax太小或特征被强尺度主导尝试τmax15~20增加其他熵特征特征归一化分类准确率虚高同一文件的连续样本同时进了训练集和测试集按文件或工况划分数据集避免数据泄漏批量实验太慢纯Python双层循环 尺度循环换EntropyHub用向量化用RCMSE代替MSE大尺度熵值波动剧烈粗粒化后序列太短估计方差大增大样本长度或减小τmax这套问题排查思路同样适用于排列熵、模糊熵等同类复杂度特征。它们的共同点是都有一堆候选参数结果对参数敏感所以排查顺序基本一致先确认输入数据质量再锁定参数选择方式最后检查样本量是否足够。最后再聊一点我个人做项目时的体会。MSE这个特征的难点从来不在公式本身而是在“用哪种r”“取多少尺度”“保留什么信息”这些看似琐碎的细节。我最早照着论文写代码第一步就踩了r归一化的坑跑出来的曲线和论文完全对不上折腾了两天才发现是每个尺度都用了各自的std整个曲线形态都变了。后来我总结出一条经验凡是熵类特征动手前先想清楚要保留的是序列内部的复杂度还是跨尺度的相对差异想明白了参数怎么定、代码怎么写都不会糊涂。如果你手里的轴承信号是现场采集的建议先对每种工况都画一下MSE曲线看看哪个尺度段区分度最高再决定特征怎么筛这比盲目堆特征、堆模型要高效得多。希望这篇内容能帮你少走一些弯路。本文还有配套的精品资源点击获取