
简介这份PDF文献面向电力系统运维人员、电气工程专业学生及从事机器学习数据建模的技术人员聚焦变压器热性故障与电性故障的自动识别问题。资源为单文件PDF大小约1.85MB内容完整呈现了基于BP神经网络的诊断方案输入层选取油中H2、CH4、C2H4、C2H2、C2H6五种特征气体输出层对应无故障、中低温过热、高温过热、低能放电、高能放电五类状态隐含层节点数按经验公式取13并给出70组故障数据的样本定义、标准化预处理与主元分析降维思路。文中还梳理了权值初始化、误差反向传播、误差平方和判定等训练流程以及MATLAB训练参数设置与20组测试集验证结果诊断准确率达90%。目前已有146人学习适合作为神经网络入门到电力故障诊断落地的参考案例。1. 从油色谱数据到故障标签电力变压器诊断为什么绕不开人工神经网络一台 110kV 主变投运三年后油中溶解气体在线监测装置报出乙炔含量缓慢爬升从 0.2μL/L 涨到 3.5μL/L。运维班组的第一反应是翻 DL/T 722 的三比值表结果落在「低能放电」和「过热」的边界上两种判断对应的检修策略完全不同——一个要停电做局放定位一个只需加强油温监视。这种「卡在表格缝里」的场景正是电力变压器故障诊断最真实的痛点传统阈值法和比值编码法规则硬、边界死遇到多故障并发或早期潜伏性缺陷时误判率居高不下。人工神经网络在这里的价值不是替代规程而是把溶解气体、绕组温度、局部放电、振动等多源特征映射到一个可学习的非线性决策面上。它擅长处理「特征之间互相耦合、标签边界模糊」的问题恰好对上变压器故障诊断的胃口。这篇内容面向两类人一类是电力系统运维或检修工程师想搞明白神经网络模型到底怎么落地到自己的台账数据上另一类是算法工程师接到「故障诊断」需求却对变压器业务不熟。全文按「特征工程 → 网络搭建 → 训练调参 → 部署排错」的路径推进代码可直接跑参数会逐个解释。2. 电力变压器故障诊断的特征工程与标签体系2.1 油中溶解气体分析DGA的输入特征怎么构造变压器故障诊断最主流的输入是油中溶解气体分析数据核心气体是 H₂、CH₄、C₂H₆、C₂H₄、C₂H₂、CO、CO₂ 七种。直接把这七个浓度值丢进网络效果一般因为浓度量纲差异大而且故障类型更多体现在气体之间的比例关系上。常见做法是构造「比值特征 浓度特征」的组合向量。特征类型具体特征物理含义是否归一化浓度特征H₂、CH₄、C₂H₆、C₂H₄、C₂H₂、CO、CO₂各气体绝对含量是对数归一化三比值特征C₂H₂/C₂H₄、CH₄/H₂、C₂H₄/C₂H₆反映故障能量密度与温度是编码或比值总烃特征总烃、总烃产气速率反映整体劣化程度是工况特征油温、负载率、运行年限修正环境干扰是三比值法的编码规则来自 DL/T 722把三个比值按区间编码成 0/1/2 的组合共对应 9 种典型故障。神经网络可以直接吃连续比值也可以吃编码后的离散值前者信息损失小后者更贴近规程、可解释性强。我一般会两套都做用连续比值训练主模型用编码值做交叉验证。2.2 故障标签的类别定义与样本不均衡处理标签体系通常按规程划分为六类正常、低能放电、高能放电、低温过热、中温过热、高温过热。实际台账里「正常」样本占八成以上放电类故障可能只有几十条直接训练会让网络偏向多数类。处理不均衡的常见手段有三种一是对少数类做 SMOTE 过采样在特征空间插值生成合成样本二是给损失函数加类别权重让少数类误判的惩罚更大三是在划分数据集时用分层抽样保证每折里各类别比例一致。下面这段代码演示特征构造和分层划分的完整流程。import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 假设 df 列h2, ch4, c2h6, c2h4, c2h2, co, co2, oil_temp, load_rate, label def build_features(df): eps 1e-6 # 防止除零 feats pd.DataFrame() # 对数归一化浓度特征压缩量纲差异 for gas in [h2, ch4, c2h6, c2h4, c2h2, co, co2]: feats[gas _log] np.log1p(df[gas]) # 三比值特征加 eps 避免分母为零 feats[r1] df[c2h2] / (df[c2h4] eps) # 乙炔/乙烯 feats[r2] df[ch4] / (df[h2] eps) # 甲烷/氢气 feats[r3] df[c2h4] / (df[c2h6] eps) # 乙烯/乙烷 # 总烃 feats[total_hc] df[[ch4, c2h6, c2h4, c2h2]].sum(axis1) # 工况特征 feats[oil_temp] df[oil_temp] feats[load_rate] df[load_rate] return feats X build_features(df).values y df[label].values # 分层划分保证训练集和测试集类别比例一致 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, stratifyy, random_state42 ) scaler StandardScaler() X_train scaler.fit_transform(X_train) # 只在训练集上拟合避免数据泄漏 X_test scaler.transform(X_test)这段代码的关键点有三个。第一np.log1p对浓度做对数变换因为气体浓度跨度可能从 0.1 到上千 μL/L对数化后分布更接近正态网络更容易收敛。第二比值特征加eps是必须的现场数据里 H₂ 或 C₂H₆ 为零的情况很常见不加保护会直接产生 inf 污染整个训练集。第三StandardScaler只能在训练集上fit测试集用transform这是很多人踩过的数据泄漏坑——如果全量数据一起标准化测试集的统计信息就泄漏进了训练过程评估结果会虚高。提示如果台账里某些气体字段大面积缺失不要简单填零。填零会让网络误以为「该气体不存在」而实际可能是「未检测」。建议加一个缺失指示列或者用同类设备的均值填充并记录填充标记。3. 用 PyTorch 搭建变压器故障诊断网络并跑通训练3.1 网络结构选型MLP 还是 1D-CNN变压器故障诊断的输入是结构化特征向量不是原始时序信号所以多层感知机MLP是最直接的选择。但如果你的数据来自在线监测装置每个样本其实是一段时序窗口的统计量这时用一维卷积1D-CNN在时间维度上提取局部模式会更合适。轴承故障诊断里常用的 CNN 思路在这里同样适用区别只是输入从振动波形换成了气体浓度序列。对于大多数以 DGA 单次检测为样本的场景我建议先用 MLP 打底结构不用深两到三个隐藏层足够。特征维度通常只有十几维网络太深反而容易过拟合。隐藏层神经元数量按「输入维度 × 2」起步逐层递减。3.2 完整训练代码与损失函数选择import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset class TransformerFaultNet(nn.Module): def __init__(self, input_dim, num_classes6): super().__init__() self.net nn.Sequential( nn.Linear(input_dim, 64), nn.BatchNorm1d(64), # 加速收敛缓解内部协变量偏移 nn.ReLU(), nn.Dropout(0.3), # 防止过拟合小样本场景必备 nn.Linear(64, 32), nn.BatchNorm1d(32), nn.ReLU(), nn.Dropout(0.3), nn.Linear(32, num_classes) ) def forward(self, x): return self.net(x) # 类别权重正常类权重低故障类权重高缓解不均衡 class_counts np.bincount(y_train) weights torch.tensor(1.0 / class_counts, dtypetorch.float32) weights weights / weights.sum() * len(class_counts) criterion nn.CrossEntropyLoss(weightweights) model TransformerFaultNet(input_dimX_train.shape[1]) optimizer optim.Adam(model.parameters(), lr1e-3, weight_decay1e-4) train_ds TensorDataset(torch.tensor(X_train, dtypetorch.float32), torch.tensor(y_train, dtypetorch.long)) train_loader DataLoader(train_ds, batch_size32, shuffleTrue) for epoch in range(200): model.train() total_loss 0 for xb, yb in train_loader: optimizer.zero_grad() out model(xb) loss criterion(out, yb) loss.backward() optimizer.step() total_loss loss.item() if (epoch 1) % 20 0: print(fEpoch {epoch1}, Loss: {total_loss/len(train_loader):.4f})逻辑说明BatchNorm1d放在Linear之后、激活函数之前是标准做法能让每层输入分布稳定学习率可以设大一点。Dropout(0.3)在小样本下很关键变压器故障样本往往只有几百条不加 dropout 训练集准确率能到 99% 但测试集惨不忍睹。损失函数用带权重的交叉熵权重按类别频率的倒数计算这样少数类故障的梯度不会被多数类淹没。参数说明学习率1e-3是 Adam 的常用起点如果 loss 震荡就降到5e-4weight_decay1e-4是 L2 正则配合 dropout 一起压制过拟合batch_size32在几百条样本下比较稳样本更少时可以降到 16。训练轮数不用死守 200建议加早停——监控验证集 loss连续 20 轮不下降就停。3.3 训练过程中的验证与早停实现best_loss float(inf) patience, wait 20, 0 for epoch in range(300): model.train() for xb, yb in train_loader: optimizer.zero_grad() loss criterion(model(xb), yb) loss.backward() optimizer.step() # 验证阶段 model.eval() with torch.no_grad(): val_out model(torch.tensor(X_test, dtypetorch.float32)) val_loss criterion(val_out, torch.tensor(y_test, dtypetorch.long)).item() if val_loss best_loss: best_loss val_loss wait 0 torch.save(model.state_dict(), best_model.pth) # 只保存最优权重 else: wait 1 if wait patience: print(fEarly stop at epoch {epoch1}) break早停的核心是「保存验证集最优的权重而不是最后一轮的权重」。很多人训练完直接用最终模型评估结果比训练中途的最优模型差好几个点。patience20是经验值数据噪声大可以放宽到 30数据干净可以收紧到 10。4. 故障诊断模型的评估、可解释性与现场排错4.1 不看准确率用混淆矩阵和召回率评估诊断效果变压器故障诊断里准确率是最容易骗人的指标。正常样本占八成模型全预测「正常」也能有 80% 准确率但放电故障一个都抓不到这种模型上线就是事故。真正要看的是少数类的召回率——高能放电、低能放电这些类别的召回率必须单独看。from sklearn.metrics import classification_report, confusion_matrix model.eval() with torch.no_grad(): pred model(torch.tensor(X_test, dtypetorch.float32)).argmax(dim1).numpy() print(confusion_matrix(y_test, pred)) print(classification_report(y_test, pred, digits3))classification_report会输出每个类别的 precision、recall、f1-score。重点关注 recall如果「高能放电」的 recall 低于 0.85说明模型漏报严重需要回头检查这类样本是不是太少或者特征里有没有能区分放电和过热的关键量比如 C₂H₂ 的权重。混淆矩阵则能看出模型把哪两类搞混了比如「低温过热」和「中温过热」经常互相误判这提示可能需要合并这两个类别或者补充温度相关特征。4.2 用 SHAP 解释模型到底学到了什么现场工程师最常问的一句话是「你这模型凭什么说它是放电」。如果答不上来模型就没法被信任。SHAP 是目前解释结构化数据模型最实用的工具它能给出每个特征对单次预测的贡献值。import shap model.eval() # 用训练集背景分布初始化解释器 explainer shap.DeepExplainer(model, torch.tensor(X_train[:100], dtypetorch.float32)) shap_values explainer.shap_values(torch.tensor(X_test[:50], dtypetorch.float32)) # 查看某个高能放电样本的特征贡献 sample_idx 0 for i, feat_name in enumerate(feature_names): print(f{feat_name}: {shap_values[2][sample_idx][i]:.4f}) # 类别2假设为高能放电如果某个高能放电样本里c2h2_log和r1的 SHAP 值特别大说明模型确实是靠乙炔和乙炔/乙烯比做出的判断这和规程里「乙炔是放电特征气体」的结论一致工程师就能放心采信。反过来如果模型靠load_rate这种工况特征做判断那就要警惕了——负载率跟故障类型没有直接因果关系很可能是数据里存在某种采集偏差。4.3 现场部署常见报错与排查清单现象可能原因排查动作推理结果全是同一类输入特征未归一化或归一化参数不匹配检查 scaler 是否和训练时一致某类故障永远不报训练样本该类过少或权重设置错误查 class_counts 和 loss weight线上效果远差于离线训练测试数据同源存在泄漏按时间划分数据集重测比值特征出现 inf分母气体浓度为 0确认 eps 保护是否生效模型输出置信度普遍偏低过拟合或类别边界模糊加 dropout、检查标签质量注意现场部署时归一化用的均值和方差必须固化成配置文件和模型权重一起版本管理。我见过太多案例是模型更新了但 scaler 没更新导致线上输入分布和训练分布对不上诊断结果直接崩掉。5. 小样本下的迁移学习与在线增量更新技巧变压器故障诊断最现实的约束是带标签的故障样本永远不够。一个供电局一年可能就攒下几十条放电故障记录靠这点数据训练深度网络泛化能力很难保证。一个实用的技巧是迁移学习——先在公开的变压器 DGA 数据集或同网省的历史台账上预训练一个特征提取器再用本地少量样本微调最后的分类层。具体做法是冻结前面几层只训练最后两层学习率设小一点比如1e-4训练轮数控制在 50 轮以内。这样既利用了外部数据的通用特征又适配了本地设备的个性分布。微调时建议用较小的 batch size8 或 16因为本地样本少大 batch 会让梯度更新过于粗糙。另一个技巧是在线增量更新。变压器状态是缓慢变化的今天正常的设备半年后可能进入潜伏期。可以设计一个滑动窗口机制把最近三个月的新样本按一定比例混入训练集重新训练同时保留旧样本防止灾难性遗忘。重训练频率不用太高季度一次足够每次重训练后必须用固定的回归测试集验证确保老故障类型的召回率没有下降。验证模型是否真的可用的方法很朴素拿最近一年实际发生并已确认的故障案例做盲测看模型能不能在故障发生前的那次检测中就给出正确预警。这个指标比任何离线准确率都有说服力。如果盲测召回率能稳定在 85% 以上这套基于人工神经网络的电力变压器故障诊断方案就具备上线价值了。本文还有配套的精品资源点击获取