Modèles de séquence à séquence, partie 1

Bonne journée à tous!

Et nous avons encore une fois un nouveau flux ouvert pour le cours Data Scientist révisé: un autre grand professeur , un programme légèrement raffiné basé sur des mises à jour. Eh bien, comme d'habitude, des leçons ouvertes intéressantes et des collections de matériel intéressant. Aujourd'hui, nous allons commencer l'analyse des modèles seq2seq de Tensor Flow.

Allons-y.

Comme déjà discuté dans le tutoriel RNN (nous vous recommandons de vous familiariser avec celui-ci avant de lire cet article), les réseaux de neurones récurrents peuvent être appris à modéliser le langage. Et une question intéressante se pose: est-il possible de former le réseau sur certaines données pour générer une réponse significative? Par exemple, pouvons-nous enseigner à un réseau de neurones à traduire de l'anglais vers le français? Il s'avère que nous le pouvons.

Ce guide vous montrera comment créer et former un tel système de bout en bout. Copiez le référentiel principal Tensor Flow et le référentiel modèle TensorFlow depuis GitHub . Ensuite, vous pouvez commencer par lancer le programme de traduction:

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



Elle téléchargera les données à traduire de l'anglais vers le français à partir du site Web WMT'15 , les préparera pour la formation et la formation. Cela nécessitera environ 20 Go sur le disque dur et beaucoup de temps pour télécharger et préparer, vous pouvez donc commencer le processus maintenant et continuer à lire ce tutoriel.

Le manuel accède aux fichiers suivants:

FichierQu'y a-t-il dedans?
tensorflow / tensorflow / python / ops / seq2seq.pyBibliothèque pour créer des modèles de séquence à séquence
models / tutorials / rnn / translate / seq2seq_model.pyModèles de traduction neuronale séquence à séquence
models / tutorials / rnn / translate / data_utils.pyFonctions d'assistance pour la préparation des données de traduction
modèles / tutoriels / rnn / translate / translate.pyLe binaire qui forme et exécute le modèle de traduction

Notions de base de séquence à séquence

Le modèle de séquence à séquence de base, tel que présenté par Cho et al., 2014 ( pdf ), se compose de deux réseaux de neurones récurrents (RNN): un encodeur (encodeur) qui traite les données d'entrée et un décodeur (décodeur) qui génère les données sortie. L'architecture de base est illustrée ci-dessous:



Chaque rectangle dans l'image ci-dessus représente une cellule du RNN, généralement une cellule GRU - un bloc à récurrence contrôlée ou une cellule LSTM - une mémoire à court terme à long terme (lisez le didacticiel RNN pour en savoir plus à leur sujet). Les encodeurs et décodeurs peuvent avoir des poids communs ou, le plus souvent, utiliser différents ensembles de paramètres. Les cellules multicouches ont été utilisées avec succès dans des modèles de séquence à séquence, par exemple, pour traduire Sutskever et al., 2014 ( pdf ).

Dans le modèle de base décrit ci-dessus, chaque entrée doit être codée dans un vecteur d'état de taille fixe, car c'est la seule chose qui est transmise au décodeur. Pour donner au décodeur un accès plus direct aux données d'entrée, un mécanisme d'attention a été introduit dans Bahdanau et al., 2014 ( pdf ). Nous n'entrerons pas dans les détails du mécanisme d'attention (pour cela vous pouvez vous familiariser avec le travail ici); il suffit de dire qu'il permet au décodeur de regarder les données d'entrée à chaque étape de décodage. Un réseau multicouche de séquence à séquence avec des cellules LSTM et le mécanisme d'attention dans le décodeur est le suivant:



Bibliothèque TensorFlow seq2seq

Comme vous pouvez le voir ci-dessus, il existe différents modèles de séquence à séquence. Tous peuvent utiliser différentes cellules RNN, mais tous acceptent les données d'entrée du codeur et les données d'entrée du décodeur. C'est la base de l'interface de la bibliothèque TensorFlow seq2seq (tensorflow / tensorflow / python / ops / seq2seq.py). Ce modèle de base, RNN, codec, séquence à séquence fonctionne comme suit.

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

