ディープ ネットワーク デザイナーを使用して時系列予測をネットワークに学習させる
この例では、"ディープ ネットワーク デザイナー" で長短期記憶 (LSTM) ネットワークに学習させて時系列データを予測する方法を説明します。
ディープ ネットワーク デザイナーを使用すると、シーケンス分類およびシーケンス回帰タスクのための深層ニューラル ネットワークを対話的に作成し、学習させることができます。
シーケンスの将来のタイム ステップの値を予測するために、sequence-to-sequence 回帰用の LSTM ネットワークに学習させることができます。その応答は、1 タイム ステップ分シフトした値を持つ学習シーケンスです。つまり、入力シーケンスの各タイム ステップで、LSTM ネットワークは次のタイム ステップの値を予測するように学習します。
この例ではデータセット 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))
numTimeStepsTrain = 448
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);
ディープ ネットワーク デザイナーを使用してネットワークに学習させるには、学習データをデータストア オブジェクトに変換します。arrayDatastore
を使用して、学習データの予測子と応答を ArrayDatastore
オブジェクトに変換します。combine
を使用して、2 つのデータ ストアを統合します。
adsXTrain = arrayDatastore(XTrain); adsYTrain = arrayDatastore(YTrain); cdsTrain = combine(adsXTrain,adsYTrain);
LSTM ネットワーク アーキテクチャの定義
LSTM ネットワーク アーキテクチャを作成するには、"ディープ ネットワーク デザイナー" を使用します。"ディープ ネットワーク デザイナー" アプリでは、深層学習ネットワークの構築、可視化、編集、および学習ができます。
deepNetworkDesigner
"ディープ ネットワーク デザイナー" のスタート ページで、[Sequence-to-Sequence] で一時停止し、[開く] をクリックします。これにより、sequence-to-sequence 分類タスクに適したプリビルド ネットワークが開きます。最終層を置き換えると、分類ネットワークを回帰ネットワークに変換できます。
ソフトマックス層と分類層を削除し、回帰層に置き換えます。
水ぼうそうのデータ セットに適するように層のプロパティを調整します。このデータには、1 つの入力特徴と 1 つの出力特徴があります。[sequenceInputLayer] を選択し、[InputSize] を 1
に設定します。[fullyConnectedLayer] を選択し、[OutputSize] を 1
に設定します。
[解析] をクリックしてネットワークを確認します。"深層学習ネットワーク アナライザー" によってエラー 0 が報告されていれば、ネットワークの学習の準備は整っています。
データのインポート
学習データストアをインポートするには、[データ] タブを選択し、[データのインポート]、[カスタム データのインポート] をクリックします。学習データとして [cdsTrain]
を、検証データとして [None]
を選択します。[インポート] をクリックします。
データ プレビューには、それぞれ 448 のタイム ステップを持つ単一の入力時系列と単一の応答時系列が表示されます。
学習オプションの指定
[学習] タブで、[学習オプション] をクリックします。[Solver] を [adam]
に、[InitialLearnRate] を 0.005
に、[MaxEpochs] を 500
に設定します。勾配の発散を防ぐために、[GradientThreshold] を 1
に設定します。
学習オプションの設定の詳細については、trainingOptions
を参照してください。
ネットワークの学習
[学習] をクリックします。
"ディープ ネットワーク デザイナー" に、学習の進行状況がアニメーション化されたプロットで表示されます。プロットには、ミニバッチの損失と精度、検証の損失と精度、および学習の進行状況に関する追加情報が表示されます。
学習が完了したら、[学習] タブの [エクスポート] をクリックして、学習済みネットワークをエクスポートします。学習済みネットワークは、変数 trainedNetwork_1
として保存されます。
将来のタイム ステップの予測
将来の複数のタイム ステップを予測させ、学習済みネットワークをテストします。関数 predictAndUpdateState
を使用して、タイム ステップを 1 つずつ予測し、予測ごとにネットワークの状態を更新します。予測ごとに、前の予測を関数への入力として使用します。
学習データと同じパラメーターを使用してテスト データを標準化します。
dataTestStandardized = (dataTest - mu) / sig; XTest = dataTestStandardized(1:end-1); YTest = dataTest(2:end);
ネットワークの状態を初期化するには、まず、学習データ XTrain
について予測を行います。次に、学習の応答 YTrain(end)
の最後のタイム ステップを使用して、最初の予測を行います。残りの予測についてループし、前の予測を predictAndUpdateState
に入力します。
データの大規模なコレクション、長いシーケンス、または大規模ネットワークの場合は、通常、GPU での予測の方が CPU での予測より計算時間が短縮されます。そうでない場合、通常、CPU での予測の計算の方が高速です。1 タイム ステップの予測には、CPU を使用します。予測に CPU を使用するには、predictAndUpdateState
の 'ExecutionEnvironment'
オプションを 'cpu'
に設定します。
net = predictAndUpdateState(trainedNetwork_1,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 を計算します。
rmse = sqrt(mean((YPred-YTest).^2))
rmse = single
175.9693
予測値と共に学習の時系列をプロットします。
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 = 119.5968
予測値をテスト データと比較します。
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)
ここで、予測値の代わりに観測値を使用してネットワークの状態を更新すると、予測がより正確になります。