J'utilise scikit-learn dans mon programme Python pour effectuer certaines opérations d'apprentissage automatique. Le problème est que mon ensemble de données présente de graves problèmes de déséquilibre.
Quelqu'un connaît-il une solution de déséquilibre dans scikit-learn ou python en général? En Java, il y a le mécanisme SMOTE. Y a-t-il quelque chose de parallèle en python?
SMOTE n'est pas intégré à scikit-learn, mais des implémentations sont disponibles en ligne.
Ici , par exemple.
Il y en a un nouveau ici
https://github.com/scikit-learn-contrib/imbalanced-learn
Il contient de nombreux algorithmes dans les catégories suivantes, y compris SMOTE
Dans Scikit learn, il existe certaines techniques de correction de déséquilibre, qui varient en fonction de l'algorithme d'apprentissage utilisé.
Certains, comme Svm ou régression logistique , ont le paramètre class_weight
. Si vous instanciez une SVC
avec ce paramètre défini sur 'auto'
, chaque exemple de classe sera pondéré proportionnellement à l'inverse de sa fréquence.
Malheureusement, il n'y a pas d'outil de préprocesseur à cette fin.
J'ai trouvé une autre bibliothèque ici qui implémente le sous-échantillonnage ainsi que plusieurs techniques de sur-échantillonnage comprenant plusieurs implémentations SMOTE
et une autre qui utilise SVM
:
Étant donné que d’autres ont répertorié des liens vers la très populaire bibliothèque d’apprentissage déséquilibrée, je vais vous donner un aperçu de la façon de l’utiliser correctement, ainsi que certains liens.
https://imbalanced-learn.org/fr/stable/generated/imblearn.under_sampling.RandomUnderSampler.html
https://imbalanced-learn.org/fr/stable/generated/imblearn.over_sampling.RandomOverSampler.html
https://imbalanced-learn.readthedocs.io/fr/stable/generated/imblearn.over_sampling.SMOTE.html
https://imbalanced-learn.org/fr/stable/combine.html
Parmi les techniques courantes de suréchantillonnage et de sous-échantillonnage dans l'apprentissage déséquilibré, on peut citer imblearn.over_sampling.RandomOverSampler, imblearn.under_sampling.RandomUnderSampler et imblearn.SMOTE. Pour ces bibliothèques, un paramètre Nice permet à l’utilisateur de modifier le taux d’échantillonnage.
Par exemple, dans SMOTE, pour modifier le ratio, vous devez saisir un dictionnaire et toutes les valeurs doivent être supérieures ou égales à la classe la plus grande (SMOTE étant une technique de suréchantillonnage). La raison pour laquelle j'ai trouvé que SMOTE convenait mieux aux performances du modèle, d'après mon expérience, est probablement parce que RandomOverSampler duplique des lignes, ce qui signifie que le modèle peut commencer à mémoriser les données plutôt que de les généraliser à de nouvelles données. SMOTE utilise l'algorithme K-Nearest-Neighbours pour créer des points de données "similaires" aux points sous-échantillonnés.
Parfois, ce n’est pas une bonne pratique d’utiliser aveuglément SMOTE, en définissant le rapport sur sa valeur par défaut (même l’équilibre entre les classes) car le modèle peut surcharger une ou plusieurs des classes minoritaires, même si SMOTE utilise les voisins les plus proches pour effectuer des observations "similaires". De la même manière que vous réglez les hyperparamètres d’un modèle ML, vous réglez les hyperparamètres de l’algorithme SMOTE, tels que le ratio et/ou knn. Vous trouverez ci-dessous un exemple concret d'utilisation correcte de SMOTE.
REMARQUE: Il est essentiel que vous n'utilisiez pas SMOTE sur l'ensemble des données. Vous DEVEZ utiliser SMOTE sur le kit d’apprentissage uniquement (c’est-à-dire après la scission), puis validez sur le jeu de validation et les jeux de test pour voir si votre modèle SMOTE a exécuté vos autres modèles. Si vous ne le faites pas, il y aura des fuites de données et vous obtiendrez un modèle totalement non pertinent.
from collections import Counter
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE
import numpy as np
from xgboost import XGBClassifier
import warnings
warnings.filterwarnings(action='ignore', category=DeprecationWarning)
sm = SMOTE(random_state=0, n_jobs=8, ratio={'class1':100, 'class2':100, 'class3':80, 'class4':60, 'class5':90})
X_resampled, y_resampled = sm.fit_sample(X_normalized, y)
print('Original dataset shape:', Counter(y))
print('Resampled dataset shape:', Counter(y_resampled))
X_train_smote, X_test_smote, y_train_smote, y_test_smote = train_test_split(X_resampled, y_resampled)
X_train_smote.shape, X_test_smote.shape, y_train_smote.shape, y_test_smote.shape, X_resampled.shape, y_resampled.shape
smote_xgbc = XGBClassifier(n_jobs=8).fit(X_train_smote, y_train_smote)
print('TRAIN')
print(accuracy_score(smote_xgbc.predict(np.array(X_train_normalized)), y_train))
print(f1_score(smote_xgbc.predict(np.array(X_train_normalized)), y_train))
print('TEST')
print(accuracy_score(smote_xgbc.predict(np.array(X_test_normalized)), y_test))
print(f1_score(smote_xgbc.predict(np.array(X_test_normalized)), y_test))