mAP的计算方法
程序员文章站
2022-04-23 15:46:26
...
AP的计算
AP(Average Precision)计算方法为PR曲线下覆盖的面积。
Precision与Recall数据的取值范围都在0~1之间,以Recall为X轴、以Precision为Y轴可以绘制PR曲线。
由于计算积分相对困难,因此引入插值法计算,计算AP公式如下:
VOC2007对计算出来结果,根据原始取得的recall进行最大插值为11点的方式来计算AP,图示如下:
当前PASCAL VOC都是基于全插值方式来计算AP,全插值方法,同样是基于最大值进行插值,得到曲线显示如下:
import numpy as np
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).
"""
# 针对2007年VOC,使用的11个点计算AP,现在不使用
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.])) #[0. 0.0666, 0.1333, 0.4 , 0.4666, 1.]
mpre = np.concatenate(([0.], prec, [0.])) #[0. 1., 0.6666, 0.4285, 0.3043, 0.]
# compute the precision envelope
# 计算出precision的各个断点(折线点)
for i in range(mpre.size - 1, 0, -1):
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i]) #[1. 1. 0.6666 0.4285 0.3043 0. ]
# to calculate area under PR curve, look for points
# where X axis (recall) changes value
i = np.where(mrec[1:] != mrec[:-1])[0] #precision前后两个值不一样的点
print(mrec[1:], mrec[:-1])
print(i) #[0, 1, 3, 4, 5]
# AP= AP1 + AP2+ AP3+ AP4
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
return ap
rec = np.array([0.0666, 0.1333,0.1333, 0.4, 0.4666])
prec = np.array([1., 0.6666, 0.6666, 0.4285, 0.3043])
ap = voc_ap(rec, prec)
print(ap) #输出:0.2456
mAP的计算
最终根据每个类别的AP求和之后除以总的检测类别数目就得到mAP(mean Average Precision)。
mAP = sum(AP) / N
其中N表示总的类别数目
computer_mAP.py
from voc_eval import voc_eval
import os
mAP = []
# 计算每个类别的AP
for i in range(8):
class_name = str(i) # 这里的类别名称为0,1,2,3,4,5,6,7
rec, prec, ap = voc_eval('path/{}.txt', 'path/Annotations/{}.xml', 'path/test.txt', class_name, './')
print("{} :\t {} ".format(class_name, ap))
mAP.append(ap)
mAP = tuple(mAP)
print("***************************")
# 输出总的mAP
print("mAP :\t {}".format( float( sum(mAP)/len(mAP)) ))