☰
MATLAB中用LSTM做短期风速预测:从数据预处理到回归模型训练避坑指南
2026/10/10 19:50:32 网站建设 项目流程

简介:这是一份基于LSTM算法在MATLAB环境下实现短期风速预测的完整代码包,面向风电、气象领域的时间序列回归任务,适合需要将深度学习应用于实际预测的工程技术人员与科研学习者。压缩包共13个文件,核心为7个.m脚本(如LSTM.m、LSTM2.m、ELM.m、elmpredict.m等,覆盖模型构建、训练、预测与对比)、3个.mat数据文件(存放训练样本及归一化参数)、2个.xlsx原始数据表(沧州气象与污染日度数据)和1个README说明文档,整体仅149KB,轻量而完整。已有1345人学习下载,说明该代码包在短期风速预测场景中具有实际参考价值。通过阅读和运行代码,读者能快速复现LSTM回归预测流程,掌握MATLAB下LSTM网络的搭建与调参思路;附带的ELM实现更便于对比不同网络在时序预测中的表现,结合真实气象数据可延伸至其他回归任务。

1. 从LSTM-regression-master.rar说起:短期风速预测在MATLAB里到底怎么做

风电场的短期风速预测,听起来是个标准的机器学习题,实际上大部分第一次下载 LSTM-regression-master.rar 的人,都会栽在同一个地方:这包跑起来不报错,但预测曲线永远比真实风速度“慢半拍”,或者测试集的 RMSE 好看得假,一放到新数据上立刻翻车。这个标题背后其实是在说一件事——用 LSTM 神经网络在 MATLAB 里做时间序列回归,而不只是搭一个分类网络。风速是一个随时间连续变化的物理量,预测下一个小时的风速,本质是回归问题,输出层只有一个神经元,损失函数是均方误差而不是交叉熵。这个 rar 包就是一套把风速数据喂给 LSTM、训练回归网络、再对短期风速做出预测的 MATLAB 实现。适合风电功率预测、气象数据分析、电力系统调度相关从业者,也适合拿它做毕业设计或课程项目的人。新手可以照步骤跑通,熟手可以借它做超参数实验和基线对比。

2. 为什么短期风速预测选LSTM:从风速序列的特性到MATLAB的回归框架

2.1 风速序列的三个特点:非线性、非平稳、强随机

短期风速预测难在哪,先说数据本身。风速序列不是一条干净的正弦波,它有三个非常明显的特征:非线性、非平稳、强随机。非线性体现在风速与气压、温度、地形之间的关系不是简单的线性叠加;非平稳体现在统计特性随时间变化,比如白天风速方差大、夜间相对平稳;强随机体现在湍流和阵风的干扰下,相邻两个采样点的风速差值可能很大。这三个特征叠加在一起,传统 ARIMA 或线性回归很容易翻车,因为它们假设序列是平稳的,或者假设自相关性是固定结构。

LSTM 神经网络能在这类问题上站稳脚跟,靠的是门控结构。LSTM 的输入门、遗忘门和输出门共同决定哪些历史信息要保留、哪些要丢弃,这个机制让网络能够自主学到“过去 6 小时风速缓慢爬升,往往预示着下一小时风速还会继续走高”这类长距离依赖。对于采样间隔为 10 分钟或 1 小时的短期风速预测,这种时间尺度上的记忆能力非常关键。相比之下,BP 神经网络和普通的 RNN 要么没有记忆能力,要么在反向传播时梯度消失,长序列训练效果差。

2.2 MATLAB深度学习工具箱:回归网络与分类网络的区别

用 MATLAB 做 LSTM 风速预测,核心工具是 Deep Learning Toolbox 里的 trainNetwork、lstmLayer、regressionLayer。很多新手一开始把 LSTM 当成分类器来搭,在网络最后接一个 softmaxLayer 和 classificationLayer,然后发现训练时 loss 降不下去,或者输出的是类型标签而不是风速数值。原因很简单:分类和回归在输出层设计上完全不同。

任务类型输出层损失函数标签形式
分类softmaxLayer + classificationLayer交叉熵离散类别标签
回归fullyConnectedLayer(1) + regressionLayer均方误差连续数值

风速预测要做的是回归,所以网络最后一层只有一个神经元,直接用 regressionLayer 告诉网络“我要拟合连续值”。除了输出层,输入数据的组织方式也不同。trainNetwork 要求时序数据以 cell 数组的形式传入,每个 cell 是一段序列,而不是直接把整条风速向量丢进去。这一点是新手最常见的卡点,也是后面第三章要重点解决的问题。MATLAB 的优势在于它把数据预处理、网络训练、结果绘图放在同一个环境下,不需要来回切换 Python 和可视化工具,尤其适合风电行业的工程师快速验证新数据。

