Aller au contenu
English

Contrôler la complexité

  • Leçon 16
  • 60 min
  • Module 5 : Essayer d'autres familles de modèles
Leçon 16 sur 27 · Apprentissage automatique : du problème à un modèle fiableContrôler la complexité

Ce que vous saurez faire

Un modèle peut être trop simple pour apprendre la tendance. Il peut aussi être si complexe qu’il apprend le bruit des billets de soutien d’entraînement. Apprenez à reconnaître les deux cas à partir de deux nombres. Choisissez les réglages qui donnent les meilleurs résultats sur des billets jamais vus.

Carnet JupyterFaites cette leçon dans un carnet JupyterColab · Kaggle · GitHub · en anglais

Le carnet contient toutes les cellules de code, les tâches et les vérifications de cette leçon, avec les instructions et les graphiques. Ses cellules de préparation installent les paquets, téléchargent les données d’exercice et créent ticket_model.py. Elles créent aussi votre journal d’expériences jusqu’ici. Le carnet fonctionne donc sans le projet local. Utilisez l’explorateur ici et exécutez le code dans le carnet.

Le carnet est en anglais. Colab et Kaggle ouvrent votre propre copie. Il faut un compte Google ou Kaggle gratuit. Vous êtes bloqué ? Consultez le carnet de solution.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 60 minutes

Ce que vous devez savoir

Ce qu’il vous faut sur votre ordinateur (seulement pour le parcours local; le carnet n’en a pas besoin)

Testé sur macOS avec Python 3.14.6, pandas 3.0.6, scikit-learn 1.9.1 et matplotlib 3.11.2. Les étapes pour Windows et Linux n’ont pas été testées. Le carnet a été testé dans Jupyter.

Trois élèves préparent un examen de mathématiques avec le même livre d’exercices.

  • Le premier élève apprend une règle : « la réponse est généralement le plus grand nombre ». Elle fonctionne pour quelques exercices. À l’examen, il répond mal à la plupart des questions. Il a appris trop peu : sa règle est trop simple pour la matière.
  • La deuxième élève apprend chaque exercice par cœur, avec sa réponse. Elle réussit parfaitement les exercices. À l’examen, les questions sont nouvelles, et elle ne sait plus quoi faire. Elle a appris trop de choses inutiles : les détails des exercices, pas la méthode.
  • La troisième élève apprend les méthodes. Elle fait quelques erreurs dans les exercices, et à peu près autant à l’examen.

Un modèle peut être n’importe lequel de ces élèves. Les deux premiers représentent les deux façons dont un modèle échoue. Le troisième est le modèle souhaité. Le problème, c’est que vous ne pouvez pas regarder dans la tête d’un modèle. Vous ne voyez que ses scores. Cette leçon montre comment deux scores permettent de distinguer les trois élèves. Le premier est le score sur les billets d’entraînement (les exercices). Le second est le score obtenu par validation croisée (les nouvelles questions).

Le code de cette leçon utilise les fonctions auxiliaires de Les arbres de décision : cv (les 5 plis), tree_pipeline() et evaluate(). Il utilise aussi le tableau tiny des 10 billets inventés. Le carnet les définit de nouveau dans sa première cellule et importe aussi learning_curve, LogisticRegression et matplotlib.

Commencez avec les 10 billets de Les arbres de décision. Entraînez trois arbres : un de profondeur 1, un de profondeur 2 et un sans limite (max_depth=None) :

x_tiny = tiny[["priority", "word_count"]]
for depth in (1, 2, None):
tiny_tree = DecisionTreeClassifier(max_depth=depth, random_state=0).fit(x_tiny, tiny["escalated"])
print(f"max_depth={depth}: {tiny_tree.get_n_leaves()} leaves, scores", tiny_tree.predict_proba(x_tiny)[:, 1].round(2))
print(export_text(tiny_tree, feature_names=["priority", "word_count"]))
Sortie
max_depth=1: 2 leaves, scores [0.75 0.75 0.75 0.75 0.17 0.17 0.17 0.17 0.17 0.17]
max_depth=2: 4 leaves, scores [1. 0. 1. 1. 0.33 0.33 0. 0. 0.33 0. ]
max_depth=None: 5 leaves, scores [1. 0. 1. 1. 1. 0. 0. 0. 0. 0.]
|--- priority <= 1.50
| |--- word_count <= 42.50
| | |--- class: 0
| |--- word_count > 42.50
| | |--- class: 1
|--- priority > 1.50
| |--- word_count <= 95.00
| | |--- class: 0
| |--- word_count > 95.00
| | |--- word_count <= 137.50
| | | |--- class: 1
| | |--- word_count > 137.50
| | | |--- class: 0

