KerasのLSTMのシーケンス長の変更について質問があります。サイズ200のバッチと可変長(= x)のシーケンスを、シーケンス(=> [200、x、100])の各オブジェクトに対して100個の特徴とともにLSTMに渡します。
LSTM(100, return_sequences=True, stateful=True, input_shape=(None, 100), batch_input_shape=(200, None, 100))
次のランダムに作成された行列にモデルを適合させています。
x_train = np.random.random((1000, 50, 100))
x_train_2 = np.random.random((1000, 10,100))
LSTM(およびKerasの実装)を正しく理解している限り、xはLSTMセルの数を指す必要があります。各LSTMセルについて、状態と3つの行列を学習する必要があります(セルの入力、状態、および出力用)。最大までパディングせずに、さまざまなシーケンス長をLSTMに渡すことはどのように可能ですか。私がしたように、指定された長さ?コードは実行されていますが、実際には実行されるべきではありません(私の理解では)。後でシーケンス長が60の別のx_train_3を渡すことも可能ですが、余分な10個のセルの状態と行列があってはなりません。
ちなみに、私はKerasバージョン1.0.8とTensorflow GPU0.9を使用しています。
これが私のサンプルコードです:
from keras.models import Sequential
from keras.layers import LSTM, Dense
import numpy as np
from keras import backend as K
with K.get_session():
# create model
model = Sequential()
model.add(LSTM(100, return_sequences=True, stateful=True, input_shape=(None, 100),
batch_input_shape=(200, None, 100)))
model.add(LSTM(100))
model.add(Dense(2, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# Generate dummy training data
x_train = np.random.random((1000, 50, 100))
x_train_2 = np.random.random((1000, 10, 100))
y_train = np.random.random((1000, 2))
y_train_2 = np.random.random((1000, 2))
# Generate dummy validation data
x_val = np.random.random((200, 50, 100))
y_val = np.random.random((200, 2))
# fit and eval models
model.fit(x_train, y_train, batch_size=200, nb_Epoch=1, shuffle=False, validation_data=(x_val, y_val), verbose=1)
model.fit(x_train_2, y_train_2, batch_size=200, nb_Epoch=1, shuffle=False, validation_data=(x_val, y_val), verbose=1)
score = model.evaluate(x_val, y_val, batch_size=200, verbose=1)
まず、stateful=True
とbatch_input
は必要ないようです。これらは、非常に長いシーケンスをパーツに分割し、シーケンスが終了したとモデルが考えずに各パーツを個別にトレーニングする場合を対象としています。
ステートフルレイヤーを使用する場合、特定のバッチが長いシーケンスの最後の部分であると判断したときに、状態/メモリを手動でリセット/消去する必要があります。
シーケンス全体を操作しているようです。ステートフルは必要ありません。
パディングは厳密には必要ありませんが、パディング+マスキングを使用して追加の手順を無視できるようです。パディングを使用したくない場合は、データを小さなバッチに分割し、各バッチのシーケンス長を変えることができます。これを参照してください:stackoverflow.com/questions/46144191
シーケンスの長さ(タイムステップ)は、セル/ユニットの数や重量を変更しません。さまざまな長さを使用してトレーニングすることが可能です。変更できない次元は、特徴の量です。
入力寸法:
入力ディメンションは(NumberOfSequences, Length, Features)
です。
入力形状とセル数の関係はまったくありません。これは、ステップまたは再帰の数のみを運びます。これはLength
次元です。
セル:
LSTM層のセルは、密な層の「ユニット」のように正確に動作します。
セルはステップではありません。セルは、「並列」操作の数だけです。セルの各グループは、繰り返しの操作と手順を一緒に実行します。
@ Yu-Yangがコメントでよく気づいたように、セル間で会話があります。しかし、それらがステップを通じて引き継がれる同じエンティティであるという考えは依然として有効です。
this などの画像に表示される小さなブロックはセルではなく、ステップです。
可変長:
とはいえ、シーケンスの長さは、LSTMレイヤーのパラメーター(行列)の数にはまったく影響しません。ステップ数に影響するだけです。
レイヤー内の固定数の行列は、長いシーケンスの場合はより多く再計算され、短いシーケンスの場合はより少ない回数で再計算されます。ただし、すべての場合において、更新を取得して次のステップに渡されるのは1つのマトリックスです。
シーケンスの長さは、更新の数のみが異なります。
レイヤー定義:
セルの数はいくつでもかまいません。これは、連携して動作する並列ミニブレインの数を定義するだけです(つまり、多かれ少なかれ強力なネットワークと、多かれ少なかれ出力機能を意味します)。
LSTM(units=78)
#will work perfectly well, and will output 78 "features".
#although it will be less intelligent than one with 100 units, outputting 100 features.
次のステップに渡され続ける固有の重みマトリックスと固有の状態/メモリマトリックスがあります。これらのマトリックスは、各ステップで単に「更新」されますが、各ステップに1つのマトリックスはありません。
各ボックス「A」は、同じグループの行列(状態、重み、...)が使用および更新されるステップです。
4つのセルはありませんが、1つの同じセルが4つの更新を実行し、入力ごとに1つの更新を実行します。
各X1、X2、...は、長さ次元のシーケンスの1つのスライスです。
長いシーケンスは、短いシーケンスよりも行列を再利用および更新する回数が多くなります。しかし、それはまだ1つのセルです。
セルの数は確かに行列のサイズに影響しますが、シーケンスの長さには依存しません。すべてのセルは並行して動作し、それらの間で会話が行われます。
モデルでは、次のようなLSTMレイヤーを作成できます。
model.add(LSTM(anyNumber, return_sequences=True, input_shape=(None, 100)))
model.add(LSTM(anyOtherNumber))
このようにinput_shape
でNone
を使用することにより、任意の長さのシーケンスを受け入れることをモデルにすでに伝えています。
あなたがしなければならないのは訓練だけです。そして、トレーニング用のコードは問題ありません。許可されていない唯一のことは、内部に異なる長さのバッチを作成することです。したがって、これまでと同様に、長さごとにバッチを作成し、各バッチをトレーニングします。