☰
滚动轴承故障诊断:NDGE归一化判别图嵌入原理、Matlab实现与结果解读
2026/10/17 5:25:05 网站建设 项目流程

拿到一批滚动轴承的振动数据,第一次跑“归一化判别图嵌入”这套流程时,我就意识到这个项目真正值钱的地方不是那个降维结果本身,而是它一口气把三个最关键的东西给了你:投影矩阵、不同维度下的准确率变化、以及每一个样本归属于每种故障模式的概率。换句话说,它不做“黑箱分类”,而是把整个判别过程摊开来给你看。

这个方向我建议所有做机械设备状态监测、故障诊断、以及模式识别相关课题的人都认真玩一遍。它特别适合两类场景:一是你手上已经有一套提取好的特征矩阵,想找一个比PCA、LDA更抗噪声、更擅长保留局部结构的降维方法;二是你需要在论文或技术报告里拿出“降维效果对比”这类硬指标,而NDGE天然就能输出一条维度-准确率曲线,省去反复调参取数的时间。本文就把这套算法的原理、Matlab实现、三个输出的用法和踩坑经验一次性说透。

1. NDGE到底在解决什么问题

1.1 为什么图嵌入适合故障诊断

传统思路里,做故障诊断最常用的是PCA和LDA。PCA只保留方差最大的方向,它看不见样本之间的局部关系;LDA虽然用了类别信息,但它假设数据是高斯分布、各类共享同一协方差,这在真实的振动信号特征上经常不成立。轴承故障特征往往高维、重叠、带噪声,样本在原始空间里可能紧挨在一起,PCA一压就糊了。

图嵌入的核心思路是“先建图,再降维”。它先把每个样本当作图上的一个节点,按邻接关系连边,再让降维后的空间尽量保留这张图的局部结构。同类故障样本在图上靠得近,降维后依然靠得近;不同故障样本之间即使原始距离不远,图上也有边来约束它们分开。比起PCA这种纯全局方法,图嵌入相当于既看了全局分布,又盯住了局部邻域,特别对故障数据这种“局部信息比全局信息更有判别力”的情况效果明显。

NDGE的“判别”二字,意味着它不只是保留结构,还把类别标签直接揉进了图的构造里。同类样本连成“类内图”,异类样本连成“类间图”,然后目标函数一边让类内样本投影后尽量靠近,一边让类间样本投影后尽量远离。这个思路和LDA有点像,但LDA用的是全局散度矩阵,NDGE用的是图拉普拉斯矩阵,在数据重叠严重时更稳。

1.2 “归一化”和“判别”这两个词的分量

很多人在看论文时会把“归一化判别图嵌入”囫囵吞枣地当成一个整体名词,其实拆开看,两个词各有各的坑。

先说“判别”。建图的时候要建两张图:类内图和类间图。类内图在同类样本之间连边,通常是k近邻或者半径内近邻,边权可以是1,也可以是热核权重,即如果第i个样本和第j个样本是同类邻居,权重设为exp(-||xi-xj||²/σ),距离越近权重越大。类间图则是在不同类别的样本之间连边。注意,不是所有异类样本都要连,一般也只取彼此靠近的异类样本连边,否则远处的异类样本反而给目标函数加了一堆不必要的大距离惩罚,判别力会变钝。

再说“归一化”。这里的归一化指的是对图拉普拉斯矩阵做对称归一化,公式是L_sym = D^(-1/2) L D^(-1/2),L是原始拉普拉斯(D-A,D是度矩阵,A是邻接权重矩阵),D^(-1/2)是对角阵,对角线元素是每个节点度的负二分之一次方。做过图论相关工作的朋友应该眼熟,这就是图神经网络里常用的GCN那套归一化。为什么非归一化不可?因为如果某个故障类别样本特别多,它的节点度就大,拉普拉斯矩阵的特征分解会被高密度节点牵着走,少数类样本的判别结构被稀释掉。归一化之后,每个节点的“影响力”被度拉回同一量级,类别不平衡对降维结果的干扰会小很多。这一点在滚动轴承诊断里特别重要,因为实际工况下正常样本往往远多于故障样本。