Sans limite, l’arbre a besoin de 5 feuilles, et ses scores correspondent exactement aux cibles. Regardez sa troisième question, word_count <= 137.50. Elle sépare T-05 (130 mots, transmis au niveau supérieur) de T-06 (160 mots) et de T-09 (145 mots). Voici sa règle : « un billet de priorité 2 ou 3 comptant de 96 à 137 mots est transmis au niveau supérieur. Un billet de 138 mots ou plus ne l’est pas ». Feriez-vous confiance à cette règle pour le prochain billet? Elle vient d’un seul billet.

Voici les deux échecs des élèves :

  • Le surapprentissage correspond à la deuxième élève. Le modèle apprend des détails des billets d’entraînement qui ne se répètent pas dans les nouveaux billets. Le score d’entraînement est élevé, et le score sur les nouveaux billets est plus faible. L’arbre sans limite fait du surapprentissage : sa règle « 96 à 137 mots » vient d’un seul billet.
  • Le sous-apprentissage correspond au premier élève. Le modèle est trop simple pour apprendre la tendance présente, donc les deux scores sont faibles. L’arbre à une question fait du sous-apprentissage. Il donne le même score (0,17) à T-05, transmis au niveau supérieur, et à T-08, qui ne l’a pas été.

Dans Les arbres de décision, l’arbre sans limite obtenait 1,000 à l’entraînement et 0,137 en validation croisée. Voici comment il y arrive :

full_tree = tree_pipeline(DecisionTreeClassifier(random_state=0))
print("tree, no limit:", evaluate(full_tree))
model = full_tree.named_steps["model"]
print("leaves:", model.get_n_leaves(), " depth:", model.get_depth())
Sortie
tree, no limit: {'train AP': 1.0, 'CV AP': 0.137, 'std': 0.004}
leaves: 2210 depth: 31

L’arbre pose jusqu’à 31 questions de suite et crée 2 210 feuilles, toutes pures. Chaque billet d’entraînement reçoit exactement sa propre cible, donc l’AP d’entraînement est de 1,000. Sur les billets jamais vus, l’AP est de 0,137, à peine au-dessus du plancher de 0,117 (un score pour tous les billets). L’arbre a appris 2 210 petites règles comme « 96 à 137 mots », et la plupart représentent du bruit.

Imaginez deux mauvais pèse-personnes. Le premier indique toujours 2 kg de trop. Pesez-vous cinq fois : il affiche cinq fois le même nombre erroné. Le second est juste en moyenne, mais ses valeurs varient : 68 kg, puis 73 kg, puis 66 kg. Les deux pèse-personnes se trompent, de façons différentes. Le premier a un biais : une erreur constante dans une direction. Le second a une grande variance : ses réponses changent beaucoup alors que rien d’important n’a changé.

Les modèles échouent des deux mêmes façons. Voici les termes techniques :

  • Le biais est l’erreur d’un modèle trop simple. Il manque toujours la même partie de la tendance, quels que soient les billets d’entraînement. Un modèle en sous-apprentissage a un biais élevé.
  • La variance mesure à quel point le modèle change quand ses billets d’entraînement changent. Un modèle en surapprentissage a une variance élevée : il suit les détails aléatoires de ses billets. D’autres billets ont d’autres détails aléatoires.

Pour les observer, Priya entraîne des arbres sur cinq moitiés aléatoires différentes des données d’entraînement. Elle calcule ensuite le score d’un billet de mai, T-117529, transmis au niveau supérieur. Elle mesure aussi la dispersion des cinq scores pour chaque billet de mai, puis calcule la moyenne :

