Attention et self-attention en Python
L'attention permet à chaque token de regarder les autres tokens et de décider lesquels comptent. Chaque token a une requête (ce qu'il cherche), une clé (ce qu'il offre) et une valeur (l'information qu'il transmet).
Le concept en termes simples
L'attention permet à chaque token de regarder les autres tokens et de décider lesquels comptent. Chaque token a une requête (ce qu'il cherche), une clé (ce qu'il offre) et une valeur (l'information qu'il transmet).
Calculez à la main la scaled dot-product attention avec des requêtes, des clés et des valeurs, puis ajoutez un masque causal comme GPT.
Idées clés
- Les poids d'attention viennent d'un softmax, donc chaque ligne totalise 1.
- Diviser par √d empêche les scores de devenir trop grands pour les longs vecteurs.
- Un masque causal empêche un token de regarder les tokens futurs pendant la génération.
- La multi-head attention exécute plusieurs attentions en parallèle, et l'encodage positionnel ajoute l'ordre des mots.
Quand l’utiliser ?
- Comprendre ce qui se passe à l'intérieur des réseaux de neurones et des bibliothèques d'IA.
- Apprendre l'idée avant de l'implémenter dans les défis correspondants.
- Se préparer aux cours d'apprentissage automatique, aux entretiens et aux projets.
À vous de jouer
Cliquez sur une ligne de la carte de chaleur pour voir où regarde ce token. Activez le masque causal pour cacher les tokens futurs, et changez la netteté pour concentrer l'attention.
Code d’exemple
import math
def softmax(row):
exps = [math.exp(v - max(row)) for v in row]
return [e / sum(exps) for e in exps]
# Three tokens, each with a query, key and value vector of size 2.
Q = [[1, 0], [0, 1], [1, 1]]
K = [[1, 0], [0, 1], [1, 1]]
V = [[10, 0], [0, 10], [5, 5]]
d = len(K[0])
def attention(causal=False):
out = []
for i, q in enumerate(Q):
# Score: how well this query matches every key, scaled by sqrt(d).
scores = [sum(a * b for a, b in zip(q, k)) / math.sqrt(d) for k in K]
if causal: # a token may only look at itself and earlier tokens
scores = [s if j <= i else -1e9 for j, s in enumerate(scores)]
weights = softmax(scores)
out.append([round(sum(w * v[c] for w, v in zip(weights, V)), 2) for c in range(2)])
return out
print("attention:", attention())
print("causal attention:", attention(causal=True))
Résultat attendu
attention: [[6.02, 3.98], [3.98, 6.02], [5.0, 5.0]]
causal attention: [[10.0, 0.0], [3.3, 6.7], [5.0, 5.0]]
Fonctionnement
Pour chaque requête, les scores sont ses produits scalaires avec toutes les clés, divisés par √d. Softmax transforme les scores en poids, et la sortie est la moyenne pondérée des valeurs. Avec le masque causal, le premier token ne voit que lui-même, donc sa sortie est exactement sa propre valeur [10, 0].
Modifiez les valeurs et exécutez le programme avec le compilateur Python en ligne CodeUtility, sans installation locale.
Exercices pratiques
Modifiez les entrées et testez les cas limites avant d’utiliser des données plus volumineuses.
- Modifiez les entrées ou les poids et prédisez la sortie avant d'exécuter.
- Affichez les valeurs intermédiaires pour suivre chaque étape du calcul.
- Résolvez les défis liés ci-dessous pour implémenter l'idée vous-même.
S'entraîner avec un défi
Utilisez le contenu de cette leçon pour résoudre un vrai problème. Chaque défi s'exécute dans le navigateur, avec des tests instantanés et une revue par l'IA.
- Encodage positionnel sinusoïdal Calculez les vecteurs de position sinus et cosinus que les Transformers ajoutent aux embeddings des tokens. Moyen
- Attention par produit scalaire mis à l'échelle Implémentez l'opération d'attention, au cœur des Transformers et des grands modèles de langage. Difficile
- Auto-attention causale (masquée) Implémentez l'attention masquée des modèles GPT, où chaque token ne voit que lui-même et les tokens précédents. Moyen
- Auto-attention multi-têtes Projetez l'entrée en requêtes, clés et valeurs, exécutez l'attention dans plusieurs têtes en parallèle et combinez-les. Difficile