Accueil / Factory / Algos ML / SMOTE (données déséquilibrées) — factory / algos ML / préparation des données

SMOTE DONNÉES DÉSÉQUILIBRÉES.

Quand 7 % des assurés ont un sinistre, un modèle apprend vite à dire « aucun sinistre » à tout le monde. SMOTE crée des exemples synthétiques de la classe rare en interpolant entre ses cas réels, pour rééquilibrer l'entraînement. Utile, mais souvent surestimé : une simple pondération des classes fait fréquemment aussi bien.

PréparationDonnées déséquilibréesClasse rareClassificationNiveau : intermédiaire

FICHE D'IDENTITÉ

notes sur 5 · usage entreprise
PerformanceAugmente le rappel au seuil par défaut, rarement l'AUC
InterprétabilitéPrincipe simple : des points entre voisins de la classe rare
VitesseRapide sur des milliers de lignes, plus lent sur des millions
Facilité de réglageNombre de voisins et taux de suréchantillonnage à tester
Tolérance aux données brutesVariables numériques mises à l'échelle, catégorielles à part
EN 30 SECONDES

Dans un sondage où un groupe est sous-représenté, on ne se contente pas de recopier ses réponses : on crée des profils intermédiaires entre des répondants proches.

1. On prend un cas de la classe rare

Un assuré sinistré, décrit par ses variables mises à l'échelle.

2. On choisit un de ses voisins

Parmi ses k plus proches voisins sinistrés (5 par défaut), on en tire un au hasard.

3. On crée un point entre les deux

Le nouvel exemple est placé au hasard sur le segment qui relie les deux cas. On répète jusqu'à la proportion voulue, en général l'équilibre.

LE CAS MÉTIER

classe rare · assurance / fraude / churn / maintenance
EN ENTRÉE

Un portefeuille auto très déséquilibré

Âge du conducteur, puissance, bonus-malus, durée d'observation. Environ 7 % des contrats ont eu un sinistre. L'objectif : repérer à la souscription les profils à surveiller.

EN SORTIE

Un modèle qui ose signaler la classe rare

Sans correction, au seuil de 50 %, le modèle ne signale presque aucun contrat. Avec SMOTE, il en signale beaucoup plus et repère une bonne part des sinistrés, au prix de nombreuses fausses alertes. La pondération des classes donne un résultat très proche.

CE QU'ON MESURE

Rappel, précision, et l'AUC comme garde-fou

On compare rappel et précision au seuil retenu. L'AUC, qui mesure le classement, bouge très peu avec SMOTE : le rééquilibrage déplace surtout le seuil. C'est le signe qu'un simple ajustement du seuil aurait pu suffire.

QUAND LE SORTIR, QUAND L'ÉVITER

OUI

  • Classe rare et modèle qui la sacrifie au seuil par défaut
  • Modèle sans option de pondération des classes
  • Variables numériques continues, où une interpolation a du sens
  • Comparaison systématique avec class_weight et un ajustement de seuil

NON

  • Avant la séparation entraînement / test : les points synthétiques contaminent l'évaluation
  • Variables catégorielles codées en 0 / 1 : SMOTE crée des valeurs absurdes, utiliser SMOTENC
  • Besoin de probabilités calibrées : SMOTE les gonfle, il faut les recalibrer
  • Boosting ou forêt avec pondération disponible : class_weight ou scale_pos_weight sont plus simples
LES 4 RÉGLAGES QUI COMPTENT

Noms donnés pour R (smotefamily) et Python (imbalanced-learn).

K / k_neighbors

Nombre de voisins de la classe rare parmi lesquels on tire. 5 par défaut. Plus petit, les points restent près des cas réels ; plus grand, ils s'étalent davantage.

dup_size / sampling_strategy

Quantité d'exemples créés. Viser l'équilibre parfait n'est pas obligatoire : un ratio de 1 pour 3 ou 1 pour 2 suffit souvent.

Mise à l'échelle

SMOTE calcule des distances : sans mise à l'échelle, la variable aux plus grandes valeurs décide seule des voisins.

Pipeline

SMOTE doit être appliqué dans chaque pli de validation croisée, sur l'entraînement seulement. En Python, le Pipeline d'imbalanced-learn le garantit.

LE CODE MINIMAL

jeu d'exemple : sinistres.csv ↓
# Assurés sinistrés, classe rare : SMOTE en R
library(smotefamily)

contrats <- read.csv("sinistres.csv")
contrats$sinistre <- as.integer(contrats$nb_sinistres > 0)   # environ 7 % de sinistrés
vars <- c("age_conducteur", "puissance_cv", "bonus_malus", "exposition")

set.seed(42)
idx <- sample(nrow(contrats), round(0.7 * nrow(contrats)))
# SMOTE mesure des distances : mise à l'échelle avec les paramètres de l'entraînement
X_train <- scale(contrats[idx, vars])
X_test <- as.data.frame(scale(contrats[-idx, vars], center = attr(X_train, "scaled:center"), scale = attr(X_train, "scaled:scale")))
y_test <- contrats$sinistre[-idx]

# Sinistrés synthétiques créés sur l'entraînement seulement, jusqu'à l'équilibre
equilibre <- SMOTE(X = as.data.frame(X_train), target = contrats$sinistre[idx], K = 5, dup_size = 0)$data
equilibre$class <- as.integer(equilibre$class)
cat("Part de sinistrés après SMOTE :", round(mean(equilibre$class), 2), "\n")

brut <- glm(class ~ ., data = data.frame(X_train, class = contrats$sinistre[idx]), family = binomial)
avec_smote <- glm(class ~ ., data = equilibre, family = binomial)

# Au seuil de 50 % : part des vrais sinistrés repérés (rappel) et volume signalé
for (m in list(brut, avec_smote)) {
  pred <- predict(m, X_test, type = "response") > 0.5
  cat("Rappel :", round(mean(pred[y_test == 1]), 2), "| part des contrats signalés :", round(mean(pred), 2), "\n")
}

QUESTIONS FRÉQUENTES

Faut-il appliquer SMOTE avant ou après la séparation train / test ?

Après, et sur l'entraînement uniquement. Appliqué avant, il crée des points synthétiques à partir de cas qui se retrouvent ensuite dans le test : l'évaluation devient trop optimiste. En validation croisée, il faut le refaire dans chaque pli.

SMOTE ou class_weight ?

Les deux corrigent le déséquilibre et donnent souvent des résultats proches. class_weight ne crée aucune donnée et ne coûte rien ; c'est le premier essai. SMOTE devient intéressant quand le modèle n'accepte pas de pondération, ou quand il améliore nettement les résultats en validation.

SMOTE améliore-t-il toujours le modèle ?

Non. Il augmente en général le rappel au seuil par défaut, mais l'AUC change peu, car le classement des cas change peu. Choisir un seuil plus bas sur le modèle d'origine donne souvent un résultat équivalent, sans données artificielles.

LES ALGOS VOISINS

à comparer avant de choisir
le modèle rééquilibré ici

Régression logistique

Avec class_weight, elle compense le déséquilibre sans créer de données.

Voir la fiche →
quand les exemples manquent

Isolation Forest

Détecte les cas atypiques sans étiquettes : utile quand la classe rare est à peine observée.

Voir la fiche →
gère le déséquilibre seul

XGBoost

Le paramètre scale_pos_weight rééquilibre les classes sans suréchantillonnage.

Voir la fiche →
— formation

Passer de la fiche à la pratique

Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.

Voir les formations →