Un modèle qui colle parfaitement à ses données d'entraînement n'est pas forcément un bon modèle — c'est parfois le signe qu'il a appris le bruit plutôt que le signal.
Un archer qui rate toujours du même côté de la cible a un problème de biais — son viseur est mal réglé. Un archer dont les flèches sont éparpillées partout autour du centre a un problème de variance — son geste n'est pas reproductible.
En machine learning, c'est exactement la même chose : un modèle trop simple rate systématiquement (biais), un modèle trop complexe est instable d'un échantillon à l'autre (variance).
Le modèle A obtient une erreur quasi nulle sur les données qu'il a vues à l'entraînement. Le modèle B se trompe visiblement plus sur ces mêmes données. Lequel déployer en production ?
>>> modele_A.erreur_entrainement 0.004 # quasiment parfait >>> modele_A.erreur_test 1.56 # 400 fois pire sur des données neuves >>> modele_B.erreur_entrainement 0.033 # nettement moins bon "sur le papier" >>> modele_B.erreur_test 0.098 # mais qui généralise beaucoup mieux
Le modèle A a un score d'entraînement éblouissant et un score de production désastreux. Le modèle B, moins impressionnant sur le papier, est en réalité le bon choix. Comprendre pourquoi demande de séparer deux sources d'erreur bien distinctes.
En clair : l'objectif n'est jamais de minimiser l'erreur d'entraînement — n'importe quel modèle assez complexe peut l'amener à zéro en mémorisant le bruit. L'objectif est de minimiser l'erreur sur des données jamais vues. Biais et variance tirent cette erreur dans deux directions opposées : c'est un compromis, pas un problème à éliminer entièrement.
Le centre de la cible représente la vraie valeur à prédire. Chaque flèche est une prédiction faite sur un échantillon d'entraînement légèrement différent.
14 points d'entraînement (cyan), 14 points de test jamais montrés au modèle (magenta). Faites varier la complexité du modèle et observez ce qu'il se passe sur les deux erreurs.
Classique dans les projets de recommandation ou de scoring : une équipe évalue son modèle uniquement sur les données historiques qui ont servi à l'entraîner, obtient un score quasi parfait, le met en production — et les performances s'effondrent dès les premières semaines.
Le vrai bug : ce n'est pas le modèle qui a régressé, c'est l'évaluation qui n'a jamais mesuré la bonne chose. Un score calculé sur les données d'entraînement ne renseigne que sur la capacité du modèle à mémoriser — jamais sur sa capacité à généraliser.
Le même principe que le simulateur, en Python avec NumPy.
import numpy as np # Données d'entraînement et de test, issues de la même fonction bruitée x_train = np.linspace(-3, 3, 14) y_train = np.sin(1.4 * x_train) + 0.15 * x_train + np.random.normal(0, 0.25, 14) x_test = np.linspace(-2.85, 2.85, 14) y_test = np.sin(1.4 * x_test) + 0.15 * x_test + np.random.normal(0, 0.25, 14) for degre in [1, 2, 5, 9, 12]: coeffs = np.polyfit(x_train, y_train, degre) modele = np.poly1d(coeffs) erreur_train = np.mean((modele(x_train) - y_train) ** 2) erreur_test = np.mean((modele(x_test) - y_test) ** 2) print(f"degré {degre:2d} → train={erreur_train:.3f} test={erreur_test:.3f}")