web-dev-qa-db-ja.com

keras lstmが正しくないinput_shape

私はlstmモデルを使用して天気を予測しようとしています(主にlstmについて学習し、pythonを使用しています)。

500,000行のデータセットがあり、それぞれが日付を表し、8つの列が特徴です。

以下は私のモデルです。

 model = Sequential()      
 model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))   
 model.add(Dropout(0.2))

 model.add(LSTM(100, return_sequences=True))
 model.add(Dropout(0.2))

 model.add(LSTM(50, return_sequences=False))
 model.add(Dropout(0.2))

 model.add(Dense(1))
 model.add(Activation('linear'))

 model.fit(
        X,
        y,
        batch_size=512,
        epochs=100,
        validation_split=0.05)

私が理解している入力パラメーターの場合、最初のパラメーターは時間ステップなので、ここでは、最後の30観測を使用して次の値を予測する必要があると考えています。私が理解している8つは、空気圧、温度などの特徴です。

私のX行列は、下の行を含む3D行列に変換するので、Xは500000、8、1行列になります。

X = np.reshape(X, (X.shape[0], X.shape[1], 1))

モデルを実行すると、以下のエラーが表示されます。

ValueError:入力チェック時のエラー:予期されたlstm_3_inputは形状(30、8)ですが、形状(8、1)の配列を取得しました

何が悪いのですか?

3
mHelpMe

レイヤーがどのように機能するかについて簡単な説明が必要なだけかもしれません。特に、すべてのKerasレイヤーは次のように動作することに注意してください:

NAME(output_dim, input_shape = (...,input_dim))

たとえば、15000、3つの長いベクトルがあり、それらを5つの長いベクトルに変更したいとします。次に、このようなものはそれを行います:

import numpy as np, tensorflow as tf

X = np.random.random((15000,3))
Y = np.random.random((15000,5))

M = tf.keras.models.Sequential()
M.add(tf.keras.layers.Dense(5,input_shape=(3,)))

M.compile('sgd','mse')
M.fit(X,Y) # Take note that I provided complete working code here. Good practice. 
           # I even include the imports and random data to check that it works. 

同様に、入力が(1000,10,5)のようになり、LSTM(7)のようなLSTMを介して実行した場合、次に、出力として(...、7)のようなものが得られることを(自動的に)知る必要があります。これらの5つの長いベクトルは、7つの長いベクトルに変更されます。理解するルール。最後の次元は常に変更するベクトルであり、レイヤーの最初のパラメーターは常にそれを変更する次元です。

次に、LSTMについて2番目に学習します。時間軸を使用します(これは最後の軸ではありません。先ほど説明したように、これは常に「変化する次元軸」です)。return_sequences= Falseの場合は削除され、return_sequences = Trueの場合は保持されます。いくつかの例:

LSTM(7) # (10000,100,5) -> (10000,7)
# Here the LSTM will loop through the 100, 5 long vectors (like a time series with memory),
# producing 7 long vectors. Only the last 7 long vector is kept. 
LSTM(7,return_sequences=True) # (10000,100,5) -> (10000,100,7)
# Same thing as the layer above, except we keep all the intermediate steps. 

次のようなレイヤーを提供します。

LSTM(50,input_shape=(30,8),return_sequences=True) # (10000,30,8) -> (10000,30,50)

30がLSTMモデルで使用されるTIMEディメンションであることに注意してください。 8と50はINPUT_DIMとOUTPUT_DIMであり、時間軸とは関係ありません。もう1つのよくある誤解は、LSTMが各サンプルに独自の完全な過去と時間軸を提供することを期待していることに注意してください。つまり、LSTMは前のサンプルポイントを次のサンプルポイントに使用しません。各サンプルは独立しており、独自の完全な過去のデータが付属しています。

それでは、モデルを見てみましょう。第一歩。モデルは何をしていて、どのようなデータを期待していますか?

from tensorflow.keras.layers import LSTM, Dropout, Activation
from tensorflow.keras.models import Sequential

model = Sequential()      
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))   
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile('sgd','mse')

print(model.input_shape)
model.summary() # Lets see what your model is doing. 

だから、今あなたのモデルがはっきりと見える:(10000,30,8)->(10000,30,50)->(10000,30,100)->(10000,50)->(10000,1)

期待していましたか?それらが中間ステップのディメンションになることをご存知ですか?モデルが予期する入力と出力がわかったので、モデルがその種のデータをトレーニングして機能することを簡単に確認できます。

from tensorflow.keras.layers import LSTM, Dropout, Activation
from tensorflow.keras.models import Sequential
import numpy as np

X = np.random.random((10000,30,8))
Y = np.random.random((10000,1))

model = Sequential()      
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))   
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile('sgd','mse')

model.fit(X,Y)

モデルが(...、30,8)のような入力を期待していることに気づきましたか?モデルが(...、1)のような出力データを期待していることをご存知でしたか?モデルが何を必要としているのかを理解していることは、興味のあるデータに合わせてモデルを変更できることも意味します。時間軸のような8つのパラメーターでデータを実行する場合は、入力ディメンションがそれを反映する必要があります。 30を8に変更し、8を1に変更します。これを行う場合、最初のレイヤーが各1の長いベクトル(単一の数値)を50の長いベクトルに拡張していることにも注意してください。それはあなたがモデルにしたいことのように聞こえますか?多分あなたのLSTMは50 ...などではなくLSTM(2)またはLSTM(5)であるべきです。次の1000時間は、使用しているデータを処理する適切なパラメーターを見つけるために費やすことができます。

FEATURE空間をTIME SPACEとして扱いたくない場合は、データをサイズ10のバッチに繰り返してみてください。各サンプルには独自の履歴があり、ディメンションは(10000,10,8)と言っています。次に、LSTM(50)は8の長い特徴空間を使用し、10の時間軸を超えて50の長い特徴空間に変更します。たぶん、return_sequences = Falseを使用して最後の特徴空間を保持したいだけかもしれません。

1
Bobby Ocean

LSTMのデータを準備するために使用した関数をコピーします。

from itertools import islice

def slice_data_for_lstm(data, lookback):
    return np.array(list(Zip(*[islice(np.array(data), i, None, 1) for i in range(lookback)])))

X_sliced = slice_data_for_lstm(X, 30)

あなたの場合、ルックバックは30である必要があり、(8、1)機能の30スタックを作成します。結果のデータは形(N、30、8、1)です。

0
Metehan