RNN (Reccurent Neural Network) ist auch in TensorFlow implementiert, und obwohl es ein Tutorial gibt, ist das Beispiel selbst ein wenig kompliziert im Umgang mit dem Sprachmodell, und ich hatte das Gefühl, dass es für Anfänger schwer zu verstehen ist.
Dieses Mal werde ich die RNN-Implementierung in TensorFlow ausprobieren, wobei ich das Problem des Umgangs mit einem einfacheren Modell als Beispiel nehme, das kein Sprachmodell ist.
Da die Version von TensorFlow aktualisiert wurde und ein Teil nicht funktioniert, hier (TensorFlow RNN-bezogener Import oder Basic LSTMCell-bezogener Fehler (v 0.11r ~) / items / dd24f176023b65e78f84)) Versuch es bitte.
Das einfache RNN-Modell und seine Implementierungsmethode sind im Blog Peters Anmerkung sehr hilfreich. Wenn Sie also zum ersten Mal hier sind, lesen Sie dies bitte zuerst. Ich empfehle es. Wenn Sie die RNN-Zahl von der obigen Site zitieren,
Es sieht aus wie das.
Mit anderen Worten, nach dem Multiplizieren der Daten von der Eingabeschichteinheit x mit dem Gewicht W_x wird die Ausgabe der Einheit s, die in die verborgene Schichteinheit s eintritt, rekursiv, und das Ergebnis der Anwendung des Gewichts W_rec ist die Einheit s im nächsten Schritt. eingeben. Unter Berücksichtigung des erweiterten Zustands rechts in der obigen Abbildung ändert der Zustand des Anfangswertes s_0 der verborgenen Schichteinheit den Zustand, während das Gewicht W_rec im Verlauf des Schritts multipliziert wird. Zu diesem Zeitpunkt wird x in jedem Schritt eingegeben, und der Zustand von s_n im letzten Schritt wird an die Ausgabeschichteinheit y ausgegeben.
Es ist ein Fluss wie dieser.
Das RNN-Modell von Peters Anmerkung ist ein Netzwerkmodell, das den Gesamtwert ausgibt, wenn der numerische Wert von X_k = 0 oder 1 eingegeben wird. ..
Zum Beispiel
X = [0. 1. 1. 0. 1. 0. 0. 1. 0. 0.]
Ist der Gesamtwert dieser Liste.
Y = 2.
Ist ein Modell, das korrekt ausgegeben wird. Es ist ein Modell, das sofort ein Ergebnis liefert, wenn Sie es einfach hinzufügen. Dieses Mal finden wir es jedoch, indem wir es mit RNN trainieren.
LSTM
Das RNN-Tutorial von TensorFlow verwendet jedoch eine Methode namens LSTM (Long-Short Term Memory) anstelle einer einfachen RNN. Wie in der obigen Abbildung gezeigt, wird bei einem normalen RNN die Größe des NN proportional zur Anzahl der Schritte immer größer. Daher besteht das Problem, dass der Rechenaufwand und der Speicher, die zum Anwenden des Fehlerrückverteilungsverfahrens erforderlich sind, zunehmen, der propagierte Fehler explodiert und die Berechnung instabil wird.
Andererseits wird in LSTM durch Verwendung der LSTM-Einheit anstelle der einfachen verborgenen Schicht, wie viel der Kernwert (Speicherzellenwert) der Einheit beim nächsten Mal beibehalten wird und wie stark er den nächsten Schritt beeinflusst Sie können es anpassen.
Eine LSTM-Einheit entspricht der Abbildung oben.
h ^ {l - 1} _t
und Ausgabe der l-ten verborgenen Schicht zum Zeitpunkt t - 1h_ {t - 1 } ^ l
.Es besteht aus den oben genannten Elementen.
Eine ausführliche Erläuterung von LSTM finden Sie in Christopher Olahs Blogbeitrag (http://colah.github.io/posts/2015-08-Understanding-LSTMs/. 08-Understanding-LSTMs /)), was eine großartige Lernerfahrung ist.
Ursprünglich ist es im obigen Beispiel nicht erforderlich, das LSTM herauszubringen, da alle vorherigen Eingaben im aktuellen Schritt gleichermaßen funktionieren. Dieses Mal werde ich jedoch das obige Gesamtbeispiel mit BasicLSTMCell versuchen, das standardmäßig in TensoreFlow implementiert ist. Ich habe den Code in https://github.com/yukiB/rnntest eingefügt.
Erstens die Datenerstellung
def create_data(num_of_samples, sequence_len):
X = np.zeros((num_of_samples, sequence_len))
for row_idx in range(nb_of_samples):
X[row_idx,:] = np.around(np.random.rand(sequence_len)).astype(int)
# Create the targets for each sequence
t = np.sum(X, axis=1)
return X, t
Es wird von gemacht.
Das Design der LSTM-Schicht ist
def inference(input_ph, istate_ph):
with tf.name_scope("inference") as scope:
weight1_var = tf.Variable(tf.truncated_normal([num_of_input_nodes, num_of_hidden_nodes], stddev=0.1), name="weight1")
weight2_var = tf.Variable(tf.truncated_normal([num_of_hidden_nodes, num_of_output_nodes], stddev=0.1), name="weight2")
bias1_var = tf.Variable(tf.truncated_normal([num_of_hidden_nodes], stddev=0.1), name="bias1")
bias2_var = tf.Variable(tf.truncated_normal([num_of_output_nodes], stddev=0.1), name="bias2")
in1 = tf.transpose(input_ph, [1, 0, 2])
in2 = tf.reshape(in1, [-1, num_of_input_nodes])
in3 = tf.matmul(in2, weight1_var) + bias1_var
in4 = tf.split(0, length_of_sequences, in3)
cell = rnn_cell.BasicLSTMCell(num_of_hidden_nodes, forget_bias=forget_bias)
rnn_output, states_op = rnn.rnn(cell, in4, initial_state=istate_ph)
output_op = tf.matmul(rnn_output[-1], weight2_var) + bias2_var
return output_op
Es wird um gemacht.
in3 = tf.matmul(in2, weight1_var) + bias1_var
Gibt die Formel für die Zellenaktualisierung in der LSTM-Einheit an. Ebenfalls
output_op = tf.matmul(rnn_output[-1], weight2_var) + bias2_var
Die von der letzten LSTM-Schicht aller Schritte erhaltene Ausgabe wird gewichtet und vorgespannt, um die endgültige Ausgabe zu erhalten.
In Bezug auf die Kostenberechnung haben wir, da der Ausgabewert diesmal ein kontinuierlicher Wert ist, MSE (Mean Square Error) verwendet und so entworfen, dass die Einheitendaten unverändert übergeben werden, ohne die Aktivierungsfunktion zu übergeben.
def loss(output_op, supervisor_ph):
with tf.name_scope("loss") as scope:
square_error = tf.reduce_mean(tf.square(output_op - supervisor_ph))
loss_op = square_error
tf.scalar_summary("loss", loss_op)
return loss_op
Um die Genauigkeit zu bewerten, haben wir eine Kombination aus 100 Listen und richtigen Antworten erstellt und das Verhältnis derjenigen mit einem Unterschied zwischen dem Vorhersageergebnis und der richtigen Antwort von weniger als 0,05 berechnet.
def calc_accuracy(output_op, prints=False):
inputs, ts = make_prediction(num_of_prediction_epochs)
pred_dict = {
input_ph: inputs,
supervisor_ph: ts,
istate_ph: np.zeros((num_of_prediction_epochs, num_of_hidden_nodes * 2)),
}
output= sess.run([output_op], feed_dict=pred_dict)
def print_result (p, q):
print("output: %f, correct: %d" % (p , q))
if prints:
[print_result(p, q) for p, q in zip(output[0], ts)]
opt = abs(output - ts)[0]
total = sum([1 if x[0] < 0.05 else 0 for x in opt])
print("accuracy %f" % (total/float(len(ts))))
return output
Geben Sie an dieser Stelle den Optimierer an und starten Sie die Berechnung.
def training(loss_op):
with tf.name_scope("training") as scope:
training_op = optimizer.minimize(loss_op)
return training_op
random.seed(0)
np.random.seed(0)
tf.set_random_seed(0)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
X, t = create_data(num_of_sample, length_of_sequences)
with tf.Graph().as_default():
input_ph = tf.placeholder(tf.float32, [None, length_of_sequences, num_of_input_nodes], name="input")
supervisor_ph = tf.placeholder(tf.float32, [None, num_of_output_nodes], name="supervisor")
istate_ph = tf.placeholder(tf.float32, [None, num_of_hidden_nodes * 2], name="istate")
output_op, states_op, datas_op = inference(input_ph, istate_ph)
loss_op = loss(output_op, supervisor_ph)
training_op = training(loss_op)
summary_op = tf.merge_all_summaries()
init = tf.initialize_all_variables()
with tf.Session() as sess:
saver = tf.train.Saver()
summary_writer = tf.train.SummaryWriter("/tmp/tensorflow_log", graph=sess.graph)
sess.run(init)
for epoch in range(num_of_training_epochs):
inputs, supervisors = get_batch(size_of_mini_batch, X, t)
train_dict = {
input_ph: inputs,
supervisor_ph: supervisors,
istate_ph: np.zeros((size_of_mini_batch, num_of_hidden_nodes * 2)),
}
sess.run(training_op, feed_dict=train_dict)
if (epoch ) % 100 == 0:
summary_str, train_loss = sess.run([summary_op, loss_op], feed_dict=train_dict)
print("train#%d, train loss: %e" % (epoch, train_loss))
summary_writer.add_summary(summary_str, epoch)
if (epoch ) % 500 == 0:
calc_accuracy(output_op)
Der Code in https://github.com/yukiB/rnntest gibt das Endergebnis wie folgt aus.
[0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0]
output: 6.010024, correct: 6
[1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0]
output: 5.986825, correct: 6
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
output: 0.223431, correct: 0
[0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
output: 3.002296, correct: 3
...
accuracy 0.980000
In der vorliegenden Umgebung betrug die Genauigkeit etwa 98%, da 5000 Mal in Chargen von 100 Stück gelernt wurde. Anscheinend lernt es richtig.
Auch als ich die Konvergenz der Kostenfunktion mit TensorBoard überprüfte
Es wurde wie oben.
Dieses Mal habe ich versucht, die RNN-Implementierung von TensorFLow durch ein einfaches Summierungsmodell zu sehen. Wenn Sie den Optimierer oder die Anzahl der ausgeblendeten Ebenen ändern, ändert sich der Konvergenzgrad erheblich. Daher ist es interessant, ihn auszuprobieren.
Recommended Posts