使用Sklearn计算ROC曲线下面积及roc_auc_score返回1的疑问
在Scikit-learn里,有两种常用的方式计算ROC AUC(Receiver Operating Characteristic Area Under the Curve):
方式一:直接使用roc_auc_score函数
这是最便捷的方法,它直接接收真实标签和模型输出的预测得分(注意是概率值或置信度,而非硬分类的0/1结果),返回最终的AUC值。示例代码如下:
from sklearn.metrics import roc_auc_score # 真实标签集合 y_true = [0, 1, 0, 1, 1] # 模型对每个样本的正类预测得分 y_scores = [0.2, 0.8, 0.3, 0.9, 0.7] auc_score = roc_auc_score(y_true, y_scores) print(f"ROC AUC值: {auc_score:.4f}")
如果是多分类任务,需要额外指定multi_class参数(可选'ovr'表示一对多策略,'ovo'表示一对一策略),同时配合average参数设置结果的平均方式。
方式二:先生成ROC曲线数据,再计算面积
如果你需要同时获取ROC曲线的假阳性率(FPR)、真阳性率(TPR)和对应阈值,可以先用roc_curve函数生成这些数据,再传入auc函数计算面积:
from sklearn.metrics import roc_curve, auc fpr, tpr, thresholds = roc_curve(y_true, y_scores) auc_score = auc(fpr, tpr) print(f"ROC AUC值: {auc_score:.4f}")
这种方式适合需要绘制ROC曲线的场景,同时能拿到不同阈值下的FPR和TPR数据,方便你分析模型在不同阈值下的表现。
roc_auc_score在这个场景中返回1? 这是一个很典型的认知误区,核心原因是你没抓住ROC AUC的本质——它衡量的是模型区分正样本和负样本的能力,而非单个样本的得分是否和标签“匹配”(比如负样本得分高没关系,只要它的得分没超过任何正样本)。
我们拆解你的例子来看:
- 真实标签
y_true = [0, 0, 1, 0, 0, 0, 0, 1]:正样本是第3个和第8个元素(索引2和7),对应的得分是0.99408和0.99673; - 负样本是剩下的6个元素,它们的最高得分是
0.89221。
ROC AUC的定义是:随机挑选一个正样本和一个负样本,正样本得分高于负样本的概率(若得分相等则计为0.5)。在你的例子里,总共有2个正样本×6个负样本=12对正负样本,每一对中,正样本的得分都严格大于负样本的得分,这个概率是100%,所以AUC自然是1。
你提到的那三个高得分负样本(0.738、0.892、0.825)确实比其他负样本得分高,但这完全不影响AUC——因为AUC只关心正负样本之间的相对排序,不关心负样本内部的排序,也不关心正样本内部的排序。只要所有正样本的得分都高于所有负样本,不管负样本内部怎么“混乱”,AUC都会是1。
举个更直观的例子:如果正样本得分是[0.6, 0.7],负样本得分是[0.3, 0.5, 0.4],哪怕负样本内部得分排序混乱,AUC还是1,因为每个正样本的得分都比所有负样本高。
内容的提问来源于stack exchange,提问作者Dr. John