2. 数据准备与预处理

2.1 特征提取:把振动信号变成算法能吃的矩阵

NDGE的输入是特征矩阵X,形状是N×n,N是样本个数,n是每个样本的特征维数。它不直接吃原始振动波形。所以做这个项目之前,第一步是把传感器采到的振动信号切成段,每一段提取一组特征。这个环节直接决定后续算法的上限,特征提得不好,后面NDGE再努力也白搭。

我自己常用的特征组合分三块。时域特征:均值、标准差、均方根、峭度、峰值因子、波形因子,六个基础指标就能比较明显地分辨裂纹、磨损和正常状态。频域特征:对每段信号做FFT,取频谱重心、均方频率、频谱方差,或者把主要频带能量占比拿出来。第三块是时频特征,用经验模态分解或小波包分解,把频带能量作为特征。比如某个项目里我对轴承振动信号做三层小波包分解,得到8个频带的能量占比,再拼接时域和频域特征,一共凑到20多维,效果比单纯用时域特征好不少。特征维数最好不要太高,一般20到50维比较合适。如果你手上特征有几百维,建议先用PCA粗降一次到50维以内,后面再跑NDGE,否则小样本高维情况下图矩阵容易奇异,这个坑后面详说。

2.2 数据标准化与划分

特征矩阵的每一维量纲不一致,标准差、均方根都是带量纲的,直接拼在一起会让欧氏距离被量纲大的特征主导。所以建图之前必须标准化,最稳妥的是z-score,每列减去均值除以标准差,让每个特征都落在同一个尺度上。

样本划分也要提前想清楚。故障诊断里经常犯的错是“用同一段连续信号切出来的样本乱分训练测试”,结果训练集和测试集实际上有大量重叠信息,准确率虚高得离谱。正确做法是按段划分——比如一个工况采了若干组数据,按采集时间段分成训练段和测试段,保证测试集样本的时间窗口和训练集没有交叠。我在实际项目里吃过这个亏,早期图省事把连续信号叠窗切完随机打乱,测试准确率能做到98%以上,换到真实设备上一试立刻掉到80%出头,原因就是信息泄漏。这也是这一类图嵌入算法论文里最容易被审稿人攻击的点,最好从一开始就按工况或时间段划分数据。

3. NDGE算法的Matlab实现

3.1 类内图与类间图的构建

NDGE的实现流程在Matlab里一共分四个步骤:建图、计算归一化拉普拉斯、解广义特征值问题、输出投影矩阵。

第一步是建图。我先给出一个简洁的类内图权重矩阵构造函数,采用“同类k近邻 + 热核权重”的方式。所谓同类k近邻,就是只在标签相同的样本里找近邻,这比在全体样本里找近邻再筛同类更可控,尤其当某类样本数量很少时,后者可能导致少数类一个邻居都找不到。

function [G_w, G_b] = construct_graphs(X, label, k_w, k_b, sigma) % X: N x n 特征矩阵, label: N x 1 类别标签 % k_w: 类内邻居数, k_b: 类间邻居数, sigma: 热核宽度 % G_w: 类内权重矩阵, G_b: 类间权重矩阵 N = size(X, 1); G_w = zeros(N, N); G_b = zeros(N, N); for i = 1:N dist_all = sum((X - X(i,:)).^2, 2); % 所有样本到当前样本的平方距离 % 类内:只看同标签样本 idx_w = find(label == label(i)); [~, order] = sort(dist_all(idx_w)); neighbors_w = idx_w(order(2:min(k_w+1, length(idx_w)))); % 去掉自己 for j = neighbors_w' G_w(i, j) = exp(-dist_all(j) / sigma^2); end % 类间:只看不同标签样本 idx_b = find(label ~= label(i)); [~, order] = sort(dist_all(idx_b)); neighbors_b = idx_b(order(1:min(k_b, length(idx_b)))); for j = neighbors_b' G_b(i, j) = exp(-dist_all(j) / sigma^2); end end end

