[PYTHON] Erstellen eines seq2seq-Modells unter Verwendung der funktionalen API-Inferenz von keras

Was für ein Artikel?

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

Inhaltsverzeichnis

  1. Übersicht
  2. Vorverarbeitung
  3. Modellbau & Lernen
  4. Argumentation (Imakoko)
  5. Modellverbesserung (noch nicht vorgenommen)

Motivation für diesen Artikel

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.

Was Sie ableiten müssen

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.

Inferenzimplementierung

Modell laden

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.

Definition des Berechnungsdiagramms

Wir werden das in der folgenden Abbildung gezeigte Modell erstellen LSTM-Page-1.png

Encoder

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.

Decoder

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

Überprüfen Sie das generierte Modell

SVG(model_to_dot(decoder_model).create(prog='dot', format='svg'))

image.png

Definition der zu übersetzenden Funktion

Konvertieren Sie die Eingabewort-ID in die Ausgabewort-ID

Geben Sie tatsächlich die Wort-ID-Spalte ein, um die übersetzte Wort-ID zu erhalten. Machen

  1. Codierung in den Hidden-Layer-Speicher per Encoder
  2. Vorhersage des ersten Wortes unter Verwendung des vom Codierer erhaltenen Speichers und des Starttokens
  3. Vorhersage des nächsten Wortes unter Verwendung des Speichers des vorherigen Wortes und der vorherigen verborgenen Schicht
  4. Ausgabe des Vorhersageergebnisses

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.]])

Konvertieren Sie die Ausgabewort-ID in ein Wort

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.

Referenz

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

Erstellen eines seq2seq-Modells unter Verwendung der funktionalen API-Inferenz von keras
Erstellen eines seq2seq-Modells mithilfe der Funktions-API-Übersicht von keras
Erstellen Sie ein seq2seq-Modell mit dem Functional API Model Building & Learning von keras
Implementierung von VGG16 mit Keras, die ohne Verwendung eines trainierten Modells erstellt wurden
Erstellen Sie mit turicreate eine API, die Daten aus einem Modell zurückgibt
Multi-Input / Multi-Output-Modell mit funktionaler API
Erstellen eines Lernmodells mit MNIST
Erstellen Sie die CRUD-API mit der Fast API
Versuchen Sie, XOR mit der Keras Functional API zu implementieren
Erstellen einer virtuellen Umgebung mit homebrew + pyenv-virtualenv
Holen Sie sich ein Referenzmodell mit Django Serializer
Fügen Sie mithilfe des Keras-Backends eine Ebene hinzu
Erstellen Sie eine REST-API mit dem in Lobe und TensorFlow Serving erlernten Modell.
Python: Zeitreihenanalyse: Erstellen eines SARIMA-Modells
Erstellen wir eine REST-API mit SpringBoot + MongoDB
Erstellen einer interaktiven Anwendung mithilfe eines Themenmodells
Bereiten Sie einen Pseudo-API-Server mit GitHub-Aktionen vor