资讯动态

半监督故障诊断:LPS-DGAT如何用图标签传播突破样本稀缺瓶颈

发布时间:2026/10/20 17:08:15 来源:尧图企业网站定制
当时接这个方向的时候项目组手里的数据分配非常尴尬一个转轴试验台跑完一轮故障注入正常和各类故障状态加起来有十多种但真正有专家确认过标签的样本每类只有十几个其余几千段监测数据全部是“有信号、无答案”的无标注状态。最初想硬套有监督CNN去训效果惨不忍睹——训练集准确率能到九十多测试集却只有七成出头标准过拟合。后来意识到在半监督故障诊断这条路上核心问题不是模型容量不够而是怎么把大量无标签数据真正利用起来。于是转向了图结构加标签传播的路线折腾出了LPS-DGAT这套组合方法。这篇文章就完整交代一下为什么这么选、整体框架怎么搭、实验验证了什么以及复现调参时踩过的那些坑。1. 为什么故障诊断需要半监督一个常被忽略的现实前提1.1 故障样本稀缺是工程常态不是理论假设很多刚接触这个方向的人第一反应是“故障诊断不是有标准数据集吗直接有监督分类不就行了”。但到了实际项目和现场设备上标准数据集那种“每类几百上千个样本随便用”的奢侈条件基本不存在。设备正常运转才是常态故障本身是低概率事件一套机组一年可能就发生两三次异常标记为特定故障类型的样本数量极其有限。更麻烦的是同类故障的损伤程度不同、负载工况不同采集到的振动波形差异很大想用几十个样本把整个类别分布覆盖住几乎不可能。标签成本也是绕不开的硬约束。故障标签不是写代码的人能拍板给的通常需要设备专家或老师傅结合停机检修记录、频谱分析报告来确认一条历史数据的标签可能要从几年前的维修工单里翻出来。这种人工确认流程周期长、价格高而且早期记录还不一定准确。相比之下传感器在线的振动、电流、温度信号一直在产生硬盘里的无标签数据越来越多形成典型的“数据管够、标注不够”局面。1.2 从有监督到半监督本质是“学会利用无标签数据”有监督模型在标签充足时表现很好可一旦标签数量掉到每类十几个模型很容易把有限标签样本的细节直接背下来泛化能力几乎为零。半监督学习的思路不太一样不把无标签数据当废料而是让模型从大量未标注样本的分布结构里挖判别信息。无标签数据里其实藏着大量规律——同类故障的特征往往聚集在特征空间的某些区域不同故障之间有明显间隔这些结构不需要标签也能被发现。半监督方法市面上不少常见路线包括一致性正则、伪标签自训练、对比学习、图半监督等。我这次选择图结构加标签传播路线是因为故障诊断数据有个天然特点样本之间本身可能存在物理层面的相似性比如相同故障类别、相近工况下的振动模式高度相似。这种关系用图来建模非常自然——样本是节点样本间的特征相似度是边标签可以沿着这些边向未知节点传播。于是就有了标题里的两个核心组件LPSLabel Propagation Strategy标签传播策略负责解决“哪些无标签数据可以用”DGATDynamic Graph Attention Network动态图注意力网络负责解决“这些数据的信息怎么被有效学进模型”。2. LPS与DGAT的组合逻辑先解决“可用数据”再解决“可学特征”2.1 DGAT动态图注意力网络在故障诊断中的定位先说说DGAT里的图注意力机制到底是什么。图注意力网络GAT的核心思想是给每个节点的邻居分配不同的注意力权重哪些邻居和当前样本更相关就在聚合特征时多听它一点哪些邻居关系没那么大就少听一点。做个类比这就像到一个新班级判断某个同学的学习水平你会重点参考那些平时和他互动多、成绩表现也相近的朋友的意见而不是把全班几十个人的评价平均一下。用在故障诊断上每个样本节点在图上都有若干个邻居节点。通过注意力系数加权聚合邻居特征节点能够吸收同类故障样本的信息从而让自身特征更有判别性。多层堆叠之后整个图上的故障模式会变得越来越清晰。而且和多层感知机、CNN这种“每个样本单独看”的模型不同图模型天然在样本间建立联系这一点在半监督场景里是杀手锏即使某些无标签样本自身特征很模糊它们只要有一群标签明确的同类故障邻居模型也能通过聚合推断出大致类别。“动态”两个字怎么理解初始图是用某种预先定义的样本相似度构建的比如特征空间欧氏距离或频域相似度。但问题是随着模型训练推进样本的特征表示在不断变化一开始算出来的邻居关系可能已经过时了两个样本初始时看起来相似训练后它们被分到了不同区域另一些初始不相似的样本反而越学越近。如果始终用旧图信息聚合就会走偏。所以DGAT会周期性根据当前特征表示重新建图保证邻域结构始终贴近特征空间的真实分布。2.2 LPS标签传播策略如何避免“错误雪崩”图有了接下来关键问题就是怎么把标签从有标注样本传到无标注样本。最朴素的伪标签做法是模型预测哪个类别的概率最高就直接拿来当硬标签训练。但半监督学习有个著名风险——错误雪崩。简单说早期模型能力不足某个无标签样本被错误打上标签这个错误标签进入训练集后会把模型往歪的方向带一点模型更歪之后又会对更多无标签样本产生错误预测这些新错误再进入训练集误差像滚雪球一样越滚越大最终所有类簇都可能被污染。LPS的设计目标就是阻止错误雪崩。它的思路不是“预测置信度够高就发标签”而是双重确认第一重确认是模型输出概率足够高高到有把握第二重确认是参考该样本在图上的邻居情况——如果它的绝大多数邻居都是同一个标签类别或者和某个已知故障簇的局部一致度很高才认为这个预测是可信的。如果模型预测置信度很高但图上邻居标签分布和它矛盾这种情况往往意味着边界样本或跨类重叠样本直接跳过比强行标注更安全。实际上LPS还借鉴了经典标签传播算法的思想标签可以沿着图上的边向远处扩散。经典标签传播的问题是它只做非参数推断不能对没见过的样本直接预测也学不到深层特征LPS则把这种传播逻辑嵌进了深度网络的迭代训练过程每次用“当前模型预测图邻域一致性”双保险挑选可靠样本同时保留一个“疑问样本池”暂不标注留到后续轮次模型更稳定时再重新判断。2.3 为什么是“LPS-DGAT”而不是“CNN伪标签”也解释一下为什么这个组合比很多现成方案更合理。明确一个事实CNN只能看到单样本内部的局部模式比如振动波形里有没有冲击成分但对“两个样本是否属于同类”这种关系一无所知。如果只用CNN加朴素伪标签相当于让模型在没有交叉验证能力的情况下自我确认错标样本几乎无法被识别出来。加入图结构之后无标签样本的判断不再孤立。即便某个样本的模型预测概率达到0.97只要它在图上和一大批标签不同的样本紧密相连我们就有理由怀疑这个高置信度预测可能只是局部过拟合的结果。LPS和DGAT的关系可以概括成一个分工LPS负责回答“哪些无标签数据值得信”DGAT负责回答“怎么把信得过的数据信息用充分”。两个模块在同一张图上运作图结构为标签筛选提供依据筛选后的伪标签又参与下一轮图重建和特征学习形成一个自我修正的循环。这三条路线的对比能说明问题。CNN朴素伪标签在标签极少时容易崩GAT朴素伪标签能利用图结构但对错标样本没有筛选LPSDGAT则是既利用图结构聚合邻居信息又通过标签传播策略把不可靠样本挡在训练集外。后面实验结果部分会看到筛选这一步对最终性能的影响非常显著。3. 方法主流程拆解从振动时序到迭代训练闭环3.1 图构建样本作为节点、相似度作为边的初始拓扑整个方法的第一步是把原始振动信号变成可供图上操作的样本节点。原始数据是连续的振动加速度时序需要先做滑窗切段。窗口长度通常要覆盖若干转轴回转周期比如1024点或2048点相邻窗口之间取50%重叠这样既增加样本量又保留足够的周期信息。每一段信号都要小心避免和未来信息混在一起特别是后续做实验评估时切段产生泄漏会直接导致结果虚高。接下来是特征提取。最初版本直接拿原始时序算样本间距离效果很差因为原始波形里噪声和随机冲击干扰太大相同故障的两个样本之间的欧氏距离可能比不同故障还大。后来改成多域特征组合时域均值、均方根值、峰值因子、峭度、偏度频域主频位置、频谱质心、若干频带能量占比时频域小波包分解后的各频段能量每个样本最终表示成一个三四十维的特征向量。接着做标准化这一步极其关键后面专门讲坑。构建初始图时用特征向量的径向基核函数计算相似度公式是# 伪代码RBF/径向基核相似度配合k近邻建图 import numpy as np from scipy.spatial.distance import cdist # X: [N, D] 每个节点一个特征向量 dist cdist(X, X, metriceuclidean) sigma np.median(dist) # 取所有配对距离的中位数作为带宽 adj np.exp(-dist ** 2 / (2 * sigma ** 2)) # 对每一行保留k个最大相似度邻居其余置零 k 15 for i in range(N): idx np.argsort(adj[i])[::-1][:k1] # 包含自环 mask np.ones(N, dtypebool) mask[idx] False adj[i][mask] 0.0 adj (adj adj.T) / 2 # 对称化k近邻保证了每个节点至少有几个可聚合的邻居避免图过于稀疏自环则保证节点自身特征不会在注意力聚合过程中被丢弃。σ参数取中位数距离是一个经验选择太大会让所有边权都趋近于1图失去区分度太小则只有极近邻才有有效权重信息传播半径过窄。3.2 LPS模块的伪标签生成与置信筛选LPS不是一次性给所有无标签样本生成伪标签而是每一轮训练之后动态更新。伪代码逻辑大致是这样# LPS模块每轮训练后执行 def generate_pseudo_labels(model, G, features, unlabeled_idx, labeled_idx, labels, tau, mu): probs model.forward(features) # [N, C] candidate [] for i in unlabeled_idx: p probs[i] conf p.max() pred_class p.argmax() if conf tau: continue # 置信度不足不入候选 # 统计图上邻居中已知标签的分布 neighbor_labels [] for j in G.neighbors(i): if j in labeled_idx or j in pseudo_dict: neighbor_labels.append(labels[j]) if len(neighbor_labels) 0: continue majority_ratio np.mean(neighbor_labels pred_class) if majority_ratio mu: # 邻居多数类与预测类别冲突视为边界样本 continue candidate.append((i, pred_class, conf * majority_ratio)) # 按可信度得分排序取前K个作为本轮伪标签 candidate.sort(keylambda x: x[2], reverseTrue) pseudo_dict {i: pred for i, pred, s in candidate[:K]} return pseudo_dict两个核心参数是置信度阈值τ和邻域一致性阈值μ。τ控制模型自身信心的门槛μ控制图结构上的旁证强度。两者同时满足才授予伪标签效果远好于单看置信度。被拒掉的样本会放进待定池下一轮继续评估不直接判死刑——因为当前模型能力弱不代表以后也弱。一个细节是伪标签集合每轮会覆盖更新上一轮发的伪标签如果在本轮模型看来已经不可靠会被撤销。这避免了错误一旦进入就永久固定的问题。3.3 DGAT骨干网络与动态图的协同更新DGAT骨干网络的结构不算复杂它由一个特征编码器加若干层图注意力层组成。特征编码器可以是简单的MLP也可以换成轻量CNN作用是先把原始特征映射到更利于图学习的空间。图注意力层的计算逻辑可以参考下面的骨架# 单层图注意力卷积简化示意 class GATLayer(nn.Module): def __init__(self, in_dim, out_dim, n_heads4): super().__init__() self.W nn.Linear(in_dim, out_dim, biasFalse) self.a nn.Parameter(torch.empty(n_heads, 2 * out_dim)) nn.init.xavier_uniform_(self.a) self.n_heads n_heads def forward(self, h, adj): Wh self.W(h) # [N, out_dim] # 对每对邻居计算未归一化注意力系数 # e_ij LeakyReLU(a^T [W h_i || W h_j]) # alpha_ij softmax_j(e_ij) # h_i 多头加权聚合邻居 Wh_j return multi_head_aggregate(Wh, adj, self.a, self.n_heads)实际使用中会堆叠两层GATLayer并在层间加入残差连接和LayerNormdropout设在0.3左右。注意力头数常用4到8多头机制能让模型从不同相关性子空间考察邻居关系稳定性更好。动态图更新的节奏需要单独控制。每轮训练都重建图会让邻域关系不停震荡模型来不及适应就又被改掉了从另外一面说更新太慢又不赶不上特征变化。实际操作中每隔E轮重建一次邻接矩阵E一般取5到10。更重要的是重建图时使用的不是当前轮次的瞬时特征而是指数滑动平均特征。这样图结构的变化更平滑不会因为某一轮的剧烈波动导致邻居关系大面积错乱。3.4 整体训练闭环与损失设计把以上组件串起来训练流程大致是用有标签样本做预热训练初始阶段只计算监督损失给网络一个合理的起点预热若干轮之后每一轮训练结束用当前DGAT输出概率执行LPS筛选在有监督样本之外加入伪标签样本训练损失由两部分组成有标签样本的交叉熵损失加上无标签伪标签样本的交叉熵损失每隔E轮用指数滑动平均特征重建图拓扑更新注意力聚合的对象关系。总损失可以写成total_loss ce_loss(labeled_logits, labeled_labels) \ lamda * ce_loss(unlabeled_logits, pseudo_labels)其中λ是伪标签损失的权重初期设小值如0.3随着训练稳定逐步升到1.0。这个权重策略和很多半监督方法里“先紧后松”的思路一致目的是保护早期模型不被大量可能含噪的伪标签带偏。预热轮数burn-in通常设为10到20轮这个阶段别急着用LPS。原因也很直白模型在最开始没有任何判别能力的时候所谓“高置信度”都是虚高这时候引入伪标签基本是引狼入室。4. 实验设计与效果验证在轴承数据上的实测对比4.1 实验配置数据划分、类别与评价指标实验用的是一套公开轴承振动数据集这里用Dataset-A代称。数据包含正常状态、内圈故障、外圈故障、滚动体故障四种大类每种故障再按损伤尺寸细分组成10个类别。采样信号是加速度振动每种工况下有大量样本。为了模拟真实的半监督故障诊断场景我做了这样的数据划分每类只随机保留10个有标签样本参与训练其余样本全部作为无标签池喂给模型但不能使用它们的真实标签参与损失计算。测试集单独从同工况后续时间段里抽取保证与训练样本没有重叠泄漏。对比方法选了四类传统机器学习代表SVM核函数映射后分类、标准CNN、固定图GCN、标准GAT再加上一个“GAT加朴素伪标签”作为对照。评价指标是总体准确率和宏平均F1分数。宏平均F1在这个场景里比准确率更值得关注因为各类样本量并不均衡单纯看准确率有时会被多数类掩盖。4.2 对比结果与关键发现表1记录了在每类仅10个标签样本条件下各方法的测试表现方法总体准确率宏平均F1SVM76.8%72.3%标准CNN81.5%77.9%GCN85.1%82.4%GAT86.3%83.7%GAT朴素伪标签89.2%85.5%LPS-DGAT94.6%92.8%三个关键发现值得展开。第一图方法整体优于普通CNN哪怕没有额外策略GCN和GAT都已经比CNN高出四五个百分点说明样本间的关系建模在半监督条件下确实有不可替代的价值。第二朴素伪标签能带来提升但方差很大换几个随机种子之后有时提升不到两个点这符合预期因为朴素伪标签不做筛选噪声积累问题不稳定。第三LPS-DGAT在准确率和F1两项上都明显领先说明双重确认的标签筛选策略确实堵住了错误传播的漏洞。进一步测试了标签数量从5张/类增加到20张/类时的表现结果同样有说服力每类标签数CNNGATLPS-DGAT570.2%77.4%87.3%1081.5%86.3%94.6%2087.9%90.5%96.8%可以看到标签越少LPS-DGAT相对其他方法的优势越明显说明这套组合对标签稀缺场景的适应力确实在线。4.3 消融实验说明为了确认每个组件都在起作用我做了三组消融。去掉LPS只用动态图DGAT准确率掉到87.5%说明光有动态图结构但缺乏可靠的标签传播策略收益会大打折扣。去掉动态图更新只保留固定图加LPS准确率在91.6%左右说明动态图修正拓扑结构带来的收益是实打实的。两个组件全部装上才是94.6%二者不是简单的叠加更像互相成就——LPS筛选出的高质量伪标签让动态图更新时特征空间更干净动态图给出的合理邻居关系又让LPS判断更准确。5. 我在复现和调参过程中踩过的几个坑5.1 图构建对量纲和特征归一化极其敏感第一次跑通流程后效果很差检查图的构建质量才发现问题严重。当时直接拿原始特征向量算欧氏距离结果因为振动信号里某些频带能量比其他特征大两三个数量级距离计算被这些高幅值特征完全主导类别信息反而被淹没。k近邻图里跨类别邻居比例高得离谱节点几乎都连到了几个幅值异常大的样本上。解决办法是对每个特征维度分别标准化频域特征还要做功率归一化避免特定频段压制其他维度。修完这步之后图上的同类邻居占比从六成提升到八成以上。想提醒做类似方法的同学图建完之后先别急着训模型直接统计一下“每个节点的多数邻居和真实标签是否一致”这个同配率指标。如果同配率低于0.75图结构多半有问题先用数据质量手段解决不要指望后续网络去硬扛。5.2 置信度阈值的选择比想象中更影响性能LPS里有三个核心超参数置信度阈值τ、一致性阈值μ、每轮新增伪标签数K。τ的影响最突出。τ太低比如0.5几乎一半无标签样本都能拿到伪标签但里面混入大量边界噪声样本错误雪崩迅速爆发τ太高比如0.95确实安全但每轮只有很少的样本能获得标签半监督退化成接近有监督提升有限。测试下来τ0.85左右是一个性价比很高的平衡点。后来我还做了一点改进把固定阈值改成动态变化。训练初期模型整体置信度都偏低就用高阈值0.92筛选最可靠的一小部分训练后期模型已经稳定可以适当放宽到0.8同时利用待定池里的样本补充训练集。每轮还要监控一个“伪标签翻转率”——也就是上一轮被授予伪标签的样本在下一轮模型预测中被改成其他类别的比例。如果翻转率超过10%说明阈值设得太松需要回调。5.3 动态图更新频率更新太勤反而振荡最初图更新设定为每个epoch都重建理由是“让图保持最新不是更好吗”结果训练损失曲线像锯齿一样大幅波动准确率反而不如固定图。原因不复杂每轮重建图后节点的邻居关系大面积改变同一轮内聚合信息的来源不稳定模型被逼着适应一套不断更换的“坐标系”学习过程自然剧烈振荡。后来把重建间隔拉到10轮并用指数滑动平均特征建图损失曲线就平滑下来了。这个经验背后是一个挺朴素的道理动态不等于高频。动态图要想好用必须以稳定性为前提否则重建出来的邻居关系根本没有足够时间让模型消化。5.4 伪标签burn-in阶段的必要性另一个容易忽略的细节是burn-in预热。最开始我一上来就开LPS觉得“反正半监督就是要用无标签数据嘛”结果前几轮模型输出的置信度毫无参考价值高置信度往往集中在几个容易混淆的类别上伪标签一进去立刻把类别中心带偏后面再想掰回来特别费劲。加入10轮左右的预热阶段让模型只靠有标签样本先站稳伪标签的质量立刻上了台阶。这个坑几乎每个做半监督深度学习的同学都会遇到属于交学费项目提前知道能省下很多调试时间。6. 关于落地与扩展的一点个人体会6.1 从公共数据到现场数据还有多远公共数据集上表现不错不等于现场就能直接复现。实际设备数据至少有三层额外困难工况漂移导致特征分布缓慢变化、传感器位置和安装方式改变信号特性、历史标签噪声远高于公开数据集。做工程部署时建图用的滑窗重叠千万不能造成信息泄漏否则评估指标完全失真另外半监督模型输出的置信度并不天然等于校准概率有条件的话建议加一层温度缩放校准避免现场人员被虚高的置信度误导。6.2 可扩展方向在线诊断与多工况迁移这套框架具备持续学习的潜力。对在线流式监测数据没必要每次全局重建图可以用滑动窗口更新局部邻域关系只把新样本插入合适的图位置同时把久远样本缓慢淡出。迁移场景也值得期待比如源工况有标签、目标工况只有无标签数据直接在图上通过特征距离做跨工况标签传播这样一个工况积累的专家知识就能被其他工况复用。LPS-DGAT本身的迭代闭环对这类问题几乎不需要改结构只要把图构建和伪标签筛选的逻辑接到新数据上即可。最后说点个人体会。这套方法让我深刻理解了一个道理半监督故障诊断不是一个“加上伪标签”就能解决的问题真正的难点在于设计一套可靠的错误容忍机制——让模型敢于利用无标签数据又不会因为个别错误标签越走越偏。图结构给出了天然的旁证渠道LPS负责把关DGAT负责学习两者的闭环配合才是性能上限的来源。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