为什么 xgboost scikit-learn 接口的答案如此不同?

Why such different answers for the xgboost scikit-learn interface?

我是第一次使用 xgboost 并尝试了两种不同的接口。首先我得到数据:

import xgboost as xgb
import dlib
import pandas as pd
import numpy as np
from sklearn.model_selection import cross_val_score
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
X = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
y = raw_df.values[1::2, 2]
dmatrix = xgb.DMatrix(data=X, label=y)

现在 scikit-learn 界面:

xgbr = xgb.XGBRegressor(objective='reg:squarederror', seed=20)
print(cross_val_score(xgbr, X, y, cv=5))

这输出:

[0.73438184 0.84902986 0.82579692 0.52374618 0.29743001]

现在 xgboost 本机接口:

dmatrix = xgb.DMatrix(data=X, label=y)
params={'objective':'reg:squarederror'}
cv_results =  xgb.cv(dtrain=dmatrix, params=params, nfold=5, metrics={'rmse'},  seed=20)
print('RMSE: %.2f' % cv_results['test-rmse-mean'].min())

这给出 3.50

为什么输出如此不同?我做错了什么?

首先,您没有在 cross_val_score 中指定度量,因此您计算的不是 RMSE,而是估算器的默认度量,通常只是它的损失函数。您需要指定它以获得可比较的结果:

cross_val_score(xgbr, X, y, cv=5, scoring = 'neg_root_mean_squared_error')

其次,您需要准确匹配sklearn的简历程序。为此,您可以将 folds 参数传递给 XGBoostcv 方法:

from sklearn.model_selection import KFold

cv_results =  xgb.cv(dtrain=dmatrix, params=params, metrics={'rmse'}, folds = KFold(n_splits=5))

最后,您需要确保 XGBoostcv 过程确实收敛。出于某种原因,默认情况下它只进行 10 轮提升,这太低而无法收敛到您的数据集。这是通过 nrounds 参数完成的(num_boost_round 如果你使用的是旧版本),我发现 100 轮在这个数据集上工作得很好:

cv_results =  xgb.cv(dtrain=dmatrix, params=params, metrics={'rmse'}, folds = KFold(n_splits=5), nrounds = 100)

现在您将获得匹配的结果。

顺便说一句,有趣的是你说这是你第一次使用 XGBoost,但实际上你在 XGBoost 上有一个 可以追溯到 2017 年。