TensorFlowをバックエンドとしてKerasを使用してLSTMを作成しました。num_stepが96のミニバッチがトレーニングに与えられる前に、LSTMの非表示状態は前のタイムステップの真の値に設定されます。
まず、パラメータとデータ:
batch_size = 10
num_steps = 96
num_input = num_output = 2
hidden_size = 8
X_train = np.array(X_train).reshape(-1, num_steps, num_input)
Y_train = np.array(Y_train).reshape(-1, num_steps, num_output)
X_test = np.array(X_test).reshape(-1, num_steps, num_input)
Y_test = np.array(Y_test).reshape(-1, num_steps, num_output)
Kerasモデルは、2つのLSTMレイヤーと1つのレイヤーで構成され、出力をnum_output(2)にトリミングします。
model = Sequential()
model.add(LSTM(hidden_size, batch_input_shape=((batch_size, num_steps, num_input)),
return_sequences=True, stateful = True)))
model.add(LSTM(hidden_size, return_sequences=True)))
model.add(Dropout(0.2))
model.add(TimeDistributed(Dense(num_output, activation='softmax')))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
ジェネレーターとトレーニング(hidden_states [x]の形状は(2、)):
def gen_data():
x = np.zeros((batch_size, num_steps, num_input))
y = np.zeros((batch_size, num_steps, num_output))
while True:
for i in range(batch_size):
model.layers[0].states[0] = K.variable(value=hidden_states[gen_data.current_idx]) # hidden_states[x] has shape (2,)
x[i, :, :] = X_train[gen_data.current_idx]
y[i, :, :] = Y_train[gen_data.current_idx]
gen_data.current_idx += 1
yield x, y
gen_data.current_idx = 0
for epoch in range(100):
model.fit_generator(generate_data(), len(X_train)//batch_size, 1,
validation_data=None, max_queue_size=1, shuffle=False)
gen_data.current_idx = 0
このコードではエラーは発生しませんが、2つの質問があります。
1)ジェネレーター内で、LSTMの非表示状態を形状(2、)のmodel.layers[0].states[0]
変数に設定hidden_states[gen_data.current_idx]
しました。非表示サイズが2より大きいLSTMでこれが可能なのはなぜですか?
2)の値はhidden_states[gen_data.current_idx]
、Kerasモデルからの出力である可能性もあります。2層LSTMがこのように非表示状態を設定することは理にかなっていますか?
LSTMは、cell state
とを計算するゲートで構成されていますhidden state
。
この図では、LSTMの右側から出ている上の矢印はセルの状態(c_t
)であり、下の矢印は非表示の状態(h_t
)です。セルの状態はゲート操作の結果であり、状態のサイズはhidden_size
LSTMのサイズと同じです。(対応する入力Xを使用して)展開するたびに、独自のセル状態になります。LSTMの場合、セルの状態はh_t
、(batch_size x hidden_size)の2つの値hidden_state()と(batch_size x hidden_size)のcell_state()で構成されc_t
ます。
batch_size = 2
num_steps = 5
num_input = num_output = 1
hidden_size = 8
inputs = Input(batch_shape=(batch_size,num_steps, num_input))
lstm, state_h, state_c = LSTM(hidden_size, return_state=True, return_sequences=True)(inputs)
model = Model(inputs=inputs, outputs=[state_h, state_c])
print (model.predict(np.zeros((batch_size, num_steps, num_input))))
print (model.layers[1].cell.state_size)
注: GRU / RNNの場合、セル状態はなく、非表示状態のみであるため、場合のセル状態はちょうどh_t
サイズ(batch_size、hidden_size)です。
状態テンソルの数は1(RNNおよびGRUの場合)または2(LSTMの場合)です。
あなたの例では、layers[0]
は1つのLSTMをlayers[1]
参照し、2番目のLSTMを参照します。c_t
(n-1)のセル状態からのようにn番目のバッチのセル状態()を初期化することを意図している場合、つまり前のバッチには2つのオプションがあります。
あなたはしかし、発電機でやっている方法は、使用states[1]
したい場合c_t
とstates[0]
についてh_t
。同様にlayers[0]
、1番目のLSTMとlayers[1]
2番目のLSTMにも使用します。ただし、set_value
代わりにメソッドを使用してください。以下の編集を参照してください。
kerasを使用するStateful=True
:statefulをtrueに設定すると、LSTM状態はバッチごとにリセットされません。したがって、5つのデータサンプル(それぞれがある程度のシーケンス長)を持つバッチがある場合、5つのデータサンプルのそれぞれのセル状態を取得します。statefulをtrueに設定すると、これらの状態は、次のバッチの次のバッチセル状態を初期化するために使用されます。
このメソッドset_value
は、テンソル変数の値を設定するために使用する必要があります。model.layers[0].states[0] = K.variable(value=hidden_states[gen_data.current_idx])
サイズの変数(batch_size X hidden_size)を指していたstate [0]をサイズの変数(batch_size x 2)に変更しているため、コードは有効です。テンソル変数の値を変更するのではなく、異なる次元の新しいテンソル変数を指すようにします。
テストコード:
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
model.layers[0].states[0]= K.variable(np.random.randn(10,2))
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
出力
<tf.Variable 'lstm_18/Variable:0' shape=(10, 8) dtype=float32_ref> 0x7f8812e6ee10
<tf.Variable 'Variable_2:0' shape=(10, 2) dtype=float32_ref> 0x7f881269afd0
ご覧のとおり、これらは2つの異なる変数です。これを行う正しい方法は
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
K.set_value(model.layers[0].states[0], np.random.randn(10,8))
print (model.layers[0].states[0], hex(id(model.layers[0].states[0])))
出力
<tf.Variable 'lstm_20/Variable:0' shape=(10, 8) dtype=float32_ref> 0x7f881138eb70
<tf.Variable 'lstm_20/Variable:0' shape=(10, 8) dtype=float32_ref> 0x7f881138eb70
コードが修正された場合
K.set_value(model.layers[0].states[0], np.random.randn(10,2))
テンソルのサイズと設定している値のサイズが一致しないため、エラーがスローされます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加