La matrice d’attention.
Depuis la leçon précédente, chaque token porte deux informations : son sens, grâce à l’embedding, et sa place, grâce à l’encodage positionnel. Mais chaque fiche reste seule dans son coin, sans savoir ce qui l’entoure. Dans cette leçon, nous allons découvrir la pièce maîtresse du Transformer, celle qui permet aux tokens de se regarder les uns les autres : le mécanisme d’attention, et la matrice d’attention qu’il calcule.
Un mot ne veut rien dire tout seul
Souvenez-vous de la leçon 03 : le « chat » de « mon chat dort » et celui de « ouvre le chat » partaient avec la même fiche. Pareil pour « avocat », qui peut être un fruit ou un métier. Pour savoir de quoi on parle, il faut regarder les mots autour : « mûr » ou « tribunal » lèvent tout de suite le doute.
C’est exactement ce que fait l’auto-attention (self-attention) : chaque token regarde tous les autres tokens de la phrase, décide lesquels sont importants pour lui, et s’enrichit de leurs informations. À la sortie, sa fiche ne décrit plus le token seul, mais le token dans son contexte. On parle de représentation contextuelle (contextual embedding).
Une question, une étiquette, un contenu
Pensez à une bibliothèque. Vous arrivez avec une question (« je cherche un livre sur les volcans »). Chaque livre porte une étiquette sur sa tranche. Vous comparez votre question aux étiquettes, et vous lisez surtout le contenu des livres dont l’étiquette correspond.
L’attention reprend ces trois rôles, avec leurs noms officiels. Chaque token fabrique trois vecteurs à partir de son vecteur d’entrée :
Requête (Query, Q) : « ce que je cherche »
Clé (Key, K) : « ce que je propose »
Valeur (Value, V) : « ce que je transmets si on me choisit »Pour les obtenir, on multiplie le vecteur d’entrée par trois matrices, notées W_Q, W_K et W_V. Cette opération s’appelle une projection linéaire (linear projection).
Concrètement, chaque matrice est une petite grille de nombres, de 3 × 3 dans le laboratoire. Elle agit comme un filtre spécialisé : chacun des trois nombres qu’elle produit est un mélange des trois composantes du vecteur d’entrée, dosé par les nombres de la grille. Le même vecteur d’entrée passe ainsi par trois filtres différents et en ressort sous trois formes de 3 nombres : W_Q formule la question Q, W_K fabrique l’étiquette K, W_V prépare le contenu V.
Q₁ = x₁ × W_Q[1][1] + x₂ × W_Q[2][1] + x₃ × W_Q[3][1]
Q₂ = x₁ × W_Q[1][2] + x₂ × W_Q[2][2] + x₃ × W_Q[3][2]
Q₃ = x₁ × W_Q[1][3] + x₂ × W_Q[2][3] + x₃ × W_Q[3][3]
x = [x₁ ; x₂ ; x₃] : le vecteur d’entrée du token
W_Q[ligne][colonne] : un nombre de la grilleCes matrices font partie des paramètres du modèle, comme la table d’embeddings de la leçon 03 : elles sont ajustées pendant l’entraînement, et c’est grâce à elles que le modèle apprend quoi chercher et quoi proposer.
Mesurer l’intérêt : le produit scalaire
Comment un token sait-il si un autre l’intéresse ? Il compare sa requête à la clé de l’autre avec un produit scalaire (dot product) : on multiplie les deux vecteurs dimension par dimension, puis on additionne. Le résultat est grand quand les deux vecteurs vont dans la même direction, un peu comme la proximité vectorielle de la leçon 03. Ce nombre s’appelle le score d’attention.
Q = [a₁ ; a₂ ; a₃] K = [b₁ ; b₂ ; b₃]
Q · K = a₁×b₁ + a₂×b₂ + a₃×b₃On divise ensuite chaque score par la racine carrée du nombre de dimensions des clés, notée √d_k. Avec beaucoup de dimensions, les produits scalaires deviennent très grands, et l’étape suivante ne donnerait presque tout qu’à un seul token. Cette division garde les scores dans une plage raisonnable. D’où le nom complet du mécanisme : l’attention à produit scalaire mise à l’échelle (scaled dot-product attention).
Partager son attention : softmax
Imaginez que chaque token dispose d’un budget d’attention de 100 % à répartir entre tous les tokens qu’il regarde. Il faut donc transformer les scores, qui peuvent être négatifs, en pourcentages positifs qui totalisent 100 %.
C’est le rôle de la fonction softmax. Elle passe chaque score dans une exponentielle, ce qui rend tout positif et accentue les écarts, puis divise par la somme. Dans le tableau ci-dessous, même un score négatif comme -0,78 devient un petit nombre strictement positif (environ 0,46) : le « h » garde donc une petite part d’attention. Le seul score positif, 0,40, devient le plus grand nombre (environ 1,49), loin devant les autres. On divise enfin chaque valeur par leur somme (environ 3,25) : 1,49 ÷ 3,25 donne les 46 % du « t », et l’ensemble totalise 100 %. Les pourcentages obtenus sont les poids d’attention (attention weights). Nous retrouverons softmax plus loin dans le cours, au moment de transformer la sortie du modèle en probabilités.
token score Q·K ÷ √3 poids
c -0,87 -0,50 → 19 %
h -1,35 -0,78 → 14 %
a -0,63 -0,36 → 21 %
t 0,69 0,40 → 46 %
─────
100 %La matrice d’attention
Faites le calcul pour chaque token, et rangez tous les poids dans un tableau : une ligne par token qui regarde, une colonne par token regardé. Vous obtenez la matrice d’attention. Chaque ligne totalise 100 %, et chaque case dit combien un token s’intéresse à un autre.
Une phrase de n tokens donne une matrice de n × n cases. Avec 1 000 tokens, cela fait déjà un million de scores à calculer. On dit que le coût de l’attention est quadratique : doubler la longueur du texte multiplie le travail par quatre. C’est l’une des raisons pour lesquelles la fenêtre de contexte de la leçon 05 a une limite.
Interdit de regarder l’avenir : le masque causal
Revenez à la leçon 04 : un modèle comme GPT est entraîné à deviner le token suivant. S’il pouvait lire ce token pendant l’entraînement, ce serait comme passer un examen avec la correction sous les yeux : il tricherait sans rien apprendre.
On applique donc un masque causal (causal mask) : chaque token ne peut regarder que lui-même et les tokens qui le précèdent. Dans la matrice, toutes les cases au-dessus de la diagonale sont bloquées, ce qui donne une forme de triangle. Les modèles construits ainsi, comme GPT, Llama ou Mistral, sont appelés modèles décodeurs (decoder-only).
Conséquence amusante : le premier token ne peut regarder que lui-même. Dans le laboratoire, le « c » de « chat » donne donc 100 % de son attention à… lui-même. Sans le masque, il répartirait au contraire son attention sur les quatre tokens : 23 %, 37 %, 25 % et 15 %.
Le résultat : un vecteur enrichi par le contexte
Il reste à utiliser ces poids. Chaque token additionne les valeurs de tous les tokens regardés, chacune multipliée par son poids : c’est une somme pondérée. Si le « t » accorde 46 % de son attention à lui-même et 21 % au « a », sa nouvelle fiche contiendra surtout sa propre valeur, avec un bon morceau de celle du « a ».
Sortie(t) = 19 % × V(c) + 14 % × V(h) + 21 % × V(a) + 46 % × V(t)Chaque V est un vecteur de 3 nombres : la somme se fait dimension par dimension, et la sortie est elle aussi un vecteur de 3 nombres. Faites ce calcul pour tous les tokens à la fois, et vous obtenez la formule complète :
Attention(Q, K, V) = softmax( Q · Kᵀ / √d_k ) · V
Kᵀ : la transposée de K, le tableau des clés basculé
(les lignes deviennent des colonnes)
Q · Kᵀ : tous les scores requête × clé, d’un coup
/ √d_k : la mise à l’échelle
softmax : les poids, ligne par ligne (la matrice d’attention)
· V : la somme pondérée des valeursPourquoi basculer K ? Q range une requête par ligne, et K une clé par ligne. Une fois K basculé, ses clés deviennent des colonnes : la multiplication de Q par Kᵀ croise alors chaque ligne avec chaque colonne, et l’ordinateur calcule tous les produits scalaires de tous les tokens d’un seul coup. Le résultat est directement le tableau n × n des scores.
Un seul calcul de ce type s’appelle une tête d’attention (attention head). Les vrais modèles en font plusieurs en parallèle, chacune avec ses propres matrices W_Q, W_K et W_V : c’est l’attention multi-têtes (multi-head attention). Une tête peut ainsi suivre la grammaire, une autre le sens, une autre encore les répétitions. La plus petite version de GPT-2 utilise par exemple 12 têtes.
Reste à recoller les morceaux. À la sortie, chaque tête a produit son propre vecteur pour chaque token. On met ces vecteurs bout à bout (on parle de concaténation), puis une dernière projection, avec une matrice apprise notée W_O (output), les fusionne. Chaque token retrouve ainsi un unique vecteur, enrichi de tous ces points de vue.
Observez par vous-même
Dans le laboratoire, tapez chat. La matrice d’attention forme un triangle : c’est le masque causal. Cliquez sur la ligne du t pour retrouver les scores, la division par √3 et les poids de la section 04.
Décochez ensuite « Masque causal » : le triangle se remplit, et le c peut enfin regarder les autres tokens. Remarquez que la dernière ligne ne change pas : le dernier token voyait déjà tout le monde.
Les limites de notre exemple
Les matrices W_Q, W_K et W_V du laboratoire sont fixes et non entraînées : les calculs sont exacts, mais les pourcentages ne reflètent aucun sens appris. Dans un modèle entraîné, la ligne du « t » montrerait des choix bien plus parlants.
Notre exemple n’utilise aussi qu’une seule tête, sur 3 dimensions, quand un vrai modèle en combine des dizaines, sur des centaines de dimensions. Et la matrice est limitée à 24 tokens pour rester lisible.
Enfin, l’attention n’est qu’une partie du travail. Dans un vrai Transformer, son résultat passe ensuite par un petit réseau de neurones, puis le tout est répété de nombreuses fois, couche après couche. C’est l’assemblage que nous verrons dans la prochaine leçon : les blocs Transformer.
Dans l’auto-attention, chaque vecteur d’entrée est projeté en une requête Q, une clé K et une valeur V par trois matrices apprises W_Q, W_K et W_V. Les scores Q · Kᵀ (Kᵀ, la transposée de K, permet de calculer tous les produits scalaires d’un coup), divisés par √d_k puis normalisés par softmax ligne par ligne, forment la matrice d’attention, de taille n × n : son coût est quadratique en la longueur du texte.
Dans un modèle décodeur comme GPT, un masque causal annule les poids des tokens futurs. La sortie de chaque token est la somme pondérée des valeurs : Attention(Q, K, V) = softmax(Q · Kᵀ / √d_k) · V. Pour le « t » de « chat » : Sortie(t) = 19 % × V(c) + 14 % × V(h) + 21 % × V(a) + 46 % × V(t). L’attention multi-têtes exécute plusieurs têtes en parallèle, chacune avec ses propres projections, puis concatène leurs sorties et les fusionne par une dernière projection W_O.
Attention Is All You Need, section 3.2 « Attention » · arXiv ↗
Comment fonctionnent les transformers ? · Hugging Face ↗