Essentiels de l’apprentissage profond : Introduction à la mémoire à long terme

Introduction

Les problèmes de prédiction de séquence existent depuis longtemps. Ils sont considérés comme l’un des problèmes les plus difficiles à résoudre dans l’industrie de la science des données. Ils comprennent un large éventail de problèmes ; de la prédiction des ventes à la recherche de modèles dans les données des marchés boursiers, de la compréhension des intrigues de films à la reconnaissance de votre façon de parler, de la traduction de langues à la prédiction du prochain mot sur le clavier de votre iPhone.

Avec les récentes percées qui ont eu lieu dans la science des données, on constate que pour presque tous ces problèmes de prédiction de séquences, les réseaux de mémoire à long court terme, alias LSTMs ont été observés comme la solution la plus efficace.

LSTMs ont un avantage sur les réseaux neuronaux conventionnels feed-forward et RNN à bien des égards. Cela est dû à leur propriété de se souvenir sélectivement des modèles pendant de longues durées. L’objectif de cet article est d’expliquer les LSTM et de vous permettre de les utiliser dans des problèmes réels. Jetons un coup d’œil !

Note : Pour parcourir cet article, vous devez avoir des connaissances de base sur les réseaux neuronaux et sur le fonctionnement de Keras (une bibliothèque d’apprentissage profond). Vous pouvez vous référer aux articles mentionnés pour comprendre ces concepts :

  • Understanding Neural Network From Scratch
  • Fondamentaux de l’apprentissage profond – Introduction aux réseaux neuronaux récurrents
  • Tutoriel : Optimisation des réseaux neuronaux à l’aide de Keras (avec étude de cas de reconnaissance d’images)

Table des matières

  1. Flashback : Un regard sur les réseaux neuronaux récurrents (RNN)
  2. Limitations des RNN
  3. Amélioration par rapport aux RNN : Mémoire à long court terme (LSTM)
  4. Architecture des LSTM
    1. Porte d’oubli
    2. Porte d’entrée
    3. Porte de sortie
  5. Génération de texte à l’aide des LSTM.

Flashback : Un regard sur les réseaux neuronaux récurrents (RNN)

Prenez un exemple de données séquentielles, qui peuvent être les données du marché boursier pour une action particulière. Un modèle d’apprentissage automatique simple ou un réseau neuronal artificiel peut apprendre à prédire les prix des actions en fonction d’un certain nombre de caractéristiques : le volume de l’action, la valeur d’ouverture, etc. Si le prix de l’action dépend de ces caractéristiques, il dépend aussi largement de la valeur de l’action les jours précédents. En fait, pour un trader, ces valeurs des jours précédents (ou la tendance) est un facteur décisif majeur pour les prédictions.

Dans les réseaux neuronaux feed-forward classiques, tous les cas de test sont considérés comme indépendants. C’est-à-dire que lors de l’ajustement du modèle pour un jour particulier, il n’y a aucune considération pour les prix des actions des jours précédents.

Cette dépendance au temps est réalisée via les réseaux neuronaux récurrents. Un RNN typique ressemble à :

Cela peut être intimidant à première vue, mais une fois déplié, cela semble beaucoup plus simple :

Maintenant, il est plus facile pour nous de visualiser comment ces réseaux considèrent la tendance des prix des actions, avant de prédire les prix des actions pour aujourd’hui. Ici, chaque prédiction au temps t (h_t) dépend de toutes les prédictions précédentes et de l’information apprise de celles-ci.

Les RRNN peuvent résoudre notre objectif de traitement des séquences dans une large mesure mais pas entièrement. Nous voulons que nos ordinateurs soient assez bons pour écrire des sonnets shakespeariens. Maintenant, les RNN sont excellents lorsqu’il s’agit de contextes courts, mais pour être en mesure de construire une histoire et de s’en souvenir, nous avons besoin que nos modèles soient capables de comprendre et de se souvenir du contexte derrière les séquences, tout comme un cerveau humain. Cela n’est pas possible avec un simple RNN.

Pourquoi ? Voyons cela.

Limites des RNN

Les réseaux neuronaux récurrents fonctionnent très bien lorsque nous traitons des dépendances à court terme. C’est-à-dire lorsqu’ils sont appliqués à des problèmes tels que :

Les RNN se révèlent assez efficaces. En effet, ce problème n’a rien à voir avec le contexte de l’énoncé. Le RNN n’a pas besoin de se souvenir de ce qui a été dit avant cela, ni de sa signification, tout ce qu’il doit savoir, c’est que dans la plupart des cas, le ciel est bleu. Ainsi, la prédiction serait:

