precision表示某一类样本预测有多准。 Recall表示某一类样本,预测正确的与所有Ground Truth的比例。 Recall和Precision一样,脱离类别是没有意义的。说道这两个指标,一定指的是某个类别的。
以Recall为横轴,Precision为纵轴,就可以画出一条PR曲线,PR曲线下的面积就定义为AP。
所有类别的平均即为MAP
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