Comprendre le SMOTE et éviter ses pièges

Plus qu’une simple ligne de code, le SMOTE est un algorithme qu’il faut utiliser de la bonne façon. Dans cet article nous détaillons son fonctionnement et précisons cinq erreurs fréquentes des projets de Machine Learning qui intègrent le SMOTE.
Apprentissage avec SMOTE
Sommaire

Cet article est le deuxième de notre série consacrée aux données déséquilibrées.

Imbalanced data, que faire ?

Dans le premier article de cette série, nous avons vu que la présence de données déséquilibrées dans les problèmes de classification pose de nombreuses difficultés, notamment lors de la modélisation. L’une des solutions pour traiter les données déséquilibrées est de les “rééquilibrer”. Ce type d’approches – appelées data-level solutions – se décline sous 2 formes principales :

  • Le sous-échantillonnage (undersampling). Parmi les individus majoritaires, on en retire une partie afin d’accorder plus d’importance aux individus minoritaires. Cette approche permet de diminuer la redondance des informations apportées par le grand nombre d’individus majoritaires.
  • Le sur-échantillonnage (oversampling). Le nombre d’individus minoritaires est augmenté pour qu’ils aient plus d’importance lors de la modélisation. Différentes solutions sont possibles, comme le “clonage” aléatoire ou le SMOTE.

Le sous-échantillonnage et le sur-échantillonnage peuvent être combinés pour corriger le déséquilibre plus efficacement.

Qu’est-ce que le SMOTE ?

Le SMOTE, acronyme pour Synthetic Minority Oversampling TEchnique [1], est une méthode de suréchantillonnage des observations minoritaires. Pour éviter de réaliser un simple clonage des individus minoritaires, le SMOTE se base sur un principe simple : générer de nouveaux individus minoritaires qui ressemblent aux autres, sans être strictement identiques. Cela permet de densifier de façon plus homogène la population d’individus minoritaires.

C’est sur ces données transformées, auxquelles on a ajouté de faux individus synthétiques, que l’on va ensuite entraîner un modèle de Machine learning.

N.b. : Pour nos articles sur le SMOTE, nous restons dans le cadre de la classification binaire (présenté dans le premier article), et considérons que les individus minoritaires de nos données sont les individus positifs.

Créer des observations synthétiques

Pour créer un individu synthétique, les étapes définies dans l’algorithme du SMOTE sont les suivantes :

  1. Sélectionner aléatoirement une observation minoritaire “initiale”.
  2. Identifier ses k plus proches voisins parmi les observations minoritaires (où k est un paramètre défini par l’utilisateur).
  3. Choisir aléatoirement l’un des k plus proches voisins.
  4. Générer aléatoirement un coefficient $0<\alpha<1$.
  5. Créer un nouvel individu entre l’observation initiale et le plus proche voisin choisi, selon la valeur du coefficient . Par exemple, si $\alpha = 0.5$, le nouvel individu sera positionné à mi-chemin entre l’observation initiale et le plus proche voisin choisi.

Ces étapes sont répétées jusqu’à ce que le nombre d’individus générés atteigne une valeur définie par l’utilisateur. Leur succession est décrite dans l’animation suivante :

Les paramètres du SMOTE

Dans l’algorithme du SMOTE, deux paramètres essentiels interviennent :

  • k, le nombre de plus proches voisins (nearest neighbors) candidats pour la création d’un nouvel individu.

Ce paramètre a un effet sur la distribution des individus synthétiques dans l’espace, et donc sur la performance du modèle qui sera entraîné après le SMOTE. Sa valeur optimale dépend de la structure des données.

SMOTE - Paramètre k

Figure 2. Influence du choix de k sur le SMOTE.
A gauche, résultats du SMOTE avec k=7. A droite, résultats du SMOTE avec k=2.
Le choix de k=7 n’est pas adapté car des individus minoritaires synthétiques (en jaune) sont créés dans la zone violette, qui n’est pas représentative des minoritaires réels (en rouge).

