ベンジオらによる「勾配降下法による長期依存性の学習は難しい」という論文から実験をやり直すことで、LSTMがバニラ/単純リカレントニューラルネットワーク(SRNN)よりも長い期間情報を記憶できる理由をよく理解したいと思います。1994。
その論文の図1と2を参照してください。シーケンスが指定されている場合、タスクは単純です。高い値(1など)で始まる場合、出力ラベルは1です。低い値(たとえば-1)で始まる場合、出力ラベルは0です。中央はノイズです。このタスクは、モデルが正しいラベルを出力するためにミドルノイズを通過するときに開始値を覚えておく必要があるため、情報ラッチと呼ばれます。単一ニューロンRNNを使用して、このような動作を示すモデルを作成しました。図2(b)は結果を示しています。このようなモデルのトレーニングの成功頻度は、シーケンスの長さが増加するにつれて劇的に減少します。LSTMは、1994年にまだ発明されていないため、結果はありませんでした。
それで、私は好奇心が強くなり、LSTMが実際にそのようなタスクに対してより良いパフォーマンスを発揮するかどうかを見たいと思います。同様に、バニラセルとLSTMセルの両方に単一のニューロンRNNを構築して、情報ラッチをモデル化しました。驚いたことに、LSTMのパフォーマンスが低下していることがわかりました。理由はわかりません。誰かが私を説明するのを手伝ってもらえますか、または私のコードに何か問題がある場合はどうですか?
これが私の結果です:
これが私のコードです:
import matplotlib.pyplot as plt
import numpy as np
from keras.models import Model
from keras.layers import Input, LSTM, Dense, SimpleRNN
N = 10000
num_repeats = 30
num_epochs = 5
# sequence length options
lens = [2, 5, 8, 10, 15, 20, 25, 30] + np.arange(30, 210, 10).tolist()
res = {}
for (RNN_CELL, key) in zip([SimpleRNN, LSTM], ['srnn', 'lstm']):
res[key] = {}
print(key, end=': ')
for seq_len in lens:
print(seq_len, end=',')
xs = np.zeros((N, seq_len))
ys = np.zeros(N)
# construct input data
positive_indexes = np.arange(N // 2)
negative_indexes = np.arange(N // 2, N)
xs[positive_indexes, 0] = 1
ys[positive_indexes] = 1
xs[negative_indexes, 0] = -1
ys[negative_indexes] = 0
noise = np.random.normal(loc=0, scale=0.1, size=(N, seq_len))
train_xs = (xs + noise).reshape(N, seq_len, 1)
train_ys = ys
# repeat each experiments multiple times
hists = []
for i in range(num_repeats):
inputs = Input(shape=(None, 1), name='input')
rnn = RNN_CELL(1, input_shape=(None, 1), name='rnn')(inputs)
out = Dense(2, activation='softmax', name='output')(rnn)
model = Model(inputs, out)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
hist = model.fit(train_xs, train_ys, epochs=num_epochs, shuffle=True, validation_split=0.2, batch_size=16, verbose=0)
hists.append(hist.history['val_acc'][-1])
res[key][seq_len] = hists
print()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(pd.DataFrame.from_dict(res['lstm']).mean(), label='lstm')
ax.plot(pd.DataFrame.from_dict(res['srnn']).mean(), label='srnn')
ax.legend()
結果はノートブックにも表示されます。これは、結果を複製したい場合に便利です。CPUのみを使用して私のマシンで実験を実行するのに1日以上かかりました。GPU対応のマシンではより高速になる可能性があります。
2018-04-18の更新:
「リカレントニューラルネットワークのトレーニングの難しさ」の図6に触発されたRNNの風景の図を再現してみました。ここで観察された長いシーケンスのトレーニングの難しさを説明することに関連している可能性がある、反復/タイムステップ/シーケンスの長さが増加するにつれて、損失の風景に崖が形成されるのを見るのは興味深いです。詳細については、こちらをご覧ください。
2018-04-19の更新
@shimaoの実験を拡張します。LSTMとGRUは情報のラッチがあまり得意ではないようです。しかし、ビットリレーと呼ばれる別のタスク(@shimaoのタスク2)に切り替えると、SRNNとLSTMが同じように悪いのに、GRUのパフォーマンスが向上します。
今、私はセルタイプのパフォーマンスがタスク固有であると思う傾向があります。
タスク1:情報のラッチ(1ユニット、10回の繰り返し、10エポック)
タスク2:ビットリレー(8ユニット、10回の繰り返し、10エポック)
エラーバーは標準偏差です。
次に、興味深い質問は、なぜLSTMが情報ラッチに機能しないのかということです。タスクの単純さを考えると、それは機能するはずですよね。グラデーションに関して、景観(崖など)に関連している可能性があります。