このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
深層学習を使用した時系列予測
この例では、長短期記憶 (LSTM) ネットワークを使用して時系列データを予測する方法を説明します。
シーケンスの将来のタイム ステップの値を予測するために、sequence-to-sequence 回帰用の LSTM ネットワークに学習させることができます。その応答は、1 タイム ステップ分シフトした値を持つ学習シーケンスです。つまり、入力シーケンスの各タイム ステップで、LSTM ネットワークは次のタイム ステップの値を予測するように学習します。
将来の複数のタイム ステップの値を予測するには、関数 predictAndUpdateState
を使用して、タイム ステップを 1 つずつ予測し、予測ごとにネットワークの状態を更新します。
この例ではデータセット chickenpox_dataset
を使用します。この例では、前月までの水ぼうそうの発生件数を与えて、水ぼうそうの発生件数を予測するよう LSTM ネットワークに学習させます。
シーケンス データの読み込み
例のデータを読み込みます。chickenpox_dataset
には、月に対応するタイム ステップと発生件数に対応する値を含む 1 つの時系列が含まれています。出力は cell 配列で、その各要素は 1 つのタイム ステップです。データを行ベクトルに形状変更します。
data = chickenpox_dataset; data = [data{:}]; figure plot(data) xlabel("Month") ylabel("Cases") title("Monthly Cases of Chickenpox")
学習データとテスト データに分割します。シーケンスの最初の 90% で学習を行い、残りの 10% でテストを行います。
numTimeStepsTrain = floor(0.9*numel(data)); dataTrain = data(1:numTimeStepsTrain+1); dataTest = data(numTimeStepsTrain+1:end);
データの標準化
良好な適合を実現し、学習の発散を防ぐには、ゼロ平均と単位分散を持つように学習データを標準化します。予測時には、学習データと同じパラメーターを使用してテスト データを標準化しなければなりません。
mu = mean(dataTrain); sig = std(dataTrain); dataTrainStandardized = (dataTrain - mu) / sig;
予測子と応答の準備
シーケンスの将来のタイム ステップの値を予測するには、1 タイム ステップ分シフトした値を持つ学習シーケンスになるように応答を指定します。つまり、入力シーケンスの各タイム ステップで、LSTM ネットワークは次のタイム ステップの値を予測するように学習します。予測子は、最後のタイム ステップを含まない学習シーケンスです。
XTrain = dataTrainStandardized(1:end-1); YTrain = dataTrainStandardized(2:end);
LSTM ネットワーク アーキテクチャの定義
LSTM 回帰ネットワークを作成します。200 個の隠れユニットを持つ LSTM 層を指定します。
numFeatures = 1;
numResponses = 1;
numHiddenUnits = 200;
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits)
fullyConnectedLayer(numResponses)
regressionLayer];
学習オプションを指定します。ソルバーを 'adam'
に設定し、学習を 250 エポック行います。勾配の発散を防ぐために、勾配のしきい値を 1 に設定します。初期学習率を 0.005 に指定し、125 エポック後に係数 0.2 を乗算して学習率を下げます。
options = trainingOptions('adam', ... 'MaxEpochs',250, ... 'GradientThreshold',1, ... 'InitialLearnRate',0.005, ... 'LearnRateSchedule','piecewise', ... 'LearnRateDropPeriod',125, ... 'LearnRateDropFactor',0.2, ... 'Verbose',0, ... 'Plots','training-progress');
LSTM ネットワークの学習
trainNetwork
を使用し、指定した学習オプションで LSTM ネットワークに学習させます。
net = trainNetwork(XTrain,YTrain,layers,options);
将来のタイム ステップの予測
将来の複数のタイム ステップの値を予測するには、関数 predictAndUpdateState
を使用して、タイム ステップを 1 つずつ予測し、予測ごとにネットワークの状態を更新します。予測ごとに、前の予測を関数への入力として使用します。
学習データと同じパラメーターを使用してテスト データを標準化します。
dataTestStandardized = (dataTest - mu) / sig; XTest = dataTestStandardized(1:end-1);
ネットワークの状態を初期化するには、まず、学習データ XTrain
について予測を行います。次に、学習の応答 YTrain(end)
の最後のタイム ステップを使用して、最初の予測を行います。残りの予測についてループし、前の予測を predictAndUpdateState
に入力します。
データの大規模なコレクション、長いシーケンス、または大規模ネットワークの場合は、通常、GPU での予測の方が CPU での予測より計算時間が短縮されます。そうでない場合、通常、CPU での予測の計算の方が高速です。1 タイム ステップの予測には、CPU を使用します。予測に CPU を使用するには、predictAndUpdateState
の 'ExecutionEnvironment'
オプションを 'cpu'
に設定します。
net = predictAndUpdateState(net,XTrain); [net,YPred] = predictAndUpdateState(net,YTrain(end)); numTimeStepsTest = numel(XTest); for i = 2:numTimeStepsTest [net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu'); end
前に計算したパラメーターを使用して予測を非標準化します。
YPred = sig*YPred + mu;
学習の進行状況プロットには、標準化されたデータから計算された平方根平均二乗誤差 (RMSE) が報告されます。非標準化された予測から RMSE を計算します。
YTest = dataTest(2:end); rmse = sqrt(mean((YPred-YTest).^2))
rmse = single
248.5531
予測値と共に学習の時系列をプロットします。
figure plot(dataTrain(1:end-1)) hold on idx = numTimeStepsTrain:(numTimeStepsTrain+numTimeStepsTest); plot(idx,[data(numTimeStepsTrain) YPred],'.-') hold off xlabel("Month") ylabel("Cases") title("Forecast") legend(["Observed" "Forecast"])
予測値をテスト データと比較します。
figure subplot(2,1,1) plot(YTest) hold on plot(YPred,'.-') hold off legend(["Observed" "Forecast"]) ylabel("Cases") title("Forecast") subplot(2,1,2) stem(YPred - YTest) xlabel("Month") ylabel("Error") title("RMSE = " + rmse)
観測値によるネットワークの状態の更新
予測と予測の間にタイム ステップの実際の値にアクセスできる場合、予測値の代わりに観測値を使用してネットワークの状態を更新できます。
まず、ネットワークの状態を初期化します。新しいシーケンスについて予測を行うには、resetState
を使用してネットワークの状態をリセットします。ネットワークの状態をリセットすると、前の予測が新しいデータについての予測に影響を与えるのを防ぐことができます。ネットワークの状態をリセットしてから、学習データに対して予測を行い、ネットワークの状態を初期化します。
net = resetState(net); net = predictAndUpdateState(net,XTrain);
タイム ステップごとに予測を行います。予測ごとに、前のタイム ステップの観測値を使用して次のタイム ステップを予測します。predictAndUpdateState
の 'ExecutionEnvironment'
オプションを 'cpu'
に設定します。
YPred = []; numTimeStepsTest = numel(XTest); for i = 1:numTimeStepsTest [net,YPred(:,i)] = predictAndUpdateState(net,XTest(:,i),'ExecutionEnvironment','cpu'); end
前に計算したパラメーターを使用して予測を非標準化します。
YPred = sig*YPred + mu;
平方根平均二乗誤差 (RMSE) を計算します。
rmse = sqrt(mean((YPred-YTest).^2))
rmse = 158.0959
予測値をテスト データと比較します。
figure subplot(2,1,1) plot(YTest) hold on plot(YPred,'.-') hold off legend(["Observed" "Predicted"]) ylabel("Cases") title("Forecast with Updates") subplot(2,1,2) stem(YPred - YTest) xlabel("Month") ylabel("Error") title("RMSE = " + rmse)
ここで、予測値の代わりに観測値を使用してネットワークの状態を更新すると、予測がより正確になります。
参考
trainNetwork
| trainingOptions
| lstmLayer
| sequenceInputLayer