网格搜索交叉验证:评分没有使用所选择的XGBRegressor评分方法

3
Scikit-learn的GridSearchCV用于对XGBRegressor模型进行超参数调优。无论在XGBRegressor().fit()中指定了何种eval_metric,GridSearchCV生成的分数值始终相同。在https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html上,对于参数scoring,它说:“如果为None,则使用评估器的得分方法。”但实际情况并非如此。结果始终相同。如何获取与XGBRegressor eval_metric相对应的结果? 此示例代码:
import numpy as np
from sklearn.model_selection import GridSearchCV, KFold
from sklearn.datasets import load_boston
import xgboost as xgb

rng = np.random.RandomState(31337)

boston = load_boston()
y = boston['target']
X = boston['data']

kf = KFold(n_splits=2, random_state=42)
folds = list(kf.split(X))

xgb_model = xgb.XGBRegressor(objective='reg:squarederror', verbose=False)
reg = GridSearchCV(estimator=xgb_model, 
                   param_grid= {'max_depth': [2], 'n_estimators': [50]}, 
                   cv=folds,
                   verbose=False)

reg.fit(X, y, **{'eval_metric': 'mae', 'verbose': False})
print('GridSearchCV mean(mae)?:  ', reg.cv_results_['mean_test_score'])
# -----------------------------------------------
reg.fit(X, y, **{'eval_metric': 'rmse', 'verbose': False})
print('GridSearchCV mean(rmse)?: ', reg.cv_results_['mean_test_score'])
print("----------------------------------------------------")

xgb_model.set_params(**{'max_depth': 2, 'n_estimators': 50})
xgb_model.fit(X[folds[0][0],:],y[folds[0][0]], eval_metric='mae', 
              eval_set = [(X[folds[0][0],:],y[folds[0][0]])], verbose=False)
print('XGBRegressor 0-mae:', xgb_model.evals_result()['validation_0']['mae'][-1])
xgb_model.fit(X[folds[0][1],:],y[folds[0][1]], eval_metric='mae', 
              eval_set = [(X[folds[0][1],:],y[folds[0][1]])], verbose=False)
print('XGBRegressor 1-mae:', xgb_model.evals_result()['validation_0']['mae'][-1])

xgb_model.fit(X[folds[0][0],:],y[folds[0][0]], eval_metric='rmse', 
              eval_set = [(X[folds[0][0],:],y[folds[0][0]])], verbose=False)
print('XGBRegressor 0-rmse:', xgb_model.evals_result()['validation_0']['rmse'][-1])
xgb_model.fit(X[folds[0][1],:],y[folds[0][1]], eval_metric='rmse', 
              eval_set = [(X[folds[0][1],:],y[folds[0][1]])], verbose=False)
print('XGBRegressor 1-rmse:', xgb_model.evals_result()['validation_0']['rmse'][-1])

返回值(上方数字应该是下方数字的平均值)

GridSearchCV mean(mae)?:   [0.70941007]
GridSearchCV mean(rmse)?:  [0.70941007]
----------------------------------------------------
XGBRegressor 0-mae: 1.273626
XGBRegressor 1-mae: 1.004947
XGBRegressor 0-rmse: 1.647694
XGBRegressor 1-rmse: 1.290872
1个回答

1

简而言之,你获得的是所谓的R2或决定系数。这是XGBRegressor score函数的默认评分指标,如果scoring=None,则GridSearchCV会选择它。

与明确编码scoring的结果进行比较:

from sklearn.metrics import make_scorer, r2_score, mean_squared_error
xgb_model = xgb.XGBRegressor(objective='reg:squarederror', verbose=False)

reg = GridSearchCV(estimator=xgb_model, scoring=make_scorer(r2_score),
                   param_grid= {'max_depth': [2], 'n_estimators': [50]}, 
                   cv=folds,
                   verbose=False)

reg.fit(X, y)
reg.best_score_
0.7333542105472226

使用 scoring=None 的那些:

reg = GridSearchCV(estimator=xgb_model, scoring=None,
                   param_grid= {'max_depth': [2], 'n_estimators': [50]}, 
                   cv=folds,
                   verbose=False)

reg.fit(X, y)
reg.best_score_
0.7333542105472226

如果您阅读了GridSearchCVdocstrings

estimator:估计器对象。 假设它实现了scikit-learn的估计器接口。 估计器需要提供一个score函数, 或者必须传递scoring

此时,您可能想要查看xgb_model.score?的文档:

签名:xgb_model.score(X, y, sample_weight=None)
文档字符串:
返回预测的决定系数R^2。

因此,借助这些文档,如果您不喜欢XGBRegressor的默认R2得分函数,请明确地提供您的得分函数给GridSearchCV

例如,如果您想要RMSE,可以执行以下操作:

reg = GridSearchCV(estimator=xgb_model,  
                   scoring=make_scorer(mean_squared_error, squared=False),
                   param_grid= {'max_depth': [2], 'n_estimators': [50]}, 
                   cv=folds,
                   verbose=False)

reg.fit(X, y)
reg.best_score_
4.618242594168436

答案的要点是你不能使用xgboost中指定的评分器。如果scorer=None,则会选择默认评分器。我解释了为什么会这样。 - Sergey Bushmanov
感谢您的回复!我可能过于简化了我的问题。我知道,在GridSearchCV中,您可以指定scoring=make_scorer(),使用来自sklearn.metrics的度量标准。如果 XGBoost 使用eval_metric='mae',我希望避免在GridSearchCV scoring=make_scorer()中重新定义 MAE。我真的想用 {'objective': 'reg:tweedie', 'eval_metric':'tweedie-nloglik'} 运行 XGBRegressor。Sklearn.metrics 没有这个度量标准。我不认为我能为此编写自己的评分函数。如何从GridSearchCV获得tweedie-nloglik作为得分输出? - Geir Inge
正如我在我的答案中清楚地说明的那样,附带文档和sklearn源代码,GridSearchCV不会选择自定义评分函数。这只是两个不同的软件包,具有不同的源代码,它们没有访问彼此的源代码库。你必须自己编写它。因此,如果你确实想要它,你真正的问题是“如何编写 tweedie-nloglik 作为评分函数”。 - Sergey Bushmanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接