[PYTHON] Modèle de transformation de séquence de didacticiel TensorFlow (traduction)

Didacticiel TensorFlow (modèles séquence à séquence) https://www.tensorflow.org/versions/master/tutorials/seq2seq/index.html#sequence-to-sequence-models C'est une traduction de. Nous sommes impatients de signaler toute erreur de traduction.


Lisez le réseau neuronal récurrent comme décrit dans Tutoriel RNN (si vous ne l'avez pas lu, lisez-le avant de continuer. Vous pouvez apprendre à modéliser la langue. Cela soulève une question intéressante: est-il possible de générer une réponse significative sous réserve de mots générés par une entrée? Par exemple, pouvez-vous former un réseau de neurones à traduire de l'anglais vers le français? La réponse s'est avérée être oui.

Ce didacticiel vous montrera comment construire et entraîner un tel système de bout en bout. Supposons que vous soyez installé par le package pip, que vous cloniez le référentiel tensorflow git et que vous soyez à la racine de l'arborescence git.

Commencez par exécuter le programme de traduction:

cd tensorflow/models/rnn/translate
python translate.py --data_dir [your_data_directory]

Ce programme télécharge les données de traduction anglais-français à partir du site Web WMT'15, prépare la formation et forme. .. Il nécessite environ 20 Go d'espace disque. Je vais télécharger et préparer pendant un moment (voir ci-dessous pour plus de détails (https://www.tensorflow.org/versions/master/tutorials/seq2seq/index.html#run_it)), alors commencez et lisez ce tutoriel. C'est une bonne idée de le faire fonctionner pendant que vous y êtes.

Dans ce tutoriel, nous ferons référence aux fichiers suivants dans models / rnn.

Fichier Contenu
seq2seq.py Bibliothèque de création de modèles de transformation de séquence
translate/seq2seq_model.py Modèle de transformation de séquence de traduction neurale
translate/data_utils.py Fonction d'assistance pour préparer les données de traduction
translate/translate.py Un binaire qui forme et exécute un modèle de traduction

Bases de la conversion de séquence

Le modèle de transformation de séquence de base consiste en deux réseaux de neurones récurrents (RNN), comme introduit dans Cho et al., 2014. : Un encodeur qui traite l'entrée et un décodeur qui produit la sortie. L'architecture de base est illustrée ci-dessous.

図

Chaque case de la figure ci-dessus est une cellule RNN, le plus souvent une cellule GRU ou une cellule LSTM (pour une description de celles-ci, voir les tutoriels RNN (https://www.tensorflow.org/versions/master/tutorials). (Voir /recurrent/index.html)) est exprimé. Les encodeurs et les décodeurs peuvent également partager des poids et, plus généralement, utiliser des ensembles de paramètres séparés. Les cellules multicouches sont également utilisées avec succès dans des modèles de transformation de séquence, par exemple [Sutskever et al., 2014] en traduction (http://arxiv.org/abs/1409.3215).

Dans le modèle de base illustré ci-dessus, toutes les entrées doivent être codées dans un vecteur d'état de taille fixe comme seule chose transmise au décodeur. Bahdanu et al., 2014 introduit un mécanisme d'attention qui permet au décodeur d'accéder plus directement à l'entrée. Je n'entrerai pas dans les détails du mécanisme d'intérêt (voir article). Il suffit de mentionner que cela permet au décodeur de se faufiler dans l'entrée à chaque étape de décodage. Un réseau de conversion de séquence multicouche avec la cellule LSTM et le mécanisme de mise au point du décodeur ressemble à ceci:

図

Bibliothèque TensorFlow seq2seq

Comme vous pouvez le voir ci-dessus, il existe une variété de modèles de transformation de séquence. Chacun de ces modèles utilise une cellule RNN différente, mais tous acceptent les entrées codeur et décodeur. Cela ouvre une interface dans la bibliothèque seq2seq de TensorFlow (models / rnn / seq2seq.py). Le modèle de conversion de séquence codeur-décodeur-séquence RNN de base fonctionne comme suit.

outputs, states = basic_rnn_seq2seq(encoder_inputs, decoder_inputs, cell)

Dans l'appel ci-dessus, encoder_inputs correspond à la liste des tenseurs qui représentent les entrées du codeur, c'est-à-dire les lettres A, B et C de la première figure ci-dessus. De même, decoder_inputs sont des tenseurs qui représentent les entrées du décodeur, GO, W, X, Y, Z sur la première figure.

L'argument de cellule est une instance de la classe models.rnn.rnn_cell.RNNCell qui définit les cellules utilisées dans le modèle. Vous pouvez utiliser des cellules existantes telles que GRUCell et LSTMCell, ou vous pouvez écrire les vôtres. Rnn_cell fournit également un wrapper pour la construction de cellules multicouches dans le but d'ajouter des abandons aux entrées et sorties de cellules et pour d'autres transformations. Pour un exemple, consultez le didacticiel RNN (https://www.tensorflow.org/versions/master/tutorials/recurrent/index.html).

L'appel à basic_rnn_seq2seq renvoie deux arguments: la sortie et l'état. Les deux sont des listes de tenseurs de même longueur que decoder_inputs. Sans surprise, la sortie correspond à la sortie du décodeur à chaque pas de temps, W, X, Y, Z, EOS sur la première figure ci-dessus. L'état renvoyé représente l'état interne du décodeur à chaque pas de temps.

Dans de nombreux cas, le modèle de conversion de séquence renvoie la sortie du décodeur au temps t et devient l'entrée du décodeur au temps t + 1. C'est ainsi que la séquence est construite lors du décodage de la séquence pendant le test. Par contre, pendant l'entraînement, vous entrez généralement la bonne réponse dans le décodeur à chaque pas de temps, même si le décodeur fait une erreur à l'étape précédente. La fonction seq2seq.py utilise l'argument feed_previous pour prendre en charge les deux modes. À titre d'exemple, analysons l'utilisation suivante du modèle RNN intégré.

outputs, states = embedding_rnn_seq2seq(
    encoder_inputs, decoder_inputs, cell,
    num_encoder_symbols, num_decoder_symbols,
    output_projection=None, feed_previous=False)

Dans le modèle embedding_rnn_seq2seq, toutes les entrées (à la fois encoder_inputs et decoder_inputs) sont des tenseurs entiers qui représentent des valeurs discrètes. Ceux-ci sont intégrés dans des représentations denses (pour plus d'informations sur l'incorporation, voir le didacticiel sur la représentation vectorielle (https://www.tensorflow.org/versions/master/tutorials/word2vec/index.html). S'il vous plaît), afin de construire ces imbrications, vous devez spécifier le nombre maximum de symboles discrets qui apparaîtront: num_encoder_symbols du côté du codeur et num_decoder_symbols du côté du décodeur.

Dans l'appel ci-dessus, nous définissons feed_previous sur False. Cela signifie que le décodeur utilisera le tenseur decoder_inputs fourni. Si feed_previous est défini sur True, le décodeur n'utilisera que le premier élément de decoder_inputs. Tous les autres tenseurs de cette liste sont ignorés et la sortie précédente du codeur est utilisée à la place. Ceci est utilisé pour la conversion de déchiffrement dans notre modèle de traduction. Il peut également être utilisé pendant la formation, comme Bengio et al., 2015, pour rendre le modèle plus robuste à ses propres erreurs. Je peux le faire.

Un autre argument important utilisé ci-dessus est output_projection. Si cela n'est pas spécifié, la sortie du modèle incorporé sera un tenseur de la forme batch size x num_decoder_symbols, représentant le logit de chaque symbole généré. Si vous entraînez votre modèle avec un grand vocabulaire de sortie, c'est-à-dire si num_decoder_symbols est grand, alors il n'est pas pratique de stocker ces grands tenseurs. Au lieu de cela, il est recommandé de renvoyer un petit tenseur de sortie. Ils seront ensuite projetés sur un grand tenseur de sortie en utilisant output_projection. Cela nous permet d'utiliser notre modèle seq2seq avec échantillonnage des pertes softmax, comme décrit dans Jean et. Al., 2015. Je peux.

En plus de basic_rnn_seq2seq et embedding_rnn_seq2seq, il existe plusieurs modèles de conversion de séquence dans seq2seq.py, alors jetez-y un œil. Ils ont tous des interfaces similaires et ne seront pas discutés en détail. Le modèle de traduction ci-dessous utilise embedding_attention_seq2seq.

Modèle de traduction neuronale

Le cœur du modèle de transformation de séquence est constitué des fonctions de models / rnn / seq2seq.py, mais il y a quelques astuces à mentionner qui sont utilisées dans le modèle de traduction dans models / rnn / translate / seq2seq_model.py. Il y a.

Échantillonnage softmax et projection de sortie

Utilisez Sampling Softmax pour traiter un vocabulaire de sortie volumineux pour les raisons mentionnées ci-dessus. Il décode à partir de la projection de sortie, vous devez donc en garder une trace. La perte softmax d'échantillonnage et la prédiction de sortie sont construites avec le code suivant dans seq2seq_model.py.

  if num_samples > 0 and num_samples < self.target_vocab_size:
    w = tf.get_variable("proj_w", [size, self.target_vocab_size])
    w_t = tf.transpose(w)
    b = tf.get_variable("proj_b", [self.target_vocab_size])
    output_projection = (w, b)

    def sampled_loss(inputs, labels):
      labels = tf.reshape(labels, [-1, 1])
      return tf.nn.sampled_softmax_loss(w_t, b, inputs, labels, num_samples,
                                        self.target_vocab_size)

Tout d'abord, notez que nous ne construisons l'échantillonnage softmax que si le nombre d'échantillons (512 par défaut) est inférieur à la taille du vocabulaire cible. Si votre vocabulaire est inférieur à 512, il est préférable d'utiliser simplement la perte standard Softmax.

Créez ensuite la projection de sortie, comme vous pouvez le voir dans le code. Il s'agit d'une paire de matrice de poids et de vecteur de biais. Lorsqu'elle est utilisée, la cellule RNN renvoie un vecteur de formes dans la taille du lot x la taille au lieu de la taille du lot x target_vocab_size. Vous devez multiplier et biaiser la matrice de poids pour récupérer le logit, comme cela se fait aux lignes 124-126 de seq2seq_model.py.

if output_projection is not None:
  self.outputs[b] = [tf.matmul(output, output_projection[0]) +
                     output_projection[1] for ...]

Godet et rembourrage

En plus de Sampling Softmax, notre modèle de traduction utilise le bucketing, qui est un moyen de traiter efficacement des phrases de différentes longueurs. Clarifions d'abord le problème. Lors de la traduction de l'anglais vers le français, il y a entrée de phrases L1 anglais de longueur variable et sortie de phrases L2 français de longueur variable. Puisque la phrase anglaise est passée en tant que encoder_inputs et devient la phrase française en tant que decoder_inputs (en commençant par le symbole GO), en principe, créez un modèle seq2seq pour toutes les paires (L1, L2 + 1) de longueurs de phrase en anglais et en français. est nécessaire. Il s'agit d'un énorme graphique composé de nombreux sous-graphiques très similaires. D'autre part, toutes les instructions peuvent également être complétées avec un symbole PAD spécial. Dans ce cas, vous n'avez besoin que du modèle seq2seq pour la seule longueur rembourrée. Cependant, de courtes déclarations rendent ce modèle inefficace car il nécessite le codage et le décodage d'un grand nombre de symboles PAD inutiles.

Pour faire un compromis entre la façon de créer un graphique pour toutes les paires de longueur et la façon de compléter à une seule longueur, utilisez plusieurs seaux et rendez chaque phrase plus longue que cela. Faites le rembourrage pour. translate.py utilise le bucket par défaut suivant:

buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]

Ceci est placé dans le premier seau si l'entrée est une phrase anglaise à 3 jetons et la sortie correspondante est une phrase française à 6 jetons, l'entrée du codeur a une longueur de 5 et l'entrée du décodeur a une longueur de 10. Cela signifie être rembourré. Si vous avez une phrase anglaise avec 8 jetons et que la phrase française correspondante est de 18 jetons, alors le seau (20, 25) est utilisé car il ne rentre pas dans le seau (10, 15), c'est-à-dire que la phrase anglaise est 20 et française. La phrase est complétée à 25.

Rappelez-vous que lors de la construction de l'entrée du décodeur, nous ajoutons un symbole GO spécial aux données d'entrée. Ceci est fait avec la fonction get_batch () dans seq2seq_model.py. Cette fonction inverse également le texte anglais d'entrée. L'inversion d'entrée a été montrée dans Sutskever et al., 2014 pour améliorer les résultats du modèle de traduction neuronale. Pour tout mettre ensemble, il y a la phrase "Je vais." En entrée, symbolisée par ["je", "aller", "."], Et la phrase "Je vais." En sortie, [" Disons qu'il est symbolisé par Je "," vais ",". "]. Dans ce cas, l'entrée codeur représentée par [PAD PAD "." "Go" "I"] et l'entrée du décodeur représentée par [GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD](5, 10) Peut être mis dans un seau.

Courons

Un grand corpus anglais-français est nécessaire pour former le modèle ci-dessus. Depuis le site Web WMT'15, utilisez un corpus 10 ^ 9 français-anglais pour la formation et comme ensemble de développement à partir du même site Utilisez le test d'actualités 2013. Lorsque vous exécutez la commande, ces ensembles de données sont téléchargés dans data_dir, l'entraînement commence et les points de contrôle sont stockés dans train_dir.

python translate.py
  --data_dir [your_data_directory] --train_dir [checkpoints_directory]
  --en_vocab_size=40000 --fr_vocab_size=40000

Il faut environ 18 Go d'espace disque et plusieurs heures pour préparer le corpus de formation. La préparation décompresse l'ensemble de données, crée un fichier lexical dans data_dir, puis tokenise le corpus et le convertit en un ID entier. Faites attention aux paramètres qui déterminent la taille du vocabulaire. L'exemple ci-dessus convertit tous les mots sauf les 40 000 mots les plus courants en jetons UNK qui représentent des mots inconnus. Si vous modifiez la taille du vocabulaire, le binaire convertira à nouveau le corpus en jetons et ID.

Une fois les données préparées, la formation commencera. Le paramètre par défaut de translate est défini pour utiliser une valeur élevée. Les modèles plus grands qui ont été formés sur une longue période donnent de bons résultats. Cependant, cela peut prendre trop de temps ou le GPU peut manquer de mémoire, vous pouvez donc demander à entraîner un modèle plus petit, comme dans l'exemple suivant.

python translate.py
  --data_dir [your_data_directory] --train_dir [checkpoints_directory]
  --size=256 --num_layers=2 --steps_per_checkpoint=50

La commande ci-dessus entraîne un modèle avec 2 couches (par défaut 3), 256 unités pour chaque couche (par défaut 1024) et enregistre les points de contrôle toutes les 50 étapes (par défaut 200). Vous pouvez autoriser le modèle à tenir dans la mémoire du GPU. Vous pouvez modifier ces paramètres pour que le modèle tienne dans la mémoire du GPU.

Pendant l'entraînement, à chaque étape step_per_checkpoint, le binaire génère des statistiques de l'étape la plus récente. Avec les paramètres par défaut (trois couches, taille 1024), le premier message ressemble à ceci:

global step 200 learning rate 0.5000 step-time 1.39 perplexity 1720.62
  eval: bucket 0 perplexity 184.97
  eval: bucket 1 perplexity 248.81
  eval: bucket 2 perplexity 341.64
  eval: bucket 3 perplexity 469.04
global step 400 learning rate 0.5000 step-time 1.38 perplexity 379.89
  eval: bucket 0 perplexity 151.32
  eval: bucket 1 perplexity 190.36
  eval: bucket 2 perplexity 227.46
  eval: bucket 3 perplexity 238.66

Vous pouvez voir que chaque étape prend moins de 1,4 seconde, et que chaque compartiment a de la perplexité sur l'ensemble d'entraînement et de la perplexité sur l'ensemble de développement. Après environ 30 000 étapes, assurez-vous que la perplexité des phrases courtes (seaux 0 et 1) est dans les chiffres uniques. Étant donné que le corpus d'apprentissage contient environ 22 millions de phrases, une époque (la période d'un cycle de données d'apprentissage) correspond à 64 tailles de lots et environ 340 000 étapes. À ce stade, vous pouvez utiliser le modèle pour traduire des phrases anglaises en français à l'aide de l'option --decode.

python translate.py --decode
  --data_dir [your_data_directory] --train_dir [checkpoints_directory]

Reading model parameters from /tmp/translate.ckpt-340000
>  Who is the president of the United States?
 Qui est le président des États-Unis ?

prochain?

L'exemple ci-dessus montre comment créer votre propre traducteur anglais-français, de bout en bout. Exécutez-le et voyez comment le modèle fonctionne. C'est une qualité raisonnablement bonne, mais les paramètres par défaut ne donnent pas le meilleur modèle de traduction. Il y a des choses qui peuvent être améliorées ici.

Tout d'abord, nous avons utilisé la fonction très primitive de tokenizer, basic_tokenizer dans data_utils. Vous pouvez trouver un meilleur tokenizer sur le site Web WMT'15 (http://www.statmt.org/wmt15/translation-task.html). L'utilisation de ce tokenizer et d'un vocabulaire plus large devrait améliorer la traduction.

De plus, les paramètres par défaut du modèle de traduction ne sont pas réglés. Vous pouvez modifier le taux d'entraînement et la décroissance, ou essayer d'initialiser les poids du modèle d'une manière différente. Vous pouvez également changer le GradientDescentOptimizer par défaut en quelque chose de plus avancé, tel que AdagradOptimizer, dans seq2seq_model.py. Essayez ces choses et voyez comment les résultats s'améliorent!

Enfin, le modèle ci-dessus peut être utilisé pour toute tâche de conversion de séquence, pas seulement pour la traduction. Par exemple, si vous souhaitez convertir une séquence en arbre pour générer un arbre d'analyse syntaxique, comme indiqué dans Vinyals & Kaiser et al., 2015 Le modèle donne des résultats de pointe. Vous pouvez créer votre propre traducteur, ainsi que des analyseurs, des chatbots ou tout autre programme auquel vous pouvez penser. Expérience!

Recommended Posts

Modèle de transformation de séquence de didacticiel TensorFlow (traduction)
Tutoriel TensorFlow - TensorFlow Mechanics 101 (Traduction)
Tutoriel TensorFlow - Reconnaissance d'image (traduction)
Modèle de prédiction de langage par TensorFlow
Tutoriel TensorFlow - Équation différentielle partielle (traduction)
[FSL] Conversion affine (mouvement parallèle + conversion linéaire)
Tutoriel TensorFlow - Réseau neuronal à convolution (traduction)
Traduction TensorFlow MNIST pour les débutants en ML
Personnaliser le modèle / la couche / la métrique avec TensorFlow
Comment convertir le modèle Tensorflow en Lite
Tutoriel TensorFlow - Représentation vectorielle des mots (traduction)
[Français] scikit-learn 0.18 Guide de l'utilisateur 3.4. Persistance du modèle
TensorFlow Deep MNIST pour la traduction d'experts