干变压器故障诊断这行的,手头最金贵的东西往往不是什么高大上的检测仪器,而是那厚厚一沓油色谱试验记录。油里溶解的气体就是变压器内部状态的“体检报告”,H2、CH4、C2H6、C2H4、C2H2这五种特征气体,搭配对应的故障类型标签,就能从数据里挖出“绝缘有没有过热”“是不是在局部放电”这些硬核结论。这次拿到的是一个非常经典的变压器故障诊断数据集:356组样本、7类标签(含正常),正好覆盖了从正常状态到各种典型潜伏性故障的全谱系。对于搞电力设备状态检修的技术人员、在做油中溶解气体分析的工程师,以及刚接触电力领域小样本分类任务的算法同学,这套数据都值得仔细盘一盘。
我之前接触过不少类似的数据集,说实话,这个量级的样本数在电力故障诊断领域非常典型——真实工况下故障样本本来就难收集,能凑齐356组已经相当不错。但小样本带来的挑战也很现实:七分类任务下,每个类别平均只有五十来组数据,如果某些故障类型样本分布不均匀,模型很容易“偏科”。所以这篇内容我就围绕这个数据集的完整技术链路来写,从气体组分和故障机理的对应关系,到数据预处理、特征构造,再到模型选型评估和避坑经验,一条龙讲清楚。
1. 先把这个数据集看透:气体组分背后是故障的“指纹”
1.1 五种气体到底在说什么
变压器内部故障的核心诱因是电和热。绝缘油的主要成分是碳氢化合物,在电场应力或热应力作用下,碳氢键会断裂,产生氢气和不饱和烃类气体。这五种气体不是平起平坐的,每种气体都指向特定的故障性质,浓度高低和比例关系则是关键的判断依据。
- H2(氢气):分子量最小,键能也相对较弱,最容易在低能量密度状态下产生。局部放电、电晕放电哪怕能量很低,也会先析出大量氢气,所以它是放电性故障的“早期信号”。
- CH4(甲烷):热分解的初级产物,在温度不太高的过热状态下占主导。变压器油温在300℃上下时,甲烷比例会明显上升。
- C2H6(乙烷):也是低温热解的产物,但相比甲烷,它在温度进一步升高时的增长速率反而放缓。它在诊断里更多是充当“配比参照物”。
- C2H4(乙烯):高温过热的关键标志。油温超过500℃后,乙烯含量会加速飙升,温度越高,乙烯在烃类气体中的占比越大。中低温过热和高温过热的区分,很多时候就看乙烯与乙烷的比例关系。
- C2H2(乙炔):这个气体在诊断中的权重极高,因为它需要非常高的能量密度才能大量生成。电弧放电、火花放电等高能放电故障下,乙炔才会显著出现。如果乙炔浓度异常,基本可以直接锁定放电类故障。
这五种气体对应的就是一张“故障指纹表”。比如局部放电时氢烃比很高、乙炔几乎没有;而高温过热时乙烯和甲烷比例大、乙炔很低。模型学习的本质就是拟合这种气体组分空间和故障类型之间的非线性映射。
1.2 七种故障类型的标签体系
这个数据集包含7类标签(含正常),在公开的和工程化的数据集中,通常对应的是:正常、局部放电、低能放电(火花放电)、高能放电(电弧放电)、中低温过热、高温过热,以及放电兼过热组合故障。具体标签含义要看数据集字典,但整体分类逻辑和大类IEC 60599的故障分类思路一致。
有一点值得注意:不同来源的数据集对“过热”的温度区间划分不完全一致,有的把300℃以下叫低温过热,300~700℃叫中温过热,700℃以上叫高温过热;有的干脆就两档,低温过热带350℃附近,高温过热带900℃附近。所以建模前第一步不是急着跑代码,而是先把标签分布和类别含义列清楚,否则后面误判分析时根本分不清是模型错了还是标签本身定义不同。
1.3 数据量和特征维度带来的客观约束
五维特征输入、七分类输出,356组样本。这个规模放在深度学习里连“小试牛刀”都谈不上,但在传统机器学习和统计学习框架下,反而是很健康的复杂度。原因在于:
- 五维特征下不需要太深的结构就能拟合决策边界;
- 356组样本足以支撑交叉验证,但要留出至少20%比例的测试集时,训练数据只有280组上下,对模型容错要求不低;
- 七分类的类别数不算多,但如果有类别不平衡,少数类的有效样本可能只有二三十组,这就会催生一系列工程处理手段。
所以,别再纠结“为什么不用深度学习”,这套数据最适合的玩法是经典机器学习加上扎实的特征工程,把每一个样本的气体比值关系榨干净。
2. 数据层面深挖:小样本分类的“地基工程”
2.1 特征空间的量纲和分布问题
五种气体的浓度单位通常是µL/L(ppm),但实际数值范围跨度极大。有的正常样本氢气只有个位数,有的高能放电样本乙炔可能直接到几百。这个量级差异会在模型训练时带来两个麻烦:一个是距离类算法(比如SVM)会把数值大的特征当成主导因素,另一个是树模型虽然不敏感,但如果特征本身存在偏移,分裂点选择也会受到影响。
所以我拿到数据的第一件事是先看描述性统计,确认每个特征的min、max、均值以及是否有异常值。气体浓度数据里偶尔会出现“离谱”的极大值,比如某些接近出厂阈值的高放样本,虽然真实存在,但对模型训练还是会产生干扰。
2.2 标签分布是建模前必须核实的硬指标
七分类标签的分布直接决定后续用不用采样策略、用不用class_weight。之前我碰过一个项目,数据说明写着“故障类型7种”,实际打开一看“正常”类占了近40%,低能放电只有20来条。常规的准确率标准在这种情况下完全失真,因为模型只要全部预测为“正常”就能拿到40%以上的正确率。
所以这里给一个很实在的建议:拿到数据后,第一行代码画个柱状图,或者直接value_counts()看一眼。类别不平衡严重的话,训练集和测试集划分时必须用分层抽样,否则某一次随机划分可能把某一类全部塞进测试集里,结果直接没法看。
2.3 小样本下的评估策略
真正能说明模型实力的不是单次划分出的测试集结果,而是交叉验证或者多次重复实验的均值方差。我个人在类似数据集上的习惯是:用StratifiedKFold做五折交叉验证,看每一折的宏平均召回率和F1;然后在固定随机种子下再划分一个最终hold-out测试集,作为“对外”报告的数字。这样既能避免单次划分的偶然性,也能在交叉验证和独立测试两套口径下交叉印证。
波动性也是判断模型是否稳定过拟合的重要指标。如果同一模型在不同折上宏F1从0.5跳到0.9,基本可以断定目前的特征或者模型容量配不上这个数据量,优先回头精简特征或者用正则化更强的模型。
3. 传统DGA判据到机器学习模型:这是一次“降维打击”吗
3.1 三比值法的天生不足
在数据建模之前,必须知道行业里传统做法是什么。最经典的是IEC三比值法,它把CH4/H2、C2H2/C2H4、C2H4/C2H6三组比值按阈值编码成0/1/2,然后查表得到故障类型。工程上确实好用,因为它不需要任何训练数据,供电人员拿着编码表就能定性。
但把三比值法用在这套数据集上,会暴露几个问题:
- 编码过程中把连续比值离散化,丢掉了大量“半饱和”信息;
- 阈值区间外的大比值直接截尾,比如CH4/H2=10和CH4/H2=100都编码成2,损失严重;
- 部分组合编码没有对应故障结论,查询表时出现“无对应判据”的盲区。
这些问题在本数据集上会直接影响诊断准确率,正好给了机器学习模型发挥空间。模型可以学习连续阈值下的软边界,而不是硬编码的粗粒度区间。所以在文章里我一直强调:三比值法适合做先验理解和特征参考,而机器学习是被验证过的更优赋能路径。
3.2 气体比值特征与原始浓度特征的取舍
关于特征构造,我们要直面一个经典问题:到底直接用五种气体的原始浓度喂给模型,还是额外构造气体比值特征?
我试过两种方案的对比:
- 原始浓度直接入模时,模型更多学到的是“浓度水平”信息,比如某些过热样本整体气体总量偏高。但变压器负荷、油量、运行年限都会影响绝对浓度,同一故障类型在不同设备上浓度可能相差一个数量级。
- 比值特征(如CH4/H2、C2H2/C2H4、C2H4/C2H6)捕捉的是组分之间的“模式”,不受总油气量线性缩放影响,这更接近色谱诊断的核心逻辑。
实战结论:对SVM、逻辑回归这类线性模型,比值特征带来的提升非常明显;对随机森林、XGBoost这类树模型,比值特征的效果有所提升但幅度不算惊人。最稳的方案是保留原始浓度和比值特征的组合版本,让模型自己决定更依赖哪些视图的信息。这里注意,构造比值时如果分母为零,通常加一个极小值或者直接保留原始列,让模型自行学习处理。
3.3 模型选型的适配逻辑
在356组样本的小数据背景下,模型选择一定要信奉“大道至简”。我的经验排序是:
| 模型 | 适配性分析 | 实际效果参考 |
|---|---|---|
| 随机森林 | 对五维特征抗过拟合能力强,自带特征重要性解释 | 稳定可靠,适合当基准模型 |
| SVM(RBF核) | 对非线性边界拟合精准,但需要标准化的配合 | 调好参数后往往是上限最高的 |
| XGBoost/LightGBM | 梯度提升在小样本上反而容易过拟合,需要把树深度压低、学习率调小 | 优于随机森林的收益有限,除非配合可靠正则化 |
| MLP | 五维特征下优势有限,但作为对比实验代表深度学习是必要的 | 容易过拟合,需要强正则,一般不作为首选 |
要表达的核心观点是:不迷信复杂模型。对一个只有356组样本的七分类任务,随机森林或者RBF-SVM配合气体比值特征,往往已经能逼近90%附近的宏平均F1。真正的瓶颈不是模型复杂度,而是特征的构造和标签质量的把控。
4. 实操环节:从零跑通一个可靠的故障诊断模型
4.1 数据加载和初步探查
假设数据是CSV格式,列名分别为H2、CH4、C2H6、C2H4、C2H2、label。第一步先把数据完整读进内存,做基础检查。
import pandas as pd import numpy as np from sklearn.model_selection import StratifiedKFold, train_test_split from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.svm import SVC from sklearn.metrics import classification_report, confusion_matrix, f1_score df = pd.read_csv("dga_dataset.csv") print(df.shape) print(df["label"].value_counts()) print(df.describe())这个阶段重点确认三件事:样本数是否356、五类气体列是否有空值、标签列类型是否为字符串或整数。气体浓度在工程记录中可能出现“0.0”值,这是合法的,但极少数样本可能出现负值或者空字符串,需要先清洗成数值类型。
4.2 构造气体比值特征
根据DGA诊断经验,我习惯构造三个核心比值作为额外特征列:
# 分母极小值处理,避免除零 eps = 1e-6 df["ratio_ch4_h2"] = df["CH4"] / (df["H2"] + eps) df["ratio_c2h2_c2h4"] = df["C2H2"] / (df["C2H4"] + eps) df["ratio_c2h4_c2h6"] = df["C2H4"] / (df["C2H6"] + eps)除这三个外,还可以加H2占总烃的比例、总烃含量(五种烃类气体之和)。但要注意:这里加特征不是越多越好。356组样本下,特征数如果超过20个,反而容易引入噪声和多重共线性。我实测下来的最好组合常常是“5维原始浓度 + 3个核心比值 + 2~3个扩展比值”,总共控制在10~12维以内。
给个提醒:除零处理用eps这种小常数比较省事,但会让某些比值的分布出现“离群大值”,后续做标准化之前建议先对这类特征做一次对数变换或者分位数裁剪,否则一个异常比值就可能主导SVM的边界。
4.3 分层划分与标准化
X = df.drop("label", axis=1).values y = df["label"].values X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42 )分层抽样这一步不是可选项。正因为样本只有356组,不用stratify划分,某些小类别很可能在训练集或测试集中彻底缺失,那评估结果就完全失真。标准化上,树模型可以跳过去,但SVM必须做。要在训练集上fit掉StandardScaler,再用同一个scaler变换测试集:
scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)这属于老生常谈,但确实是很多新人最容易埋雷的环节——一旦把scaler放到全量数据上fit,测试集信息就泄漏进了训练流程,交叉验证分数会虚高,落地时马上现原形。
4.4 模型训练与对比评估
我用随机森林和RBF-SVM各跑一遍,并在测试集上输出宏平均F1和分类报告。
rf = RandomForestClassifier(n_estimators=200, max_depth=8, random_state=42) rf.fit(X_train_scaled, y_train) y_pred_rf = rf.predict(X_test_scaled) svm = SVC(kernel="rbf", C=10, gamma="scale", class_weight="balanced") svm.fit(X_train_scaled, y_train) y_pred_svm = svm.predict(X_test_scaled) print("RF classification report:") print(classification_report(y_test, y_pred_rf, zero_division=0)) print("SVM classification report:") print(classification_report(y_test, y_pred_svm, zero_division=0))等代码跑完,重点看两类指标:一是宏平均F1,比准确率更能刻画七分类在类别不平衡下的整体能力;二是每个故障类别的召回率。放电类故障召回率如果偏低,比如低能放电被大量误判成高能放电,往往提示气体比例特征在两类间区分度不足,这时候可以针对这两类单独做特征对比分析,或者把它们视作“放电大类”做两阶段诊断策略。
4.5 五折交叉验证报告
单次划分的结果只是抽样结果,更严谨的做法是交叉验证。这里给出一个简洁的写法:
cv_scores = [] cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) for train_idx, val_idx in cv.split(X_scaled, y): X_tr, X_val = X_scaled[train_idx], X_scaled[val_idx] y_tr, y_val = y[train_idx], y[val_idx] svm_clf = SVC(kernel="rbf", C=10, gamma="scale", class_weight="balanced") svm_clf.fit(X_tr, y_tr) y_pred_cv = svm_clf.predict(X_val) cv_scores.append(f1_score(y_val, y_pred_cv, average="macro")) print(f"CV macro-F1 mean: {np.mean(cv_scores):.4f} ± {np.std(cv_scores):.4f}")交叉验证分数和测试集分数如果相差在5个百分点以内,说明模型稳定性合格;差太多就要考虑是不是特征里有离群点,或者某一个折的类别分布太极端。之前我跑类似数据集时,某折宏F1突然跳到0.6以下,排查后才发现是某个“高温过热”样本浓度比其他同类高了上百倍,树模型不断被这个点带偏。做一次分位数裁剪就恢复正常。
4.6 特征重要性和误判分析
用随机森林的特征重要性做个简单排序,可以验证哪些气体信息对诊断贡献最大。多数情况下C2H2和C2H4的重要性排名靠前,这和乙炔指向放电、乙烯指向高温过热的机理完全吻合。之后把混淆矩阵列出来,重点观察相邻故障类型的互相误判,这通常能告诉你后续应该往哪个方向补充数据或调整特征。
5. 实际做项目时踩过的一些坑
5.1 数据集标签含义必须先核对
不同来源的“7种故障类型”看起来差别不大,实际语义可能完全不同。有的数据集把“低温过热”和“中温过热”分开,有的合二为一。如果拿别人的标签语义套用到自己的业务场景,模型训练得再好也解释不了现场问题。拿到数据后尽快确认分类边界,不明确时宁可先按粗粒度大类合并,也别硬着头皮细分。
5.2 气体比值的除零处理要比想象中麻烦
原始气体浓度存在大量0值是常态,比如正常状态下乙炔浓度通常就是0.0。构造C2H2/C2H4时,如果不加处理,这个比值特征会变成一堆“0.0”夹杂几个极端大值,分布严重右偏。我试过几种方案:
- 直接加eps:简单但会产生虚假的极小数值;
- 用np.where判断分母为零时置为某个大常数:需要额外处理;
- 不使用比值,而是同时输入原始浓度和比值,让树模型自行处理条件关系。
最终我倾向第三种:核心比值和原始浓度同时入模,树深度控制在10以内,既保留比例信息又避免除零虚构值干扰。
5.3 类别不平衡时别只盯准确率
这个数据集里如果“正常”类占比高而少数故障类样本少,模型完全可能靠“预测全为正常”拿到高的整体正确率。所以用宏平均F1或者加权F1更可靠。我一直坚持在项目报告里同时给出混淆矩阵和按故障类型的召回率,不然很容易被单指标误导。
5.4 随机种子和重复实验是诚信问题
同一个模型在random_state=1和random_state=42下可能跑出完全不同的结论。小样本下随机划分的方差被放得很大。想要确认模型真的有效,建议至少跑5个不同的种子,看宏F1的均值和极差。极差过大时,说明当前特征或模型无法在数据中稳定捕捉可复现的模式,一味调参数只是自欺欺人。
5.5 先做简单模型再上复杂模型
先用逻辑回归或决策树跑通基线,再对比随机森林和SVM。如果简单的线性模型已经能有不错表现,说明气体特征与故障类别本身就存在较强的线性可分关系,这时候再引入复杂模型才有确定的增益空间。不要跳过这一步,它能帮你在后续调参时找准自己的位置。
6. 这套数据后续还能怎么挖
6.1 两阶段诊断策略
小样本下直接七分类容易把“放电”和“过热”大类之间的边界当成纠缠重点。更符合工程实际的思路是:第一阶段分大类,判断是放电、过热还是正常;第二阶段在放电内部细分局部放电、低能放电、高能放电。两阶段模型的好处是每个阶段的类别数降到两三个,分类难度下降,少数类样本也能被更充分地关注。
6.2 把模型输出和传统判据融合
模型输出的概率值可以和IEC三比值法的判据结果做一致性校验。当模型和传统方法结论一致时,诊断置信度可以显著提高;不一致时则提示样本可能处于临界状态或标签本身存在争议。这种做法在现场项目中既接地气,又能解释给运检人员听。
6.3 迁移学习的思路在DGA领域同样有用
如果手头有其他来源的DGA数据(哪怕只有一两百组),可以先用大样本数据预训练一个随机森林或SVM,再用本数据集精调。树模型在这方面的收益不一定大,但对特征空间的初始覆盖有意义。更常见的方式是先用大量无标签样本估计各气体浓度的正常波动范围,再基于此构造异常偏离度特征,这比单纯标准化更贴近设备诊断逻辑。
我在实际做项目中最大的体会是:DGA小样本诊断的重心一定在数据和特征层面。气体种类就这么五种,标签类别也相对固定,与其追求模型结构的复杂,不如把每个样本的原始记录、现场工况、试验条件都吃透,把特征构造做扎实。这种东西没有捷径,就是从一次次的混淆矩阵和误判回看中磨出来的。这个356组的数据集虽然不算大,但把它的价值挖掘到极致,足够支撑一次完整的状态检修诊断研究和实用性验证。