Extra Trees, pour Extremely Randomized Trees, pousse l'idée de la Random Forest plus loin : les seuils de découpage sont tirés au hasard au lieu d'être optimisés. Les arbres sont plus rapides à construire et plus différents entre eux. Sur des données bruitées, le résultat est souvent aussi bon qu'une Random Forest, parfois meilleur.
Une forêt où chaque arbre coupe au jugé plutôt qu'au millimètre. Pris un par un, ils sont grossiers ; ensemble, leurs approximations se compensent.
À chaque nœud, comme en Random Forest, on ne considère qu'une partie des variables (ou toutes, selon le réglage).
Pour chaque variable candidate, un seul seuil est tiré au hasard entre son minimum et son maximum dans le nœud. On garde le meilleur de ces découpages aléatoires.
Par défaut, chaque arbre voit toutes les lignes, sans tirage avec remise. La moyenne des arbres donne la prédiction, comme pour une forêt.
Âge du conducteur, puissance, bonus-malus, zone, nombre de sinistres et durée d'observation du contrat. La cible est la fréquence : sinistres par année assurée, chaque contrat pesant selon sa durée.
Sur le jeu d'exemple, l'âge du conducteur est de loin la variable la plus importante. Les 20 % de contrats jugés les plus risqués ont une fréquence observée d'environ 0,28 sinistre par an, contre 0,06 pour les 20 % jugés les moins risqués.
L'événement est rare : l'erreur ligne à ligne n'a pas de sens. On classe les contrats par risque prédit, on les regroupe en quintiles et on vérifie que la fréquence observée monte bien d'une tranche à l'autre.
Noms donnés pour R (ranger) et Python (scikit-learn).
Nombre d'arbres. Comme en forêt, plus il y en a, plus c'est stable. Le hasard étant plus fort, il en faut un peu plus : 300 à 1 000.
Nombre de variables candidates à chaque nœud. En régression, scikit-learn les prend toutes par défaut : seul le seuil est aléatoire.
Taille minimale des feuilles. Pour un événement rare comme un sinistre, des feuilles larges (100 contrats ou plus) évitent de suivre le bruit.
Par défaut, Extra Trees n'utilise pas de tirage avec remise. ranger en fait un par défaut, même en mode extratrees ; replace = FALSE et sample.fraction = 1 retrouvent la méthode d'origine.
# Fréquence de sinistres auto : Extra Trees en R
library(ranger)
contrats <- read.csv("sinistres.csv")
contrats$zone <- factor(contrats$zone)
contrats$frequence <- contrats$nb_sinistres / contrats$exposition # sinistres par année assurée
set.seed(42)
idx <- sample(nrow(contrats), round(0.7 * nrow(contrats)))
train <- contrats[idx, ]
test <- contrats[-idx, ]
# splitrule = "extratrees" : seuils tirés au hasard ; case.weights fait tirer
# les contrats en proportion de leur durée d'observation
modele <- ranger(frequence ~ age_conducteur + puissance_cv + bonus_malus + zone, data = train,
num.trees = 500, splitrule = "extratrees", num.random.splits = 1, mtry = 4,
min.bucket = 100, case.weights = train$exposition, importance = "impurity", seed = 42)
print(sort(importance(modele), decreasing = TRUE))
# Fréquence observée par quintile de risque prédit (1 = contrats jugés les moins risqués)
pred <- predict(modele, data = test)$predictions
quintile <- cut(rank(pred, ties.method = "first"), 5, labels = 1:5)
print(round(tapply(test$nb_sinistres, quintile, sum) / tapply(test$exposition, quintile, sum), 3))
# Fréquence de sinistres auto : Extra Trees en Python
import pandas as pd
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.model_selection import train_test_split
contrats = pd.read_csv("sinistres.csv")
X = pd.get_dummies(contrats[["age_conducteur", "puissance_cv", "bonus_malus", "zone"]], dtype=float)
y = contrats["nb_sinistres"] / contrats["exposition"] # sinistres par année assurée
poids = contrats["exposition"] # un contrat vu 3 mois pèse 4 fois moins
X_train, X_test, y_train, y_test, p_train, p_test = train_test_split(X, y, poids, test_size=0.3, random_state=42)
# Seuils de découpage tirés au hasard ; feuilles larges car l'événement est rare
modele = ExtraTreesRegressor(n_estimators=500, min_samples_leaf=100, max_features=1.0, n_jobs=-1, random_state=42)
modele.fit(X_train, y_train, sample_weight=p_train)
print(pd.Series(modele.feature_importances_, index=X.columns).sort_values(ascending=False).round(3))
# Fréquence observée par quintile de risque prédit (1 = contrats jugés les moins risqués)
test = pd.DataFrame({"quintile": pd.qcut(modele.predict(X_test), 5, labels=[1, 2, 3, 4, 5]),
"sinistres": y_test * p_test, "exposition": p_test})
somme = test.groupby("quintile", observed=True)[["sinistres", "exposition"]].sum()
print((somme["sinistres"] / somme["exposition"]).round(3))
La Random Forest cherche le meilleur seuil pour chaque variable candidate et entraîne chaque arbre sur un tirage avec remise. Extra Trees tire les seuils au hasard et utilise par défaut toutes les lignes. Les arbres sont plus rapides à construire et plus différents entre eux.
Parfois, souvent pas de beaucoup. Sur des données bruitées, le hasard supplémentaire réduit le surapprentissage ; sur d'autres, la forêt classique garde un léger avantage. Le coût de calcul étant faible, on teste les deux.
Extremely Randomized Trees, arbres extrêmement aléatoires. La méthode a été publiée par Pierre Geurts, Damien Ernst et Louis Wehenkel en 2006.
Seuils optimisés et tirage avec remise. Un peu plus lente, performance très proche.
Voir la fiche → la référence actuarielleModélise directement un nombre de sinistres avec l'exposition. Moins souple, entièrement lisible.
Voir la fiche → souvent plus précisArbres construits en série pour corriger les erreurs. Plus fort, plus long à régler.
Voir la fiche →Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.
Nous utilisons des cookies de mesure d'audience et de suivi publicitaire pour comprendre la fréquentation du site et l'efficacité de nos annonces. Rien n'est déposé sans votre accord. En savoir plus