Module 08 · Leçon 6

Le surapprentissage et comment le combattre

Un réseau qui a tout juste sur le jeu d'entraînement mais ne progresse pas sur des données jamais vues souffre de surapprentissage. Provoquer volontairement un surapprentissage, puis essayer la décroissance des poids, le dropout, l'arrêt précoce et l'ajout de données, pour voir sur de vrais résultats lequel est le plus efficace.

  • Environ 40 minutes
  • Niveau : Intermédiaire
  • Testé : 2026-09-14 torch 2.14, scikit-learn 1.9, CPU, graine aléatoire fixée

Le code et les sorties des programmes sont reproduits tels qu’ils ont tourné : commentaires et sorties sont donc en chinois.

Le réseau de la leçon précédente atteignait 100 % sur le jeu d'entraînement et 97,8 % sur le jeu de test. Cet écart de 2,2 points, c'est la part que le réseau a « apprise par cœur » sans vraiment la comprendre.

Tant que l'écart est petit, peu importe. Mais si les données d'entraînement sont rares et le modèle grand, le réseau apprend par cœur tout le jeu d'entraînement : tout juste sur l'entraînement, et il montre son vrai visage dès qu'on change de données. C'est le surapprentissage (overfitting). Cette leçon provoque volontairement un surapprentissage, puis essaie quelques remèdes courants.

python overfitting.py

Trois jeux de données

Cette leçon divise les données en trois :

X_pool, X_rest, y_pool, y_rest = train_test_split(X, y, test_size=0.5, random_state=0)
X_val, X_test, y_val, y_test = train_test_split(X_rest, y_rest, test_size=0.5, random_state=0)
X_small, y_small = X_pool[:100], y_pool[:100]  # 故意只用 100 张
可用于训练的图 898 张(先只用其中 100 张),验证集 449 张,测试集 450 张
模型共 301066 个参数
  • Le jeu d'entraînement : sert à mettre à jour les paramètres.
  • Le jeu de validation : sert pendant l'entraînement à observer et à ajuster les réglages (quel taux d'apprentissage, quand s'arrêter), mais pas à mettre à jour les paramètres.
  • Le jeu de test : consulté une seule fois à la fin, une fois tous les réglages fixés, comme résultat final.

Pourquoi un jeu de validation en plus ? Parce qu'à chaque fois que vous regardez le score sur le jeu de test puis ajustez vos réglages en conséquence, un peu de l'information du jeu de test s'infiltre dans vos décisions. Après des dizaines d'ajustements, les réglages retenus conviennent peut-être seulement par hasard à ce jeu de test. On règle donc avec le jeu de validation, et on garde le jeu de test pour la fin.

Le modèle est volontairement grand : deux couches cachées de 512 neurones, 300 000 paramètres, pour seulement 100 images. Trois mille paramètres par image : les apprendre par cœur est un jeu d'enfant.

À quoi ressemble le surapprentissage

== 什么都不加
  第   1 轮  训练损失 2.2147 准确率 26.0%  |  验证损失 2.2507 准确率 16.5%
  第  10 轮  训练损失 1.3077 准确率 79.0%  |  验证损失 1.5603 准确率 62.6%
  第  25 轮  训练损失 0.1552 准确率 98.0%  |  验证损失 0.4420 准确率 87.3%
  第  50 轮  训练损失 0.0058 准确率 100.0%  |  验证损失 0.3772 准确率 88.4%
  第 100 轮  训练损失 0.0013 准确率 100.0%  |  验证损失 0.4038 准确率 89.8%
  第 200 轮  训练损失 0.0004 准确率 100.0%  |  验证损失 0.4371 准确率 90.0%
  第 300 轮  训练损失 0.0002 准确率 100.0%  |  验证损失 0.4667 准确率 89.8%
  最终:测试集准确率 88.7%,测试损失 0.5089

(La perte de la première passe, 2,21, est proche des 2,30 de la leçon précédente : au départ, le réseau ne sait rien.)

À la passe 50, le jeu d'entraînement est déjà juste à 100 %, perte d'entraînement 0,006, et elle continue de descendre jusqu'à 0,0002. Mais la précision sur le jeu de validation stagne autour de 90 %, et la perte de validation remonte à partir de 0,377 à la passe 50, jusqu'à 0,467 à la passe 300.

Les deux courbes se séparent : la perte d'entraînement baisse encore, la perte de validation monte. C'est le signe du surapprentissage. La perte de validation monte parce que le réseau devient de plus en plus « sûr de lui » sur le jeu d'entraînement, et se trompe aussi avec assurance sur les images jamais vues ; l'entropie croisée sanctionne lourdement ce genre d'erreur.

En graphique, cela ressemble à peu près à ceci :

损失
 │ \
 │  \  验证损失
 │   \____/ ̄ ̄ ̄ ̄
 │    \
 │     \_  训练损失
 │         ̄ ̄______
 └──────────────────────── 轮
          ↑
    验证损失最低的地方

