Aller au contenu
Kudos AI
Read in English
Réseaux de neurones

La rétropropagation et la descente de gradient

Comment un réseau de neurones apprend : la perte comme fonction des poids, la descente de gradient, et la rétropropagation comme règle de dérivation en chaîne appliquée à rebours, avec toutes les dérivées partielles d’un petit réseau calculées à la main et vérifiées contre autograd.

8 min de lectureKudos AI

Prérequis : La régression linéaire à partir des premiers principes, La régression logistique et la classification

La perte dessinée comme une surface, le gradient pointant vers le haut et le pas allant en sens inverse, puis la règle de dérivation en chaîne parcourue à rebours dans le réseau travaillé de l’article jusqu’à ce que la perte tombe de 0,66125 à 0,2457.

Un réseau de neurones est une chaîne d’opérations simples, chacune munie de poids réglables. L’entraîner, c’est trouver les poids qui rendent la sortie correcte. Deux idées font tout le travail : la descente de gradient, qui indique dans quelle direction déplacer les poids, et la rétropropagation, qui calcule le gradient efficacement quelle que soit la profondeur de la chaîne.

On décrit souvent la rétropropagation comme difficile. C’est la règle de dérivation en chaîne, appliquée dans un ordre précis. Cet article calcule à la main chaque dérivée d’un petit réseau, puis vérifie les résultats contre un moteur de différentiation automatique.

A. Couches, poids et perte

Une couche dense applique une transformation linéaire suivie d’une non-linéarité élément par élément :

a=g(Wx+b),\mathbf{a} = g(W\mathbf{x} + \mathbf{b}) ,

où WW est une matrice de poids, b\mathbf{b} un vecteur de biais et gg une fonction d’activation. Sans gg, empiler des couches serait vain : une composition d’applications linéaires n’est qu’une autre application linéaire, et le réseau ne pourrait rien représenter qu’une seule couche ne représente déjà.

Nous employons la ReLU, g(z)=max⁡(0,z)g(z) = \max(0, z), dont la dérivée vaut 11 pour z>0z > 0 et 00 pour z<0z < 0.

Une fonction de perte note la sortie face à la cible. Pour une sortie scalaire nous utilisons

L=12(y^−y)2,L = \tfrac{1}{2}(\hat y - y)^2 ,

le 12\tfrac12 étant une commodité qui s’annule à la dérivation.

Le recadrage clé : les données étant fixées, LL est une fonction des poids. Entraîner, c’est minimiser cette fonction.

B. La descente de gradient

Le gradient ∇L\nabla L pointe dans la direction de plus forte croissance ; pour faire décroître LL nous marchons à contresens :

w←w−η∂L∂w,w \leftarrow w - \eta \frac{\partial L}{\partial w} ,

avec η\eta le taux d’apprentissage. Trop petit, l’entraînement rampe ; trop grand, il dépasse la cible - la défaillance même démontrée numériquement dans La régression logistique, où un pas de 0.50.5 dégradait substantiellement l’objectif.

Tout le problème se réduit donc au calcul de ∂L/∂w\partial L / \partial w pour chaque poids. Un réseau peut en compter des millions, et les calculer un à un serait sans espoir. La rétropropagation les obtient tous en une seule passe arrière.

C. Le réseau que nous allons dériver

Deux entrées, une couche cachée ReLU à deux unités, une sortie linéaire. Les biais sont nuls.

x=[12],W(1)=[0.10.30.20.4],W(2)=[0.5−0.5],y=1.\mathbf{x} = \begin{bmatrix}1\\2\end{bmatrix},\quad W^{(1)} = \begin{bmatrix}0.1 & 0.3\\ 0.2 & 0.4\end{bmatrix},\quad W^{(2)} = \begin{bmatrix}0.5 & -0.5\end{bmatrix},\quad y = 1 .

Passe avant.

z(1)=W(1)x=[0.1(1)+0.3(2)0.2(1)+0.4(2)]=[0.71.0].\mathbf{z}^{(1)} = W^{(1)}\mathbf{x} = \begin{bmatrix}0.1(1) + 0.3(2)\\ 0.2(1) + 0.4(2)\end{bmatrix} = \begin{bmatrix}0.7\\ 1.0\end{bmatrix} .

