ROCAUC=1.0 怎么可能不准确?

机器算法验证 scikit-学习 奥克
2022-04-16 01:31:03

我使用 sklearn 计算roc_auc_score了一个包含 72 个实例的数据集。准确率为 97%(2 次错误分类),但 ROC AUC 得分为 1.0。这怎么可能?我认为即使是一次错误分类也应该将分数降至略低于 1.0。

# Python 3.6.4
# numpy==1.14.3
# scikit-learn==0.19.1
# scipy==1.1.0

from sklearn import metrics
import numpy as np

y_true = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0])
y_prob = np.array([0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.7, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.0, 0.0, 0.9, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.1, 0.1, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.1, 0.0, 0.9, 0.0, 0.0, 0.4, 0.0, 0.0, 0.0])

# Show which actuals do not match their expected probabilities
for index, (actual, predicted_prob) in enumerate(zip(y_true, y_prob)):
  if (actual == 1 and predicted_prob <= 0.5) or (actual == 0 and predicted_prob > 0.5):
    print (f'Mismatch at index {index}. Actual={actual}, predicted_prob={predicted_prob}')


rocauc = metrics.roc_auc_score(y_true, y_prob)
    print (f'ROCAUC: {rocauc}')

# Outputs:
# Mismatch at index 14. Actual=1.0, predicted_prob=0.5
# Mismatch at index 68. Actual=1.0, predicted_prob=0.4
# ROCAUC: 1.0

然后我调试了分数计算本身并查看了坐标 ROC 输出。

# In sklearn/metrics/ranking.py, line 271:
--> 271         fpr, tpr, tresholds = roc_curve(y_true, y_score,
    272                                         sample_weight=sample_weight)

ipdb> fpr
array([0.        , 0.        , 0.        , 0.18181818, 1.        ])
ipdb> tpr
array([0.33333333, 0.66666667, 1.        , 1.        , 1.        ])
ipdb> tresholds
array([0.9, 0.7, 0.4, 0.1, 0. ])

# coords = []
# for x, y in zip(fpr, tpr):
#   coords.append((x, y))

ipdb> pp coords
[(0.0, 0.3333333333333333),
 (0.0, 0.6666666666666666),
 (0.0, 1.0),
 (0.18181818181818182, 1.0),
 (1.0, 1.0)]

所有这些坐标都在 x=0 或 y=1 上,这意味着 ROCAUC 显示为 1.0。我能想到的唯一合理的解释是,如果 alg 有更多的 fpr/tpr 点,它将显示一条非常紧的曲线,永远不会达到 x,y = (0, 1),并且 ROCAUC 将接近 1,但是不完全是 1. 这是一个合理的解释还是我错过了什么?

1个回答

ROC AUC 和C-statistic 是等价的,并且衡量随机选择的正样本排名高于随机选择的负样本的概率如果所有正例的得分为 0.49,所有负例的得分为 0.48,则 ROC AUC 为 1.0,因为此属性。这可能会导致违反直觉的结果。在这个假设中,使用 0.5 截止规则的准确度为 0.0,因为所有预测都低于 0.5!

在您的数据中,有一个预测为 0.4 但标签为 1.0 的样本;这是得分最低且标签为 1.0 的样本。该样本以及标签为 1.0 且得分为 0.5 的样本正在降低您的准确性。但是标签为 0.0 的样本的最高分数是 0.1,因此我们知道我们正在处理完美 ROC AUC 的情况,因为 0.1 小于 0.4。

我发现这本书是获取有关 ROC 曲线信息的好资源:Wojtek J. Krzanowski(作者)和 David J. Hand。连续数据的 ROC 曲线