Apprendre de ses erreurs : loss et gradient.
De la leçon 03 à la leçon 09, nous avons croisé des milliers de poids : la table d’embeddings, les matrices W_Q, W_K et W_V de l’attention, les couches du feed-forward, la tête de langage. Nous les avons toujours reçus tout prêts. Pourtant, au départ, tous ces poids sont tirés au hasard, et le modèle ne produit qu’un charabia où chaque token est aussi probable que les autres. Cette leçon montre comment une simple formule d’erreur et un calcul de pente permettent d’ajuster automatiquement des milliards de nombres. Elle reste théorique : vous observez un vrai apprentissage dans le laboratoire, et vous entraînerez votre propre modèle dans le projet MiniLab.
Des millions d’exercices cachés dans un simple texte
Un modèle est une immense machine pleine de boutons de réglage : ce sont ses paramètres, ou poids. GPT-2 dans sa plus petite version en compte environ 124 millions, les grands modèles actuels des centaines de milliards. Au départ, ils sont tirés au hasard : c’est l’initialisation. Le modèle produit alors des distributions presque plates, comme notre Transformer non entraîné de la leçon 08.
Entraîner un modèle, c’est ajuster tous ces boutons, petit à petit, pour que ses prédictions collent à de vrais textes. La première grande phase s’appelle le pré-entraînement (pre-training) : le modèle lit d’énormes quantités de texte et apprend une seule chose, deviner le token suivant.
Point remarquable : personne n’a besoin d’écrire les réponses. Le texte contient lui-même la bonne réponse, puisque le token suivant est déjà écrit. On parle d’apprentissage auto-supervisé (self-supervised learning). Il suffit de décaler le texte d’un token : à chaque position, l’entrée est tout ce qui précède, et la cible (target) est le token qui suit.
contexte → cible
c → h
c h → a
c h a → tGrâce au masque causal de la leçon 06, un Transformer traite tous ces exercices en un seul passage : chaque position prédit son token suivant sans voir la réponse. Un texte de mille tokens donne ainsi mille exercices d’un coup.
Mesurer l’erreur : la cross-entropy loss et la perplexité
Pour s’améliorer, il faut d’abord mesurer à quel point on se trompe. Pour chaque exercice, on regarde la probabilité p que le modèle a donnée au bon token. Une probabilité est comprise entre 0 et 1, donc son logarithme naturel ln(p) est toujours négatif ou nul : c’est le logprob de la leçon 08. On le change simplement de signe pour obtenir une punition positive : 0 quand le modèle a tout juste, et un nombre de plus en plus grand quand il se trompe.
p = 100 % → loss = 0 parfait
p = 50 % → loss = 0,69
p = 10 % → loss = 2,30
p = 1 % → loss = 4,61
p = 0,9 % → loss = 4,71 un tirage au hasard parmi 111 tokens
p → 0 → loss → ∞ le bon token était jugé impossibleCette mesure s’appelle l’entropie croisée (cross-entropy). Sa moyenne sur tous les exercices est la loss, ou fonction de perte (loss function). Plus elle est basse, mieux le modèle prédit. Astuce de professionnel : au tout début, un modèle bien initialisé devine au hasard, donc sa loss doit valoir environ ln(taille du vocabulaire), soit 4,71 pour nos 111 tokens. Si ce n’est pas le cas, il y a un bug.
On présente aussi souvent la perplexité (perplexity), qui vaut exp(loss). Elle se lit comme un nombre de candidats. Si le modèle donne 10 % au bon token, sa loss vaut 2,30 et sa perplexité exp(2,30) = 10 : tout se passe comme s’il hésitait au hasard entre 10 tokens équiprobables. S’il ne donne que 1 %, sa loss vaut 4,61 et sa perplexité 100 : il hésite comme entre 100 tokens. Plus la loss et la perplexité sont basses, moins le modèle est « perplexe ».
Dans quel sens tourner les boutons : le gradient et la rétropropagation
Imaginez-vous dans le brouillard, sur le flanc d’une montagne, et vous voulez descendre dans la vallée. Vous ne voyez rien, mais vous sentez la pente sous vos pieds. Il suffit de faire un pas dans le sens de la descente, puis de recommencer. Ici, l’altitude, c’est la loss ; votre position, ce sont les valeurs de tous les paramètres.
La pente, c’est le gradient (gradient) : pour chaque paramètre, il indique si augmenter ce paramètre ferait monter ou descendre la loss, et à quel point. Pour la dernière couche, celle des logits, le gradient est remarquablement simple : probabilité prédite − résultat voulu, où le voulu vaut 1 pour le bon token et 0 pour tous les autres.
token t (la cible) : 0,20 − 1 = −0,80 → signal fort : augmenter son score
token r : 0,50 − 0 = +0,50 → baisser son scoreLe signe dit dans quel sens corriger, la taille dit avec quelle force. Le « t », sous-estimé, reçoit un gradient négatif : son score doit monter. Le « r », qui volait la moitié de la probabilité, reçoit un gradient positif : son score doit baisser.
Reste à propager ce signal jusqu’aux poids qui ont produit ces scores. Le modèle est une chaîne d’opérations emboîtées : embeddings, attention, feed-forward, logits, puis loss. On remonte cette chaîne à l’envers, de la sortie vers l’entrée, en calculant à chaque maillon la part de responsabilité de chaque poids dans l’erreur finale. Cet algorithme s’appelle la rétropropagation (backpropagation) ; il repose sur la règle de dérivation en chaîne (chain rule), qui combine les pentes de chaque maillon.
Souvenez-vous des connexions résiduelles de la leçon 07, x + sous-couche(x). Elles servent précisément ici : sans elles, le signal d’erreur s’affaiblirait à chaque couche traversée et n’arriverait presque plus aux premières (on parle de vanishing gradient, ou disparition du gradient). L’addition résiduelle offre une véritable autoroute au gradient. Personne n’écrit ce calcul à la main : des bibliothèques comme PyTorch le font automatiquement (on parle d’autograd), avec une simple ligne, loss.backward().
Un pas dans la bonne direction : la descente de gradient
Une fois le gradient connu, on fait un pas : chaque paramètre est corrigé d’une petite quantité. C’est la descente de gradient (gradient descent). La taille du pas est réglée par le taux d’apprentissage (learning rate).
nouveau poids ← ancien poids − taux d’apprentissage × gradient
notation classique : θ ← θ − η × ∇loss
θ (thêta) : un poids du modèle
η (êta) : le taux d’apprentissage
∇loss : le gradient de la lossPourquoi soustraire ? Le gradient indique le sens dans lequel l’erreur monte. Pour descendre au fond de la vallée et réduire l’erreur, il faut donc faire un pas dans le sens opposé.
Le taux d’apprentissage est le réglage le plus important de tout l’entraînement. Dans le laboratoire, après 500 étapes, il donne trois comportements. Trop petit (5) : le modèle apprend très lentement, sa loss n’est qu’à 2,65. Bien réglé (50) : il descend régulièrement jusqu’à 2,43. Trop grand : à 200, il fait des pas démesurés et oscille autour de 3,08 ; à 1 000, il rebondit d’une paroi à l’autre de la vallée et l’erreur explose au-delà de 19. On dit que l’entraînement diverge.
Ces taux de 50 ou 200 vous paraissent énormes ? Ils le sont, et c’est propre à notre laboratoire. Chaque pas y suit le gradient moyen sur environ 139 000 exercices, et chaque poids de notre table ne concerne qu’une seule paire de caractères, présente dans une petite fraction d’entre eux : son gradient moyen est donc minuscule, et il faut un grand taux pour qu’il bouge. Dans un vrai Transformer entraîné avec AdamW, comme dans PyTorch ou nanochat, c’est l’inverse : le taux d’apprentissage est un tout petit nombre, typiquement entre 0,0001 et 0,001. Ce qui compte n’est pas sa valeur absolue, mais son réglage par rapport au modèle : trop petit, trop grand ou bien réglé.
Observez par vous-même
Dans le laboratoire, tapez Phileas Fogg. Dans la carte « La loss sur votre texte », placez-vous à l’étape 0 : chaque caractère suivant a 0,9 % de chances, la loss vaut 4,71 et la perplexité 111, le pur hasard. Passez à l’étape 500 : le « o » après le « F » monte à 57 %, la loss moyenne tombe à 2,18 et la perplexité à 8,8.
Dans la carte « La descente de gradient », le gradient détaillé est celui du dernier exercice de votre texte : pour « Phileas Fogg », c’est « g → g », le dernier « g » qui suit l’avant-dernier. Regardez-le : à l’étape 500, le bon « g » n’a que 12,5 %, d’où un gradient de −0,875, tandis que le « e », à 16,2 %, est poussé vers le bas avec +0,162. Changez ensuite le taux d’apprentissage pour voir la courbe ramper, descendre proprement, osciller ou exploser. Les deux cartes sont liées : l’étape et le taux choisis, rappelés en haut de chacune, changent les chiffres des deux.
Les limites de notre exemple
Notre modèle n’est pas un Transformer : c’est un modèle bigramme, une simple table de scores « caractère précédent → caractère suivant », avec 12 321 paramètres (111 × 111). Il ne regarde qu’un caractère en arrière, et sa loss ne peut donc pas descendre beaucoup plus bas. Sa table part de zéros, ce qui donne exactement le hasard, plutôt que de valeurs tirées au sort. Mais la loss, le gradient et le taux d’apprentissage fonctionnent exactement comme pour GPT-2.
Nous savons maintenant comment le modèle réduit son erreur, pas à pas. Mais que se passe-t-il quand on l’entraîne sur des milliers de livres ? Comment découper un corpus gigantesque, et surtout comment vérifier que le modèle a compris les règles de la langue au lieu d’apprendre son texte par cœur ? C’est le sujet de la prochaine leçon : le surapprentissage et le passage à l’échelle.
Le pré-entraînement est auto-supervisé : en décalant le texte d’un token, chaque position donne un exercice (contexte, cible = token suivant), et le masque causal permet de tous les traiter en un passage. La loss est l’entropie croisée : la moyenne de −ln(p du bon token). Elle vaut ln(taille du vocabulaire) pour un modèle qui devine au hasard, et la perplexité, exp(loss), se lit comme un nombre de candidats.
Pour les logits, le gradient vaut probabilité prédite − résultat voulu (1 pour la cible, 0 sinon). La rétropropagation le remonte jusqu’à chaque poids grâce à la règle de dérivation en chaîne ; les connexions résiduelles l’empêchent de s’éteindre. La descente de gradient fait ensuite un pas : θ ← θ − η × ∇loss. Un taux d’apprentissage trop petit rend l’apprentissage lent ; trop grand, la loss oscille ou diverge.
Automatic differentiation with torch.autograd · PyTorch ↗
Training a causal language model from scratch · Hugging Face ↗