拓冰建站拓冰建站
首页 / 资讯中心 / 正文

MATLAB R2025b实战:LSTM-GRU混合网络实现光伏功率时间序列预测数据预处理、模型原理、完整代码与误差评估

图 1 LSTM-GRU 光伏功率时间序列预测整体主题示意图MATLAB R2025b实战LSTM-GRU混合网络实现光伏功率时间序列预测数据预处理、模型原理、完整代码与误差评估摘要本文围绕光伏功率单步时间序列预测给出一套基于 MATLAB R2025b 的 LSTM-GRU 混合网络实现方案。文章从光伏功率的随机性、间歇性和非线性出发解释 LSTM 与 GRU 的互补关系完成数据质量控制、按时间切分、仅使用训练段统计量进行标准化、滑动窗口构造、网络训练、反标准化与多指标评估并提供可直接改造到真实电站数据的完整 MATLAB 示例代码。重点处理了时间序列数据泄漏、旧版训练接口、输入维度方向、目标反标准化以及夜间零功率导致 MAPE 失真等常见问题。关键词MATLABLSTMGRU光伏功率预测时间序列预测深度学习trainnet滑动窗口光伏功率预测的难点不在于“把历史数据送进神经网络”这一动作本身而在于如何同时处理长期周期、短期天气扰动、数据质量、时间依赖和工程可复现性。对于固定采样间隔的光伏场站数据LSTM-GRU 混合模型可以把 LSTM 的长期记忆能力与 GRU 的紧凑动态建模能力串联起来形成“先提取长期时序结构再聚合局部动态变化”的预测链路。本文任务定义为 sequence-to-one 回归使用过去 lookBack 个时间步的多变量数据预测下一时刻光伏有功功率。默认输入特征为 Power、Temperature、Irradiance实际项目可继续加入组件温度、风速、湿度、云量、太阳高度角和数值天气预报等变量。训练/验证/测试按时间先后切分不采用随机打乱切分避免未来信息进入训练过程。标准化参数只由训练段计算再应用到验证段和测试段目标功率单独保存均值与标准差用于反标准化。MATLAB R2025b 推荐使用 trainnet minibatchpredict旧的 trainNetwork 工作流仍可能运行但当前官方文档已标注为“不推荐”。光伏夜间真实功率大量为 0传统 MAPE 容易出现极端值因此正文同时给出 RMSE、MAE、WMAPE 和 R²并把 MAPE 作为可选的“日间指标”。图 2 光伏功率预测的端到端实现流程光伏发电输出受太阳辐照度、环境温度、组件温度、云层遮挡、阵列倾角、污染程度以及设备运行状态等多因素共同影响。晴天条件下功率曲线通常具有明显的日周期和相对平滑的上升—峰值—下降结构多云天气下局部云团快速移动会造成辐照度骤降或骤升功率序列随之产生高频震荡、尖峰和短时阶跃。这意味着预测模型既要记住“慢变量”例如一天中的时段、连续晴阴天气过程和前一时段的惯性趋势又要对“快变量”敏感例如几分钟内的云遮挡和辐照突变。单一线性回归或传统自回归模型往往难以充分表达这种非线性耦合单一深度循环层虽然能够拟合时序关系但在长期依赖、参数规模、训练速度和局部响应之间仍存在取舍。工程目标预测精度不是唯一目标。一个可落地的光伏预测模型还应满足数据链路清晰、训练过程可复现、对未知时间段有稳定泛化能力、误差指标可解释并且能在储能调度、功率计划和微电网能量管理中被持续调用。LSTMLong Short-Term Memory在普通 RNN 的隐藏状态之外引入细胞状态并通过遗忘门、输入门和输出门控制信息保留与更新。其核心价值是缓解长序列反向传播中的梯度消失使模型可以在较长时间范围内保留关键历史信息。对光伏序列而言日周期、持续晴天/阴天过程以及功率爬坡趋势都具有明显的长期依赖。LSTM 的典型门控关系符号化表达f_t sigmoid(W_f [h_(t-1), x_t] b_f)i_t sigmoid(W_i [h_(t-1), x_t] b_i)C~_t tanh(W_c [h_(t-1), x_t] b_c)C_t f_t .* C_(t-1) i_t .* C~_to_t sigmoid(W_o [h_(t-1), x_t] b_o)h_t o_t .* tanh(C_t)GRUGated Recurrent Unit把 LSTM 的部分门控结构合并为更新门和重置门参数量通常更少、计算路径更紧凑。对于局部云遮挡、短时辐照变化和功率快速波动GRU 可以在较低参数复杂度下对近邻状态进行更新因此适合作为 LSTM 后的动态聚合层。GRU 的典型门控关系符号化表达z_t sigmoid(W_z [h_(t-1), x_t] b_z)r_t sigmoid(W_r [h_(t-1), x_t] b_r)h~_t tanh(W_h [r_t .* h_(t-1), x_t] b_h)h_t (1-z_t) .* h_(t-1) z_t .* h~_t本文使用 LSTM 输出完整序列再交给 GRU 输出最后一个时刻的高层表示。这样做的直觉是LSTM 先在每个时间步上形成包含长期记忆的表示GRU 再对这些高层时序特征进行二次动态压缩最后把融合后的表示映射为下一时刻功率。它不是保证优于单模型的“万能结构”但提供了一种清晰的长期—短期分工。最终是否优于单 LSTM、单 GRU 或 TCN仍应通过相同数据切分下的消融实验验证。图 3 LSTM-GRU 混合网络结构与功能分工项目本文约定说明MATLABR2025b本文代码按 R2025b 可用流程编写工具箱Deep Learning Toolbox用于 LSTM、GRU、trainnet 与训练监控任务类型sequence-to-one 回归历史窗口预测下一时刻功率输入字段Time / Power / Temperature / Irradiance字段名可按实际数据表修改默认窗口lookBack 24如果采样周期为 1 h则代表过去 24 h若为 15 min则只代表过去 6 h数据划分70% / 15% / 15%严格按时间顺序切分优化器Adam初始学习率 1e-3并设置分段衰减评估指标RMSE / MAE / WMAPE / R²MAPE 对零功率敏感因此不作为唯一指标需要特别注意lookBack 的物理含义由采样间隔决定。代码中的 24 只是“24 个时间步”不能脱离采样频率直接理解为“24 小时”。如果电站数据每 15 分钟采样一次希望建模过去 24 小时则 lookBack 应设置为 96。版本说明在当前 MathWorks 文档中trainNetwork 已标记为“不推荐”trainnet 用于新式深度学习训练流程。本文不使用 R2026a 才新增的 NormalizeTargets / inverseNormalizationLayer而是手动对目标功率进行训练段标准化因此可保持 R2025b 兼容性。时序模型对数据顺序非常敏感。原始 CSV 应先按照 Time 升序排列再对缺失值和异常点处理。本文对功率使用滑动中位数规则识别异常点把异常值置为 NaN 后再线性插值并对序列首尾使用最近值补齐。这样比“直接对异常值子集调用 fillmissing”更可靠因为异常值本身并不是缺失值。数据质量控制示例data readtable(pv_power_data.csv);data sortrows(data,Time);power fillmissing(data.Power,linear,EndValues,nearest);temp fillmissing(data.Temperature,linear,EndValues,nearest);irr fillmissing(data.Irradiance,linear,EndValues,nearest);idxOut isoutlier(power,movmedian,25);power(idxOut) NaN;power fillmissing(power,linear,EndValues,nearest);power max(power,0);irr max(irr,0);这是时间序列建模中最常见、也最隐蔽的数据泄漏之一。如果先使用全量数据计算均值、标准差、最大值或最小值再切分训练集和测试集那么测试时段的统计信息已经提前进入训练数据的尺度变换。模型虽然没有直接看到测试标签但训练过程已经间接获取未来分布信息最终评估会偏乐观。正确流程应当是先确定训练样本覆盖的原始时间区间只用这部分原始数据计算标准化参数然后把同一组参数应用到验证和测试时段。目标变量也要独立保存自己的均值和标准差不能错误复用输入特征的归一化参数。图 4 按时间切分与滑动窗口构造原则设输入特征维数为 F窗口长度为 L。第 i 个样本使用 X[i : iL-1] 作为输入序列目标为 y[iL]。对于 trainnet 的常规向量序列输入每个 cell 中建议组织为“时间步 × 特征”矩阵即 L × F。这样与 sequenceInputLayer 的默认序列数据布局保持一致。滑动窗口样本构造for i 1:numSamplesXCell{i} Xn(i:ilookBack-1,:); % 时间步 × 特征YVec(i) yn(ilookBack); % 下一时刻功率end层配置作用sequenceInputLayernumFeatures接收多变量序列输入lstmLayer64, OutputModesequence提取长期依赖并向下一层输出完整序列dropoutLayer0.2降低过拟合风险gruLayer32, OutputModelast聚合高层序列并输出最后状态fullyConnectedLayer16压缩和重组时序特征reluLayer—增加非线性表达dropoutLayer0.1进一步正则化fullyConnectedLayer1输出单一连续功率值64 和 32 并不是固定最优值而是中等规模的起点。隐藏单元过少可能欠拟合过多则增加训练成本和过拟合风险。更规范的做法是在固定数据划分下对隐藏单元、窗口长度、学习率、Dropout 和 MiniBatchSize 做网格搜索、贝叶斯优化或实验管理而不是只报告一次偶然结果。下面代码可以保存为 pv_lstm_gru_forecast.m。它假设 CSV 至少包含 Time、Power、Temperature、Irradiance 四列如字段名不同请在读取位置对应修改。代码采用训练段统计量标准化、时间顺序切分、LSTM-GRU 混合网络、早停以及多指标评估。完整脚本pv_lstm_gru_forecast.m%% LSTM-GRU 光伏功率单步预测MATLAB R2025bclc; clear; close all;rng(42); % 保证可复现%% 1. 读取与检查数据data readtable(pv_power_data.csv);requiredVars [Time,Power,Temperature,Irradiance];assert(all(ismember(requiredVars,string(data.Properties.VariableNames))), ...数据表必须包含 Time、Power、Temperature、Irradiance 四列。 );data sortrows(data,Time);power fillmissing(data.Power,linear,EndValues,nearest);temp fillmissing(data.Temperature,linear,EndValues,nearest);irr fillmissing(data.Irradiance,linear,EndValues,nearest);% 使用滑动中位数识别功率异常点再进行插值修复idxOut isoutlier(power,movmedian,25);power(idxOut) NaN;power fillmissing(power,linear,EndValues,nearest);% 物理约束光伏功率与辐照度不应为负power max(power,0);irr max(irr,0);Xraw [power,temp,irr];yraw power;%% 2. 定义窗口与时间顺序数据划分lookBack 24; % 24 个时间步物理时长 lookBack × 采样间隔N size(Xraw,1);numSamples N - lookBack;assert(numSamples 100,有效样本过少请检查数据长度或减小 lookBack。);nTrain floor(0.70 * numSamples);nVal floor(0.15 * numSamples);nTest numSamples - nTrain - nVal;% 最后一个训练样本的输入使用到此原始时刻trainInputEnd nTrain lookBack - 1;% 训练目标对应的原始索引trainTargetIdx (lookBack1):(lookBacknTrain);%% 3. 仅使用训练段统计量进行标准化避免数据泄漏muX mean(Xraw(1:trainInputEnd,:),1,omitnan);sigmaX std(Xraw(1:trainInputEnd,:),0,1,omitnan);sigmaX(sigmaX eps) 1;Xn (Xraw - muX) ./ sigmaX;muY mean(yraw(trainTargetIdx),omitnan);sigmaY std(yraw(trainTargetIdx),0,omitnan);if sigmaY epssigmaY 1;endyn (yraw - muY) ./ sigmaY;%% 4. 构造 sequence-to-one 滑动窗口样本numFeatures size(Xn,2);XCell cell(numSamples,1);YVec zeros(numSamples,1);for i 1:numSamplesXCell{i} Xn(i:ilookBack-1,:); % 时间步 × 特征YVec(i) yn(ilookBack); % 下一时刻标准化功率endXTrain XCell(1:nTrain);YTrain YVec(1:nTrain);XVal XCell(nTrain1:nTrainnVal);YVal YVec(nTrain1:nTrainnVal);XTest XCell(nTrainnVal1:end);YTest YVec(nTrainnVal1:end);%% 5. 搭建 LSTM-GRU 混合网络layers [sequenceInputLayer(numFeatures)lstmLayer(64,OutputModesequence)dropoutLayer(0.20)gruLayer(32,OutputModelast)fullyConnectedLayer(16)reluLayerdropoutLayer(0.10)fullyConnectedLayer(1)];%% 6. 训练配置itersPerEpoch max(1,ceil(nTrain/64));validationFrequency itersPerEpoch;options trainingOptions(adam, ...MaxEpochs150, ...MiniBatchSize64, ...InitialLearnRate1e-3, ...LearnRateSchedulepiecewise, ...LearnRateDropPeriod50, ...LearnRateDropFactor0.5, ...GradientThreshold1, ...L2Regularization1e-4, ...Shuffleevery-epoch, ...ValidationData{XVal,YVal}, ...ValidationFrequencyvalidationFrequency, ...ValidationPatience8, ...OutputNetworkbest-validation, ...Metricsrmse, ...Plotstraining-progress, ...Verbosefalse);%% 7. 使用 trainnet 训练回归网络net trainnet(XTrain,YTrain,layers,mse,options);%% 8. 测试集预测与反标准化YPredN minibatchpredict(net,XTest,MiniBatchSize64);YPredN double(YPredN(:));YTestN double(YTest(:));YPred YPredN * sigmaY muY;YTrue YTestN * sigmaY muY;% 功率物理约束可按项目实际情况保留或取消YPred max(YPred,0);%% 9. 误差指标err YPred - YTrue;RMSE sqrt(mean(err.^2));MAE mean(abs(err));WMAPE sum(abs(err)) / max(sum(abs(YTrue)),eps) * 100;R2 1 - sum(err.^2) / max(sum((YTrue-mean(YTrue)).^2),eps);% 日间 MAPE排除接近零功率的时刻避免夜间 0 值放大百分比误差threshold max(1e-6,0.01*max(abs(YTrue)));idxDay abs(YTrue) threshold;if any(idxDay)MAPE_day mean(abs(err(idxDay)./YTrue(idxDay))) * 100;elseMAPE_day NaN;endfprintf(RMSE %.6f\n,RMSE);fprintf(MAE %.6f\n,MAE);fprintf(WMAPE %.3f %%\n,WMAPE);fprintf(Day MAPE %.3f %%\n,MAPE_day);fprintf(R^2 %.6f\n,R2);%% 10. 结果可视化figure(Color,w);plot(YTrue,LineWidth,1.2); hold on;plot(YPred,LineWidth,1.2);grid on;xlabel(测试样本);ylabel(光伏功率);title(LSTM-GRU 光伏功率预测真实值与预测值);legend(真实值,预测值,Location,best);figure(Color,w);scatter(YTrue,YPred,14,filled); hold on;minV min([YTrue;YPred]);maxV max([YTrue;YPred]);plot([minV,maxV],[minV,maxV],--,LineWidth,1.2);grid on; axis equal;xlabel(真实功率);ylabel(预测功率);title(sprintf(预测散点图R^2 %.4f,R2));figure(Color,w);histogram(err,40);grid on;xlabel(预测误差);ylabel(频数);title(sprintf(误差分布RMSE %.4fMAE %.4f,RMSE,MAE));trainnet 把网络结构与损失函数分开定义回归任务直接指定 mse。这种写法与当前 Deep Learning Toolbox 的训练接口方向一致同时配合 minibatchpredict 进行批量预测。对于 R2025b 项目新代码优先采用这一工作流更有利于后续版本维护。“按时间切分”和“训练批次打乱”是两个不同层面。训练/验证/测试的边界必须保持时间先后否则未来时段会混入训练集评估失真而每个滑动窗口样本本身已经包含完整的内部时间顺序因此在无状态的 sequence-to-one 小批量训练中对训练样本顺序进行 Shuffle 通常可以改善优化过程。如果采用连续流式状态训练则需要重新审视这一设置。输入 X 是多特征矩阵目标 y 是单一功率序列两者的统计量维度和含义不同。反标准化预测值时必须使用目标变量自己的均值与标准差。如果误用输入特征的标准化参数可能直接产生维度错误或者更隐蔽地得到尺度不正确的预测结果。MAPE 的分母是真实值。光伏夜间功率为 0 或接近 0 时百分比误差会趋于无穷或被极小分母放大导致指标失去工程意义。因此本文使用 WMAPE 作为全时段百分比指标并只在真实功率高于阈值时计算日间 MAPE。RMSE 用于观察大偏差MAE 反映平均绝对误差R² 则描述整体拟合解释能力。图 5 光伏功率预测常用评价指标的侧重点观察现象可能原因建议处理训练损失持续下降验证损失先降后升过拟合提高 Dropout、增加训练数据、减小隐藏单元或启用更早的验证停止训练和验证损失都很高欠拟合或特征不足增加窗口长度、隐藏单元加入气象特征检查异常值与采样对齐晴天拟合很好多云天误差大外生天气信息不足加入云量、风速、NWP 辐照预测或更高频气象数据峰值位置对但幅值偏低模型趋向均值或极值样本不足调整损失、增加峰值样本、检查归一化与容量上限测试集明显差于验证集时间分布漂移检查季节变化、设备状态变化与训练覆盖范围MAPE 极大但曲线看起来正常夜间零功率导致分母问题改用 WMAPE / MAE或只统计日间 MAPE没有真实数据就不能负责任地给出“RMSE某个数、R²0.99”之类的固定结果。正确做法是用自己的电站数据运行脚本记录测试集指标和曲线再与单 LSTM、单 GRU、持久性预测Persistence等基线放在同一时间切分下比较。如果要证明 LSTM-GRU 的价值最好不要只展示一个模型的绝对误差而应建立基线。至少可以比较以下四组实验并确保使用完全一致的数据预处理与测试时段。模型/基线目的关注点Persistenceŷ(t1)y(t)最基本时序基线复杂模型是否真的超过“上一时刻就是下一时刻”单 LSTM验证长期记忆贡献与混合模型对比 RMSE、参数量和训练耗时单 GRU验证紧凑动态建模能力观察多云快速波动场景LSTM-GRU验证融合收益若只提升极小需要评估复杂度是否值得进一步可以对 lookBack、LSTM 隐藏单元、GRU 隐藏单元和 Dropout 做消融。例如把 lookBack 从 12、24、48、96 逐级测试观察短窗口对突变响应与长窗口对周期趋势的权衡。这样的实验比简单描述“混合网络更强”更有说服力。错误先对全量数据归一化再切分训练/测试。后果未来统计信息泄漏测试分数偏乐观。错误随机划分时间序列样本。后果训练集中混入未来时段破坏真实部署条件。错误trainnet 的 cell 序列仍按“特征 × 时间”组织却没有声明数据格式。建议常规 vector sequence 直接使用“时间 × 特征”。错误异常点识别后直接对异常值子集 fillmissing。异常值不是 NaN应先置 NaN 或使用专门的异常值填充函数。错误用输入特征的标准化设置反标准化目标功率。输入 X 和目标 y 必须独立保存尺度参数。错误仅报告 MAPE。夜间真实功率为 0 时 MAPE 会失真应配合 RMSE、MAE、WMAPE、R²。错误看到训练曲线下降就认为模型有效。必须查看完全未参与训练的测试时段并与基线模型对比。错误把 lookBack24 直接解释为 24 小时。它实际是 24 个采样点必须结合采样间隔。LSTM-GRU 适合处理有明确时间依赖、样本量中等且能够提供历史功率与气象特征的预测任务但它并不天然解决所有问题。若站点跨季节分布漂移明显、气象变量缺失、设备限功率频繁或预测跨度很长单纯依赖历史序列可能不足。多步预测把 fullyConnectedLayer(1) 改为输出未来 H 个时间点构造 sequence-to-vector 目标或使用 sequence-to-sequence 预测。引入时间特征小时、日序号、太阳高度角可采用 sin/cos 周期编码帮助模型显式理解昼夜与季节周期。引入天气预报对于未来数小时预测NWP 的未来辐照度、云量和温度往往比单纯增加历史窗口更有效。加入注意力或 TCN当窗口更长或希望增强并行计算能力时可比较 Attention、TCN、Transformer 等结构。概率预测在电网调度中除了点预测还可输出预测区间或分位数以表达不确定性。滚动更新部署后监控误差漂移按周或按月重训练避免季节变化和组件衰减造成模型失效。适用边界混合网络不是越深越好。数据规模较小、采样噪声较高或气象特征非常有限时简单模型可能更稳定。任何“模型更优”的结论都应建立在同一测试时段、同一预处理规则和可复现实验上。本文给出了一套面向 MATLAB R2025b 的 LSTM-GRU 光伏功率时间序列预测实现方案。核心并不是简单堆叠两个循环层而是建立完整、可验证的数据与模型闭环先清洗并按时间组织数据仅使用训练时段计算尺度参数再通过滑动窗口构造 sequence-to-one 样本网络中由 LSTM 提取长期时序结构GRU 聚合局部动态训练使用 trainnet 与验证早停预测后使用目标变量自己的尺度参数反标准化并通过 RMSE、MAE、WMAPE、日间 MAPE 和 R² 从不同角度评估误差。对于真实光伏场站模型性能最终取决于数据质量、采样频率、气象特征完整度、季节覆盖范围和预测跨度。建议在相同时间切分下加入 Persistence、单 LSTM 和单 GRU 基线通过消融实验确认 LSTM-GRU 的实际增益再决定是否用于储能调度、功率计划或在线预测。[1] MathWorks. trainnet — Train deep learning neural network. https://www.mathworks.com/help/deeplearning/ref/trainnet.html[2] MathWorks. trainNetwork — (Not recommended) Train neural network. https://www.mathworks.com/help/deeplearning/ref/trainnetwork.html[3] MathWorks. Sequence-to-One Regression Using Deep Learning. https://www.mathworks.com/help/deeplearning/ug/sequence-to-one-regression-using-deep-learning.html[4] MathWorks. LSTMLayer — Long short-term memory layer. https://www.mathworks.com/help/deeplearning/ref/nnet.cnn.layer.lstmlayer.html[5] MathWorks. GRULayer — Gated recurrent unit layer. https://www.mathworks.com/help/deeplearning/ref/nnet.cnn.layer.grulayer.html[6] MathWorks. trainingOptions — Options for training deep learning neural network. https://www.mathworks.com/help/deeplearning/ref/trainingoptions.html
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门