2.3 LSTM-regression-master包:拿到手先别跑,先看这几个文件

LSTM-regression-master.rar 是一个典型的 GitHub 默认分支压缩包,名字里的 master 就是分支名。这类包通常包含主脚本、训练好的模型、原始风速数据、以及若干辅助函数和绘图脚本。我的建议是拿到手先别急着双击运行,第一件事是打开主脚本,看清楚它怎么读数据,数据格式是 .mat 还是 .xlsx,风速是单列向量还是多列特征矩阵。

如果主脚本里直接用 load 加载 .mat 文件,那下一步要确认数据是行向量还是列向量,因为 sequenceInputLayer 要求每个样本是一个列向量组成的序列。如果数据是普通矩阵,需要在脚本里先转成 cell 数组再送入网络。还要检查是否依赖 Statistics and Machine Learning Toolbox,因为部分老项目的绘图函数和数据处理函数用到了这个工具箱,缺少它会直接报 Undefined function。相比之下,mapminmax 属于 Deep Learning Toolbox,通常不会缺。环境确认完毕后,再运行主脚本,这样即使报错也能快速定位是数据问题还是工具箱问题。这套流程能帮你省下至少半小时的排错时间。

3. 数据准备:把风速序列切成LSTM能吃的样子

3.1 原始数据清理:处理NaN和毛刺

真实风电场的测风塔数据远没有测试数据干净。传感器故障、通讯中断、冻雨覆盖,都会让风速序列出现缺失值和突变毛刺。如果这些数据直接送进 LSTM,训练过程中 loss 很可能变成 NaN,或者模型被个别异常点带偏。清理数据是整套流程的地基,不要省略。

% 读取风速时间序列,单列向量,单位 m/s wind = load("wind_speed.mat").wind; t = (1:length(wind))'; % 处理缺失值:用前后有效时刻线性插值填充 missIdx = isnan(wind); if any(missIdx) wind(missIdx) = interp1(t(~missIdx), wind(~missIdx), t(missIdx), 'linear'); end % 用3倍标准差检测毛刺,毛刺点用中值滤波替换,窗口长度取5 mu = mean(wind); sigma = std(wind); spikeIdx = abs(wind - mu) > 3 * sigma; wind(spikeIdx) = medfilt1(wind, 5);

interp1 在这里的作用是用已知时刻的风速线性估算缺失时刻的风速,比用全局均值填充更贴近风速的变化趋势。中值滤波窗口长度取 5,意思是每个点用自己的前两个、后两个原始值的中位数代替,能有效削平单点毛刺,同时尽量保留风速的真实波动。需要提醒的是,不要做多次平滑或使用过大窗口,否则风速序列的高频细节被抹掉,预测结果会变得过度平滑,看起来误差小了,实际上没有抓住真实变化。

3.2 归一化:为什么风速预测必须做归一化

LSTM 内部使用 tanh 和 sigmoid 激活函数,这两种激活函数在输入绝对值过大时,梯度会趋于饱和,网络收敛极慢甚至不收敛。风速原始数值通常在 0 到 25 m/s 之间,如果不做归一化,LSTM 的输入门和遗忘门很难在这个量级上做出有效响应。常见做法是用 mapminmax 把风速映射到 0 到 1 区间,用公式 x' = (x - xmin) / (xmax - xmin)。

一个关键细节是归一化的时机。很多人对整条风速序列先做归一化,再切训练集和测试集,这在时间序列预测里会造成数据泄露。因为测试集的统计信息在训练时已经被模型间接看到,测试误差会被低估。正确做法是先按时间顺序切分,再对训练集计算归一化参数,最后用同一组参数映射测试集。

trainRatio = 0.8; trainLen = floor(length(wind) * trainRatio); trainData = wind(1:trainLen); testData = wind(trainLen+1:end); % 对训练集做归一化并保存参数 ps,后面反归一化要用 [xTrainNorm, ps] = mapminmax(trainData', 0, 1); % 用训练集的参数归一化测试集,而不是对测试集单独计算 xTestNorm = mapminmax('apply', testData', ps);

