目标检测AP、mAP计算方法

关于AP和mAP的定义可以参考以下链接:

参考:https://blog.csdn.net/qq_35916487/article/details/89076570
参考:https://zhuanlan.zhihu.com/p/56961620
代码来源:https://github.com/rbgirshick/py-faster-rcnn/blob/master/lib/datasets/voc_eval.py

        AP(Average Precison)是计算具体某个类别的AP,相当于一个二分类问题,计算步骤如下:

  1. 先确定划分positive和negative的IoU阈值,预测的proposal与当前这个类别的GT的IoU大于阈值,则这个预测结果为positive(TP),否则为negative(FP)
  2. 平均计算所有类别的AP就是mAP
  3. 计算P-R曲线下的面积就是这单个类别预测结果的AP值
  4. 使用不同的置信度阈值得到一组Precision和Recall得到PR曲线
  5. 计算得到当前IoU和置信度阈值下的precision和Recall
  6. 基于第一步和第二步预测得到的positive和negative,以及TP和FP计算混淆矩阵TP、FP、FN、TN
  7. 在确定好IoU阈值的基础上,将预测的一系列proposal按照置信度倒序排序,将排序后的每个置信度依次作为置信度阈值,设定预测置信度阈值,大于阈值的proposal预测为positive,小于阈值的proposal预测为negative
  8. 在得到precision和recall之后,关于AP和mAP的计算有几种不同的方式:

        由于mAP是数据集中所有类别AP值得平均,所以我们要计算mAP,首先得知道某一类别的AP值怎么求。不同数据集的某类别的AP计算方法大同小异,主要分为三种:

        方式一:

        (1)在VOC2010以前,只需要选取当Recall >= 0, 0.1, 0.2, ..., 1共11个点时的Precision最大值,然后AP就是这11个Precision的平均值,mAP就是所有类别AP值的平均。

        方式二:

        (2)在VOC2010及以后,需要针对每一个不同的Recall值(包括0和1),选取其大于等于这些Recall值时的Precision最大值,然后计算PR曲线下面积作为AP值,map就是所有类别AP值的平均。

        方式三:

        (3)COCO数据集,设定多个IOU阈值(0.5-0.95,0.05为步长),在每一个IOU阈值下都有某一类别的AP值,然后求不同IOU阈值下的AP平均,就是所求的最终的某类别的AP值。

下面以一个具体的例子来说明如何计算上述第1、2两种方式的AP:

输入真值标签和预测概率
gt_label: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0]
pred: [0.12156912078311422, 0.6707490847267786, 0.8258527551050476, 0.13670658968495297, 0.57509332942725, 0.891321954312264, 0.20920212211718958, 0.18532821955007506, 0.10837689046425514, 0.21969749262499216]

基于gt_label和pred计算得到的precision
precision: [1., 1., 1., 0.66666667, 0.75, 0.6, 0.5, 0.42857143, 0.5]

基于gt_label和pred计算得到的recall
recall: [0., 0.25, 0.5, 0.5, 0.75, 0.75, 0.75, 0.75, 1.]

基于pred排序得到的thresh
thresh: [0.89132195, 0.82585276, 0.67074908, 0.57509333, 0.21969749, 0.20920212, 0.18532822, 0.13670659]

使用三种不同方式(方式一、方式二、sklearn)计算的AP结果
1、使用11-point方法计算得到的AP: 0.8181818181818181
2、使用recall方法计算得到的AP:0.8125
3、使用sklearn方法计算得到的AP:0.8125

