Оценки Lightgbm для пользовательской функции потерь RMSE и встроенной RMSE различаются - PullRequest
0 голосов
/ 25 мая 2020

Для начала с пользовательских целевых функций для lightgbm я начал воспроизводить стандартную объективную RMSE. К сожалению, оценки разные. Мой пример основан на этом сообщении или github .
Grad и hess такие же, как в lightgbm source или как указано в ответе на следующий вопрос .
Что не так с пользовательской функцией RMSE?
Примечание: В этом примере финальная потеря кажется близкой, но траектория совсем другая. На других (более крупных) примерах я наблюдаю еще большие различия в окончательной потере.

import numpy as np
import matplotlib.pyplot as plt
from lightgbm import LGBMRegressor
import lightgbm 
from sklearn.datasets import  make_friedman1
from sklearn.model_selection import train_test_split

X, y = make_friedman1(n_samples=10000, n_features=7, noise=10.0, random_state=11)
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.20, random_state=42)

gbm2 = lightgbm.LGBMRegressor(objective='rmse', random_state=33, early_stopping_rounds = 5, n_estimators=10000)
gbm2.fit(X_train,  y_train, eval_set=[(X_valid, y_valid)], eval_metric='rmse', verbose=10)
gbm2eval = gbm2.evals_result_

def custom_RMSE(y_true, y_pred):
    residual = (y_pred - y_true)
    grad = residual
    hess = np.ones(len(y_true))
    return grad, hess

gbm3 = lightgbm.LGBMRegressor(random_state=33, early_stopping_rounds = 5, n_estimators=10000)
gbm3.set_params(**{'objective': custom_RMSE})
gbm3.fit(X_train,  y_train, eval_set=[(X_valid, y_valid)], eval_metric='rmse', verbose=10)
gbm3eval = gbm3.evals_result_

plt.plot(gbm2eval['valid_0']['rmse'],label='rmse')
plt.plot(gbm3eval['valid_0']['rmse'],label='custom rmse')
plt.legend()

eval_results для gbm2:

Training until validation scores don't improve for 5 rounds
[10]    valid_0's rmse: 10.214
[20]    valid_0's rmse: 10.044
[30]    valid_0's rmse: 10.0348
Early stopping, best iteration is:
[28]    valid_0's rmse: 10.028

eval_results для gbm3:

Training until validation scores don't improve for 5 rounds
[10]    valid_0's rmse: 11.5991 valid_0's l2: 134.539
[20]    valid_0's rmse: 10.2721 valid_0's l2: 105.516
[30]    valid_0's rmse: 10.0801 valid_0's l2: 101.608
[40]    valid_0's rmse: 10.0424 valid_0's l2: 100.849
Early stopping, best iteration is:
[44]    valid_0's rmse: 10.0351 valid_0's l2: 100.703

и здесь в виде графика: потери для стандартного RMSE и пользовательского RMSE

1 Ответ

0 голосов
/ 25 мая 2020

RMSE - это квадрат root MSE (среднеквадратичная ошибка):

MSE equation

Итак, если вы хотите минимизировать RMSE, вы должны изменить ваша функция custom_RMSE () для измерения квадратов остатков. Попробуйте:

def custom_RMSE(y_true, y_pred):
    squared_residual = (y_pred - y_true)**2
    grad = squared_residual
    hess = np.ones(len(y_true))
    return grad, hess

В любом случае функция custom_RMSE () не похожа на выдачу:

grad -> подобный массиву shape = [n_samples] или shape = [ n_samples * n_classes] (для мультиклассовой задачи) Значение производной первого порядка (градиент) для каждой точки выборки.

hess -> подобный массиву shape = [n_samples] или shape = [n_samples * n_classes] (для мультиклассовой задачи) Значение производной второго порядка (гессиана) для каждой точки выборки. Источник: https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.LGBMRegressor.html

...