计算机视觉基础之mAP

9 篇文章 1 订阅
本文详细介绍了mAP(mean Average Precision)的概念及其在图像检索和目标检测中的计算方法,包括Precision-Recall曲线、AP的计算以及VOC07和VOC10两种不同的mAP评估标准。通过对不同recall区间的precision取最大值来确定AP,并展示了从排序后的预测结果中计算PR曲线的过程。最后,提供了VOC风格mAP的Python代码实现。
摘要由CSDN通过智能技术生成

## mAP

mAP定义及相关概念

  1. mAP:mean Average Precision,即各类别AP的平均值
  2. AP:PR曲线下面积
  3. PR曲线:Precision-Recall曲线
  4. Precision:TP/(TP+FP)
  5. Recall:TP/(TP+FN)
  6. TP:IoU>0.5的检测框数量(同一Ground Truth只计算一次)
  7. FP:IoU <=0.5的检测框,或者是检测到同一个GT的多余检测框的数量
  8. FN:没有检测到的GT的数量

图像检索mAP

图像检索中的mAP和目标检测中的mAP几乎一模一样:

在这里插入图片描述
以上是图像检索中mAP的计算案例,简要说明如下:
1、查询图片1在图像库中检索相似的图像,假设图像库中有五张相似图像,表示为图片1、……、图片5,排名不分先后
2、检索,返回top-10图像,如上图第二行,橙色表示相似图像,灰色表示无关图像
3、接下来就是precision、recall的计算过程,结合上图比较容易理解,
以返回图片6的节点为例:
top-6中,有3张图像确实为相似的图像,另外三张为无关图像,因此precision = 3/6;同时,总共五张相似图像,top-6检索出来了三张因此,recall = 3/5
4、然后计算AP,可以看右边的计算公式,可以发现是把列出来的查询率(precision)相加取平均,那么最关键的问题来了,为什么选择这几张图像的precision求平均?可惜图中没有告诉我们答案。
其实不难,一句话就是:选择每个recall区间内对应的最高precision;
eg:以上图橙色检索案例为例,当我们只选择top-1作为检索结果返回(即,只返回一个检索结果)时,检索性能为:

top-1:recall = 1 / 5、precision = 1 / 1# 以下类推;
top-2:recall = 1 / 5、precision = 1 / 2;
top-3:recall = 2 / 5、precision = 2 / 3;
top-4:recall = 2 / 5、precision = 2 / 4;
top-5:recall = 2 / 5、precision = 2 / 5;
top-6:recall = 3 / 5、precision = 3 / 6;
top-7:recall = 3 / 5、precision = 3 / 7;
top-8:recall = 3 / 5、precision = 3 / 8;
top-9:recall = 4 / 5、precision = 4 / 9;
top-10:recall = 5 / 5、precision = 5 / 10

结合上面清单,先找找recall = 1 / 5区间下的最高precision,对应着precision = 1 / 1;
同理,recall = 2 / 5区间下的最高precision,对应着precision = 2 / 3;
recall = 3 / 5区间下的最高precision,对应着precision = 3 / 6;依次类推;
这样AP = (1 / 1 + 2 / 3 + 3 / 6 + 4 / 9 + 5 / 10) / 5;
那么mAP是啥?计算所有检索图像返回的AP均值,对应上图就是橙、绿突图像计算AP求均值,对应红色框;
这样mAP就计算完毕啦~~~是不是很容易理解?目标检测的mAP也是类似操作了;

目标检测中mAP计算流程

