Concepts d'IA en Python

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

Exécuter le code →
main.py
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.

  1. Modifiez les entrées ou les poids et prédisez la sortie avant d'exécuter.
  2. Affichez les valeurs intermédiaires pour suivre chaque étape du calcul.
  3. Résolvez les défis liés ci-dessous pour implémenter l'idée vous-même.
Exécuter dans l’IDE Python →

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.

Tous les défis