Schématiquement, si les individus minoritaires originaux sont répartis sous forme de groupes de taille inférieure à $n$ individus et que l’on utilise $k > n$, les individus générés risquent d’être positionnés entre les groupes de minoritaires réels. Ils ne sont alors pas représentatifs des données réelles et risquent de diminuer les performances du modèle.

  • Le nombre d’observations synthétiques à générer. Ce paramètre est exprimé sous la forme d’un taux d’observations minoritaires à atteindre, noté $\alpha_{os}$ (os pour “oversampling“) :

The ratio is expressed as

\begin{equation*}\alpha_{os} = \frac{N_{rm}}{N_{M}}\end{equation*}

where $N_{rm}$ is the number of samples in the minority class after resampling and N_{M} is the number of samples in the majority class. [2]

Notons que plus le ratio est élevé par rapport au ratio initial de vos données, plus l’algorithme devra produire d’individus synthétiques et plus son temps de calcul sera long.

Illustrons le rôle de ce paramètre avec un histogramme  :

SMOTE - Paramètre alpha

Figure 3. Structure des données avant/après le SMOTE.

En ordonnée : nombre d’individus dans les données

Exemple : considérons des données avec 6 observations minoritaires et 100 majoritaires. Si $\alpha_{os}=20%$, l’algorithme du SMOTE générera 14 observations minoritaires, pour atteindre le ratio $\frac{6+14}{100}=20%$.

Ces deux paramètres déterminent la structure des données d’apprentissage du modèle et doivent être optimisés. Nous y revenons plus loin.

Utiliser le SMOTE avec Python ou R

Pour appliquer le SMOTE à un jeu de données, utilisons son implémentation Python avec le package imbalanced-learn : imblearn.over_sampling.SMOTE [2]. Sous R, le SMOTE est disponible grâce à la fonction SMOTE du package DMwR [3].

Le code Python pour “smoter” des données numériques est assez simple. Imbalanced-learn reprend le formalisme de sklearn et il suffit :

  • De définir une instance de SMOTE avec les paramètres suivants :
    • k_neighbors (k), le nombre de plus proches voisins
    • sampling_strategy ($\alpha_{os}$), le taux d’observations minoritaires à atteindre.
  • D’appeler la fonction fit_resample sur les données X et y.
				
					# Importation du package
from imblearn.over_sampling import SMOTE
 
# Définition de l'instance SMOTE
sm = SMOTE(k_neighbors=3, sampling_strategy=0.75)
 
# Application du SMOTE aux données
X_res, y_res = sm.fit_resample(X, y)

				
			

Les vecteurs rééchantillonnés (X_res et y_res) contiennent les individus déjà présents dans X et y, plus les individus synthétiques.

Examinons le résultat sur un jeu de données réel

(avec k = 3  et  $\alpha_{os} = 0.75$) :

SMOTE - Résultats SMOTE numérique

Figure 4. Application du SMOTE à un couple de variables numériques. Les points bleus sont les individus majoritaires, les triangles verts les individus minoritaires et les triangles violets les individus synthétiques générés par SMOTE.

Cette illustration montre à la fois les forces et les faiblesses du SMOTE : il a bien densifié les zones où sont localisés les individus minoritaires, mais a aussi généré des individus synthétiques dans des régions qui sont moins pertinentes.

Réduire l’overfitting grâce au SMOTE

Comme indiqué dans l’article sur les données déséquilibrées, l’utilisation du SMOTE permet de réduire le surapprentissage (ou overfitting) du modèle.

Pour le montrer, considérons d’abord les prédictions d’un modèle entraîné sur les données brutes :

SMOTE - Surapprentissage sans SMOTE

Figure 5. Surapprentissage du modèle sans utilisation du SMOTE. La couleur rouge désigne les zones de fortes probabilités prédites par le modèle entraîné sur les données Train. En s’entraînant sur les données originales, le modèle apprend des “points” de prédiction très limités et performe faiblement sur les données Test.