valid = load("valid")
ticket = valid[valid["ticket_id"] == "T-117529"]
for depth in (None, 3):
ticket_scores, all_scores = [], []
for seed in range(5):
half = train.sample(frac=0.5, random_state=seed)
pipeline = tree_pipeline(DecisionTreeClassifier(max_depth=depth, random_state=0))
pipeline.fit(half[FEATURES], half[TARGET])
ticket_scores.append(round(float(pipeline.predict_proba(ticket[FEATURES])[0, 1]), 3))
all_scores.append(pipeline.predict_proba(valid[FEATURES])[:, 1])
spread = pd.DataFrame(all_scores).std(ddof=0).mean()
print(f"max_depth={depth}: T-117529 gets {ticket_scores}; mean spread over May {spread:.3f}")
Sortie
max_depth=None: T-117529 gets [0.0, 1.0, 0.0, 1.0, 0.0]; mean spread over May 0.194
max_depth=3: T-117529 gets [0.117, 0.099, 0.099, 0.12, 0.113]; mean spread over May 0.024
  • L’arbre sans limite a une variance élevée. Pour le même billet, sa réponse passe de 0 à 1 selon les billets d’entraînement reçus. Sur l’ensemble des billets de mai, ses cinq scores diffèrent de 0,194 en moyenne.
  • L’arbre de profondeur 3 est stable (0,024), mais donne seulement environ 0,1 à ce billet transmis au niveau supérieur. Ses quelques feuilles ne peuvent pas suivre la tendance de près : il a un biais plus élevé.

Un bon modèle se situe entre les deux. C’est le compromis entre biais et variance : plus de complexité réduit le biais et augmente la variance. Vous trouvez le meilleur équilibre avec la validation croisée, comme le montrent les prochaines sections. Les méthodes d’ensemble, la prochaine leçon, réduit la variance autrement : elle fait la moyenne de nombreux arbres à variance élevée.

Quelle profondeur donner à un arbre? L’arbre ne peut pas répondre lui-même à cette question. Quand vous appelez fit(), l’arbre apprend ses questions et ses seuils de séparation à partir des données. Ces valeurs apprises sont les paramètres du modèle : les poids de la régression logistique sont aussi des paramètres. Mais max_depth n’est pas appris. Vous le choisissez avant l’entraînement, et il contrôle le déroulement de l’entraînement.

Un réglage choisi avant l’entraînement est un hyperparamètre. « Hyper » signifie « au-dessus » : un hyperparamètre se situe au-dessus des paramètres et contrôle leur apprentissage. Pensez à un appareil photo. La photo enregistre ce qui se trouve devant l’objectif. Mais vous réglez le zoom avant de la prendre, et le zoom détermine le niveau de détail visible. max_depth est le zoom d’un arbre. Chaque algorithme a des hyperparamètres : max_depth et min_samples_leaf pour un arbre, C pour la régression logistique, comme vous le verrez plus bas.

Vous choisissez un hyperparamètre comme tout le reste dans la boucle. Essayez plusieurs valeurs, évaluez chacune par validation croisée sur les données d’entraînement et gardez la meilleure. Régler les hyperparamètres, au module 6, le fait pour plusieurs hyperparamètres à la fois. Ici, vous le faites pour un seul.

Priya entraîne un arbre pour chaque max_depth de 1 à 20 et ajoute l’écart : AP d’entraînement − AP en validation croisée. L’écart montre à quel point l’arbre réussit mieux sur les billets utilisés pour apprendre que sur de nouveaux billets. Cela prend environ 10 secondes.

rows = []
for depth in range(1, 21):
result = evaluate(tree_pipeline(DecisionTreeClassifier(max_depth=depth, random_state=0)))
rows.append({"depth": depth, **result})
sweep = pd.DataFrame(rows).set_index("depth")
sweep["gap"] = (sweep["train AP"] - sweep["CV AP"]).round(3)
print(sweep.loc[[1, 2, 3, 4, 5, 6, 7, 8, 10, 15, 20]])

Avant de lire la sortie, faites une prédiction : quelle profondeur donne la meilleure AP en validation croisée, 2, 6 ou 20?

Sortie
train AP CV AP std gap
depth
1 0.178 0.178 0.008 0.000
2 0.217 0.215 0.010 0.002
3 0.244 0.234 0.011 0.010
4 0.275 0.247 0.008 0.028
5 0.308 0.255 0.010 0.053
6 0.346 0.258 0.010 0.088
7 0.391 0.250 0.012 0.141
8 0.441 0.235 0.012 0.206
10 0.579 0.211 0.014 0.368
15 0.917 0.159 0.009 0.758
20 0.996 0.139 0.006 0.857
  • AP d'entraînement (les billets utilisés pour apprendre)
  • AP en validation croisée (les billets jamais vus)
