Pour ceux qui veulent essayer ceci ou cela pour la modélisation du deep learning mais ne savent pas comment l'implémenter Utiliser l'API fonctionnelle de Keras comme un framework relativement flexible et raisonnablement abstrait Essayez d'implémenter seq2seq, ce qui est difficile avec séquentiel, aussi simplement que possible
J'ai pu tout apprendre, mais le flux de données au moment de l'apprentissage et le flux de données au moment de l'inférence sont légèrement différents. Comment puis-je faire des inférences en utilisant les paramètres obtenus par l'apprentissage? Je vais répondre à la question.
Commençons par charger le modèle qui a été entraîné et enregistré une fois. Puisque le flux de données est différent lors de l'inférence, il est nécessaire de définir un modèle avec un graphe de calcul différent de celui de l'apprentissage.
Aussi, afin de réaliser le processus de prédiction du mot suivant à partir du mot précédent Utilisez le modèle défini comme une fonction dans une boucle pour déduire séquentiellement.
Les modèles enregistrés dans des fichiers h5, etc. peuvent être chargés comme suit.
model = keras.models.load_model(filepath)
De plus, pickle semble être obsolète.
Nous allons construire le modèle montré dans la figure suivante
Le même encodeur qu'au moment de l'apprentissage peut être utilisé tel quel.
#define encoder
encoder_model = Model(inputs=model.input[0], #encoder_input
outputs=model.get_layer('lstm_1').output[1:]) #enconder lstm hidden state
S'il peut être utilisé tel quel, il est possible d'extraire la sortie au milieu de Model
de cette manière.
Le décodeur a un code un peu plus long.
Il y a trois choses à faire avec le décodeur: Incorporation (pour forcer l'enseignant), LSTM et Dense dans le mot précédent.
L'incorporation, LSTM et Dense ont chacun des pondérations pendant l'entraînement, utilisez donc ces valeurs.
De plus, la mémoire de la couche cachée qui doit être entrée dans LSTM
n'est pas toujours la même que la sortie de l'encodeur, mais la mémoire après avoir déduit le mot précédent, elle doit donc être réécrite à partir du moment de l'apprentissage.
L'exemple de mise en œuvre est le suivant
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)
Qu'est-ce qui est différent d'apprendre
model.get_layer (<nom de la couche>). Get_weights ()
.forme
de ʻInput` est 1.return_sequences = True
de LSTM
pour obtenir la sortie LSTM
pour chaque étapeLSTM
est nouvellement ajoutée en tant que couche d'entrée.Model
decoder_model`.SVG(model_to_dot(decoder_model).create(prog='dot', format='svg'))
En fait, entrez la colonne d'ID de mot pour obtenir l'ID de mot traduit. Faire
est. L'exemple de mise en œuvre est le suivant. (Je l'ai écrit pour qu'il puisse être traité par lots, mais ce n'est pas indispensable)
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
Les instances de la classe «Model» ont une méthode «prédire». Si vous passez l'entrée à la méthode «prédire», le calcul sera effectué selon le graphe de calcul défini et la sortie sera obtenue.
Tout d'abord, nous utilisons ʻencoder_model.predict` pour encoder l'entrée dans la mémoire de couche cachée.
En supposant que target_seq
avec une taille de [batch_size, 1] ʻest le mot précédent, utilisez
decoder_model.predict` avec la mémoire de la couche cachée pour se souvenir du mot suivant et de la couche cachée à entrer ensuite. Je suis en train
Les mots obtenus prennent ʻargmaxdans l'ordre et prennent Stockez-le dans
decoded_sentence pour que la sortie soit de taille
[batch_size, max_length_targ]`.
Exécutez cette boucle autant de fois que la longueur maximale de la chaîne de mots de sortie et affichez decoded_sentence
.
Exemple de sortie
array([[ 15., 33., 5., 27., 121., 9., 482., 6., 8.,
4., 3., 0., 0., 0., 0., 0., 0., 0.]])
Puisque l'ID de mot et la règle de conversion de mot sont obtenus à l'avance par keras.preprocessing.text.Tokenizer
Tout ce que vous avez à faire est d'appliquer la loi de conversion de chaque composant de ndarray
.
Pour que les fonctions python fonctionnent sur tous les composants de ndarray
, vous pouvez utiliser np.vectorize
pour écrire sans boucles
L'exemple de mise en œuvre est le suivant
#decoded_mot de sens_Convertir l'index en mot et supprimer les jetons de début / fin
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
Pour le moment, le traitement des exceptions a été inclus. Enfin, supprimez l'espace perdu et les jetons de début / fin pour terminer.
La partie prétraitement est la suivante Traduction automatique neuronale avec attention https://www.tensorflow.org/tutorials/text/nmt_with_attention
La base de code pour la partie apprentissage / inférence est la suivante Sequence to sequence example in Keras (character-level). https://keras.io/examples/lstm_seq2seq/
Les données utilisées pour l'apprentissage sont les suivantes https://github.com/odashi/small_parallel_enja
Le référentiel contenant le code de cet article https://github.com/nagiton/simple_NMT
Recommended Posts