背景
平均精度是一种流行且重要的性能指标,广泛用于例如检索和检测任务。它测量精度召回曲线下的面积,该曲线绘制所有可能检测阈值的精度值与各自的召回值。
典型的精确召回曲线看起来有点像这样。
混乱
由于在任何给定的有限数据集上只需要评估有限数量的阈值,因此精确召回曲线是分段线性函数。因此,我一直认为计算该曲线下面积的正确方法是使用梯形规则:
ap = sum( (recall[k+1] - recall[k]) * (precision[k+1] - precision[k]) / 2 )
显然,不仅我这么认为,因为用于评估牛津建筑数据集结果的官方代码(这是基于内容的图像检索中广泛使用的基准)也以这种方式计算 AP。
但是,scikit-learnPython 的包在函数中计算平均精度的方式不同sklearn.metrics.average_precision_score,遵循Wikipedia 中对 AP 的定义。他们使用矩形方法:
ap = sum( (recall[k+1] - recall[k]) * precision[k+1] )
在上面给出的示例中,这将使用下图中的红色函数来近似精确召回曲线下的面积:
的文档scikit-learn对此进行了以下说明:
这种实现不同于使用梯形规则计算精确召回曲线下的面积,梯形规则使用线性插值并且可能过于乐观。
另一方面,牛津建筑数据集的一位策展人在 StackOverflow 上的一个相关问题中解释说,矩形方法将是“常用的更差近似”。
问题
糟糕的是,不同的基准和不同的包使用不同的平均精度变体来比较方法,但现在我想知道:
- 这两个版本中的哪一个是“更好”的做法?梯形法则还是矩形法?
- 各有什么优缺点?
scikit-learn文档中关于梯形规则“过于乐观”的说法是什么意思?


