AP score详解

2024-11-29发布于深度学习 | 最后更新于2024-11-29 17:11:00

Pytorch EvalMetric

评价指标AP详解

sklearn.metrics.average_precision_score 是一个在各种领域中都非常常用的函数,用于综合评判模型的性能。其本质是计算Average Precision。

前置知识

  • TP: True Positive,真阳性,即检查认为患病的确实得病了
  • TN: True Negative,真阴性,即检查认为没患病的确实未得病
  • FP: False Positive,假阳性,即检查认为患病的其实没得病,属于“误报”
  • FN: False Negative,假阴性,即检查认为没患病的其实得病了,属于“漏报”

准确率Precision,即所有阳性预测判断中判断正确的比例(算上误报的);召回率Recall,即在所有事实上阳性的样本中预测判断出了阳性的比例(算上漏报的),“召回”可以理解为所有病人召回来了多少

$$ \mathrm{Precision}=\frac{TP}{TP+FP} $$
$$ \mathrm{Recall}=\frac{TP}{TP+FN} $$

Average Precision

事实上,AP的“平均”并不是体现在除以某个数量,而是体现在Precision在不同召回率水平下的“加权”。此处先介绍当前最主流的计算方法,也是sklearn中使用的方法。

二分类

先讨论二分类下的情况,设一次计算中有 \(N_S=4\) 个样本,模型为这些样本预测的概率值分别为 \(\left[0.4,0.1,0.8,0.35\right]\) ,这些样本的真实情况(ground truth)为 \(\left[0,0,1,1\right]\)

  1. 按预测概率值从大到小排列这些样本: \(\left[0.8,0.4,0.35,0.1\right]\) ,对应的真实情况为 \(\left[1,0,1,0\right]\)
  2. 分别以各个预测概率值为阈值得到预测类别,大于等于阈值的视为类别1、小于的视为类别0,下面是以各阈值得到预测类别的情况:
    • 0.8: \(\left[1,0,0,0\right]\)
    • 0.4: \(\left[1,1,0,0\right]\)
    • 0.35: \(\left[1,1,1,0\right]\)
    • 0.1: \(\left[1,1,1,1\right]\)
  3. 计算各阈值下的召回率 \(R_i\) 与准确率 \(P_i\)
    • 0.8: \(P_1=1,R_1=1/2\)
    • 0.4: \(P_2=1/2,R_2=1/2\)
    • 0.35: \(P_3=2/3,R_3=1\)
    • 0.1: \(P_4=2/4,R_4=1\)
  4. 通过下式计算AP,认为\(R_0=0\)

    $$ \mathrm{AP}=\sum_{i=1}^n{\left(R_i-R_{i-1}\right)\cdot P_i} $$

    因此,此处的AP为

    $$ \mathrm{AP}=\left(\frac{1}{2}-0\right)\times 1 + \left(\frac{1}{2}-\frac{1}{2}\right)\times \frac{1}{2} + \left(1-\frac{1}{2}\right)\times \frac{2}{3}+\left(1-1\right)\times \frac{2}{4}=\frac{5}{6} $$

另外一种已经过时的方法称为“11点插值法”,区别在与不取各个预测概率为阈值,而是固定地取阈值分别为 \(0,0.1,0.2,\dots,1\) ,共11个,其他计算步骤与上述完全一致。

多分类

在多分类的情况下,记类别数为 \(N_C\) ,每个样本就有 \(N_C\) 个预测概率与真实值,且一个样本可以被分到一个或多个类别中。这时,若从类别的角度出发,对于给定的某个类别,各个样本在该类别上就是一个二分类问题,即预测样本能不能属于该类别,共有 \(N_C\) 个这样的二分类问题。

假设 \(N_C=3,N_S=4\) ,4个样本的预测概率值结果与对应真实值标签分别为

  • \(\left[0.1,0.8,0.3\right]\)\(\left[0,1,0\right]\)
  • \(\left[0.9,0.7,0.5\right]\)\(\left[1,1,0\right]\)
  • \(\left[0.2,0.1,0.9\right]\)\(\left[0,1,1\right]\)
  • \(\left[0.1,0.8,0.6\right]\)\(\left[1,1,0\right]\)

换一个视角,从类别出发,3个类别的预测概率值与对应的真实值标签分别为

  • \(\left[0.1,0.9,0.2,0.1\right]\)\(\left[0,1,0,1\right]\)
  • \(\left[0.8,0.7,0.1,0.8\right]\)\(\left[1,1,1,1\right]\)
  • \(\left[0.3,0.5,0.9,0.6\right]\)\(\left[0,0,1,0\right]\)

对这三个类别分别执行上述二分类中的步骤,可以得到这三个类别下的AP分别为0.75、1、1。

mean Average Precision

mAP的值就是对各个类别下的AP取平均,对于上例

$$ \mathrm{mAP}=\frac{1}{3}\times\left(0.75+1+1\right)=\frac{11}{12} $$

average_precision_score详解

sklearn库中的average_precision_score函数原型如下:

sklearn.metrics.average_precision_score(
    y_true, y_score, *,
    average='macro',
    pos_label=1, sample_weight=None
)

其中,y_true为ground truth标签值,应该只包含整数0和1,或者均为布尔值;y_score为预测结果,可以是概率值或得分。对于二分类,这两个参数的尺寸要求均为 \(\left(N_S,\right)\) ;对于多分类,尺寸要求均为 \(\left(N_S,N_C\right)\)

pos_label参数用于在二分类情况下指定正样本的label值,会将y_true中的该指定值视为正样本,其他的均视为负样本

sample_weight参数用于在二分类情况下指定各个样本的权重,可以视为该样本的数量(原本均为1)。以预测概率 \(\left[0.5,0.4,0.3,0.1\right]\) 、标签 \(\left[1,0,0,1\right]\) 、sample_weight \(\left[2,0.5,1,1\right]\) 为例,计算Presicion与Recall如下:

$$ \mathrm{P}=\left[\frac{2}{2},\frac{2}{2.5},\frac{2}{3.5},\frac{3}{4.5}\right] $$
$$ \mathrm{R}=\left[\frac{2}{3},\frac{2}{3},\frac{2}{3},1\right] $$

再正常计算AP即可,最终AP值为 \(\frac{8}{9}\)

average参数用于将多个AP值进行聚合(多分类的情况下):

  • 默认值为macro,即将前述方式计算各个类别AP的平均值
  • 若指定为None,则返回各个类别的AP值(共 \(N_C\) 个)
  • 若指定为micro,则会将y_truey_score都展平成一维,视为一个有 \(N_S\times N_C\) 个样本的二分类
  • 若指定为samples,则将每个样本视为一个二分类问题,共求得 \(N_S\) 个AP值,对他们求平均值即可
  • 若指定为weighted,先按前述方式计算各个类别的AP值,但不再简单的直接求平均,而是求加权平均。每个类别的权重为该类别正样本数在所有正样本中的比例。对于上例,总正样本数为7,三个类别各自的权重分别为 \(\frac{2}{7},\frac{4}{7},\frac{1}{7}\) ,AP的加权平均值为:
$$ \mathrm{AP}=\frac{2}{7}\times 0.75+\frac{4}{7}\times 1+\frac{1}{7}\times 1=\frac{13}{14} $$