这段代码有两点值得说明。第一,类间图只连接最近的k_b个异类样本,不是所有异类都连,目的就是避免远处的异类样本在目标函数里占据超额权重,把优化方向带偏。第二,热核权重里的sigma怎么选,我一般取所有样本两两距离的中位数再乘0.5到1,太大会导致所有权重趋同、图的局部信息退化,太小又会把邻接矩阵变得过于稀疏,后面特征分解时容易出数值问题。

3.2 归一化拉普拉斯与广义特征分解

有了类内权重G_w和类间权重G_b,下一步是把它们分别变成拉普拉斯矩阵。拉普拉斯矩阵的通用形式是L = D - G,D是对角矩阵,D(i,i) = sum(G(i,:)),也就是节点i连出去的所有边的权重之和。之后做对称归一化,即L_norm = D^(-1/2) * L * D^(-1/2)。

NDGE的优化目标是让投影后同类样本尽量靠近、异类样本尽量远离,这可以写成一个广义特征值问题:

min_w (w^T X L_w X^T w) / (w^T X L_b X^T w)

其中L_w是类内图对应的归一化拉普拉斯矩阵,L_b是类间图对应的归一化拉普拉斯矩阵。求解的时候令分母为约束,转成广义特征分解:

X L_w X^T w = λ X L_b X^T w

取前d个最小特征值对应的特征向量组成投影矩阵,因为目标函数极小化这个瑞利商,特征值越小说明投影后的类内紧凑程度越高、判别性越强。

Matlab实现直接调eig函数,比eigs稳,因为eigs对稀疏性要求高而且容易丢特征值。代码段如下:

function [W_ndge, eigvals] = ndge_project(X, label, k_w, k_b, sigma, d, reg) % 输入: X标准化后的特征矩阵, label标签 % k_w, k_b: 图近邻参数, sigma: 热核宽度 % d: 目标维度, reg: 正则化系数 [G_w, G_b] = construct_graphs(X, label, k_w, k_b, sigma); D_w = diag(sum(G_w, 2)); D_b = diag(sum(G_b, 2)); L_w = D_w - G_w; L_b = D_b - G_b; % 对称归一化 D_w_inv_sqrt = diag(1 ./ sqrt(max(D_w, 1e-12))); D_b_inv_sqrt = diag(1 ./ sqrt(max(D_b, 1e-12))); L_w_norm = D_w_inv_sqrt * L_w * D_w_inv_sqrt; L_b_norm = D_b_inv_sqrt * L_b * D_b_inv_sqrt; % 核心:求解广义特征值问题 S_w = X' * L_w_norm * X; S_b = X' * L_b_norm * X + reg * eye(size(X, 2)); % 关键的正则化项 [V, D_matrix] = eig(S_w, S_b); eigvals = diag(D_matrix); % 按特征值升序排列,取前d个 [~, idx] = sort(eigvals); W_ndge = V(:, idx(1:d)); end

这里最容易翻车的细节是reg这个正则化系数。S_b这个矩阵在样本数比特征维数少的场景下几乎必然奇异,Matlab的eig面对奇异分母会输出Inf或者NaN,直接让后面所有结果报废。加一个reg*eye(),就是在分母矩阵对角线上放一个极小值,把奇异问题拉回来。reg的取值建议在1e-4到1e-8之间,太小没效果,太大会把类间约束过度平滑导致判别性下降。我的习惯是先试1e-6,然后看特征值序列里有没有明显的Inf或负数,再考虑调大或调小。

3.3 投影矩阵和低维嵌入

拿到W_ndge之后,低维嵌入就一句话:Y = X * W_ndge。Y是N×d的矩阵,每一行就是原样本在低维空间的新坐标。这个Y可以喂给kNN、SVM或者任何后续分类器,也可以用在前两维上画散点图,直观地看各类故障样本有没有被分开。

关于d的取值,这里有一个工程经验和理论相结合的点。投影矩阵W_ndge的每一列是一个嵌入方向,特征值越小的方向越适合判别,但并不是说方向越多越好。我在实验里跑维度准确率曲线时,经常看到d从2升到10时准确率稳步上涨,到了12左右开始掉,原因在于排名靠后的那些方向对应的特征值已经接近噪声水平,投影矩阵里的信息被噪声污染了。所以后面第四部分那个“不同维度的准确率曲线”,本质上就是在帮你找d的上限。曲线到了平台期就别继续加了,加得越多,过拟合风险越大。

