基于MALTAB的LSTM神经网络时序多步预测(完整代码)

本文部分理论引用了:4 Strategies for Multi-Step Time Series Forecasting

首先在本文中不考虑已知序列的预测,即不使用观测值去进行下一步的预测,这在实际中是没有应用意义的,除非是已知实验数据再去进行一个模型的检验。

第一步:加载数据,并进行数据预处理

load Forcedata_1.mat %加载数据(double型,只有一列数据,时序预测没有实际时间,只有事情发生的顺序)
data=force';    %将数据集转置
%% 序列的前 90% 用于训练,后 10% 用于测试
dataTrain = data(1:1000);    %定义训练集
dataTest = data(1001:1100);    %该数据是用来在最后与预测值进行对比的
%% 数据预处理,将训练数据标准化为具有零均值和单位方差。
mu = mean(dataTrain);    %求均值 
sig = std(dataTrain);      %求均差 
dataTrainStandardized = (dataTrain - mu) / sig;     %这里是防止数据发散,获得较好的拟合

 LSTM对于数据标准化要求很高。且这里只对训练集进行标准化的原因是,对于测试集我们应该是不知道的。

第二步: 输入的每个时间步,LSTM网络学习预测下一个时间步(这里一个时间步我是0.01秒)的值,这和时间的概念相符合,将前面的为x、后面的为y作为神经网络的映射关系来源。

XTrain = dataTrainStandardized(1:end-1);  
YTrain = dataTrainStandardized(2:end);  

大多数LSTM相关的资料还是使用默认的lag=1来将时间序列拆分为具有输入和输出分量的样本。我在自己的其他试验中使用不同时间步的滞后来观察(lag=1,2,5,10)。其数目的意义是能规定用于预测下一时间步长y的输入变量的数目。设置不同时间步的目的是观察是否能够改善预测模型性能。但据某些验证表明,增加滞后并不能改善预测模型的性能。

现在即输入[[1],[2],[3],...,[10]]对应着输出[[2],[3],[4],...[11]],lag为2的时候即[[1,2],[2,3],[3,4],...,[9,10]]对应着[[3],[4],[5],...,[11]]。但不论怎样输出对应的都应该是下一个时间步,要与实际结合。

  1. 转化序列数据使其呈静态。具体来说,就是使用 lag=1差分移除数据中的增长趋势。
  2. 将时间序列问题转化为监督学习问题。具体来说,就是将数据组为输入和输出模式,上一时间步长的观察值可作为输入用于预测当前时间步长的观察值。
  3. 转化观察值使其处在特定区间。具体来说,就是将数据缩放带 -1 至1的区间内,以满足LSTM模型默认的双曲正切激活函数。

第三步:定义LSTM网络架构

numFeatures = 1;    %是时间序列,因此输入一维
numResponses = 1;  %输出一维
numHiddenUnits = 93;   %创建LSTM回归网络,指定LSTM层的隐含单元个数93
 
layers = [ ...
    sequenceInputLayer(numFeatures)    %输入层
    lstmLayer(numHiddenUnits)  % lstm层,如果是构建多层的LSTM模型,可以修改。
    fullyConnectedLayer(numResponses)    %为全连接层,是输出的维数。
    regressionLayer];      %其计算回归问题的半均方误差模块 。即说明这不是在进行分类问题。

%指定训练选项,求解器设置为adam, 1000轮训练。
%梯度阈值设置为 1。指定初始学习率 0.01,在 125 轮训练后通过乘以因子 0.2 来降低学习率。
options = trainingOptions('adam', ...
    'MaxEpochs',1000, ...
    'GradientThreshold',1, ...
    'InitialLearnRate',0.01, ...      
    'LearnRateSchedule','piecewise', ...%每当经过一定数量的时期时,学习率就会乘以一个系数。
    'LearnRateDropPeriod',125, ...      %乘法之间的纪元数由“ LearnRateDropPeriod”控制。
    'LearnRateDropFactor',0.2, ...      %乘法因子由参“ LearnRateDropFactor”控制, 
    'Verbose',0,  ...  %如果将其设置为true,则有关训练进度的信息将被打印到命令窗口中。默认值为true。
    'Plots','training-progress');    %构建曲线图 将'training-progress'替换为none