AP d'entraînement et AP en validation croisée d'un arbre de décision pour chaque max_depth de 1 à 20. La courbe d'entraînement monte toujours; celle de validation croisée atteint son sommet à la profondeur 6, puis descend.
Description textuelle du graphique

L’axe horizontal représente la profondeur maximale, de 1 à 20. L’axe vertical représente la précision moyenne, de 0 à 1. À la profondeur 1, les deux courbes commencent à 0,178. La courbe d’entraînement (orange) monte à chaque profondeur : 0,346 à 6, 0,579 à 10, 0,917 à 15 et 0,996 à 20. La courbe de validation croisée (bleue) atteint son sommet, 0,258, à la profondeur 6. Puis elle descend : 0,211 à 10, 0,159 à 15 et 0,139 à 20, près du plancher de 0,117.

Lisez le graphique de gauche à droite :

  • Profondeurs 1 à 3, sous-apprentissage. Les deux courbes sont basses et proches. L’arbre est trop simple. Chaque question supplémentaire aide encore sur les nouveaux billets.
  • Profondeur 6, meilleure AP en validation croisée : 0,258 ± 0,010. Les profondeurs 5 (0,255) et 7 (0,250) sont à moins d’un écart-type : elles sont aussi bonnes.
  • Profondeur 8 et plus, surapprentissage. La courbe d’entraînement continue de monter, mais celle de validation croisée descend. L’écart passe de 0,088 à la profondeur 6 à 0,857 à la profondeur 20. Chaque nouveau niveau de questions apprend davantage de bruit que de tendance.

La meilleure profondeur vient uniquement de la validation croisée sur les données d’entraînement. Le mois de validation reste disponible pour confirmer le choix final plus tard. Et le meilleur arbre, à 0,258, reste loin derrière la régression logistique (0,327 ± 0,012).

L’explorateur contient les mêmes nombres, plus le nombre de feuilles à chaque profondeur. Déplacez le curseur et observez la tuile de l’écart et la ligne d’état.

Explorer

AP d'entraînement, AP en validation croisée et écart, selon la profondeur

Profondeur max.
3
AP d’entraînement
0,244
AP en VC (± é.-t.)
0,234 ± 0,011
Écart : entraînement − VC
0,010
Feuilles
8

Trop simple (sous-apprentissage) : l’AP d’entraînement et l’AP en VC sont toutes deux basses, et l’écart n’est que de 0,010. L’arbre ne peut pas encore suivre le motif.

  • AP d’entraînement (les billets appris)
  • AP en VC (billets jamais vus)
00,20,40,60,81Précision moyenne (AP)12468101214161820Profondeur max. de l’arbreécart 0,010
00,20,40,60,81Précision moyenne (AP)15101520Profondeur max. de l’arbreécart 0,010
Valeurs précalculées à partir des données d'entraînement réelles : un arbre de décision sur les 10 caractéristiques du cours SQL et préparation des données pour l'IA pour chaque max_depth de 1 à 20, évalué sur les données d'entraînement et par validation croisée stratifiée à 5 plis.
Description textuelle de l’explorateur

L’explorateur a un curseur : la profondeur maximale, de 1 à 20. Il commence à la profondeur 3. Les indicateurs affichent la profondeur maximale, l’AP d’entraînement, l’AP en validation croisée avec son écart-type, l’écart et le nombre de feuilles. L’écart (AP d’entraînement − AP en validation croisée) est mis en évidence. Un graphique montre les courbes d’entraînement et de validation croisée pour toutes les profondeurs. À la profondeur choisie, il ajoute une ligne pointillée, deux points et une barre ombrée pour l’écart.

Les valeurs : profondeur 1 : entraînement 0,178, validation croisée 0,178 ± 0,008, écart 0,000, 2 feuilles. Profondeur 2 : 0,217, 0,215, écart 0,002, 4 feuilles. Profondeur 3 : 0,244, 0,234, écart 0,010, 8 feuilles. Profondeur 4 : 0,275, 0,247, écart 0,028, 16 feuilles. Profondeur 5 : 0,308, 0,255, écart 0,053, 31 feuilles. Profondeur 6 : 0,346, 0,258 ± 0,010, écart 0,088, 59 feuilles. Profondeur 7 : 0,391, 0,250, écart 0,141, 104 feuilles. Profondeur 8 : 0,441, 0,235, écart 0,206, 176 feuilles. Profondeur 10 : 0,579, 0,211, écart 0,368, 416 feuilles. Profondeur 12 : 0,735, 0,185, écart 0,550, 817 feuilles. Profondeur 15 : 0,917, 0,159, écart 0,758, 1 507 feuilles. Profondeur 20 : 0,996, 0,139, écart 0,857, 2 093 feuilles.

