web-dev-qa-db-ja.com

TF LSTM複数ステップ予測が間違っているようです

enter image description here

ここで完全なソースを見ることができます

https://colab.research.google.com/drive/1kk24KjpZQEZpdlBxr4D4DO-IGHJ0439v?usp=sharing

x_testの元のデータには、非線形ランダムウォークプロパティがあります。

しかし、新しく予測された20個の値は線形の形をしています。

明らかに、私は間違った予測をしましたか?

1
user12483252

私は先に進んで、あなたのデータを少し読みました。トレーニングとモデルに関するコメント:

1)LSTMを具体的にトレーニングして、過去の20個の値から1つの値を未来に予測しました。最初の1つの値から別の19個の値を予測するために、そのモデルが外挿できると予想するのはなぜですか?モデルはそれを行うように訓練されておらず、それが重要であることを知りません。

2)モデルが非常に小さい。モデルには491個の変数(model.summary())があり、非常に小さいです。株式市場に影響を与える機能はいくつあると思いますか?各機能をモデル化する変数はいくつあると思いますか?ほとんどのディープラーニングでは、何百万もの変数を使用して、株式市場のような複雑なものを学習します。また、これは非常に複雑な分野であり、世界中の何百万人もの人々に研究を依頼しています。

3)データがどれほど複雑であるかについてのトレーニングはほとんど行っていません。 GPUで100エポック、つまり約250秒のトレーニングを実行しました。

4)あなたのモデルは非常にオーバーフィットです。 「低損失」==「良い予測モデル」と誤解していると思いますが、これは事実ではありません。これは私がググった例ですが、私が何を意味するかを示しています

https://towardsdatascience.com/regularization-the-path-to-bias-variance-trade-off-b7a7088b4577

https://miro.medium.com/max/552/1%[email protected]

この例では、トレーニング済みモデルの損失は本質的にゼロであり、入力データを完全に予測します。しかし、モデルは、ノイズのある入力データを駆動する基礎となるフィーチャカーブについて何も明確に認識していません。したがって、モデルで次の値を予測しようとすると、非常に不正確になります。

5)モデルのトレーニングについて誤解していると思います。モデルをトレーニングすると、低損失を生み出す「一般的な」答えに収束します。モデルは、本当によく予測する重みの極端な例を見つけることはありません。損失が少ない一般的なソリューションを見つけてゆっくりと収束させるだけです。たとえば、ウェイトをゼロに向かってわずかに調整すると、損失が小さくなり、トレーニング中に繰り返し強調されます。一様な線形回答を予測すると、一見ランダムに見えるデータのセットの中で最も損失が少ない場合、トレーニング中に何度も何度も強化されます。一般的に(上記でコメントしたように)、モデルが一様にランダムな情報に直面すると、情報の平均が優先される傾向があります(バッチ間での損失が少ないため)。

あなたが提供したコードとあなたが得た結果は期待されていると思います。


編集:

時系列データモデルのいくつかの例を次に示します(データに依存しますが、それらは優れています)。

# Basic LSTM that attempts to produce a prediction vector from a sequence of time data. 
model = tf.keras.Sequential([
    tf.keras.layers.LSTM(20), 
])

# Maybe throw a few LSTM layers to help learn the information, add some dimensions. 
model = tf.keras.Sequential([
    tf.keras.layers.LSTM(5,return_sequences=True), 
    tf.keras.layers.LSTM(50,return_sequences=True),
    tf.keras.layers.LSTM(20),
])

# Maybe some Dense layers should be used to re-arrange information. 
model = tf.keras.Sequential([
    tf.keras.layers.LSTM(20), 
    tf.keras.layers.Dense(500),
    tf.keras.layers.Dense(20),
])

多分いくつかのアクティベーションを投入するかもしれませんが、reluは便利かもしれません(不要な値を削除するためにレイヤーにガベージキャンを与えるようなものです)。あるいは、シグモイド(値を小さく保つ)またはソフトマックス(確率のような値を扱う)かもしれません。一部のドロップアウトレイヤーを投入して、過剰適合を防止することもできます(モデルをつま先に置いて、すばやく落ち着かないようにしてください)。また、データの正規化も役立ちます。重みが急速に増加することがわかった場合は、データを学習するときにモデルに小さな重みを使用するように強制する正規化を追加します。

model = tf.keras.Sequential([
    tf.keras.layers.LSTM(5,return_sequences=True,activation='relu'), 
    tf.keras.layers.Dropout(0.10),
    tf.keras.layers.LSTM(50,return_sequences=True,activation='relu'),
    tf.keras.layers.Dropout(0.10),
    tf.keras.layers.LSTM(20),
])

学習がうまくいかないと思われる場合は、「adam」から別の学習アルゴリズムに切り替えてください。多分、あなたの「平均二乗誤差」損失関数は、大きな誤差には厳しすぎ、おそらく学習を遅くします。代わりに「logcosh」を試してください。 24時間そのまま実行し、できればGPUを使用します。

LSTMレイヤーが遅すぎる場合。代わりに、いくつかのアテンションレイヤーまたは残差レイヤーを使用するように切り替えます(このカスタムアイデアについては、Googleにアクセスしてください)。

LSTMの代わりにGRUレイヤーを常に試すことができます。パフォーマンスはほぼ同じですが、トレーニングは少し速くなります。

2
Bobby Ocean

私が正しく理解していれば、反復予測を操作しようとしています。したがって、入力全体で与えられたシーケンス全体を使用して、次の値を予測します。最後に予測を追加し、プロセスを繰り返します。

この操作を計算するコードは少し混乱しています。書き直してみる

plist = x_test[-2]
for i in range(20):
    temp = model.predict(plist.reshape(-1,20,1))
    plist = np.append(plist[1:],temp[0])

私たちの目的はx_test [-1]を予測することなので、x_test [-2]から始めます。最後に、結果は以下に示されています

plt.plot(x_test[-1], label='true')
plt.plot(plist, label='pred')
plt.legend()

enter image description here

手順が正しくなりました(これも逆スケーリングなし)

1
Marco Cerliani