4. 三个输出结果的解读与应用

4.1 最终投影矩阵怎么用

标题里要输出的第一个东西是NDGE的最终投影矩阵,也就是上面代码里的W_ndge,尺寸是n×d。它代表的是“从原始特征空间到判别低维空间的线性映射”。投影矩阵的行数等于原始特征数,列数等于目标维度。

很多人拿到投影矩阵不知道该怎么分析。我的建议是至少做两件事。第一,检查每一列向量里的非零元素分布,看哪些原始特征在判别方向上权重最大,这能反过来验证你的特征提取是否有物理意义。比如某一次实验里,投影矩阵第一列里峭度和频谱重心对应的系数明显大于均值,说明这两个特征对分辨当前故障模式贡献最大;如果某一个自认为很重要的特征在所有列里系数都接近于0,那它可能既无判别性又无冗余价值,可以考虑删掉。第二,把W_ndge存成一个单独的mat文件,作为后续在线诊断的固定参数。离线训练阶段把投影矩阵学好后,在线阶段只需要把新样本的特征向量塞进同样的z-score标准化,再乘W_ndge,再做距离判别,不需要重新建图、重新分解,这个投影矩阵就是把整套算法部署到现场的“核心钥匙”。

4.2 不同维度的准确率怎么看

第二个输出是不同维度下的准确率。这个实验结果一般画成一条折线图,横轴是维度d(通常从2到20逐点取),纵轴是测试集分类准确率。理论上曲线应该先快速上升,然后进入平台期,少数情况会轻微下降。

读这条曲线有三个关键点。一看是否有明显的“拐点”。比如d=4的时候准确率已经92%,d=8只有93%,那说明核心判别信息集中在前4维,后面加的是边际收益,这种情况实际应用时直接选d=4能省不少计算量。二看曲线的抖动程度。理想的曲线应该平稳,如果你看到d=5是90%,d=6突然掉到80%,d=7又回到90%,大概率不是算法随机性,而是图构建时S_b矩阵在某个维度组合下出现近奇异,特征向量不稳定。出现这种情况时优先把reg调大一个量级再重新跑,通常能压下来。三看曲线有没有过拟合尾巴。d超过某个值之后准确率持续下滑,说明后面那些维度学到的不是判别结构而是训练集噪声,这就是加维加过头的信号。

跑维度实验时有一个偷懒但有效的技巧:不用每个d都重新解一次特征分解。因为Matlab的eig一次就能把所有特征值和特征向量全求出来,你只需要按特征值排序后依次取前d列,然后重新算一次分类准确率就行。也就是说,建图、拉普拉斯、广义特征分解这些昂贵步骤全程只做一次,后面循环里只做矩阵乘法和kNN分类,几十个维度几分钟就能跑完。

4.3 每个样本的故障模式概率怎么解读

第三个输出是“每个样本对不同故障模式的概率”,这一项最容易被人忽略,但其实是实际诊断里最有价值的信息。NDGE本身是降维方法,不直接输出概率,所以需要在降维后的空间上接一层概率输出头。

我在项目里习惯用两种方式做这个概率输出,各有适用场景。

第一种是Softmax温度缩放:以每个类别的中心点为参考,计算样本投影到各类别中心的距离,再套一个Softmax函数把距离转换成概率,公式是P_k = exp(-dist_k / T) / Σ_j exp(-dist_j / T),T是温度系数。T越大,概率分布越平滑,样本在模糊区域时各类概率会更接近;T越小,分布越尖,几乎变成硬分类。这个方法的优点是不需要额外训练分类器,缺点是它假设每个类别的形状是球形分布在中心附近,真实数据不满足时概率置信度会失真。我一般把T设为所有距离的平均值,这样概率处于一个比较自然的范围。