La ligne d’état indique « trop simple » aux profondeurs 1 à 4 et « meilleure AP en validation croisée » à la profondeur 6. Elle indique « près du meilleur résultat » aux profondeurs 5 et 7 (à moins d’un écart-type). Elle indique « trop complexe » à partir de la profondeur 8.

De la profondeur 6 à 7, l’AP en validation croisée baisse de 0,008, tandis que l’écart augmente de 0,053. Ensuite, chaque niveau supplémentaire augmente davantage l’écart que la qualité de l’ajustement. À la profondeur 10, l’arbre a 416 feuilles pour 16 939 billets; à la profondeur 20, il en a 2 093.

Exercice guidé : choisir la profondeur avec la validation croisée

Section intitulée « Exercice guidé : choisir la profondeur avec la validation croisée »

Faites cet exercice dans le carnet. Chaque étape comporte une vérification.

  1. Exécutez la cellule de balayage. Vous devriez voir le tableau ci-dessus : 0.346 0.258 0.010 0.088 à la profondeur 6.
  2. Exécutez la cellule du graphique. La courbe de validation croisée doit atteindre son sommet à la profondeur 6.
  3. Donnez à best_depth la profondeur avec l’AP en validation croisée la plus élevée. Utilisez int(sweep["CV AP"].idxmax()) : idxmax() donne l’indice de la plus grande valeur.
  4. Donnez à gap_at_best l’écart à cette profondeur : float(sweep.loc[best_depth, "gap"]).
  5. Exécutez la cellule de vérification. Vous devriez voir Check passed: best_depth is 6. (vérification réussie : best_depth vaut 6) et Check passed: gap_at_best is 0.088. (vérification réussie : gap_at_best vaut 0,088).

Autres limites : taille des feuilles et régularisation

Section intitulée « Autres limites : taille des feuilles et régularisation »

max_depth est une façon de limiter un arbre. min_samples_leaf en est une autre : le nombre minimal de billets d’entraînement qu’une feuille peut contenir. Une règle tirée d’un seul billet, comme « 96 à 137 mots », n’est alors pas permise.

La régression logistique a aussi une limite. La régularisation pénalise les poids élevés, ce qui garde le modèle plus simple. Le modèle doit « payer » pour chaque poids élevé. Il utilise donc des poids élevés seulement quand les données le justifient clairement. Dans scikit-learn, l’hyperparamètre C règle cette pénalité : un C plus petit signifie une pénalité plus forte. La valeur par défaut est C = 1.0. Avec une pénalité très forte, C = 0.0001, la régression logistique fait du sous-apprentissage :

strong_penalty = evaluate(build_pipeline(LogisticRegression(C=0.0001, max_iter=1000)))
print("logistic regression, C = 1 (default):", evaluate(build_pipeline()))
print("logistic regression, C = 0.0001: ", strong_penalty)
Sortie
logistic regression, C = 1 (default): {'train AP': 0.328, 'CV AP': 0.327, 'std': 0.012}
logistic regression, C = 0.0001: {'train AP': 0.301, 'CV AP': 0.302, 'std': 0.012}

Les deux scores baissent d’environ 0,025, et l’écart reste près de zéro. Avec la valeur par défaut C = 1, la régression logistique n’a presque aucun écart. Elle ne fait pas de surapprentissage, donc une pénalité plus forte peut seulement lui faire perdre quelque chose. Régler les hyperparamètres essaie plusieurs valeurs de C au module 6.

Plus de données seraient-elles utiles? Une courbe d’apprentissage répond à cette question. Elle montre le score d’entraînement et le score de validation croisée (CV) quand le modèle reçoit plus de billets d’entraînement. La fonction learning_curve de scikit-learn entraîne le modèle sur une partie des billets d’entraînement de chaque pli. Leur nombre va de 500 à 13 551. C’est quatre cinquièmes des données d’entraînement, le maximum permis par un pli :

