Skip to content

Why did the default base_score for reg:squaredlogerror change in xgboost 3.0.0? #11442

Description

@sktin

My understanding is that in version 3.0.0, the default base_score for those GLM-inspired loss functions has been changed to use the closed-form solution, but reg:squaredlogerror shouldn't be one of them. Apparently it has been changed to use the mean of the target values. If closed-form solution is preferred over the one-step Newton approach, then at least the "exp-mean-log" should be used instead. What was the rationale for the change?

I am not sure what the "best" default choice for reg:squaredlogerror should be, but for the following dataset from a kaggle competition, one-step Newton is the only choice that would not lead to divergence. Note also how different the value from one-step Newton is from the other choices.

import numpy as np
import pandas as pd
import json

from sklearn.model_selection import train_test_split
from sklearn.metrics import root_mean_squared_log_error
from xgboost import XGBRegressor

# train.csv from https://www.kaggle.com/competitions/playground-series-s5e5/data
X = pd.read_csv('train.csv', index_col='id')
y = X.pop('Calories')
X.pop('Sex') # remove categorical variable for simplicity
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)

import sklearn; print(F'{sklearn.__version__=}')
import xgboost; print(F'{xgboost.__version__=}')

def rmsle(y_true, y_pred):
    # y_pred could go wild when XGBRegressor diverges
    return root_mean_squared_log_error(
        y_true, np.clip(y_pred, -1+1e-6, None)
    )

params = {'objective': 'reg:squaredlogerror', 'random_state': 0}

print('\n# 3.0.0 default')
model =  XGBRegressor(**params)
print('RMSLE: ',
    rmsle(
        y_test, 
        model.fit(X_train, y_train).predict(X_test)
    )
) 
config = json.loads(model.get_booster().save_config())
print('Base score used: ', config['learner']['learner_model_param']['base_score'])

print('\n# base_score from mean of target')
model =  XGBRegressor(**params, base_score=y_train.mean())
print('RMSLE: ',
    rmsle(
        y_test, 
        model.fit(X_train, y_train).predict(X_test)
    )
)  
config = json.loads(model.get_booster().save_config())
print('Base score used: ', config['learner']['learner_model_param']['base_score'])

print('\n# base_score from exp-mean-log of target')
model =  XGBRegressor(**params, base_score=np.expm1(np.log1p(y_train).mean()))
print('RMSLE: ',
    rmsle(
        y_test, 
        model.fit(X_train, y_train).predict(X_test)
    )
)   
config = json.loads(model.get_booster().save_config())
print('Base score used: ', config['learner']['learner_model_param']['base_score'])

print('\n# base_score from one-step Newton')
model =  XGBRegressor(
    **params, 
    base_score=np.log1p(y_train).sum()/(1+np.log1p(y_train)).sum()
)
print('RMSLE: ',
    rmsle(
        y_test, 
        model.fit(X_train, y_train).predict(X_test)
    )
) 
config = json.loads(model.get_booster().save_config())
print('Base score used: ', config['learner']['learner_model_param']['base_score'])

# optional: xgboost 2.1.4
if 'xgboost_2_1_4' in globals():
    with xgboost_2_1_4():
        print('\n# 2.1.4 default')
        import xgboost; print(F'{xgboost.__version__=}')
        from xgboost import XGBRegressor
        model =  XGBRegressor(**params)
        print('RMSLE: ',
            rmsle(
                y_test, 
                model.fit(X_train, y_train).predict(X_test)
            )
        ) 
        config = json.loads(model.get_booster().save_config())
        print('Base score used: ', config['learner']['learner_model_param']['base_score'])

Expected output:

sklearn.__version__='1.6.1'
xgboost.__version__='3.0.0'

# 3.0.0 default
RMSLE:  9.073920894159356
Base score used:  8.827874E1

# base_score from mean of target
RMSLE:  9.073920894159356
Base score used:  8.827874E1

# base_score from exp-mean-log of target
RMSLE:  6.978755750166066
Base score used:  6.1856785E1

# base_score from one-step Newton
RMSLE:  0.07439065625016286
Base score used:  8.0548E-1

# 2.1.4 default
xgboost.__version__='2.1.4'
RMSLE:  0.07439065625016286
Base score used:  8.0548E-1

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions