17. Le deep learning en pratique
Jusqu'ici, chaque leçon dérivait à la main les mécanismes des réseaux de neurones : passe avant, fonction de coût, rétropropagation et optimiseur. En pratique, vous n'écrivez presque rien de tout cela. Les frameworks modernes stockent les données sous forme de tenseurs, enregistrent les opérations que vous effectuez et les différencient automatiquement, si bien que la boucle d'entraînement que vous codez est courte et que les gradients viennent gratuitement. Cette leçon de synthèse relie la théorie aux outils, au matériel et aux habitudes qui permettent à un modèle de réellement s'entraîner.
Objectifs
- Expliquer ce qu'un tenseur et la différentiation automatique vous apportent, et comment l'autograd implémente la rétropropagation.
- Écrire de mémoire une boucle d'entraînement indépendante du framework.
- Raisonner sur la taille de batch, les accélérateurs et la précision mixte comme des compromis pratiques.
- Appliquer l'apprentissage par transfert : réutiliser un backbone préentraîné, geler les premières couches, affiner le reste.
- Reconnaître et corriger les modes de défaillance courants qui sabotent discrètement un entraînement.
- Situer les modèles de ce cours sur une même carte et les transmettre à la production.
17.1 Frameworks, tenseurs et autograd
Les deux piles logicielles dominantes sont PyTorch et TensorFlow, avec JAX comme troisième en forte croissance, qui associe une API à la NumPy à des transformations de fonctions. Les trois partagent deux idées.
Un tenseur est un tableau à n dimensions qui réside sur un périphérique (CPU ou accélérateur) et porte un type de données. Un scalaire est un tenseur 0-D, un vecteur 1-D, une matrice 2-D, et un lot d'images RVB est typiquement un tenseur 4-D de forme (batch, canaux, hauteur, largeur). Chaque activation \(a^{[l]}\), poids \(W^{[l]}\) et biais \(b^{[l]}\) des leçons précédentes est un tenseur.
La différentiation automatique (autograd) est ce qui vous évite de coder la rétropropagation. Pendant l'exécution de la passe avant, le framework enregistre chaque opération primitive dans un graphe de calcul. L'appel à backward() parcourt ce graphe à l'envers et applique la règle de la chaîne, donnant \(\partial J / \partial W^{[l]}\) et \(\partial J / \partial b^{[l]}\) pour chaque paramètre. C'est exactement la rétropropagation que vous avez dérivée plus tôt, exécutée pour vous :
Remarque : PyTorch construit le graphe dynamiquement à chaque passe avant (define-by-run), ce qui fait que le débogage ressemble à du Python ordinaire. TensorFlow et JAX peuvent tracer et compiler le graphe à l'avance pour la vitesse. Vous appelez rarement vous-même les calculs de gradient, mais connaître la formule ci-dessus est la raison pour laquelle vous pouvez diagnostiquer un gradient qui s'évanouit ou explose lorsqu'un réseau profond refuse d'apprendre.
17.2 La boucle d'entraînement
Sous chaque framework, la boucle est la même. Vous itérez sur les époques, et au sein de chaque époque sur les mini-lots, en exécutant quatre étapes par lot : passe avant, fonction de coût, passe arrière, pas de l'optimiseur. Un détail piège les débutants : les gradients s'accumulent par défaut, vous devez donc les remettre à zéro à chaque itération.
for epoch in range(num_epochs): for x_batch, y_batch in dataloader: # mini-batches, shuffled optimizer.zero_grad() # clear accumulated gradients yhat = model(x_batch) # forward pass a[L] = model(x) loss = loss_fn(yhat, y_batch) # per-batch cost J loss.backward() # autograd: backpropagation optimizer.step() # update W[l], b[l] validate(model, val_loader) # track generalization
Remarque : l'ordre compte. Remettez les gradients à zéro avant backward(), et n'appelez jamais optimizer.step() avant que la passe arrière n'ait rempli les gradients. Dans TensorFlow, ces mêmes quatre étapes vivent à l'intérieur d'un contexte GradientTape, mais la structure est identique.
17.3 Matériel et batching
Les réseaux de neurones sont de l'algèbre linéaire dense, qui se projette parfaitement sur les GPU et autres accélérateurs (TPU). Un GPU exécute des milliers de multiplications matricielles en parallèle, si bien que déplacer à la fois le modèle et les données sur le périphérique est en général la plus grande accélération que vous obtiendrez.
17.3.1 Taille de mini-lot
La taille de batch est un compromis central, pas un détail.
| Taille de batch | Qualité du gradient | Utilisation du matériel | Généralisation |
|---|---|---|---|
| Petite (8 à 32) | estimation bruitée | sous-utilise le GPU | le bruit peut aider à échapper aux minima aigus |
| Grande (256+) | estimation lisse et précise | sature le GPU | peut converger vers des minima aigus, nécessite un warmup |
Remarque : une règle empirique courante consiste à choisir le plus grand batch qui tient en mémoire, puis à régler le taux d'apprentissage en conséquence, puisqu'un batch plus grand nécessite en général un taux d'apprentissage plus élevé (ou progressif via un warmup).
17.3.2 Précision mixte
Stocker les activations et les poids en flottants 16 bits (float16 ou bfloat16) plutôt qu'en 32 bits divise la mémoire par deux et accélère les multiplications matricielles, tandis qu'une copie maîtresse des poids et de la fonction de coût reste en 32 bits pour la stabilité numérique. C'est la précision mixte, et sur les accélérateurs modernes elle offre des gains de performance quasi gratuits.
17.4 Apprentissage par transfert et fine-tuning
Entraîner un grand réseau à partir de zéro nécessite beaucoup de données et de calcul. L'apprentissage par transfert contourne cela en réutilisant un modèle déjà entraîné sur un grand corpus. Vous conservez son backbone (les couches d'extraction de caractéristiques), remplacez la tête finale spécifique à la tâche, et entraînez sur votre plus petit jeu de données.
La recette habituelle :
- Geler les premières couches, dont les caractéristiques (contours, textures, motifs génériques de tokens) se transfèrent d'une tâche à l'autre.
- Remplacer la tête par une tête dimensionnée pour vos classes ou vos sorties.
- Affiner les couches ultérieures, et éventuellement dégeler le reste avec un faible taux d'apprentissage une fois que la tête s'est stabilisée.
L'apprentissage par transfert réutilise un backbone préentraîné, remplace la tête et affine les couches ultérieures sur la nouvelle tâche.
Remarque : c'est là que le préentraînement auto-supervisé porte ses fruits. Un modèle préentraîné à la manière de BERT ou de GPT sur d'énormes quantités de texte non étiqueté encode déjà une riche structure du langage, si bien que l'affiner sur un petit ensemble étiqueté surpasse de loin l'entraînement d'un modèle neuf. Il en va de même pour les backbones de vision préentraînés sur de vastes collections d'images.
17.5 Pièges courants
La plupart des entraînements ratés n'ont rien d'exotique. Ils proviennent d'une courte liste d'erreurs, et chacune a une correction directe.
| Piège | Symptôme | Correction |
|---|---|---|
| Surapprentissage | le coût d'entraînement baisse, le coût de validation monte | régulariser, ajouter du dropout, augmenter les données ou arrêter tôt |
| Mauvais taux d'apprentissage | le coût diverge ou reste plat | balayer le taux, utiliser un scheduler ou un warmup |
| Fuite de données | excellent score de validation, mauvaise performance en production | séparer avant le prétraitement, garder les données de test invisibles |
| Oubli de mélanger | le coût plafonne ou oscille en cycle | mélanger l'ensemble d'entraînement à chaque époque |
| Absence de normalisation des entrées | entraînement lent ou instable | standardiser les caractéristiques à moyenne nulle et variance unitaire |
Remarque : la fuite de données est la plus dangereuse car elle se déguise en succès. Si vous ajustez un scaler ou sélectionnez des caractéristiques en utilisant l'ensemble complet des données avant de le séparer, une information sur l'ensemble de test s'infiltre dans l'entraînement, et le score rapporté n'est qu'un mirage.
17.6 Une carte du domaine
Les modèles de ce cours forment une lignée. Les perceptrons multicouches entièrement connectés ont fourni les mécanismes de base. Les convolutions ont ajouté la structure spatiale pour les images. Les réseaux récurrents et les LSTM ont géré les séquences. L'attention a supprimé le goulot d'étranglement séquentiel, les transformers l'ont mise à l'échelle, et le préentraînement des transformers à grande échelle a produit les modèles de fondation qui ancrent aujourd'hui la plupart des applications.
Une carte du cours : du perceptron multicouche aux réseaux convolutifs et récurrents, en passant par l'attention, les Transformers et les modèles de fondation.
Un modèle entraîné ne représente que la moitié du travail. Le servir de façon fiable, surveiller la dérive, versionner les données et automatiser le réentraînement constituent une discipline à part entière.
Pour amener n'importe lequel de ces modèles d'un notebook à un service de production fiable, poursuivez avec le cours MLOps.
Suivant : Vue d'ensemble du cours
