Une explication qui répond à la question que tout le monde pose vraiment : que faudrait-il changer pour obtenir une autre décision ? « Votre crédit serait accordé avec 5 000 € d'apport en plus. » « Ce client resterait probablement s'il passait en contrat annuel. » On cherche le plus petit changement réaliste qui fait basculer la prédiction du modèle.
Un GPS qui annonce « vous arriverez en retard » est moins utile qu'un GPS qui dit « partez 10 minutes plus tôt et vous serez à l'heure ». Le contrefactuel transforme un verdict en action.
Le résultat souhaité : un risque de départ sous 25 %, un crédit accordé, un sinistre classé non suspect.
On fait varier ce qui peut réellement changer (type de contrat, remise, apport) et on fige le reste (âge, historique, ancienneté).
Parmi les scénarios qui atteignent la cible, on retient les plus proches de la situation actuelle, et plusieurs options différentes si possible.
Un modèle de churn a scoré la base. Le conseiller a devant lui un client en contrat mensuel à plus de 70 € par mois, avec un risque de départ de 45 %. Il peut proposer un autre type de contrat et une remise mensuelle jusqu'à 30 €.
Sur le jeu d'exemple, aucune remise jusqu'à 30 € ne fait passer ce client sous 25 % s'il reste en mensuel : le risque ne descend pas sous 33 %. Un passage en contrat annuel, sans remise, suffit : le risque prédit tombe à 13 %.
Un bon contrefactuel est atteignable, proche de la situation actuelle et plausible au vu des données. Le modèle décrit des corrélations, pas des causes : l'effet réel d'une offre se mesure ensuite par un test A/B.
Ici, une recherche simple sur une grille de scénarios. Pour plus de variables, les bibliothèques DiCE (Python) et counterfactuals (R) automatisent la recherche.
La liste des variables qu'on a le droit de modifier, et dans quel sens. C'est une décision métier, et la plus importante.
Le seuil de probabilité à atteindre ou la classe voulue. Un seuil trop ambitieux ne donne aucune solution ; un seuil trop proche du score actuel donne des solutions fragiles.
Comment comparer 10 € de remise et un changement de contrat ? On fixe une mesure de distance ou un coût en euros pour classer les options.
Plutôt qu'une seule réponse, proposer 2 ou 3 options différentes laisse le choix au client ou au conseiller.
# Que proposer pour qu'un client reste : contrefactuels en R
library(randomForest)
clients <- read.csv("clients_churn.csv")
clients$churn <- as.factor(clients$churn)
clients$contrat <- factor(clients$contrat)
set.seed(42)
modele <- randomForest(churn ~ anciennete + appels_support + montant + contrat + incidents_3m,
data = clients, ntree = 300, nodesize = 20)
# Le client étudié : contrat mensuel à plus de 70 €, risque de départ proche de 45 %
proba <- predict(modele, clients, type = "prob")[, "1"]
cible <- which(clients$contrat == "mensuel" & clients$montant > 70)
i <- cible[which.min(abs(proba[cible] - 0.45))]
print(clients[i, ])
cat("Risque actuel :", round(proba[i], 2), "\n")
# Scénarios sur les seuls leviers actionnables : type de contrat x remise mensuelle (0 à 30 €)
leviers <- expand.grid(contrat = levels(clients$contrat), remise = 0:30)
essais <- cbind(clients[rep(i, nrow(leviers)), c("anciennete", "appels_support", "montant", "incidents_3m")], leviers)
essais$montant <- essais$montant - essais$remise
essais$risque <- predict(modele, essais, type = "prob")[, "1"]
# Contrefactuels : pour chaque contrat, la plus petite remise qui fait passer le risque sous 25 %
# (un contrat absent du résultat : aucune remise jusqu'à 30 € ne suffit)
print(aggregate(remise ~ contrat, data = essais[essais$risque < 0.25, ], FUN = min))
# Que proposer pour qu'un client reste : contrefactuels en Python
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
clients = pd.read_csv("clients_churn.csv")
variables = ["anciennete", "appels_support", "montant", "contrat", "incidents_3m"]
X = pd.get_dummies(clients[variables], dtype=float)
modele = RandomForestClassifier(n_estimators=300, min_samples_leaf=20, random_state=42)
modele.fit(X, clients["churn"])
encode = lambda d: pd.get_dummies(d[variables], dtype=float).reindex(columns=X.columns, fill_value=0)
# Le client étudié : contrat mensuel à plus de 70 €, risque de départ proche de 45 %
proba = modele.predict_proba(X)[:, 1]
cible = (clients["contrat"] == "mensuel") & (clients["montant"] > 70)
i = clients.index[cible][np.argmin(np.abs(proba[cible] - 0.45))]
client = clients.loc[[i], variables]
print(client.to_string(index=False), "| risque actuel :", f"{proba[i]:.0%}")
# Scénarios sur les seuls leviers actionnables : type de contrat x remise mensuelle (0 à 30 €)
essais = pd.concat([client] * 93, ignore_index=True)
essais["contrat"] = ["mensuel", "annuel", "deux_ans"] * 31
essais["remise"] = np.repeat(np.arange(31), 3)
essais["montant"] = essais["montant"] - essais["remise"]
essais["risque"] = modele.predict_proba(encode(essais))[:, 1]
# Contrefactuel : pour chaque contrat, la plus petite remise qui fait passer le risque sous 25 %
for contrat in ["mensuel", "annuel", "deux_ans"]:
ok = essais[(essais["contrat"] == contrat) & (essais["risque"] < 0.25)]
if len(ok):
print(f"{contrat:8s} : remise de {ok['remise'].min()} €, risque {ok['risque'].iloc[0]:.0%}")
else:
print(f"{contrat:8s} : aucune remise jusqu'à 30 € ne suffit (risque mini {essais.loc[essais['contrat'] == contrat, 'risque'].min():.0%})")
C'est une explication de la forme « si telle variable avait eu telle valeur, la décision aurait été différente ». Elle indique le plus petit changement des données d'entrée qui fait basculer la prédiction du modèle. Le concept a été popularisé en 2017 par Wachter, Mittelstadt et Russell, dans le contexte du RGPD.
SHAP répartit une prédiction entre les variables : il dit ce qui pèse et dans quel sens. Le contrefactuel dit ce qu'il faudrait changer pour obtenir une autre décision. Les deux se complètent : SHAP pour comprendre, le contrefactuel pour agir.
Non. Elle décrit ce que le modèle prédirait, et le modèle a appris des corrélations. Les clients en contrat annuel partent moins, mais transférer un client mensuel vers l'annuel ne produira pas forcément le même effet. Seul un test contrôlé ou un modèle causal permet de mesurer l'effet réel.
Dit ce qui pousse le score vers le haut. Le contrefactuel dit ce qu'il faudrait changer pour le faire baisser.
Voir la fiche → l'autre explication localeApproche le modèle par une petite formule autour d'un individu. Descriptif, pas prescriptif.
Voir la fiche → l'effet causalMesure l'effet réel d'une action sur chaque client à partir d'un test. Le complément indispensable avant de généraliser une offre.
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