ML Atlas

Le machine learning en partant de zéro · Leçon 5.2 · 27 sur 33 leçons prêtes · 10 min

Ensembles : pourquoi une forêt bat un seul arbre

En bref

Un ensemble combine de nombreux modèles imparfaits dont les erreurs se compensent en partie. Ainsi, une forêt aléatoire gagne en exactitude et en stabilité.

Échauffement Deux questions de leçons précédentes. Une minute, sans jamais bloquer la leçon.
De la leçon 5.1 : Arbres de décision : le jeu des vingt questions Un arbre sans limite de profondeur atteint une exactitude d’entraînement presque parfaite. Pourquoi est-ce un signal d’alarme ?

Voir la réponse

Bonne réponse : Il a sans doute appris par cœur des passagers d’entraînement isolés, donc il généralisera moins bien

Un arbre qui se divise jusqu’à ce que chaque feuille soit pure colle au bruit de l’échantillon d’entraînement, le signe classique du surapprentissage.

De la leçon 4.6 : Pipeline : du tableau à la prédiction Que fait la validation croisée sur l’entraînement quand le scaler est dans le pipeline ?

Voir la réponse

Bonne réponse : Il réajuste le scaler dans chaque fold, seulement sur la partie d’apprentissage de ce fold

Un pipeline est un seul modèle, donc dans chaque fold toute la machine apprend de zéro. Le fold qui joue le test ne touche ni le scaler ni le kNN.

Demandez à une seule personne combien de bonbons contient un grand bocal, et son estimation sera peut-être très loin du compte. Demandez à quelques centaines de personnes et faites la moyenne de leurs estimations : le résultat est souvent étonnamment proche. Aucun des participants n’est devenu plus malin. Leurs erreurs allaient simplement dans des directions différentes et se sont annulées. Peut-on construire un modèle de la même façon, à partir de beaucoup de modèles médiocres ?

Prédisez, puis vérifiez Une forêt aléatoire composée d’un seul arbre (échantillon aléatoire de passagers, 2 variables au choix à chaque division) et un arbre ordinaire poussé jusqu’au bout : lequel fait mieux sur les passagers de test ?
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 : L’arbre ordinaire

La forêt à un arbre classe correctement 70,9 % des passagers de test et l’arbre ordinaire 73,9 % : un arbre unique rendu aléatoire est même plus faible. Seule la moyenne de nombreux arbres aide : 10 arbres donnent 76,1 % et 100 arbres 76,9 %.

À vous de jouer

  • Commencez avec le curseur du nombre d’arbres sur un et comparez la forêt à l’arbre unique. Avec un seul arbre, la « forêt » n’est qu’un arbre rendu aléatoire.
  • Montez progressivement le nombre d’arbres et observez l’exactitude de test de la forêt. Repérez où elle cesse de s’améliorer nettement.
  • Continuez d’augmenter le nombre d’arbres. L’exactitude de la forêt se met-elle à baisser, comme celle de l’arbre profond dans la leçon 9, ou se stabilise-t-elle ?
  • Comparez l’arbre unique et la grande forêt. Auquel confieriez-vous un cas que vous n’avez jamais vu ?

L’idée en quelques mots

Voyons maintenant ce que vous venez de manipuler, en termes simples.

Un ensemble est un modèle fait de nombreux modèles dont on combine les prédictions, par vote pour des catégories ou par moyenne pour des nombres. L’ensemble le plus célèbre est la forêt aléatoire (random forest), présentée par Leo Breiman en 2001 : un grand nombre d’arbres de décision, chacun poussé un peu différemment, qui votent ensemble.

La leçon 9 s’est terminée sur une faiblesse des arbres : un petit changement dans les données peut produire un arbre complètement différent. Un arbre profond isolé est comme un parieur trop sûr de lui – vif, mais imprévisible. Une forêt transforme ce comportement imprévisible en atout. Si chaque arbre fait des erreurs différentes, le vote majoritaire a raison plus souvent qu’un arbre typique.

Pourquoi ça marche

