在 GridSearch 和交叉验证中,我只得到 XGBClassifier 的 `accuracy_score` 而不是 `roc_auc`

Posted

技术标签:

【中文标题】在 GridSearch 和交叉验证中,我只得到 XGBClassifier 的 `accuracy_score` 而不是 `roc_auc`【英文标题】:I am only getting `accuracy_score` instead of `roc_auc` for XGBClassifier in both GridSearch and cross validation 【发布时间】:2021-07-04 13:13:12 【问题描述】:

我将 XGBClassifier 用于Rain in Australia 数据集,并试图预测今天是否会下雨。我想用 GridSearch 调整分类器的超参数并用 ROC_AUC 对其进行评分。这是我的代码:

param_grid = 
    "max_depth": [3, 4, 5, 7],
    "gamma": [0, 0.25, 1],
    "reg_lambda": [0, 1, 10],
    "scale_pos_weight": [1, 3, 5],
    "subsample": [0.8],  # Fix subsample
    "colsample_bytree": [0.5],  # Fix colsample_bytree


from sklearn.model_selection import GridSearchCV

# Init the classifier
xgb_cl = xgb.XGBClassifier(objective="binary:logistic", verbose=0)

# Init the estimator
grid_cv = GridSearchCV(xgb_cl, param_grid, scoring="roc_auc", n_jobs=-1)

# Fit
_ = grid_cv.fit(X, y)

当搜索最终完成时,我使用.best_score_ 获得了最高分,但不知何故只获得了准确度得分而不是 ROC_AUC。我认为这只是 GridSearch 的情况,所以我尝试了 HalvingGridSearchCVcross_val_score,将 scoring 设置为 roc_auc,但我也得到了它们的准确度分数。我通过使用sklearn.metrics.roc_auc_score 手动计算 ROC_AUC 来检查这一点。

我做错了什么或者这种行为的原因是什么?

【问题讨论】:

出于好奇,您为什么将拟合搜索存储在 _ 中? 否则,单元格将打印出整个分类器及其参数,这会使笔记本变得混乱 你怎么知道best_score_ 给出的准确性? (我怀疑您的手动检查有误...) 我使用了来自sklearn.metricsroc_auc_score。它首先引发了一个错误,因为目标没有被编码,所以我首先对其进行了编码。然后,我从 GridSearch 的最佳估计器中获得预测,并将编码的目标和预测传递给roc_auc_score。这似乎是正确的? 【参考方案1】:

您是否尝试过自己的 roc_auc 评分规则?似乎您正在为 roc_auc 传递标签而不是概率(您最初需要)。

这里描述的问题: Different result roc_auc_score and plot_roc_curve

自己的得分手的解决方案: Grid-Search finding Parameters for AUC

更新2

抱歉,今天看到我笔记本上的介绍文字不见了,哈哈

在计算 roc_auc_score 时,您可以选择(无论是否使用 gridsearch,使用或不使用管道),您可以将标签(0/1)或概率(0.995、0.6655)传递给它。如果您只是将您的 probas 转换为标签,那么第一个应该很容易获得。然而,这将导致(直接反转 L)输出图。这有时看起来很难看。另一种选择是使用预测概率将它们传递给 roc_auc_score。这将产生一个(楼梯反转的 L)输出图,看起来要好得多。 所以你首先应该测试的是,如果是这样的话,你能不能得到一个带有标签的 roc auc 分数,有没有网格。然后,您应该尝试获得概率。而且,我相信,你必须编写自己的评分方法,因为网格中的 roc-auc_score 只提供标签,这将导致高 roc_auc 分数。我给你写了一些东西,所以你可以看到标签的方法:

import xgboost as xgb
from sklearn.metrics import confusion_matrix
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import roc_auc_score

cancer = load_breast_cancer()

X = cancer.data
y = cancer.target

xgb_model = xgb.XGBClassifier(objective="binary:logistic", 
                              eval_metric="auc", 
                              use_label_encoder=False,
                              colsample_bytree = 0.3, 
                              learning_rate = 0.1,
                              max_depth = 5, 
                              gamma = 10, 
                              n_estimators = 10,
                              verbosity=None)

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42) 
xgb_model.fit(X_train, y_train)
preds = xgb_model.predict(X_test)

print(confusion_matrix(preds, y_test))
print ('ROC AUC Score',roc_auc_score(y_test,preds))

给予:

[[51  2]  
[ 3 87]] 
ROC AUC Score 0.9609862671660424

在这里你可以看到它的高度可笑。

如果你想用网格来做: 摆脱这个:

# Fit
_ = grid_cv.fit(X, y)

just grid_cv.fit(x, y)fit 是一种应用于 grid_cv 的方法,结果存储在 grid_cv 中

print(grid_cv.best_score_) 应该按照您已经定义的方式交付 auc。 另见:different roc_auc with XGBoost gridsearch scoring='roc_auc' and roc_auc_score? 但这也应该是可笑的,因为您可能会提供标签而不是 probas。

还要注意: What is the difference between cross_val_score with scoring='roc_auc' and roc_auc_score?

并且没有人阻止您将 roc-auc_score 函数应用于您的 grid_results...

【讨论】:

但是在网格搜索或 CV 之外使用 roc_auc_score 可以正常工作,没有任何错误。对不起,我是 sklearn 的新手,我没有完全理解你的回答 如果您使用 roc_auc,您的结果会得到优化(因为它的网格),那么您可以根据需要在 grid_results 上使用 roc-auc 函数,但它也应该为您提供适当的 roc 分数网格,您是否没有使用混淆矩阵对其进行测试,并根据网格的 conf-matrix 计算您自己的 roc_auc_score,以便您可以确定 grid_cv.score_ 等于 roc-auc? 如果 roc_auc 不同,可能你必须插入概率而不是标签,正如我已经说过的那样。 那么,我应该使用predict_proba 而不仅仅是predict 来获得预测? 嘿,是的,你应该试试 predict_proba 但我不确定,如果 xgboost 可以,如果不行,你必须自己写。我更新了我的答案,因为我笔记本上的介绍性文字不知何故丢失了。我用 roc_auc 给你写了标签的例子。对于网格或没有网格,这应该始终是可能的。但是当你想做probas时,我相信你必须自己写,我相信xgboost没有提供predict_proba。但总的来说是的,我相信你应该编写自己的评分“predict_proba”

以上是关于在 GridSearch 和交叉验证中,我只得到 XGBClassifier 的 `accuracy_score` 而不是 `roc_auc`的主要内容,如果未能解决你的问题,请参考以下文章

交叉验证与网格搜索

机器学习交叉验证和网格搜索案例分析

K-近邻算法交叉验证,网格搜索

交叉验证后如何获取支持向量数

评估 scikit-learn GridSearchCV 中交叉验证分数的平均值、标准差

如何通过索引自定义 sklearn 交叉验证迭代器?