Les deux entrées sont positives, la ReLU les laisse donc passer inchangées :

a(1)=[0.71.0].\mathbf{a}^{(1)} = \begin{bmatrix}0.7\\ 1.0\end{bmatrix} . y^=z(2)=0.5(0.7)+(−0.5)(1.0)=0.35−0.5=−0.15.\hat y = z^{(2)} = 0.5(0.7) + (-0.5)(1.0) = 0.35 - 0.5 = -0.15 . L=12(−0.15−1)2=12(−1.15)2=12(1.3225)=0.66125.L = \tfrac12(-0.15 - 1)^2 = \tfrac12(-1.15)^2 = \tfrac12(1.3225) = 0.66125 .

D. La passe arrière

Nous remontons maintenant à rebours, en portant à chaque étape la dérivée de LL par rapport à chaque quantité. Chaque étape est une application de la règle de dérivation en chaîne.

Étape 1 - la sortie.

∂L∂y^=y^−y=−0.15−1=−1.15.\frac{\partial L}{\partial \hat y} = \hat y - y = -0.15 - 1 = -1.15 .

Étape 2 - les poids de sortie. Comme y^=W(2)a(1)\hat y = W^{(2)}\mathbf{a}^{(1)}, on a ∂y^/∂Wj(2)=aj(1)\partial \hat y / \partial W^{(2)}_j = a^{(1)}_j, donc

∂L∂W(2)=∂L∂y^ a(1)=−1.15[0.71.0]=[−0.805−1.15].\frac{\partial L}{\partial W^{(2)}} = \frac{\partial L}{\partial \hat y}\,\mathbf{a}^{(1)} = -1.15 \begin{bmatrix}0.7 & 1.0\end{bmatrix} = \begin{bmatrix}-0.805 & -1.15\end{bmatrix} .

Notez la structure : le gradient d’un poids est le signal d’erreur qui lui parvient multiplié par l’activation qui y entre. Ce motif vaut à chaque couche.

Étape 3 - retour à travers la couche de sortie. Pour continuer, il nous faut la variation de LL avec les activations cachées :

∂L∂a(1)=∂L∂y^ W(2)=−1.15[0.5−0.5]=[−0.5750.575].\frac{\partial L}{\partial \mathbf{a}^{(1)}} = \frac{\partial L}{\partial \hat y}\,W^{(2)} = -1.15\begin{bmatrix}0.5 & -0.5\end{bmatrix} = \begin{bmatrix}-0.575 & 0.575\end{bmatrix} .

L’erreur est redistribuée vers l’arrière proportionnellement aux poids qui ont porté le signal vers l’avant.

Étape 4 - à travers la ReLU. On multiplie élément par élément par la dérivée de l’activation. Les deux pré-activations étaient positives, les deux dérivées valent donc 11 :

∂L∂z(1)=[−0.5750.575].\frac{\partial L}{\partial \mathbf{z}^{(1)}} = \begin{bmatrix}-0.575 & 0.575\end{bmatrix} .

C’est de là que viennent les unités mortes. Si une pré-activation avait été négative, la dérivée de la ReLU vaudrait 00 et le gradient serait anéanti - > aucun signal d’erreur n’atteint les poids qui alimentent cette unité, et elle ne peut pas apprendre. Une unité restée négative pour toutes les entrées est une unité morte, et c’est la motivation standard de variantes comme la leaky ReLU.

Étape 5 - les poids d’entrée. Même motif qu’à l’étape 2 : signal d’erreur fois activation entrante, ici l’entrée elle-même.

∂L∂W(1)=∂L∂z(1)x⊤=[−0.5750.575][12]=[−0.575−1.150.5751.15].\frac{\partial L}{\partial W^{(1)}} = \frac{\partial L}{\partial \mathbf{z}^{(1)}} \mathbf{x}^{\top} = \begin{bmatrix}-0.575\\ 0.575\end{bmatrix}\begin{bmatrix}1 & 2\end{bmatrix} = \begin{bmatrix}-0.575 & -1.15\\ 0.575 & 1.15\end{bmatrix} .

