Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Comment marche l’attention dans un transformeur

Après cette leçon: Je peux calculer à la main la sortie de l’attention pour un jeton.

Leçon de 65 min2 commandesLab JupyterLab de science des données : pandas, Matplotlib et scikit-learn dans le navigateur

Quels mots d’avant comptent pour celui-ci ?

L’attention est l’étape d’un transformeur où chaque jeton regarde les autres jetons et leur prend ce dont il a besoin. C’est grâce à elle qu’un modèle de langage relie « il » au bon nom, plusieurs mots en arrière.

Dans « le train est bondé », le mot bondé parle du train. L’attention est la façon dont le modèle le trouve avec des nombres.

À la fin de cette leçon

Remarque

Je peux calculer à la main la sortie de l’attention pour un jeton.

Mots-clés

MotCe que ça veut direExemple
Requêteun vecteur qui dit ce qu’un jeton cherche
Cléun vecteur qui dit ce qu’un jeton offre
Valeurun vecteur qui porte ce qu’un jeton transmet
Scoreà quel point une requête correspond à une clé2
Softmaxchange des scores en parts dont la somme vaut 1
Poidsla part d’une valeur qui entre dans la sortie0,665

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Requête, clé et valeur pour chaque jeton

Le module d’algèbre linéaire montre comment une table multiplie un vecteur. L’attention multiplie chaque vecteur d’entrée par trois tables apprises, ce qui donne trois nouveaux vecteurs.

La requête dit ce que ce jeton cherche. La clé dit ce qu’il offre aux autres. La valeur est ce qu’il transmet s’il est choisi. Ci-dessous, nous partons des trois vecteurs déjà calculés.

Exemple travaillé : noter la requête de bondé

JetonCléRequête de bondé fois cléScore
train2, 11x2 + 0x12
est0, 21x0 + 0x20
bondé1, 11x1 + 0x11

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Softmax change les scores en poids

Les scores peuvent avoir n’importe quelle taille, même sous 0. Le softmax les change en poids tous positifs, dont la somme vaut 1.

On prend d’abord e puissance chaque score, la touche exp d’une calculatrice. Chaque nombre devient positif, et un grand score devient bien plus grand. Puis on divise chacun par le total. Les vrais modèles divisent aussi chaque score par un nombre fixe avant. Nous sautons cette étape ici.

Exemple travaillé : softmax de 2, 0 et 1

JetonScoree puissance le scorePoids : diviser par 11,11
train27,390,665
est01,000,090
bondé12,720,245
Total11,111,000

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Scores et poids avec NumPy

Commande
docker exec jupyter python3 -c "import numpy as np; K = np.array([[2, 1], [0, 2], [1, 1]]); s = K @ np.array([1, 0]); w = np.exp(s) / np.exp(s).sum(); print(s.tolist(), w.round(3).tolist())"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

La sortie est un mélange pondéré des valeurs

On multiplie la valeur de chaque jeton par son poids, puis on additionne les résultats. Cette somme est le nouveau vecteur de bondé.

Bondé a pris les deux tiers de son nouveau vecteur chez train, donc bondé porte maintenant une part du sens de train. Chaque jeton fait de même avec sa propre requête, au même moment.

Exemple travaillé : mélanger les valeurs

JetonPoidsValeurPoids fois valeur
train0,66510, 06,65, 0
est0,0900, 100, 0,90
bondé0,2455, 51,22, 1,22
Sortieenviron 7,88, 2,12

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

L’attention pour un jeton en Python

Code: python
import math

cles = [[2, 1], [0, 2], [1, 1]]         # train, est, bondé
valeurs = [[10, 0], [0, 10], [5, 5]]
requete = [1, 0]                        # la requête de bondé

scores = []
for cle in cles:
    scores.append(requete[0] * cle[0] + requete[1] * cle[1])

puissances = []
for s in scores:
    puissances.append(math.exp(s))
total = sum(puissances)
poids = []
for p in puissances:
    poids.append(p / total)

melange = [0, 0]
for i in range(len(valeurs)):
    for j in range(2):
        melange[j] = melange[j] + poids[i] * valeurs[i][j]

print("scores :", scores)
print("poids :", [round(w, 3) for w in poids])
print("sortie :", [round(m, 2) for m in melange])
# Remplacez la requête par [0, 1], puis cliquez sur Exécuter.
# Quel jeton reçoit le plus de poids maintenant ?

Une erreur fréquente

Attention

Beaucoup pensent que l’attention choisit un jeton et ignore les autres. Elle prend une part de la valeur de chaque jeton. Un poids est proche de 0 seulement quand la clé correspond mal à la requête, et les poids font toujours 1 au total.

L’attention pour les trois jetons à la fois

Commande
docker exec jupyter python3 -c "import numpy as np; Q = np.array([[0, 1], [1, 1], [1, 0]]); K = np.array([[2, 1], [0, 2], [1, 1]]); V = np.array([[10, 0], [0, 10], [5, 5]]); S = Q @ K.T; W = np.exp(S) / np.exp(S).sum(axis=1, keepdims=True); print(W.round(3).tolist()); print((W @ V).round(2).tolist())"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

À propos de ce labo et de sa source: Lab JupyterLab de science des données : pandas, Matplotlib et scikit-learn dans le navigateur

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.