Cependant, les RNN vanille ne parviennent pas à comprendre le contexte derrière une entrée. Quelque chose qui a été dit longtemps auparavant, ne peut pas être rappelé lors de la réalisation de prédictions dans le présent. Comprenons ceci comme un exemple :

Ici, nous pouvons comprendre que puisque l’auteur a travaillé en Espagne pendant 20 ans, il est très probable qu’il puisse posséder une bonne maîtrise de l’espagnol. Mais, pour faire une prédiction correcte, le RNN doit se souvenir de ce contexte. Les informations pertinentes peuvent être séparées du point où elles sont nécessaires, par une énorme charge de données non pertinentes. C’est là qu’un réseau neuronal récurrent échoue!

La raison derrière cela est le problème du Vanishing Gradient. Pour comprendre cela, vous devez avoir quelques connaissances sur la façon dont un réseau neuronal à action directe apprend. Nous savons que pour un réseau neuronal feed-forward classique, la mise à jour des poids appliquée à une couche particulière est un multiple du taux d’apprentissage, du terme d’erreur de la couche précédente et de l’entrée de cette couche. Ainsi, le terme d’erreur d’une couche particulière est quelque part un produit de toutes les erreurs des couches précédentes. Lorsqu’on utilise des fonctions d’activation comme la fonction sigmoïde, les petites valeurs de ses dérivées (qui apparaissent dans la fonction d’erreur) sont multipliées plusieurs fois à mesure que l’on se déplace vers les couches de départ. En conséquence, le gradient disparaît presque au fur et à mesure que nous nous déplaçons vers les couches de départ, et il devient difficile de former ces couches.

Un cas similaire est observé dans les réseaux neuronaux récurrents. Le RNN ne se souvient des choses que pour de petites durées, c’est-à-dire que si nous avons besoin de l’information après une petite période, elle peut être reproductible, mais une fois que beaucoup de mots sont introduits, cette information se perd quelque part. Ce problème peut être résolu en appliquant une version légèrement modifiée des RNN – les réseaux à mémoire à long court terme.

Amélioration par rapport aux RNN : Les réseaux LSTM (Long Short-Term Memory)

Lorsque nous organisons notre calendrier pour la journée, nous priorisons nos rendez-vous n’est-ce pas ? Si au cas où nous avons besoin de faire de la place pour quelque chose d’important, nous savons quelle réunion pourrait être annulée pour accueillir une éventuelle réunion.

Il s’avère qu’un RNN ne le fait pas. Afin d’ajouter une nouvelle information, il transforme complètement l’information existante en appliquant une fonction. De ce fait, l’information est modifiée, dans son ensemble, c’est-à-dire qu’il n’y a pas de considération pour les informations « importantes » et les informations « moins importantes ».

LSTMs, en revanche, apportent de petites modifications à l’information par des multiplications et des additions. Avec les LSTM, l’information circule à travers un mécanisme connu sous le nom d’états cellulaires. De cette façon, les LSTM peuvent se souvenir ou oublier des choses de manière sélective. L’information à un état cellulaire particulier a trois dépendances différentes.

Nous allons visualiser cela avec un exemple. Prenons l’exemple de la prédiction du prix des actions pour une action particulière. Le prix de l’action d’aujourd’hui va dépendre de :

  1. La tendance que l’action a suivie les jours précédents, peut-être une tendance à la baisse ou une tendance à la hausse.
  2. Le prix de l’action le jour précédent, car de nombreux traders comparent le prix de l’action le jour précédent avant de l’acheter.
  3. Les facteurs qui peuvent affecter le prix de l’action d’aujourd’hui. Il peut s’agir d’une nouvelle politique de l’entreprise qui est largement critiquée, ou d’une baisse du bénéfice de l’entreprise, ou peut-être d’un changement inattendu dans la haute direction de l’entreprise.

Ces dépendances peuvent être généralisées à n’importe quel problème sous la forme suivante :

  1. L’état précédent de la cellule (c’est-à-dire l’information qui était présente dans la mémoire après le pas de temps précédent)
  2. L’état caché précédent (c’est-à-dire l’information qui était présente dans la mémoire après le pas de temps précédent). c’est le même que la sortie de la cellule précédente)
  3. L’entrée au pas de temps actuel (c’est-à-dire la nouvelle information qui est introduite à ce moment-là)

Une autre caractéristique importante du LSTM est son analogie avec les bandes transporteuses !

