AvancéDeep Learning
30 min de lecture21 vues

Transformers : l'Architecture qui a Tout Changé

Comprenez le mécanisme d'attention, l'architecture Transformer (encoder/decoder), BERT, GPT et les Vision Transformers avec des implémentations PyTorch.

Avant les Transformers : le Problème des Séquences

Les limites des RNN et LSTM

Avant 2017, le traitement du langage reposait sur les réseaux récurrents (RNN, LSTM, GRU). Ces architectures traitent les mots un par un, dans l''ordre :

Problèmes :

  • Séquentiel : impossible de paralléliser → entraînement lent
  • Mémoire courte : les premiers mots sont "oubliés" dans les longues phrases
  • Vanishing gradient : le gradient s''évanouit en traversant trop d''étapes

La révolution de 2017

Le papier "Attention Is All You Need" (Vaswani et al., 2017) a tout changé en proposant une architecture basée uniquement sur des mécanismes d''attention, sans aucune récurrence.

Ce papier de Google est probablement le plus influent de la dernière décennie en IA. Il a engendré GPT, BERT, Claude, Gemini, Stable Diffusion et presque tous les modèles modernes.


Le Mécanisme d''Attention

L''intuition

Quand vous lisez "Le chat qui était sur le tapis dort", vous savez instinctivement que "dort" se rapporte à "chat" et pas à "tapis". Le mécanisme d''attention fait la même chose : il apprend quels mots sont importants les uns par rapport aux autres.

Self-Attention pas à pas

Pour chaque mot (token), on calcule 3 vecteurs :

  • Query (Q) : "Je cherche quoi ?"
  • Key (K) : "Qu''est-ce que je contiens ?"
  • Value (V) : "Quelle information je transmets ?"
Attention(Q, K, V) = softmax(Q · Kᵀ / √dₖ) · V

Étape par étape :

  1. Calculer les scores : Q · Kᵀ → chaque mot note sa compatibilité avec tous les autres
  2. Normaliser : diviser par √dₖ pour éviter les valeurs trop grandes
  3. Softmax : transformer en probabilités (somme = 1)
  4. Pondérer : multiplier par V pour obtenir la représentation contextuelle

Exemple concret

Phrase : "Le chat dort"

Lechatdort
Le0.10.70.2
chat0.10.30.6
dort0.00.80.2

"dort" accorde 80% de son attention à "chat" → il comprend que c''est le chat qui dort.

Implémentation simplifiée en PyTorch

import torch
import torch.nn.functional as F

def self_attention(x, d_model=64):
    """
    x : tensor de shape (batch, seq_len, d_model)
    """
    # Projections linéaires
    W_q = torch.nn.Linear(d_model, d_model, bias=False)
    W_k = torch.nn.Linear(d_model, d_model, bias=False)
    W_v = torch.nn.Linear(d_model, d_model, bias=False)

    Q = W_q(x)  # (batch, seq_len, d_model)
    K = W_k(x)
    V = W_v(x)

    # Score d''attention
    d_k = Q.size(-1)
    scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5)

    # Softmax → poids d''attention
    attn_weights = F.softmax(scores, dim=-1)

    # Sortie pondérée
    output = torch.matmul(attn_weights, V)
    return output, attn_weights

Multi-Head Attention

Au lieu d''une seule attention, on en exécute plusieurs en parallèle (typiquement 8 ou 12 "têtes"). Chaque tête peut apprendre un type de relation différent :

  • Tête 1 : relations sujet-verbe
  • Tête 2 : relations adjectif-nom
  • Tête 3 : coréférences (pronoms)
class MultiHeadAttention(torch.nn.Module):
    def __init__(self, d_model=512, n_heads=8):
        super().__init__()
        self.n_heads = n_heads
        self.d_head = d_model // n_heads

        self.W_q = torch.nn.Linear(d_model, d_model)
        self.W_k = torch.nn.Linear(d_model, d_model)
        self.W_v = torch.nn.Linear(d_model, d_model)
        self.W_o = torch.nn.Linear(d_model, d_model)

    def forward(self, x):
        batch, seq_len, d_model = x.shape

        # Projeter et diviser en têtes
        Q = self.W_q(x).view(batch, seq_len, self.n_heads, self.d_head).transpose(1, 2)
        K = self.W_k(x).view(batch, seq_len, self.n_heads, self.d_head).transpose(1, 2)
        V = self.W_v(x).view(batch, seq_len, self.n_heads, self.d_head).transpose(1, 2)

        # Attention par tête
        scores = torch.matmul(Q, K.transpose(-2, -1)) / (self.d_head ** 0.5)
        attn = F.softmax(scores, dim=-1)
        context = torch.matmul(attn, V)

        # Recombiner les têtes
        context = context.transpose(1, 2).contiguous().view(batch, seq_len, d_model)
        return self.W_o(context)

L''Architecture Transformer Complète

Encodage Positionnel

L''attention n''a aucune notion d''ordre. "Le chat mange la souris" et "La souris mange le chat" produiraient le même résultat. On ajoute donc un encodage positionnel :

import math

def positional_encoding(seq_len, d_model):
    pe = torch.zeros(seq_len, d_model)
    position = torch.arange(0, seq_len).unsqueeze(1).float()
    div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))

    pe[:, 0::2] = torch.sin(position * div_term)  # Dimensions paires
    pe[:, 1::2] = torch.cos(position * div_term)  # Dimensions impaires
    return pe

