Rétropropagation, fonctions d’activation, disparition du gradient, dropout, normalisation par lots, optimiseurs, CNN et transformeurs : l’apprentissage profond en entretien.
Cliquez sur une question pour dérouler la réponse attendue.
Une composition de transformations simples, empilées en couches, dont on apprend les paramètres par descente de gradient.
Chaque couche fait deux choses : une combinaison linéaire des entrées — des poids et un biais — puis une fonction non linéaire appliquée au résultat. Empiler ces couches permet de représenter des fonctions que ni l’une ni l’autre ne pourrait produire seule.
Le point qui montre qu’on a compris, et qu’il faut donner sans qu’on le demande : sans la non-linéarité, empiler des couches ne sert à rien. La composition de plusieurs transformations linéaires reste une transformation linéaire, donc un réseau de dix couches sans activation est exactement équivalent à une régression linéaire. C’est l’activation qui fait la profondeur.
Le vocabulaire à placer correctement :
Et ce qu’il faut savoir dire sur la profondeur, parce que c’est la question qui suit : le théorème d’approximation universelle assure qu’un réseau à une seule couche cachée suffisamment large peut approcher n’importe quelle fonction continue. Ce résultat est vrai et il n’explique rien de la pratique : ce qui rend les réseaux profonds efficaces, c’est qu’ils apprennent des représentations hiérarchiques — des contours puis des motifs puis des objets — et qu’ils atteignent avec peu de paramètres par couche ce qu’une couche unique demanderait en largeur démesurée.
À introduire la non-linéarité, sans laquelle la profondeur n’apporte rien. Une composition de couches linéaires reste linéaire : un réseau de vingt couches sans activation a exactement le pouvoir d’expression d’une régression linéaire.
Les fonctions à connaître, avec ce qui les distingue :
| Fonction | Sortie | Usage |
|---|---|---|
| ReLU | 0 ou l’entrée | le défaut des couches cachées |
| Leaky ReLU | pente faible en négatif | quand des neurones meurent |
| GELU, SiLU | variantes lisses | transformeurs et réseaux récents |
| Sigmoïde | entre 0 et 1 | sortie d’une classification binaire |
| Softmax | probabilités sommant à 1 | sortie d’une classification multiclasse |
| Tanh | entre −1 et 1 | portes des LSTM, réseaux anciens |
La règle pratique tient en deux phrases : ReLU dans les couches cachées — ou GELU dans un transformeur — et une activation dictée par le problème en sortie. Sigmoïde pour une probabilité binaire, softmax pour une classe parmi plusieurs, aucune activation pour une régression, ce qui est l’oubli le plus fréquent : mettre une sigmoïde en sortie d’un modèle qui doit prédire un prix borne les prédictions entre 0 et 1.
Ce qu’il faut ajouter pour montrer qu’on connaît le raisonnement historique : les activations saturantes comme la sigmoïde ont une dérivée quasi nulle sur presque tout leur domaine, ce qui étouffe le gradient à mesure qu’il remonte les couches. C’est ce qui rendait les réseaux profonds inentraînables avant que ReLU ne se généralise — et c’est la raison pour laquelle une question sur les activations est presque toujours une question déguisée sur la disparition du gradient.
C’est la règle de dérivation en chaîne appliquée de la sortie vers l’entrée, qui calcule le gradient de la perte pour tous les paramètres en un seul passage au lieu d’un par paramètre.
Lire la réponse détailléeLes trois se distinguent par le nombre d’exemples utilisés pour calculer chaque mise à jour.
| Exemples par mise à jour | Comportement | |
|---|---|---|
| Par lots | tout le jeu | direction exacte, très lent |
| Stochastique | un seul | très bruité, mises à jour fréquentes |
| Par mini-lots | 32 à 512 | le compromis, et le standard |
Par lots complets : le gradient est exact, donc la trajectoire est régulière. Inutilisable dès que le jeu ne tient pas en mémoire, et coûteux : un passage complet sur des millions d’exemples pour un seul pas.
Stochastique, un exemple à la fois : les mises à jour sont très nombreuses et très bruitées. Le bruit n’est pas seulement un défaut — il aide à s’échapper des minima locaux médiocres — mais il empêche la convergence fine, et il exploite très mal le parallélisme d’une carte graphique.
Par mini-lots : c’est ce que tout le monde fait, et ce que « SGD » désigne dans la pratique courante. Le gradient est une estimation raisonnable de la vraie direction, le bruit résiduel est bénéfique, et le lot remplit les unités de calcul de la carte graphique.
Ce qu’il faut ajouter pour montrer qu’on connaît le vrai critère : la taille du lot est d’abord une contrainte matérielle. On prend la plus grande puissance de deux qui tient en mémoire, puis on ajuste le taux d’apprentissage en conséquence — un lot plus grand donne un gradient moins bruité, donc autorise un pas plus grand. La règle empirique la plus citée est de multiplier le taux d’apprentissage par le même facteur que la taille du lot.
Et la précision de vocabulaire qui évite un malentendu : dans un article, « batch gradient descent » désigne le passage sur tout le jeu, alors que dans un cadre de programmation, batch désigne le mini-lot. C’est la source de confusion la plus commune sur ce sujet, et savoir la lever est un bon signe.
C’est l’hyperparamètre le plus important d’un entraînement, et il faut le dire d’emblée : mal réglé, aucun autre réglage ne rattrape le résultat.
Les deux symptômes à reconnaître :
Comment on le trouve. La méthode qui vaut mieux qu’une grille de recherche : le balayage de taux d’apprentissage. On lance quelques centaines d’itérations en augmentant le taux exponentiellement, on trace la perte en fonction du taux, et on retient une valeur légèrement inférieure à celle où la perte décroît le plus vite. Cela coûte quelques minutes et remplace une journée de tâtonnement.
Les ordres de grandeur à connaître, parce qu’on les demande : autour de 1e-3 pour Adam sur un réseau entraîné de zéro, 1e-4 ou 1e-5 pour l’affinage d’un modèle pré-entraîné — où un pas trop grand efface ce que le pré-entraînement avait appris — et 1e-2 à 1e-1 pour SGD avec inertie.
Le programme d’évolution compte autant que la valeur initiale. Un taux constant est presque toujours un mauvais choix : on veut de grands pas au début pour parcourir l’espace, et de petits pas à la fin pour s’installer dans le minimum.
La combinaison échauffement puis décroissance en cosinus est ce qu’on trouve dans la quasi-totalité des entraînements récents, et savoir la citer montre qu’on a lu du code réel.
Et la relation à ne pas oublier, parce qu’elle relie ce réglage aux autres : le taux d’apprentissage se règle avec la taille du lot. Doubler le lot réduit le bruit du gradient, ce qui autorise — et demande — un pas plus grand. Les deux ne se choisissent pas indépendamment.
En remontant les couches, les gradients se multiplient : une chaîne de facteurs inférieurs à 1 tend vers zéro, et les premières couches cessent d’apprendre. Les connexions résiduelles y répondent.
Lire la réponse détailléeTrois raisons, dont une décisive.
Elle ne rétrécit pas le gradient. Sa dérivée vaut exactement 1 pour toute entrée positive, alors que celle de la sigmoïde plafonne à 0,25 et devient quasi nulle dès que l’entrée s’éloigne de zéro. Sur dix couches de sigmoïdes, le gradient est multiplié par au mieux 0,25 dix fois : il ne reste rien pour les premières couches. C’est la raison principale, et celle qu’il faut donner en premier.
Elle est presque gratuite à calculer : un maximum entre zéro et l’entrée, contre une exponentielle pour la sigmoïde. À l’échelle de milliards d’opérations, cela compte.
Elle produit de la parcimonie. Environ la moitié des neurones sortent zéro à un instant donné, ce qui rend les représentations creuses — un effet régularisant, et des calculs plus légers.
Son défaut, qu’il faut nommer soi-même : le neurone mort. Si les poids d’un neurone le placent durablement en zone négative, sa sortie est zéro, donc sa dérivée est zéro, donc son gradient est nul : il ne se corrigera jamais. Un taux d’apprentissage trop élevé peut ainsi tuer une part notable du réseau, définitivement.
Les remèdes, à citer avec ce qu’ils changent :
Et la mise à jour à donner pour montrer qu’on suit l’état de l’art : ReLU n’est plus le défaut des architectures récentes. Les transformeurs utilisent GELU ou SwiGLU, dont le comportement lisse près de zéro se marie mieux avec la normalisation de couche et les grands entraînements. ReLU reste excellente, très répandue en vision, et c’est désormais un choix parmi d’autres plutôt que la réponse unique.
Un point de précision, enfin : la sigmoïde n’a pas disparu, elle a changé de place. Elle reste la bonne activation en sortie d’une classification binaire, où l’on veut précisément une valeur entre 0 et 1. Ce qu’on lui reproche concerne les couches cachées.
Parce qu’elle détermine si le signal et le gradient traversent le réseau à une échelle utilisable, ou s’ils s’éteignent et explosent avant d’arriver.
Les deux cas dégénérés à savoir expliquer :
Tous les poids à zéro — ou tous à la même valeur. Tous les neurones d’une couche calculent alors la même chose et reçoivent le même gradient : ils resteront identiques pour toujours. La couche entière se comporte comme un neurone unique. C’est le problème de symétrie, et c’est pour cela qu’il faut du hasard.
Des poids trop grands ou trop petits. Trop petits, la variance des activations diminue de couche en couche et le signal s’éteint. Trop grands, elle croît et le gradient explose. Dans les deux cas, l’entraînement échoue avant d’avoir commencé.
D’où l’idée directrice des méthodes modernes : choisir l’échelle initiale pour que la variance des activations soit préservée d’une couche à l’autre.
Les biais s’initialisent à zéro, ce qui ne pose aucun problème de symétrie puisque les poids sont déjà aléatoires.
Ce qu’il faut ajouter pour montrer qu’on situe la question dans le temps : l’initialisation était critique, elle l’est un peu moins aujourd’hui. La normalisation par lots et la normalisation de couche recentrent les activations à chaque étage, ce qui rend le réseau bien plus tolérant à une mauvaise échelle initiale. Elles n’ont pas supprimé le problème, elles l’ont amorti.
Et la remarque qui compte le plus en pratique : la meilleure initialisation est souvent un modèle pré-entraîné. Sur des images, du texte ou de l’audio, partir de poids appris sur un grand corpus vaut mieux que n’importe quel tirage aléatoire, et cette réponse-là est celle qui a le plus d’effet sur un projet réel.
À chaque passage avant de l’entraînement, on éteint aléatoirement une fraction des neurones d’une couche — 20 à 50 % typiquement. Ils sortent zéro et ne reçoivent pas de gradient. À chaque lot, ce sont d’autres neurones qui tombent.
Pourquoi cela régularise, et c’est l’explication attendue : le réseau ne peut plus dépendre d’un neurone en particulier, puisqu’il peut disparaître à tout moment. Il est donc contraint de répartir l’information sur des chemins redondants, ce qui l’empêche de bâtir des détecteurs très spécialisés qui mémorisent des exemples précis.
La seconde lecture, plus élégante : le dropout entraîne implicitement un ensemble exponentiel de sous-réseaux qui partagent leurs poids, et l’inférence en moyenne les prédictions. C’est une méthode d’ensemble déguisée, obtenue pour le prix d’un seul modèle.
Le point technique à ne pas manquer, parce que c’est là que la plupart des candidats trébuchent : le dropout est actif à l’entraînement, inactif à l’inférence. À l’inférence, tous les neurones sont présents, donc la somme des entrées d’une couche est plus grande d’un facteur 1/(1−p) qu’à l’entraînement. Il faut compenser cette différence d’échelle : les implémentations modernes le font pendant l’entraînement, en divisant les activations survivantes par (1−p) — c’est le inverted dropout. En pratique, cela se traduit par un appel à model.eval(), et l’oublier fait chuter les performances de manière déroutante.
Ce qu’il faut ajouter sur son usage actuel, pour montrer qu’on ne récite pas un cours de 2015 :
Les alternatives à citer pour compléter : décroissance des poids, arrêt anticipé, augmentation de données — et la plus efficace de toutes, plus de données.
Elle recentre et remet à l’échelle les activations d’une couche à partir des statistiques du lot, ce qui stabilise l’entraînement et autorise un taux d’apprentissage plus élevé.
Lire la réponse détailléeLa plus grande qui tient en mémoire, ajustée ensuite par ce qu’on observe. Mais la réponse complète tient dans le compromis, et c’est ce qu’on vérifie.
Un grand lot donne un gradient moins bruité, donc une trajectoire plus régulière, et il exploite bien mieux le parallélisme d’une carte graphique — c’est-à-dire plus d’exemples traités par seconde. Il consomme davantage de mémoire, et il produit moins de mises à jour par époque, ce qui peut ralentir la convergence en nombre d’époques.
Un petit lot donne un gradient bruité. Ce bruit n’est pas seulement un défaut : il agit comme une régularisation et aide à éviter les minima étroits, ceux qui généralisent mal. C’est le résultat souvent cité selon lequel les grands lots convergent vers des minima « pointus » et généralisent légèrement moins bien.
La règle qui relie les deux réglages, et qu’il faut absolument citer : la taille du lot et le taux d’apprentissage se règlent ensemble. Doubler le lot réduit le bruit du gradient, ce qui permet — et demande — un pas plus grand. La règle empirique est la mise à l’échelle linéaire : multiplier le taux d’apprentissage par le même facteur que le lot, accompagnée d’un échauffement sur les premières itérations.
Les ordres de grandeur usuels : 32 à 256 en vision, davantage sur les gros modèles de langage où les lots effectifs atteignent des millions de jetons grâce à l’accumulation et à la répartition sur plusieurs cartes.
Les deux techniques à connaître quand la mémoire manque :
Et la contrainte particulière à ne pas manquer : avec de la normalisation par lots, un lot trop petit est un vrai problème — les statistiques deviennent bruitées et la moyenne mobile peu fiable. En dessous de 8 ou 16 exemples, il faut passer à une normalisation de groupe ou de couche. C’est une interaction que peu de candidats mentionnent, et elle explique de vraies dégradations en pratique.
Adam converge plus vite et se règle plus facilement, SGD avec inertie généralise parfois un peu mieux en vision. Adam — ou plutôt AdamW — est le bon défaut.
Lire la réponse détailléeDans l’ordre d’efficacité réelle, ce qui n’est pas l’ordre dans lequel on les cite d’habitude :
1. Plus de données. Le seul remède sans contrepartie. Et quand en obtenir de nouvelles est impossible, l’augmentation de données en produit à partir de l’existant — recadrages, symétries, variations de couleur en vision ; masquage ou substitution en texte.
2. Un modèle pré-entraîné. Sur des images ou du texte, partir de poids appris sur un grand corpus est de très loin la meilleure défense contre le surapprentissage d’un petit jeu de données. Un affinage sur mille exemples généralise mieux qu’un réseau entraîné de zéro sur cinquante mille.
3. L’arrêt anticipé. On surveille la perte de validation et on garde les poids de son minimum. Gratuit, systématique, et il donne en prime le bon nombre d’époques sans avoir à le chercher.
4. La décroissance des poids — la régularisation L2 de l’optimiseur, weight_decay. À activer par défaut, avec AdamW pour qu’elle se comporte comme prévu.
5. Le dropout, sur les couches denses et dans les transformeurs. Moins utile entre couches convolutives, où la normalisation par lots régularise déjà.
6. Réduire la capacité. Moins de couches, moins d’unités. C’est le levier le plus évident et souvent le moins efficace : un grand réseau bien régularisé bat généralement un petit réseau nu.
7. Le lissage des étiquettes, qui empêche le modèle de viser une confiance de 100 % et améliore la calibration en classification.
Ce qu’il faut ajouter pour montrer qu’on ne récite pas une liste : il faut d’abord vérifier que c’est bien du surapprentissage. Un grand écart entre entraînement et validation peut aussi venir d’un découpage mal fait — mêmes individus des deux côtés, périodes différentes, fuite de données. Régulariser un problème de découpage ne le corrigera jamais.
Et la contre-indication qui mérite d’être mentionnée : sur les très grands réseaux, l’intuition classique ne s’applique plus tout à fait. Au-delà du point d’interpolation, l’erreur de test peut redescendre — c’est la double descente — et la bonne stratégie est souvent un modèle plus grand avec plus de données et une régularisation modérée, plutôt qu’un modèle plus petit.
Trois unités différentes, souvent confondues, et l’intervieweur vérifie surtout qu’on ne les mélange pas.
La relation, qu’il faut pouvoir donner de tête :
iterations par epoque = nombre d'exemples / taille du lotDix mille exemples avec des lots de cent font cent itérations par époque. Cinquante époques font donc cinq mille mises à jour.
Ce qu’il faut ajouter, parce que c’est là que la question devient intéressante : le nombre d’époques n’est pas la bonne unité pour raisonner. Ce qui compte pour l’optimisation, c’est le nombre de mises à jour. Passer d’un lot de 32 à un lot de 256 divise par huit le nombre de mises à jour pour le même nombre d’époques — donc à réglage inchangé, l’entraînement converge moins loin, et c’est ce qui fait croire à tort que les grands lots dégradent les résultats.
Deux précisions utiles :
Et l’élément qui va avec, si l’on veut être complet : le mélange des données à chaque époque. Sans lui, les lots sont toujours composés des mêmes exemples dans le même ordre, ce qui introduit un biais dans les mises à jour — et devient franchement néfaste si le fichier d’origine est trié par classe.
Par la nature de la sortie d’abord, par le coût des erreurs ensuite.
| Problème | Perte | Sortie du réseau |
|---|---|---|
| Régression | erreur quadratique | aucune activation |
| Régression bruitée | Huber, erreur absolue | aucune activation |
| Classification binaire | entropie croisée binaire | sigmoïde |
| Multiclasse exclusive | entropie croisée | softmax |
| Multi-étiquettes | entropie croisée binaire par classe | sigmoïde par classe |
| Ordonnancement, similarité | triplet, contrastive | plongement |
Deux distinctions qui montrent qu’on a pratiqué :
Multiclasse et multi-étiquettes ne se traitent pas pareil. Une image contient un chat ou un chien : softmax et entropie croisée, les probabilités somment à 1. Une image contient un chat et un canapé : une sigmoïde par classe et une entropie croisée binaire, chaque classe étant décidée indépendamment. Utiliser softmax pour un problème multi-étiquettes force les classes à se concurrencer, ce qui est faux.
Huber contre erreur quadratique. L’erreur quadratique punit les grands écarts au carré, ce qui la rend très sensible aux valeurs aberrantes : quelques exemples extrêmes peuvent dominer l’entraînement. Huber est quadratique près de zéro et linéaire au-delà, donc robuste tout en restant dérivable. Sur des données réelles à valeurs extrêmes, c’est souvent le bon choix.
Les ajustements liés au métier, à mentionner parce qu’ils sortent du catalogue :
Et le détail d’implémentation qui compte vraiment : il faut donner les logits à la perte, pas les probabilités. Les implémentations combinent softmax et entropie croisée en une seule opération numériquement stable ; appliquer un softmax soi-même avant la perte revient à l’appliquer deux fois, ce qui dégrade l’entraînement sans lever d’erreur. En PyTorch, CrossEntropyLoss attend les logits — c’est l’une des erreurs les plus fréquentes chez les débutants, et savoir la citer est un bon signal.
Parce que leur combinaison produit un gradient d’une simplicité remarquable, et parce que chacune répond à ce que l’autre exige.
Softmax transforme des scores quelconques — les logits — en probabilités : elle exponentie chaque score puis divise par la somme, ce qui garantit des valeurs positives sommant à 1.
L’entropie croisée mesure l’écart entre la distribution prédite et la distribution réelle. Pour une étiquette unique, elle se réduit au logarithme négatif de la probabilité attribuée à la bonne classe : si le modèle donne 0,9 à la bonne classe, la perte est faible ; s’il donne 0,01, elle est très élevée.
Le résultat qui justifie leur mariage, et qu’il faut savoir citer : le gradient de l’entropie croisée par rapport aux logits vaut simplement la probabilité prédite moins la cible. Une soustraction. Pas d’exponentielle résiduelle, pas de terme qui sature — le gradient est proportionnel à l’erreur commise, ce qui est exactement le comportement souhaité.
C’est ce qui explique le choix par comparaison avec l’erreur quadratique : associée à une sigmoïde, l’erreur quadratique fait apparaître la dérivée de la sigmoïde dans le gradient. Or cette dérivée est quasi nulle quand le modèle est très confiant — y compris quand il a très confiamment tort. Le gradient s’évanouit là où il devrait être maximal, et l’apprentissage se bloque. L’entropie croisée n’a pas ce défaut.
Deux points techniques qui font bonne impression :
La stabilité numérique. Exponentier un logit de 100 déborde en virgule flottante. Les implémentations soustraient donc le maximum des logits avant l’exponentielle — ce qui ne change pas le résultat — et fusionnent softmax et logarithme en une seule opération. D’où la règle : on passe les logits à la fonction de perte, jamais des probabilités déjà calculées.
La température. Diviser les logits par une valeur avant le softmax règle la netteté de la distribution : une température basse concentre la masse sur la classe dominante, une température haute l’aplatit. C’est le paramètre qu’on retrouve dans la génération de texte et dans la distillation de modèles, et faire ce lien montre qu’on comprend l’objet au-delà de la classification.
Un petit filtre glisse sur l’image et calcule une réponse locale à chaque position. Les poids sont partagés, ce qui divise leur nombre par des milliers et rend la détection indépendante du lieu.
Lire la réponse détailléeÀ réduire la résolution spatiale. Un max pooling 2 × 2 ne garde que la valeur maximale de chaque carré de quatre pixels, divisant la hauteur et la largeur par deux — donc le nombre d’activations par quatre.
Ce que cela apporte :
Les variantes utiles :
Ce qu’il faut ajouter pour montrer qu’on connaît le débat actuel : le pooling n’est plus indispensable. Une convolution avec un pas de 2 réduit aussi la résolution, tout en apprenant comment le faire au lieu d’appliquer un maximum fixe. Beaucoup d’architectures récentes s’en passent entièrement.
Et la nuance importante sur l’invariance, souvent mal comprise : le pooling n’apporte qu’une invariance très locale, de l’ordre du pixel. Un réseau convolutif n’est pas invariant à une translation importante, ni à une rotation, ni à un changement d’échelle — c’est l’augmentation de données qui procure cette robustesse, pas l’architecture. Confondre les deux est une erreur fréquente.
Enfin, le cas où il faut s’en méfier : en segmentation ou en détection, la position précise compte, et chaque réduction détruit de l’information spatiale. C’est pourquoi ces architectures utilisent des connexions de saut pour rapatrier les cartes haute résolution, comme dans U-Net.
Parce qu’un RNN simple ne retient rien au-delà d’une dizaine de pas de temps, et la raison est la disparition du gradient dans sa forme la plus aiguë.
Un RNN applique la même matrice de poids à chaque pas. Rétropropager sur cent pas revient donc à multiplier cent fois par des facteurs du même ordre : s’ils sont inférieurs à 1, le gradient s’annule ; supérieurs à 1, il explose. La dépendance longue est inapprenable — le réseau ne peut pas relier un mot de la fin de la phrase à un mot du début.
Ce que les LSTM changent. Ils introduisent une cellule d’état qui traverse les pas de temps en étant modifiée par addition plutôt que par multiplication répétée. Le gradient dispose ainsi d’un chemin où il ne se contracte pas — c’est exactement l’idée des connexions résiduelles, appliquée au temps.
Trois portes, apprises, contrôlent ce flux :
Le GRU fait la même chose avec deux portes et sans cellule séparée : moins de paramètres, entraînement plus rapide, résultats comparables dans la plupart des cas. Le choix entre les deux se fait par expérimentation, pas par principe.
Ce qu’il faut ajouter pour ne pas répondre à une question de 2016 : les LSTM ont eux-mêmes été supplantés par les transformeurs, et pour une raison qui n’est pas la qualité mais la parallélisation. Un LSTM traite les pas de temps en séquence : le pas t attend le pas t−1, donc l’entraînement ne se parallélise pas sur la longueur de la séquence. L’attention regarde toutes les positions en une seule opération matricielle, ce qui exploite pleinement une carte graphique — et c’est ce qui a permis de passer à des corpus de milliers de milliards de jetons.
Les LSTM conservent malgré tout des usages réels, et c’est bon à savoir dire : sur des séquences longues où la mémoire est contrainte, en traitement de flux à faible latence — où l’état se met à jour d’un pas à la fois, sans recalculer l’attention sur tout le contexte — et sur les petits jeux de données, où un LSTM se contente de bien moins d’exemples qu’un transformeur.
Chaque position construit sa représentation en pondérant toutes les autres selon leur pertinence, avec des poids calculés à la volée. Le chemin entre deux positions devient de longueur 1.
Lire la réponse détailléeLa réponse principale n’est pas la qualité des prédictions, c’est la parallélisation — et c’est ce qui distingue une bonne réponse d’une réponse convenue.
Un réseau récurrent traite la séquence pas à pas : la représentation à la position t dépend de celle à t−1. L’entraînement ne peut donc pas être parallélisé sur la longueur de la séquence, ce qui laisse une carte graphique largement inoccupée. Un transformeur calcule toutes les positions en une seule multiplication matricielle. À matériel égal, il traite un ordre de grandeur plus de données dans le même temps — et c’est cette efficacité qui a rendu possible l’entraînement sur des corpus de milliers de milliards de jetons.
Les autres avantages, réels mais secondaires :
Ce qu’il faut savoir donner en contrepartie, parce que la question invite à la nuance :
Et la mise en perspective qui fait bonne impression : le débat n’est pas clos. Les architectures à espace d’états — Mamba et ses dérivés — proposent un coût linéaire en longueur de séquence tout en restant parallélisables à l’entraînement. Elles réhabilitent l’idée récurrente sous une forme qui n’a pas le défaut d’origine, et c’est aujourd’hui la piste la plus sérieuse pour les contextes très longs.
Réutiliser un modèle entraîné sur une grande tâche générale pour résoudre une tâche particulière avec peu de données. On ne repart pas de poids aléatoires, on repart de ce qui a déjà été appris.
Pourquoi cela fonctionne : les premières couches d’un réseau apprennent des représentations génériques — contours, textures, structures syntaxiques — qui ne dépendent pas de la tâche finale. Seules les dernières couches sont spécialisées. Il n’y a donc aucune raison de réapprendre les premières.
Les trois façons de procéder, du plus léger au plus lourd :
L’extraction de caractéristiques. On gèle tout le réseau et on ne l’utilise que pour produire des vecteurs, sur lesquels on entraîne un modèle simple — régression logistique, gradient boosting. C’est très rapide, cela demande très peu d’exemples, et cela suffit souvent.
L’affinage partiel. On gèle les premières couches, on réentraîne les dernières avec un taux d’apprentissage faible. Le compromis habituel.
L’affinage complet. Tout le réseau est réentraîné avec un taux très faible. À réserver aux cas où l’on dispose de données en quantité et où le domaine cible s’éloigne du domaine d’origine.
Les deux règles pratiques qui font la différence :
Ce qu’il faut ajouter sur les limites : le transfert fonctionne d’autant mieux que les domaines sont proches. D’ImageNet vers des photographies de produits, il est spectaculaire ; vers de l’imagerie médicale ou des images satellites, le gain se réduit et il faut affiner plus profondément. Et sur des données tabulaires, il n’y a rien à transférer — chaque jeu a ses propres colonnes — ce qui explique que le domaine reste dominé par les arbres boostés.
Et la version moderne du sujet, à mentionner parce qu’elle est devenue la norme : sur les grands modèles, on n’affine plus tous les poids. Les méthodes à faible rang comme LoRA n’entraînent qu’un petit nombre de paramètres additionnels et laissent le modèle d’origine intact — même bénéfice, pour une fraction de la mémoire et un modèle de base partagé entre plusieurs tâches.
Cela dépend de deux facteurs, et il faut les nommer avant de répondre : la quantité de données disponibles et la distance entre le domaine d’origine et le domaine cible.
| Données | Domaine proche | Domaine éloigné |
|---|---|---|
| Peu | geler presque tout, réentraîner la tête | geler le début, affiner les couches hautes |
| Beaucoup | affiner tout, taux faible | affiner tout, voire réentraîner de zéro |
Le raisonnement qui sous-tend le tableau : les premières couches codent des motifs génériques réutilisables, les dernières sont spécialisées. Plus le domaine cible est éloigné, plus il faut remonter haut dans le gel. Et moins on a de données, plus geler protège du surapprentissage — chaque paramètre libéré est un paramètre à contraindre avec les exemples dont on ne dispose pas.
La stratégie la plus efficace en pratique, et celle qui vaut d’être citée : le dégel progressif. On commence par entraîner la tête seule, puis on libère les couches par blocs en partant du haut, avec un taux d’apprentissage plus faible pour les couches basses que pour les hautes. Ce sont les taux différenciés par couche, et c’est ce que font les bonnes recettes d’affinage.
Trois points techniques qui distinguent une réponse solide :
Les couches de normalisation par lots demandent une décision explicite. Même gelées au sens des poids, elles continuent de mettre à jour leurs statistiques mobiles si le module est en mode entraînement — ce qui altère un modèle qu’on croyait figé. Sur un petit jeu de données, il est généralement préférable de les laisser en mode évaluation, statistiques comprises. C’est une subtilité qui explique de vrais écarts de résultats et que peu de candidats connaissent.
La tête doit être remplacée, pas seulement réentraînée : le nombre de classes diffère, donc la dernière couche est nouvelle et part de poids aléatoires.
Il faut échauffer la tête avant de libérer le reste. Une tête aléatoire produit de gros gradients qui, propagés dans un corps pré-entraîné, en détruisent les poids dès les premières itérations.
Et le cadrage actuel du sujet, sur les grands modèles : la question du gel se pose autrement, puisqu’on gèle la totalité du modèle et qu’on entraîne des adaptateurs — LoRA — insérés dans les couches d’attention. Le débat porte alors sur le rang de ces adaptateurs et sur les modules à équiper, plus sur le nombre de couches à dégeler.
À créer de nouveaux exemples d’entraînement en transformant ceux qu’on possède, de façon que l’étiquette reste valable. Un chat retourné horizontalement est toujours un chat ; le réseau voit un exemple de plus.
C’est la forme de régularisation la plus efficace, parce qu’elle ne contraint pas le modèle : elle enseigne une invariance. On apprend au réseau que la classe ne dépend pas de l’orientation, du cadrage ou de la luminosité — trois choses qu’il ne devinerait pas d’un petit jeu de données.
Les transformations, par domaine :
Le principe qui décide de tout, et qu’il faut énoncer : l’augmentation doit préserver l’étiquette et refléter les variations attendues en production. Retourner horizontalement une photo d’animal est légitime ; retourner un chiffre manuscrit transforme un 2 en quelque chose qui n’existe pas. Retourner verticalement une radiographie thoracique produit une image anatomiquement impossible, dont le réseau apprendra une invariance nuisible.
Deux points techniques à ne pas manquer :
Et la version moderne, à citer pour montrer qu’on suit : les politiques apprises ou aléatoires comme RandAugment ou TrivialAugment remplacent le réglage manuel des transformations, et donnent d’aussi bons résultats sans qu’on ait à choisir les paramètres.
On vérifie d’abord que le réseau peut surapprendre une dizaine d’exemples. S’il n’y arrive pas, le défaut est dans le code ou les données, pas dans les hyperparamètres.
Lire la réponse détailléeUn NaN se propage et ne disparaît jamais : dès qu’un poids en contient un, tout le réseau est perdu. Il faut donc trouver l’opération qui l’a produit, et il y a peu de suspects.
Les causes, dans l’ordre où on les vérifie :
Un taux d’apprentissage trop grand. La cause la plus fréquente de loin. Les poids divergent, les activations explosent, et le dépassement de capacité arrive en quelques itérations. Le symptôme caractéristique : la perte grandit d’un facteur énorme sur deux ou trois pas avant de devenir NaN. On divise le taux par dix et on regarde.
L’explosion du gradient, typiquement dans un réseau récurrent ou très profond. Le remède est l’écrêtage de la norme du gradient, standard dans l’entraînement des modèles de langage.
Un logarithme de zéro, ou une division par zéro. Cela arrive quand on calcule soi-même une entropie croisée à partir de probabilités, dont l’une vaut exactement 0. La réponse est de passer les logits à la fonction de perte fournie par la bibliothèque, qui est numériquement stable. Même chose pour une racine carrée ou une normalisation sans terme epsilon au dénominateur.
Des NaN déjà présents dans les données. Une colonne avec des valeurs manquantes non traitées, une division par zéro dans la préparation des variables, un fichier tronqué. Il suffit d’un seul exemple pour empoisonner tout l’entraînement, et le symptôme apparaît alors à une itération apparemment aléatoire — celle où le lot contenant l’exemple fautif passe.
La précision réduite. En float16, la plage représentable est étroite et les dépassements sont faciles. C’est exactement le problème que résout la mise à l’échelle de la perte (loss scaling) de l’entraînement en précision mixte : on multiplie la perte avant le passage arrière pour maintenir les petits gradients dans la plage représentable. Utiliser bfloat16, dont la plage est celle du float32, évite l’essentiel de ces incidents.
La méthode qui répond vraiment à la question :
Et le réflexe préventif qui coûte peu : un échauffement du taux d’apprentissage sur les premières centaines d’itérations. La plupart des divergences se produisent au tout début de l’entraînement, sur des poids encore aléatoires.
D’abord savoir ce qui occupe la mémoire, parce que les leviers ne sont pas les mêmes selon le poste :
Sur un entraînement, les activations dominent souvent ; sur un grand modèle, les états d’optimiseur. Cette distinction est ce qu’on attend, parce qu’elle oriente la suite.
Les leviers, du moins coûteux au plus lourd :
Réduire la taille du lot, puis compenser par une accumulation de gradients pour retrouver le même lot effectif. On échange du temps contre de la mémoire, sans changer le résultat.
Passer en précision mixte. Les activations en float16 ou bfloat16 divisent leur empreinte par deux, et les cartes récentes calculent plus vite dans ces formats. C’est le meilleur rapport gain/effort, et bfloat16 évite les problèmes de plage du float16.
Le recalcul d’activations (gradient checkpointing). On ne conserve que quelques activations et on recalcule les autres au passage arrière : la mémoire baisse fortement, le temps augmente d’environ 30 %.
Changer d’optimiseur ou alléger ses états — 8-bit Adam, Adafactor — ce qui économise plusieurs fois la taille du modèle.
Répartir sur plusieurs cartes : partitionner les états d’optimiseur, les gradients puis les poids, ce que font ZeRO et FSDP. C’est la réponse quand le modèle ne tient pas, pas quand le lot ne tient pas.
Réduire l’entrée : résolution d’image, longueur de séquence. Le coût de l’attention étant quadratique en longueur, tronquer le contexte est très efficace.
Les erreurs qui provoquent une saturation sans qu’il n’y ait de vrai problème de taille, et qu’il faut savoir citer :
Et le point de méthode : mesurer avant d’agir. Les outils du cadre de travail indiquent la mémoire allouée par poste, et une saturation qui survient à l’évaluation plutôt qu’à l’entraînement désigne immédiatement une cause différente.
La seule réponse honnête est « cela dépend », mais l’intervieweur attend qu’on sache de quoi cela dépend, et qu’on donne une méthode plutôt qu’un chiffre.
Les facteurs :
La méthode qui remplace le chiffre, et qui est la vraie réponse : tracer une courbe d’apprentissage. On entraîne sur 10, 25, 50 puis 100 % des données disponibles et on regarde la validation.
Cette courbe transforme une question d’opinion en une décision chiffrée, et elle permet d’estimer le retour d’un budget d’étiquetage avant de le dépenser.
Les ordres de grandeur, puisqu’on les demande souvent : quelques centaines d’exemples par classe pour un affinage en vision, quelques milliers pour un entraînement de zéro sur une tâche simple, des dizaines de milliers pour une architecture profonde sans pré-entraînement. En traitement du langage, l’affinage d’un modèle pré-entraîné fonctionne à partir de quelques centaines d’exemples, et l’apprentissage en contexte d’un grand modèle fonctionne avec quelques exemples dans l’invite — ce qui déplace complètement la question.
Et la remarque qui distingue une réponse expérimentée : quand les données manquent, la bonne stratégie n’est pas d’en collecter davantage au hasard. C’est de collecter les bons exemples — ceux que le modèle rate — par apprentissage actif, et de corriger les étiquettes douteuses du jeu existant. Sur un petit corpus, la revue des cent erreurs les plus confiantes du modèle rapporte plus que mille nouveaux exemples.
La réponse tient à la nature des données, et elle est plus tranchée que la plupart des candidats ne le croient.
Gradient boosting sur données tabulaires : colonnes hétérogènes, quelques dizaines de milliers de lignes, pas de structure spatiale ou séquentielle. C’est le choix par défaut, et il est difficile à battre. Les coupures s’accommodent des unités différentes, les interactions sont apprises sans être déclarées, l’absence de valeurs est gérée nativement, et rien ne demande de normalisation.
Réseau de neurones dès que la structure des données porte l’information : images, texte, audio, séries temporelles longues, graphes. La disposition spatiale, l’ordre des mots ou la topologie sont exactement ce que les convolutions et l’attention exploitent — un arbre voit un pixel comme une colonne indépendante de ses voisines.
Les autres critères qui tranchent en pratique :
Ce qu’il faut savoir dire sur l’état de la littérature, parce que cela ancre la réponse : plusieurs études comparatives publiées depuis 2021 concluent que sur données tabulaires, les arbres boostés restent devant les architectures profondes conçues pour ce cas — y compris les transformeurs tabulaires — et que l’écart de coût d’ingénierie est plus grand encore que l’écart de performance.
Et la réponse qui vaut mieux qu’un choix, parce que c’est celle des systèmes réels : les combiner. On encode le texte, l’image ou la séquence avec un modèle profond, puis on donne ces représentations comme variables à un gradient boosting, avec les colonnes du tableau. Chaque famille traite ce qu’elle traite mieux que l’autre.
Un modèle entraîné n’est pas un service. Il faut traiter le format, la latence, le coût et la surveillance, et la réponse doit couvrir les quatre.
Figer le modèle dans un format d’inférence. On exporte vers ONNX, TorchScript ou TensorRT plutôt que de servir le code d’entraînement : le graphe est optimisé, les dépendances réduites, et le service ne dépend plus de la bibliothèque qui a servi à entraîner. C’est aussi ce qui permet d’exécuter sur un autre matériel que celui de l’entraînement.
Réduire le coût de l’inférence. Trois leviers, à citer avec leur contrepartie :
Regrouper les requêtes. Une carte graphique est très inefficace sur une requête isolée. Un regroupement dynamique — attendre quelques millisecondes pour constituer un lot — multiplie le débit pour un coût de latence maîtrisé. C’est le réglage le plus rentable d’un service d’inférence, et il oppose directement débit et latence : il faut savoir dire lequel on optimise.
Reproduire exactement le prétraitement. Même normalisation, même redimensionnement, même tokeniseur qu’à l’entraînement. Un écart ici produit une dégradation silencieuse — le fameux décalage entre entraînement et service — et le remède est de livrer le prétraitement avec le modèle, dans le même artefact, plutôt que de le réimplémenter côté service.
Versionner ensemble le code, les poids et le prétraitement, et pouvoir revenir en arrière en une commande.
Surveiller ce qui est observable. Sans étiquettes immédiates, on suit la distribution des entrées, celle des prédictions, la latence par centile, le taux d’erreurs, et la part de requêtes dont la confiance est basse. Et on consigne les entrées et les sorties avec la version du modèle : sans cette trace, aucun diagnostic n’est possible plus tard.
Déployer prudemment : d’abord en observation, le modèle prédisant sans décider, puis sur une fraction du trafic avec mesure, puis complètement.
Et le choix qu’il faut savoir poser, parce qu’il détermine l’architecture : inférence en temps réel ou par lots ? Beaucoup de cas d’usage réputés temps réel se satisfont d’un calcul nocturne stocké en base, ce qui divise le coût par un facteur important et supprime la moitié des problèmes de latence. Poser cette question avant de construire un service en ligne est un réflexe d’ingénieur.