Le modèle prédit uniformément une probabilité très faible sur la majorité de l’espace, à l’exception de quelques zones très réduites, celles où sont situées les données Train. Ces zones sont trop restreintes pour permettre de bien prédire les données Test, qui sont souvent situées juste à côté, mais dans une zone de faible probabilité. Le modèle a donc une bonne performance sur Train, mais médiocre sur Test : il a surappris les données et a une forte variance.

Comparons ces prédictions avec celles d’un modèle entraîné sur les données rééchantillonnées par le SMOTE :

SMOTE - Apprentissage par zones SMOTE

Figure 6. Diminution visible du surapprentissage grâce au SMOTE. En s’entraînant sur les données suréchantillonnées grâce au SMOTE, le modèle apprend des zones de prédiction plus larges, cohérentes avec les données de Test.
En zoomant sur la zone encadrée en rouge, le triangle entouré en jaune donne l’exemple d’un individu mieux prédit grâce au SMOTE car il appartient à l’enveloppe convexe de plusieurs points minoritaires présents dans les données Train.

Les zones de forte probabilité prédites par le modèle sont à présent plus larges, et permettent de couvrir l’espace dans lequel se trouvent les données Test. Ainsi le point entouré en jaune se voit bien attribuer une probabilité élevée, alors qu’il était dans une zone de probabilité faible avec le premier modèle. Le modèle a une performance similaire sur Train et Test : il a une faible variance.

En prenant une métrique de performance adaptée à la classification des données déséquilibrées, l’aire sous la courbe Precision-Recall (AUC-PR), confirmons la meilleure performance du deuxième modèle sur les données de test :

SMOTE - Performance AUC PR avant après

Figure 7. Augmentation de l’AUC-Precision-Recall du modèle grâce au SMOTE.

La performance du modèle après utilisation du SMOTE est ici presque 3 fois supérieure à la performance du modèle sans SMOTE.

Cinq règles d’or pour utiliser SMOTE correctement

Optimiser les paramètres du SMOTE

Conserver les deux paramètres du SMOTE à leur valeur par défaut peut fortement limiter le potentiel de l’algorithme pour votre modèle. Le nombre optimal de plus proches voisins et le meilleur taux d’individus minoritaires à atteindre dépendent en effet largement de la structure de vos données !

La meilleure solution pour trouver les bons paramètres est d’optimiser l’ensemble “SMOTE + Modèle”, en fournissant à votre optimiseur (bayesian search, grid search, random search…) à la fois les paramètres du SMOTE et les hyperparamètres du modèle (nous précisons cette méthode dans notre formation sur les données déséquilibrées).

Normaliser les variables numériques avant le SMOTE

Le SMOTE repose sur le calcul de distances euclidiennes entre les points. Il est donc influencé par l’échelle de vos variables. Pour que toutes les variables soient toutes traitées de la même manière, il est nécessaire de faire un scaling avant d’utiliser le SMOTE. Ce point est détaillé dans le quatrième article de cette série.

Retraiter les variables discrètes après le SMOTE

Le SMOTE génère les individus synthétiques de façon continue entre les individus réels, ce qui pose problème pour les variables numériques discrètes. Cela conduit en effet à créer des individus minoritaires avec des valeurs qui n’existent pas dans les données réelles. Le modèle a tendance à cibler ces individus, ce qui pose de multiples problèmes.

Ce point est également détaillé dans le quatrième article de notre série.

Ne jamais encoder les variables catégorielles en numériques 

Nous n’avons jusqu’ici considéré que des variables numériques car le SMOTE classique ne permet pas de traiter les variables catégorielles. Pour traiter des données mixtes (mixed data), c’est-à-dire contenant à la fois des variables numériques et catégorielles, il faut utiliser une variante du SMOTE : le SMOTE-NC, pour SMOTE-Nominal Continuous.