Pourquoi sin/cos ? Ces fonctions permettent au modèle d''apprendre des positions relatives : la différence entre la position 5 et 10 est la même qu''entre 100 et 105.

Bloc Transformer (Encoder)

Chaque bloc contient :

  1. Multi-Head Attention + Residual Connection + Layer Norm
  2. Feed-Forward Network + Residual Connection + Layer Norm
class TransformerBlock(torch.nn.Module):
    def __init__(self, d_model=512, n_heads=8, d_ff=2048, dropout=0.1):
        super().__init__()
        self.attention = MultiHeadAttention(d_model, n_heads)
        self.norm1 = torch.nn.LayerNorm(d_model)
        self.norm2 = torch.nn.LayerNorm(d_model)
        self.ffn = torch.nn.Sequential(
            torch.nn.Linear(d_model, d_ff),
            torch.nn.ReLU(),
            torch.nn.Linear(d_ff, d_model),
        )
        self.dropout = torch.nn.Dropout(dropout)

    def forward(self, x):
        # Self-attention + residual
        attn_out = self.attention(x)
        x = self.norm1(x + self.dropout(attn_out))

        # Feed-forward + residual
        ffn_out = self.ffn(x)
        x = self.norm2(x + self.dropout(ffn_out))
        return x

BERT vs GPT : Encoder vs Decoder

Le Transformer original a un encoder ET un decoder. Les modèles modernes n''utilisent souvent qu''un seul des deux.

BERT (Encoder only)

  • Attention bidirectionnelle : chaque mot voit tous les autres
  • Entraînement : masquer des mots et les prédire (Masked Language Model)
  • Usage : classification, NER, question answering
Entrée :  "Le [MASK] dort sur le tapis"
BERT :    "Le  chat   dort sur le tapis"

GPT (Decoder only)

  • Attention causale : chaque mot ne voit que les précédents
  • Entraînement : prédire le mot suivant (autorégressif)
  • Usage : génération de texte, chatbots (ChatGPT, Claude)
Entrée :  "Le chat dort sur"
GPT :     → "le"  → "tapis"  → "."
BERTGPT
ArchitectureEncoderDecoder
AttentionBidirectionnelleCausale (gauche→droite)
TâcheComprendreGénérer
ExemplesBERT, RoBERTa, CamemBERTGPT-4, Claude, Llama

CamemBERT est un modèle BERT entraîné spécifiquement sur du texte français. Il est excellent pour les tâches NLP en français.


Exercice : Utiliser un Transformer Pré-entraîné

Classification de sentiment avec Hugging Face

from transformers import pipeline

# Charger un pipeline de classification de sentiment
classifier = pipeline("sentiment-analysis", model="nlptown/bert-base-multilingual-uncased-sentiment")

# Tester sur des phrases françaises
phrases = [
    "Ce film est absolument magnifique, je le recommande !",
    "Service client horrible, jamais plus.",
    "Le repas était correct, sans plus.",
]

for phrase in phrases:
    result = classifier(phrase)[0]
    print(f"'{phrase[:50]}...' → {result['label']} ({result['score']:.2f})")

Génération de texte avec GPT-2

from transformers import pipeline

generator = pipeline("text-generation", model="gpt2")

prompt = "Deep learning is"
results = generator(prompt, max_length=50, num_return_sequences=3)

for i, result in enumerate(results):
    print(f"\n--- Génération {i+1} ---")
    print(result["generated_text"])

Vision Transformers (ViT)

Les Transformers ne sont pas limités au texte. Le Vision Transformer (2020) traite les images en les découpant en patches et en les traitant comme une séquence de tokens.

Résultat : ViT atteint des performances comparables ou supérieures aux CNN, surtout avec beaucoup de données d''entraînement.

ViT nécessite beaucoup de données. Avec peu de données, un CNN avec transfer learning reste souvent meilleur. Google a entraîné ViT sur 300 millions d''images (JFT-300M).


Scaling Laws : Plus c''est Gros, Mieux c''est ?

Les recherches de Kaplan et al. (2020) ont montré que les performances des Transformers suivent des lois de puissance prévisibles :

On augmente...La performance...
Le nombre de paramètresS''améliore (log-linéaire)
La quantité de donnéesS''améliore (log-linéaire)
Le compute (FLOPs)S''améliore (log-linéaire)

C''est ce qui a motivé la course aux modèles géants :

ModèleParamètresAnnée
BERT base110M2018
GPT-21.5B2019
GPT-3175B2020
GPT-4~1.7T (estimé)2023
Llama 3.1405B2024

Nuance importante : les scaling laws montrent aussi des rendements décroissants. Doubler les paramètres ne double pas les performances. C''est pourquoi la recherche s''oriente aussi vers des modèles plus efficaces (distillation, quantization, MoE).


Pour Aller Plus Loin

  • Exercice avancé : implémentez un Transformer encoder complet de zéro en PyTorch
  • Lisez le papier original Attention Is All You Need
  • Explorez Hugging Face pour découvrir les milliers de modèles pré-entraînés disponibles
  • Testez CamemBERT sur des tâches NLP françaises : camembert-base sur Hugging Face

Specialiste IA — Master Intelligence Artificielle

Diplome d'un Master en Intelligence Artificielle, je travaille au quotidien sur des projets IA en entreprise. J'ai cree IwanttolearnAI pour rendre l'apprentissage de l'IA accessible a tous, gratuitement.