Wiki IA
Deep Learning

RNN et LSTM

Réseaux récurrents pour les données séquentielles

Les Recurrent Neural Networks (RNN) sont conçus pour traiter des séquences de données où l'ordre et le contexte importent : texte, audio, séries temporelles.

Le problème des séquences

Les MLP et CNN traitent des entrées de taille fixe. Mais de nombreuses données sont des séquences de longueur variable :

  • Texte : phrases de longueurs différentes
  • Audio : parole, musique
  • Vidéo : suite d'images
  • Séries temporelles : cours boursiers, capteurs

L'ordre compte ! "Le chat mange la souris" ≠ "La souris mange le chat"

RNN : l'idée de base

Un RNN traite les éléments un par un en maintenant un état caché qui résume l'historique.

Architecture

        x₁        x₂        x₃        x₄
         ↓         ↓         ↓         ↓
       ┌───┐     ┌───┐     ┌───┐     ┌───┐
h₀ ──→ │RNN│ ──→ │RNN│ ──→ │RNN│ ──→ │RNN│ ──→ h₄
       └───┘     └───┘     └───┘     └───┘
         ↓         ↓         ↓         ↓
        y₁        y₂        y₃        y₄

Les mêmes poids sont partagés à chaque pas de temps !

Équations

hₜ = tanh(Wₕₓ · xₜ + Wₕₕ · hₜ₋₁ + bₕ)
yₜ = Wᵧₕ · hₜ + bᵧ

L'état caché hₜ encode l'information des étapes précédentes.

Types de RNN

One-to-One          One-to-Many         Many-to-One
(Standard)          (Génération)        (Classification)
    ┌───┐              ┌───┐→y₁           x₁→┌───┐
x → │   │ → y      x → │   │→y₂           x₂→│   │
    └───┘              │   │→y₃           x₃→│   │ → y
                       └───┘              x₄→└───┘

Many-to-Many        Many-to-Many
(Aligned)           (Seq2Seq)
x₁→┌───┐→y₁        x₁→┌───┐    ┌───┐→y₁
x₂→│   │→y₂        x₂→│Enc│───→│Dec│→y₂
x₃→│   │→y₃        x₃→└───┘    └───┘→y₃
x₄→└───┘→y₄

Le problème du Vanishing Gradient

Les RNN simples ont du mal à apprendre les dépendances long terme.

"Le chat qui a mangé la souris qui vivait dans le trou est ___"

Le RNN doit "se souvenir" que le sujet est "chat" sur plusieurs mots.

Pourquoi ?

Gradient = ∏ ∂hₜ/∂hₜ₋₁

Si |∂h/∂h| < 1 répété 100 fois → gradient ≈ 0 (vanishing)
Si |∂h/∂h| > 1 répété 100 fois → gradient → ∞ (exploding)

LSTM : Long Short-Term Memory

Solution au vanishing gradient proposée en 1997 par Hochreiter & Schmidhuber.

Idée clé : la cellule mémoire

Le LSTM ajoute une cellule mémoire C séparée de l'état caché, avec des portes qui contrôlent le flux d'information.

┌─────────────────────────────────────────────────┐
│                     LSTM Cell                    │
├─────────────────────────────────────────────────┤
│                                                  │
│                    ┌─────┐                      │
│          Cₜ₋₁ ────→│  ×  │──────────→ Cₜ       │
│                    └──┬──┘                      │
│         ↑            +                          │
│    ┌────┴────┐    ┌──┴──┐                      │
│    │ Forget  │    │ Add │                      │
│    │  Gate   │    │     │                      │
│    └────┬────┘    └──┬──┘                      │
│         │            │                          │
│    ┌────┴────┐  ┌────┴────┐                    │
│    │   σ     │  │  tanh   │                    │
│    └────┬────┘  └────┬────┘                    │
│         │            │                          │
│      [hₜ₋₁,xₜ]   [hₜ₋₁,xₜ]                    │
│                                                  │
└─────────────────────────────────────────────────┘

Les 4 portes

# 1. Forget Gate : que garder de l'ancienne mémoire ?
fₜ = σ(Wf · [hₜ₋₁, xₜ] + bf)    # Entre 0 et 1

# 2. Input Gate : quoi ajouter de nouveau ?
iₜ = σ(Wi · [hₜ₋₁, xₜ] + bi)    # Entre 0 et 1
C̃ₜ = tanh(Wc · [hₜ₋₁, xₜ] + bc) # Candidat

# 3. Cell State : mise à jour de la mémoire
Cₜ = fₜ * Cₜ₋₁ + iₜ * C̃ₜ

# 4. Output Gate : que sortir ?
oₜ = σ(Wo · [hₜ₋₁, xₜ] + bo)
hₜ = oₜ * tanh(Cₜ)

Pourquoi ça marche ?

Le flux de gradient à travers C est linéaire (additions/multiplications), évitant le vanishing gradient.

∂Cₜ/∂Cₜ₋₁ = fₜ  (proche de 1 si on veut garder)

Le gradient peut "couler" sur de longues séquences.

GRU : Gated Recurrent Unit

Version simplifiée du LSTM (2014), souvent aussi performante.

# Reset Gate : que garder du passé ?
rₜ = σ(Wr · [hₜ₋₁, xₜ])

# Update Gate : combien mettre à jour ?
zₜ = σ(Wz · [hₜ₋₁, xₜ])