第二种是直接训练一个多分类逻辑回归或kNN后验估计,在训练集的低维嵌入Y上拟合,让模型自己学出软分类边界。这个方法概率更可靠,但多了一步训练和交叉验证。如果只是做实验对比,用第一种就够了;如果是给现场诊断提供参考置信度,建议用第二种。

拿到概率之后怎么解读,我这里说一个真正有用的经验:不要只看最大概率的类别,要看概率分布的“形状”。如果某个样本在正常状态概率0.45、内圈故障概率0.43,那这个样本是典型的“边界样本”,算法几乎无法可靠判别,现场应该提示复检或者补充特征。真正状态清晰、特征明显的样本,概率分布会有一个绝对峰值,比如98%指向同一故障模式。把那些最大概率低于0.6的样本全部捞出来,看它们的原始信号长什么样,往往能发现新的故障演化阶段或者特征质量问题。这一步做得好,比单纯刷准确率值钱得多。

5. 参数调节与常见问题排查

5.1 邻接图参数怎么选

图嵌入算法的效果一大半由建图参数决定,模型本身的容错能力反而不高。三个核心参数分别是类内邻居数k_w、类间邻居数k_b、热核宽度sigma。

k_w太小,比如取1到2,类内图会变得非常稀疏,图可能分裂成多个不连通子图,降维结果出现碎片化;k_w太大,比如取到样本总数的30%以上,类内图把所有同类样本全连上了,局部结构信息被平均掉,算法退化成接近全局方法。我的经验范围是k_w取5到15之间,具体看每类样本数量,最好保证k_w不超过最少的类别样本数减1。

k_b的取值逻辑不太一样。它不是越大越好,而是通常比k_w小。因为类间图的主要作用是推开异类的近邻样本,一个样本身边真正构成“判别压力”的异类其实就那么几个,取3到8就够。k_b取太大会把各种边远地区的异类全部拉进目标函数,反而让局部判别结构被全局分布拉扯。

sigma的选取最容易迷惑人。热核权重exp(-dist²/sigma²)对sigma极其敏感,sigma太小时,距离稍微远一点的邻居权重直接趋近于0,图矩阵变得非常稀疏;sigma太大时,权重差异极小,所有连边的权重都接近1,等于用了无权重图。我推荐一个实操标定方法:计算训练集所有样本两两距离的中位数med_dist,让sigma从0.5med_dist到2med_dist之间按倍数扫一遍,挑验证集准确率最高的值。这个方法虽然土,但比强行套某个理论公式要稳定得多。

5.2 典型问题实录速查表

在实际跑NDGE的过程中,下面这些是我和身边同事踩过、也帮别人排查过的高频问题,整理成速查表方便对照。

现象根本原因解决办法
eig求解出现NaN或Inf特征值类间散布矩阵S_b奇异,常见于样本数少于特征数在S_b上加reg*eye(),reg从1e-6开始调
投影矩阵某些列为全零或接近全零对应广义特征值趋于0或无穷大,数值退化检查是否在同质样本簇之间建了过于稀疏的邻接图,适当增大k_b
不同维度准确率曲线剧烈抖动部分维度特征向量不稳定,分母矩阵轻度奇异增大正则项,或改用核化的距离权重:先对X做PCA白化再建图
kNN分类准确率一直上不去特征矩阵质量不够,或者图参数选得不匹配先直接跑PCA+LDA看基线的准确率,再回来调图参数,NDGE不应低于LDA太多
训练准确率极高、测试准确率明显更低信息泄漏或过拟合确认训练测试按时间切分而非随机打乱,选更小维度d,增大正则项
概率输出基本等于硬分类温度参数T设置过小把T设为所有样本距离的平均值,概率曲线立刻平滑很多

这里面最隐蔽的坑是“PCA白化”这一步。很多做实验的人习惯把特征矩阵标准化后直接建图,但标准化只解决了尺度问题,没有解决特征之间的相关性。如果特征里有两个高度相关的维度,那么XL_bX'的奇异程度会更高。我的做法是在标准化之后,先对X做一个PCA旋转并保留95%能量,把相关性和冗余在进入NDGE之前先去掉一层。这不会破坏NDGE的判别信息,反而让广义特征值求解的稳定性显著提高。

5.3 概率置信度不靠谱怎么办