(第一种方式)11-point方法AP计算过程:
1、设定11个点的recall阈值:
[0.0, 0.1, 0.2, 0.3 ,0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
2、对于这11个recall阈值,在recall和precision列表里面找recall大于阈值对应的precision的最大值
3、recall阈值列表[0.0, 0.1, 0.2, 0.3 ,0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]找到的对应的precision如下:
[ 1,   1,   1,   1,   1,   1,  0.75,0.75, 0.5,0.5, 0.5]
4、累加找到的precision,然后除以11得到AP = (1 + 1 + 1 + 1 + 1 + 1 + 0.75 + 0.75 + 0.5 + 0.5 + 0.5) / 11 = 0.8181818181818181

(第二种方式)recall区间方法AP计算过程(目前最常见的计算方式):
1、先根据recall列表划分recall区间[0-0.25, 0.25-0.5, 0.5-0.75, 0.75-1.0]
2、计算各个recall区间内对应的precision的最大值[1, 1, 0.75, 0.5]
3、recall区间长度乘以对应的precision,然后求和,0.25 * 1 + 0.25 * 1 + 0.25 * 0.75 + 0.25 * 0.5 = 0.8125

以下是测试例子的完整代码:

import numpy as np
from sklearn.metrics import average_precision_score, precision_recall_curve
np.random.seed(100)


# AP,mAP
def voc_ap(rec, prec, use_07_metric=False):
    """ ap = voc_ap(rec, prec, [use_07_metric])
    Compute VOC AP given precision and recall.
    If use_07_metric is true, uses the
    VOC 07 11 point method (default:False).
    """
    if use_07_metric:
        # 11 point metric
        ap = 0.
        for t in np.arange(0., 1.1, 0.1):
            if np.sum(rec >= t) == 0:
                p = 0
            else:
                p = np.max(prec[rec >= t])
            ap = ap + p / 11.
    else:
        # correct AP calculation
        # first append sentinel values at the end
        mrec = np.concatenate(([0.], rec, [1.]))
        mpre = np.concatenate(([0.], prec, [0.]))
        print(mpre)
        # compute the precision envelope
        for i in range(mpre.size - 1, 0, -1):
            mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
        # to calculate area under PR curve, look for points
        # where X axis (recall) changes value
        i = np.where(mrec[1:] != mrec[:-1])[0]
        ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
        print(mpre)
    return ap


if __name__ == '__main__':
    # 构造预测置信度概率和GT值
    gt_label = np.random.randint(0, 2, 10).tolist()
    pred = np.random.rand(10).tolist()
    print(gt_label)
    print(pred)
    print(np.unique(np.array(pred)))
    # 根据预测结果计算precision和recall
    precision, recall, thresh = precision_recall_curve(gt_label, pred)
    precision = precision[::-1]
    recall = recall[::-1]
    thresh = thresh[::-1]
    print("precision: {}".format(precision))
    print("recall: {}".format(recall))
    print("thresh: {}".format(thresh))

    # 根据得到的precision列表和recall列表计算AP,mAP
    ap = voc_ap(recall, precision, use_07_metric=True)
    print(ap)

    ap = voc_ap(recall, precision, use_07_metric=False)
    print(ap)
    # 使用sklearn计算AP
    ap_sklearn = average_precision_score(gt_label, pred)
    print(ap_sklearn)

    """
    结果分析:
    输入:
    gt_label: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0]
    pred: [0.12156912078311422, 0.6707490847267786, 0.8258527551050476, 0.13670658968495297, 0.57509332942725, 0.891321954312264, 0.20920212211718958, 0.18532821955007506, 0.10837689046425514, 0.21969749262499216]
    
    # 基于gt_label和pred计算得到的precision
    precision: [1., 1., 1., 0.66666667, 0.75, 0.6, 0.5, 0.42857143, 0.5]
    
    # 基于gt_label和pred计算得到的recall
    recall: [0., 0.25, 0.5, 0.5, 0.75, 0.75, 0.75, 0.75, 1.]
    
    # 基于pred排序得到的thresh
    thresh: [0.89132195, 0.82585276, 0.67074908, 0.57509333, 0.21969749, 0.20920212, 0.18532822, 0.13670659]
    
    # 使用11-point方法计算得到的AP: 0.8181818181818181
    # 使用recall方法计算得到的AP:0.8125
    # 使用sklearn方法计算得到的AP:0.8125
    
    11-point方法AP计算过程:
    1、设定11个点的recall阈值:[0.0, 0.1, 0.2, 0.3 ,0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
    2、对于这11个recall阈值,在recall和precision列表里面找recall大于阈值对应的precision的最大值
    3、recall阈值列表[0.0, 0.1, 0.2, 0.3 ,0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]找到的对应的precision如下:
    [ 1,   1,   1,   1,   1,   1,  0.75,0.75, 0.5,0.5, 0.5]
    4、累加找到的precision,然后除以11得到AP = (1 + 1 + 1 + 1 + 1 + 1 + 0.75 + 0.75 + 0.5 + 0.5 + 0.5) / 11 = 0.8181818181818181
    
    # recall区间方法AP计算过程(目前最常见的计算方式):
    1、先根据recall列表划分recall区间[0-0.25, 0.25-0.5, 0.5-0.75, 0.75-1.0]
    2、计算各个recall区间内对应的precision的最大值[1, 1, 0.75, 0.5]
    3、recall区间长度乘以对应的precision,然后求和,0.25 * 1 + 0.25 * 1 + 0.25 * 0.75 + 0.25 * 0.5 = 0.8125
    """

  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测中的AP(Average Precision)是一种常用的评价指标,用于衡量目标检测算法在不同类别上的性能。AP的计算方式根据不同的数据集和评价方法可能会有所不同,这里我给出一种常见的计算方式。 首先,需要明确几个概念: - TP(True Positive):检测到的目标被正确地分类为正样本(目标存在)。 - FP(False Positive):检测到的目标被错误地分类为正样本(目标不存在)。 - Precision(精确率):TP与(TP + FP)的比值,表示正确分类为正样本的概率。 - Recall(召回率):TP与(TP + FN)的比值,表示正样本被正确检测出的概率。 - FN(False Negative):目标未被检测到,即目标存在但被错误地分类为负样本(目标不存在)。 AP的计算步骤如下: 1. 对于每个类别,首先按照预测结果的置信度进行排序。 2. 从置信度最高的预测开始,依次计算Precision和Recall,并绘制Precision-Recall曲线。 3. 通过计算Precision-Recall曲线下的面积(AUC),得到AP值。 AP值越高,表示目标检测算法在对应类别上的性能越好。同时,AP值还可以通过计算多个类别的平均值得到mAP(mean Average Precision),用于综合评估目标检测算法的性能。 需要注意的是,不同数据集和评价方法可能会对AP的计算方式有所调整,因此具体的计算公式可能会有所差异。以上是一种常见的计算方式的解释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值