sizes = [500, 1000, 2000, 4000, 8000, 13551]
curves = {}
for name, pipeline in {"logistic regression": build_pipeline(),
"tree, depth 6": tree_pipeline(DecisionTreeClassifier(max_depth=6, random_state=0)),
"tree, no limit": tree_pipeline(DecisionTreeClassifier(random_state=0))}.items():
n, train_scores, cv_scores = learning_curve(pipeline, train[FEATURES], train[TARGET], cv=cv, train_sizes=sizes,
scoring="average_precision", shuffle=True, random_state=0)
curves[name] = (train_scores.mean(axis=1), cv_scores.mean(axis=1))
print(f"{name:20s} train {train_scores.mean(axis=1).round(3)}")
print(f"{'':20s} CV {cv_scores.mean(axis=1).round(3)}")
Sortie
logistic regression train [0.408 0.386 0.371 0.349 0.337 0.329]
CV [0.279 0.304 0.317 0.323 0.325 0.327]
tree, depth 6 train [0.681 0.669 0.545 0.459 0.396 0.355]
CV [0.157 0.171 0.21 0.221 0.242 0.258]
tree, no limit train [1. 1. 1. 1. 1. 1.]
CV [0.139 0.135 0.138 0.136 0.141 0.137]
  • Régression logistique
  • Arbre, profondeur 6
  • Arbre, sans limite
  • Pointillés : AP d'entraînement. Ligne pleine avec points : AP en CV.
Courbes d'apprentissage de trois modèles, de 500 à 13 551 billets d'entraînement. Les lignes pointillées montrent l'AP d'entraînement, les lignes pleines avec points, l'AP en CV.
Description textuelle du graphique

L’axe horizontal indique le nombre de billets utilisés pour l’entraînement, de 500 à 13 551. L’axe vertical indique la précision moyenne, de 0 à 1. Régression logistique (bleu) : la ligne d’entraînement descend de 0,408 à 0,329, et la ligne de CV monte de 0,279 à 0,327. À 4 000 billets, elles sont à 0,349 et 0,323; à 13 551, elles se rejoignent presque. Arbre de profondeur 6 (orange) : la ligne d’entraînement descend de 0,681 à 0,355. La ligne de CV monte de 0,157 à 0,258 et monte encore à la fin. Arbre sans limite (vert) : la ligne d’entraînement reste à 1,0 pour toutes les tailles. La ligne de CV reste entre 0,135 et 0,141.

Chaque modèle montre une situation différente :

  • La régression logistique a appris tout ce qu’elle pouvait. Les deux lignes se rejoignent presque, et la ligne de CV est plate. De 4 000 à 13 551 billets, elle monte seulement de 0,323 à 0,327. Deux fois plus de billets du même type aideraient peu. Pour faire mieux, le modèle a besoin de meilleures caractéristiques. La leçon Sélectionner les caractéristiques utiles les teste dans le module 6.
  • L’arbre de profondeur 6 s’améliore encore. Sa ligne de CV monte à chaque étape, et l’écart diminue. Plus de billets aideraient cet arbre, mais il reste loin de 0,327.
  • L’arbre sans limite ne s’améliore pas du tout. Il mémorise les billets, peu importe leur nombre : 1,000 à l’entraînement pour toutes les tailles, environ 0,137 en CV. Plus de données ne corrigent pas un modèle qui apprend le bruit.

Une courbe d’apprentissage avec un grand écart dit : « surapprentissage : limitez le modèle ou obtenez plus de données ». Deux lignes qui se rejoignent à un niveau bas disent : « sous-apprentissage : un modèle plus flexible ou de meilleures caractéristiques ».

À vous : limitez les feuilles plutôt que la profondeur

Section intitulée « À vous : limitez les feuilles plutôt que la profondeur »

Changez une condition. Gardez une profondeur sans limite, mais limitez plutôt la taille des feuilles. Essayez min_samples_leaf = 1, 5, 20, 50, 100, 200 et 500. Avant de lancer le code, prédisez : quelle valeur donnera la meilleure AP en CV? Dépassera-t-elle la meilleure profondeur (0,258)?

