时间序列预测是数据分析领域的经典问题,从电力负荷预测到股票走势分析都离不开它。今天我要分享的是三种最实用的预测模型在Matlab中的实现方案——支持向量机(SVM)、BP神经网络和LSTM网络。这三种方法各有特点,适用于不同场景,我会结合电力负荷预测的实例,带大家从数据准备到模型调优完整走一遍流程。
为什么选择这三种模型?SVM在小样本情况下表现稳定,BP神经网络对非线性关系捕捉能力强,而LSTM则是处理长序列依赖的利器。实测下来,用同一组电力负荷数据(2018-2020年每小时记录),LSTM的24小时预测平均误差能控制在3.2%以内,SVM约5.7%,BP网络约4.9%。下面我就拆解每个模型的关键实现步骤。
无论哪种模型,优质的数据准备都是成功的前提。我们从Excel读取电力负荷数据时,要特别注意处理缺失值和异常点:
matlab复制data = xlsread('power_load.xlsx');
% 处理缺失值(线性插值)
missing_idx = isnan(data);
data(missing_idx) = interp1(find(~missing_idx), data(~missing_idx), find(missing_idx));
% 剔除异常值(3σ原则)
mu = mean(data);
sigma = std(data);
data(data < mu-3*sigma | data > mu+3*sigma) = mu;
时间序列预测的关键是将序列数据转化为监督学习问题。我们定义一个滑动窗口函数:
matlab复制function [X, Y] = create_dataset(data, lag)
X = []; Y = [];
for i = 1:length(data)-lag
X = [X; data(i:i+lag-1)]; % 输入窗口
Y = [Y; data(i+lag)]; % 输出值
end
end
对于电力负荷预测,通常取lag=24(一天周期)效果较好。记得将数据分为训练集和测试集:
matlab复制lag = 24;
[X, Y] = create_dataset(data, lag);
split_ratio = 0.8;
split_idx = floor(length(Y)*split_ratio);
XTrain = X(1:split_idx,:); YTrain = Y(1:split_idx);
XTest = X(split_idx+1:end,:); YTest = Y(split_idx+1:end);
不同模型对数据尺度敏感度不同:
matlab复制% SVM可以直接用原始数据
% BP和LSTM需要归一化
[XTrain_bp, ps] = mapminmax(XTrain', -1, 1); XTrain_bp = XTrain_bp';
[YTrain_bp, ps_y] = mapminmax(YTrain', -1, 1); YTrain_bp = YTrain_bp';
% LSTM需要转换为cell数组
XTrain_lstm = num2cell(XTrain_bp', 1);
YTrain_lstm = num2cell(YTrain_bp', 1);
支持向量回归(SVR)通过核函数将数据映射到高维空间实现非线性回归:
matlab复制svm_model = fitrsvm(XTrain, YTrain, ...
'KernelFunction','gaussian', ... % RBF核
'KernelScale','auto', ...
'Standardize',true);
关键参数说明:
使用5折交叉验证评估模型:
matlab复制cv_svm = crossval(svm_model, 'KFold',5);
loss = kfoldLoss(cv_svm);
fprintf('SVM交叉验证MAE: %.2f%%\n', loss*100);
预测未来24小时负荷的滚动预测方法:
matlab复制current_window = XTest(1,:); % 初始窗口
pred_svm = zeros(24,1);
for i = 1:24
pred_svm(i) = predict(svm_model, current_window);
current_window = [current_window(2:end), pred_svm(i)]; % 更新窗口
end
注意:SVM对输入数据尺度敏感,建议始终开启'Standardize'选项
双隐层网络通常能更好捕捉复杂模式:
matlab复制net = feedforwardnet([15 10], 'trainlm'); % Levenberg-Marquardt算法
net.trainParam.epochs = 1000;
net.trainParam.max_fail = 20; % 早停机制
net.divideFcn = 'dividerand';
net.divideParam.trainRatio = 0.7;
net.divideParam.valRatio = 0.15;
net.divideParam.testRatio = 0.15;
训练过程可视化有助于调试:
matlab复制net.trainParam.showWindow = true;
[net, tr] = train(net, XTrain_bp', YTrain_bp');
% 绘制训练曲线
plotperform(tr)
预测结果需要转换回原始尺度:
matlab复制pred_bp = net(XTest_bp');
pred_bp = mapminmax('reverse', pred_bp, ps_y);
% 计算测试集误差
mae_bp = mean(abs(pred_bp' - YTest));
LSTM特有的序列处理能力适合时间序列:
matlab复制layers = [...
sequenceInputLayer(1)
lstmLayer(100, 'OutputMode','sequence')
dropoutLayer(0.2) % 防止过拟合
lstmLayer(50, 'OutputMode','last')
fullyConnectedLayer(1)
regressionLayer];
options = trainingOptions('adam', ...
'MaxEpochs', 300, ...
'MiniBatchSize', 32, ...
'InitialLearnRate', 0.001, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropFactor',0.5, ...
'LearnRateDropPeriod',100);
LSTM的状态更新是滚动预测的关键:
matlab复制net_lstm = trainNetwork(XTrain_lstm, YTrain_lstm, layers, options);
% 初始化状态
net_lstm = resetState(net_lstm);
[net_lstm, pred] = predictAndUpdateState(net_lstm, XTest_lstm{1});
% 滚动预测
pred_lstm = zeros(24,1);
current_input = XTest_lstm{1};
for i = 1:24
[net_lstm, pred_lstm(i)] = predictAndUpdateState(net_lstm, current_input);
current_input = pred_lstm(i); % 用预测值作为下一步输入
end
我们使用三个指标评估模型:
| 模型 | MAE (%) | 训练时间(s) | 内存占用(MB) |
|---|---|---|---|
| SVM | 5.7 | 12.4 | 85 |
| BP | 4.9 | 8.2 | 120 |
| LSTM | 3.2 | 325.7 | 210 |
根据场景选择合适模型:
实际项目中可以组合使用:
现象:预测曲线总是比实际值"慢半拍"
解决方法:
现象:训练误差低但测试误差高
对策:
可能原因:
我在电力公司实际部署时发现,将LSTM预测结果与业务规则结合(如节假日修正),能进一步提升5-8%的准确率。另外,建议保存训练好的模型以便复用:
matlab复制% 保存模型
save('power_predict_model.mat', 'net_lstm', 'svm_model', 'net')
% 加载模型
load('power_predict_model.mat')