mapminmax 默认按行处理,所以这里把列向量转置成了行向量。ps 是一个结构体,里面保存了这个归一化的最小值、最大值和映射公式。反归一化时同样要传入这个 ps,否则预测结果还原不到真实风速尺度。这里还要注意一个边界情况:如果测试集中出现了比训练集最大值更大的风速,mapminmax 的 apply 会输出大于 1 的值,这不是错误,反而比重新计算一套参数更诚实。

3.3 时序样本构造:步长与预测目标怎么对齐

LSTM 不是直接把一长串风速向量丢给 network 就能训练。它需要把原始序列切分成“用过去 numSteps 个点预测下一点”的样本对。比如用过去 12 个小时的风速预测下一个小时的风速,那每组输入是 12 个连续时刻的数值,输出是第 13 个时刻的数值。这个窗口长度 numSteps 直接决定模型能看到多长的历史信息。

numSteps = 12; % 输入窗口长度 [X, Y] = deal([]); for i = 1:length(xTrainNorm) - numSteps X = [X; xTrainNorm(i:i+numSteps-1)]; Y = [Y; xTrainNorm(i+numSteps)]; end % MATLAB 深度学习输入格式:N个cell,每个cell是一个numSteps×1的列向量 XTrain = num2cell(X', 1)'; % 每列转成独立cell YTrain = num2cell(Y', 1)'; % 每个样本的标签也是一个cell

这个循环虽然朴素,但逻辑最清晰。X 中第 i 行是窗口内的风速序列,Y 中第 i 行是对应的预测目标。转成 cell 数组时,num2cell 的第二个参数 1 表示按列拆分,再转置成 N×1 的 cell 数组。sequenceInputLayer 要求输入是一个 cell 数组,每个 cell 代表一个独立序列样本,内部是 numSteps×1 的向量。步长 numSteps 的选择不能拍脑袋,一般用自相关分析先看风速序列的记忆长度。我的做法是画一下 autocorr(wind),找到自相关系数开始明显衰减的滞后阶数,再把 numSteps 设成那个值附近。窗口太小,模型只看得到瞬时的风速惯性;窗口过大,训练样本数量减少,而且模型会把不相关的历史噪声也学进去。

4. 训练模型:基于LSTM的MATLAB风速回归实现

4.1 构建LSTM回归网络层

风速预测的 LSTM 网络不需要很复杂。一个能跑通的最小结构包含四层:输入层、LSTM 层、全连接输出层、回归损失层。这里的重点是 LSTM 层的 OutputMode 参数,它决定网络的输出形式。风速预测是单步回归,每个样本只需要最后一个时刻的输出,因此要设成 'last'。如果设成 'sequence',每一个时刻都会产生一个输出,全连接层接到的序列维度就变了,训练会直接报维度不匹配。

numHiddenUnits = 100; layers = [ sequenceInputLayer(1) lstmLayer(numHiddenUnits, 'OutputMode', 'last') fullyConnectedLayer(1) regressionLayer ];

sequenceInputLayer(1) 表示输入是单变量风速序列,每个时刻只有一个特征。如果你手里有温度、气压、湿度等多个气象要素,可以把这里的参数改成特征数量,同时把数据矩阵的每一行扩展成多列。lstmLayer 的 hiddenUnits 是一个可调参数,100 是从小数据集起步的稳妥值。hiddenUnits 太大会过拟合,太少则学不到风速的趋势;如果训练样本只有几千条,50 到 200 之间的差异通常不大。fullyConnectedLayer(1) 把 LSTM 最后一个隐藏状态映射成一个实数,regressionLayer 则计算均方误差作为损失,告诉网络这是一个回归任务。

4.2 训练参数设置:先保住loss不炸,再谈精度

训练参数的选择比网络结构更影响最终效果。对于风速这类时间序列,LSTM 训练的常见参数配置如下:

options = trainingOptions('adam', ... 'MaxEpochs', 200, ... 'MiniBatchSize', 64, ... 'InitialLearnRate', 0.005, ... 'GradientThreshold', 1, ... 'Shuffle', 'never', ... 'Verbose', 0, ... 'Plots', 'training-progress'); net = trainNetwork(XTrain, YTrain, layers, options);

adam 是时序回归的默认选择,它在大部分场景下比 sgdm 收敛更快。MaxEpochs 设 200 是一个折中值,风速数据量不大,200 轮通常足够收敛;如果 loss 还没平稳,可以加到 500。MiniBatchSize 设 64 是为了平衡内存和梯度稳定性,太小会导致更新方向抖动,太大则单次迭代耗时增加。Shuffle 设为 'never' 是这里最容易被忽略的参数——LSTM 依赖时间顺序,如果训练时把样本顺序打乱,等于告诉网络“未来信息可以提前看到”,训练和测试就都不靠谱了。

InitialLearnRate 从 0.005 开始,如果训练进度图中 loss 振荡,那就降到 0.001。GradientThreshold 设 1 是防止梯度爆炸的保险措施,风速数据里偶尔会有大脉动,梯度阈值能阻止权重一次更新过大,LSTM 训练变成 NaN 的情况大多和这个参数没设有关。训练结束后用 analyzeNetwork(net) 检查网络维度,确认各层数据流通无误。

4.3 预测与反归一化:算出来的RMSE必须对齐时间点

训练完成后,用 predict 在测试集上做预测,再把归一化后的预测值还原成真实风速。这一段的坑在于输出的 cell 数组格式和时序对齐。

XTestCell = num2cell(xTestNorm', 1)'; YPredNorm = predict(net, XTestCell, 'MiniBatchSize', 64); % 转成行向量后反归一化 YPredNorm = cell2mat(YPredNorm')'; YPred = mapminmax('reverse', YPredNorm, ps); % 对齐真实值:因为用前12个点预测下一点,真实序列要从第13点开始 YTrue = testData(numSteps+1:end); YPred = YPred(1:length(YTrue)); % 计算误差 rmse = sqrt(mean((YPred - YTrue).^2)); mae = mean(abs(YPred - YTrue)); fprintf('RMSE=%.3f m/s, MAE=%.3f m/s\n', rmse, mae);

predict 返回的通常是一个 cell 数组,每个 cell 里是预测值。cell2mat 之后,要确认方向是行向量还是列向量,再与 ps 的结构匹配。mapminmax 的 reverse 模式要求输入与 ps 保存的维度一致,常见报错就在这里。最后对齐时,YTrue 从 numSteps+1 开始,因为前 12 个历史点没有足够的过去信息用来预测。很多新手在这里直接拿整段测试集与预测序列比较,RMSE 看起来很大,实际上是错位比较。

5. 避坑:风速预测中LSTM训练失败的五个常见原因

5.1 训练集和测试集数据泄露:随机划分让时间序列“开卷考试”

现象:测试集 RMSE 比训练集还低,或者训练 loss 下降得很漂亮,但预测曲线其实已经严重滞后。

原因:不少人拿到数据后习惯性用 randperm 或 cvpartition 做随机划分。随机打乱风速序列会破坏时间顺序,相当于测试集里的一部分数据在训练时已经出现过,LSTM 记忆了整个序列的形状,而不是学风速的变化规律。这属于数据泄露。

解决:时间序列永远按时间顺序切分。最稳妥的方式是直接按索引切分,前 80% 训练、后 20% 测试。如果要交叉验证,改用滑窗式或滚动时间序列分割,禁止整体随机打乱。

5.2 归一化范围不一致:反归一化后所有预测值都偏低

现象:预测曲线的整体趋势对了,但幅值全部压缩在均值附近,峰值和低谷都被削平。

原因:对整段风速做了一次 mapminmax 后再切分训练测试集,或者对测试集单独做了一遍归一化,导致反归一化时使用了错误的映射参数。测试集的归一化范围如果和训练集不一致,预测值回到原始尺度后就会系统性偏移。

解决:严格按照第三章的做法——先切分,再对训练集算 ps,测试集用 mapminmax('apply', data, ps),反归一化也用同一个 ps。另外,如果你知道某个测风塔风速的物理上限,可以不做 mapminmax,直接除以一个固定阈值,比如 30 m/s,这样能避免测试集中出现超范围风速带来的外推误差。

5.3 步长设置不合理:预测曲线永远慢半拍

现象:预测曲线像是真实曲线被向后平移了一个采样点,下一时刻的预测约等于上一时刻的真实值。这个现象几乎每个做过风速 LSTM 预测的人都遇到过。

原因:步长 numSteps 太小,模型学不到风速的上升或下降趋势,只能利用瞬时惯性做预测;或者数据采样间隔和预测目标不匹配,比如采样间隔 10 秒,预测目标却是 1 小时后的风速,这中间的物理过程几乎不可能从 10 秒级数据推断。

解决:先用 stats 工具箱里的 autocorr(wind, 'NumLags', 50) 看自相关衰减情况,选择自相关还较强的滞后阶数作为 numSteps 候选值。我的经验是对 10 分钟采样数据做 1 小时风速预测,numSteps 取 6 到 12 比较合理;对 1 小时采样数据做次日预测,则要结合多个气象特征,单纯靠风速历史数据很难有效。

5.4 学习率过大导致loss变成NaN:训练过程突然中断

现象:training-progress 图中 loss 在某个 epoch 后变成 NaN,训练停止,之后 predict 出来的结果全是 NaN。

原因:学习率过大,梯度更新幅度超过正常范围,权重不断被推向极值;或者风速数据里还残留 Inf 和极端毛刺,导致损失计算溢出。

解决:训练前用 any(isinf(wind))、any(isnan(wind)) 做检查,确保数据干净。训练参数上,设置 GradientThreshold 为 1,并把 InitialLearnRate 降到 0.001 或 0.0005。如果还在 NaN,把 MiniBatchSize 调大,让梯度更新更平滑。这一步能解决 90% 的 NaN 问题。

5.5 训练慢但精度不高:网络容量和你的数据量不匹配

现象:同样跑 200 轮,别人的 LSTM 能到 RMSE 1.2 m/s,你的只能到 2.0 m/s,而且训练时间还多了一倍。

原因:最常见的是隐藏单元数设得太大,几千条风速样本硬塞给一个 500 隐藏单元的 LSTM,模型容量远超数据需求,结果就是欠拟合和过拟合同时出现。另一个原因是 MiniBatchSize 太小,导致每个 batch 的梯度方向都是噪声。

解决:先把 hiddenUnits 降到 50 跑通,再逐步增加到 100、150,观察验证集误差拐点。MiniBatchSize 至少设 32。更大的改进方向是把单变量风速扩展成多变量输入——把温度、湿度、气压等多列特征拼进输入矩阵,sequenceInputLayer 的维度对应增加,LSTM 就能学到风速与其他变量的耦合关系。这一步通常比单纯调大网络对精度的提升更明显。

6. 进阶:多步预测与模型验证,别只盯RMSE

6.1 用MAE、RMSE和R²一起判断模型好坏

RMSE 对个别大误差非常敏感,风速序列里偶尔一次阵风会造成 RMSE 明显增大,但调度关心的可能是连续时段的整体偏移。所以我通常把 MAE、RMSE 和 R² 三个指标一起打印:

ssRes = sum((YTrue - YPred).^2); ssTot = sum((YTrue - mean(YTrue)).^2); r2 = 1 - ssRes / ssTot;

R² 接近 1 说明模型解释了风速序列的大部分方差,但要注意风速序列本身方差大,R² 会偏高。这时候再看 MAE,如果 MAE 低而 RMSE 高,说明模型在大部分时刻表现好,但在个别阵风点被拉低,这属于可接受现象。

6.2 多步预测:用predictAndUpdateState做滚动预测

单步预测只是第一步。实际调度往往需要未来 6 小时、12 小时的风速曲线,这就涉及多步预测。常见做法是滚动预测:把上一步的预测值作为下一步的输入,同时不断更新 LSTM 的状态。MATLAB 里用 predictAndUpdateState 而不是 predict,否则网络状态不会随预测推进:

net = resetState(net); numPredSteps = 12; ypredAll = zeros(numPredSteps, 1); inputSeq = xTestNorm(1:numSteps); % 初始输入序列 for k = 1:numPredSteps [net, yPred] = predictAndUpdateState(net, inputSeq, 'MiniBatchSize', 1); ypredAll(k) = yPred; inputSeq = [inputSeq(2:end); yPred]; end

注意预测会随时间步积累误差,步数越长,后续预测越逼近风速均值。如果多步预测误差明显增大,不要慌,这是递归预测的正常特性,不代表模型坏了。工程上如果更看重前 3 步的精度,可以训练专门的 3 步预测模型,而不是无限滚动下去。

6.3 守住一条底线:别让测试集被反复“看”

我吃过一次亏:为了调参,连续一个星期都在同一个测试集上比较结果,最终选了 RMSE 最低的那组参数,上线后效果却很差。原因是测试集已经被反复使用,超参数间接过拟合到了测试集上。现在的习惯是把数据切成三段:训练集、验证集、全未碰过的最终测试集。平时用验证集调参,最后才碰一次测试集。这个习惯比任何网络结构改进都重要。

另一个实用习惯是:训练完成后立刻用 save('wind_lstm_net.mat', 'net', 'ps') 保存网络和归一化参数。下次部署时直接 load,不需要重新训练,而且 ps 必须和 net 一起保存,否则新数据进来根本没法归一化和反归一化。这套流程走完,你可以放心说,短期风速预测这件事,在 MATLAB 里用 LSTM 不只能跑通,还能跑得明明白白。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询