leaf_rows = []
for leaf in [1, 5, 20, 50, 100, 200, 500]:
result = evaluate(tree_pipeline(DecisionTreeClassifier(min_samples_leaf=leaf, random_state=0)))
leaf_rows.append({"min_samples_leaf": leaf, **result})
leaf_sweep = pd.DataFrame(leaf_rows).set_index("min_samples_leaf")
print(leaf_sweep)
Afficher la réponse
Sortie
train AP CV AP std
min_samples_leaf
1 1.000 0.137 0.004
5 0.742 0.180 0.006
20 0.466 0.228 0.016
50 0.373 0.265 0.017
100 0.328 0.278 0.017
200 0.302 0.266 0.015
500 0.269 0.255 0.012

La meilleure valeur est min_samples_leaf=100 : AP en CV de 0,278 ± 0,017, avec un écart de seulement 0,050. L’arbre a alors 124 feuilles. On observe le même comportement qu’avec la profondeur. Une feuille trop petite cause du surapprentissage (1 et 5), et une feuille trop grande cause du sous-apprentissage (500). La meilleure taille de feuille dépasse la meilleure profondeur de 0,020, soit environ un écart-type. Elle est donc, au mieux, un peu meilleure. Les deux arbres restent sous la régression logistique (0,327 ± 0,012). Les limites rendent l’arbre honnête; elles ne lui donnent pas la bonne forme pour une relation additive.

Deux expériences de cette leçon vont dans le journal. La première est le meilleur arbre jusqu’ici (min_samples_leaf=100, dans votre exercice). La deuxième est la forte pénalité pour la régression logistique. L’essai de plusieurs profondeurs a retenu la profondeur 6, déjà inscrite au journal sous E07. Aucune nouvelle expérience ne dépasse E03, donc les deux sont rejetées :

log_experiment("E09", "Decision tree, no depth limit, min_samples_leaf=100", leaf_sweep.loc[100, "CV AP"],
leaf_sweep.loc[100, "std"], None, "reject", "The best tree so far, still far below E03.")
log_experiment("E10", "E03 with C=0.0001 (a very strong penalty)", strong_penalty["CV AP"], strong_penalty["std"],
None, "reject", "It underfits: both train and CV AP fall.")
show_log(columns=("id", "change", "cv_ap", "cv_std", "decision"))

Les dernières lignes de la sortie :

Sortie
id change cv_ap cv_std decision
...
E08 Decision tree, no depth limit 0.137 0.004 reject
E09 Decision tree, no depth limit, min_samples_leaf=100 0.278 0.017 reject
E10 E03 with C=0.0001 (a very strong penalty) 0.302 0.012 reject

Dix expériences, et la régression logistique avec ses réglages par défaut reste la meilleure. C’est un résultat normal de la boucle : la plupart des expériences sont rejetées. Chaque ligne rejetée a quand même appris quelque chose. Les arbres ont montré que ces données comportent peu d’interactions. La pénalité a montré que la régression logistique ne fait pas de surapprentissage.

Erreur courante

Aucun écart, donc aucun problème?

Symptôme : Tomás a appris qu’un écart indique du surapprentissage. Il veut un modèle sans aucun écart et en trouve un :

print("tree, depth 1:", evaluate(tree_pipeline(DecisionTreeClassifier(max_depth=1, random_state=0))))
print("tree, depth 6:", evaluate(tree_pipeline(DecisionTreeClassifier(max_depth=6, random_state=0))))
Sortie
tree, depth 1: {'train AP': 0.178, 'CV AP': 0.178, 'std': 0.008}
tree, depth 6: {'train AP': 0.346, 'CV AP': 0.258, 'std': 0.01}

« La profondeur 1 donne un écart de zéro. Le modèle ne fait pas de surapprentissage, donc c’est le plus sûr. »

Cause : un écart de zéro signifie seulement que le modèle n’apprend pas le bruit. L’arbre de profondeur 1 pose une question, « priority = 1? », et attribue à chaque billet l’un de deux scores. Il fait du sous-apprentissage. Son AP en CV, 0,178, dépasse à peine le plancher de 0,117. Elle reste loin de l’arbre de profondeur 6 (0,258) et de la régression logistique (0,327). Son biais est élevé. La régression logistique avec C = 0.0001 montre la même chose : aucun écart, mais une AP en CV de 0,302 plutôt que 0,327.