Dans l'appel indiqué ci-dessus, encoder_inputs est une liste de tenseurs représentant les données d'entrée de l'encodeur, correspondant aux lettres A, B, C de l'image ci-dessus. De même, les decoder_inputs sont des tenseurs représentant les données d'entrée du décodeur. GO, W, X, Y, Z à partir de la première photo.

L'argument de cell est une instance de la classe tf.contrib.rnn.RNNCell qui détermine quelle cellule sera utilisée dans le modèle. Vous pouvez utiliser des cellules existantes, par exemple, GRUCell ou LSTMCell , ou vous pouvez écrire les vôtres. De plus, tf.contrib.rnn fournit des shells pour créer des cellules multicouches, ajouter des exceptions à l'entrée et à la sortie des cellules, ou d'autres transformations. Consultez le tutoriel RNN pour des exemples.

L'appel basic_rnn_seq2seq renvoie deux arguments: les outputs et les states . Ils représentent tous les deux une liste de tenseurs de la même longueur que decoder_inputs . outputs correspondent aux données de sortie du décodeur à chaque pas de temps, dans la première image, il s'agit de W, X, Y, Z, EOS. Les states renvoyés représentent l'état interne du décodeur à chaque pas de temps.

Dans de nombreuses applications utilisant le modèle séquence à séquence, la sortie du décodeur à l'instant t est retransmise à l'entrée du décodeur à l'instant t + 1. Pendant les tests, pendant le décodage de séquence, c'est ainsi que l'on en construit un nouveau. D'un autre côté, lors de la formation, il est habituel de transmettre au décodeur les données d'entrée correctes à chaque pas de temps, même si le décodeur s'est précédemment trompé. Les fonctions de seq2seq.py prennent en charge les deux modes avec l'argument feed_previous . Par exemple, envisagez l'utilisation suivante d'un modèle RNN imbriqué.

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

Dans le modèle embedding_rnn_seq2seq , toutes les données d'entrée ( encoder_inputs et decoder_inputs ) sont des tenseurs entiers qui reflètent des valeurs discrètes. Ils seront imbriqués dans une représentation serrée (pour plus de détails sur la pièce jointe, reportez-vous au Guide des vues vectorielles ), mais pour créer ces pièces jointes, vous devez spécifier le nombre maximal de caractères discrets: num_encoder_symbols côté encodeur et num_decoder_symbols côté décodeur.

Dans l'appel ci-dessus, nous avons défini feed_previous sur False. Cela signifie que le décodeur utilisera les tenseurs decoder_inputs sous la forme dans laquelle ils sont fournis. Si nous définissons feed_previous sur True, le décodeur n'utilisera que le premier élément decoder_inputs . Tous les autres tenseurs de la liste seront ignorés et la valeur précédente de la sortie du décodeur sera utilisée à la place. Il est utilisé pour décoder les traductions dans notre modèle de traduction, mais peut également être utilisé pendant la formation, pour améliorer la stabilité du modèle face à ses erreurs. Approximativement comme dans Bengio et al., 2015 ( pdf ).

Un autre argument important utilisé ci-dessus est output_projection . Sans précision, les conclusions du modèle embarqué seront des tenseurs de la forme du nombre d'échantillons d'apprentissage par num_decoder_symbols , car ils représentent les logithmes de chaque symbole généré. Lors de la formation de modèles avec de grands dictionnaires de sortie, par exemple avec de grands num_decoder_symbols , le stockage de ces grands tenseurs devient peu pratique. Au lieu de cela, il est préférable de renvoyer des tenseurs plus petits, qui seront ensuite projetés sur le grand tenseur à l'aide de output_projection . Cela nous permet d'utiliser nos modèles seq2seq avec des pertes softmax échantillonnées, comme décrit par Jean et. al., 2014 ( pdf ).

En plus de basic_rnn_seq2seq et embedding_rnn_seq2seq , il existe plusieurs autres modèles de séquence à séquence dans seq2seq.py . Faites attention à eux. Tous ont une interface similaire, nous ne nous attarderons donc pas sur leurs détails. Pour notre modèle de traduction ci-dessous, utilisez embedding_attention_seq2seq .

À suivre.

Source: https://habr.com/ru/post/fr430780/


All Articles