下面以检测人脸为例,gt label表示1为人脸,0为bg,某张图像中一共检测出了20个pred bbox,id:1~20,并对应了confidence score,gt label也很容易获得,pred bbox与gt bbox算IoU,给定一个threshold,那么就知道该pred bbox是否为正确的预测结果,那么就知道该pred bbox是否为正确的预测结果了,就对应了其gt label。---- 其实下表不应该这么理解的,但我们还是先这么认为,忽略差异吧,先直捣黄龙,table 1:
在这里插入图片描述
接下来对confidence score排序,得到table 2:
在这里插入图片描述
这张表很重要,接下来的precision和recall都是依照这个表计算的,那么这里的confidence score其实就是和图像检索中的相似度关联上了,具体的,就是如第一节的图像检索中,虽然我们计算mAP没在乎其检索返回的先后顺序,但top1肯定是与待检索图像最相似的,对应的similarity score最高,对人脸检测而言,pred bbox的confidence score最高,也说明该bbox最有可能是人脸。
然后计算precision和recall ,这两个标准的定义如下:
在这里插入图片描述
上面的图看看就行,能理解就理解,不理解可以参照第一节图像检索的例子来理解;

现以返回的top-5结果为例,如table 3:在这里插入图片描述
​在这个例子中,true positives就是指id = 4、2的pred bbox,false positives就是指id = 13、19、6的pred bbox。方框内圆圈外的元素(false negatives + true negatives)是相对于方框内的元素而言,在这个例子中,是指confidence score排在top-5之外的元素,即table 4:在这里插入图片描述
其中,false negatives是指id = 9、16、7、20的4个pred bbox,true negatives是指id = 1、18、5、15、10、17、12、14、8、11、3的11个pred bbox;

那么,这个例子中Precision = 2 / 5 = 40%,意思是对于人脸检测而言,我们选定了5 pred bbox,其中正确的有2个,即准确率为40%;Recall = 2 / 6 = 33%,意思是该图像中共有6个人脸,但是因为我们只召回了2个,所以召回率为33%;

实际的目标检测任务中,我们通常不满足只通过top-5来衡量一个模型的好坏,而是需要知道从top-1到top-N(N是所有pred bbox,本文中为20)对应的precision和recall;显然随着我们选定的pred bbox越来也多,recall一定会越来越高,而precision整体上会呈下降趋势;把recall当成横坐标,precision当成纵坐标,即可得到常用的precision-recall曲线,以上例子的precision-recall曲线如fig 1:
在这里插入图片描述
以上图像如何计算的?可以参照第一节图像检索中的栗子,还是比较容易理解的吧;

上面的每个红点,就相当于根据table 2,按照第一节中图像检索的方式计算出来的,也可以直接参照下面的table 5,自己心里算一算;

那么按照选择每个recall区间内对应的最高precision的计算方案,各个recall区间内对应的top-precision,就刚好如fig 1中的绿色框位置,可以进一步结合table 5中的绿色框理解;

好了,那么对这张图像而言,其AP = ​(1 / 1 + 2 / 2 + 3 / 6 + 4 / 7 + 5 / 11 + 6 / 16)/ 6;这是针对单张图像而言,所有图像也类似方式计算,那么就可以根据所有图像上的pred bbox,采用同样的方式,就计算出了所有图像上人脸这个类的AP;因为人脸检测只有一个类,如Pascal VOC这种20类的,每类都可以计算出一个AP,那么AP_total / 20,就是mAP啦;
但是等等,有没有发现table 5中,计算方式好像跟我们讲的有一点不一样?我们继续看看;

Pascal VOC的两套mAP评估标准

Pascal VOC中对mAP的计算经历了两次迭代,一种是VOC07的计算标准,对应绿色框:

首先设定一组阈值,T = [0、0.1、0.2、…、1],然后对于recall大于每一个阈值Ti(比如recall > 0.3),我们都会在该recall区间内得到一个对应的最大precision,这样我们就计算出了11个precision;----- 这里与上两节介绍的概念是一样的,只不过上面recall的区间是参照gt label来划分的,这里是我们人为划分的11个节点;

AP即为这11个precision的平均值,这种方法英文叫做11-point interpolated average precision;有了一个类的AP,所有类的AP均值即为mAP;

另一种是VOC10的计算标准,对应白色框:

