恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
基于改进PSO优化RBF神经网络的变压器故障诊断方法
首页
资讯中心
/
基于改进PSO优化RBF神经网络的变压器故障诊断方法
基于改进PSO优化RBF神经网络的变压器故障诊断方法
发布时间:2026/9/30 3:15:33
简介这份PDF是一篇面向电力系统运维人员、电气工程专业学生及机器学习算法研究者的技术论文由国网上海电力公司从业者撰写聚焦以改进粒子群算法PSO优化径向基函数RBF神经网络解决变压器故障诊断中人工分析耗时、判读准确率不稳的问题为电网安全运行提供算法级支撑。全文围绕变压器油中溶解气体特征结合DGA法展开建模完整阐述了改进PSO原理、RBF网络结构及二者融合的诊断流程并在Matlab平台上通过编程实现智能算法对比以故障识别结果验证改进后模型的诊断准确性与鲁棒性尤其针对RBF网络常见早熟问题给出了优化思路。资源为单个PDF文件大小1.62MB不含附加源码但正文含图表、公式与算法流程细节便于快速把握从数据到诊断的智能建模全貌。已有152人学习下载适合需要掌握PSO-RBF建模路线、复现变压器故障诊断实验或撰写相关方向论文的读者参考。1. 基于改进PSO优化RBF神经网络的变压器故障诊断为什么查表法斗不过边界样本一组油中溶解气体数据摆在仪表上H2 156ppm、CH4 82ppm、C2H2 3.2ppm、C2H4 96ppm、C2H6 11ppm按IEC三比值法查表落在“中温过热”解体后却确认是低能放电伴过热——一次误判意味着一次多余的停电和万元级拆检。基于改进PSO优化RBF神经网络的变压器故障诊断就是把三比值查表换成一台能逼近任意边界的分类器用粒子群优化PSO把RBF神经网络的径向基中心、宽度和输出权值一起搜出来再用油色谱样本把故障类别拟合进去。适合电力设备状态检修工程师和做算法基线复现的研究生。下面按建模、优化、落地、避坑、验证的顺序展开代码用Python与NumPy不依赖深度学习框架也能复现。2. 从IEC三比值到RBF把变压器故障诊断拆成特征与类别的分类问题2.1 先想清楚模型输入什么DGA特征量选择与三比值法的边界变压器故障诊断的主流信号源是油中溶解气体分析DGA。变压器内部过热或放电会让绝缘油裂解产生氢气、甲烷、乙烷、乙烯、乙炔等特征气体。常见做法是取H2、CH4、C2H6、C2H4、C2H2六维浓度作为输入特征有的方案把CO也加进去变成七维。输出侧则是故障类别局部放电、低温过热、中温过热、高温过热、低能放电、高能放电再加上正常状态一共七类。传统IEC三比值法先算C2H2/C2H4、CH4/H2、C2H4/C2H6三对比值再映射到0/1/2编码查表。它的硬伤在于比值边界是截断的1.99和2.01可能落入完全不同的故障类而且多故障叠加时查表直接无解。换到RBF的视角这六个气体特征可以直接作为输入输出层做类别概率映射边界是一层连续的非线性曲面不需要人为硬编码。DGA样本与故障类别的对应关系在设计标签时通常按下面的方式编码。PSO训练时输出层用softmax概率取最大概率的索引作为预测类别。故障类别标签索引正常0局部放电1低温过热300℃2中温过热300~700℃3高温过热700℃4低能放电5高能放电62.2 RBF为什么适合这张表前馈神经网络里的“局部响应”机制RBF神经网络是三层前馈神经网络输入层不做变换隐含层用径向基函数计算样本与中心的距离输出层做线性加权。隐含层的高斯径向基函数是这样定义的phi_j(x) exp(-||x - c_j||^2 / (2 * sigma_j^2))这里的c_j是第j个径向基中心sigma_j是宽度。直观理解样本离中心越近这个隐含神经元输出越接近1离得越远输出指数衰减到0。所以每个中心相当于“这个故障模式在气体特征空间里长什么样”宽度则对应“这个模式的响应半径”。RBF在DGA这种中小规模表格数据上比BP类网络稳得多。BP神经网络结构图里一旦层数加深梯度消失和爆炸问题就跟着来学习率调不对还会直接nanRBF把非线性压在隐含层一层里输出层是纯线性加权PSO可以在不计算梯度的前提下直接寻优。不同神经网络的适用场景差异很明显卷积神经网络擅长图像LSTM这类循环神经网络擅长时序而RBF这种结构在几十到几百条样本的表格分类上反而是最不容易翻车的那一档。2.3 先搭一个RBF前向骨架最小的可运行分类器下面这段代码把RBF的前向计算完整做出来后续PSO的适应度函数会反复调用它。先跑通这个再谈优化。import numpy as np def rbf_forward(X, centers, widths, weights): # X: (n_samples, n_features) 输入样本 # centers: (n_hidden, n_features) 径向基中心 # widths: (n_hidden,) 高斯宽度 # weights: (n_classes, n_hidden) 输出层权值 n_samples X.shape[0] n_hidden centers.shape[0] phi np.zeros((n_samples, n_hidden)) for j in range(n_hidden): # 欧氏距离平方除以宽度平方决定该中心对样本的响应强度 dist_sq np.sum((X - centers[j]) ** 2, axis1) phi[:, j] np.exp(-dist_sq / (2 * widths[j] ** 2)) # 输出层线性加权后做 softmax转成故障类别概率 logits phi weights.T exp_logits np.exp(logits - np.max(logits, axis1, keepdimsTrue)) prob exp_logits / np.sum(exp_logits, axis1, keepdimsTrue) return prob, phi这段代码里centers的形状是(n_hidden, n_features)每行是一个隐含中心的坐标widths是每个中心的宽度weights是输出层权值行数等于故障类别数。返回值里prob是标准化后的类别概率phi是隐含层输出矩阵。phi在后面PSO调试时可以直接拿出来当特征用观察每个样本被哪些中心激活。这个骨架只做前向推断不包含任何训练逻辑。宽度参数如果设得太大所有样本响应都接近分类边界糊成一片设得太小每个中心只“看见”自己周围极近的点泛化能力基本为零。宽度怎么控制是后面PSO改进的重点之一。2.4 三种输入方案的取舍别一上来就堆特征我做过对比的三种输入方案分别是直接用六维气体浓度、用三比值再加总烃、六维浓度加三比值一起上。直接六维浓度经过min-max归一化后信息保留最完整三比值法并没有比它更稳六维加三比值虽然让单模型精度略涨但维度从6翻到9粒子搜索维度也跟着膨胀训练时长和过拟合风险都上来了。对小样本场景我的习惯是先用六维浓度。如果样本量在50条以下三比值降维反而更能抗过拟合因为比值消除了部分量纲差异。但要注意三比值编码会丢掉气体绝对浓度的信息两种放热程度接近但气体总量差一个数量级的样本比值完全相同。3. 改进PSO优化RBF粒子编码、适应度函数和两个防早熟手段3.1 粒子如何对应RBF参数编码设计与维度预算标准PSO里每个粒子是一组候选解向量对应RBF全部可调参数。最直接的编码方式是把三组参数展平后首尾拼接先放所有隐含中心的坐标再放所有宽度最后放输出层权值。粒子维度按这个公式算dim n_hidden * n_features n_hidden n_hidden * n_classes以六维特征、15个隐含中心、7类输出为例15×6 15 15×7 90 15 105 210维。这个规模对PSO是小场面粒子数30、迭代80次就够这也正是选PSO而不是梯度下降的关键理由之一——RBF的宽度参数对梯度极其敏感一步学习率没调好就冲到负值或爆炸而PSO不需要算梯度搜索过程由边界约束兜底。粒子拆包代码def unpack_particle(particle, n_hidden, n_features, n_classes): center_dim n_hidden * n_features width_dim n_hidden centers particle[:center_dim].reshape(n_hidden, n_features) widths particle[center_dim:center_dim width_dim] weights particle[center_dim width_dim:].reshape(n_classes, n_hidden) return centers, widths, weights这段拆包逻辑在后续每个环节都会复用训练时把粒子变成RBF参数预测时同样调它。注意weights的reshape顺序必须按(n_classes, n_hidden)反过来会让类别错位训练过程还不会报错属于隐藏最深的坑。3.2 标准PSO在RBF场景的两个典型翻车现场标准PSO直接用在RBF上最常见的是两个现象。第一个是早熟收敛。粒子群迭代到中后期所有粒子挤到gbest附近速度向量趋近于零搜索彻底停摆。原因在于惯性权重固定为0.7左右前期探索不充分种群提前锁定了一个局部极值。故障诊断数据类别多、样本少局部极值一抓一大把。第二个是宽度坍塌。适应度函数只惩罚分类错误PSO会把部分宽度压到接近0径向基函数变成一族尖锐的“小尖刺”。训练集上每个样本都被对应的尖刺记住loss非常好看测试集上新的气体样本落不进任何尖刺范围模型输出单类别甚至全零概率。这个坑在RBFPSO组合里出现频率极高大多数复现翻车都栽在宽度没有下界约束上。3.3 改进策略一惯性权重线性递减第一个改进是把固定惯性权重改成随迭代线性递减。前期权重高粒子飞得快、探索范围大后期权重低粒子在gbest附近精细搜索。速度更新公式保持标准形式v w * v c1 * r1 * (pbest - x) c2 * r2 * (gbest - x) x x vw从0.9线性降到0.4c1和c2都取1.5。0.9的起始值保证前期粒子有足够动量跳出局部区域0.4的终值让收敛阶段不至于在最优解周围来回震荡。这个改进不引入额外计算量对早熟收敛的抑制却很明显是性价比最高的一步。3.4 改进策略二混沌初始化与变异算子第二个改进是粒子初始化换成Logistic混沌映射。随机均匀初始化的问题是粒子容易扎堆种群多样性差混沌序列在[0,1]区间内遍历性更好用同一套映射生成初值粒子分布更散。初始化代码把混沌序列映射到参数上下界每个粒子的初始位置都不一样且不聚集。第三个改进是变异算子。每次迭代里以5%的概率对pbest的随机一个维度做高斯扰动扰动幅度取该维度参数范围的10%左右。这样即使整个种群收敛到局部极值变异也可能把某个粒子的历史最优解弹出去重新激活搜索。def pso_update(particles, vels, pbest, pbest_loss, gbest, gbest_loss, w, c1, c2, bounds, pm0.05, mutation_scale0.1): dim particles.shape[1] r1 np.random.rand(dim) r2 np.random.rand(dim) vels w * vels c1 * r1 * (pbest - particles) c2 * r2 * (gbest - particles) particles particles vels # 越界回拉宽度下界在这里生效防止宽度坍塌 lb, ub bounds particles np.clip(particles, lb, ub) # 变异算子对小概率粒子做单维度扰动帮助跳出局部极值 for i in range(particles.shape[0]): if np.random.rand() pm: j np.random.randint(0, dim) span ub[j] - lb[j] pbest[i, j] np.random.randn() * span * mutation_scale pbest[i, j] np.clip(pbest[i, j], lb[j], ub[j]) return particles, vels这段代码里np.clip是关键动作粒子速度更新后可能越过参数范围直接剪回边界。宽度下界的数值会在下一章给出它是整个改进方案里最核心的防翻车参数。变异只用pbest不用当前的x因为pbest是粒子历史最优扰动它更有潜力扰动当前解只会增加无效搜索。4. 改进PSO-RBF完整落地从DGA样本到故障类别输出的闭环4.1 数据准备与预处理的四个步骤DGA样本常见来源是实验室模拟故障数据和现场油色谱台账。预处理按四步走字段清洗、缺失处理、归一化、分层切分。字段清洗时把时间、油温、负载率等无关列去掉只保留H2、CH4、C2H6、C2H4、C2H2、CO六列浓度。缺失值用中位数填充重复行去重这一步能去掉不少台账里的脏数据。归一化用z-score但统计量只从训练集计算测试集的变换直接套用训练集算好的均值和标准差顺序不能反。分层切分按类别比例抽常见比例是训练集70%、测试集30%。变压器故障诊断里正常样本往往占比过半直接随机切分容易把某个故障类全切进测试集分层抽样能避免这种尴尬。特征含义单位H2氢气微升/升CH4甲烷微升/升C2H6乙烷微升/升C2H4乙烯微升/升C2H2乙炔微升/升CO一氧化碳微升/升4.2 适应度函数与PSO主循环完整整合适应度函数取交叉熵加L2正则。交叉熵对“概率没押对”的惩罚是平滑的比直接数分类错误个数信息量大得多。正则项只加在输出层权值上因为RBF参数里最容易被样本数撑爆的就是输出层的自由度。下面的代码把边界构造、混沌初始化、PSO迭代和RBF训练整合成一个函数。这才是这个方案真正可跑的最小闭环。def train_pso_rbf(X, y, n_hidden15, n_particles30, n_iter80, c11.5, c21.5, w_max0.9, w_min0.4, reg1e-4): n_samples, n_features X.shape n_classes len(np.unique(y)) dim n_hidden * n_features n_hidden n_hidden * n_classes # 构造参数边界 feat_min, feat_max X.min(0), X.max(0) feat_std X.std(0) 1e-8 lb np.concatenate([ np.tile(feat_min, n_hidden), # 中心下界特征最小值 0.2 * feat_std.mean() * np.ones(n_hidden), # 宽度下界防止宽度坍塌 -np.ones(n_hidden * n_classes) # 权值下界 ]) ub np.concatenate([ np.tile(feat_max, n_hidden), # 中心上界特征最大值 2.0 * np.sqrt(((feat_max - feat_min) ** 2).sum()) * np.ones(n_hidden), np.ones(n_hidden * n_classes) # 权值上界 ]) # Logistic 混沌初始化 seq np.zeros((n_particles, dim)) xk 0.7 for i in range(n_particles * dim): xk 4.0 * xk * (1.0 - xk) seq[i // dim, i % dim] xk particles lb seq * (ub - lb) vels np.zeros_like(particles) def _fitness(p): centers p[:n_hidden * n_features].reshape(n_hidden, n_features) widths p[n_hidden * n_features:n_hidden * (n_features 1)] weights p[n_hidden * (n_features 1):].reshape(n_classes, n_hidden) prob, _ rbf_forward(X, centers, widths, weights) eps 1e-12 loss -np.log(prob[np.arange(n_samples), y] eps).mean() loss reg * np.sum(weights ** 2) return loss pbest particles.copy() pbest_loss np.array([_fitness(p) for p in particles]) gbest pbest[np.argmin(pbest_loss)].copy() gbest_loss pbest_loss.min() for t in range(n_iter): w w_max - (w_max - w_min) * t / n_iter r1 np.random.rand(n_particles, dim) r2 np.random.rand(n_particles, dim) vels w * vels c1 * r1 * (pbest - particles) c2 * r2 * (gbest - particles) particles np.clip(particles vels, lb, ub) losses np.array([_fitness(p) for p in particles]) improved losses pbest_loss pbest[improved] particles[improved] pbest_loss[improved] losses[improved] if pbest_loss.min() gbest_loss: idx np.argmin(pbest_loss) gbest pbest[idx].copy() gbest_loss pbest_loss[idx] return gbest, gbest_loss这个函数里的边界构造是整个改进方案的核心细节。宽度下界取0.2倍特征标准差均值粒子更新后任何宽度小于这个值的都会被np.clip拉回来径向基函数永远不会变成孤立尖刺。中心边界取训练集各维特征的最小值和最大值保证中心落在样本分布范围内。权值边界取正负1因为归一化后的输入和phi都在0到1附近这个范围够用。混沌初始化用Logistic映射生成n_particles×dim个[0,1]序列值再线性映射到参数边界。相比用np.random.rand直接初始化粒子分布更均匀第一次迭代的适应度方差也更小。提示训练结束后检查gbest里widths的均值如果小于宽度下界的1.1倍大概率是宽度坍塌的前兆需要把下界再往上提。4.3 测试与评估准确率之外必须看混淆矩阵训练完拿到gbest粒子直接用unpack_particle还原RBF参数跑测试集from sklearn.metrics import confusion_matrix, classification_report def predict(X_test, p, n_hidden, n_features, n_classes): centers, widths, weights unpack_particle(p, n_hidden, n_features, n_classes) prob, _ rbf_forward(X_test, centers, widths, weights) return np.argmax(prob, axis1), prob pred, prob predict(X_test, gbest, n_hidden, n_features, n_classes) print(confusion_matrix(y_test, pred)) print(classification_report(y_test, pred))混淆矩阵是必须看的。DGA故障诊断里正常样本往往占60%以上模型全猜正常也有不错的准确率但放电类样本一个都抓不到这才是工程上的致命伤。classification_report会逐类输出精确率和召回率哪个故障类别被淹没一眼就能看出来比总体准确率信息量大得多。5. 变压器故障诊断的避坑指南5个让改进PSO-RBF翻车的隐蔽问题5.1 数据泄漏归一化统计量混进测试集现象测试集准确率高得离谱冲到98%以上但拿现场新样本一测就崩。原因先对整个数据集做归一化再切分测试集的均值和标准差通过归一化过程泄漏进了训练环节。PSO搜索到的边界在这个“作弊”的测试集上极其好看真实场景根本不成立。解决先切分再用训练集的统计量变换两个集合mu, std X_train.mean(0), X_train.std(0) X_train (X_train - mu) / std X_test (X_test - mu) / std切分之后训练集统计量一旦算好就固定住后续调参重跑时不要再重新算train_val的统计量否则同样会慢慢泄漏。5.2 样本不平衡准确率95%可能是“全猜正常”现象混淆矩阵里正常样本一大块放电类召回率全零但总体准确率看起来体面。原因正常样本占比过高PSO的适应度是全局平均交叉熵少数类样本的损失被多数类稀释优化器只要把正常类预测对就能拿到很低的loss。解决评估时强制打印classification_report逐类看召回率。训练侧可以给少数类样本在_fitness里加权或者干脆复制几份做简单过采样。现场诊断场景里漏报一次放电故障的代价远高于误报一次正常别因为多数类比例高就放过这个坑。5.3 宽度坍塌训练loss很低测试集一塌糊涂现象训练收敛后loss降到0.05级别测试集预测结果却几乎全是同一个类别。原因宽度下界没有设好PSO粒子把部分宽度推向极小值径向基函数退化成尖刺函数。每个训练样本被自己的尖刺记住样本之间的平滑响应消失新的测试样本落在所有尖刺之间激活值全是0输出概率被softmax强行归一化后变成随机猜测。解决边界里宽度下界不能设0按特征标准差的0.1到0.3倍起步。训练结束后打印widths均值如果低于宽度下界1.1倍基本可以断定坍塌风险把下界提高30%重新训练。5.4 隐含中心数拍脑袋中心越多不代表效果越好现象n_hidden从10加到50训练越来越慢交叉验证结果反而变差。原因中心数超过样本量的一半后模型开始逐点记忆同时粒子维度从210涨到490PSO搜索空间膨胀改进算法也拉不回局部极值。解决用5折交叉验证扫n_hidden我一般试8、12、16、20四档。样本量只有30到60条时8到15个中心完全够用。中心数一旦超过样本量复杂度的代价远大于拟合收益。5.5 只报一个类别名边界样本没有置信度输出现象现场工程师拿诊断结果跟DGA台账复核发现处于两类边界的样本被强行分成某一类最大概率只有0.34也照样输出。原因预测时直接取np.argmax概率低也当硬结论发出去。DGA数据本身存在天然模糊区低能放电和高能放电经常只有乙炔浓度一个维度的差异样本落在这两者中间时任何分类器都不能给出可靠答案。解决预测时设定置信阈值。最大概率低于0.6时输出“无法可靠判型建议复检”而不是硬报一个类别。电力检修现场“宁可不报不可报错”比统计准确率更实用这条经验比任何调参技巧都值钱。这一节的排错顺序也是有讲究的先查数据泄漏再查样本平衡然后看宽度是否坍塌最后才轮到调网络结构和阈值。很多人一上来就调粒子数、迭代次数折腾一整晚不如先按这个顺序排查一轮。6. 进阶验证用误检样本做逐条复盘把改进PSO-RBF推到可上线模型在测试集上跑完别只看混淆矩阵就收工。最后一个步骤是把误检样本逐个拉出来复盘这一步能发现混淆矩阵看不出的规律。做法是把所有测试样本的完整概率分布保存下来筛出预测错误的那批打印它们的真实类别、预测类别、最大概率和第二大概率。如果第二大概率对应的是真实类别说明模型其实已经捕捉到了这个样本的双重特征只是第一名的概率更高如果最大的两个概率都指向错误类别那大概率是训练标签本身有问题。def review_misclassified(X_test, y_test, p, n_hidden, n_features, n_classes): pred, prob predict(X_test, p, n_hidden, n_features, n_classes) mis np.where(pred ! y_test)[0] for i in mis: order np.argsort(prob[i])[::-1] print(fidx{i} true{y_test[i]} pred{pred[i]} ftop1{prob[i][order[0]]:.3f}({order[0]}) ftop2{prob[i][order[1]]:.3f}({order[1]}))把输出整理成下面这种复盘表比任何综合指标都直观样本编号真实故障预测故障最大概率第二大概率12低能放电(5)高能放电(6)0.510.4027中温过热(3)高温过热(4)0.470.43样本12的最大概率只有0.51第二大概率0.40指向真实类别说明它本身处在低能放电和高能放电的交界区乙炔浓度恰好卡在中间。这类样本通过阈值规则拦下来走人工复检比强行分类更负责。样本27的top1和top2都偏了但两者只差0.04一个轻微扰动就会换边属于训练数据里该类样本本就稀少导致的欠拟合需要补样本不是调参能解决的。我第一次做这个方向的时候只看全局准确率0.94就准备收工直到把误检样本拉出来才发现六类故障里有两类几乎完全被多数类淹没。从那以后我给自己立了条规矩凡是分类模型准确率只作为参考线真正的验收标准是逐类召回率和误检样本的top2概率差。这个习惯帮我避开了很多看起来精度高、现场不能用的模型。希望帮到你。本文还有配套的精品资源点击获取