需要提醒的是:在MATLAB中,其已经将LSTM网络进行封装,类似工具箱的形式,因此不再涉及底层的“门”概念。

第四步:训练LSTM网络

net = trainNetwork(XTrain,YTrain,layers,options); 

第五步:初始化网络状态

net = predictAndUpdateState(net,XTrain);  %将新的XTrain数据用在网络上进行初始化网络状态
[net,YPred] = predictAndUpdateState(net,YTrain(end));  %用训练的最后一步来进行预测第一个预测值

训练的最后一个,即预测的第一个。

第六步:利用LSTM网络进行循环预测(100步)递归多步预测

for i = 2:100  %从第二步开始
    [net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu');  %predictAndUpdateState函数是一次预测一个值并更新网络状态
end

递归多步预测会一直累积误差,以至于使性能迅速下降,但LSTM对比NAR网络独有的是其有这个特殊的函数predictAndUpdateState能够在每次预测时更新网络状态。因此其能够预测更长的序列。需要说明的是,使用预测值或者观测值要根据实际情况去确定。如波浪力是实时变化的,在 实验中能够通过仪器在两次预测之间能够观测到波浪力的值,即0.01s之内并将其作为输入来更新网络状态然后输出下一个预测值的。毕竟根据我的工作来说,只是已知100个数据,要往下一直推8000步数据,只能用观测值来进行更新。

第七步:进行预测结果的对比

YPred = sig*YPred + mu;      %使用先前计算的参数对预测去标准化。
rmse = sqrt(mean((YPred-YTest).^2)) ;     %计算均方根误差 (RMSE)。
% 利用预测绘制整个时序
figure   
subplot(2,1,1)
plot(dataTrain(1:end))
hold on
idx = 1000:(1000+100);
plot(idx,[data(1000) YPred],'.-')
hold off
xlabel("Time")
ylabel("Force")
title("Forecast")
legend(["Observed" "Forecast"])
subplot(2,1,2)
plot(data)
xlabel("Time")
ylabel("Force")
title("Wave Force") 
% 将预测值与测试数据进行比较。
figure
subplot(2,1,1)
%指的是在一个2行1列共2个子图的图中,定位第1个图来进行操作。
% plot(dataTest)
hold on    %用于添加新绘图的时候保留当前绘图
plot(YPred,'.-')     %点变成点画线
hold off     %取消hold on功能,即不保留
legend(["Observed" "Predicted"])   
ylabel("Force")      
title("Wave Force")
 
subplot(2,1,2) 
% stem(YPred - dataTest)   %stem函数用于绘制火柴棍图
xlabel("Time")
ylabel("Error")
title("RMSE = " + rmse)  %需要说的是RMSE与MSE相比,RMSE对预测误差的惩罚性更大 

第八步:重置网络状态

net = resetState(net);  

如果需要进行其他的预测,如进行下一轮300个的预测。需要重置一下网络状态。

应用到实际可以发现:

基于MALTAB的LSTM神经网络时序多步预测(完整代码)_第1张图片

但在预测的时候,不能单从训练集和预测集的数量以及比例去评价这个数据集的好坏,从理论上来说,训练集应包含一个周期的变化,不然肯定无法通过此去进行预测(不管是不是用到之前所述的插值策略,插值策略是根据我的控制理论来决定的)。而且100个数据去预测30个数据这并不意味着用1000个数据去预测后面300个是一样的表现,两者是不相同的。

使预测模型更加精确的方法有:增加预测输入的维度,即加入不同的特征。

你可能感兴趣的:(MPC,时序预测,lstm,神经网络,人工智能)