Une suite de questions oui / non sur les variables, qui mène à une décision. L'arbre se lit comme une procédure : par exemple, un client qui a appelé le support plus de 5 fois est à risque. On l'utilise quand les équipes doivent comprendre, vérifier et appliquer les règles elles-mêmes.
Le jeu « Qui est-ce ? » : à chaque tour, on pose la question qui élimine le plus de mauvaises pistes.
L'algorithme teste chaque variable et chaque seuil possible (plus de 2 appels au support ? contrat mensuel ?) et garde celui qui sépare le mieux partants et fidèles, au sens de l'indice de Gini.
Chaque groupe obtenu est redécoupé de la même façon, jusqu'à une profondeur maximale ou un effectif minimum par feuille.
Un arbre trop profond apprend le bruit. On coupe les branches qui n'améliorent pas assez le modèle, selon un paramètre de complexité.
Un nouveau client descend l'arbre question par question. La feuille où il arrive donne sa classe et la part de partants observée dans ce groupe.
Ancienneté, nombre d'appels au support, montant mensuel, type de contrat, incidents des 3 derniers mois. Et la colonne à prédire : le client est-il parti ?
Huit feuilles au plus, chacune décrite par une règle et un taux de départ. Sur le jeu d'exemple, les clients qui ont appelé le support plus de 5 fois partent près de 2 fois sur 3, contre 22 % en moyenne.
On compare le taux de départ de chaque feuille entre entraînement et test. Une règle qui annonce 70 % à l'entraînement et 30 % en test a été apprise par cœur : on ne la transmet pas aux équipes.
Les trois premiers empêchent l'arbre d'apprendre par cœur. Noms donnés pour R (rpart) et Python (scikit-learn).
Profondeur maximale. Trois niveaux donnent huit règles au plus, quatre niveaux seize : au-delà, plus personne ne les lit.
Nombre minimum de clients par feuille. Fixé à 50, il évite les règles bâties sur une poignée de cas.
Complexité : une branche n'est gardée que si elle améliore assez le modèle. Même principe, échelles différentes. En R, printcp() affiche l'erreur en validation croisée pour choisir où élaguer.
Poids des classes. Avec class_weight="balanced", une feuille est étiquetée 1 dès que son taux de départ dépasse la moyenne de la base, et non plus 50 %.
# Churn clients : arbre de décision (CART) en R
library(rpart)
clients <- read.csv("clients_churn.csv")
clients$churn <- factor(clients$churn)
clients$contrat <- factor(clients$contrat)
set.seed(42)
idx <- sample(nrow(clients), round(0.7 * nrow(clients)))
train <- clients[idx, ]
test <- clients[-idx, ]
arbre <- rpart(churn ~ anciennete + appels_support + montant + contrat + incidents_3m,
data = train, method = "class",
control = rpart.control(maxdepth = 3, minbucket = 50, cp = 0.001))
# Élagage : on garde le cp qui minimise l'erreur en validation croisée (xerror)
printcp(arbre)
arbre <- prune(arbre, cp = arbre$cptable[which.min(arbre$cptable[, "xerror"]), "CP"])
# Les règles : effectif, classe prédite et part de partants (yprob) par nœud
print(arbre)
# Chaque feuille : taux prévu (entraînement) en nom, taux observé en test en valeur
proba <- predict(arbre, newdata = test, type = "prob")[, "1"]
print(round(tapply(test$churn == "1", round(proba, 2), mean), 2))
# Churn clients : arbre de décision (CART) en Python
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_text
from sklearn.model_selection import train_test_split
clients = pd.read_csv("clients_churn.csv")
X = pd.get_dummies(clients[["anciennete", "appels_support", "montant", "contrat", "incidents_3m"]], dtype=float)
y = clients["churn"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# class_weight="balanced" rééquilibre les classes (partants et fidèles pèsent autant) :
# l'arbre obtenu peut donc différer de celui de R
arbre = DecisionTreeClassifier(max_depth=3, min_samples_leaf=50, class_weight="balanced", random_state=42)
arbre.fit(X_train, y_train)
# Les règles : « class: 1 » = taux de départ supérieur à la moyenne
print(export_text(arbre, feature_names=list(X.columns)))
# Taux de départ par feuille, dans l'ordre de lecture des règles
feuilles = pd.DataFrame({
"taux_train": y_train.groupby(arbre.apply(X_train)).mean(),
"taux_test": y_test.groupby(arbre.apply(X_test)).mean(),
"clients_test": y_test.groupby(arbre.apply(X_test)).size()})
print(feuilles.round(2))
C'est une mesure du mélange dans un groupe : 0 si tous les clients ont la même issue, 0,5 au maximum avec deux classes à parts égales. À chaque découpage, CART choisit la question qui fait le plus baisser ce mélange. Il ne faut pas le confondre avec le coefficient de Gini utilisé en économie ou en scoring.
En limitant sa croissance : profondeur maximale, effectif minimum par feuille, puis élagage par le paramètre de complexité. Ces réglages se choisissent en regardant la performance sur des données de validation, jamais sur les données d'entraînement.
CART découpe toujours en deux branches et traite classification comme régression. C4.5 choisit ses questions avec le ratio de gain d'information et peut créer une branche par modalité. CHAID s'appuie sur des tests du khi-deux et découpe en plusieurs branches à la fois.
Des centaines d'arbres entraînés sur des tirages différents qui votent. Bien plus précise et stable, mais illisible.
Voir la fiche → l'autre modèle lisibleDes coefficients au lieu de règles. Plus stable, et meilleure quand l'effet d'une variable est progressif.
Voir la fiche → le cousin marketingUn arbre qui découpe en plusieurs branches à la fois selon des tests du khi-deux. Très utilisé en études.
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