Проблема предсказания с пользовательской функцией потерь xgboost

Вопрос или проблема

У меня проблема с пользовательскими функциями потерь в xgboost: я не могу получить последовательные прогнозы. Другими словами, масштаб моих прогнозов не соответствует значениям, которые я хотел бы предсказать. Я попробовал многие пользовательские функции потерь, но всегда получаю одну и ту же проблему.

import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn.datasets import make_regression

n_samples_train = 500
n_samples_test = 100
n_features = 200

X, y = make_regression(n_samples_train, n_features, noise=10)
X_test, y_test = make_regression(n_samples_test, n_features, noise=10)

param = {'verbosity': 1,
          'max_depth': 12,
          'learning_rate': 0.01,
          'nthread': 3,
          }

dtrain = xgb.DMatrix(X, y)

best_nrounds = 50

bst_reglinear = xgb.train(param, 
                          dtrain, 
                          best_nrounds)

def reg_obj(preds, dtrain):
    y = dtrain.get_label()
    N = len(y)
    #residual = (preds-y).astype("float")
    grad = 2*preds-y
    hess = 2*N*np.ones(len(y))
    return grad, hess

bst_custom = xgb.train(param,
                        dtrain,
                        best_nrounds,
                        obj=reg_obj)

dtest = xgb.DMatrix(X_test)

pred = bst_reglinear.predict(dtest)
print(np.abs(pred).mean())

pred_custom = bst_custom.predict(dtest)
print(np.abs(pred_custom).mean())

Я думаю, что ваш градиент и гессиан неправильно посчитаны, попробуйте:

grad = 2*(preds-y)
hess = 2*np.ones(len(y))

Ответ или решение

Проблема, с которой вы столкнулись, связана с нестабильностью прогнозов при использовании пользовательской функции потерь (loss function) в XGBoost. Давайте проанализируем вашу ситуацию более подробно и обсудим, как это можно исправить.

Описание проблемы

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

Анализ пользовательской функции потерь

Ваша текущая реализация функции потерь выглядит следующим образом:

def reg_obj(preds, dtrain):
    y = dtrain.get_label()
    N = len(y)
    grad = 2*preds - y
    hess = 2*N*np.ones(len(y))
    return grad, hess

В этой реализации вы извлекаете метки y из dtrain, а затем вычисляете градиенты и гессианы. Исходная форма градиентов (grad) выглядит правильно, однако, при вычислении гессианов вы используете N, что может неправильно масштабировать ваши значения.

Рекомендации по улучшению пользовательской функции потерь

Вместо использования hess = 2*N*np.ones(len(y)), попробуйте использовать просто константу, как предложили в комментарии. Ваш обновлённый код функции может выглядеть следующим образом:

def reg_obj(preds, dtrain):
    y = dtrain.get_label()
    grad = 2 * (preds - y)
    hess = 2 * np.ones(len(y))
    return grad, hess

Применение изменений в XGBoost

После внесенных изменений, повторите процесс обучения модели с использованием ваших данных. Убедитесь, что у вас правильно определены параметры для обучения и выборки данных:

bst_custom = xgb.train(param,
                   dtrain,
                   best_nrounds,
                   obj=reg_obj)

Верификация прогнозов

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

pred_custom = bst_custom.predict(dtest)
print(np.abs(pred_custom).mean())

Заключение

Проблема, с которой вы столкнулись, скорее всего связана с неправильным вычислением градиентов и гессианов в вашей пользовательской функции потерь. Попробуйте обновленный вариант функции и протестируйте, улучшилась ли стабильность и согласованность ваших прогнозов. При дальнейшем анализе может оказаться полезным изучение влияния других гиперпараметров и использование раннего останова (early stopping) для избежания переобучения модели.

Если после всех рекомендаций проблема останется, возможно, потребуется более глубокий анализ данных, который вы используете для обучения модели.

Оцените материал
Добавить комментарий

Капча загружается...