目标检测的AP(Average Precision)代码解析与深入思考

1. 引言

Average Precision的原理可见 多标签图像分类任务的评价方法-mAP ,个人感觉文章对计算流程、PR曲线(Precision-Recall)、图例都展示得比较好。

另外,忘记从哪篇文章中提到的一句讲得特别精髓,大致意思如下:

对confidence socre降序排列后,再把第k行作为top-k的分界线,进行Precision和Recall的计算。

所以我们计算AP是对conf排序后,从上往下的计算,一直从top-1到top-N。
通常情况下,从top-1到top-N伴随的是召回率的提升和精确率的下降。
理想情况下是两者恒为1。

2. 代码实现

这里我们假设某个类的precision和recall序列都已求出,本文主要关注AP的实现:

def voc_ap(rec, prec, use_07_metric=False):
	"""
	rec: recall序列,单调递增,[0.5, 0.5, 1]
	prec: precision序列,呈锯齿状,[1, 0.5 , 0.66]
	use_07_metric: 是否采用VOC07的AP计算方式,True or Flase
	
	这里rec和prec的每个值,rec[i]和prec[i]分别代表top-i时,recall和precision是多少
	"""
    if use_07_metric:
        # 11 point metric
        ap = 0.
        # 设定一组阈值, 然后对于大于这个阈值的recall,都能取到最大的precision
        # 因为precision呈锯齿状,所以P(r'>r)的最大值有可能在更后面
        for t in np.arange(0.,1.1,0.1):
            if np.sum(rec >= t) == 0:
                p = 0
            else:
                # p取recall大于t的结果里面,precision最大的值
                p = np.max(prec[rec>=t])
            ap = ap + p/11.  # 11点求均值

    else:
        # correct ap caculation
        mrec = np.concatenate(([0.],rec,[1.]))  # 左接0,右接1
        mpre = np.concatenate(([0.],prec,[0.]))  # 左右接0

		# precision反过来遍历
        for i in range(mpre.size -1, 0, -1):  
            # 这里目的是让mpre[i-1]不小于mpre[i]
            # 即平滑了PR曲线的锯齿状
            # 例如[0.5, 0.66] -> [0.66, 0.66]
            
            # 平滑过后的mpre单调递减
            mpre[i-1] = np.maximum(mpre[i-1],mpre[i])

        # 找出mrec变化的地方
        # mrec = [0. , 0.5, 0.5, 1. , 1. ]
        # i = [0, 2]
        i = np.where(mrec[1:] != mrec[:-1])[0]

        # mpre = [1, 1, 0.66, 0.66, 0]
        # 算法是针对每个recall值,取r'>r的precision最大值
        # 因为mpre已经平滑了PR曲线,所以r'>r的P最大值就是mpre[i+1](因为mpre单调递减)

        # 从这里mrec[i+1] - mrec[i]可以看出,前面在rec右接1,就是为了处理这里的边界
        # 而prec右接0只是为了对齐mrec
        # rec左接0是为了确保左边有0可以减,用来算x轴的距离
        # 而prec左接0也是为了对齐
		
		# 最后是求平滑后的PR曲线的面积
		# 上面超链接写的是Precision的平均值,好像不对
        ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])

    return ap

上面的AP是针对某个类别进行计算的,mAP只要对所有类别(剔除背景)的AP求平均就好啦~

3. 深入思考

在预测任务中,Precision和Recall是两个比较对立的指标(当然具体的业务场景可能对特定的指标有更高的要求)。
从top-1到top-N,target在不断被预测中,同时也不可避免的会有误判情况,因此Recall会不断的提高,Precision也会随着误判而降低。

根据VOC07求AP的算法思路,划分11个阈值,并求 P m a x ( r > t ) P_{max}(r>t) Pmax(r>t)t为阈值。考虑到此时的PR曲线都是折线图,因此就是取t右边最高的峰值。
语义就是让模型的召回率最少达到 t 时,精确率最高能达到 P m a x P_{max} Pmax,再对11个t求平均。

然而阈值的分布还是人为设定的,并且阈值之间的距离仍然不可忽略,对于两个模型的mAP值对比,难免会有误差。

VOC10之后采用的mAP计算方式,在继承了原算法的思路:召回率为t时,精确率最高能达到 的同时,通过积分的方式减少误差(PR曲线下方的面积)。
并且top-1到top-N并不是每次都能成功命中target,也即召回率的变化次数并不高,因此算法仅捕捉召回率变化瞬间,用平滑PR曲线的方式获取最大的Precision。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值