C’est vrai !

Les industries les utilisent pour déplacer les produits pour différents processus. Les LSTMs utilisent ce mécanisme pour déplacer l’information.

Nous pouvons avoir des ajouts, des modifications ou des suppressions d’informations au fur et à mesure qu’elles circulent dans les différentes couches, tout comme un produit peut être moulé, peint ou emballé alors qu’il se trouve sur un tapis roulant.

Le diagramme suivant explique la relation étroite entre les LSTM et les tapis roulants.

Source

Bien que ce diagramme ne soit même pas proche de l’architecture réelle d’un LSTM, il résout notre objectif pour le moment.

Parce que cette propriété des LSTM, où ils ne manipulent pas l’ensemble des informations mais les modifient légèrement, ils sont capables d’oublier et de se souvenir des choses de manière sélective. Comment le font-ils, c’est ce que nous allons apprendre dans la section suivante ?

Architecture des LSTM

Le fonctionnement des LSTM peut être visualisé en comprenant le fonctionnement de l’équipe d’une chaîne d’information couvrant une histoire de meurtre. Maintenant, une histoire d’actualité est construite autour de faits, de preuves et de déclarations de nombreuses personnes. Chaque fois qu’un nouvel événement se produit, vous prenez l’une ou l’autre de ces trois étapes.

Disons que nous supposions que le meurtre a été commis en « empoisonnant » la victime, mais le rapport d’autopsie qui vient d’arriver dit que la cause de la mort était « un impact sur la tête ». En tant que membre de l’équipe de journalistes, que faites-vous ? Vous oubliez immédiatement la cause précédente de la mort et toutes les histoires qui ont été tissées autour de ce fait.

Quoi, si un tout nouveau suspect est introduit dans le tableau. Une personne qui avait de la rancune envers la victime et qui pourrait être le meurtrier ? Vous entrez cette information dans votre fil d’actualité, n’est-ce pas ?

Maintenant, tous ces morceaux d’information brisés ne peuvent pas être servis sur les médias grand public. Donc, après un certain intervalle de temps, vous devez résumer ces informations et sortir les choses pertinentes pour votre public. Peut-être sous la forme de « XYZ s’avère être le principal suspect. ».

Maintenant, entrons dans les détails de l’architecture du réseau LSTM :

Source

Maintenant, ceci est loin d’être proche de la version simplifiée que nous avons vue auparavant, mais laissez-moi vous guider. Un réseau LSTM typique est composé de différents blocs de mémoire appelés cellules
(les rectangles que nous voyons dans l’image). Il y a deux états qui sont transférés à la cellule suivante : l’état de la cellule et l’état caché. Les blocs de mémoire sont responsables de la mémorisation des choses et les manipulations de cette mémoire sont effectuées par trois mécanismes principaux, appelés portes. Chacun d’eux est discuté ci-dessous.

4.1 Porte d’oubli

Prenons l’exemple d’un problème de prédiction de texte. Supposons qu’un LSTM est alimenté, la phrase suivante:

Dès que le premier point complet après « personne » est rencontré, la porte d’oubli réalise qu’il peut y avoir un changement de contexte dans la phrase suivante. En conséquence, le sujet de la phrase est oublié et la place du sujet est libérée. Et lorsque nous commençons à parler de « Dan », cette position du sujet est attribuée à « Dan ». Ce processus d’oubli du sujet est provoqué par la porte d’oubli.

Une porte d’oubli est responsable de l’élimination des informations de l’état cellulaire. L’information qui n’est plus nécessaire pour que le LSTM comprenne les choses ou l’information qui est de moindre importance est retirée via la multiplication d’un filtre. Ceci est nécessaire pour optimiser les performances du réseau LSTM.

Cette porte prend deux entrées ; h_t-1 et x_t.

h_t-1 est l’état caché de la cellule précédente ou la sortie de la cellule précédente et x_t est l’entrée à ce pas de temps particulier. Les entrées données sont multipliées par les matrices de poids et un biais est ajouté. Ensuite, la fonction sigmoïde est appliquée à cette valeur. La fonction sigmoïde produit un vecteur, avec des valeurs allant de 0 à 1, correspondant à chaque chiffre de l’état de la cellule. En fait, la fonction sigmoïde est chargée de décider des valeurs à conserver et de celles à rejeter. Si un ‘0’ est émis pour une valeur particulière de l’état de la cellule, cela signifie que la porte d’oubli veut que l’état de la cellule oublie complètement cet élément d’information. De même, un ‘1’ signifie que la porte d’oubli veut se souvenir de cette information dans son intégralité. Cette sortie vectorielle de la fonction sigmoïde est multipliée à l’état de la cellule.

