评分='roc_auc' 的 cross_val_score 和 roc_auc_score 有啥区别?

Posted

技术标签:

【中文标题】评分=\'roc_auc\' 的 cross_val_score 和 roc_auc_score 有啥区别?【英文标题】:What is the difference between cross_val_score with scoring='roc_auc' and roc_auc_score?评分='roc_auc' 的 cross_val_score 和 roc_auc_score 有什么区别? 【发布时间】:2016-02-12 01:10:14 【问题描述】:

我对 cross_val_score 评分指标“roc_auc”和我可以直接导入和调用的 roc_auc_score 之间的区别感到困惑。

文档 (http://scikit-learn.org/stable/modules/model_evaluation.html#scoring-parameter) 表明指定 score='roc_auc' 将使用 sklearn.metrics.roc_auc_score。但是,当我使用 score='roc_auc' 实现 GridSearchCV 或 cross_val_score 时,我收到的数字与我直接调用 roc_auc_score 时非常不同。

这是我的代码,用于帮助演示我所看到的:

# score the model using cross_val_score

rf = RandomForestClassifier(n_estimators=150,
                            min_samples_leaf=4,
                            min_samples_split=3,
                            n_jobs=-1)

scores = cross_val_score(rf, X, y, cv=3, scoring='roc_auc')

print scores
array([ 0.9649023 ,  0.96242235,  0.9503313 ])

# do a train_test_split, fit the model, and score with roc_auc_score

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33)
rf.fit(X_train, y_train)

print roc_auc_score(y_test, rf.predict(X_test))
0.84634039111363313 # quite a bit different than the scores above!

我觉得我在这里遗漏了一些非常简单的东西——很可能是我在实施/解释其中一个评分指标时的错误。

谁能解释这两个评分指标之间存在差异的原因?

【问题讨论】:

我也完全被这种差异搞糊涂了。我还尝试使用标准的 make_scorer() 函数将分数函数转换为 cross_val_score 的正确 Scorer 对象,但结果是相同的。 make_scorer() 给出了与我的手动实现相同的结果,而 'roc_auc' 给出了更高的分数。幸运的是,在我的示例中,差异只有百分之几,与您的不同,但仍然:我应该信任哪个函数? 【参考方案1】:

这是因为您提供了预测的 y,而不是 roc_auc_score 中的概率。这个函数需要一个分数,而不是分类标签。尝试这样做:

print roc_auc_score(y_test, rf.predict_proba(X_test)[:,1])

它应该给出与 cross_val_score 之前的结果相似的结果。 Refer to this post for more info.

【讨论】:

你完全正确!如果我能停止哭泣,我会笑。谢谢!【参考方案2】:

我刚刚遇到了类似的问题here。关键点是cross_val_score 使用KFold 策略和默认参数来进行训练测试拆分,这意味着拆分成连续的块而不是洗牌。另一方面,train_test_split 进行了随机拆分。

解决方案是明确拆分策略并指定洗牌,如下所示:

shuffle = cross_validation.KFold(len(X), n_folds=3, shuffle=True)
scores = cross_val_score(rf, X, y, cv=shuffle, scoring='roc_auc')

【讨论】:

Aniket,感谢您的回答。但是指定折叠并将它们传递给 cross_val_score 并不能解决评分指标之间的差异。 我知道我已经很晚了,但是当您使用带有roc_auc 评分的cross_val_score 方法时,为什么要传递预测的类标签而不是预测的概率?既然是AUC,是不是需要概率代替,所以可以测试不同的阈值?【参考方案3】:

我自己遇到了这个问题,经过一番挖掘找到了答案。为爱而分享。

其实有两个半问题。

    您需要使用相同的 Kfold 来比较分数(训练/测试的相同拆分); 您需要将概率输入roc_auc_score(使用predict_proba() 方法)。但是,一些估算器(如 SVC)没有predict_proba() 方法,您可以使用decision_function() 方法。

这是一个完整的例子:

# Let's use the Digit dataset
digits = load_digits(n_class=4)
X,y = digits.data, digits.target
y[y==2] = 0 # Increase problem dificulty
y[y==3] = 1 # even more

使用两个估算器

LR = LogisticRegression()
SVM = LinearSVC()

拆分训练集/测试集。但是把它保存在一个我们可以重复使用的变量中。

fourfold = StratifiedKFold(n_splits=4, random_state=4)

将其提供给GridSearchCV 并保存分数。请注意,我们传递的是fourfold

gs = GridSearchCV(LR, param_grid=, cv=fourfold, scoring='roc_auc', return_train_score=True)
gs.fit(X,y)
gs_scores = np.array([gs.cv_results_[k][0] for k in gskeys])

将其提供给cross_val_score 并保存分数。

 cv_scores = cross_val_score(LR, X, y, cv=fourfold, scoring='roc_auc')

有时,您想要循环并计算几个不同的分数,所以这就是您所使用的。

loop_scores = list()
for idx_train, idx_test in fourfold.split(X, y):
  X_train, y_train, X_test, y_test = X[idx_train], y[idx_train], X[idx_test], y[idx_test]
  LR.fit(X_train, y_train)
  y_prob = LR.predict_proba(X_test)
  auc = roc_auc_score(y_test, y_prob[:,1])
  loop_scores.append(auc)

我们的分数是否相同?

print [((a==b) and (b==c)) for a,b,c in zip(gs_scores,cv_scores,loop_scores)]
>>> [True, True, True, True]


但是,有时我们的估算器没有predict_proba() 方法。所以,根据这个example,我们这样做:
for idx_train, idx_test in fourfold.split(X, y):
  X_train, y_train, X_test, y_test = X[idx_train], y[idx_train], X[idx_test], y[idx_test]
  SVM.fit(X_train, y_train)
  y_prob = SVM.decision_function(X_test)
  prob_pos = (y_prob - y_prob.min()) / (y_prob.max() - y_prob.min())
  auc = roc_auc_score(y_test, prob_pos)

【讨论】:

以上是关于评分='roc_auc' 的 cross_val_score 和 roc_auc_score 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我将 GridSearchCV 与 roc_auc 评分一起使用时,grid_search.score(X,y) 和 roc_auc_score(y, y_predict) 的分数不同?

加快 SVM 评分中的交叉验证

VotingClassifier 中的 roc_auc,scikit-learn (sklearn) 中的 RandomForestClassifier

如何计算具有 3 个类别的 ROC_AUC 分数

best_score_的gridsearch cv的AUC分数与gridsearch cv的最佳模型的auc_roc_score不同

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