尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

纵横交叉算法优化BP神经网络的电力负荷预测MATLAB实现

纵横交叉算法优化BP神经网络的电力负荷预测MATLAB实现 简介资源为电力负荷预测方向的学术论文PDF面向电力系统调度、负荷预测研究人员及深度学习、神经网络学习者针对传统BP神经网络对含冲击负荷地区高频分量预测精度不足、泛化能力弱的问题给出了一种基于小波变换与纵横交叉算法优化的改进方案。文中通过小波分解负荷序列利用纵横交叉算法对神经网络的权重与阈值进行全局寻优并用实际电网算例验证模型在冲击负荷场景下的预测精度与泛化能力。资源仅有1个PDF文档约357KB完整收录论文正文、图表、公式及参考文献适合想快速了解该方法原理、流程与实验对比结果的读者。目前已有103人浏览学习下载后可直接阅读原始文献获取CSO算法设计思想、小波分解重构架构、网络训练策略以及实际预测结果分析等细节便于复现实验或作为写作参考。1. 为什么要用纵横交叉算法去优化神经网络的负荷预测模型电力负荷预测并不是查一度电的历史记录就算完。一条完整的日负荷曲线会同时被温度、湿度、日类型、前一天用电行为等多个因素叠加影响非线性强普通回归模型根本拉不动。BP 这类前馈神经网络能刻画这种非线性可它的权重训练依赖梯度下降初值不好或样本噪声大时很容易停在局部最优附近负荷尖峰段怎么都拟合不上。纵横交叉优化Crisscross Optimization常缩写为 CSO是一种不依赖梯度的群智能算法特征是同时做横向交叉和纵向交叉两种搜索正适合用来替换 BP 原生的随机初始化加梯度训练。下面从输入构造、BP 基线和 CSO 调权流程一路走下来MATLAB 代码可以直接落地适合正在做负荷预测建模或竞赛题的工程师参考。2. 纵横交叉算法的两个算子在负荷预测里各管什么2.1 横向交叉在父代连线附近构造更宽的搜索区间纵横交叉优化的核心结构是“横向交叉 纵向交叉”两个算子。横向交叉先对当前种群做随机两两配对然后对配对的两个个体在同一维度上各自生成一个后代。常见的生成公式是Ms1(a,d) r1 * a(d) (1 - r1) * b(d) c1 * (a(d) - b(d)) Ms2(b,d) r2 * b(d) (1 - r2) * a(d) c2 * (b(d) - a(d))r1、r2 是 (0,1) 均匀随机数c1、c2 取 (-1,1)。前半截是父代线性混合后半截是差分修正和差分进化有点像但差分进化只对一个主向量加扰动这里是对两个方向同时做搜索区域是一个以两个父代为中心点的斜四边形比单纯在连线中点取点要宽。对负荷预测这种响应曲面很不光滑的问题来说这样的搜索步长能在早期覆盖到更多局部盆地。2.2 纵向交叉主动解耦被平铺的权重维度BP 网络要优化的量不是一个标量而是把好几层的权重矩阵、阈值向量全部展开成一个一维向量。这个平铺过程会把原本硬件上独立的两组权重变成相邻的维度梯度下降走起来容易“牵一发动全身”。纵向交叉随机取同一个体的两个维度把其中一个维度的取值按权重 r 和另一个维度作线性混合也就是维度之间的交叉。这样做有两个直接好处一是跳出只沿坐标轴移动的局限二是当某两个维度高度相关时用这种“跳变”能更快摆脱鞍点比只做横向的种群扰动更稳。负荷预测的输入特征里温度和湿度往往存在耦合历史负荷的前日值与前两日值也高度相关这些耦合关系反映到权重向量上就表现为若干维度之间存在较强的相关结构纵向交叉恰好处理的是这部分冗余。2.3 和粒子群、遗传算法相比CSO 更适合调高维权重对比项粒子群 (PSO)遗传算法 (GA)纵横交叉算法 (CSO)信息交换方式个体朝历史最优与全局最优靠拢选择、交叉、变异随机组合成对横向组合 跨维纵向组合对超参数的敏感度高惯性权重进退两难高交叉率变异率耦合低主调种群规模和迭代数权重向量超过 100 维速度项频繁抖动早熟常见变异步长难匹配量纲纵向交叉主动消除维间冗余负荷预测场景的表现训练误差低但验证集抖动收敛慢结果复现性差收敛适中验证误差更集中实现难度低低中两个算子需要分别写BP 网络的可训练参数在本文这种 6-12-6-1 结构里是一百多维起步PSO 的“跟最优走”策略在高维空间里会退化成向某些优秀维度的堆叠。GA 保持多样性的能力还行但交叉率、变异率一旦没调好后期搜索步长会被锁死。CSO 的两个算子分工明确横向负责种群采样宽度纵向负责维度间解耦我在做负荷预测模型调参时通常只改种群规模和迭代次数省下来的时间都拿去调整输入特征。2.4 用最小的一段代码看一眼横向交叉下面是一段 MATLAB 函数对应 2.1 节里的两行公式function [Ms1, Ms2] hc_once(a, b, d) % HC_ONCE 横向交叉算子对单个维度的计算 % a, b : 两个父代个体向量 % d : 当前维度序号 r1 rand(); % 与 b 混合的比例 r2 rand(); c1 -1 2 * rand(); % 差分修正系数落在 [-1,1] c2 -1 2 * rand(); Ms1 r1 * a(d) (1 - r1) * b(d) c1 * (a(d) - b(d)); Ms2 r2 * b(d) (1 - r2) * a(d) c2 * (b(d) - a(d)); end这段代码只做单个维度的单次交叉真正优化中要把它套进“种群配对 逐维循环 边界处理 贪心更新”四步里。注意 c1、c2 的随机幅度是 2即最大差分扩到两倍这样做能保证后代偶尔跳出父代连线的包围区间否则交叉搜索就退化成了局部平均。运行它不需要神经网络工具箱只要有基础 MATLAB 就能验证固定两个向量 a、b 跑一千次后代点会形成围绕连线两侧的锥形分布随机差分项是形成这个形状的唯一来源。3. 用 MATLAB 把 BP 负荷预测基线先搭起来3.1 输入特征与样本切分顺序负荷预测模型有日、周、时等多个粒度标题里这种“先造特征、再用浅层网络回归”的做法主要针对短期日负荷预测。常见做法是取以下 6 个特征构成一个 n×6 矩阵列位特征说明数据来源1前一日同时刻负荷历史负荷库2前两日同时刻负荷历史负荷库3前一周同时刻负荷历史负荷库4温度气象接口5湿度气象接口6节假日标志日历注意节假日标志不要编码成 1~7 的整数序号BP 会把这些数字当作连续量把“周日”和“周一”之间的距离当成数值大小。惯用一个 0/1 标志就够了最多再做 one-hot 展开。样本切分要按时间顺序不能用随机抽样的方式打乱否则相邻天的信息会提前泄漏进训练集验证集误差会好看得失真。3.2 隐藏层结构与激活函数的选择用两层隐藏层处理日负荷这种数据第一层 12 个神经元、第二层 6 个神经元的 BP 网络结构算是常见的起步形态。起步节点数可以由经验公式估算隐藏层节点数取round(sqrt(m n) a)其中 m 是输入维度n 是输出维度a 在 1 到 10 之间浮动。6 个输入、1 个输出代入后第一层给 8 到 13 都不会太离谱这里取 12 是为了保留一点余量。第二层减半取 6让网络先把输入压缩到低维表示再映射到负荷值。两层隐藏层都用 tansig输出层用 purelin。原因负荷标签做归一化后落在 [-1,1]tansig 的饱和区能提供必要的非线性输出层用线性激活能让预测值不受 [-1,1] 硬限制反归一化后的量纲还原也更稳。3.3 BP 基线的完整训练代码% 数据划分按时间切块避免随机抽样的时间泄漏 row size(X, 1); idxTr 1:round(row * 0.7); idxVa round(row * 0.7) 1:row; Xtr X(idxTr, :); Ytr y(idxTr, :); Xva X(idxVa, :); Yva y(idxVa, :); % 归一化到 [-1,1]和 tansig 的动态范围保持一致 [Xtr_n, psX] mapminmax(Xtr); [Ytr_n, psy] mapminmax(Ytr); Xva_n mapminmax(apply, Xva, psX); Yva_n mapminmax(apply, Yva, psy); % 建 6-12-6-1 网络 net feedforwardnet([12 6]); net.layers{1}.transferFcn tansig; net.layers{2}.transferFcn tansig; net.layers{3}.transferFcn purelin; net.trainFcn trainlm; % Levenberg-Marquardt net.trainParam.showWindow false; net.trainParam.epochs 800; net.trainParam.goal 1e-5; net.divideFcn divideblock; % 按块划分不打乱时序 [net, ~] train(net, Xtr_n, Ytr_n); pred_norm sim(net, Xva_n); mse_bp mean((pred_norm - Yva_n).^2); fprintf(BP 验证集 MSE %.6f\n, mse_bp);这里有几个参数需要解释。mapminmax默认把数据映射到 [-1,1]训练时保存的psX和psy必须留着后面做测试集预测时用apply的方式复用同一套归一化参数不能用测试集重新计算最小值和最大值。feedforwardnet([12 6])生成两层隐藏层trainlm在几千条样本下收敛快但如果样本量超过十万建议换成trainscg否则trainlm的雅可比矩阵会吃掉大量内存。divideblock是最后一块区域做验证保证验证样本在时间上晚于训练样本。3.4 先画 BP 神经网络拟合曲线再判断基线是否可用直接看误差数字往往不够把pred_norm反归一化后画出来可以直观地看 BP 神经网络拟合曲线在什么位置掉链子pred_load mapminmax(reverse, pred_norm, psy); Yva_load mapminmax(reverse, Yva_n, psy); plot(1:length(Yva_load), Yva_load, -); hold on; plot(1:length(pred_load), pred_load, --); legend(真实负荷, BP 预测);如果这条曲线的早晚高峰段贴合度尚可、误差相对均匀说明数据本身没大问题如果只在少数尖峰样本上误差大而平段误差很小那么大概率是梯度法把网络带进了局部最优。这时候再引入纵横交叉算法才有意义否则就是在给一个已经够用的模型额外加复杂度。4. 纵横交叉算法嵌入 BP 的完整代码与参数表4.1 优化对象是权重向量不是网络结构CSO 只负责调整权重和阈值网络结构仍然按 6-12-6-1 保持固定。把所有可训练参数展平成向量后每个个体就是一个候选权重集个体长度 D 等于D 12*6 12 6*12 6 6*1 1 169这 169 维里权重占 150 维阈值占 19 维。在 MATLAB 里用reshape把它们还原成矩阵再前向计算即可。注意reshape默认按列优先展开只要编码和解码使用同一套顺序具体怎么排并不影响搜索能力。4.2 适应度函数与训练、验证、测试三块数据的职责标准做法是让 CSO 直接把神经网络的权重训练过程顶替掉适应度取验证集上的均方误差。也就是说CSO 每评估一个个体就把个体还原成权重在验证集上做一次前向计算得到 MSE不调用train不做 BP 反向传播。数据要切三块训练 60%、验证 20%、测试 20%CSO 的适应度只看验证集测试集在整个优化结束后才打开一次。如果所有数据都参与适应度打分最后的误差会自我欺骗。4.3 CSO-BP 主循环代码function [gBest, gBestVal] cso_bp(Xtr, Ytr, Xva, Yva, M, maxIter) % CSO_BP 纵横交叉算法优化 BP 权重 % 结构固定 6-12-6-1输入 X 为 n×6目标 Y 为 n×1 dims [12*6, 12, 6*12, 6, 6*1, 1]; D sum(dims); lb -5 * ones(1, D); ub 5 * ones(1, D); pop lb rand(M, D) .* (ub - lb); fit zeros(M, 1); for i 1:M fit(i) nn_mse(pop(i,:), Xva, Yva, dims); end [gBestVal, idx] min(fit); gBest pop(idx, :); for iter 1:maxIter % ---------- 横向交叉 ---------- perm randperm(M); for p 1:2:(M-1) i perm(p); j perm(p1); Ms1 zeros(1, D); Ms2 zeros(1, D); for d 1:D r1 rand(); r2 rand(); c1 -1 2 * rand(); c2 -1 2 * rand(); Ms1(d) r1*pop(i,d) (1-r1)*pop(j,d) c1*(pop(i,d)-pop(j,d)); Ms2(d) r2*pop(j,d) (1-r2)*pop(i,d) c2*(pop(j,d)-pop(i,d)); end Ms1 min(max(Ms1, lb), ub); Ms2 min(max(Ms2, lb), ub); f1 nn_mse(Ms1, Xva, Yva, dims); f2 nn_mse(Ms2, Xva, Yva, dims); if f1 fit(i), pop(i,:) Ms1; fit(i) f1; end if f2 fit(j), pop(j,:) Ms2; fit(j) f2; end end % ---------- 纵向交叉 ---------- for i 1:M if rand() 0.5, continue; end d1 randi(D); d2 randi(D); if d1 d2, continue; end Ms pop(i, :); r rand(); Ms(d1) r * pop(i,d1) (1 - r) * pop(i,d2); Ms min(max(Ms, lb), ub); f nn_mse(Ms, Xva, Yva, dims); if f fit(i), pop(i,:) Ms; fit(i) f; end end [bestVal, idx] min(fit); if bestVal gBestVal gBestVal bestVal; gBest pop(idx, :); end end end配套的适应度函数function mse nn_mse(theta, Xva, Yva, dims) % 把个体还原成权重前向计算验证集 MSE W1 reshape(theta(1:dims(1)), 12, 6); b1 theta(dims(1)1 : sum(dims(1:2))); W2 reshape(theta(sum(dims(1:2))1 : sum(dims(1:3))), 6, 12); b2 theta(sum(dims(1:3))1 : sum(dims(1:4))); W3 reshape(theta(sum(dims(1:4))1 : sum(dims(1:5))), 1, 6); b3 theta(sum(dims(1:5))1 : sum(dims(1:6))); a1 tanh(Xva * W1 b1); a2 tanh(a1 * W2 b2); pred a2 * W3 b3; mse mean((pred - Yva).^2); end两个函数要放在同一个cso_bp.m文件里或者都定义在同一个脚本末尾。横向交叉里的randperm(M)把种群顺序打乱后两两配对保证每代配对关系都不同min(max(Ms, lb), ub)是边界约束把越界分量压回 [-5,5]。纵向交叉里rand() 0.5控制参与概率也就是说每次迭代只有一半个体做纵向交叉和参数表的Vc 0.5对应。4.4 CSO-BP 关键参数表参数常用范围本次取值取值依据种群规模 M10~4030个体太少容易丢失搜索宽度太多则单代评估成本上升最大迭代次数30~10050负荷预测验证集 MSE 通常在 30 代后进入缓慢下降区横向交叉概率 Hc1每代执行1横向交叉是主要搜索动力不建议调小纵向交叉概率 Vc0.2~0.80.5过大破坏已有优秀维度组合过小失去解耦作用权重边界[-5,5] 或 [-10,10][-5,5]输入输出归一化后大权重容易导致饱和适应度函数验证集 MSE/MAPE验证集 MSEMSE 对大残差敏感利于剔除尖峰段坏解5. 验证纵横交叉负荷预测模型的三个门槛与实际技巧5.1 用一组独立数据做最终判决CSO 优化结束后把最优个体gBest还原成权重在从未参与过适应度计算的测试集上跑一次前向再反归一化回真实量纲pred_norm forward_net(gBest, Xte_n, dims); pred_load mapminmax(reverse, pred_norm, psy); MAPE mean(abs(pred_load - Yte_raw) ./ Yte_raw) * 100; RMSE sqrt(mean((pred_load - Yte_raw).^2));Xte_n是用第 3 章保存的psX归一化后的测试输入Yte_raw是测试集原始负荷值。这里的forward_net可以直接从nn_mse里把前向计算那段抽出来返回值改成pred。只有这份测试集误差才有资格和 BP 基线做对比拿验证集误差对比两边都不可信。5.2 三个容易翻车的地方第一随机 K 折不能直接用。负荷数据是时间序列随机抽样会把未来信息混进训练集优化时看起来误差很低换到真实预测第二天就露馅。第二归一化参数必须复用训练集保存下来的psX、psy不能用测试集重新计算否则预测值还原后会带进测试集的统计信息。第三CSO 的适应度函数里一旦用了测试集模型就等于提前看到了考试答案后期调参全部失去意义。5.3 后期调参的两个方向当纵横向交叉优化的结果在训练集和验证集都低、测试集偏高时优先把纵向交叉概率Vc从 0.5 降到 0.3让维度解耦动作更克制而不是盲目增加迭代次数。当结果整体偏高、曲线平段贴得不错但尖峰跟不上时把种群规模 M 加到 50维持横向交叉的搜索宽度。负荷预测的尖峰段通常由极端温度触发这类样本在数据集中占比小只有靠横向交叉不断在父代周围制造差分扰动才有机会让权重组合覆盖到这类稀疏样本。最后把反归一化后的预测曲线和真实曲线叠在一起早晨尖峰与晚高峰两侧的贴合程度就是这套模型在你这套数据上真实能力的直观体现。本文还有配套的精品资源点击获取
返回列表