Может кто-нибудь помочь мне, как написать пользовательский счет F1 для классификации мультикласса в Python ???
Редактировать: я редактирую вопрос, чтобы дать лучшую картину того, что я хочу сделать
Это моя функция для пользовательской метрики оценки eval f1 для задачи мультикласса с 5 классами.
def evalerror(preds, dtrain):
labels = dtrain.get_label()
preds = preds.reshape(-1, 5)
preds = preds.argmax(axis = 1)
f_score = f1_score(preds, labels, average = 'weighted')
return 'f1_score', f_score, True
Примечание. Причина, по которой я изменяю форму, состоит в том, что истинное значение валидации имеет длину 252705, тогда как preds - это массив длиной 1263525, который в 5 раз больше фактического. Причина в том, что LGB выводит вероятности каждого класса для каждого прогноза.
Ниже я преобразую данные поезда и проверки в формат, который будет принимать LGB.
dtrain = lgb.Dataset(train_X, label= train_Y, free_raw_data = False)
dvalid = lgb.Dataset(valid_X, label= valid_Y, free_raw_data = False,
reference= dtrain)
Ниже приведена модель ЛГБ, которую я подгоняю к данным обучения. Как вы можете видеть, я передал пользовательскую функцию evalerror
в свою модель на feval
, а также данные проверки dvalid
, для которых я хочу увидеть оценку f1 во время тренировки.
Я тренирую модель в течение 10 итераций.
evals_result = {}
num_round = 10
lgb_model = lgb.train(params,
dtrain,
num_round,
valid_sets = dvalid,
feval = evalerror,
evals_result = evals_result)
Поскольку модель обучается в течение 10 раундов, показатель F1 для каждой итерации в наборе проверки отображается ниже, что неверно, поскольку я получаю около 0,18.
[1] valid_0's multi_logloss: 1.46839 valid_0's f1_score: 0.183719
[2] valid_0's multi_logloss: 1.35684 valid_0's f1_score: 0.183842
[3] valid_0's multi_logloss: 1.26527 valid_0's f1_score: 0.183853
[4] valid_0's multi_logloss: 1.18799 valid_0's f1_score: 0.183909
[5] valid_0's multi_logloss: 1.12187 valid_0's f1_score: 0.187206
[6] valid_0's multi_logloss: 1.06452 valid_0's f1_score: 0.187503
[7] valid_0's multi_logloss: 1.01437 valid_0's f1_score: 0.187327
[8] valid_0's multi_logloss: 0.97037 valid_0's f1_score: 0.187511
[9] valid_0's multi_logloss: 0.931498 valid_0's f1_score: 0.186957
[10] valid_0's multi_logloss: 0.896877 valid_0's f1_score: 0.18751
Но как только модель обучается за 10 итераций, я запускаю приведенный ниже код для прогнозирования на том же наборе проверки.
lgb_prediction = lgb_model.predict(valid_X)
lgb_prediction = lgb_prediction.argmax(axis = 1)
lgb_F1 = f1_score(lgb_prediction, valid_Y, average = 'weighted')
print("The Light GBM F1 is", lgb_F1)
The Light GBM F1 is 0.743250263548
Примечание: я не изменил здесь, как я сделал это в пользовательской функции, потому что lgb_model.predict()
выводит массив numpy (252705, 5)
Также обратите внимание, что я передаю valid_X
, а не dvalid
, потому что при прогнозировании нам придется передавать исходный формат, а не разреженный, как мы передаем в lgb.train()
Когда я прогнозирую тот же набор данных проверки, я получаю оценку F1 0,743250263548, что достаточно хорошо. Таким образом, я ожидаю, что результат проверки F1 на 10-й итерации будет таким же, как и прогноз, который я предсказал после обучения модели.
Может кто-нибудь помочь мне с тем, что я делаю неправильно. Спасибо