Le mot clé est différentes. Faire la moyenne de modèles identiques ne change rien ; leurs erreurs sont les mêmes. Une forêt aléatoire rend ses arbres différents de deux façons. D’abord, chaque arbre est entraîné sur un échantillon bootstrap : des lignes tirées au hasard dans le jeu d’entraînement avec remise, si bien que chaque arbre voit un jeu de données légèrement différent, où certaines lignes sont répétées et d’autres absentes. Cette idée s’appelle le bagging. Ensuite, à chaque division, un arbre ne peut choisir que parmi un sous-ensemble aléatoire des variables, pour que tous les arbres ne s’appuient pas sur la même variable la plus forte.

La statistique nous dit combien cela aide. Si l’erreur de chaque arbre a une variance σ² et que les erreurs de deux arbres quelconques ont une corrélation ρ, la moyenne de n arbres a pour variance

ρ·σ² + (1 − ρ)·σ² / n

Le second terme diminue quand on ajoute des arbres et disparaît pour un grand n. Le premier, non : c’est la part de l’erreur que tous les arbres partagent. Voilà pourquoi le hasard compte. Moins les arbres se ressemblent (plus ρ est petit), plus la forêt y gagne – et c’est aussi pourquoi ajouter des arbres au-delà d’un certain point n’apporte presque plus rien.

Conséquence agréable : ajouter des arbres ne fait pas apprendre davantage par cœur à la forêt. Chaque nouvel arbre rejoint simplement le vote, et les prédictions de la forêt se stabilisent au lieu de s’emballer. Le prix de plus d’arbres, c’est du temps de calcul, pas du surapprentissage.

Il existe une seconde grande famille d’ensembles, le boosting, qui fonctionne à l’inverse : au lieu d’arbres indépendants qui votent, il construit de petits arbres l’un après l’autre, chacun corrigeant les erreurs des précédents. Les arbres à gradient boosting gagnent souvent sur les données tabulaires, y compris dans de nombreuses compétitions Kaggle.

Erreur fréquente

Un ensemble ne peut pas créer une information absente des variables. Si chaque arbre est trompé de la même façon – par exemple par une variable qui laisse fuir la réponse, ou par des données qui ne représentent pas les personnes pour qui l’on prédit –, le vote ne fait que répéter la même erreur avec plus d’assurance. Le terme corrélé de la formule, c’est exactement cette erreur partagée. Autre erreur : croire que plus d’arbres aident toujours ; une fois les gains aplatis, les arbres supplémentaires ne coûtent que du temps. Enfin, une forêt est bien plus difficile à lire qu’un arbre unique ; vous échangez l’organigramme contre de l’exactitude.

Les arbres et les forêts découpent l’espace des variables en boîtes. Dans la prochaine leçon, nous rencontrons un modèle qui courbe au contraire sa frontière en douceur : le réseau de neurones.

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. Pourquoi faire la moyenne de nombreux arbres n’aide-t-il que si les arbres diffèrent ?
Voir la réponse

Bonne réponse : Des arbres identiques font des erreurs identiques, donc la moyenne n’annule rien

Les erreurs ne s’annulent que si elles vont dans des directions différentes ; la part partagée de l’erreur reste après la moyenne.

2. Qu’est-ce qu’un échantillon bootstrap ?
Voir la réponse

Bonne réponse : Des lignes tirées au hasard dans le jeu d’entraînement avec remise

Le tirage avec remise donne à chaque arbre un jeu de données légèrement différent, ce qui fait diverger les arbres de façon utile.

3. Vous faites passer une forêt aléatoire de 300 à 3 000 arbres. Quel est l’effet le plus probable ?
Voir la réponse

Bonne réponse : L’exactitude change à peine, mais l’entraînement devient beaucoup plus long

Une fois la part indépendante de l’erreur moyennée, plus d’arbres ajoutent du calcul, mais peu d’exactitude et aucun apprentissage par cœur supplémentaire.

À retenir

  • Un ensemble combine de nombreux modèles ; les erreurs qui vont dans des directions différentes s’annulent.
  • Une forêt aléatoire rend ses arbres différents grâce aux échantillons bootstrap et aux sous-ensembles aléatoires de variables.
  • L’erreur partagée par tous les arbres ne disparaît pas avec la moyenne, donc les gains s’aplatissent quand on ajoute des arbres.
  • Plus d’arbres coûtent du temps mais ne font pas surapprendre une forêt ; le boosting est une seconde famille d’ensembles, séquentielle.

Pour aller plus loin : formule, code, pratique

Les maths

