Sto lavorando a un set di dati con etichetta binaria altamente squilibrato, in cui il numero di etichette vere è solo il 7% dall'intero set di dati. Ma una combinazione di funzionalità potrebbe produrre un numero di unità superiore alla media in un sottoinsieme.
Ad esempio, abbiamo il seguente set di dati con una singola funzione (colore):
180 campioni rossi - 0
20 campioni rossi - 1
300 campioni verdi - 0
100 campioni verdi - 1
Possiamo costruire un semplice albero decisionale:
(color)
red / \ green
P(1 | red) = 0.1 P(1 | green) = 0.25
P (1) = 0,2 per il set di dati complessivo
Se eseguo XGBoost su questo set di dati, è possibile prevedere probabilità non superiori a 0,25. Ciò significa che se prendo una decisione alla soglia 0,5:
- 0 - P <0,5
- 1 - P> = 0,5
Quindi otterrò sempre tutti i campioni etichettati come zero . Spero di aver chiaramente descritto il problema.
Ora, nel set di dati iniziale sto ottenendo il seguente diagramma (soglia sull'asse x):
Avere un massimo di f1_score alla soglia = 0,1. Ora ho due domande:
- dovrei anche usare f1_score per un set di dati di tale struttura?
- è sempre ragionevole utilizzare la soglia 0,5 per mappare le probabilità sulle etichette quando si utilizza XGBoost per la classificazione binaria?
Aggiornare. Vedo che l'argomento attira un certo interesse. Di seguito è riportato il codice Python per riprodurre l'esperimento rosso / verde utilizzando XGBoost. Produce effettivamente le probabilità previste:
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
import numpy as np
X0_0 = np.zeros(180) # red - 0
Y0_0 = np.zeros(180)
X0_1 = np.zeros(20) # red - 1
Y0_1 = np.ones(20)
X1_0 = np.ones(300) # green - 0
Y1_0 = np.zeros(300)
X1_1 = np.ones(100) # green - 1
Y1_1 = np.ones(100)
X = np.concatenate((X0_0, X0_1, X1_0, Y1_1))
Y = np.concatenate((Y0_0, Y0_1, Y1_0, Y1_1))
# reshaping into 2-dim array
X = X.reshape(-1, 1)
import xgboost as xgb
xgb_dmat = xgb.DMatrix(X_train, label=y_train)
param = {'max_depth': 1,
'eta': 0.01,
'objective': 'binary:logistic',
'eval_metric': 'error',
'nthread': 4}
model = xgb.train(param, xg_mat, 400)
X0_sample = np.array([[0]])
X1_sample = np.array([[1]])
print('P(1 | red), predicted: ' + str(model.predict(xgb.DMatrix(X0_sample))))
print('P(1 | green), predicted: ' + str(model.predict(xgb.DMatrix(X1_sample))))
Produzione:
P(1 | red), predicted: [ 0.1073855]
P(1 | green), predicted: [ 0.24398108]
xgboost
supporta pesi di classe, l'OP dovrebbe giocare con quelli se lui non è soddisfatto della metrica che vuole massimizzare.