Respostas:
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.
Esta resposta de @KeremT está correta. Eu forneço um exemplo para aqueles que ainda têm problemas com a implementação exata.
weight
O 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 weight
vetor 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
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 -
Obrigado wacax
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_weight
sklearn 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)