Dados multiclasses desbalanceados com o XGBoost

19

Eu tenho 3 classes com esta distribuição:

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

E eu estou usando xgboostpara classificação. Eu sei que existe um parâmetro chamado scale_pos_weight.

Mas como ele é tratado no caso 'multiclass' e como posso defini-lo corretamente?

shda
fonte

Respostas:

18

scale_pos_weighté usado para classificação binária como você afirmou. É uma solução mais generalizada para lidar com classes desequilibradas. Uma boa abordagem ao atribuir um valor scale_pos_weighté:

sum(negative instances) / sum(positive instances)

Para o seu caso específico, há outra opção para ponderar pontos de dados individuais e levar em consideração seus pesos ao trabalhar com o booster, e permitir que a otimização ocorra em relação aos pesos para que cada ponto seja representado igualmente. Você só precisa usar:

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

Você pode definir os pesos como quiser e, ao fazê-lo, pode até lidar com desequilíbrios nas classes, bem como desequilíbrios entre diferentes classes.

Kerem T
fonte
> A abordagem bom quando atribuir um valor a scale_pos_weight é: soma (casos negativos) / soma (casos positivos)
lcrmorin
1
Eu vejo esse conselho em todos os lugares e faz sentido atribuir um peso maior à classe menos representada. No entanto, tenho dificuldade em encontrar uma fonte para discutir esse valor exato. Eu entendo a intuição por trás desse valor específico (equilibrar a amostra), mas suspeito que exista uma troca de variação em algum lugar, que faria você querer considerar um peso menor.
Lcrmorin
6

Esta resposta de @KeremT está correta. Eu forneço um exemplo para aqueles que ainda têm problemas com a implementação exata.

weightO parâmetro no XGBoost é por instância e não por classe. Portanto, precisamos atribuir o peso de cada classe a suas instâncias, o que é a mesma coisa.

Por exemplo, se tivermos três classes desequilibradas com proporções

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

Seus pesos seriam (dividindo a menor classe por outras)

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

Então, se os dados de treinamento forem

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

nós construímos o weightvetor da seguinte maneira:

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

Todo mundo se depara com essa questão ao lidar com o problema de classificação multiclasse desequilibrada usando o XGBoost em R. Eu também!

Eu estava procurando um exemplo para entender melhor como aplicá-lo. Investiu quase uma hora para encontrar o link mencionado abaixo. Para todos aqueles que procuram um exemplo, aqui vai -

/datascience//a/9493/37156

Obrigado wacax

Krithi07
fonte
0

Basta atribuir cada instância dos seus dados de trem com o peso da classe. Primeiro obtenha os pesos da classe com o class_weight.compute_class_weightsklearn e atribua a cada linha dos dados do trem o peso apropriado.

Suponho aqui que os dados do trem tenham a coluna 'classe' contendo o número da classe. Também assumi que existem nb_classes que são de 1 a 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)
Firas Omrane
fonte