Backpropagation
La rétropropagation applique la règle de la chaîne à rebours dans un réseau neuronal afin de calculer le gradient de chaque poids en une passe. Présentation des mathématiques, du coût et du code.
La rétropropagation, abréviation de « propagation rétrograde des erreurs », est l’algorithme qui calcule la contribution de chaque poids d’un réseau neuronal à l’erreur d’une prédiction. À partir de la fonction de perte, elle applique la règle de la chaîne couche par couche en remontant vers l’entrée et réutilise chaque résultat intermédiaire ; un seul passage arrière fournit ainsi le gradient de chaque poids, que le modèle compte des milliers ou des milliards de paramètres. Un optimiseur utilise ensuite ces gradients pour mettre à jour les poids ; la rétropropagation constitue donc l’étape d’apprentissage de pratiquement tous les modèles d’apprentissage profond. Rumelhart, Hinton et Williams l’ont popularisée pour les réseaux neuronaux dans leur article de 1986 publié dans Nature, Learning representations by back-propagating errors.
Fonctionnement de la rétropropagation#
L’entraînement sur un lot s’effectue en deux passages. Le passage avant fait transiter les entrées par chaque couche, stocke les activations intermédiaires et se termine par le calcul de la perte. Le passage arrière part de la perte et parcourt les couches dans l’ordre inverse. Chaque couche reçoit le gradient de la perte par rapport à sa sortie, appelé gradient amont, et le multiplie par ses dérivées locales pour produire deux résultats : le gradient des poids de la couche, conservé pour l’optimiseur, et le gradient par rapport à l’entrée de la couche, qui devient le gradient amont de la couche précédente.
Comme chaque couche n’a besoin que de son gradient amont et de ses activations stockées, aucun dérivé n’est calculé deux fois. En termes de différentiation automatique, la rétropropagation est la différentiation en mode inverse du graphe de calcul du réseau ; PyTorch construit ce graphe pendant le passage avant et le parcourt à rebours lors de l’appel à loss.backward(). Dans un réseau à deux poids, on peut comparer le résultat d’autograd de PyTorch à l’application écrite à la main de la règle de la chaîne :
import torch
# A two-weight network: prediction = w2 * tanh(w1 * x)
x, target = torch.tensor(1.5), torch.tensor(0.5)
w1 = torch.tensor(0.8, requires_grad=True)
w2 = torch.tensor(-1.2, requires_grad=True)
# Forward pass, keeping the hidden activation h for the backward pass
h = torch.tanh(w1 * x)
loss = (w2 * h - target) ** 2
# Backward pass: autograd applies the chain rule from the loss back to each weight
loss.backward()
# The same chain rule by hand, reusing the upstream gradient dL/dy for both weights
dL_dy = 2 * (w2 * h - target)
dL_dw2 = dL_dy * h
dL_dw1 = dL_dy * w2 * (1 - h**2) * x
print(f"autograd: dL/dw1 = {w1.grad:.4f}, dL/dw2 = {w2.grad:.4f}")
print(f"by hand: dL/dw1 = {dL_dw1:.4f}, dL/dw2 = {dL_dw2:.4f}")Les deux lignes affichent dL/dw1 = 1.6475, dL/dw2 = -2.5016. La version écrite à la main calcule dL_dy une seule fois et le réutilise pour les deux poids, comme autograd le fait pour gérer des réseaux comptant des milliards de poids. La rétropropagation à travers le temps (BPTT) est le même algorithme appliqué à un réseau neuronal récurrent déroulé sur ses pas de temps.
Rétropropagation et optimiseur#
La rétropropagation ne fait que calculer les gradients et ne modifie aucun poids. Un algorithme d’optimisation, comme la descente de gradient stochastique (SGD) ou Adam, transforme ces gradients en mises à jour des poids, mises à l’échelle par le taux d’apprentissage. PyTorch ajoute le résultat de chaque passage arrière aux gradients déjà stockés sur les poids ; une étape de l’optimiseur peut donc combiner plusieurs lots :
L’entraînement Ultralytics YOLO utilise cette accumulation de gradients pour atteindre une taille de lot nominale de 64 images (nbs=64) : après la phase de chauffe, une exécution batch=16 effectue la rétropropagation à chaque lot, mais ne met à jour l’optimiseur que tous les quatre lots, après avoir limité la norme du gradient combiné à 10.
Disparition et explosion des gradients#
La passe arrière multiplie les dérivées locales couche après couche, de sorte que la taille du gradient peut diminuer ou augmenter géométriquement avec la profondeur. Lorsque la plupart des facteurs sont inférieurs à 1, comme pour les unités sigmoïdes saturées, les premières couches ne reçoivent presque aucun signal : c’est le problème du gradient évanescent. Lorsque la plupart des facteurs sont supérieurs à 1, le problème du gradient explosif entraîne des mises à jour considérables et des pertes NaN. Les activations de la famille ReLU, une initialisation des poids à échelle adaptée, la normalisation par lots et les connexions de saut des réseaux résiduels stabilisent l’amplitude des gradients sur des centaines de couches.
Coût en calcul et en mémoire#
Chaque activation nécessaire à une dérivée locale doit rester en mémoire depuis la passe avant jusqu’à ce que la passe arrière l’atteigne. La mémoire requise pour l’entraînement augmente donc avec la taille du lot, la résolution d’entrée et la profondeur, et l’entraînement nécessite bien plus de mémoire que l’inférence. Le checkpointing des gradients stocke seulement certaines activations et recalcule les autres pendant la passe arrière, ce qui réduit la mémoire au prix d’un surcroît de calcul. La précision mixte conserve la plupart des activations dans des formats 16 bits qui occupent deux fois moins d’espace que les flottants 32 bits. En termes de calcul, la passe arrière coûte environ deux fois plus que la passe avant, car chaque couche calcule les gradients de ses poids et de ses entrées. C’est pourquoi les estimations fondées sur les lois d’échelle comptent environ 6 opérations en virgule flottante par paramètre et par jeton d’entraînement : 2 pendant la passe avant et 4 pendant la passe arrière.










