web-dev-qa-db-ja.com

LSTMを使用した時系列の複数のフォワードタイムステップの予測

週ごとに予測可能な特定の値を予測したい(低SNR)。年の週で構成される年の時系列全体を予測する必要があります(52個の値-図1)

Figure 1: Year time series by week

私の最初のアイデアは、Kensors over TensorFlowを使用して多対多のLSTMモデル(図2)を開発することでした。 52個の入力層(前年の時系列)と52個の予測出力層(来年の時系列)でモデルをトレーニングしています。 train_Xの形状は(X_examples、52、1)、言い換えると、トレーニングするX_examplesで、それぞれ1フィーチャの52タイムステップです。 Kerasは52個の入力を同じドメインの時系列と見なすことを理解しています。 train_Yの形状は同じです(y_examples、52、1)。 TimeDistributedレイヤーを追加しました。私の考えは、アルゴリズムが値を孤立した値ではなく時系列として予測することでした(私は正しいですか?)

Kerasのモデルのコードは次のとおりです。

y = y.reshape(y.shape[0], 52, 1)
X = X.reshape(X.shape[0], 52, 1)
# design network
model = Sequential()
model.add(LSTM(n_neurons, input_shape=(X.shape[1], X.shape[2]), return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(loss='mean_squared_error', optimizer='adam')
# fit network
model.fit(X, y, epochs=n_epochs, batch_size=n_batch, verbose=2)

Figure 2: Many-to-many LSTM architecture

問題は、アルゴリズムが例を学習していないことです。属性の値に非常に類似した値を予測しています。問題を正しくモデリングしていますか?

2番目の質問:別のアイデアは、1入力と1出力でアルゴリズムをトレーニングすることですが、テスト中に「1入力」を見ずに2015年の時系列全体をどのように予測しますか?テストデータは、トレーニングデータとは異なる形状になります。

14
Lucas Brito

データが少なすぎるという同じ懸念を共有して、このようにすることができます。

まず、値を-1から+1の間に保つことをお勧めします。そのため、最初に値を正規化します。

LSTMモデルの場合、_return_sequences=True_を使用していることを確認する必要があります。
モデルに「間違った」ものは何もありませんが、希望するものを実現するために必要なレイヤーまたはユニットは多かれ少なかれあります。 (ただし、これに対する明確な答えはありません)。

次のステップを予測するためのモデルのトレーニング:

必要なのは、YをシフトされたXとして渡すことだけです。

_entireData = arrayWithShape((samples,52,1))
X = entireData[:,:-1,:]
y = entireData[:,1:,:]
_

これらを使用してモデルをトレーニングします。

未来を予測する:

さて、未来を予測するために、より多くの予測要素の入力として予測要素を使用する必要があるため、ループを使用してモデルを_stateful=True_にします。

次の変更を加えて、前のモデルと同じモデルを作成します。

  • すべてのLSTMレイヤーには_stateful=True_が必要です
  • バッチ入力の形状は_(batch_size,None, 1)_でなければなりません-これは可変長を許可します

以前にトレーニングしたモデルの重みをコピーします。

_newModel.set_weights(oldModel.get_weights())
_

一度に1つのサンプルのみを予測し、シーケンスを開始する前にmodel.reset_states()を呼び出すことを忘れないでください。

最初に、既知のシーケンスで予測します(これにより、モデルは将来を予測するために状態を適切に準備します)

_model.reset_states()
predictions = model.predict(entireData)
_

訓練したところで、予測の最後のステップは最初の将来の要素になります。

_futureElement = predictions[:,-1:,:]

futureElements = []
futureElements.append(futureElement)
_

次に、この要素が入力であるループを作成します。 (ステートフルのため、モデルは、それが新しいシーケンスではなく前のシーケンスの新しい入力ステップであることを理解します)

_for i in range(howManyPredictions):
    futureElement = model.predict(futureElement)
    futureElements.append(futureElement)
_

このリンクには、2つの機能の将来を予測する完全な例が含まれています。 https://github.com/danmoller/TestRepo/blob/master/TestBookLSTM.ipynb

22
Daniel Möller

10年のデータがあります。トレーニングデータセットが次のとおりである場合:5週目を予測するための4週間からの値とシフトし続ける場合、モデルをトレーニングするためのほぼ52 X 9の例と(昨年)を予測するための52の例があります

これは、実際には、それぞれ52の機能を備えたトレーニングサンプルが9つしかないことを意味します(高度に重複する入力データでトレーニングする場合を除く)。いずれにせよ、これはLSTMのトレーニングに値するほどには十分ではないと思います。

もっと簡単なモデルを試すことをお勧めします。入力データと出力データのサイズは固定されているため、 sklearn.linear_model.LinearRegression を試してみてください。これは、トレーニング例ごとに複数の入力機能(この場合は52)と、複数のターゲット(52も)を処理します。

更新:mustLSTMを使用する必要がある場合は、 LSTM Neural Network時系列予測の場合KerasLSTM実装で、複数の将来の予測を一度に、または各予測を入力としてフィードバックすることにより繰り返しサポートします。あなたのコメントに基づいて、これはまさにあなたが望むものでなければなりません。

この実装のネットワークのアーキテクチャは次のとおりです。

model = Sequential()

model.add(LSTM(
    input_shape=(layers[1], layers[0]),
    output_dim=layers[1],
    return_sequences=True))
model.add(Dropout(0.2))

model.add(LSTM(
    layers[2],
    return_sequences=False))
model.add(Dropout(0.2))

model.add(Dense(
    output_dim=layers[3]))
model.add(Activation("linear"))

ただし、線形回帰または1つの隠れ層を持つ単純なフィードフォワードネットワークを実行し、LSTMと精度を比較することをお勧めします。特に、一度に1つの出力を予測し、それを入力としてフィードバックする場合、エラーが簡単に蓄積して、非常に悪い予測がさらに続く可能性があります。

2
Imran

この質問に追加したいのですが

TimeDistributedレイヤーを追加しました。私の考えは、アルゴリズムが値を孤立した値ではなく時系列として予測することでした(私は正しいですか?)

私自身はKeras TimeDistributedレイヤーの背後にある機能を理解するのにかなり苦労しました。

あなたの動機は、時系列予測の計算をnot分離する権利があると主張します。具体的にはdo将来の形状を予測するときに、シリーズ全体の特性と相互依存性を一緒に取得したくない場合。

ただし、これはTimeDistributed Layerの目的とは正反対です。各タイムステップで計算を分離するためのものです。なぜこれが便利なのでしょうか?完全に異なるタスクの場合、例えばシーケンス入力(i1, i2, i3, ..., i_n)があり、各タイムステップのラベル(label1, label2, label1, ..., label2)を個別に出力することを目的としたシーケンスラベリング。

最高の説明は、この postKeras Documentation にあります。

このため、TimeDistributedレイヤーを追加するすべての直観に対してが時系列予測の良いアイデアになることはないと主張します。それについて他の意見を聞いて喜んで!

1
ATrain