归一化判别图嵌入NDGE:基于图局部结构的故障诊断降维方法

📅 发布时间:2026/10/17 9:37:36
归一化判别图嵌入NDGE:基于图局部结构的故障诊断降维方法
1. 高维特征让分类器失灵故障诊断为什么需要 NDGE 这种降维法1.1 特征向量越拼越长近邻关系却越来越不可靠在旋转机械的故障诊断流程里特征提取几乎是绕不开的一步。时域上算均值、峰值、峭度、偏度、波形因子频域上算重心频率、均方根频率、谱峰集中度时频域再弄几个小波包能量占比七七八八拼起来一个样本很容易就到三四十维。我刚接触这套东西的时候想法很简单特征越多信息越全分类器应该越准。结果做下来完全不是那么回事。真正到了高维空间欧氏距离会表现出一种反直觉的特性各样本之间的距离普遍趋同最近邻和最远邻的差距变得很小。这意味着原本在低维空间里靠“离哪个类近就判哪个类”的思路失效了。每个故障样本周围都能找到异类邻居k 近邻分类器的边界被噪声拉扯得七零八落。这还不是最麻烦的更麻烦的是很多特征之间有很强的相关性导致特征矩阵的协方差结构非常不稳定稍微换一段数据统计特性就明显漂移。1.2 PCA 和 LDA 的假设在工况变化面前站不住脚既然直接分类不稳那就先降维。主成分分析 PCA 是故障诊断里用得最多的降维方法它的目标是最优化方差保留率并不关心样本标签。在稳定的实验室条件下PCA 降维后还能看但一旦工况波动导致某些背景成分方差变大PCA 保留的方向就容易被转速基频、谐波等非故障成分带走。判别分析 LDA 虽然用到了标签但它的核心假设是每个类都服从相同协方差的高斯分布实际故障数据远没有这么规整。加上特征维度高、样本量少时LDA 的类内散度矩阵经常求不出可靠的逆计算结果会抖得非常厉害。从更高层面看PCA 和 LDA 都是一种“全局”方法它们用整个数据集的统计量来估计投影方向。但故障诊断中最有价值的信息往往藏在局部结构里比如某个故障类别内部样本的密集程度、不同故障类别在邻域边界上的重叠方式。全局统计量不会去管这些细节它只会把类别之间的均值差异拉大却处理不了邻域层面的交错。1.3 NDGE 的思路用图的局部结构承载判别信息归一化判别图嵌入简称 NDGE本质上是把两类约束同时放进一个目标函数同一故障模式的样本在原始空间离得近投影之后也要离得近不同故障模式的样本即使原始空间离得近投影之后也要被拉开。前者是图嵌入里的“保持局部结构”后者是判别分析里的“增大类间分离”。它和 LDA 最大的区别是不要求数据服从某个全局分布而是先用 k 近邻图把样本之间的局部关系刻画出来再在投影过程中尽量保留自己人和别人的边界。和 PCA 最大的区别是它显式地使用故障标签投影方向本身就带有判别性。这一点在实际调试时非常有用降维到三五个维度之后散点图上能看到清晰的分簇而不是 PCA 那种连续过渡的云团。2. NDGE 的数学骨架同类拉近、异类推开是怎样结合的2.1 图的构建类内图和类间图的分工NDGE 的第一步是把样本关系转成图。给定特征矩阵 Xn×d和标签向量 yn×1对每个样本 x_i先利用欧氏距离找到它的 k 个近邻。接下来按标签一分为二如果近邻样本 x_j 和 x_i 属于同一故障模式就把它记录到类内图 G_w边的权重取热核值 exp(-||x_i-x_j||²/σ)如果近邻样本 x_j 和 x_i 属于不同故障模式就把它记录到类间图 G_b权重同样取热核值或直接取 1。热核权重的好处是同时编码了“是否同类”和“距离多近”两层信息。同类但距离远权重小约束弱一点同类且距离近权重大投影时必须重点保住这个组合。异类边也一样距离越近的异类样本越需要在投影空间被推开否则这两个样本在原始空间的特征高度相似投影后不拉开分类器必然在它们的邻域里犯错。这里有个非常容易被忽略的细节构图必须做对称化处理也就是如果 x_j 是 x_i 的近邻反过来也要让 x_i 是 x_j 的近邻并保留同样的权重。原因在于拉普拉斯矩阵 L D - W 只有在 W 对称时才具有半正定的物理性质目标函数才能稳定。实际写代码时我会在循环结束后统一做一次 W max(W, W)把图补成对称矩阵。2.2 目标函数一个比值同时控制两类目标类内图 G_w 的权重矩阵记为 W_w度矩阵 D_w 是对角阵每个对角元素是该行权重之和。类内拉普拉斯矩阵 L_w D_w - W_w。类间图对应的 L_b 同理。投影矩阵 P 的优劣用下面这个比值衡量J(P) tr(P^T X^T L_b X P) / tr(P^T X^T L_w X P)分子是投影后异类样本的离散程度来自类间图分母是投影后同类样本的离散程度来自类内图。最大化这个比值就是希望投影空间中异类样本尽量分散同类样本尽量紧凑。换句更直接的话说就是找到一个方向让同类的邻居抱得更紧同时让混在附近的异类邻居被推远。这个目标函数和 LDA 的 Fisher 准则形式非常像但里面的散度矩阵不是全局统计量而是由图结构导出的局部统计量。所以它同时具备了 LDA 的判别性和图嵌入对局部结构的敏感度这也是 NDGE 名称中“判别图嵌入”的来源。2.3 归一化、正则化和广义特征值分解直接最大化这个比值等价于求解广义特征值问题X^T L_b X p λ X^T L_w X p取前 m 个最大特征值对应的特征向量按列拼成投影矩阵 P。但在真实数据上直接这么做通常会碰到两个问题。第一X^T L_w X 在高维小样本时近似奇异直接求特征分解数值上很危险得到的方向对噪声极其敏感。第二不同样本区域的密度差异会让某些密集区域在目标函数里权重过大投影方向被少数密集簇主导。NDGE 里的归一化主要针对这两点。对拉普拉斯矩阵做对称归一化把 L 替换成 D^{-1/2} L D^{-1/2}可以抑制密集簇的尺度效应另外在 X^T L_w X 上加一个很小的正则项比如 1e-6 乘以单位阵保证矩阵可逆。实际经验是这两步缺一不可少了对称归一化结果容易偏离少了正则项特征分解经常报错特征向量顺序不稳定。3. Matlab 实现主流程从特征矩阵到三个输出3.1 整体流程编排与函数接口设计Matlab 实现 NDGE 时我习惯分成四个函数数据准备、构图、求投影、分类与概率输出。数据准备解决特征矩阵的标准化和标签格式问题构图输入 X 和 y输出类内图、类间图两个权重矩阵求投影输入权重矩阵和 X输出投影矩阵 P 和对应特征值分类与概率输出负责在降维后的特征上训练分类器输出准确率和每个样本的故障概率。接口设计上尽量保持输入输出简单。比如求投影的函数签名function [P, evals] ndge_projection(X, Ww, Wb, m, reg) % 输入 % X - n×d 特征矩阵行是样本列是特征 % Ww - 类内图权重矩阵 % Wb - 类间图权重矩阵 % m - 保留的投影方向个数 % reg - 正则化系数默认可取 1e-6 % 输出 % P - d×m 投影矩阵 % evals - 按降序排列的广义特征值前 m 个这个函数在内部按特征值从大到小排序时就已经隐含了对投影维度 m 的选择逻辑特征值越大越有判别价值降维时优先保留前面的列。3.2 关键代码距离矩阵、图构建与拉普拉斯分解构图这一步是 NDGE 的性能瓶颈也是最容易写错的地方。用 pdist 配合 squareform 一步算出距离矩阵然后逐行取 k 近邻。下面这段代码可以直接套用function [Ww, Wb] ndge_build_graph(X, y, k, sigma) % 构建类内图和类间图 % X: n×d 特征矩阵, y: n×1 标签(1..C), k: 近邻数, sigma: 热核宽度 n size(X, 1); D squareform(pdist(X, euclidean)); Ww zeros(n, n); Wb zeros(n, n); for i 1:n [~, idx] sort(D(i, :)); nbrs idx(2:min(k1, n)); % 去掉自身并防止 k 越界 for j nbrs w exp(-D(i, j)^2 / sigma); if y(i) y(j) Ww(i, j) w; else Wb(i, j) w; end end end % 对称化保证拉普拉斯半正定 Ww max(Ww, Ww); Wb max(Wb, Wb); end构造完两个权重矩阵后连接归一化拉普拉斯与广义特征值分解。这里贴出我常用的版本function [P, evals] ndge_projection(X, Ww, Wb, m, reg) % 求解 NDGE 投影矩阵 Lw diag(sum(Ww, 2)) - Ww; Lb diag(sum(Wb, 2)) - Wb; % 对称归一化拉普拉斯抑制样本密度差异 invSqrtDw diag(1 ./ sqrt(sum(Ww, 2) eps)); Lwn invSqrtDw * Lw * invSqrtDw; invSqrtDb diag(1 ./ sqrt(sum(Wb, 2) eps)); Lbn invSqrtDb * Lb * invSqrtDb; Mw X * Lwn * X reg * eye(size(X, 2)); Mb X * Lbn * X; [V, D] eig(Mb, Mw); evals real(diag(D)); [~, ord] sort(evals, descend); P V(:, ord(1:m)); evals evals(ord(1:m)); end这里最值得说的细节是归一化顺序。我是先对拉普拉斯矩阵做对称归一化再计算 X^T L X 的散度形式。如果先对原始特征做标准化确实能让数值稳定一些但对邻域密度差异的抑制不够直接。按上面这种写法不同样本密度区域的尺度差异在拉普拉斯层就被消掉了。3.3 分类与概率输出softmax 回归和前向预测降维之后做什么取决于你的诊断目标。如果只想要准确率降维后的特征接一个 kNN 分类器就够用如果还想要每个样本对不同故障模式的概率建议直接用 softmax 回归。下面是一个自包含的 Matlab 实现不依赖额外工具箱function [Wc, Bc] softmax_train(Ytr, ytr, lambda, epochs) % 训练 softmax 回归 % Ytr: n×m 降维后训练特征, ytr: n×1 标签, lambda: L2 正则, epochs: 迭代次数 n size(Ytr, 1); d size(Ytr, 2); C max(ytr); Wc 0.01 * randn(d, C); Bc zeros(1, C); Yone zeros(n, C); for i 1:n Yone(i, ytr(i)) 1; end lr 0.05; for iter 1:epochs scores Ytr * Wc Bc; p exp(scores); p p ./ sum(p, 2); gradW (Ytr * (p - Yone)) / n lambda * Wc; gradB mean(p - Yone, 1); Wc Wc - lr * gradW; Bc Bc - lr * gradB; end end预测阶段把测试样本转到同一投影空间输出概率矩阵function [prob, pred] softmax_predict(Yte, Wc, Bc) % Yte: nte×m 降维后测试特征 scores Yte * Wc Bc; prob exp(scores); prob prob ./ sum(prob, 2); [~, pred] max(prob, [], 2); end如果你更习惯内置统计函数也可以使用 mnrfit 做多项逻辑回归但要注意一个坑mnrfit 返回的系数是按参照类编码的并不直接给你完整的 C 类系数矩阵需要自己补全参照类的系数和概率。我之前因为这个在结果对齐上栽过跟头所以后来干脆用上面的自定义实现逻辑透明也好做概率修正。还有一个关键约束测试集的投影必须用训练集学到的 P 去乘绝不能用测试集重新构图重新求投影否则等于把测试集信息泄漏进了降维过程得到的准确率是虚高的。这一点我见过不少新手踩坑准确率看着 98%换个现场数据直接打回原形。4. 三个输出结果怎么解读投影矩阵、维度准确率、故障模式概率4.1 投影矩阵 P每一列都是一个判别方向别只看行列数投影矩阵 P 的维度是 d×m。每一列对应一个投影方向第一列对应最大广义特征值理论上是最强的判别方向。判断投影矩阵是否合理我最常用的做法是直接看投影后的二维散点图取前两列对训练样本投影正常样本、内圈故障、外圈故障、滚动体故障应该各自成簇簇与簇之间有清晰的间隙。如果前两列散点图已经分不开不要急着怀疑算法先检查构图参数是不是没调好。把 k 调小一点、σ 按距离的 0.1 分位数到 0.5 分位数去扫描通常就能看到可分离性明显改善。另一个验证手段是看投影方向本身把 P 的第一列还原到特征维度检查哪些原始特征在投影方向上有较大权重。如果第一列主要集中在某个小波包能量特征和峭度特征上说明该故障模式在时频能量分布和冲击特性上体现得最明显这个结论可以反过去指导特征优选。4.2 维度-准确率曲线选多少个投影方向最合适NDGE 输出里最有决策价值的其实是不同维度下的准确率曲线。做法并不复杂把 m 从一个很低的维数逐步增加到十几个维每取一个 m用训练集求一次投影矩阵再在测试集上评估准确率最后画出一条“维度 vs 准确率”的曲线。我自己做实验时的典型结果如下表所示投影维度 m测试集准确率备注20.894前两维已经能区分主要故障30.927滚动体故障开始和正常样本分离50.951大部分误判来自轻微故障与正常样本80.968增益开始放缓100.972接近饱和150.966略有下降开始出现过拟合这张表的价值在于帮你找到一个拐点在拐点之前增加维度收益明显在拐点之后增加维度收益很小甚至下降。下降的原因通常是高维投影保留了噪声方向也就是那些特征值很小的判别方向它们对训练集有拟合作用对测试集没有泛化能力。实际工程里我通常选拐点前一两维而不是选准确率最高的维度因为拐点附近模型的工况鲁棒性好得多。4.3 样本级故障概率从判断类别到量化置信度softmax 概率输出把每个测试样本表示成一个 C 维概率向量比如 [0.963, 0.027, 0.008, 0.002]代表该样本有 96.3% 的置信度属于正常状态2.7% 属于内圈故障。这种输出的好处是不只是给一个标签还给出了决策的置信度方便现场人员决定要不要停机检查。使用概率输出时我会额外做两件事。第一设置一个最低置信度阈值比如 0.85低于这个值的样本一律标为待复查而不是硬给一个故障标签。第二把混淆矩阵和概率分布结合起来看重点观察哪两类故障之间的概率经常相互纠缠。当某个样本在正常和滚动体故障上分别有 0.52 和 0.45 的概率时说明该样本大概率处于早期退化阶段特征还不足以把两者分开这种样本恰恰是状态监测最有价值的目标——提前预警而不是事后分类。5. 调参经验与踩坑记录这些细节代码里不会告诉你5.1 k 和 sigma先粗扫后精调结果是准的NDGE 最重要的两个超参数就是近邻个数 k 和热核宽度 σ。k 太小图结构太稀疏局部信息保持不了k 太大异类近邻混入太多类间推开的约束过强同类样本反而被撕裂。我的一般顺序是先固定 k 在 5 到 10扫描 σ 取距离矩阵的 10% 分位数、30% 分位数、50% 分位数几个值看哪个 σ 附近准确率最高然后固定这个 σ把 k 从 3 扫到 15再选最优。两步下来基本能满足大多数数据。有个更微妙的地方σ 对图权重的影响是非线性的太大时所有近邻权重都接近 1图和二值图没区别太小时只有最近的样本才有非零权重图变得极度稀疏广义特征值分解容易出病态结果。建议画一次距离直方图让 σ 落在样本距离分布较密集的区域这样权重的区分度最好。5.2 小样本广义特征值分解的数值坑故障诊断数据集往往是样本少、特征多几十个样本、四五十个特征非常典型。这种情况下一不留神就会遇到一个坑特征分解返回的特征值和特征向量看起来正常但交叉验证时每次投影矩阵的列顺序不同导致后续可视化对不上。原因是小样本下散度矩阵有大量接近零的特征值归一化后这些方向上数值极不稳定特征向量的符号甚至意义都会抖动。解决办法有三层第一尽量对原始特征做标准化减少量纲差异第二正则项系数不要太小我通常取 1e-6 到 1e-4视特征尺度而定第三对比实验时固定随机种子保证交叉验证划分一致。最后一点尤其重要否则你很难判断准确率的变化到底是算法改进还是数据划分的偶然波动。5.3 类别不平衡下的概率输出偏差现场故障数据普遍不平衡正常样本很多故障样本很少。此时 softmax 输出概率会偏向样本量大的类哪怕算法本身没问题。我的处理方式是按故障类别的先验比例对概率做校正p_corrected(c) p_raw(c) / prior(c)再归一化成概率分布。prior(c) 用训练集类别占比近似。这个方法粗暴但有效在早期退化警告场景下能够明显提高小样本故障类别的召回率。另外评价指标也不要只看准确率。样本不平衡时准确率可能被多数类带得很高真正关心的漏报率却很差。建议固定看 F1-score或者在混淆矩阵上调阈值兼顾每类故障的查全率和查准率。5.4 对比实验的公平性降维和分类评测别混在一起做方法对比时最容易犯的错误是对 NDGE 用了复杂的调参对 PCA 和 LDA 却用默认参数最后 NDGE 赢主要是赢在调参上而不是算法本身。我现在的做法是统一评测流程所有方法都在同一个标准化后的特征上执行投影维度扫描相同的范围下游分类器全部用同样的 softmax 模型或者同样的 kNNk1并且使用相同的交叉验证折数。做完一组实验才能放心地说 NDGE 的准确率提升来自判别图嵌入带来的投影质量而不是分类器或评价口径的差异。最后回到实际操作本身。我自己用 NDGE 最顺手的场景是那种特征维度三四十、故障类别四五个、每类样本二三十个的中小样本故障诊断任务。把投影维度定在 5 左右准确率曲线和概率输出一起看基本能覆盖大多数工程场景。如果数据规模很大、特征上万的话建议先用 PCA 把维度压到一两百再做 NDGE速度和数值稳定性都会好很多。这个组合思路我一直在用实测下来的确比单一降维方法更省心。