Quelques remèdes

Voici plusieurs remèdes courants contre le surapprentissage. Chacun ne modifie qu'une chose, tout le reste étant identique (même graine aléatoire, mêmes 100 images).

La décroissance des poids (weight decay) : à chaque mise à jour, on tire tous les poids un peu vers 0. L'idée : un modèle aux paramètres petits est plus « simple », et réagit moins exagérément à des exemples isolés. Le paramètre weight_decay de l'optimiseur AdamW règle la force de cette traction :

optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=weight_decay)

Le dropout : pendant l'entraînement, à chaque étape, une partie des neurones « se repose » au hasard (sa sortie est mise à 0). Ici réglé à 0,5 : à chaque étape, la moitié des neurones cachés ne travaille pas. Le réseau ne peut plus compter sur quelques neurones précis pour mémoriser une image, et doit apprendre des régularités plus robustes. Pour l'évaluation, on désactive le dropout avec model.eval(), et on le réactive pour l'entraînement avec model.train() :

nn.Linear(64, 512), nn.ReLU(), nn.Dropout(dropout),

L'arrêt précoce (early stopping) : à chaque passe, on regarde la perte de validation et on mémorise les paramètres du moment où elle est minimale. Si la perte de validation n'atteint pas de nouveau minimum pendant 20 passes, on s'arrête et on revient à ce moment-là :

if val_loss < best_val:
    best_val, best_epoch, patience = val_loss, epoch, 0
    best_state = {k: v.clone() for k, v in model.state_dict().items()}
else:
    patience += 1
if early_stop and patience >= 20:  # 验证损失连续 20 轮没有创新低,就停下来
    break

Et le remède le plus simple : plus de données. On utilise les 898 images disponibles pour l'entraînement.

Résultats : une conclusion inattendue

== 权重衰减 weight_decay=0.1
  第  50 轮  训练损失 0.0059 准确率 100.0%  |  验证损失 0.3762 准确率 88.4%
  第 300 轮  训练损失 0.0002 准确率 100.0%  |  验证损失 0.4543 准确率 89.8%
  最终:测试集准确率 88.0%,测试损失 0.5008

== 权重衰减 weight_decay=1.0
  第  50 轮  训练损失 0.0079 准确率 100.0%  |  验证损失 0.3674 准确率 89.1%
  第 300 轮  训练损失 0.0012 准确率 100.0%  |  验证损失 0.4243 准确率 89.3%
  最终:测试集准确率 88.0%,测试损失 0.4574

== dropout 0.5
  第  50 轮  训练损失 0.0561 准确率 100.0%  |  验证损失 0.3784 准确率 88.4%
  第 300 轮  训练损失 0.0003 准确率 100.0%  |  验证损失 0.3879 准确率 90.2%
  最终:测试集准确率 88.2%,测试损失 0.4321

== 早停
  第 55 轮停止:验证损失从第 35 轮之后就没再下降
  最终:测试集准确率 87.3%,测试损失 0.4053

== 什么都不加,但用 898 张图训练
  第   1 轮  训练损失 2.2261 准确率 34.6%  |  验证损失 2.2390 准确率 27.4%
  第  10 轮  训练损失 1.3170 准确率 88.1%  |  验证损失 1.3714 准确率 84.4%
  第  25 轮  训练损失 0.2208 准确率 94.4%  |  验证损失 0.2675 准确率 91.1%
  第  50 轮  训练损失 0.0437 准确率 99.3%  |  验证损失 0.1072 准确率 96.9%
  第 100 轮  训练损失 0.0074 准确率 100.0%  |  验证损失 0.0854 准确率 97.1%
  第 200 轮  训练损失 0.0016 准确率 100.0%  |  验证损失 0.0850 准确率 97.1%
  第 300 轮  训练损失 0.0007 准确率 100.0%  |  验证损失 0.0875 准确率 97.3%
  最终:测试集准确率 96.2%,测试损失 0.1682

测试集汇总:
  什么都不加            准确率 88.7%  损失 0.5089
  权重衰减 0.1         准确率 88.0%  损失 0.5008
  权重衰减 1.0         准确率 88.0%  损失 0.4574
  dropout 0.5      准确率 88.2%  损失 0.4321
  早停               准确率 87.3%  损失 0.4053
  898 张训练数据        准确率 96.2%  损失 0.1682

Ces résultats diffèrent de ce que disent beaucoup de tutoriels, et méritent un examen attentif.

Décroissance des poids, dropout et arrêt précoce n'ont pas amélioré la précision. La précision sur le jeu de test est partout entre 87 % et 89 %, à peu près les 88,7 % sans aucun ajout ; l'arrêt précoce fait même un peu moins bien. Sur 450 images de test, 1 point ne représente que quatre ou cinq images ; un tel écart ne dit pas qui est meilleur.