# Candidat
h̃ₜ = tanh(W · [rₜ * hₜ₋₁, xₜ])

# Nouvel état
hₜ = (1 - zₜ) * hₜ₋₁ + zₜ * h̃ₜ

LSTM vs GRU

AspectLSTMGRU
ParamètresPlusMoins
Portes42
PerformanceSouvent meilleure sur longues séquencesComparable, plus rapide
MémoireCellule séparéeÉtat unique

Implémentation PyTorch

RNN simple

import torch
import torch.nn as nn

# RNN basique
rnn = nn.RNN(input_size=10, hidden_size=20, num_layers=2, batch_first=True)

# Entrée : (batch, seq_len, input_size)
x = torch.randn(32, 50, 10)
h0 = torch.zeros(2, 32, 20)  # (num_layers, batch, hidden_size)

output, hn = rnn(x, h0)
# output: (32, 50, 20) - toutes les sorties
# hn: (2, 32, 20) - dernier état caché

LSTM

lstm = nn.LSTM(input_size=10, hidden_size=20, num_layers=2, batch_first=True)

h0 = torch.zeros(2, 32, 20)
c0 = torch.zeros(2, 32, 20)

output, (hn, cn) = lstm(x, (h0, c0))
# cn: cellule mémoire finale

GRU

gru = nn.GRU(input_size=10, hidden_size=20, num_layers=2, batch_first=True)

output, hn = gru(x, h0)

Architectures avancées

Bidirectionnel

Traite la séquence dans les deux sens.

     →  →  →  →
x₁  x₂  x₃  x₄
     ←  ←  ←  ←

Utile quand le contexte futur compte (NLP).
lstm = nn.LSTM(input_size=10, hidden_size=20,
               bidirectional=True, batch_first=True)

# Output: (batch, seq_len, hidden_size * 2)

Multi-couches (Stacked)

        x₁    x₂    x₃
         ↓     ↓     ↓
       ┌───┐ ┌───┐ ┌───┐
       │L1 │→│L1 │→│L1 │  Couche 1
       └───┘ └───┘ └───┘
         ↓     ↓     ↓
       ┌───┐ ┌───┐ ┌───┐
       │L2 │→│L2 │→│L2 │  Couche 2
       └───┘ └───┘ └───┘
         ↓     ↓     ↓
        y₁    y₂    y₃
lstm = nn.LSTM(input_size=10, hidden_size=20,
               num_layers=3, batch_first=True, dropout=0.2)

Seq2Seq avec attention

Base des premiers systèmes de traduction neuronale.

Encoder                    Decoder
  ┌───┐                    ┌───┐
→ │   │→                 → │   │→ "Le"
  └───┘                    └───┘
  ┌───┐                    ┌───┐
→ │   │→  ═══Context═══> → │   │→ "chat"
  └───┘                    └───┘
  ┌───┐                    ┌───┐
→ │   │→                 → │   │→ "dort"
  └───┘                    └───┘
 "The cat sleeps"

Exemple complet : Classification de texte

import torch
import torch.nn as nn

class TextClassifier(nn.Module):
    def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.lstm = nn.LSTM(embed_dim, hidden_dim,
                           num_layers=2, batch_first=True,
                           bidirectional=True, dropout=0.3)
        self.fc = nn.Linear(hidden_dim * 2, num_classes)
        self.dropout = nn.Dropout(0.5)

    def forward(self, x):
        # x: (batch, seq_len) - indices de tokens

        # Embedding
        embedded = self.embedding(x)  # (batch, seq_len, embed_dim)

        # LSTM
        output, (hn, cn) = self.lstm(embedded)
        # hn: (num_layers * 2, batch, hidden_dim)

        # Concaténer les derniers états forward et backward
        hidden = torch.cat([hn[-2], hn[-1]], dim=1)
        # hidden: (batch, hidden_dim * 2)

        # Classification
        out = self.dropout(hidden)
        out = self.fc(out)

        return out

# Utilisation
model = TextClassifier(vocab_size=10000, embed_dim=128,
                       hidden_dim=256, num_classes=5)

# Batch de 32 séquences de 100 tokens
x = torch.randint(0, 10000, (32, 100))
output = model(x)  # (32, 5)

Applications

Traitement du langage naturel

  • Classification de texte (sentiment, spam)
  • Génération de texte
  • Traduction automatique
  • Résumé automatique

Séries temporelles

  • Prévision météo
  • Prédiction boursière
  • Détection d'anomalies
  • Maintenance prédictive

Audio et parole

  • Reconnaissance vocale
  • Synthèse vocale
  • Transcription musicale

Limites des RNN/LSTM

Malgré leurs succès, les RNN ont des limites :

LimiteConséquence
SéquentielPas de parallélisation, lent à entraîner
Dépendances très longuesLSTM aide mais pas parfait
Contexte limitéDifficile de "regarder loin"

Depuis 2017, les Transformers ont largement remplacé les LSTM pour le NLP grâce à leur parallélisme et leur gestion supérieure du contexte long.

LSTM vs Transformers

AspectLSTMTransformer
ParallélisationNon (séquentiel)Oui (attention)
Contexte longDifficileExcellent
EntraînementLentRapide
MémoireFaibleÉlevée
InterprétabilitéDifficileAttention visualisable

Les LSTM restent utiles pour :

  • Séries temporelles courtes
  • Ressources limitées
  • Applications temps réel sur edge

On this page