Ich möchte besser verstehen, warum sich LSTM über einen längeren Zeitraum an Informationen erinnern kann als Vanille / einfaches wiederkehrendes neuronales Netzwerk (SRNN), indem ich ein Experiment aus dem Artikel Lernen von Langzeitabhängigkeiten mit Gradientenabstieg von Bengio et al. 1994 .
Siehe Abb. 1. und 2 auf diesem Papier. Die Aufgabe ist in einer bestimmten Reihenfolge einfach. Wenn sie mit einem hohen Wert (z. B. 1) beginnt, lautet die Ausgabebezeichnung 1; Wenn es mit einem niedrigen Wert beginnt (z. B. -1), ist das Ausgabeetikett 0. Die Mitte ist Rauschen. Diese Aufgabe wird als Informations-Latching bezeichnet, da sich das Modell beim Durchlaufen des mittleren Rauschens den Startwert merken muss, um ein korrektes Etikett auszugeben. Es wurde ein einzelnes Neuron-RNN verwendet, um ein Modell zu erstellen, das ein solches Verhalten aufweist. Die Abbildung 2 (b) zeigt die Ergebnisse, und die Erfolgshäufigkeit des Trainings eines solchen Modells nimmt mit zunehmender Sequenzlänge dramatisch ab. Es gab kein Ergebnis für LSTM, da es 1994 noch nicht erfunden wurde.
Ich werde also neugierig und würde gerne sehen, ob LSTM für eine solche Aufgabe tatsächlich eine bessere Leistung erbringt. In ähnlicher Weise konstruierte ich ein einzelnes Neuron-RNN sowohl für Vanille- als auch für LSTM-Zellen, um das Informations-Latching zu modellieren. Überraschenderweise stellte ich fest, dass LSTM schlechter abschneidet, und ich weiß nicht warum. Könnte mir jemand helfen zu erklären oder wenn etwas mit meinem Code nicht stimmt, bitte?
Hier ist mein Ergebnis:
Hier ist mein Code:
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()
Ich habe auch das Ergebnis im Notizbuch angezeigt , was praktisch wäre, wenn Sie die Ergebnisse replizieren möchten. Es dauerte über einen Tag, bis das Experiment auf meinem Computer nur mit CPU ausgeführt wurde. Auf einem GPU-fähigen Computer könnte es schneller sein.
Update 2018-04-18 :
Ich habe versucht, eine Figur in der Landschaft von RNN zu reproduzieren, die von Abbildung 6 in Über die Schwierigkeit des Trainings wiederkehrender neuronaler Netze inspiriert ist . Ich finde es interessant, die Bildung von Klippen in der Verlustlandschaft zu sehen, wenn die Anzahl der Wiederholungen / Zeitschritte / Sequenzlängen zunimmt, was mit der Erklärung der hier beobachteten Schwierigkeit des Trainings langer Sequenzen zusammenhängen könnte. Weitere Details finden Sie hier .
Update 2018-04-19
@ Shimaos Experiment erweitern. Es scheint, dass LSTM und GRU einfach nicht so gut darin sind, Informationen zu erfassen. Wenn Sie jedoch zu einer anderen Aufgabe wechseln, die ich als Bit-Relay bezeichne (@ shimaos Aufgabe 2), ist die GRU besser, während SRNN und LSTM gleich schlecht sind.
Jetzt neige ich dazu zu glauben, dass die Leistung eines Zelltyps aufgabenspezifisch sein könnte.
Aufgabe 1: Informationsspeicherung (1 Einheit; 10 Wiederholungen; 10 Epochen)
Aufgabe 2: Bitrelais (8 Einheiten; 10 Wiederholungen; 10 Epochen)
Fehlerbalken sind Standardabweichungen.
Eine interessante Frage ist dann, warum LSTM beim Latching von Informationen nicht funktioniert. Angesichts der Einfachheit der Aufgabe sollte sie funktionieren können, nicht wahr? Könnte in Bezug auf die Steigungen mit der Landschaft (z. B. Klippen) zusammenhängen.