ML Atlas

Le machine learning en partant de zéro · Leçon 3.5 · 18 sur 33 leçons prêtes · 14 min

Régler les hyperparamètres sans tricher

En bref

Le meilleur des 9 réglages de l’arbre obtient 93,7 % en validation croisée et 88,3 % sur de nouvelles biopsies. Choisir le gagnant gonfle son score.

Échauffement Deux questions de leçons précédentes. Une minute, sans jamais bloquer la leçon.
De la leçon 3.4 : Régularisation : ridge et lasso Dans le lab, le lasso garde 3 variables et le R² de test passe de 0,470 à 0,386. Qu’est-ce que cela veut dire ?

Voir la réponse

Bonne réponse : Qu’un modèle plus simple coûte un peu de précision : il faut peser les deux objectifs

Moins de variables rendent un modèle plus facile à utiliser et à expliquer, mais ici il explique une plus petite part de la variation du résultat. La force de la pénalité se choisit en validation, en pesant simplicité et précision.

De la leçon 3.3 : Courbes d’apprentissage : données ou meilleur modèle ? Pourquoi l’exactitude en entraînement baisse-t-elle quand les données d’entraînement grandissent ?

Voir la réponse

Bonne réponse : Parce que mémoriser chaque exemple devient plus dur, donc le modèle généralise

Avec 50 images, le modèle les réussit toutes, avec 1438, il en réussit 98,0 %. La validation, elle, monte de 82,3 % à 95,8 %.

Dans la leçon 3.2, la validation croisée évaluait un seul réglage du modèle. En pratique, on en essaie beaucoup et on garde le meilleur. C’est le réglage des hyperparamètres. Les réglages que vous choisissez avant l’entraînement (la profondeur d’un arbre, la force de la pénalité α de la leçon 3.4) sont des hyperparamètres : le modèle ne les apprend pas à partir des données, c’est vous qui les choisissez. Aujourd’hui, vous allez voir que le score du gagnant du réglage est trop optimiste, et pourquoi.

Prédisez, puis vérifiez Un arbre de décision reconnaît les tumeurs malignes sur 398 biopsies. Vous essayez 9 réglages : 3 profondeurs fois 3 nombres minimaux de biopsies par feuille. Vous évaluez chacun en validation croisée à 5 blocs. Le gagnant obtient 93,7 %. Combien obtiendra-t-il sur 171 nouvelles biopsies qu’il n’a jamais vues ?
Quel est votre degré de certitude ?

Labo interactif

Ce labo interactif fonctionne dans un navigateur avec JavaScript activé. Le texte qui l’entoure décrit ce qu’il montre.

Voir la réponse

Bonne réponse : Moins, par exemple 88,3 %, parce que nous avons aussi choisi du bruit favorable

Sur les 171 biopsies de test, le gagnant obtient 88,3 %, 5,4 points de moins qu’en validation croisée. Une partie vient de la sélection, une partie de la petite taille du test : une biopsie vaut 0,6 point. Choisir la meilleure de 20 graines de découpage gonfle le score de 2,7 points. Ce découpage est du côté pessimiste : sur 50 autres découpages (code plus bas), le gagnant perd en moyenne 1,4 point.

À vous de jouer

  • Avec la grille, passez le budget de 4 à 9. Quel score a le gagnant en validation croisée, et lequel au test ?
  • Passez à la recherche aléatoire et cliquez plusieurs fois sur « nouveau tirage ». Le gagnant est-il parfois meilleur au test qu’en validation ?
  • Dans la deuxième partie, déplacez le curseur des graines de 1 à 20. Comment le meilleur score augmente-t-il, et à quelle distance s’éloigne-t-il de la moyenne de 200 découpages ?

Une fois vérifié dans le lab, mettons un nom sur ce que vous voyez.

L’idée en quelques mots

Régler, c’est comparer de nombreux réglages sur des données de validation et choisir le meilleur. La recherche en grille essaie toutes les combinaisons de quelques valeurs. La recherche aléatoire tire des combinaisons dans toute la plage. À budget égal, une grille 3×3 n’essaie que 3 profondeurs : 1, 6 et 12. Neuf essais au hasard voient en général plus de valeurs différentes de chaque hyperparamètre.

Chaque score de validation est la vraie qualité du réglage plus un peu de chance : quelles biopsies sont tombées dans quelle partie. Quand vous choisissez le meilleur score, vous choisissez aussi le réglage que la chance a le plus aidé. Sur de nouvelles données, cette chance a disparu. C’est la malédiction du gagnant. Elle grandit avec le nombre de réglages comparés et diminue avec la taille des données.

La même chose arrive quand vous cherchez le meilleur découpage des données. La même régression logistique sur 200 découpages aléatoires obtient en moyenne 93,8 % au test. Si vous essayez les graines 1–20 et publiez la meilleure, vous obtenez 96,5 %, 2,7 points de plus. Le code est le même ; vous avez seulement choisi la chance.