Tous les gradients du réseau, à partir d’une passe avant et d’une passe arrière.

E. Vérification contre autograd

Les dérivations à la main sont sujettes à l’erreur, et il n’y a aucune raison de faire confiance à l’une d’elles sans vérification :

Python

S'exécute dans votre navigateur. La première exécution télécharge l'environnement Python (~10 Mo), puis il est mis en cache.

Les deux affichent True : les gradients calculés à la main s’accordent avec l’autograd de PyTorch à la précision flottante près.

F. Faire le pas

Chaque poids se déplace à l’encontre de son propre gradient. Avec η=0.1\eta = 0.1 :

W(2)←[0.5−0.5]−0.1[−0.805−1.15]=[0.5805−0.385],W^{(2)} \leftarrow \begin{bmatrix}0.5 & -0.5\end{bmatrix} - 0.1\begin{bmatrix}-0.805 & -1.15\end{bmatrix} = \begin{bmatrix}0.5805 & -0.385\end{bmatrix} , W(1)←[0.10.30.20.4]−0.1[−0.575−1.150.5751.15]=[0.15750.4150.14250.285].W^{(1)} \leftarrow \begin{bmatrix}0.1 & 0.3\\ 0.2 & 0.4\end{bmatrix} - 0.1\begin{bmatrix}-0.575 & -1.15\\ 0.575 & 1.15\end{bmatrix} = \begin{bmatrix}0.1575 & 0.415\\ 0.1425 & 0.285\end{bmatrix} .

En recalculant la passe avant avec les deux matrices mises à jour, on obtient y^=0.2989\hat y = 0.2989 et

L=12(0.2989−1)2=0.2457,L = \tfrac12(0.2989 - 1)^2 = 0.2457 ,

contre 0.661250.66125 auparavant. Un pas a plus que divisé la perte par deux. Notez que y^\hat y est passé de −0.15-0.15 vers la cible y=1y = 1 - il n’a rien dépassé, il s’est simplement déplacé dans la bonne direction, ce qui est tout ce qu’un pas de gradient promet.

La figure ci-dessous est ce réseau avec tous ses nombres : les activations sur les unités, et sur chaque poids le gradient qui lui parvient. Vérifiez-en n’importe lequel contre l’arithmétique ci-dessus. Déplacez ensuite le taux d’apprentissage. La leçon a raison de dire que les pas rétrécissent d’eux-mêmes près d’un minimum ; il vaut la peine de savoir à quelle distance se trouve la falaise de l’autre côté : à 0,5, cinq fois le taux utilisé ici, le premier pas trop grand rend une unité cachée négative et le troisième rend l’autre négative, ReLU bloque alors tout gradient en dessous, et le réseau reste à une perte de 0,5 pour toujours. Ce n’est pas une divergence, c’est une mort, et elle prend trois pas.

Interactif : une passe arrière, tous les nombres sur la table

Le réseau de la leçon. Faites un pas, puis essayez un taux plus grand.

Valeurs avant, et gradient sur chaque poids

-0.5750.575-1.1501.150-0.805-1.150x1 = 1x2 = 2h10.700h21.000y-chapeau-0.150
Prédiction
-0.1500
Perte
0.6612
dL/dy-chapeau
-1.1500
Pas effectués
0

La prédiction vaut -0,15 pour une cible de 1 : la perte est donc 0,6612 et la dérivée première -1,15. Lisez ce signe comme une direction et non comme un verdict : négatif veut dire que la perte baisse quand la prédiction monte, ce qui est exact pour une prédiction située sous sa cible. Tous les gradients du schéma sont ce même nombre poussé vers l’arrière à travers les poids : calculé une fois, réutilisé pour chaque paramètre qui alimente la sortie.

G. Les lots, et pourquoi l’algorithme passe à l’échelle