概率输出不准的问题一般有两个来源。

第一个来源是建图本身的标签不平衡。如果某种故障模式的样本量只有另一种的十分之一,类间图里少数类样本被正常类包围,概率输出里少数类的后验估计天然偏低。这时候不要直接怪分类器,先看训练集的类别构成。可以给少数类在训练阶段提高样本权重,或者在构造图的时候把节点度归一化做得更细。另一个办法是生成少数类的合成样本,比如用简单插值或者SMOTE技术给少数类扩充数据,但要记得插值之后必须重新标准化再建图。

第二个来源是测试样本落在训练数据分布之外。现场数据往往带着新的工况、转速、载荷变化,模型在训练分布上表现再好也没用。判定的办法简单直接:拿测试样本在嵌入空间里找它的k(比如5)个最近邻居,算一下这5个邻居的平均距离。如果这个平均距离超过训练集里所有样本的平均距离的三倍以上,直接把这个样本标记为“低置信度样本”,概率结果不要作为最终判据。这在实际项目里比调温度参数有用得多,本质上就是给算法加了一个“我不确定”的出口。

6. 与同类方法的横向对比

6.1 三种方法放在一起比什么

做学术或写实验报告时,NDGE很少单独出现,通常要和PCA、LDA、LPP这类方法放在一起做降维对比,你能拿出来讲的核心亮点就是“利用判别信息 + 归一化抵抗类别不平衡”。

PCA作为无监督基线,不关心标签,只看方差。LDA是全局判别方法,假设各类高斯分布同协方差。LPP是局部保结构但不利用标签的流形方法。NDGE和这几类相比,最大差异在于:它同时在类内图上收紧同类样本的距离、在类间图上推开异类邻居,并且用归一化拉普拉斯解决了类别不平衡问题。对比实验时固定同一套特征矩阵和分类器,分别用这几种方法降到同一维度,比较测试集准确率,NDGE通常在中低维度上占优,特别是在样本重叠度高的情况下。

有一点需要特别提醒:LDA有个天然限制,类别数减1是它的最大可投影维度,所以多类故障诊断场景下LDA降到二维做可视化是不成立的,最多只能降到类别数减1维。NDGE没有这个限制,维度可以从2一直取到几十,这也是它适合画维度准确率曲线的原因之一。

6.2 实验设计的一些个人经验

这类算法实验的设计很容易踩“看起来热闹但证明不了什么”的坑。我总结下来,一套能站得住的对比实验至少包含三个部分。

第一部分是维度扫描曲线。所有方法在同一个维度范围下逐点取准确率,画成一条线,而不是只在某一个维度下比一个数字。这样一来,你可以看出谁的信息压缩效率高,谁在高维下开始过拟合。

第二部分是可视化。选一个固定维度(比如二维或三维),把测试样本的投影结果散点图放出来。连续看几个不同方法的散点图,你会有很强的直觉判断:NDGE的同类簇是否更紧凑、异类边界是否更清晰。很多时候散点图的说服力比准确率数字强得多,因为它直接展示了算法的判别几何。

第三部分是稳定性检验。把训练测试的划分方式换几种,比如按不同时间段划分、在不同转速工况下测试,看准确率是否保持稳定。NDGE如果连换几种工况都不掉链子,那才是真正的实用价值。只在一个固定划分上跑出来的高准确率,参考价值有限。

最后分享一个我实际项目里反复用到的习惯:这类图嵌入算法不必一上来就追求最高准确率,而是先把重心放在“错误样本长什么样”上。把NDGE分错的样本和PCA分错的样本单独打印出来对比,你会很明显地看到,分错样本的分布是有规律的,通常是处于故障早期或者故障模式混合状态的样本,而这些样本本来就处于模糊地带。算法把边界样本识别出来,其实比硬把它们塞进某一个类别更有用。这也是我为什么越来越喜欢带概率输出的故障诊断流程——它不只是给一个答案,还告诉你这个答案有多可靠。把每个样本的概率分布存下来,累积一段时间后回看,那些反复处于低置信度状态的样本,往往就是设备变化最早的信号。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询