新的计算方法假设N个pred bbox中有M个gt bbox,那么我们会得到M个recall节点(1 / M、2 / M、…、 M / M),对于每个recall值 r,我们可以计算出对应(r’ > r)的最大precision,然后对这M个precision值取平均即得到最后的AP值,计算方法如table 5:在这里插入图片描述
从VOC07的绿框、VOC10的白框对比可知,差异主要在recall = 3 / 6下的precision,可以发现VOC07找的top-precision是在该recall区间段内的,但VOC10相当于是向后查找的,需确保该recall阈值以后的区间内,对应的是top-precision,可知4 / 7 > 3 / 6,因此使用4 / 7替换了3 / 6,其他recall阈值下的操作方式类似;

那么代码的实操中,就得从按照recall阈值从后往前计算了,这样就可以一遍就梭哈出所有结果,如果按recall从前往后计算,就有很多重复性计算(不断地重复向后recall区间内查找top-precision),然后呢,就可以使用到动态规划的方式做了,理论结合实践啊有木有~~~

那么VOC10下,相应的Precision-Recall曲线如fig 2,可以发现这条曲线是单调递减的,剩下的AP计算方式就与VOC07相同了:

这里还需要继续一点,VOC07是11点插值的AP方式,等于是卡了11个离散的点,划分10个区间来计算AP,但VOC10是是根据recall值变化的区间来计算的,在这个栗子里,recall只变化了6次,但如果recall变化很多次,如100次、1000次、9999次等,就可以认为是一种 “伪” 连续的方式计算了;在这里插入图片描述
总结:

AP衡量的是模型在每个类别上的好坏,mAP衡量的是模型在所有类别上的好坏,得到AP后mAP的计算就变得很简单了,就是取所有类别AP的平均值。

代码实现

这个函数假设我们已经得到了排序好的precision、recall的list,对应上图fig 2,进一步可以参照第一节中的清单理解

# VOC-style mAP,分为两个计算方式,之所有两个计算方式,是因为2010年后VOC更新了评估方法,因此就有了07-metric和else...
def voc_ap(rec, prec, use_07_metric=False):
    """
    average precision calculations
    [precision integrated to recall]
    :param rec: recall list
    :param prec: precision list
    :param use_07_metric: 2007 metric is 11-recall-point based AP
    :return: average precision
    """
    if use_07_metric:
        # 11 point metric
        ap = 0.
        # VOC07是11点插值的AP方式,等于是卡了11个离散的点,划分10个区间来计算AP
        for t in np.arange(0., 1.1, 0.1):
            if np.sum(rec >= t) == 0:
                p = 0    # recall卡的阈值到顶了,1.1
            else:
                p = np.max(prec[rec >= t])   # VOC07:选择每个recall区间内对应的最高precision的计算方案
            ap = ap + p / 11.    # 11-recall-point based AP
    else:
        # correct AP calculation
        # first append sentinel values at the end
        mrec = np.concatenate(([0.], rec, [1.]))
        mpre = np.concatenate(([0.], prec, [0.]))

        # compute the precision envelope
        for i in range(mpre.size - 1, 0, -1):
            mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])    # 这个是不是动态规划?从后往前找之前区间内的top-precision,多么优雅的代码呀~~~

        # to calculate area under PR curve, look for points where X axis (recall) changes value
        # 上面的英文,可以结合着fig 2的绿框理解,一目了然
        # VOC10是是根据recall值变化的区间来计算的,如果recall变化很多次,就可以认为是一种 “伪” 连续的方式计算了,以下求的是recall的变化
        i = np.where(mrec[1:] != mrec[:-1])[0]

        # 计算AP,这个计算方式有点玄乎,是一个积分公式的简化,应该是对应的fig 2中红色曲线以下的面积,之前公式的推导我有看过,现在有点忘了,麻烦各位同学补充一下
        # 现在理解了,不难,公式:sum (\Delta recall) * prec,其实结合fig2和下面的图,不就是算的积分么?如果recall划分得足够细,就可以当做连续数据,然后以下公式就是积分公式,算的precision、recall下面的面积了
        ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
    return ap

修改于:https://zhuanlan.zhihu.com/p/48992451

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值