Jak to policzono
  • Biopsies : Breast Cancer Wisconsin (Diagnostic), UCI, licence CC BY 4.0. 569 biopsies, 10 mesures « mean » chacune.
  • Réglage : découpage stratifié, 398 biopsies pour régler et 171 pour le test. Un arbre CART (Gini), 10 profondeurs fois 11 nombres minimaux de biopsies par feuille, soit 110 réglages, chacun en validation croisée à 5 blocs sur les 398 biopsies.
  • Gagnant : la meilleure moyenne sur les 5 parties ; en cas d’égalité, l’arbre le plus simple. Au test, on évalue l’arbre entraîné sur les 398 biopsies.
  • Graines : régression logistique (C = 1) sur des mesures standardisées, 200 découpages aléatoires 70/30, avec 171 biopsies de test dans chacun.

Pourquoi ça marche

Prenez 9 réglages de vraie qualité presque égale. Leurs scores de validation diffèrent surtout par le bruit. Le plus haut des 9 scores est presque toujours un score où le bruit était positif. Dans le lab, la meilleure CV trouve juste 373 biopsies sur 398, et plusieurs réglages n’ont qu’une ou deux biopsies de retard. Des écarts aussi petits relèvent en bonne partie du hasard.

La sélection se voit en mode aléatoire : sur 200 tirages de 9 réglages, le gagnant obtient plus en validation qu’au test dans chacun d’eux, 3,6 points en moyenne. Le test n’a pas participé au choix, il ne porte donc aucune sélection, seulement le bruit ordinaire d’un ensemble fini. Mais les 200 tirages sont des réglages différents sur un seul et même découpage des données, et celui-ci est tombé du côté pessimiste : même sans aucun choix, les 110 réglages obtiennent en moyenne 0,6 point de plus en validation qu’au test. Dans le code plus bas, sur 50 découpages différents, le gagnant perd en moyenne 1,4 point, et dans 17 découpages sur 50 la validation ne dépasse pas le test.

C’est pourquoi le test ne doit pas servir à choisir. Si l’on choisissait un réglage d’après son score de test, la meilleure case obtiendrait 92,4 % au test. Ce nombre serait gonflé lui aussi, seulement plus difficile à repérer, parce qu’il ne resterait plus de données pour le vérifier.

Erreur fréquente

Vrai ou faux : « le score du gagnant du réglage est une prévision pour de nouvelles données ». Faux. Le score de validation du gagnant est gonflé, car c’est le maximum de nombreux nombres bruités. Dans le lab, le gagnant des 9 réglages a 93,7 % en validation et 88,3 % au test. Dans le code plus bas, sur 50 découpages et 110 réglages, le gagnant obtient en moyenne 93,3 % en validation et 91,9 % sur le test mis de côté.

Une prévision honnête passe par l’une de deux voies. La première : un test mis de côté, qui ne sert à aucun choix et que l’on regarde une fois, à la fin. La seconde : la validation croisée imbriquée, c’est-à-dire tout le réglage répété dans chaque partie d’une validation croisée extérieure. Sur les 569 biopsies, le gagnant obtient 94,0 % en validation croisée ordinaire, alors que la validation imbriquée donne 91,9 %. Le second nombre est plus proche de ce que fera le modèle demain.

Quiz

Trois questions pour vérifier vos acquis. Choisissez une réponse ou dépliez la solution sous chaque question. Au clavier : les flèches choisissent, Entrée ou Espace valide.

1. Qu’est-ce qu’un hyperparamètre ?
Voir la réponse

Bonne réponse : Un réglage choisi avant l’entraînement, que le modèle n’apprend pas lui-même des données

Les hyperparamètres, comme la profondeur d’un arbre ou la force de la pénalité α, c’est vous qui les choisissez, en général en validation. Les poids et les seuils d’un arbre, le modèle les apprend lui-même.

2. Le gagnant du réglage obtient 93,7 % en validation croisée. À quoi s’attendre sur de nouvelles données ?
Voir la réponse

Bonne réponse : Plutôt moins, parce que choisir le meilleur de nombreux scores choisit aussi la chance

C’est la malédiction du gagnant. Dans le lab, le gagnant des 9 réglages obtient 88,3 % au test ; sur 200 tirages, son score de validation dépasse son score de test à chaque fois.

3. Comment évaluer honnêtement un modèle dont vous avez choisi les hyperparamètres par validation croisée ?
Voir la réponse

Bonne réponse : Le vérifier sur un test mis de côté ou par une validation croisée imbriquée autour du réglage

Le test mis de côté et la validation croisée imbriquée n’ont pas participé au choix. Dans le code, la validation croisée ordinaire donne 94,0 %, l’imbriquée 91,9 %.

À retenir

  • Les hyperparamètres, c’est vous qui les choisissez, avant l’entraînement ; on les règle en validation, jamais sur le test.
  • Le score du gagnant du réglage est gonflé : en choisissant le meilleur score, on choisit aussi la chance (la malédiction du gagnant).
  • Choisir la meilleure graine de découpage, c’est aussi régler sur le jeu de test.
  • Une prévision honnête vient d’un test mis de côté regardé une seule fois, ou de la validation croisée imbriquée.

Pour aller plus loin : formule, code, pratique

Les maths

