Le bloc Transformer.
Faisons le point. Chaque token a reçu une fiche de sens, l’embedding (leçon 03), puis une fiche de place, l’encodage positionnel (leçon 05). Avec l’attention (leçon 06), les tokens ont enfin pu se regarder et s’enrichir du contexte. Mais l’attention se contente de mélanger des informations qui existent déjà : elle ne les transforme pas vraiment. Dans cette leçon, nous ajoutons les pièces qui manquent et nous les assemblons en une unité complète, répétée des dizaines de fois dans tous les grands modèles : le bloc Transformer.
Une réunion, puis du travail personnel
Pensez à une journée dans une équipe. Le matin, tout le monde se réunit : chacun écoute les autres et repart avec les informations utiles. C’est l’attention. L’après-midi, chacun retourne à son bureau, relit ses notes et réfléchit seul à ce qu’il a entendu, en s’appuyant sur ce qu’il sait déjà. C’est le rôle d’une nouvelle pièce, le réseau feed-forward.
Un bloc Transformer (Transformer block), c’est exactement cette journée : une réunion, puis un temps de travail personnel. Et un modèle de langage enchaîne les journées. La plus petite version de GPT-2 empile 12 blocs ; à chaque passage, les fiches des tokens deviennent un peu plus riches. On parle aussi de couche (layer) : « un modèle à 12 couches » veut dire « 12 blocs empilés ». Leur nombre est la profondeur du modèle.
Le plan d’un bloc
Un bloc contient deux sous-couches (sub-layers) : l’attention, puis le feed-forward. Chacune est précédée d’une normalisation et suivie d’une connexion résiduelle, deux notions que nous allons voir en détail. Voici le trajet d’un token, dans l’ordre utilisé par GPT-2 :
h = x + Attention( LayerNorm(x) )
sortie = h + FeedForward( LayerNorm(h) )
x : le vecteur qui entre dans le bloc
h : le vecteur après la première sous-couche
+ : la connexion résiduellePas d’inquiétude si ces noms sont encore nouveaux : le feed-forward, la connexion résiduelle (+ Résiduelle) et LayerNorm sont expliqués pas à pas dans les sections suivantes.
Point important : à la sortie, chaque token a toujours un vecteur de la même taille qu’à l’entrée, d_model dimensions. C’est ce qui permet de brancher la sortie d’un bloc directement sur l’entrée du suivant, comme des briques de Lego.
Le feed-forward : chaque token réfléchit seul
Le réseau feed-forward (feed-forward network, souvent abrégé FFN) est un petit réseau de neurones. On l’appelle aussi MLP (multilayer perceptron, perceptron multicouche). « Feed-forward » signifie « propagation vers l’avant » : l’information le traverse dans un seul sens, sans retour en arrière.
Contrairement à l’attention, il traite chaque token séparément, sans regarder les autres : c’est le moment du travail personnel. Il fonctionne en trois temps.
1. Élargir : vecteur · W₁ (d_model → d_ff, 4 fois plus large)
2. Activer : GELU sur chaque valeur, une par neurone
3. Rétrécir : résultat · W₂ (d_ff → d_model)
GPT-2 : 768 → 3 072 → 768
laboratoire : 3 → 12 → 3Chaque valeur de la couche élargie est un neurone. La couche du milieu s’appelle la couche cachée (hidden layer), et sa taille se note d_ff. Les matrices W₁ et W₂ sont des poids (weights) : des paramètres appris pendant l’entraînement, comme W_Q, W_K et W_V à la leçon 06. Les vrais modèles ajoutent aussi à chaque étape un petit vecteur appris, le biais (bias), que nous laissons de côté ici.
Pourquoi élargir ? Pour donner de la place. Avec 3 072 neurones, le modèle peut repérer des milliers de petits motifs différents. Les chercheurs pensent d’ailleurs qu’une bonne partie des connaissances d’un modèle, comme « Paris est la capitale de la France », est stockée dans ces couches. Elles représentent environ les deux tiers des paramètres d’un bloc.
La fonction d’activation : un interrupteur souple
Entre les deux multiplications, chaque neurone passe par une fonction d’activation. Sans elle, deux multiplications de matrices à la suite reviendraient à une seule, et le réseau ne pourrait représenter que des relations très simples, dites linéaires. L’activation ajoute une non-linéarité : c’est elle qui donne au réseau sa vraie puissance.
Pensez au calcul mental : multiplier par 3, puis par 2, revient simplement à multiplier une seule fois par 6. Il en va de même pour les matrices : sans interrupteur non linéaire (ReLU ou GELU) entre W₁ et W₂, les deux multiplications se fondraient en une seule, et le détour par les 3 072 neurones s’écraserait en une opération simple, sans aucun intérêt.
L’idée est celle d’un interrupteur. Un neurone qui reçoit une valeur positive « s’allume » et transmet son signal ; un neurone qui reçoit une valeur négative reste presque éteint. La version la plus simple, ReLU, remplace tout nombre négatif par 0. GPT-2 utilise une version plus souple, GELU (Gaussian Error Linear Unit), qui laisse passer une toute petite partie des valeurs négatives.
neurone 2 : 1,41 → GELU → 1,30 allumé
neurone 10 : 1,45 → GELU → 1,34 allumé
neurone 7 : -1,40 → GELU → -0,11 presque éteintVous croiserez aussi SwiGLU, une variante utilisée par la famille Llama : le principe reste le même, un interrupteur souple sur chaque neurone.
Les connexions résiduelles : ajouter au lieu de remplacer
Imaginez un document qui passe entre les mains de douze relecteurs. Si chacun le réécrit entièrement, le texte d’origine aura disparu au bout de quelques passages. Si chacun se contente d’ajouter ses annotations dans la marge, le texte d’origine reste intact, et il s’enrichit à chaque étape.
C’est l’idée de la connexion résiduelle (residual connection ou skip connection). Au lieu de remplacer le vecteur du token par la sortie d’une sous-couche, on additionne les deux : x + Attention(…), puis h + FeedForward(…). Chaque sous-couche n’apporte qu’une correction. Le vecteur qui traverse ainsi tous les blocs, en s’enrichissant à chaque addition, s’appelle le flux résiduel (residual stream).
Le laboratoire montre ce qui arrive sans cette addition. On fait passer « chat » dans 6 blocs et on mesure, après chaque bloc, à quel point ses tokens se ressemblent.
Ce score de ressemblance va de 0, quand les vecteurs n’ont aucun rapport, à 1, quand ils pointent exactement dans la même direction et deviennent donc indiscernables. Cette mesure géométrique, qui prolonge la proximité vectorielle de la leçon 03, s’appelle la similarité cosinus (cosine similarity).
Au départ, la ressemblance vaut 0,17. Sans connexions résiduelles, elle atteint 1,00 dès le quatrième bloc : les quatre tokens ont exactement la même direction, et le modèle ne peut plus distinguer le « c » du « t ». Avec les connexions résiduelles, elle reste proche de 0 : chaque token garde son identité.
Cette idée vient des réseaux de reconnaissance d’images ResNet (2015). Elle aide aussi beaucoup pendant l’entraînement, que nous étudierons plus tard : elle permet de construire des modèles très profonds sans qu’ils deviennent impossibles à ajuster.
La normalisation : garder les valeurs sous contrôle
À force d’additions, les valeurs du flux résiduel peuvent grandir, ou au contraire devenir minuscules. Les sous-couches recevraient alors des nombres de tailles très différentes d’un token à l’autre et d’un bloc à l’autre, ce qui rend l’apprentissage instable. C’est comme régler le volume avant chaque chanson d’une playlist : on veut que tout arrive à un niveau comparable.
La normalisation de couche (layer normalization, ou LayerNorm) fait ce réglage, token par token. Elle calcule la moyenne des valeurs du vecteur et leur écart type (leur dispersion autour de la moyenne), puis elle recentre le vecteur sur 0 et le remet à une dispersion de 1.
vecteur : [0,36 ; -1,16 ; 0,46]
moyenne : -0,11
écart type : 0,74
normalisé : (valeur - moyenne) ÷ écart type
= [0,64 ; -1,41 ; 0,77]Dans un vrai modèle, LayerNorm a aussi deux petits vecteurs appris, le gain et le biais, qui ajustent le résultat ; nous les laissons à leurs valeurs neutres (1 et 0). Le Transformer d’origine plaçait la normalisation après chaque addition (post-norm). GPT-2 l’a déplacée avant chaque sous-couche (pre-norm), comme dans notre laboratoire, et ajoute une dernière LayerNorm après le dernier bloc : c’est devenu la norme, car l’entraînement est plus stable. Llama utilise une variante plus simple, RMSNorm, qui ne recentre pas sur 0.
Empiler les blocs : la profondeur
Un modèle complet empile des blocs identiques par leur forme, mais chacun a ses propres poids. Les chercheurs observent souvent que les premiers blocs captent des motifs proches du texte (lettres, mots, grammaire) et que les blocs plus profonds manipulent des idées plus abstraites.
Ces quelques réglages, que l’on appelle des hyperparamètres parce qu’ils sont choisis avant l’entraînement, suffisent à décrire la taille d’un modèle. Vous les retrouverez dans toutes les fiches techniques :
n_layer = 12 blocs empilés
d_model = 768 dimensions de chaque vecteur
n_head = 12 têtes d’attention par bloc
d_ff = 3 072 neurones du feed-forward (4 × 768)
contexte = 1 024 tokens au maximum (leçon 05)
paramètres ≈ 124 millionsPour GPT-2, chaque bloc compte environ 7 millions de paramètres, dont les deux tiers dans le feed-forward, soit 85 millions pour les 12 blocs. La table d’embeddings et la table de positions apportent le reste.
Comment estimer le nombre de paramètres d’un bloc ?
Petite astuce de pro : un bloc contient environ 12 × d_model² paramètres. L’attention en compte 4 × d_model², avec W_Q, W_K, W_V et la projection finale W_O vue à la leçon 06, qui fusionne les résultats des têtes. Le feed-forward en compte 8 × d_model² : 2 matrices de d_model × 4·d_model. Soit 12 × d_model² = 4 × d_model² + 8 × d_model². Pour GPT-2, 12 × 768² ≈ 7 millions.
Observez par vous-même
Dans le laboratoire, tapez chat. Le t est sélectionné par défaut : suivez son trajet étape par étape, de son vecteur d’entrée à la sortie du bloc. Vous y retrouverez la normalisation de la section 06.
Descendez ensuite jusqu’aux 12 neurones du feed-forward : les neurones 2 et 10 s’allument nettement, tandis que le neurone 7, très négatif, est presque éteint par GELU. Cliquez sur un autre token : ce ne sont plus les mêmes neurones qui s’allument.
Enfin, regardez la carte « Empiler 6 blocs ». Comparez les deux colonnes : sans connexions résiduelles, la ressemblance entre les tokens grimpe jusqu’à 1,00. Essayez avec d’autres mots, comme bonjour.
Les limites de notre exemple
Comme dans les leçons précédentes, les poids du laboratoire sont fixes et non entraînés : les calculs sont exacts, mais les neurones qui s’allument ne correspondent à aucun motif appris.
Notre bloc est aussi très simplifié : 3 dimensions, 12 neurones, une seule tête d’attention sans projection W_O, ni biais, ni gain. Et pour l’empilement, les 6 blocs réutilisent les mêmes poids, alors que chaque bloc d’un vrai modèle a les siens.
Enfin, à la sortie du dernier bloc, nous avons des vecteurs bien enrichis… mais toujours pas de prédiction. Comment passer d’un vecteur de 768 nombres à « le prochain caractère est probablement un e » ? C’est le rôle des logits, le sujet de la prochaine leçon.
Un bloc Transformer pre-norm (GPT-2) applique deux sous-couches, chacune précédée d’une LayerNorm et entourée d’une connexion résiduelle : h = x + Attention(LayerNorm(x)), puis sortie = h + FFN(LayerNorm(h)). L’entrée et la sortie ont la même dimension d_model, ce qui permet d’empiler n_layer blocs, chacun avec ses propres poids.
Le feed-forward traite chaque token séparément : FFN(x) = GELU(x · W₁) · W₂ (biais omis), avec une couche cachée de d_ff = 4 × d_model neurones. La fonction d’activation (ReLU, GELU, SwiGLU) apporte la non-linéarité. LayerNorm recentre chaque vecteur (moyenne 0, écart type 1) avant d’appliquer un gain et un biais appris. Un bloc compte environ 12 × d_model² paramètres, dont environ deux tiers dans le feed-forward : GPT-2 small = 12 blocs, d_model = 768, d_ff = 3 072, 12 têtes, environ 124 millions de paramètres.
Attention Is All You Need, sections 3.1 « Encoder and Decoder Stacks » et 3.3 « Position-wise Feed-Forward Networks » · arXiv ↗
Language Models are Unsupervised Multitask Learners (GPT-2), section 2.3 « Model » · OpenAI ↗
Comment fonctionnent les transformers ? · Hugging Face ↗