Für diejenigen, die dies oder jenes für Deep-Learning-Modellierung ausprobieren möchten, aber nicht wissen, wie sie es implementieren sollen Verwendung der funktionalen API von keras als Framework, das relativ flexibel und angemessen abstrahiert ist Versuchen Sie, seq2seq, das mit sequentiellen Funktionen schwierig ist, so einfach wie möglich zu implementieren
Ich konnte den ganzen Weg lernen, aber der Datenfluss zum Zeitpunkt des Lernens und der Datenfluss zum Zeitpunkt der Schlussfolgerung unterscheiden sich geringfügig. Wie kann ich anhand der aus dem Lernen gewonnenen Parameter Rückschlüsse ziehen? Ich werde die Frage beantworten.
Laden Sie zunächst das Modell, das einmal trainiert und gespeichert wurde. Da der Datenfluss während der Inferenz unterschiedlich ist, muss ein Modell mit einem anderen Berechnungsdiagramm als im Training definiert werden.
Auch um den Prozess der Vorhersage des nächsten Wortes aus dem vorherigen Wort zu realisieren Verwenden Sie das definierte Modell wie eine Funktion in einer Schleife, um nacheinander zu schließen.
Modelle, die in h5-Dateien usw. gespeichert sind, können wie folgt geladen werden.
model = keras.models.load_model(filepath)
Außerdem scheint Gurke veraltet zu sein.
Wir werden das in der folgenden Abbildung gezeigte Modell erstellen
Es kann derselbe Encoder wie zum Zeitpunkt des Lernens verwendet werden.
#define encoder
encoder_model = Model(inputs=model.input[0], #encoder_input
outputs=model.get_layer('lstm_1').output[1:]) #enconder lstm hidden state
Wenn es so verwendet werden kann, wie es ist, ist es möglich, die Ausgabe in der Mitte von "Modell" auf diese Weise zu extrahieren.
Der Decoder hat einen etwas längeren Code. Es gibt drei Dinge, die mit dem Decoder zu tun haben: Einbetten (zum Erzwingen von Lehrern), LSTM und Dicht im vorherigen Wort. Embedding, LSTM und Dense haben während des Trainings jeweils Gewichte. Verwenden Sie daher diese Werte. Außerdem ist der Speicher der verborgenen Schicht, der in "LSTM" eingegeben werden soll, nicht immer derselbe wie der Encoderausgang, sondern der Speicher nach dem Ableiten des vorherigen Wortes, sodass er ab dem Zeitpunkt des Lernens neu geschrieben werden muss. Das Implementierungsbeispiel lautet wie folgt
from keras.layers import Input, LSTM, Dense, Embedding
#define decoder
embedding_dim = 256
units = 1024
vocab_tar_size = model.get_layer('dense_1').weights[1].shape.as_list()[0]
decoder_word_input = Input(shape=(1,),name='decoder_input')
decoder_input_embedding = Embedding(input_dim=vocab_tar_size,
output_dim=embedding_dim,
weights=model.get_layer('embedding_2').get_weights())(decoder_word_input)
decoder_state_input_h = Input(shape=(units,), name='decoder_input_h')
decoder_state_input_c = Input(shape=(units,), name='decoder_input_c')
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_lstm = LSTM(units,
return_sequences=False,
return_state=True,
weights=model.get_layer('lstm_2').get_weights())
decoder_output, state_h, state_c = decoder_lstm(decoder_input_embedding,
initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_dense = Dense(vocab_tar_size,
activation='softmax',
weights=model.get_layer('dense_1').get_weights())
decoder_output = decoder_dense(decoder_output)
decoder_model = Model(inputs=[decoder_word_input] + decoder_states_inputs,
outputs=[decoder_output] + decoder_states)
Was ist anders als Lernen
model.get_layer (<Ebenenname>). Get_weights ()
erhalten werden.Form
von Input
ist 1.return_sequences = True
von LSTM
, um die LSTM
-Ausgabe für jeden Schritt zu erhaltenModel
decoder_model` wurde ein Hidden-Layer-Speicher hinzugefügt.SVG(model_to_dot(decoder_model).create(prog='dot', format='svg'))
Geben Sie tatsächlich die Wort-ID-Spalte ein, um die übersetzte Wort-ID zu erhalten. Machen
ist. Das Implementierungsbeispiel lautet wie folgt. (Ich habe es geschrieben, damit es stapelweise verarbeitet werden kann, aber es ist nicht unbedingt erforderlich.)
def decode_sequence(input_seq, targ_lang, max_length_targ):
# Encode the input as state vectors.
states_value = encoder_model.predict(input_seq)
vocab_tar_size = np.array(list(targ_lang.index_word.keys())).max()
inp_batch_size = len(input_seq)
# Generate empty target sequence of length 1.
target_seq = np.zeros((inp_batch_size, 1))
# Populate the first character of target sequence with the start character.
target_seq[:, 0] = targ_lang.word_index['<start>']
# Sampling loop for a batch of sequences
decoded_sentence = np.zeros((inp_batch_size, max_length_targ))
for i in range(max_length_targ):
output_tokens, h, c = decoder_model.predict([target_seq] + states_value)
# Sample a token
sampled_token_index = np.argmax(output_tokens,axis=1) #array of size [inp_batch_size, 1]
decoded_sentence[:,i] = sampled_token_index
# Update the target sequence (of length 1).
target_seq = np.zeros((inp_batch_size, 1))
target_seq[:, 0] = sampled_token_index
# Update states
states_value = [h, c]
return decoded_sentence
Instanzen der Klasse "Model" haben eine "Predict" -Methode. Wenn Sie die Eingabe an die "Vorhersage" -Methode übergeben, wird die Berechnung gemäß dem definierten Berechnungsdiagramm durchgeführt und die Ausgabe wird erhalten.
Zuerst verwenden wir "encoder_model.predict", um die Eingabe in den Speicher der verborgenen Schicht zu codieren.
Unter der Annahme, dass "target_seq" mit einer Größe von "[batch_size, 1]" das vorherige Wort ist, verwenden Sie "decoder_model.predict" zusammen mit dem Speicher der verborgenen Ebene, um sich das nächste Wort und die als nächstes einzugebende verborgene Ebene zu merken. Ich erhalte
Die erhaltenen Wörter nehmen "argmax" nacheinander und nehmen Speichern Sie es in "decoded_sentence", so dass die Ausgabe die Größe "[batch_size, max_length_targ]" hat.
Führen Sie diese Schleife so oft wie die maximale Länge der Ausgabewortzeichenfolge aus und geben Sie "decoded_sentence" aus.
Ausgabebeispiel
array([[ 15., 33., 5., 27., 121., 9., 482., 6., 8.,
4., 3., 0., 0., 0., 0., 0., 0., 0.]])
Da die Wort-ID und die Wortkonvertierungsregel im Voraus von keras.preprocessing.text.Tokenizer
erhalten werden
Alles was Sie tun müssen, ist das Umwandlungsgesetz jeder Komponente von "ndarray" anzuwenden.
Damit Python-Funktionen auf allen Komponenten von "ndarray" funktionieren, können Sie "np.vectorize" verwenden, um ohne Schleifen zu schreiben
Das Implementierungsbeispiel lautet wie folgt
#decoded_Urteilswort_Konvertieren Sie den Index in ein Wort und entfernen Sie die Start- / End-Token
def seq2sentence(seq,lang):
def index2lang(idx, lang):
try:
return lang.index_word[idx]
except KeyError:
return ''
langseq2sentence = np.vectorize(lambda x: index2lang(x,lang),otypes=[str])
sentences = langseq2sentence(seq)
sentences = [' '.join(list(sentence)) for sentence in sentences]
sentences = [sentence.lstrip('<start>').strip(' ').strip('<end>') for sentence in sentences]
return sentences
Vorerst war die Ausnahmebehandlung enthalten. Entfernen Sie zum Schluss den verschwendeten Speicherplatz und starten / beenden Sie die Token, um den Vorgang abzuschließen.
Der Vorbehandlungsteil ist wie folgt Neuronale maschinelle Übersetzung mit Aufmerksamkeit https://www.tensorflow.org/tutorials/text/nmt_with_attention
Die Codebasis für den Lern- / Inferenzteil ist wie folgt Sequence to sequence example in Keras (character-level). https://keras.io/examples/lstm_seq2seq/
Die zum Lernen verwendeten Daten sind wie folgt https://github.com/odashi/small_parallel_enja
Das Repository mit dem Code für diesen Artikel https://github.com/nagiton/simple_NMT
Recommended Posts