【效能评估方法系列10】粒子群优化 BP 神经网络(PSO-BP):让 BP 不再“看初值脸色”

发布时间:2026/9/12 21:05:10
【效能评估方法系列10】粒子群优化 BP 神经网络(PSO-BP):让 BP 不再“看初值脸色” 一、为什么要用 PSO 优化 BPBP 神经网络有个老问题梯度下降 ≠ 全局最优​初值一换结果可能天差地别。粒子群算法Particle Swarm Optimization, PSO不一样不靠梯度靠“群体经验 个体经验”搜索实现简单、参数少、收敛快所以工业界很喜欢这么玩这就是PSO-BPNN。二、PSO-BP 的核心思想1. 粒子是什么一个粒子 一组 BP 网络参数网络结构4-6-1时 每个粒子是 37 维空间里的一个点。2. PSO 更新公式必背速度更新位置更新w惯性权重保留原来速度c1认知因子相信自己c2社会因子相信群体pBest粒子历史最优gBest全队最优3. 适应度怎么定用 BP 跑一小会儿算 MSEfitness msePSO 的目标是让 MSE 越来越小。三、PSO-BP 训练流程四、C语言代码获取/** * file : Alg_14_PSABPNN.h * brief : 粒子群优化BP神经网络模型 * details : Particle Swarm Optimization - BP Neural Network * author : 三环上的骑士 * date : 2026-05 * version : v1.1 * note : PSO用于全局搜索BP初始权阈缓解初值敏感与局部极小 * warning : 惯性权重W、学习因子C1/C2需合理设置以防早熟收敛 */ #include stdio.h #include stdlib.h #include math.h #include time.h #define INNUM 4 #define HIDNUM 6 #define OUTNUM 1 #define SAMPLE 5 #define NP 20 // 粒子数 #define MAXITER 50 #define EPOCHS 200 #define EPOCHS_FINAL 2000 #define W 0.6 #define C1 1.5 #define C2 1.5 #define LB -1.0 #define UB 1.0 #define NW (HIDNUM*INNUM HIDNUM OUTNUM*HIDNUM OUTNUM) #define RESULTPATH ../../../006_效能评估结果数据包/14_psobpnn_result.txt /* 工具函数 */ static inline double sigmoid(double x) { if (x -40.0) return 0.0; return 1.0 / (1.0 exp(-x)); } static inline double randd(void) { return (double)rand() / RAND_MAX; } /* BP权值结构体 */ typedef struct { double W1[HIDNUM][INNUM]; double b1[HIDNUM]; double W2[OUTNUM][HIDNUM]; double b2[OUTNUM]; } BPWeights; /* 解码染色体 - BP权值 */ void decode(double chrom[NW], BPWeights *net) { int idx 0; for (int i 0; i HIDNUM; i) for (int j 0; j INNUM; j) net-W1[i][j] chrom[idx]; for (int i 0; i HIDNUM; i) net-b1[i] chrom[idx]; for (int i 0; i OUTNUM; i) for (int j 0; j HIDNUM; j) net-W2[i][j] chrom[idx]; for (int i 0; i OUTNUM; i) net-b2[i] chrom[idx]; } /* BP前向传播 */ double bp_forward(BPWeights *net, double x[INNUM]) { double a1[HIDNUM]; for (int i 0; i HIDNUM; i) { double z net-b1[i]; for (int j 0; j INNUM; j) z net-W1[i][j] * x[j]; a1[i] sigmoid(z); } double y net-b2[0]; for (int i 0; i HIDNUM; i) y net-W2[0][i] * a1[i]; return y; } /* BP训练小迭代用于PSO适应度评估 */ double bp_train( BPWeights *net, double X[INNUM][SAMPLE], double T[SAMPLE], int epochs ) { const double lr 0.05; double mse 0.0; for (int ep 0; ep epochs; ep) { for (int s 0; s SAMPLE; s) { /* 前向 */ double a1[HIDNUM]; for (int i 0; i HIDNUM; i) { double z net-b1[i]; for (int j 0; j INNUM; j) z net-W1[i][j] * X[j][s]; a1[i] sigmoid(z); } double y net-b2[0]; for (int i 0; i HIDNUM; i) y net-W2[0][i] * a1[i]; double err y - T[s]; /* 反向 */ double dZ2 err; double dW2[HIDNUM]; for (int i 0; i HIDNUM; i) dW2[i] dZ2 * a1[i]; double db2 dZ2; double dZ1[HIDNUM]; for (int i 0; i HIDNUM; i) dZ1[i] net-W2[0][i] * dZ2 * a1[i] * (1.0 - a1[i]); /* 更新输出层 */ for (int i 0; i HIDNUM; i) net-W2[0][i] - lr * dW2[i]; net-b2[0] - lr * db2; /* 更新隐层 */ for (int i 0; i HIDNUM; i) { for (int j 0; j INNUM; j) net-W1[i][j] - lr * dZ1[i] * X[j][s]; net-b1[i] - lr * dZ1[i]; } } } /* 计算MSE */ mse 0.0; for (int s 0; s SAMPLE; s) { double y bp_forward(net, (double *)X[s]); double e y - T[s]; mse e * e; } return mse / SAMPLE; } /* PSO训练 */ void pso_train( double X[INNUM][SAMPLE], double T[SAMPLE], double gBest[NW], double fitCurve[MAXITER] ) { double pos[NP][NW]; double vel[NP][NW]; double pBest[NP][NW]; double pBestFit[NP]; double gBestFit 1e20; srand((unsigned int)time(NULL)); /* 初始化 */ for (int p 0; p NP; p) { for (int i 0; i NW; i) { pos[p][i] LB (UB - LB) * randd(); vel[p][i] 0.0; } pBestFit[p] 1e20; } /* PSO主循环 */ for (int iter 0; iter MAXITER; iter) { for (int p 0; p NP; p) { BPWeights net; decode(pos[p], net); double mse bp_train(net, X, T, EPOCHS); if (mse pBestFit[p]) { pBestFit[p] mse; for (int i 0; i NW; i) pBest[p][i] pos[p][i]; // ✅ 修复原Bug } if (mse gBestFit) { gBestFit mse; for (int i 0; i NW; i) gBest[i] pos[p][i]; } } /* 更新速度/位置 */ for (int p 0; p NP; p) { for (int i 0; i NW; i) { vel[p][i] W * vel[p][i] C1 * randd() * (pBest[p][i] - pos[p][i]) C2 * randd() * (gBest[i] - pos[p][i]); pos[p][i] vel[p][i]; if (pos[p][i] LB) pos[p][i] LB; if (pos[p][i] UB) pos[p][i] UB; } } fitCurve[iter] gBestFit; printf(Iter %2d | Best MSE %.6f\n, iter 1, gBestFit); } } /* 结果输出控制台 */ void print_psobpnn_results( double T[SAMPLE], double Y_pred[SAMPLE], double fitCurve[MAXITER] ) { int i; double mse 0.0, mae 0.0, rmse 0.0; double mean 0.0, var 0.0, r2 0.0; for (i 0; i SAMPLE; i) mean T[i]; mean / SAMPLE; for (i 0; i SAMPLE; i) { double err Y_pred[i] - T[i]; mse err * err; mae fabs(err); var (T[i] - mean) * (T[i] - mean); } mse / SAMPLE; mae / SAMPLE; rmse sqrt(mse); r2 (var 1e-12) ? 0.0 : (1.0 - mse * SAMPLE / var); printf(\n PSO-BPNN 效能评估结果 \n); printf(结构: %d-%d-%d | PSO: %d×%d | BP: %d%d epoch\n, INNUM, HIDNUM, OUTNUM, NP, MAXITER, EPOCHS, EPOCHS_FINAL); printf(\n---------- 1. 样本预测明细 ----------\n); printf(%-8s %10s %10s %12s\n, 方案, 真实值, 预测值, 绝对误差); const char *labels[SAMPLE] { A, B, C, D, E }; for (i 0; i SAMPLE; i) printf(%-8s %10.4f %10.4f %12.4f\n, labels[i], T[i], Y_pred[i], fabs(Y_pred[i] - T[i])); printf(\n---------- 2. 模型性能 ----------\n); printf(MSE%.6f | RMSE%.4f | MAE%.4f | R²%.4f\n, mse, rmse, mae, r2); printf(\n---------- 3. PSO优化效果 ----------\n); printf(初始MSE: %.6f\n, fitCurve[0]); printf(最终MSE: %.6f\n, fitCurve[MAXITER - 1]); printf(\n); } /* 结果输出文件 */ void print_psobpnn_results_to_file( double T[SAMPLE], double Y_pred[SAMPLE], double fitCurve[MAXITER], FILE *fp ) { int i; double mse 0.0, mae 0.0, rmse 0.0; double mean 0.0, var 0.0, r2 0.0; /* ---------- 1. 统计指标计算 ---------- */ for (i 0; i SAMPLE; i) mean T[i]; mean / SAMPLE; for (i 0; i SAMPLE; i) { double err Y_pred[i] - T[i]; mse err * err; mae fabs(err); var (T[i] - mean) * (T[i] - mean); } mse / SAMPLE; mae / SAMPLE; rmse sqrt(mse); r2 (var 1e-12) ? 0.0 : (1.0 - mse * SAMPLE / var); /* ---------- 2. 文件头与模型性能 ---------- */ fprintf(fp, \n PSO-BPNN 效能评估结果 \n); fprintf(fp, MSE%.6f | RMSE%.4f | MAE%.4f | R²%.4f\n, mse, rmse, mae, r2); /* ---------- 3. PSO 优化收敛曲线 ---------- */ fprintf(fp, \n---------- PSO 优化收敛过程 ----------\n); for (i 0; i MAXITER; i) fprintf(fp, 第%2d次迭代 | 最优MSE%.6f\n, i 1, fitCurve[i]); fprintf(fp, \n); } /* 测试入口 */ void testPSOBPNN(void) { double X[INNUM][SAMPLE] { { 0.5294, 0.1765, 0.4118, 1.0000 }, { 0.2353, 0.3529, 0.1765, 0.4118 }, { 1.0000, 0.0000, 1.0000, 0.0000 }, { 0.0000, 0.4706, 0.0000, 0.4118 } }; double T[SAMPLE] { 0.6218, 0.4873, 0.7125, 0.8031, 0.6652 }; double gBest[NW]; double fitCurve[MAXITER]; pso_train(X, T, gBest, fitCurve); BPWeights net; decode(gBest, net); bp_train(net, X, T, EPOCHS_FINAL); double Ypred[SAMPLE]; for (int i 0; i SAMPLE; i) Ypred[i] bp_forward(net, (double *)X[i]); print_psobpnn_results(T, Ypred, fitCurve); FILE *fp fopen(RESULTPATH, w); if (fp) { print_psobpnn_results_to_file(T, Ypred, fitCurve, fp); fclose(fp); printf([INFO] PSO-BPNN结果已写入: %s\n, RESULTPATH); } }五、MATLAB代码获取%% % file : Alg_14_PSABPNN.m % brief : 粒子群优化BP神经网络模型 % details : Particle Swarm Algorithm-Backpropagation Neural Network % 利用PSO算法优化BP网络的初始权值和阈值再精细训练 % author : 三环上的骑士 % date : 2026-05 % version : v1.0 % note : 收敛速度通常优于GA-BP常写作PSO-BPNN % warning : 粒子群参数(惯性权重、学习因子)需合理设置以防止早熟收敛 clc; clear; close all; %% 1. 样本数据装备方案效能评估 X [ 0.5294 0.1765 0.4118 1.0000; % A 0.2353 0.3529 0.1765 0.4118; % B 1.0000 0.0000 1.0000 0.0000; % C 0.0000 0.4706 0.0000 0.4118; % D 0.8235 0.6471 0.8235 0.7647 % E ]; % 4×5 T [0.6218 0.4873 0.7125 0.8031 0.6652]; % 1×5 [inNum, S] size(X); hidNum 6; outNum 1; %% 2. 网络与权值长度 nW hidNum*inNum hidNum outNum*hidNum outNum; %% 3. PSO参数 nParticle 20; maxIter 50; w 0.6; % 惯性权重 c1 1.5; % 认知系数 c2 1.5; % 社会系数 lb -1; ub 1; rng(2026); sigmoid (x) 1./(1exp(-x)); %% 4. 初始化粒子群 pos lb (ub-lb).*rand(nParticle, nW); vel zeros(nParticle, nW); pBest pos; pBestFit inf(nParticle,1); gBest pos(1,:); gBestFit inf; fitCurve zeros(maxIter,1); %% 5. PSO主循环 for iter 1:maxIter for p 1:nParticle % ---- 解码 ---- chrom pos(p,:); idx 1; W1 reshape(chrom(idx:idxhidNum*inNum-1), hidNum, inNum); idx idx hidNum*inNum; b1 chrom(idx:idxhidNum-1); idx idx hidNum; W2 reshape(chrom(idx:idxoutNum*hidNum-1), outNum, hidNum); idx idx outNum*hidNum; b2 chrom(idx:idxoutNum-1); % ---- 小规模BP训练 ---- W1c W1; b1c b1; W2c W2; b2c b2; lr 0.05; epochs_bp 200; for ep 1:epochs_bp Z1 W1c*X repmat(b1c,1,S); A1 sigmoid(Z1); Z2 W2c*A1 repmat(b2c,1,S); E Z2 - T; dZ2 E; dW2 dZ2*A1/S; db2 mean(dZ2,2); dA1 W2c*dZ2; dZ1 dA1.*A1.*(1-A1); dW1 dZ1*X/S; db1 mean(dZ1,2); W2c W2c - lr*dW2; b2c b2c - lr*db2; W1c W1c - lr*dW1; b1c b1c - lr*db1; end % ---- 适应度 ---- Z1 W1c*X repmat(b1c,1,S); A1 sigmoid(Z1); Yp W2c*A1 repmat(b2c,1,S); mse mean((Yp - T).^2); fit mse; % ---- 更新个体最优 ---- if fit pBestFit(p) pBestFit(p) fit; pBest(p,:) pos(p,:); end % ---- 更新全局最优 ---- if fit gBestFit gBestFit fit; gBest pos(p,:); end end % ---- 更新速度与位置 ---- for p 1:nParticle r1 rand(1,nW); r2 rand(1,nW); vel(p,:) w*vel(p,:) ... c1*r1.*(pBest(p,:)-pos(p,:)) ... c2*r2.*(gBest-pos(p,:)); pos(p,:) pos(p,:) vel(p,:); % 边界处理 pos(p,:) max(pos(p,:), lb); pos(p,:) min(pos(p,:), ub); end fitCurve(iter) gBestFit; fprintf(Iter %2d | Best MSE %.6f\n, iter, gBestFit); end %% 6. 用全局最优初始化最终BP chrom gBest; idx 1; W1 reshape(chrom(idx:idxhidNum*inNum-1), hidNum, inNum); idx idx hidNum*inNum; b1 chrom(idx:idxhidNum-1); idx idx hidNum; W2 reshape(chrom(idx:idxoutNum*hidNum-1), outNum, hidNum); idx idx outNum*hidNum; b2 chrom(idx:idxoutNum-1); % 最终训练 lr 0.05; epochs_final 2000; for ep 1:epochs_final Z1 W1*X repmat(b1,1,S); A1 sigmoid(Z1); Z2 W2*A1 repmat(b2,1,S); E Z2 - T; dZ2 E; dW2 dZ2*A1/S; db2 mean(dZ2,2); dA1 W2*dZ2; dZ1 dA1.*A1.*(1-A1); dW1 dZ1*X/S; db1 mean(dZ1,2); W2 W2 - lr*dW2; b2 b2 - lr*db2; W1 W1 - lr*dW1; b1 b1 - lr*db1; end %% 7. 预测 Z1 W1*X repmat(b1,1,S); A1 sigmoid(Z1); Y_pred W2*A1 repmat(b2,1,S); mse mean((Y_pred-T).^2); rmse sqrt(mse); R2 1 - sum((T-Y_pred).^2)/sum((T-mean(T)).^2); fprintf(\n PSO-BP效能评估结果 \n); labels {A,B,C,D,E}; for i 1:S fprintf(方案%s %10.4f %10.4f %12.4f\n,... labels{i}, T(i), Y_pred(i), abs(Y_pred(i)-T(i))); end fprintf(\nMSE%.6f RMSE%.4f R2%.4f\n, mse, rmse, R2); %% 8. 收敛曲线 figure(Color,w); plot(fitCurve,LineWidth,1.5); grid on; xlabel(Iteration); ylabel(Best MSE); title(PSO优化BP收敛曲线无工具箱);六、MATALAB代码获取%% % file : Alg_14_PSOBPNN.m % brief : 粒子群优化BP神经网络模型 % details : Particle Swarm Algorithm-Backpropagation Neural Network % 利用PSO算法优化BP网络的初始权值和阈值再精细训练 % author : 三环上的骑士 % date : 2026-05 % version : v1.0 % note : 收敛速度通常优于GA-BP常写作PSO-BPNN % warning : 粒子群参数(惯性权重、学习因子)需合理设置以防止早熟收敛 clc; clear; close all; %% 1. 样本数据装备方案效能评估 X [ 0.5294 0.1765 0.4118 1.0000; % A 0.2353 0.3529 0.1765 0.4118; % B 1.0000 0.0000 1.0000 0.0000; % C 0.0000 0.4706 0.0000 0.4118; % D 0.8235 0.6471 0.8235 0.7647 % E ]; % 4×5 T [0.6218 0.4873 0.7125 0.8031 0.6652]; % 1×5 [inNum, S] size(X); hidNum 6; outNum 1; %% 2. 网络与权值长度 nW hidNum*inNum hidNum outNum*hidNum outNum; %% 3. PSO参数 nParticle 20; maxIter 50; w 0.6; % 惯性权重 c1 1.5; % 认知系数 c2 1.5; % 社会系数 lb -1; ub 1; rng(2026); sigmoid (x) 1./(1exp(-x)); %% 4. 初始化粒子群 pos lb (ub-lb).*rand(nParticle, nW); vel zeros(nParticle, nW); pBest pos; pBestFit inf(nParticle,1); gBest pos(1,:); gBestFit inf; fitCurve zeros(maxIter,1); %% 5. PSO主循环 for iter 1:maxIter for p 1:nParticle % ---- 解码 ---- chrom pos(p,:); idx 1; W1 reshape(chrom(idx:idxhidNum*inNum-1), hidNum, inNum); idx idx hidNum*inNum; b1 chrom(idx:idxhidNum-1); idx idx hidNum; W2 reshape(chrom(idx:idxoutNum*hidNum-1), outNum, hidNum); idx idx outNum*hidNum; b2 chrom(idx:idxoutNum-1); % ---- 小规模BP训练 ---- W1c W1; b1c b1; W2c W2; b2c b2; lr 0.05; epochs_bp 200; for ep 1:epochs_bp Z1 W1c*X repmat(b1c,1,S); A1 sigmoid(Z1); Z2 W2c*A1 repmat(b2c,1,S); E Z2 - T; dZ2 E; dW2 dZ2*A1/S; db2 mean(dZ2,2); dA1 W2c*dZ2; dZ1 dA1.*A1.*(1-A1); dW1 dZ1*X/S; db1 mean(dZ1,2); W2c W2c - lr*dW2; b2c b2c - lr*db2; W1c W1c - lr*dW1; b1c b1c - lr*db1; end % ---- 适应度 ---- Z1 W1c*X repmat(b1c,1,S); A1 sigmoid(Z1); Yp W2c*A1 repmat(b2c,1,S); mse mean((Yp - T).^2); fit mse; % ---- 更新个体最优 ---- if fit pBestFit(p) pBestFit(p) fit; pBest(p,:) pos(p,:); end % ---- 更新全局最优 ---- if fit gBestFit gBestFit fit; gBest pos(p,:); end end % ---- 更新速度与位置 ---- for p 1:nParticle r1 rand(1,nW); r2 rand(1,nW); vel(p,:) w*vel(p,:) ... c1*r1.*(pBest(p,:)-pos(p,:)) ... c2*r2.*(gBest-pos(p,:)); pos(p,:) pos(p,:) vel(p,:); % 边界处理 pos(p,:) max(pos(p,:), lb); pos(p,:) min(pos(p,:), ub); end fitCurve(iter) gBestFit; fprintf(Iter %2d | Best MSE %.6f\n, iter, gBestFit); end %% 6. 用全局最优初始化最终BP chrom gBest; idx 1; W1 reshape(chrom(idx:idxhidNum*inNum-1), hidNum, inNum); idx idx hidNum*inNum; b1 chrom(idx:idxhidNum-1); idx idx hidNum; W2 reshape(chrom(idx:idxoutNum*hidNum-1), outNum, hidNum); idx idx outNum*hidNum; b2 chrom(idx:idxoutNum-1); % 最终训练 lr 0.05; epochs_final 2000; for ep 1:epochs_final Z1 W1*X repmat(b1,1,S); A1 sigmoid(Z1); Z2 W2*A1 repmat(b2,1,S); E Z2 - T; dZ2 E; dW2 dZ2*A1/S; db2 mean(dZ2,2); dA1 W2*dZ2; dZ1 dA1.*A1.*(1-A1); dW1 dZ1*X/S; db1 mean(dZ1,2); W2 W2 - lr*dW2; b2 b2 - lr*db2; W1 W1 - lr*dW1; b1 b1 - lr*db1; end %% 7. 预测 Z1 W1*X repmat(b1,1,S); A1 sigmoid(Z1); Y_pred W2*A1 repmat(b2,1,S); mse mean((Y_pred-T).^2); rmse sqrt(mse); R2 1 - sum((T-Y_pred).^2)/sum((T-mean(T)).^2); fprintf(\n PSO-BP效能评估结果 \n); labels {A,B,C,D,E}; for i 1:S fprintf(方案%s %10.4f %10.4f %12.4f\n,... labels{i}, T(i), Y_pred(i), abs(Y_pred(i)-T(i))); end fprintf(\nMSE%.6f RMSE%.4f R2%.4f\n, mse, rmse, R2); %% 8. 收敛曲线 figure(Color,w); plot(fitCurve,LineWidth,1.5); grid on; xlabel(Iteration); ylabel(Best MSE); title(PSO优化BP收敛曲线无工具箱);对比项GA-BPPSO-BP核心操作选择/交叉/变异速度/位置更新参数数量多少实现难度中低收敛速度慢一点快全局搜索强中易早熟交叉失效时粒子聚集时工程推荐样本少/要稳快速验证模型经验结论PSO-BP快、简单、够用​GA-BP稳、抗局部极小、慢七、工程建议很重要✅ 1. 惯性权重别写死w 0.9 - 0.5 * iter / maxIter;前期探索后期精修。✅ 2. 小样本别神话 PSO-BP5 个样本、37 个参数 → 本质还是过参数化PSO 的价值在30 样本​ 时才明显✅ 3. PSO 阶段 BP 别跑太多200 轮够排序2000 轮留给最终训练八、一句话总结BP 负责“学”PSO 负责“起好头”。​PSO-BP 不是最强模型但它是“让 BP 不再玄学”的最省事方案之一。九、勘误及更新说明本文如有疏漏或表述不当之处欢迎各位读者在评论区指正博主会持续关注反馈并及时修正优化力求内容准确可靠。感谢大家的监督与陪伴。如果本文对你的研究或项目有帮助欢迎点赞、收藏、关注三连​版权声明本文为原创技术文章未经作者同意不得转载。代码遵循MIT开源协议。