Données multiclasses déséquilibrées avec XGBoost


20

J'ai 3 classes avec cette distribution:

Class 0: 0.1169
Class 1: 0.7668
Class 2: 0.1163

Et j'utilise xgboostpour la classification. Je sais qu'il y a un paramètre appelé scale_pos_weight.

Mais comment est-il géré pour le cas «multiclasse», et comment puis-je le configurer correctement?

Réponses:


18

scale_pos_weightest utilisé pour la classification binaire comme vous l'avez indiqué. Il s'agit d'une solution plus généralisée pour gérer les classes déséquilibrées. Une bonne approche lors de l'attribution d'une valeur à scale_pos_weightest la suivante:

sum(negative instances) / sum(positive instances)

Pour votre cas spécifique, il existe une autre option pour pondérer les points de données individuels et prendre en compte leurs poids tout en travaillant avec le booster, et laisser l'optimisation se produire concernant leurs poids afin que chaque point soit représenté de manière égale. Il vous suffit simplement d'utiliser:

xgboost.DMatrix(..., weight = *weight array for individual weights*)

Vous pouvez définir les pondérations comme vous le souhaitez et, ce faisant, vous pouvez même gérer les déséquilibres au sein des classes ainsi que les déséquilibres entre les différentes classes.


> Une bonne approche lors de l'attribution d'une valeur à scale_pos_weight est: sum (instances négatives) / sum (instances positives)
lcrmorin

1
Je vois ce conseil partout et il est logique d'attribuer un poids plus élevé à la classe la moins représentée. Cependant, j'ai du mal à trouver une source pour discuter de cette valeur exacte. J'ai l'intuition derrière cette valeur spécifique (équilibrer l'échantillon) mais je soupçonne qu'il y a un compromis de variance quelque part, qui vous donnerait envie de considérer un poids plus faible.
lcrmorin

7

Cette réponse de @KeremT est correcte. Je donne un exemple à ceux qui ont encore des problèmes avec la mise en œuvre exacte.

weightdans XGBoost est par instance et non par classe. Par conséquent, nous devons attribuer le poids de chaque classe à ses instances, ce qui est la même chose.

Par exemple, si nous avons trois classes déséquilibrées avec des ratios

class A = 10%
class B = 30%
class C = 60%

Leurs poids seraient (en divisant la plus petite classe par d'autres)

class A = 1.000
class B = 0.333
class C = 0.167

Ensuite, si les données d'entraînement sont

index   class
0       A
1       A
2       B
3       C
4       B

nous construisons le weightvecteur comme suit:

index   class    weight
0       A        1.000
1       A        1.000
2       B        0.333
3       C        0.167
4       B        0.333

5

Tout le monde tombe sur cette question lorsqu'il s'agit d'un problème de classification multiclasse déséquilibré en utilisant XGBoost dans R. Je l'ai fait aussi!

Je cherchais un exemple pour mieux comprendre comment l'appliquer. Investi près d'une heure pour trouver le lien mentionné ci-dessous. Pour tous ceux qui cherchent un exemple, voici -

/datascience//a/9493/37156

Merci wacax


0

Attribuez simplement à chaque instance de vos données de train son poids de classe. Obtenez d'abord les poids de classe avec class_weight.compute_class_weightde sklearn puis attribuez à chaque ligne des données du train son poids approprié.

Je suppose ici que les données du train ont la colonne «classe» contenant le numéro de classe. J'ai supposé aussi qu'il y a nb_classes qui vont de 1 à nb_classes.

from sklearn.utils import class_weight
class_weights = list(class_weight.compute_class_weight('balanced',
                                             np.unique(train['class']),
                                             train['class']))

w_array = np.ones(y_train.shape[0], dtype = 'float')
for i, val in enumerate(y_train):
    w_array[i] = class_weights[val-1]

xgb_classifier.fit(X, y, sample_weight=w_array)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.