ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

深層学習を使用した時系列予測

この例では、長短期記憶 (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("Monthy 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
    209.5295

予測値と共に学習の時系列をプロットします。

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 = 122.2634

予測値をテスト データと比較します。

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)

ここで、予測値の代わりに観測値を使用してネットワークの状態を更新すると、予測がより正確になります。

参考

| | |

関連するトピック