4.2 Porte d’entrée

Ok, prenons un autre exemple où le LSTM analyse une phrase :

Maintenant l’information importante ici est que « Bob » sait nager et qu’il a servi dans la marine pendant quatre ans. Ceci peut être ajouté à l’état de la cellule, cependant, le fait qu’il ait raconté tout cela par téléphone est un fait moins important et peut être ignoré. Ce processus d’ajout de quelques nouvelles informations peut être fait via la porte d’entrée.

Voici sa structure:

La porte d’entrée est responsable de l’ajout d’informations à l’état de cellule. Cet ajout d’information est essentiellement un processus en trois étapes comme on le voit sur le diagramme ci-dessus.

  1. Régulation des valeurs qui doivent être ajoutées à l’état de la cellule en impliquant une fonction sigmoïde. Ceci est fondamentalement très similaire à la porte forget et agit comme un filtre pour toutes les informations provenant de h_t-1 et x_t.
  2. Créer un vecteur contenant toutes les valeurs possibles qui peuvent être ajoutées (telles que perçues à partir de h_t-1 et x_t) à l’état de la cellule. Ceci est fait en utilisant la fonction tanh, qui produit des valeurs de -1 à +1.
  3. Multiplier la valeur du filtre régulateur (la porte sigmoïde) au vecteur créé (la fonction tanh) puis ajouter ces informations utiles à l’état cellulaire par une opération d’addition.

Une fois ce processus en trois étapes effectué, nous nous assurons que seules les informations importantes et non redondantes sont ajoutées à l’état cellulaire.

4.3 Porte de sortie

Toutes les informations qui parcourent l’état cellulaire, ne sont pas aptes à être sorties à un certain moment. Nous allons visualiser cela avec un exemple:

Dans cette phrase, il pourrait y avoir un certain nombre d’options pour l’espace vide. Mais nous savons que l’entrée actuelle de ‘brave’, est un adjectif qui est utilisé pour décrire un nom. Ainsi, quel que soit le mot qui suit, il a une forte tendance à être un nom. Et donc, Bob pourrait être une sortie appropriée.

Ce travail de sélection d’informations utiles à partir de l’état actuel de la cellule et de les montrer comme une sortie est fait via la porte de sortie. Voici sa structure :

Le fonctionnement d’une porte de sortie peut à nouveau être décomposé en trois étapes :

  1. Création d’un vecteur après application de la fonction tanh à l’état de la cellule, mettant ainsi les valeurs à l’échelle de -1 à +1.
  2. Faire un filtre en utilisant les valeurs de h_t-1 et x_t, de sorte qu’il puisse réguler les valeurs qui doivent être sorties du vecteur créé ci-dessus. Ce filtre emploie à nouveau une fonction sigmoïde.
  3. Multiplier la valeur de ce filtre régulateur au vecteur créé à l’étape 1, et l’envoyer en sortie et aussi à l’état caché de la cellule suivante.

Le filtre dans l’exemple ci-dessus fera en sorte de diminuer toutes les autres valeurs sauf ‘Bob’. Ainsi, le filtre doit être construit sur les valeurs d’entrée et d’état caché et être appliqué sur le vecteur d’état de la cellule.

Génération de texte à l’aide de LSTM

Nous en avons assez des concepts théoriques et du fonctionnement des LSTM. Maintenant, nous essaierions de construire un modèle qui puisse prédire un certain nombre n de caractères après le texte original de Macbeth. La plupart des textes classiques ne sont plus protégés par des droits d’auteur et peuvent être trouvés ici. Une version mise à jour du fichier .txt peut être trouvée ici.

Nous utiliserons la bibliothèque Keras, qui est une API de haut niveau pour les réseaux neuronaux et fonctionne au-dessus de TensorFlow ou Theano. Assurez-vous donc qu’avant de plonger dans ce code, vous avez Keras installé et fonctionnel.

Ok, alors générons du texte !

  • Importer les dépendances

# Importing dependencies numpy and kerasimport numpyfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import Dropoutfrom keras.layers import LSTMfrom keras.utils import np_utils

Nous importons toutes les dépendances requises et c’est assez explicite.

  • Chargement du fichier texte et création des mappings caractères vers entiers

# load textfilename = "/macbeth.txt"text = (open(filename).read()).lower()# mapping characters with integersunique_chars = sorted(list(set(text)))char_to_int = {}int_to_char = {}for i, c in enumerate (unique_chars): char_to_int.update({c: i}) int_to_char.update({i: c})

