Метрика f1_score в молнии

Я хочу обучить модель LGG с пользовательской метрикой: f1_score с weighted средний.

Я просмотрел расширенные примеры lightgbm и обнаружил, что в них реализована пользовательская функция двоичной ошибки. Я реализовал как подобную функцию для возврата f1_score, как показано ниже.

def f1_metric(preds, train_data):

    labels = train_data.get_label()

    return 'f1', f1_score(labels, preds, average='weighted'), True

Я пытался тренировать модель, передавая feval параметр как f1_metric как показано ниже.

evals_results = {}

bst = lgb.train(params, 
                     dtrain, 
                     valid_sets= [dvalid], 
                     valid_names=['valid'], 
                     evals_result=evals_results, 
                     num_boost_round=num_boost_round,
                     early_stopping_rounds=early_stopping_rounds,
                     verbose_eval=25, 
                     feval=f1_metric)

Тогда я получаю ValueError: Found input variables with inconsistent numbers of samples:

Обучающий набор передается в функцию, а не в проверочный набор.

Как я могу настроить так, чтобы набор проверки был пройден, а f1_score возвращен.?

1 ответ

Решение

Документы немного сбивают с толку. При описании сигнатуры функции, которую вы передаете feval, они вызывают ее параметры preds и train_data, что немного вводит в заблуждение.

Но, кажется, работает следующее:

from sklearn.metrics import f1_score

def lgb_f1_score(y_hat, data):
    y_true = data.get_label()
    y_hat = np.round(y_hat) # scikits f1 doesn't like probabilities
    return 'f1', f1_score(y_true, y_hat), True

evals_result = {}

clf = lgb.train(param, train_data, valid_sets=[val_data, train_data], valid_names=['val', 'train'], feval=lgb_f1_score, evals_result=evals_result)

lgb.plot_metric(evals_result, metric='f1')

Чтобы использовать несколько пользовательских метрик, определите одну общую функцию пользовательских метрик, как описано выше, в которой вы вычисляете все метрики и возвращаете список кортежей.

Редактировать: Исправлен код, конечно, если F1 больше, лучше установить True.

Что касается ответов Тоби:

def lgb_f1_score(y_hat, data):
    y_true = data.get_label()
    y_hat = np.round(y_hat) # scikits f1 doesn't like probabilities
    return 'f1', f1_score(y_true, y_hat), True

Я предлагаю изменить часть y_hat на это:

y_hat = np.where(y_hat < 0.5, 0, 1)  

Причина: я использовал y_hat = np.round(y_hat) и fonud, чтобы во время обучения модель lightgbm иногда (очень маловероятно, но все же изменение) будет рассматривать наше предсказание y как мультиклассовое, а не двоичное.

Мое предположение: иногда прогноз y будет небольшим или достаточно большим, чтобы округлить его до отрицательного значения или 2? Я не уверен, но когда я изменил код с помощью np.where, ошибка исчезла.

Потратил мне утро, чтобы понять эту ошибку, хотя я не совсем уверен, что решение np.where хорошее.

Другие вопросы по тегам