资讯动态

基于标准Elman神经网络的DGA变压器故障诊断与小样本分类实践

发布时间:2026/10/23 9:34:36 来源:尧图企业网站定制
做变压器故障诊断的人绕不开DGA原始数据。所谓DGA就是溶解气体分析油浸式变压器内部绝缘油在一定温度和电场下会裂解出氢气、甲烷、乙炔等气体不同故障类型对应的产气组合差异很大。项目标题写得很直白基于标准Elman神经网络对DGA原始数据做故障诊断分类与预测。也就是说输入是七种气体的浓度输出是故障类型中间靠一个带记忆的反馈型神经网络来完成映射。我借着之前维护的一套历史油色谱标注样本把这个小项目从数据清洗一直跑到结果评估中间踩了不少坑也整理出一些能在工程里直接复用的经验。这篇文章适合两类人。一类是做电力设备状态检修的工程师想用神经网络替代传统三比值法但手头样本量不大、又不想一上来就上LSTM或Transformer那种大模型另一类是刚接触小样本分类的开发者想搞明白Elman这种反馈网络到底怎么落地和BP相比到底强在哪里。下文我会把数据预处理、网络设计、训练评估、避坑经验全部展开整体偏实操代码思路可以直接迁移到自己的数据集上。1. 从问题到方案为什么DGA诊断适合Elman神经网络1.1 先看数据里藏着哪些故障信息油浸式电力变压器一旦内部出现放电或过热绝缘油和固体绝缘材料就会发生裂解反应产生气体并溶解在油中。工程上最常看的特征气体有七种氢气H2、甲烷CH4、乙烷C2H6、乙烯C2H4、乙炔C2H2、一氧化碳CO、二氧化碳CO2。前五种是判断放电和过热的核心气体后两种更多反映固体绝缘老化但在神经网络模型里往往也能提供辅助信息。不同故障类型对应不同的产气模式。比如局部放电的电子能量不足以完全打断油分子中较强的化学键所以主要产氢气电弧放电温度极高油分子深度裂解乙炔浓度会明显上升低温过热阶段主要是甲烷和乙烷比例高温度升高到700摄氏度以上后乙烯和氢气占比会显著增加。把这些机理列成表会更直观故障类型主导气体典型特征正常老化H2微量、CH4少量总烃不高局部放电H2乙炔几乎为零甲烷少量低能放电H2、CH4、C2H2火花放电乙炔出现高能放电H2、C2H2、C2H4、CH4乙炔浓度高温度剧烈低温过热300℃CH4、C2H6甲烷比例高中温过热300~700℃CH4、C2H4、C2H6乙烯比例上升高温过热700℃C2H4、H2、C2H2乙烯明显乙炔少量这些气体浓度从几ppm到几千ppm不等量级差距很大。刚开始做这个项目时我直接把原始浓度扔进网络发现训练损失下降得非常慢后来才意识到量级差异会让梯度被大数值特征主导这个坑在预处理部分会重点展开。1.2 传统编码方法为什么在真实数据上失灵国内油浸式变压器DGA判断导则里常用的改良三比值法思路是把甲烷比氢气、乙炔比乙烯、乙烯比乙烷三组比值分别按阈值量化为0、1、2组成三位编码再查故障类型表。这个方法在常规放电和过热场景下已经用了很多年优点是简单、无需训练缺点也很明显边界特别脆。举个例子一组气样中乙炔和乙烯的比值恰好落在0.1附近采样误差或温度偏差让比值从0.09变成0.11编码就从0跳成1查表结果可能从低能放电直接变成高能放电。实际数据经常同时存在多类故障叠加还伴随CO、CO2、水分等干扰硬阈值查表很容易落入编码表中找不到的空白项。我当时处理一批历史样本时用三比值法能直接查表命中标签的比例只有60%出头剩下要么是编码越界要么是跟解体检查结论不符。神经网络的优势在于它用样本直接学习气体浓度到故障类型的连续映射决策边界是训练得到的不用人为设阈值。尤其是Elman这种带记忆的网络在处理同台变压器多次采样数据时还能把气体浓度的变化趋势利用起来比纯前馈网络更贴合诊断加预测的场景。1.3 标准Elman vs BP vs LSTM选型过程最开始尝试的是标准BP网络三层结构很快收敛单条样本分类准确率也能到80%左右但有个明显短板BP对每一条输入都是独立处理的完全不携带时间信息。如果手里有同一台变压器上个月的DGA数据和这个月的数据BP只能把它们当成两条无关样本气体比值是否在向危险方向发展这类趋势信号全部丢失。LSTM倒是有很强的时序记忆但参数数量多训练需要的数据量也大。DGA标注样本往往只有几百条放到LSTM里很容易过拟合训练时间也长。标准Elman处于两者之间结构非常简单只增加了一个承接层用来保存隐藏层上一时刻的输出参数量只比BP多一点却具备最基本的动态记忆能力。在小样本条件下这种轻量记忆结构往往比复杂网络更稳。网络记忆能力参数量DGA小样本适用性实现难度BP无少一般低标准Elman一层隐状态较少较好中LSTM/GRU强多易过拟合高Elman不是没有缺点它对初始权重比较敏感超参数需要调试网络过深时梯度传播也不够稳定。但对这种百级样本量的工程项目来说标准Elman是投入产出比很划算的选择。2. DGA原始数据的清洗、变换与小样本防泄漏2.1 读数据之前先画清特征边界原始数据常见格式是每行一个油样列包含采样日期、七种气体浓度和故障标签。有些表还会带上总烃、产气速率等衍生量。特征取哪几列直接决定模型输入维度我建议先只用七种气体浓度把CO和CO2单独保留。虽然CO和CO2主要用于固体绝缘诊断把它们放进特征对放电和过热分类也会有一点点帮助但加上后输入节点变成9个数据量少时反而增加负担。所以先跑一个七特征基线再尝试九特征对比用验证集准确率说话不要拍脑袋决定。标签方面通常会把溶解气体分析结果标注成正常、局部放电、低能放电、高能放电、低温过热、中温过热、高温过热这几类。如果某些类别样本太少比如只有三五条可以考虑合并把低能放电和高能放电合成放电把低温、中温、高温过热合成过热先做四分类。类别合并会损失细粒度信息但能让模型训练稳定很多实际项目里是常用妥协。2.2 清洗和变换浓度跨数量级不是小事清洗阶段要处理三类脏数据浓度列出现负值或明显录入错误部分气体浓度为0也就是低于检测限标签缺失或与典型编码明显矛盾。负值直接剔除0值不要直接当真实零点用可以先加一个极小值再参与对数变换。DGA浓度最大的问题就是量级差异太大。一台正常变压器的氢气可能只有几ppm而故障变压器的乙炔能到上千ppm。如果不做处理直接喂给神经网络数值大的特征会在距离计算和梯度更新里完全压过数值小的特征。我习惯先对浓度做log1p也就是log(1x)把几十到几千ppm的跨度压到几以内再做最大最小归一化把区间缩放到0到1之间。这一步做完模型收敛速度和精度都会有可感知的提升。还有一个小细节容易被忽视归一化的极值哪里来。正确的做法是从训练集上统计min和max测试集也沿用训练集的极值。如果直接用整个数据集统计测试集信息就等于提前泄漏给了模型评估结果会偏乐观。小数据集上这个偏差尤其明显。2.3 按设备分组划分堵住最隐蔽的数据泄漏DGA数据经常会来自同一台变压器的多次定期采样。若随机按行划分训练集和测试集同一台设备前后两次采样很可能会被分到两边模型等于提前见过这个设备的历史气体状态测试准确率会虚高。更麻烦的是迭代调参时会看到这种虚高感觉自己模型做得不错真正部署到新设备上才发现完全不是那么回事。可靠的划分思路是按设备编号或油样来源分组一台设备的所有采样记录要么全部进训练集要么全部进测试集。这样模型面对的才是真正没见过的设备样本评估结果更接近实际运维场景。我通常在sklearn的train_test_split之前先按设备id分组再在组内按类别分层抽一部分做验证集。虽然数据集只有几百条但每折结果波动依然不小所以还要配合交叉验证看整体分布。2.4 数据增强要不要做小样本场景下我会做一种非常保守的增强对同一来源样本的气体浓度乘以0.95到1.05之间的随机因子模拟采样和检测误差。这个操作等于告诉模型气体浓度小幅波动时故障类别不应该改变天然带有正则作用。不过增强要克制不要成倍复制导致网络把原样本的分布淹没。如果发现模型训练误差居高不下先检查是不是增强过度引入了噪声而不是急着加大网络。3. 标准Elman网络的记忆机制与结构设计3.1 承接层到底记住了什么标准Elman神经网络是在BP基础上增加一个承接层也叫上下文层。承接层的输入是隐藏层上一时刻的输出它的输出又拼接到隐藏层当前时刻的输入里。前向计算可以写成h(t) tanh( U * x(t) W * c(t) b_h ) c(t) h(t-1) y(t) softmax( V * h(t) b_o )从公式能看出来c(t)是一个状态变量保存了前一步隐藏层激活结果。输入x(t)进入网络时不是只按当前数值计算而是被上一时刻的状态调制过。这种机制让网络具备了最简单的时序记忆能力。落到DGA场景如果按时间顺序输入同台变压器的多次监测数据隐藏节点在每一步都会承接上一次采样留下的编码相当于把浓度从正常到轻微异常再到明显异常的变化过程压缩进状态向量。最后的输出层不只看当前浓度还带有演化趋势信息这对故障预测特别有用。3.2 输入、隐藏、输出层节点数怎么定输入层节点数由特征数决定用七种气体就是7加入CO和CO2就是9。输出层节点数等于故障类别数四分类是4七分类是7。需要重点定的是隐藏层节点数这是Elman里对效果影响最大的超参数。经验上可以先取m sqrt(n l) a其中n是输入节点数l是输出节点数a取1到10之间的整数。比如7输入7输出的场景sqrt(14)约等于4加a以后大致落在5到14。我一般直接拿隐藏节点在5到15之间做一轮小网格搜索每个配置用交叉验证评估。节点数太少网络没有足够容量学习非线性边界节点数太多小样本上会对着噪声死记硬背训练集能到100%测试集迅速掉下来。我实际跑下来隐藏节点取10到12之间表现最稳再往上加收益很小。3.3 激活函数、损失函数与训练算法怎么配标准Elman通常有两个激活函数隐藏层用双曲正切tanh把状态压缩在-1到1之间输出层做分类时用softmax给出各类别概率。隐藏层不要用ReLU原因有两个ReLU输出没有上界承接层状态会不断累积放大容易让下一时刻输入变得不稳定另外tanh的梯度在小样本场景下更温和早期训练不容易直接发散。损失函数用交叉熵这是多分类的标准选择它和softmax天然搭配。优化器我分别试过带动量的SGD和Adam。从彻底贴合标准Elman原始算法的角度看带动量SGD更对口实际训练中Adam则往往更省心尤其在调参初期可以避免损失到处乱跳。小样本场景建议先选Adam练两三百轮看趋势再换SGD调优到稳定收敛。模块推荐选择原因隐藏层激活tanh状态有界承接层稳定输出层激活softmax输出类概率配合交叉熵损失函数CrossEntropyLoss多分类标准选择优化器SGD动量 / Adam前者接近标准Elman训练后者更稳权重初始化均匀分布[-0.5, 0.5]避免初始状态过大3.4 状态初始化和时间步组织每次前向计算开始承接层状态c(0)都初始化为全零向量。如果坚持在单样本模式下做分类每条样本都应当重置状态不能让前一条样本的隐状态串到后一条样本的预测里。很多初学者在PyTorch里复现Elman时踩到的坑就是这个把整个batch当成一条长序列结果模型输出莫名其妙乱掉。如果要做趋势预测则把同一台设备的连续采样数据组织成序列比如最近的5次DGA记录作为一组输入取序列末端输出作为当前故障状态预测。这种用法才是Elman相对BP的真正优势所在。4. 从零实现一套可复用的Elman诊断模型4.1 PyTorch实现标准Elman网络我在项目里用PyTorch手写了一个非常朴素的标准Elman完整类如下import torch import torch.nn as nn class StandardElman(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super().__init__() self.hidden_dim hidden_dim self.U nn.Linear(input_dim, hidden_dim) self.W nn.Linear(hidden_dim, hidden_dim) self.V nn.Linear(hidden_dim, output_dim) def forward(self, x_seq, contextNone): if x_seq.dim() 2: x_seq x_seq.unsqueeze(1) # [batch, 1, input_dim] batch, seq_len, _ x_seq.shape if context is None: context torch.zeros(batch, self.hidden_dim, devicex_seq.device) for t in range(seq_len): context torch.tanh( self.U(x_seq[:, t, :]) self.W(context) ) output self.V(context) return output, context这段代码把标准Elman的核心逻辑压缩得很短U是输入到隐藏层的权重W是承接层状态到隐藏层的权重V是隐藏层到输出层的权重。每个时间步都用上一个context和当前输入共同更新隐藏状态最后把状态向量映射成类别得分。需要说明的是seq_len1时就退化成一条样本一次预测这时它和BP的差别就在于隐藏层还带着W(context)这样的反馈项。如果数据组织成多步序列循环就会自动展开多次最后输出的就是序列末端的故障预测。4.2 训练循环和管理细节训练时我建议每条样本重置上下文避免样本间状态串扰。一个可运行的训练片段如下model StandardElman(input_dim7, hidden_dim12, output_dimnum_classes) optimizer torch.optim.Adam(model.parameters(), lr0.01, weight_decay1e-4) criterion nn.CrossEntropyLoss() X_train_t torch.tensor(X_train, dtypetorch.float32) y_train_t torch.tensor(y_train, dtypetorch.long) for epoch in range(1000): model.train() total_loss 0.0 for x_i, y_i in zip(X_train_t, y_train_t): context None output, context model(x_i, context) loss criterion(output.unsqueeze(0), y_i.unsqueeze(0)) optimizer.zero_grad() loss.backward() optimizer.step() total_loss loss.item() if epoch % 200 0: print(fepoch {epoch}, avg_loss {total_loss / len(X_train_t):.4f})这里的要点是x_i维度是[7]进入forward后会自动unsqueeze成[1, 7]也就是seq_len1。context传的是Noneforward内部初始化成全零状态。每个样本独享一个全零起始状态梯度不会跨样本混淆。训练轮数不要死盯1000。更稳的做法是拿一小份验证集做早停每训练50轮评估一次验证集准确率连续若干次不上升就停止并保留验证集表现最好的那组权重。小数据集上多训练几轮不会带来质的提升反而容易过拟合。4.3 评估指标选择与结果解读训练结束后在按设备分组划分的测试集上统计混淆矩阵和分类报告。from sklearn.metrics import classification_report, confusion_matrix model.eval() preds [] with torch.no_grad(): for x_i in X_test_t: x_i x_i.unsqueeze(0) output, _ model(x_i, None) preds.append(torch.argmax(output, dim1).item()) print(confusion_matrix(y_test, preds)) print(classification_report(y_test, preds, digits3))看结果不能只看总准确率要看每一类的召回率。DGA诊断里最容易混的是温度和放电类型低温过热和中温过热经常互分低能放电和高能放电的乙炔比例差异也没想象中那么分明。如果混淆矩阵显示低温过热经常被分成中温过热那可能不是模型不行而是样本标签本身在边界处就不清晰可以考虑合并这两类。我这边用七特征、五分类模型在留出测试集上大概做到85%左右的准确率七分类细分时降到75%上下但也在工程可接受范围。关键不是追求测试集数字有多高而是确认每个类别都有足够的召回率尤其正常类不能被误判成故障否则运维人员会被无效告警淹没。5. 实际项目中最容易踩的坑与处置办法5.1 故障样本太少类别不平衡怎么办DGA历史数据里正常样本往往占一半以上局部放电和低能放电样本寥寥无几。如果直接训练模型会倾向于把所有样本都猜成多数类准确率看起来不低但少数类故障几乎全漏。处置思路有三层。第一层是在损失函数里给少数类更高的权重用交叉熵的class_weight参数就能实现少数类别分配3到5倍权重。第二层是类别合并把样本极少的子类合并成上一级类别宁做不多。第三层是评估时同时看macro recall别看整体准确率因为准确率会被多数类冲高。我在这批数据上做七分类时低能放电的召回率只有四成合并成放电类之后召回率能到八成以上。5.2 训练集高、测试集低过拟合与泄漏这个现象在小样本里最常见。出现之后先查数据划分有没有按设备分组如果发现同设备数据混在训练和测试两侧先修划分逻辑。其次看隐藏节点数超过20个时在小数据集上基本就是在背答案把隐藏节点降到8到12之间。再配合验证集早停和L2正则测试集表现会明显变稳。我在第一次跑七分类模型时训练准确率接近100%、测试准确率只有60%排查到最后就是隐藏节点设了24个同时还有两处数据泄漏修完才恢复到正常水平。5.3 Elman特有的状态串扰问题前面提过PyTorch里很容易把batch样本当成一条连续序列来跑context在样本之间没有重置。症状表现为损失曲线抖动、测试集准确率波动剧烈甚至同一个模型跑两遍结果截然不同。排查方法是在forward入口打印context看每个batch前状态是否为零。记住单样本分类场景每条样本前必须把context设为None只有真正按时间序列组织数据时才允许context跨时间步传递。这个坑我印象很深因为模型跑出来的结果看起来并不是完全不可用准确率忽高忽低很容易让人误以为是学习率或权重初始化的问题。后来在单样本循环里加了context None所有抖动都消失了。5.4 小样本稳定性的最后手段交叉验证如果最终数据集只有一百多条标注样本单次划分的测试结果受随机性影响很大。我在最终交付前会用5折交叉验证跑完整流程每一折单独记录混淆矩阵然后汇总所有折叠的结果。这样得到的准确率和召回率比单次划分靠谱得多。交叉验证的另一个好处是可以在同一份数据上比较多个候选模型选模型时不容易被某一次随机划分误导。具体操作上每一折都用同一个数据预处理流程重新计算归一化参数不要把全量统计量带到每一折里。最后说一点个人体会。把标准Elman用在DGA数据上最花时间的地方并不是网络代码而是数据清洗、分组划分和故障类别定义。只要这三件事做扎实一个隐藏节点只有12个的Elman网络就足以完成大部分分类任务。如果你现在正面临小样本设备诊断问题我建议别急着堆LSTM和注意力机制先用标准Elman跑通基线和评估闭环再根据实际精度瓶颈决定要不要升级模型。这个思路在我后续做几个类似的工业小样本诊断项目时都让我少走了不少弯路。

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

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

免费获取报价 →
↑