Ils ont fait baisser la perte de test. De 0,51 à entre 0,40 et 0,50, surtout avec l'arrêt précoce. Autrement dit, le réseau répond juste aux mêmes questions, mais il ne « se trompe plus avec autant d'assurance », et ses probabilités sont plus fiables. Dans certains cas, c'est important, par exemple si l'on décide selon la probabilité de faire vérifier un résultat par un humain.

Plus de données dépasse de loin tous les autres remèdes. Même modèle, sans aucun ajout, données d'entraînement passées de 100 à 898 images : la précision de test bondit de 88,7 % à 96,2 %, la perte de test tombe de 0,51 à 0,17. La perte de validation ne remonte plus nettement non plus, et se stabilise autour de 0,085.

Comment le comprendre

Ces méthodes de régularisation (décroissance des poids, dropout et arrêt précoce sont regroupés sous ce nom) ne sont pas inutiles, mais elles ont leur domaine d'application. Elles atténuent le surapprentissage, mais ne peuvent pas créer une information absente des données. Avec 100 images, soit en moyenne 10 par chiffre, on est loin d'avoir vu toutes les façons d'écrire un même chiffre. Aussi contraint soit-il, le modèle ne peut pas reconnaître une écriture qu'il n'a jamais vue.

Dans un vrai entraînement, on combat le surapprentissage à peu près dans cet ordre :

  1. D'abord chercher à obtenir plus de données. Des données plus nombreuses et plus variées sont presque toujours le plus efficace.
  2. Toujours avoir un jeu de validation, et le surveiller. Si belle que soit la baisse de la perte d'entraînement, elle ne sert à rien si les indicateurs de validation ne progressent pas. L'arrêt précoce ne coûte presque rien : activez-le par défaut.
  3. Ensuite, affiner avec la régularisation. La force de la décroissance des poids et du dropout se trouve par essais sur le jeu de validation ; il n'y a pas de valeur universelle.
  4. Le modèle n'a pas besoin d'être grand d'emblée. Avec peu de données, un modèle plus petit suffit souvent.

C'est la même chose pour l'entraînement des grands modèles. Leurs moyens de régularisation ne sont pas compliqués ; la vraie clé, ce sont des données d'entraînement massives, variées et propres. En entraînant le petit GPT du module 09, vous verrez de vos propres yeux qu'avec trop peu de données, il apprend les vers par cœur au lieu d'apprendre à écrire des poèmes.

Exercices

  1. Fixez les données d'entraînement à 200 puis 400 images, et dressez un tableau « quantité de données d'entraînement → précision de test ». La précision augmente-t-elle régulièrement avec la quantité de données ?
  2. Passez les couches cachées du modèle de 512 à 32, et entraînez avec seulement 100 images. La précision de test est-elle meilleure ou moins bonne que celle du grand modèle à 300 000 paramètres ?
  3. Réglez le dropout à 0,2 et 0,8, la décroissance des poids à 0,01 et 5,0, trouvez la meilleure combinaison sur le jeu de validation, puis regardez une dernière fois le jeu de test.

Auto-test

1. Comment repérer un surapprentissage au cours de l'entraînement ?

La perte d'entraînement continue de baisser, alors que la perte de validation cesse de baisser, voire remonte : les deux courbes se séparent. Une précision sur le jeu d'entraînement nettement supérieure à celle sur le jeu de validation est aussi un signal.

2. On a déjà un jeu de test : pourquoi faut-il en plus un jeu de validation ?

Pour régler, on regarde les scores encore et encore avant de modifier les réglages. Si l'on regarde le jeu de test, les réglages retenus après de nombreux ajustements conviendront peut-être seulement par hasard à ce jeu de test, et son score ne représentera plus le comportement sur de nouvelles données. On règle donc avec le jeu de validation, et on ne regarde le jeu de test qu'une seule fois, à la fin.

3. Dans l'expérience de cette leçon, décroissance des poids, dropout et arrêt précoce n'ont pas amélioré la précision. Pourquoi plus de données l'ont-elles beaucoup améliorée ?

Les méthodes de régularisation ne font qu'empêcher le modèle de trop dépendre des détails du jeu d'entraînement ; elles n'apportent aucune information nouvelle. Avec 100 images, chaque chiffre n'en a qu'une dizaine, beaucoup d'écritures n'ont jamais été vues, et aucune contrainte ne permet au modèle de les reconnaître. Plus de données lui montrent directement davantage d'écritures, d'où un effet bien supérieur. Dans cette expérience, les autres méthodes ont surtout fait baisser la perte de test, pour que le modèle ne se trompe plus avec assurance.

Questions et discussion

Bloqué sur cette leçon ? Posez votre question ici. Et si vous pouvez répondre à quelqu'un, n'hésitez pas.

Une question rapporte 3 points, une réponse 6. Les messages paraissent après vérification.

Chargement de la discussion…