Le fichier texte est ouvert, et tous les caractères sont convertis en minuscules. Afin de faciliter les étapes suivantes, nous ferons correspondre chaque caractère à un nombre respectif. Ceci est fait pour rendre la partie calcul du LSTM plus facile.

  • Préparation du jeu de données

# preparing input and output datasetX = Y = for i in range(0, len(text) - 50, 1): sequence = text label =text X.append( for char in sequence]) Y.append(char_to_int)

Les données sont préparées dans un format tel que si nous voulons que le LSTM prédise le ‘O’ dans ‘HELLO’, nous introduirions comme entrée et comme sortie attendue. De même, ici, nous fixons la longueur de la séquence que nous voulons (fixée à 50 dans l’exemple), puis nous enregistrons les encodages des 49 premiers caractères dans X et la sortie attendue, c’est-à-dire le 50e caractère dans Y.

  • Reshaping of X

# reshaping, normalizing and one hot encodingX_modified = numpy.reshape(X, (len(X), 50, 1))X_modified = X_modified / float(len(unique_chars))Y_modified = np_utils.to_categorical(Y)

Un réseau LSTM s’attend à ce que l’entrée soit sous la forme où les échantillons sont le nombre de points de données que nous avons, les pas de temps sont le nombre d’étapes dépendantes du temps qui sont là dans un seul point de données, les caractéristiques se réfèrent au nombre de variables que nous avons pour la vraie valeur correspondante dans Y. Nous mettons ensuite à l’échelle les valeurs dans X_modifié entre 0 à 1 et un chaud coder nos vraies valeurs dans Y_modifié.

  • Définir le modèle LSTM

# defining the LSTM modelmodel = Sequential()model.add(LSTM(300, input_shape=(X_modified.shape, X_modified.shape), return_sequences=True))model.add(Dropout(0.2))model.add(LSTM(300))model.add(Dropout(0.2))model.add(Dense(Y_modified.shape, activation='softmax'))model.compile(loss='categorical_crossentropy', optimizer='adam')

On utilise un modèle séquentiel qui est un empilement linéaire de couches. La première couche est une couche LSTM avec 300 unités de mémoire et elle renvoie des séquences. Ceci est fait pour s’assurer que la couche LSTM suivante reçoit des séquences et pas seulement des données dispersées au hasard. Une couche d’exclusion est appliquée après chaque couche LSTM pour éviter un surajustement du modèle. Enfin, nous avons la dernière couche comme une couche entièrement connectée avec une activation ‘softmax’ et des neurones égaux au nombre de caractères uniques, car nous avons besoin de sortir un seul résultat codé à chaud.

  • Ajustement du modèle et génération de caractères

# fitting the modelmodel.fit(X_modified, Y_modified, epochs=1, batch_size=30)# picking a random seedstart_index = numpy.random.randint(0, len(X)-1)new_string = X# generating charactersfor i in range(50): x = numpy.reshape(new_string, (1, len(new_string), 1)) x = x / float(len(unique_chars)) #predicting pred_index = numpy.argmax(model.predict(x, verbose=0)) char_out = int_to_char seq_in = for value in new_string] print(char_out) new_string.append(pred_index) new_string = new_string

Le modèle est ajusté sur 100 époques, avec une taille de lot de 30. Nous fixons ensuite une graine aléatoire (pour faciliter la reproductibilité) et commençons à générer des caractères. La prédiction du modèle donne l’encodage du caractère prédit, il est ensuite décodé pour retrouver la valeur du caractère et annexé au motif.

Voici à quoi ressemblerait la sortie du réseau

Éventuellement, après suffisamment d’époques d’entraînement, il donnera des résultats de plus en plus bons au fil du temps. C’est ainsi que vous utiliseriez le LSTM pour résoudre une tâche de prédiction de séquence.

Notes de fin

LSTMs sont une solution très prometteuse pour les problèmes liés aux séquences et aux séries temporelles. Cependant, le seul inconvénient que je leur trouve, est la difficulté de leur formation. Il faut beaucoup de temps et de ressources système pour former même un modèle simple. Mais il ne s’agit là que d’une contrainte matérielle ! J’espère avoir réussi à vous donner une compréhension de base de ces réseaux. Pour tout problème ou question relative au blog, n’hésitez pas à commenter ci-dessous.

Apprenez, engagez , hackez et faites-vous embaucher !

.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.