sklearn.metrics.average_precision_score 对相同的数据但不同的格式得到不同的答案

数据挖掘 Python scikit-学习 计分
2022-02-09 20:30:11

我试图了解如何在 scikit-learn 中计算和实现平均精度 (AP)。我已经阅读了文档,但我认为我还没有完全理解它。

考虑以下两个片段:

import numpy as np
from sklearn.metrics import average_precision_score
y_true = np.array([0, 1, 0])
y_scores = np.array([0.4, 0.4, 0.8])
average_precision_score(y_true, y_scores) # 0.3333333333333333

y_true = np.array([[1,0], [0,1],[1,0]])
y_scores = np.array([[0.6,0.4], [0.6,0.4], [0.2,0.8]])
average_precision_score(y_true, y_scores) # 0.45833333333333326

据我了解,这些是相同的数据,但格式不同。第一个只显示正类的真实标签和预测分数,而第二个是提供两个类的信息。

但是为什么他们给出不同的答案呢?特别是这两个结果是如何计算的?哪一个是正确的?我正在阅读这篇文章,但我不明白答案中的精确召回表是如何构建的。任何人都可以为我的示例进行类似的计算吗?

1个回答

通过显式给出两个类,sklearn计算每个类的平均精度。然后我们需要查看average参数:默认为macro

计算每个标签的指标,并找到它们的未加权平均值......

如果将参数切换为None,则得到

average_precision_score(y_true, y_scores, average=None)
# array([0.58333333, 0.33333333])

其第二个条目与正类的答案一致,其平均值为您提供了您所看到的其他输出。


至于手工计算:
对于正类,阈值在(0.8,1]我们得到零正面预测,因此召回率为 0,精度为 1(按照惯例)。随着门槛(0.4,0.8)我们得到一个假阳性、一个假阴性和一个真阴性,所以召回率为 0,精度为 0。随着门槛[0,0.4)我们得到一个真阳性和两个假阳性,所以 1 召回和 0.333 精度。所以在这种情况下,来自链接问题的表格是

    R     P
1   0.0   1.0   
2   0.0   0.0   
3   1.0   0.333   

最后,平均精度计算为

(0.00.0)0.0+(1.00.0)0.333=0.333
有点退化的例子,但它检查出来了。

对于另一类: (0.6,1]给出零个“正”预测,所以又是 0 和 1。 (0.2,0.4)给出一个真阳性、一个假阳性和一个真阴性。 [0,0.2)给出两个真阳性,一个假阳性。所以

    R     P
1   0.0   1.0   
2   0.5   0.5   
3   1.0   0.666   

平均精度为

(0.50.0)0.5+(1.00.5)0.666=0.58333