为什么 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
参数传递给 XGBoost
的 cv
方法:
from sklearn.model_selection import KFold
cv_results = xgb.cv(dtrain=dmatrix, params=params, metrics={'rmse'}, folds = KFold(n_splits=5))
最后,您需要确保 XGBoost
的 cv
过程确实收敛。出于某种原因,默认情况下它只进行 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 年。
我是第一次使用 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
参数传递给 XGBoost
的 cv
方法:
from sklearn.model_selection import KFold
cv_results = xgb.cv(dtrain=dmatrix, params=params, metrics={'rmse'}, folds = KFold(n_splits=5))
最后,您需要确保 XGBoost
的 cv
过程确实收敛。出于某种原因,默认情况下它只进行 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
上有一个