Correction : examinez toujours deux éléments ensemble. L’écart vous renseigne sur le surapprentissage. Le niveau du score de CV, comparé à la référence de base et au meilleur modèle, vous renseigne sur le sous-apprentissage. Choisissez la complexité qui donne le meilleur score de CV. Parmi les modèles à moins d’un écart-type de ce score, choisissez le plus simple.

Conséquence dans le travail en IA : un modèle choisi seulement pour « ne pas faire de surapprentissage » peut être trop faible pour être utile. L’équipe senior de Grace recevrait des signalements à peine meilleurs que la règle « signaler chaque billet de priorité 1 ». C’est pourtant cette règle que le modèle devait dépasser.

Vérifiez votre compréhension

Un modèle a une AP d'entraînement de 0,40 et une AP en CV de 0,39 pour toutes les tailles d'entraînement, de 2 000 à 13 551 billets. Fait-il du surapprentissage ou du sous-apprentissage? Deux fois plus de billets du même type aideraient-ils? Qu'essaieriez-vous plutôt?

Afficher la réponse

Les lignes se sont rejointes et restent plates, donc le modèle ne fait pas de surapprentissage. Il a appris tout ce qu’il pouvait à partir de ces caractéristiques. Plus de billets du même type aideront très peu. Pour faire mieux, donnez-lui plus d’information (de meilleures caractéristiques) ou utilisez un modèle plus flexible. Vérifiez le résultat par validation croisée. Si son niveau est aussi bas par rapport aux autres modèles, il fait du sous-apprentissage.

Vérifiez votre compréhension

Prédisez le résultat d'un arbre avec max_depth 25 sur les mêmes données. Son AP d'entraînement sera-t-elle plus haute ou plus basse qu'à la profondeur 20 (0,996)? Et son AP en CV? Expliquez avec les mots biais et variance.

Afficher la réponse

L’AP d’entraînement monte à 1,000, car plus de questions permettent à l’arbre de s’ajuster à chaque billet d’entraînement. L’AP en CV reste basse : sur ces données, elle est de 0,138, près de l’arbre sans limite (0,137). Un arbre plus profond a un biais plus faible, mais une variance beaucoup plus élevée. Ses feuilles décrivent des billets individuels, donc il change beaucoup selon les billets d’entraînement. Il fonctionne moins bien sur de nouveaux billets.

Vérifiez votre compréhension

Priya dit : « La profondeur 6 a une AP en CV de 0,258, et la profondeur 5, de 0,255. La profondeur 6 donne le meilleur arbre. » A-t-elle raison? Lequel choisiriez-vous, et pourquoi?

Afficher la réponse

La différence, 0,003, est beaucoup plus petite que l’écart-type (environ 0,010), donc ce n’est pas une vraie différence. Les deux profondeurs donnent des résultats aussi bons sur de nouveaux billets. Choisissez la profondeur 5 : elle est plus simple (31 feuilles plutôt que 59), plus facile à lire et un peu plus stable. La règle : parmi les modèles à moins d’un écart-type du meilleur, choisissez le plus simple.

Récapitulatif

  • Sous-apprentissage : deux scores bas et proches (biais élevé). Surapprentissage : grand écart entre le score d’entraînement et le score de CV (variance élevée).
  • L’arbre sans limite a 2 210 feuilles pures : AP d’entraînement de 1,000, AP en CV de 0,137. Son score pour un billet passe de 0 à 1 selon les billets d’entraînement.
  • Un hyperparamètre est un réglage que vous choisissez avant l’entraînement : max_depth, min_samples_leaf, C. Le modèle apprend ses paramètres; vous choisissez ses hyperparamètres par validation croisée sur les données d’entraînement. La meilleure profondeur est 6 (0,258 ± 0,010), et la meilleure taille de feuille est 100 (0,278 ± 0,017).
  • La régularisation garde un modèle plus simple. La régression logistique avec C = 1 n’a presque aucun écart; avec C = 0.0001, elle fait du sous-apprentissage (0,302).
  • Une courbe d’apprentissage montre si plus de données seraient utiles. Pour la régression logistique, elles ne le seraient pas. La prochaine étape consiste à améliorer les caractéristiques, dans le module 6.
  • Votre journal a dix lignes. E03, la régression logistique, reste la meilleure.

Ensuite, vous combinez plusieurs arbres en un seul modèle et voyez ce que cela coûte.

Leçon suivante : Les méthodes d'ensemble