这个例子展示了如何使用长短期记忆(LSTM)网络预测时间序列数据。
为了预测序列的未来时间步长的值,您可以训练一个序列到序列的回归LSTM网络,其中的响应是值平移了一个时间步的训练序列。也就是说,在输入序列的每一个时间步,LSTM网络都会学习预测下一个时间步的值。
若要预测未来多个时间步长的值,请使用predictAndUpdateState
函数一次预测一个时间步长,并在每次预测时更新网络状态。
本例使用数据集chickenpox_dataset
.该示例训练LSTM网络,根据前几个月的病例数预测水痘病例数。
加载示例数据。chickenpox_dataset
包含单个时间序列,时间步长对应于月份,值对应于病例数。输出是一个单元格数组,其中每个元素都是一个时间步长。将数据重塑为行向量。
数据= chickenpox_dataset;数据= [Data {:}];Figure plot(data) xlabel(“月”) ylabel (“案例”)标题(“每月水痘病例”)
对训练数据和测试数据进行划分。训练序列的前90%,测试最后10%。
numTimeStepsTrain = floor(0.9* nummel (data));dataTrain = data(1:numTimeStepsTrain+1);dataTest = data(numTimeStepsTrain+1:end);
为了更好的拟合和防止训练发散,对训练数据进行标准化,使其均值为零,单位方差为零。在预测时,必须使用与训练数据相同的参数对测试数据进行标准化。
mu = mean(dataTrain);sig = std(dataTrain);datatrainstandardization = (dataTrain - mu) / sig;
为了预测序列未来时间步长的值,将响应指定为值平移一个时间步的训练序列。也就是说,在输入序列的每一个时间步,LSTM网络都会学习预测下一个时间步的值。预测器是没有最后时间步长的训练序列。
XTrain = datatrainstandardization (1:end-1);YTrain = datatrainstandardization (2:end);
创建一个LSTM回归网络。指定LSTM层有200个隐藏单元。
numFeatures = 1;numResponses = 1;numHiddenUnits = 200;层= [...sequenceInputLayer(numFeatures) lstmLayer(numHiddenUnits) fullyConnectedLayer(numResponses) regressionLayer];
指定培训选项。设置解算器为“亚当”
并训练250个纪元。为了防止梯度爆炸,将梯度阈值设置为1。指定初始学习速率0.005,并在125个epoch之后通过乘以0.2的因子来降低学习速率。
选项= trainingOptions(“亚当”,...“MaxEpochs”, 250,...“GradientThreshold”, 1...“InitialLearnRate”, 0.005,...“LearnRateSchedule”,“分段”,...“LearnRateDropPeriod”, 125,...“LearnRateDropFactor”, 0.2,...“详细”,0,...“阴谋”,“训练进步”);
使用指定的训练选项对LSTM网络进行训练trainNetwork
.
net = trainNetwork(XTrain,YTrain,图层,选项);
若要预测未来多个时间步长的值,请使用predictAndUpdateState
函数一次预测一个时间步长,并在每次预测时更新网络状态。对于每个预测,使用之前的预测作为函数的输入。
使用与训练数据相同的参数使测试数据标准化。
datateststandardization = (dataTest - mu) / sig;XTest = datateststandardization (1:end-1);
为了初始化网络状态,首先对训练数据进行预测XTrain
.接下来,使用训练响应的最后一个时间步骤进行第一个预测YTrain(结束)
.循环其余的预测,并输入先前的预测predictAndUpdateState
.
对于大型数据集合、长序列或大型网络,GPU上的预测通常比CPU上的预测更快。否则,CPU上的预测通常计算得更快。对于单时间步预测,使用CPU。若要使用CPU进行预测,请设置“ExecutionEnvironment”
选择predictAndUpdateState
来“cpu”
.
net = predictAndUpdateState(net,XTrain);[net,YPred] = predictAndUpdateState(net,YTrain(end));numTimeStepsTest = numel(XTest);为i = 2:numTimeStepsTest [net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),“ExecutionEnvironment”,“cpu”);结束
使用先前计算的参数对预测进行非标准化。
YPred = sig*YPred + mu;
训练进度图报告从标准化数据计算的均方根误差(RMSE)。从非标准化预测中计算RMSE。
YTest = dataTest(2:end);rmse =√(mean(YPred-YTest).^2))
rmse =单248.5531
用预测值绘制训练时间序列。
figure plot(dataTrain(1:end-1))稍等在idx = numTimeStepsTrain:(numTimeStepsTrain+numTimeStepsTest);情节(idx (numTimeStepsTrain) YPred][数据,“。”)举行从包含(“月”) ylabel (“案例”)标题(“预测”)传说([“观察”“预测”])
将预测值与试验数据进行比较。
图子图(2,1,1)图(YTest) hold住在情节(YPred“。”)举行从传奇([“观察”“预测”]) ylabel (“案例”)标题(“预测”) subplot(2,1,2) stem(YPred - YTest) xlabel(“月”) ylabel (“错误”)标题(" rmse = "+ rmse)
如果您可以访问预测之间的时间步长的实际值,那么您可以使用观测值而不是预测值更新网络状态。
首先,初始化网络状态。要对一个新的序列进行预测,使用重置网络状态resetState
.重置网络状态可以防止先前的预测影响对新数据的预测。重置网络状态,然后对训练数据进行预测,初始化网络状态。
net = resetState(net);net = predictAndUpdateState(net,XTrain);
对每个时间步进行预测。对于每个预测,使用前一个时间步的观测值预测下一个时间步。设置“ExecutionEnvironment”
选择predictAndUpdateState
来“cpu”
.
YPred = [];numTimeStepsTest = numel(XTest);为i = 1:numTimeStepsTest [net,YPred(:,i)] = predictAndUpdateState(net,XTest(:,i),“ExecutionEnvironment”,“cpu”);结束
使用先前计算的参数对预测进行非标准化。
YPred = sig*YPred + mu;
计算均方根误差(RMSE)。
rmse =√(mean(YPred-YTest).^2))
Rmse = 158.0959
将预测值与试验数据进行比较。
图子图(2,1,1)图(YTest) hold住在情节(YPred“。”)举行从传奇([“观察”“预测”]) ylabel (“案例”)标题(“最新天气预报”) subplot(2,1,2) stem(YPred - YTest) xlabel(“月”) ylabel (“错误”)标题(" rmse = "+ rmse)
在这里,用观测值更新网络状态比用预测值更新网络状态更准确。
trainNetwork
|trainingOptions
|lstmLayer
|sequenceInputLayer