Une pratique fréquente est à éviter absolument : il ne faut pas encoder les variables catégorielles en variables numériques – que ce soit par du one-hot encoding, du label encoding ou autre. Encoder ces variables pour ensuite appliquer le SMOTE classique génère un traitement inadapté [4] (p.72). L’utilisation du SMOTE-NC permet de traiter les variables catégorielles de façon plus adaptée, sans avoir à réaliser de preprocessing au préalable.

Le traitement correct des catégorielles avec SMOTE-NC est détaillé dans le troisième article de cette série.

Ne jamais utiliser SMOTE sur les données validation/test

L’utilisation du SMOTE permet d’améliorer l’entraînement du modèle mais il faut faire attention à son utilisation dans les autres étapes de modélisation, et notamment la validation et le test.

Pour évaluer un modèle de Machine Learning, il faut séparer le jeu de données en un ensemble d’entraînement (les données train), un ensemble de validation et un de test (voir [5] pour plus d’informations). Les données de validation et de test sont utilisées pour valider statistiquement le modèle de Machine Learning obtenu. 

La validation ([6]) consiste à s’assurer que le modèle sera performant sur de futures données. Il est donc essentiel que les données de validation et de test soient le plus proche possible des données réelles futures. C’est pourquoi il ne faut pas utiliser SMOTE dessus. Si le SMOTE est appliqué aux données validation/test, un “faux” signal généré sur les données d’entraînement rééchantillonnées sera aussi généré dans les données de validation/test. Cela donne une performance élevée qui ne se concrétisera pas dans la réalité.

D’une manière générale, la plupart des métriques de classification étant sensibles au déséquilibre de classes, si les données de validation ne contiennent pas le même taux de positifs que les données réelles alors la performance ne sera pas représentative de la performance réelle.

Conclusion

Le SMOTE est une technique très utile pour rééquilibrer les données numériques en entrée d’un modèle de Machine Learning. Il permet d’éviter le surapprentissage du modèle en densifiant les individus minoritaires de façon homogène et peut améliorer significativement les performances de vos modèles.

Pour utiliser le SMOTE sans danger, il est indispensable de se souvenir des cinq règles suivantes  :

  • Les paramètres optimaux du SMOTE dépendent de vos données et doivent donc être optimisés. Le plus simple est de les optimiser en même temps que votre modèle.
  • Les variables numériques doivent être normalisées.
  • Les variables discrètes doivent être retraitées entre le SMOTE et le modèle.
  • Les variables catégorielles doivent être conservées telles quelles et ne pas être encodées.
  • Le SMOTE est réservé à l’entraînement du modèle et ne doit surtout pas être appliqué aux données de validation et de test.

L’article suivant de cette série aborde l’une de ces règles, en détaillant le traitement optimal des variables catégorielles.

 

Références :

  1. N. V. Chawla, K. W. Bowyer, L. O. Hall, et W. P. Kegelmeyer, « SMOTE: Synthetic Minority Over-sampling Technique », J. Artif. Intell. Res., vol. 16, p. 321‑357, juin 2002.

  2. « SMOTE — Version 0.8.1 ». https://imbalanced-learn.org/stable/references/generated/imblearn.over_sampling.SMOTE.html

  3. « SMOTE function – RDocumentation ». https://www.rdocumentation.org/packages/DMwR/versions/0.4.1/topics/SMOTE

  4. C. Tremblay, « Mémoire présenté devant l’ENSAE ParisTech pour l’obtention du diplôme de la filière Actuariat et l’admission à l’Institut des Actuaires le 22/02/2017 », p. 123.

  5. « Jeux d’entrainement, de validation et de test », Wikipédia. 8 septembre 2021. [En ligne]. Disponible sur: https://fr.wikipedia.org/w/index.php?title=Jeux_d%27entrainement,_de_validation_et_de_test&oldid=186167325

  6. P. I. Good et J. W. Hardin, Common errors in statistics (and how to avoid them), Fourth edition. Hoboken, New Jersey: Wiley, 2012.

Sommaire

Voir aussi

Voir aussi

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *