首页 / 资讯中心 / 文章详情

MATLAB+RBF神经网络电力负荷预测完整搭建指南

MATLAB+RBF神经网络电力负荷预测完整搭建指南 ★ FEATURED ARTICLE
电力负荷预测这事儿外行看着就是一张Excel表内行知道它是配电站调度、设备检修、容量规划的地基。之前有位老师傅每天靠经验估第二天负荷估得准不准全看手感遇到天气突变经常被打脸。后来我给他搭了一套MATLAB加RBF神经网络的预测脚本Excel表格拖进去几分钟出来一条次日负荷曲线误差肉眼可见地降下来。今天这篇文章就是把整套搭建过程从零拆开讲数据怎么整理、代码怎么写、参数怎么调、坑怎么躲一步一步走完保证你能复现。1. 电力负荷预测为什么选RBF神经网络1.1 负荷预测难点到底在哪电力负荷不是一条平稳曲线它有明显的周期性一天之内有早晚高峰工作日和周末形态不一样冬夏两季又有完全不同的用电规律。更麻烦的是它还受气温、降水、突发活动等外部因素干扰非线性程度很高。你很难用一条简单的数学公式去描述明天下午三点这个台区大概吃多少电。传统的线性回归在这种场景下非常吃力因为负荷与影响因素之间根本不是线性关系。自回归移动平均类模型能抓住一部分时间序列规律但遇到强非线性片段就露馅。所以这类预测任务天然适合神经网络来做尤其是能处理高维非线性映射的网络结构。1.2 RBF的逼近能力从哪来径向基函数神经网络是一种三层前馈网络输入层不做加工隐层每个神经元对应一个径向基函数中心输出层对隐层输出做线性加权。它常用的激活函数是高斯函数样本离中心越近神经元输出越大离得越远就指数级衰减这就是局部响应特性。关键在于输出层是线性的。中心一旦确定输出权重通过最小二乘法一次求出来不需要像BP那样反复迭代反向传播。配合万能逼近定理只要隐层神经元数量够RBF能以任意精度拟合连续函数。这意味着它既能表达负荷曲线的复杂形态又不会让训练过程慢到让人失去耐心。1.3 和BP、LSTM对比RBF适合什么场景BP网络是全局逼近每个权重影响整个输出空间隐层节点数得靠猜训练容易陷进局部最优。LSTM在长序列依赖上确实强但数据量少于几万条时优势不明显而且训练耗时、超参数多对只想快速上线一个预测脚本的工程场景来说属于杀鸡用牛刀。RBF的好处是训练快、参数少、隐层结构还能自动增长。数据量几千到几万条的负荷序列跑一次训练几乎就是几秒钟的事。MATLAB的newrb函数采用每轮增加一个隐层神经元的策略哪里的误差大就选哪里放中心自动决定网络复杂度省掉了手动试隐层尺寸的功夫。如果你面对的是一份Excel历史负荷表想尽快看到靠谱的预测曲线RBF是性价比极高的选择。2. 数据准备Excel表格怎么整理才不拖后腿2.1 表格格式建议与读取代码预测模型吃的是数字矩阵但实际工作中拿到的Excel经常五花八门。最省心的格式是两张表头A列时间戳B列负荷值。时间戳格式尽量统一比如都用2025-03-01 00:00:00别有的行写日期、有的行写纯数字。采集间隔也要一致15分钟一个点就全是15分钟混着间隔会让滑动窗口构造样本时错位。读取用readtable就够代码只有一行data readtable(load_data.xlsx); load_series data{:, 2}; % 假设负荷在第二列如果读出来发现负荷列全是NaN优先检查是不是Excel文件里还有隐藏的工作表或者表头下面有多余的空行。也可以用xlsread(load_data.xlsx, 1, B:B)指定工作表和列范围这种写法更直接不容易被表头干扰。2.2 缺失值和异常值必须提前清掉真实采集数据几乎没有一条干干净净的序列。采集终端断线、通讯故障、人工补录出错都会留下缺口和毛刺。newrb对NaN很敏感训练集里只要有一个NaN整个网络可能直接建不出来。缺失值建议用fillmissing(load_series, linear)做线性插值简单且对负荷这类平滑曲线效果好。异常值处理则要小心别把真实的负荷峰谷给削掉。我常用的办法是计算相邻差分找出那些变化幅度远超正常水平3倍的孤立点用前后两个点的均值替换。负荷突变更常见的情况是某一天某设备集中投切曲线会有一个大台阶这种不算毛刺是真实物理事件处理时不要误伤。2.3 滑动窗口把时间序列变成监督学习样本神经网络预测本质上是监督学习给模型一组输入特征让它学习对应的输出。时间序列本身没有输入输出结构需要自己构造。做法是滑动窗口用前in_len个时刻的负荷作为特征预测后out_len个时刻的负荷。采样间隔15分钟时in_len8意味着用前2小时数据预测未来15分钟这个窗口覆盖了负荷短时惯性效果比较稳。out_len1对应单步预测代码最简单。构造样本的循环如下in_len 8; out_len 1; N length(load_series); sample_count N - in_len - out_len 1; X zeros(sample_count, in_len); Y zeros(sample_count, out_len); for i 1:sample_count X(i, :) load_series(i : i in_len - 1); Y(i, :) load_series(i in_len : i in_len out_len - 1); end每条样本的前8个点与后1个点不能重叠滚动步长是1也就是每往后挪一个采样点就产生一条新样本。数据量就这么扩充起来了。2.4 数据集划分和归一化的顺序绝对不能错很多新手栽在数据划分上直接把所有样本随机打乱再切训练测试集。对时序预测这是大忌因为未来信息会被混进训练集测试时模型等于开卷考试指标好看但没有实际意义。必须按时间先后顺序切前85%训练、后15%测试才算合规。归一化同样有顺序问题。正确做法是先切分再只对训练集统计min/max生成归一化器测试集用同一套参数做变换。如果先对整个矩阵归一化再切分测试集的统计信息就泄漏进了训练过程。原因很简单归一化参数来自全体数据模型在训练时已经间接知道了未来的数据范围。正确写法看第3部分的完整脚本我会把每一步的先后顺序标清楚。3. 核心环节MATLAB搭建RBF网络的完整代码拆解3.1 工具箱准备运行这段脚本需要MATLAB的Deep Learning Toolbox老版本叫Neural Network Toolbox。新版MATLAB中newrb这个经典接口仍然保留安装工具箱后直接用就行不需要额外配置。如果是比较新的版本注意函数可能在工具箱雷达中标记为recommended但不影响调用。3.2 可以直接抄的完整脚本下面这整段代码就是我从零搭建时用的版本数据格式是Excel两列时间戳加负荷值。你复制下来以后只需要改文件名、窗口大小、spread参数这三个地方。%% 电力负荷预测MATLAB RBF神经网络完整脚本 % 数据格式Excel 两列A列为时间戳B列为负荷值单位kW % 运行前准备安装 Deep Learning Toolbox / Neural Network Toolbox clc; clear; close all; %% 1. 读取Excel数据 filename load_data.xlsx; % 改成你的文件路径 data readtable(filename); time_col data{:, 1}; % 时间列仅用于画图 load_series data{:, 2}; % 负荷列 %% 2. 简单清洗 % 缺失值线性插值 load_series fillmissing(load_series, linear); % 异常值剔除变化幅度超过正常中位数3倍的孤立点用前后均值替换 diff_series abs(diff(load_series)); threshold 3 * median(diff_series); idx find(diff_series threshold); for k 1:length(idx) pos idx(k) 1; if pos length(load_series) load_series(pos) (load_series(pos-1) load_series(pos1)) / 2; end end %% 3. 滑动窗口构造训练样本 in_len 8; % 用前8个采样点2小时作为输入 out_len 1; % 预测下一个采样点 N length(load_series); sample_count N - in_len - out_len 1; X zeros(sample_count, in_len); Y zeros(sample_count, out_len); for i 1:sample_count X(i, :) load_series(i : i in_len - 1); Y(i, :) load_series(i in_len : i in_len out_len - 1); end %% 4. 按时间顺序划分训练/测试集 train_ratio 0.85; train_num floor(sample_count * train_ratio); X_train X(1:train_num, :); Y_train Y(1:train_num, :); X_test X(train_num1:end, :); Y_test Y(train_num1:end, :); %% 5. 归一化只统计训练集的min/max [X_train_norm, ps_in] mapminmax(X_train, 0, 1); [Y_train_norm, ps_out] mapminmax(Y_train, 0, 1); X_test_norm mapminmax(apply, X_test, ps_in); %% 6. 创建并训练RBF神经网络 goal 0.01; % 均方误差目标 spread 2.0; % 径向基函数扩展常数最重要的参数 max_neurons 100; % 最大隐层神经元数 net newrb(X_train_norm, Y_train_norm, goal, spread, max_neurons); %% 7. 模型测试与反归一化 Y_pred_norm sim(net, X_test_norm); Y_pred mapminmax(reverse, Y_pred_norm, ps_out); Y_pred Y_pred(:); %% 8. 评估指标 mae mean(abs(Y_test - Y_pred)); rmse sqrt(mean((Y_test - Y_pred).^2)); mape mean(abs((Y_test - Y_pred) ./ max(Y_test, 1))) * 100; sst sum((Y_test - mean(Y_test)).^2); sse sum((Y_test - Y_pred).^2); r2 1 - sse / sst; fprintf(MAE %.4f kW\n, mae); fprintf(RMSE %.4f kW\n, rmse); fprintf(MAPE %.4f %%\n, mape); fprintf(R2 %.4f\n, r2); %% 9. 画图 figure; plot(Y_test, b, LineWidth, 1); hold on; plot(Y_pred, r--, LineWidth, 1); legend(实测负荷, RBF预测); xlabel(测试样本序号); ylabel(负荷/kW); title(电力负荷预测结果对比); grid on;这段代码跑通后输出窗口会打印出误差指标图形窗口会显示一条蓝色实测曲线和一条红色预测曲线。两条线贴合程度越高模型效果越好。3.3 newrb函数参数背后到底在算什么newrb(P, T, goal, spread, MN)五个参数逐个说清楚你调起来才有方向。P和T分别是归一化后的输入矩阵和目标矩阵注意格式矩阵的每一列是一个样本每一行是一个特征维度所以上面代码里输入都要转置。goal是网络要逼近的均方误差目标不是越小越好之后会专门讲。spread是径向基函数的扩展常数决定高斯函数的辐射半径。MN是隐层神经元数量上限。newrb每增加一个神经元就重新计算一次输出权重直到达到goal或神经元数量到上限。newrb训练过程中命令窗口会不断打印当前神经元数和训练误差这不是报错。看到误差持续下降然后停在某个值附近很正常说明网络规模已到收敛点。如果打印信息刷了很久都没停多半是goal设得太低把期望拉回0.01到0.05这个区间即可。3.4 仿真输出与反归一化测试阶段用sim(net, X_test_norm)得到的是归一化空间的预测值必须用之前保存的ps_out做逆变换才能得到真实量纲的负荷。mapminmax(reverse, Y_pred_norm, ps_out)这一行就是在做这件事。有一点容易漏sim返回的矩阵可能和你预期维度不同。输入矩阵每一列是一个样本时输出矩阵的每一列是对应样本的预测值所以要加一句Y_pred Y_pred(:)把它拉成一维向量再和Y_test直接做减法算误差。4. 模型训练完怎么验收指标计算与结果解读4.1 四个指标代表什么含义误差指标不能只看一个我一般同时报四个MAE是平均绝对误差单位是kW直观体现平均偏离多少。RMSE是均方根误差因为先平方再开方对大误差特别敏感能反映预测曲线的稳定性。MAPE是平均绝对百分比误差通常报成百分数业务上最好理解。R2是决定系数接近1表示模型解释了大部分数据波动接近0表示预测基本等于瞎猜。无论用哪个指标都要和负荷本身的量级对比。如果台区平均负荷是5000kWRMSE能做到80kWMAPE大概1%已经够满足日常调度参考。但如果RMSE是500kW曲线估计连峰谷都跟不住需要回头调参数加特征。4.2 画图看偏差曲线重叠还不够预测曲线和实测曲线重叠良好只是第一步。我习惯再画一张残差图把Y_test - Y_pred画出来观测残差是否围绕零轴均匀分布。如果残差有明显的正负交替趋势比如低谷时段预测偏高、高峰时段预测偏低说明模型学到的规律还不够可能缺少温度或者时刻特征。还有一种常见形态是残差在某个时间区间突然持续增大。这时候检查测试集时间范围是不是刚好跨了节假日。训练集全是工作日形态模型没见过节假日负荷测试集一跨到节假日误差立刻暴增。解决办法是训练集至少覆盖一个完整自然周并且把星期特征加进去。4.3 一种容易误判的滞后现象用前8个点预测下一个点时某些模型会偷懒学成最后一个点的值就是预测值表现为预测曲线整体比实测晚一步峰值和谷值都偏移了一个采样点。这种滞后在曲线上看着很贴合但业务上不可接受因为预测的永远是上一刻的负荷。判断滞后很简单计算预测值和测试集前一个时刻实测值的相关系数如果这个相关系数比预测值和同时刻实测值的相关系数还高基本可以断定模型退化成一步滞后。解决办法是调整样本结构比如增大in_len或者加入更多跨天的远期特征让网络意识到目标值不等于历史最近点。5. RBF参数调优与踩坑实录5.1 spread是灵魂参数newrb里最值得反复打磨的是spread。它控制高斯函数的径向作用范围。spread太小每个隐层神经元只对训练样本附近极小区域响应测试样本稍有偏移就误差爆炸这是过拟合。spread太大所有神经元响应区域重叠严重输出曲线被磨得太平峰谷根本预测不出来。我的做法是对spread做扫描。从0.5到5步长0.5每个值训练一次记录测试集RMSE选RMSE最低的点。下面这段代码放在脚本第6步的位置循环训练后画一条RMSE随spread变化的曲线spread_list 0.5:0.5:5; rmse_list zeros(size(spread_list)); for s_idx 1:length(spread_list) net_tmp newrb(X_train_norm, Y_train_norm, goal, spread_list(s_idx), max_neurons); pred_tmp sim(net_tmp, X_test_norm); pred_tmp mapminmax(reverse, pred_tmp, ps_out); rmse_list(s_idx) sqrt(mean((Y_test - pred_tmp(:)).^2)); fprintf(spread%.1f, RMSE%.4f\n, spread_list(s_idx), rmse_list(s_idx)); end实测中spread在2到3之间往往表现稳定而且对噪声容忍度更高。你可以把最终选中的spread值填回主脚本作为正式模型参数。5.2 goal与神经元数量怎么平衡goal是均方误差的优化目标理论上设得越小训练误差越小但代价是隐层神经元数量暴增网络复杂度上升泛化能力反而下降。这和所有机器学习模型一样训练误差低不代表测试误差低。我用0.01配合max_neurons100通常能在拟合度和复杂度之间拿到平衡点。max_neurons设100是为了限制训练时间。如果数据量有好几万条newrb每增加一个神经元就要重新求解一次输出权重训练会明显变慢。在实际项目中超过200个神经元的RBF网络已经很容易过拟合所以不要无脑调大上限。5.3 我踩过的三个坑第一个坑是归一化顺序搞错。一开始我图省事把整个样本矩阵构造出来后先归一化再切训练测试结果测试集RMSE漂亮得离谱后来才发现测试集的min/max信息已经参与训练了。改回先切分再归一化之后指标立刻真实了很多。第二个坑是测试集撞上节假日。有次模型训练数据是连续两周的工作日数据测试集正好从周五晚上开始预测值在周六早上明显偏离实测。后来我把训练集拉长到包含完整自然周并且加入时间特征这个问题才解决。第三个坑是Excel隐藏的脏数据。某次读表后没有检查整个负荷序列最后几百个点全是0fillmissing对0不处理导致样本构造和训练全部正常但预测值在对应区段直接掉到谷底。从那以后我读表后第一件事是plot(load_series)看全貌再处理异常。5.4 进阶方向从能跑变成好用基础脚本跑通后往下走有几个性价比很高的提升方向。第一个是加时刻编码。把每个采样点在一天中的位置映射成sin和cos两个数值比如15分钟粒度一天96个点第i个点的编码是sin(2*pi*i/96)和cos(2*pi*i/96)这样网络能识别昼夜节律。这个改动对峰值预测的提升非常明显。第二个是加外部变量。把预测时刻的气温、湿度、星期类型作为额外输入列接到X的末尾输入维度从8变成11或者更多。温度对夏季空调负荷影响大加上之后MAPE通常能再降零点几个百分点。第三个是预测多步。out_len从1改成4或24一次输出未来1小时或1天的负荷曲线。注意多步预测时输出维度变大网络需要更多隐层神经元训练时间也会上升建议配合max_neurons上限一起调整。我现在做完一套负荷预测脚本已经习惯先把原始数据画出来看形状再跑一遍默认参数看残差最后根据残差特征决定加特征还是调spread。RBF不是最花哨的算法但它在Excel数据流场景下确实是少折腾、出结果快、解释起来也顺手的方案。如果你正在用MATLAB做负荷预测建议先拿这套代码完整跑通一次再逐步把特征和结构加厚。
阅读完成 · 觉得有帮助?
咨询建站