Mean Average Precise
也叫(mAP),“ to evaluate the ranked retrieval results”。
这个评价指标用于对信息检索,推荐算法的评价。最近在做目标检测的项目,mAP也用到了检测结果的好坏的评价上。与一般precise,recall,f评价体系不同的是,mAP将“顺序”的因素考虑在内。希望在positive结果中,tp的部分先出现。
参考了不少资料发现以下两组资料最为详尽,足够答疑解惑。同时结合代码分析mAP的计算过程。
源地址1:http://blog.sina.com.cn/s/blog_9db078090102whzw.html
源地址2(斯坦福NLP实验室资料):https://nlp.stanford.edu/IR-book/html/htmledition/evaluation-of-ranked-retrieval-results-1.html
代码来源: py-faster-rcnn /lib/dataSet/voc_eval.py AP计算部分源码
# tp = [1,0,1,0,0,0,...] size(tp) = all positive
# fp = [0,1,0,1,1,1,...]
# compute precision recall
fp = np.cumsum(fp) # fp = [0,1,1,2,3,4,...]
tp = np.cumsum(tp) # tp = [1,1,2,2,2,2,...]
rec = tp / float(npos) # npos(number of pos),此时rec为累计的rec
"""
# recall的计算:
假定一次输出x(positive)个结果,真正相关的结果数为r(true/relevant),当前计算的位置为i;
i为fp,则deta_rec = 0;
i为tp,
(1)当 x>=r ,deta_rec = 1/r;
(2)else,deta_rec = 1/x;
上述例子中,deta_rec 取 1/x
"""
# avoid divide by zero in case the first detection matches a difficult ground truth
# 所有的运算都不考虑difficult的样本
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
ap = voc_ap(rec, prec, use_07_metric)
# 计算 Everage Precise
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).
"""
# voc07版本
if use_07_metric:
# 11 point metric
ap = 0.
# 将recall分成11等份 (0-0.1),(0.1-0.2),...
for t in np.arange(0., 1.1, 0.1):
if np.sum(rec >= t) == 0:
p = 0
else:
# 计算该范围对应的precise
p = np.max(prec[rec >= t])
# deta_precise = p; deta_recall = 1/11
ap = ap + p / 11.
# voc07以上版本
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
"""
目的是找出precise的包络。参考“源2”,Figure8.2 中红线
"""
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
"""
找出recall变化的位置
"""
i = np.where(mrec[1:] != mrec[:-1])[0]
# and sum (\Delta recall) * prec
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
return ap