scikit-learn中AUC的正确计算方式及两种ROC曲线绘制代码结果差异问题
在scikit-learn中正确计算AUC与ROC曲线绘制的问题
一、正确计算AUC的方式
首先要明确:ROC AUC的计算依赖于模型输出的连续得分(概率值或决策函数值),而不是直接使用predict()返回的硬分类标签(0/1)。
原因很简单:ROC曲线的核心是遍历所有可能的分类阈值,观察不同阈值下的假阳性率(FPR)和真阳性率(TPR)变化;而硬标签相当于固定了一个特定阈值(通常是0.5),丢失了阈值变化的信息,用它计算的"AUC"并不是真正意义上的ROC AUC。
具体步骤:
- 如果你的模型支持输出概率(比如
SVC需要设置probability=True,LogisticRegression默认支持),使用model.predict_proba(X_test)[:, 1]获取正类的预测概率; - 如果模型不支持概率输出(比如默认的
SVC),使用model.decision_function(X_test)获取决策函数值(模型用于分类的原始输出); - 最后用
roc_auc_score(y_test, score)计算AUC,这里的score是上述的概率或决策函数值。
二、你两段代码结果差异的原因
先看你的示例代码里的问题:
你用y_predicted = svclassifier.predict(X_test)得到的是硬分类标签,然后用roc_auc_score(y_test, y_predicted)计算的AUC,本质是基于单一阈值的分类结果计算的,和metrics.plot_roc_curve内部计算的AUC完全不是一回事:
metrics.plot_roc_curve会自动使用模型的决策函数值(因为默认的SVC没有开启概率输出)来计算ROC AUC并绘制曲线,这个结果才是正确的;- 你手动计算的那个AUC是错误的,因为它用了硬标签,丢失了阈值维度的信息。
所以结论是:代码#1的方式是正确的;代码#2的问题出在你手动计算AUC时用了硬标签,导致和plot函数内部的正确结果不一致。
三、修正后的可复现代码
我们调整代码,用正确的方式计算AUC并匹配plot函数的结果:
from sklearn.metrics import roc_auc_score from sklearn import metrics import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.datasets import load_breast_cancer data = load_breast_cancer() X = data.data y = data.target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=12) # 开启probability参数,让SVC可以输出正类概率 svclassifier = SVC(kernel='rbf', probability=True) svclassifier.fit(X_train, y_train) # 用正类概率计算正确的ROC AUC y_pos_proba = svclassifier.predict_proba(X_test)[:, 1] correct_roc_auc = roc_auc_score(y_test, y_pos_proba) print('正确的ROC AUC = %.2f' % correct_roc_auc) # 绘制ROC曲线,此时标签里的AUC和plot函数内部计算的完全一致 metrics.plot_roc_curve( svclassifier, X_test, y_test, ax=plt.gca(), label=f'SVC (AUC = {correct_roc_auc:.2f})' ) plt.show()
补充说明
如果你不想开启probability=True(因为会增加训练时间),也可以用决策函数值来计算AUC:
y_score = svclassifier.decision_function(X_test) correct_roc_auc = roc_auc_score(y_test, y_score)
这个结果和metrics.plot_roc_curve输出的AUC也会完全一致。
内容的提问来源于stack exchange,提问作者David Ws.
相关产品推荐
相关产品推荐

