Une régression qui prédit une probabilité plutôt qu'un chiffre : risque de départ, de défaut, d'achat. Chaque variable reçoit un coefficient qui se traduit en « cote multipliée par tant ». C'est la référence du scoring en banque et en assurance, parce que chaque score se justifie devant un client ou un régulateur.
Une grille de points : tant de points par appel au support, tant de points en moins par mois d'ancienneté. On additionne, puis une courbe en S transforme le total en probabilité.
Comme en régression linéaire, chaque variable reçoit un poids. La somme pondérée donne un score sans limite, positif ou négatif.
La fonction logistique, une courbe en S, ramène ce score entre 0 et 1. Un score nul donne 50 %, un score très positif s'approche de 100 %.
L'algorithme ajuste les poids pour que les clients partis reçoivent des probabilités hautes et les fidèles des probabilités basses. C'est le maximum de vraisemblance.
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 ?
Chaque client reçoit une probabilité de départ. Les odds ratios expliquent pourquoi : sur le jeu d'exemple, un contrat mensuel multiplie la cote de départ par plus de 2 par rapport à un contrat annuel, et chaque appel au support par environ 1,5.
L'AUC vérifie que les partants reçoivent un score plus haut que les fidèles : 0,5 correspond au hasard, 1 à la perfection (ici entre 0,75 et 0,80). Les probabilités étant en général bien calibrées, on peut aussi chiffrer le gain attendu d'une campagne de rétention.
Peu de paramètres, mais chacun change la lecture du modèle. Noms donnés pour R (glm) et Python (scikit-learn).
scikit-learn freine les coefficients par défaut (pénalité L2, C = 1). Plus C est petit, plus le frein est fort. glm() n'en applique aucune, il faut glmnet en R. Sur quelques milliers de lignes, l'écart reste faible.
Sans mise à l'échelle, un odds ratio se lit par unité : par mois, par euro. Avec StandardScaler dans un Pipeline, il se lit par écart-type : les variables deviennent comparables et la pénalité les traite à égalité.
Les coefficients d'une variable catégorielle se lisent par rapport à une modalité de base, ici le contrat annuel. En R, relevel() permet d'en changer.
Le modèle donne une probabilité, pas une décision. Le seuil de 50 % n'a rien d'obligatoire : on le fixe selon le coût d'une action de rétention et la valeur d'un client conservé.
# Churn clients : régression logistique en R
clients <- read.csv("clients_churn.csv")
clients$contrat <- factor(clients$contrat) # référence : annuel
set.seed(42)
idx <- sample(nrow(clients), round(0.7 * nrow(clients)))
train <- clients[idx, ]
test <- clients[-idx, ]
modele <- glm(churn ~ anciennete + appels_support + montant + contrat + incidents_3m,
data = train, family = binomial)
# Odds ratios et intervalles à 95 % : facteur multiplicatif sur la cote de départ
print(round(exp(cbind(OR = coef(modele), confint.default(modele)))[-1, ], 3))
# Score de départ sur les clients jamais vus
proba <- predict(modele, newdata = test, type = "response")
# AUC calculée en R base (formule des rangs)
rangs <- rank(proba)
n1 <- sum(test$churn == 1)
n0 <- sum(test$churn == 0)
auc <- (sum(rangs[test$churn == 1]) - n1 * (n1 + 1) / 2) / (n1 * n0)
cat("AUC test :", round(auc, 3), "\n")
# Churn clients : régression logistique en Python
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
clients = pd.read_csv("clients_churn.csv")
# drop_first : le contrat annuel sert de référence
X = pd.get_dummies(clients[["anciennete", "appels_support", "montant", "contrat", "incidents_3m"]], drop_first=True, 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)
modele = LogisticRegression(max_iter=1000)
modele.fit(X_train, y_train)
# Odds ratios : facteur multiplicatif sur la cote de départ
print(pd.Series(np.exp(modele.coef_[0]), index=X.columns).round(3))
# Score de départ sur les clients jamais vus
proba = modele.predict_proba(X_test)[:, 1]
print("AUC test :", round(roc_auc_score(y_test, proba), 3))
Un odds ratio de 1,5 pour les appels au support signifie que chaque appel supplémentaire multiplie la cote de départ par 1,5, les autres variables étant fixes. La cote est la probabilité de partir divisée par la probabilité de rester. Au-dessus de 1, le risque augmente, en dessous il baisse. C'est la cote qui est multipliée, pas la probabilité.
Le modèle fait bien une régression : il estime un score continu, le logarithme de la cote, comme une somme pondérée des variables. La classification n'intervient qu'à la fin, quand on applique un seuil à la probabilité obtenue.
La Random Forest gagne souvent quelques points d'AUC, car elle capte seule les seuils et les interactions. La régression logistique reste préférable quand il faut expliquer chaque score, documenter le modèle pour un régulateur ou le recoder dans un outil métier.
Des centaines d'arbres qui votent. Capte seule les seuils et les interactions, mais ne se lit pas ligne à ligne.
Voir la fiche → le format bancaireUne régression logistique dont les variables sont découpées en tranches et les coefficients convertis en points.
Voir la fiche → l'autre modèle lisibleDes règles si / alors au lieu de coefficients. Plus parlant pour le terrain, moins stable.
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