Une forêt fait la moyenne des prédictions de n arbres. Supposons que l’erreur de chaque arbre ait pour variance σ², et que les erreurs de deux arbres quelconques aient pour corrélation ρ. La moyenne a alors pour variance :

  • Var = ρ·σ² + (1 − ρ)·σ² / n
  • Le second terme, (1 − ρ)·σ² / n, est la part qui diminue quand on ajoute des arbres.
  • Le premier terme, ρ·σ², est le plancher : l’erreur que tous les arbres partagent. Aucun nombre d’arbres ne la supprime.
  • Pour des arbres indépendants (ρ = 0), la variance baisse comme σ² / n. Pour des arbres identiques (ρ = 1), elle ne baisse pas du tout.
  • Les échantillons bootstrap et les sous-ensembles aléatoires de variables existent pour faire baisser ρ.
  • La moyenne ne réduit que la part de variance de l’erreur. Le biais que tous les arbres partagent reste, donc une forêt d’arbres biaisés est toujours biaisée.
En code (Python)

Une vraie forêt aléatoire sur les passagers du Titanic, avec 2 variables essayées à chaque coupure. Elle utilise le même découpage que le code de la leçon 9, pas celui du lab, donc les nombres diffèrent des 73,9 % et 76,9 % du lab. Le notebook lié sous la sortie télécharge lui-même les données.

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

df = pd.read_csv("data/raw/titanic.csv")
X = pd.DataFrame({"female": (df["sex"] == "female").astype(int)}).join(df[["pclass", "age", "sibsp", "parch", "fare"]])
Xtr, Xte, ytr, yte = train_test_split(X, df["survived"], test_size=0.3, stratify=df["survived"], random_state=1)
Xtr, Xte = Xtr.fillna({"age": Xtr["age"].median()}), Xte.fillna({"age": Xtr["age"].median()})  # médiane d'entraînement pour les deux
tree = DecisionTreeClassifier(random_state=0).fit(Xtr, ytr)
print(f"one full tree: test {tree.score(Xte, yte):.3f}")
for n in (1, 10, 100, 500):
    forest = RandomForestClassifier(n_estimators=n, max_features=2, random_state=0).fit(Xtr, ytr)
    print(f"forest of {n:3d}: test {forest.score(Xte, yte):.3f}")
oob = RandomForestClassifier(n_estimators=500, max_features=2, oob_score=True, random_state=0).fit(Xtr, ytr)
print(f"out-of-bag estimate (500 trees, training rows only): {oob.oob_score_:.3f}")

Sortie

one full tree: test 0.780
forest of   1: test 0.754
forest of  10: test 0.806
forest of 100: test 0.802
forest of 500: test 0.802
out-of-bag estimate (500 trees, training rows only): 0.809

Un arbre aléatoire seul (0,754) est moins bon qu’un arbre complet (0,780), mais le vote bat les deux : 10 arbres donnent 0,806, et 100 et 500 arbres donnent 0,802. La forêt se stabilise au lieu de baisser comme l’arbre profond de la leçon 9. L’estimation hors sac, 0,809, est calculée à partir des seules lignes d’entraînement.

Pour les praticiens
  • Commencez par les valeurs par défaut, par exemple 100 à 500 arbres, puis vérifiez sur des données de validation où la courbe s’aplatit. Au-delà, des arbres supplémentaires ne coûtent que du temps et de la mémoire.
  • Réglez le nombre de variables essayées par coupure et la profondeur ou la taille des feuilles avant de régler le nombre d’arbres. Ils changent la corrélation entre les arbres.
  • Utilisez le score hors sac (oob_score=True) comme estimation gratuite : chaque ligne d’entraînement n’est prédite que par les arbres dont l’échantillon bootstrap l’a laissée de côté, et ces prédictions sont notées. Ne réglez rien sur le jeu de test.
  • Vérifiez d’où viennent les données avant de vous fier au vote. Si une variable qui fuit trompe chaque arbre, la forêt répète l’erreur avec plus d’assurance.
  • Une forêt est difficile à lire. Les importances des variables donnent un classement approximatif, mais elles favorisent les variables à nombreuses valeurs distinctes ; l’importance par permutation sur des données mises de côté est une vérification plus sûre.

Aller plus loin dans l’Atlas

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