简介这份变压器溶解气体数据集面向电力设备运维人员、故障诊断研究者及机器学习工程师用于支撑变压器故障识别与智能监控模型的开发验证。数据覆盖中低温过热、高温过热、低能放电、高能放电、局部放电与正常状态六类典型工况并围绕氢气、甲烷、乙烷、乙烯、乙炔等特征气体的浓度变化展开便于读者结合比值法与判别函数法开展特征分析与算法对比。资源以rar压缩包形式提供整体约6.97MB上游未返回文件总数与类型明细故不赘述具体构成。目前已有177人学习下载适合作为故障诊断建模、数据分析和算法验证的实测样本。读者可据此构建分类模型、复现气体比值判据、验证特征工程效果并对照不同故障类型的气体生成规律加深对变压器运行状态与潜在风险的理解为电力系统可靠性研究提供数据支撑。1. 变压器溶解气体数据.rar一份油色谱数据到手后先别急着训练模型拿到一个名为「变压器溶解气体数据.rar」的压缩包很多人的第一反应是解压、读表、丢进模型跑一遍准确率。我见过太多这样的流程最后卡在同一个地方数据里混着不同电压等级、不同取样周期、不同故障类型的记录标签还可能是「正常/注意/异常」这种粗粒度分级模型学到的其实是取样批次的分布而不是溶解气体和故障之间的物理关系。变压器油中溶解气体分析DGA本身是一套成熟的状态评估手段核心逻辑是绝缘油在过热或放电条件下裂解产生特征气体不同故障类型对应不同的气体组合与产气速率。这份数据要解决的就是把「气体浓度 → 故障类型/严重程度」这条映射做成可复现的建模流程。它适合两类人一类是做电力设备状态监测、想用真实油色谱数据验证特征工程和分类模型的人另一类是想把 DGA 从「看三比值表」升级到「批量筛查趋势预警」的运维工程师。前提是你得先接受一件事——这份数据不是拿来直接喂给神经网络的清洗和特征构造占掉七成工作量。2. 解压之后先做数据体检字段、量纲与标签分布2.1 先确认压缩包里到底是什么结构.rar本身只是容器里面常见的是 CSV、Excel 或者多个按年份/站点拆分的子表。不要假设字段名统一我一般先做一次目录扫描和编码探测避免后面读表时中文列名乱码。# 查看压缩包内文件清单不解压 unrar l 变压器溶解气体数据.rar # 解压到独立目录避免污染原始包 mkdir -p dga_raw unrar x 变压器溶解气体数据.rar dga_raw/ # 查看文件类型与编码Linux/macOS file dga_raw/*逻辑说明unrar l只列清单确认里面是单表还是多表unrar x保留目录结构解压。参数上如果压缩包有密码-p后接密码但多数公开数据集不带密码。解压后先别批量读用file看编码中文列名常见 GBK 和 UTF-8 混用这一步能省掉后面反复调encoding的时间。2.2 用 pandas 做一次字段体检DGA 数据的典型字段包括氢气 H2、甲烷 CH4、乙烷 C2H6、乙烯 C2H4、乙炔 C2H2、一氧化碳 CO、二氧化碳 CO2、总烃以及取样日期、设备编号、电压等级、故障标签。单位常见 μL/L即 ppm。先做缺失率、量纲范围和标签分布三件事。import pandas as pd import numpy as np df pd.read_csv(dga_raw/dga.csv, encodinggbk) # 1) 字段与缺失率 print(df.isna().mean().sort_values(ascendingFalse).head(10)) # 2) 量纲体检气体浓度不应为负总烃应约等于各烃类之和 gas_cols [H2, CH4, C2H6, C2H4, C2H2, CO, CO2] print(df[gas_cols].describe().T[[min, max, mean]]) # 3) 标签分布 if fault_type in df.columns: print(df[fault_type].value_counts(dropnaFalse))逻辑说明缺失率排序能快速定位是「整列缺失」还是「零星缺失」describe看最小值是否为负、最大值是否离谱比如 CO2 出现 10 万级可能是单位混用标签分布决定后面要不要做重采样。参数上encoding按上一步探测结果改GBK 读不了就换utf-8-sig。如果总烃和各烃类之和对不上说明有重复计数或单位不统一必须先修。2.3 标签粒度决定建模路线很多 DGA 数据的标签是「正常 / 注意 / 异常」三级也有的是具体故障类型过热、局部放电、电弧放电。三级标签适合做筛查模型具体故障类型适合做诊断模型。如果标签里混着两种粒度不要硬合并先按粒度拆成两个子任务。常见做法是先用三比值或大卫三角做一次规则基线再用机器学习模型对比提升幅度这样你能说清楚模型到底带来了多少增量。3. 特征工程从原始气体浓度到可解释的 DGA 特征3.1 三比值法的编码逻辑与实现三比值法是 DGA 里最经典的规则特征用 C2H2/C2H4、CH4/H2、C2H4/C2H6 三个比值编码成整数组合再查表对应故障类型。它的价值不在于多准而在于可解释、可复现适合作为基线特征。def ratio_code(row): # 三比值编码边界按常见工程阈值处理 r1 row[C2H2] / row[C2H4] if row[C2H4] 0 else np.nan r2 row[CH4] / row[H2] if row[H2] 0 else np.nan r3 row[C2H4] / row[C2H6] if row[C2H6] 0 else np.nan def code(v, t1, t2): if pd.isna(v): return -1 if v t1: return 0 elif v t2: return 1 return 2 return pd.Series({ code_r1: code(r1, 0.1, 3.0), code_r2: code(r2, 0.1, 1.0), code_r3: code(r3, 1.0, 3.0), }) df df.join(df.apply(ratio_code, axis1))逻辑说明三个比值分别对应不同故障的产气特征编码后组合成 0-2 的整数。参数上阈值t1/t2是工程经验值不同标准略有差异建议先按常见阈值跑通再在验证集上微调。注意分母为 0 的情况直接给-1表示无效不要用 0 填充否则会引入错误编码。3.2 产气速率与趋势特征单次取样只能看「当前状态」加上时间维度才能看「发展趋势」。如果数据里有设备编号和取样日期一定要构造产气速率特征相邻两次取样的浓度差除以时间间隔。df[sample_date] pd.to_datetime(df[sample_date]) df df.sort_values([device_id, sample_date]) for col in gas_cols: df[f{col}_rate] ( df.groupby(device_id)[col] .diff() / df.groupby(device_id)[sample_date].diff().dt.days )逻辑说明diff()算相邻差值除以天数得到每日产气速率。参数上如果同一设备同一天有多条记录先去重或取均值否则速率会失真。产气速率对局部放电和电弧放电的区分度往往比绝对浓度更高这是很多人忽略的一点。3.3 特征归一化与共线性处理气体浓度跨度大CO2 可能到几千C2H2 可能只有个位数直接进模型会被大尺度特征主导。常见做法是对数变换后再标准化同时检查总烃和各烃类的共线性。from sklearn.preprocessing import StandardScaler feat_cols gas_cols [code_r1, code_r2, code_r3] df[feat_cols] df[feat_cols].apply(lambda x: np.log1p(x.clip(lower0))) scaler StandardScaler() df[[c _z for c in feat_cols]] scaler.fit_transform(df[feat_cols])逻辑说明log1p压缩长尾clip(lower0)防止负值导致对数报错。标准化用fit_transform只在训练集上拟合验证集和测试集要用训练集的均值方差否则会数据泄漏。这一步是很多「离线准确率很高、上线就崩」的根源。4. 建模与验证别让随机划分骗了你4.1 按设备划分而不是按样本随机划分DGA 数据里同一台设备有多条记录如果随机划分同一设备的不同时间点会同时出现在训练集和测试集模型相当于「见过这台设备」准确率虚高。正确做法是按设备编号分组划分。from sklearn.model_selection import GroupShuffleSplit gss GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, test_idx next(gss.split(df, groupsdf[device_id])) train_df df.iloc[train_idx] test_df df.iloc[test_idx]逻辑说明groups传设备编号保证同一设备只出现在一侧。参数上test_size按数据量定设备数少于 50 时建议用交叉验证而不是单次划分。这一步做完准确率通常会掉几个点但那个数字才是可信的。4.2 基线模型与对比先用逻辑回归或决策树做基线再用随机森林或梯度提升对比。不要一上来就上深度学习DGA 数据量通常不大树模型更稳。from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report X_train train_df[[c _z for c in feat_cols]] y_train train_df[fault_type] X_test test_df[[c _z for c in feat_cols]] y_test test_df[fault_type] lr LogisticRegression(max_iter1000, class_weightbalanced) lr.fit(X_train, y_train) print(LR:\n, classification_report(y_test, lr.predict(X_test))) rf RandomForestClassifier(n_estimators300, class_weightbalanced, random_state42) rf.fit(X_train, y_train) print(RF:\n, classification_report(y_test, rf.predict(X_test)))逻辑说明class_weightbalanced处理类别不均衡DGA 数据里正常样本远多于故障样本。参数上n_estimators300 起步再大边际收益低max_depth不设时树会深建议用交叉验证调。看报告时重点看故障类的召回率漏报比误报代价高。4.3 用 SHAP 看模型到底学了什么树模型可解释性可以用 SHAP 值看特征贡献确认模型没有依赖设备编号或取样日期这类泄漏特征。import shap explainer shap.TreeExplainer(rf) shap_values explainer.shap_values(X_test) shap.summary_plot(shap_values, X_test, plot_typebar)逻辑说明TreeExplainer对树模型效率高summary_plot按特征重要性排序。如果排在前面的不是气体浓度或比值特征而是某个编码或日期衍生特征就要回头查数据泄漏。这一步是上线前的最后一道保险。5. 避坑与排查DGA 数据建模最常见的五个翻车点5.1 单位混用导致浓度量级错乱现象同一列气体浓度部分记录是 μL/L部分是 mg/L 或百分比describe里最大值和最小值差几个数量级。原因不同来源的数据表直接拼接没有做单位归一。解决先按设备或来源分组统计量纲确认单位后统一换算到 μL/L换算系数查标准不要凭感觉乘。5.2 标签泄漏用未来数据预测过去现象离线准确率 0.98上线后一塌糊涂。原因特征里混入了取样日期之后的记录或者用了全量数据做标准化。解决按时间切分训练/测试标准化只在训练集拟合产气速率特征确认只用了历史记录。5.3 三比值编码的边界陷阱现象模型对某些故障类型完全无召回。原因三比值阈值设得太死边界附近的样本被编码到错误区间。解决把编码从硬阈值改成模糊隶属度或者直接把原始比值作为连续特征输入模型让模型自己学边界。5.4 缺失值填充引入偏差现象填充后模型在缺失率高的设备上表现差。原因用全局均值填充忽略了设备差异。解决按设备分组填充或者把「是否缺失」作为一个二值特征加进去让模型知道这条记录的信息完整度。5.5 类别不均衡下的准确率幻觉现象准确率 0.95但故障类召回率不到 0.3。原因正常样本占绝大多数模型全预测正常也能拿高准确率。解决看混淆矩阵和每类召回率用class_weight或重采样评估指标换成宏平均 F1 或故障类召回率。6. 把模型变成可复现的筛查流程一个最小落地技巧前面几章把数据体检、特征工程、建模验证和避坑都过了一遍最后一章落到一个具体技巧怎么把整个流程封装成一条命令能跑通的筛查脚本方便后续换数据、换阈值、换模型时快速复现。我一般会写一个run_dga.py把配置抽成字典数据路径、特征列表、模型类型、评估指标都从配置读这样下次拿到新的.rar只需要改配置不用动代码。# run_dga.py import yaml import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import GroupShuffleSplit from sklearn.metrics import f1_score def load_config(pathconfig.yaml): with open(path, r, encodingutf-8) as f: return yaml.safe_load(f) def main(): cfg load_config() df pd.read_csv(cfg[data_path], encodingcfg[encoding]) # 特征与标签 feat_cols cfg[feature_cols] label_col cfg[label_col] group_col cfg[group_col] # 按设备分组划分 gss GroupShuffleSplit(n_splits1, test_sizecfg[test_size], random_state42) train_idx, test_idx next(gss.split(df, groupsdf[group_col])) train_df, test_df df.iloc[train_idx], df.iloc[test_idx] model RandomForestClassifier( n_estimatorscfg[n_estimators], class_weightbalanced, random_state42, ) model.fit(train_df[feat_cols], train_df[label_col]) pred model.predict(test_df[feat_cols]) score f1_score(test_df[label_col], pred, averagemacro) print(fmacro F1: {score:.4f}) if __name__ __main__: main()配套的config.yaml长这样data_path: dga_raw/dga.csv encoding: gbk feature_cols: - H2_z - CH4_z - C2H6_z - C2H4_z - C2H2_z - code_r1 - code_r2 - code_r3 label_col: fault_type group_col: device_id test_size: 0.2 n_estimators: 300逻辑说明配置和代码分离换数据只改 YAMLGroupShuffleSplit保证设备不跨集f1_score用宏平均避免类别不均衡下的准确率幻觉。参数上n_estimators和test_size是最常调的两个前者影响训练时间后者影响评估稳定性。这个脚本不追求一步到位它的价值在于把「数据体检 → 特征 → 划分 → 模型 → 指标」这条链路固定下来后面每次迭代只改一个环节能清楚知道是数据变了还是模型变了。我自己的习惯是拿到任何一份 DGA 数据先跑一遍这个脚本拿到基线 macro F1再决定要不要加特征、换模型。如果基线已经够用就不折腾如果不够至少知道差距在哪。血泪经验是很多翻车不是因为模型不够强而是因为划分方式错了、单位没统一、或者标签本身就有问题。把这三件事先做对比换十个模型都管用。希望帮到你。本文还有配套的精品资源点击获取