Soit μₖ la vraie qualité du réglage k et Ŝₖ = μₖ + εₖ son score de validation, où le bruit εₖ a une moyenne de 0. Pour un réglage, E[Ŝₖ] = μₖ. Pour le gagnant k = argmaxₖ Ŝₖ, en moyenne E[Ŝ_k] ≥ μ_k* : le maximum de plusieurs nombres bruités est en moyenne plus haut que la vraie qualité de celui qu’on choisit. Avec m réglages de même qualité, E[max εₖ] croît avec m à peu près comme σ · √(2 · ln m).

Une biopsie de test pour n = 171 vaut 1/171, soit 0,6 point. L’erreur type d’une exactitude p sur n exemples : √(p(1 − p)/n).

Validation croisée imbriquée : une boucle extérieure découpe les données en K parties ; pour chaque partie, tout le réglage (une validation croisée intérieure) se fait sur les autres seulement, et le modèle choisi est évalué sur la partie mise de côté.

En code (Python)

La même expérience dans scikit-learn : la malédiction du gagnant sur 50 découpages avec les 110 réglages de l’arbre, la validation croisée ordinaire et imbriquée sur toutes les biopsies, et la meilleure de 20 graines de découpage.

import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, GridSearchCV, StratifiedKFold, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

X, y = load_breast_cancer(return_X_y=True)
X = X[:, :10]  # les 10 mesures « mean », comme dans le lab
grid = {"max_depth": [1, 2, 3, 4, 5, 6, 7, 8, 10, 12], "min_samples_leaf": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48]}  # les 110 réglages du lab
tree = DecisionTreeClassifier(random_state=0)
r = []
for s in range(50):
    tr, te = train_test_split(np.arange(len(y)), test_size=0.3, stratify=y, random_state=s)
    search = GridSearchCV(tree, grid, cv=StratifiedKFold(5, shuffle=True, random_state=s)).fit(X[tr], y[tr])
    r.append((search.best_score_, search.score(X[te], y[te])))  # la CV du gagnant, puis le gagnant sur le test mis de côté
r = np.array(r)
print(f"winner of 110 settings, 50 splits: CV {r[:, 0].mean():.1%}, held-out test {r[:, 1].mean():.1%}; CV higher in {(r[:, 0] > r[:, 1]).sum()} of 50")
outer = StratifiedKFold(5, shuffle=True, random_state=0)
flat = GridSearchCV(tree, grid, cv=outer).fit(X, y).best_score_  # le score du gagnant sur les mêmes parties qui l’ont choisi
nested = cross_val_score(GridSearchCV(tree, grid, cv=StratifiedKFold(5, shuffle=True, random_state=1)), X, y, cv=outer).mean()  # la recherche se fait dans chaque partie extérieure
print(f"all 569 biopsies: winner's CV {flat:.1%}, nested CV {nested:.1%}")
model = make_pipeline(StandardScaler(), LogisticRegression())
acc = []
for s in range(200):  # 200 découpages aléatoires, 30 % de test, comme dans le lab
    tr, te = train_test_split(np.arange(len(y)), test_size=0.3, random_state=s)
    acc.append(model.fit(X[tr], y[tr]).score(X[te], y[te]))
acc = np.array(acc)
best = acc.reshape(10, 20).max(axis=1)  # dix personnes, chacune essaie 20 graines et publie la meilleure
print(f"logistic regression, 200 seeds: mean {acc.mean():.1%}; best of 20 seeds {best.mean():.1%} on average (+{(best.mean() - acc.mean()) * 100:.1f} points), higher in {(best > acc.mean()).sum()} of 10")

Sortie

winner of 110 settings, 50 splits: CV 93.3%, held-out test 91.9%; CV higher in 33 of 50
all 569 biopsies: winner's CV 94.0%, nested CV 91.9%
logistic regression, 200 seeds: mean 93.7%; best of 20 seeds 96.4% on average (+2.6 points), higher in 10 of 10

Les découpages diffèrent de ceux du lab, donc les nombres aussi. L’image est la même : le gagnant du réglage obtient en moyenne 93,3 % en validation et 91,9 % sur le test mis de côté ; la validation est plus haute dans 33 découpages sur 50. La validation croisée imbriquée donne 91,9 % au lieu de 94,0 %, et la meilleure de 20 graines gonfle le score de 2,6 points, pour chacune des 10 personnes.

Pour les praticiens
  • Dans scikit-learn : GridSearchCV et RandomizedSearchCV. Le best_score_ est gonflé pour la même raison que dans le lab ; évaluez le gagnant avec score sur un test mis de côté.
  • Validation croisée imbriquée : cross_val_score(GridSearchCV(...), X, y, cv=...). Le réglage se fait alors dans chaque partie extérieure.
  • Avec de nombreux hyperparamètres dont peu comptent, la recherche aléatoire trouve en général un bon réglage plus vite qu’une grille (Bergstra et Bengio, 2012).
  • Fixez la graine aléatoire une fois, avant l’expérience, et notez-la. Donnez la moyenne et la dispersion sur plusieurs découpages ou en validation croisée, pas le score de la meilleure graine.

Aller plus loin dans l’Atlas

Articles de l’encyclopédie sur les notions de cette leçon :