web-dev-qa-db-fra.com

Classification non équilibrée à l'aide de RandomForestClassifier dans sklearn

J'ai un jeu de données où les classes sont déséquilibrées. Les classes sont "1" ou "0", où le rapport de la classe "1": "0" est 5: 1. Comment calculer l'erreur de prédiction pour chaque classe et les poids de rééquilibrage en conséquence dans Random Forest, un peu comme dans le lien suivant: http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home. htm # balance

32
mlo

Vous pouvez passer l'argument de pondération d'échantillon à Random Forest méthode d'ajustement

sample_weight : array-like, shape = [n_samples] or None

Poids d'échantillonnage. Si aucune, les échantillons sont pondérés de manière égale. Splits cela créerait des nœuds enfants avec un poids net nul ou négatif sont ignoré lors de la recherche d'une scission dans chaque nœud. Dans le cas de classification, les scissions sont également ignorées si elles aboutissent à un classe unique ayant un poids négatif dans l'un des nœuds enfants.

Dans les versions antérieures, il existait une méthode preprocessing.balance_weights permettant de générer des pondérations pour des échantillons donnés, de sorte que les classes soient uniformément réparties. Il est toujours là, dans le pré-traitement._weights module interne, mais toujours utilisable, mais est déconseillé et sera supprimé dans les prochaines versions. Je ne sais pas les raisons exactes pour cela.

Mettre à jour

Quelques éclaircissements, car vous semblez confus. L'utilisation de sample_weight est simple, une fois que vous vous rappelez que son but est d'équilibrer les classes cibles dans le jeu de données d'apprentissage. Autrement dit, si vous avez X comme observations et y comme classes (étiquettes), alors len(X) == len(y) == len(sample_wight) et chaque élément du tableau sample witght 1-d représente le poids pour une paire (observation, label) correspondante. Pour votre cas, si la classe 1 est représentée 5 fois comme la classe 0 et que vous équilibrez les distributions des classes, vous pouvez utiliser des méthodes simples. 

sample_weight = np.array([5 if i == 0 else 1 for i in y])

attribuer un poids de 5 à toutes les instances de 0 et un poids de 1 à toutes les instances de 1. Voir le lien ci-dessus pour une fonction d'évaluation de poids balance_weights un peu plus astucieuse.

44
alko

C'est vraiment dommage que la méthode "fit" de sklearn ne permette pas de spécifier une mesure de performance à optimiser. Personne autour de nous ne semble comprendre, s’interroger ou s’intéresser à ce qui se passe réellement lorsque l’on appelle la méthode fit sur un échantillon de données lors de la résolution d’une tâche de classification.

Nous (utilisateurs du paquet scikit learn) restons silencieux avec la suggestion d’utiliser indirectement la recherche sur grille croisée avec une méthode de notation spécifique adaptée aux ensembles de données non équilibrés dans l’espoir de tomber sur un ensemble de paramètres/métaparamètres qui produit le score approprié de l’ASC ou de la F1.

Mais réfléchissez-y: on dirait que la méthode "en forme", appelée sous le capot, optimise toujours la précision. En fin de compte, si nous voulons maximiser le score F1, GridSearchCV nous donne le "modèle avec le meilleur F1 de tous les modes avec la meilleure précision". N'est-ce pas idiot? Ne vaudrait-il pas mieux optimiser directement les paramètres du modèle pour un score maximal de F1? Rappelez-vous le bon vieux paquetage Matlab ANNs, dans lequel vous pouvez définir la métrique de performance souhaitée sur RMSE, MAE, et ce que vous voulez, étant donné que le calcul du gradient est également défini. Pourquoi le choix de la métrique de performance est-il silencieusement omis de sklearn?

Du moins, pourquoi n’existe-t-il pas une option simple pour attribuer automatiquement des pondérations aux instances de classe afin de résoudre les problèmes de jeux de données non équilibrés? Pourquoi devons-nous calculer les poids manuellement? En outre, dans de nombreux livres/articles d’apprentissage automatique, j’ai vu des auteurs vanter le manuel de Sklearn comme étant génial, sinon la meilleure source d’information sur le sujet. Pas vraiment? Pourquoi les ensembles de données non équilibrés posent-ils un problème (ce qui est évidemment d'une importance capitale pour les scientifiques des données) alors même nulle part dans la documentation? ... Je réponds à ces questions aux contributeurs de Sklearn, s'ils le lisent. Ou quiconque connaissant les raisons de le faire est le bienvenu pour commenter et clarifier les choses.

METTRE À JOUR

Depuis scikit-learn 0.17, il existe une option class_weight = 'pondérée' que vous pouvez au moins transmettre à certains classificateurs:

Le mode «équilibré» utilise les valeurs de y pour ajuster automatiquement poids inversement proportionnels aux fréquences de classe dans les données d'entrée comme n_samples/(n_classes * np.bincount (y)).

7
Anatoly Alekseev

Si la classe de la majorité est 1 et la classe de la minorité est 0 et que leur ratio est de 5: 1, le tableau sample_weight devrait être:

sample_weight = np.array([5 if i == 1 else 1 for i in y])

Notez que vous n'inversez pas les ratios. Ceci s'applique également à class_weights. Le plus grand nombre est associé à la classe majoritaire.

2
Meena Mani

Utilisez le paramètre class_weight='balanced' 

D'après la documentation de Sklearn: Le mode symétrique utilise les valeurs de y pour ajuster automatiquement les poids inversement proportionnels aux fréquences de classe dans les données d'entrée sous la forme n_samples / (n_classes * np.bincount(y))

0
negas