在 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 的情况,所以我尝试了 HalvingGridSearchCV
和 cross_val_score
,将 scoring
设置为 roc_auc
,但我也得到了它们的准确度分数。我通过使用sklearn.metrics.roc_auc_score
手动计算 ROC_AUC 来检查这一点。
我做错了什么或者这种行为的原因是什么?
【问题讨论】:
出于好奇,您为什么将拟合搜索存储在_
中?
否则,单元格将打印出整个分类器及其参数,这会使笔记本变得混乱
你怎么知道best_score_
给出的准确性? (我怀疑您的手动检查有误...)
我使用了来自sklearn.metrics
的roc_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`的主要内容,如果未能解决你的问题,请参考以下文章