L’entraînement réel n’utilise pas un seul exemple. La descente de gradient stochastique calcule le gradient sur un petit mini-lot aléatoire et effectue un pas, en répétant sur le jeu de données. Le gradient d’un lot est plus bruité que celui du jeu complet mais infiniment moins coûteux, et le bruit est souvent utile - il peut sortir les paramètres de régions médiocres.

L’efficacité de la rétropropagation est ce qui rend tout cela réalisable : une passe avant et une passe arrière donnent la dérivée par rapport à chaque paramètre, à un coût proportionnel à la passe avant plutôt qu’au nombre de paramètres. Calculer séparément chacune d’un million de dérivées partielles par différences finies exigerait un million de passes avant.

Le gradient est local, et la surface de perte n’est pas convexe. Contrairement aux moindres carrés, la perte d’un réseau possède de nombreux minima et points-selles, et la descente de gradient n’offre aucune garantie de trouver le meilleur. En pratique les minima suffisamment bons sont fréquents, mais « ça a convergé » n’est pas « ça a trouvé l’optimum ».

À retenir

  • L’entraînement recadre la perte comme une fonction des poids et la minimise par descente de gradient, w←w−η ∂L/∂ww \leftarrow w - \eta\,\partial L/\partial w.
  • Les activations non linéaires sont essentielles ; des couches linéaires empilées se réduisent à une seule.
  • La rétropropagation est la règle de dérivation en chaîne appliquée à rebours, réutilisant chaque dérivée intermédiaire.
  • Chaque gradient de poids est activation entrante × signal d’erreur sortant - la même règle à chaque couche.
  • Notre réseau : L=0.66125L = 0.66125, ∂L/∂W(2)=[−0.805,−1.15]\partial L/\partial W^{(2)} = [-0.805, -1.15], ∂L/∂W(1)=[[−0.575,−1.15],[0.575,1.15]]\partial L/\partial W^{(1)} = [[-0.575, -1.15], [0.575, 1.15]], confirmés contre autograd.
  • Les unités ReLU à pré-activation négative transmettent un gradient nul et peuvent mourir.

La suite

La même passe arrière entraîne l’architecture derrière les modèles de langue modernes, mais ces modèles ont besoin d’un mécanisme permettant à chaque position d’une séquence de consulter toutes les autres. Ce mécanisme, c’est L’attention et l’auto-attention.

Références et lectures complémentaires

  • François Chollet, Deep Learning with Python, Manning (2nd edition, MEAP), 2020· Bibliothèque de référence Kudos AI

Les œuvres protégées par le droit d’auteur sont citées à titre de référence uniquement et ne sont pas hébergées ici ; veuillez consulter l’éditeur pour y accéder.

Lecture associée

11 min de lectureRéseaux de neurones

Ce qui fait vraiment converger un entraînement

Deux pour cent d’écart sur le taux d’apprentissage séparent une exécution convergée d’une autre à cinq ordres de grandeur, un conditionnement prédit le taux de convergence à six décimales, et la descente de gradient stochastique à pas fixe ne converge jamais - elle se stabilise dans une boule dont le rayon croît comme la racine carrée du pas. Chaque chiffre a été calculé sur un problème dont l’optimum exact est connu.

OptimisationApprentissage profondApprentissage automatique
5 min de lectureRéseaux de neurones

La direction la plus lente impose le rythme

Le pas que vous avez le droit de prendre est fixé par la direction la plus raide et le nombre de pas nécessaires par la plus plate : le coût de la descente de gradient est donc leur rapport. Le même ajustement des moindres carrés, aux mêmes dix décimales, demande 1742 pas dans une base, 147 dans une base remise à l’échelle et exactement 1 dans une base orthonormée, et l’inertie ne rachète que la racine carrée du rapport.

Apprentissage automatiqueMathématiques
8 min de lectureRéseaux de neurones

Qu’est-ce qu’un réseau de neurones ?

Les couches comme transformations paramétrées, la passe avant, et pourquoi profondeur et non-linéarité ne sont pas optionnelles : une preuve qu’aucune couche linéaire seule ne peut calculer le XOR, et un réseau à deux couches qui y parvient, entièrement déroulé à la main.

Apprentissage profondMathématiques
← Retour à tous les articles