图像检索评价指标:mAP@k、mAP的计算
mAP ,mean Average Precision,平均检索精度.是图像检索领域最最常用的评价指标。
一、mAP@k、mAP
1.1 mAP@k
很多地方喜欢用这张图来解释,确实画的很好了,不过略有瑕疵,我稍微修改了一下。这张图是求mAP@10的结果。
原图主要存在的问题就是,在前10张图片中,把所有的相似的结果都返回了。这样会给读者造成这样的困扰:没检索出来的但是又相似的图片怎么办??
改了之后,就清晰多了。我们就会发现我们这里求mAP的时候是不考虑召回率的,也就是并没有考虑那些相似的但是不在topk中的那些漏掉的图片。只考虑了topk中,相似的图片。
注:当然还有一种计算mAP的方法,就是考虑召回率的计算方法,我们这里不展开。
mAP@k,理解的话应该是m(AP@k),而不是(mAP)@k。也就是先求AP@k,再求平均。
AP@k,理解的话应该是A(P@k),而不是(AP)@k。也就是先求P@k,再求平均。
P@k = 前k个中有多少个正样本 / k,比如对于查询1的结果:P@1 = 1, P@2 = 1/2, P@3 = 2/3...
求AP@k的时候,是求哪些P@k,然后再求平均呢?是求检索到的k张图片中,正样本位置上的P@k。比如,查询1中,返回了10张图片,但是只有5个正样本,分别在第1、3、6、9、10位。所以要求P@1,P@3,P@6, P@9,P@10这5个值,再求平均得到AP@10.
在求mAP@k的时候,k是指每次查询的时候返回k张图片。这个写@k是与后面要讲的mAP做区分用的。写论文的时候有的时候都不写@k,到底是用的mAP@k,还是mAP,自己把握去吧
【举例】
假设有3张图片,这三张图片的哈希码为:query1=[1,-1,1,1], query2=[-1,1,-1,-1],query3=[1,-1,-1,-1]。
数据库中有7张图片,对应的哈希码为:gallery=[[ 1,-1,-1,-1], [-1, 1, 1,-1], [ 1, 1, 1,-1], [-1,-1, 1, 1], [ 1, 1,-1,-1], [ 1, 1, 1,-1], [-1, 1,-1,-1]]
三张query图片的标签为:[1,0,0], [1,1,0], [0,0,1]。
7张gallery图片的标签为:[0,1,0], [1,1,0], [1,0,1], [0,0,1], [0,1,0], [0,0,1], [1,1,0]
求mAP@5.
(1)对于query1([1,-1,1,1]):
首先query1与gallery图片求距离,然后按照距离进行排序,得到最近的topk(这里设为5)张图片。
gallery | 汉明距离(有几位不同) | 排序 |
[ 1,-1,-1,-1] | 2 | 2 |
[-1, 1, 1,-1] | 3 | 5 |
[ 1, 1, 1,-1] | 2 | 3 |
[-1,-1, 1, 1] | 1 | 1 |
[ 1, 1,-1,-1] | 3 | |
[ 1, 1, 1,-1] | 2 | 4 |
[-1, 1,-1,-1] | 4 |
然后,看看返回的topk张图片中,哪些是正样本,哪些是负样本。query1的标签为[1,0,0],所以包含第1类的都是正样本。
返回的topk | 图片4 | 图片1 | 图片3 | 图片6 | 图片2 |
标签 | [0,0,1] | [0,1,0] | [1,0,1] | [0,0,1] | [1,1,0] |
是否正样本 | 否 | 否 | 是 | 否 | 是 |
最后,计算AP@5值:
(1/3 + 2/5)/2 = 0.3667
(2)对于query2([-1,1,-1,-1]):
首先query2与gallery图片求距离,然后按照距离进行排序,得到最近的topk(这里设为5)张图片。
gallery | 汉明距离(有几位不同) | 排序 |
[ 1,-1,-1,-1] | 2 | 4 |
[-1, 1, 1,-1] | 1 | 2 |
[ 1, 1, 1,-1] | 2 | 5 |
[-1,-1, 1, 1] | 3 | |
[ 1, 1,-1,-1] | 1 | 3 |
[ 1, 1, 1,-1] | 2 | |
[-1, 1,-1,-1] | 0 | 1 |
然后,看看返回的topk张图片中,哪些是正样本,哪些是负样本。query2的标签为 [1,1,0],所以包含第1类或第2类的都是正样本。
返回的topk | 图片7 | 图片2 | 图片5 | 图片1 | 图片3 |
标签 | [1,1,0] | [1,1,0] | [0,1,0] | [0,1,0] | [1,0,1] |
是否正样本 | 是 | 是 | 是 | 是 | 是 |
最后,计算AP@5值:
(1/1 + 2/2 + 3/3 + 4/4 + 5/5)/5 = 1.0
(3)对于query3([1,-1,-1,-1]):
首先query3与gallery图片求距离,然后按照距离进行排序,得到最近的topk(这里设为5)张图片。
gallery | 汉明距离(有几位不同) | 排序 |
[ 1,-1,-1,-1] | 0 | 1 |
[-1, 1, 1,-1] | 3 | |
[ 1, 1, 1,-1] | 2 | 3 |
[-1,-1, 1, 1] | 3 | |
[ 1, 1,-1,-1] | 1 | 2 |
[ 1, 1, 1,-1] | 2 | 4 |
[-1, 1,-1,-1] | 2 | 5 |
然后,看看返回的topk张图片中,哪些是正样本,哪些是负样本。query3的标签为 [0,0,1],所以包含第3类的都是正样本。
返回的topk | 图片1 | 图片5 | 图片3 | 图片6 | 图片7 |
标签 | [0,1,0] | [0,1,0] | [1,0,1] | [0,0,1] | [1,1,0] |
是否正样本 | 否 | 否 | 是 | 是 | 否 |
最后,计算AP@5值:
(1/3 + 2/4)/2 = 0.4165
(4)对所有的query的AP值,求平均
mAP@5 = (0.3667 + 1 + 0.4165) /3 = 0.5944
1.2 mAP与mAP@k的区别
mAP呢,就是每次查询的时候不是返回k张图片了,而是把所有的图片都按相似度进行返回。也就是k的值等于gallery数据库的大小。
【举例】
还是用上面的例子。求mAP。
(1)对于query1([1,-1,1,1]):
首先query1与gallery图片求距离,然后按照距离进行排序
gallery | 汉明距离(有几位不同) | 排序 |
[ 1,-1,-1,-1] | 2 | 2 |
[-1, 1, 1,-1] | 3 | 5 |
[ 1, 1, 1,-1] | 2 | 3 |
[-1,-1, 1, 1] | 1 | 1 |
[ 1, 1,-1,-1] | 3 | 6 |
[ 1, 1, 1,-1] | 2 | 4 |
[-1, 1,-1,-1] | 4 | 7 |
然后,看看返回的topk张图片中,哪些是正样本,哪些是负样本。query1的标签为[1,0,0],所以包含第1类的都是正样本。
返回的topk | 图片4 | 图片1 | 图片3 | 图片6 | 图片2 | 图片5 | 图片7 |
标签 | [0,0,1] | [0,1,0] | [1,0,1] | [0,0,1] | [1,1,0] | [0,1,0] | [1,1,0] |
是否正样本 | 否 | 否 | 是 | 否 | 是 | 否 | 是 |
最后,计算AP值:
(1/3 + 2/5 + 3/7)/3 = 0.3873
(2)对于query2([-1,1,-1,-1]):
首先query2与gallery图片求距离,然后按照距离进行排序,得到最近的topk(这里设为5)张图片。
gallery | 汉明距离(有几位不同) | 排序 |
[ 1,-1,-1,-1] | 2 | 4 |
[-1, 1, 1,-1] | 1 | 2 |
[ 1, 1, 1,-1] | 2 | 5 |
[-1,-1, 1, 1] | 3 | 7 |
[ 1, 1,-1,-1] | 1 | 3 |
[ 1, 1, 1,-1] | 2 | 6 |
[-1, 1,-1,-1] | 0 | 1 |
然后,看看返回的topk张图片中,哪些是正样本,哪些是负样本。query2的标签为 [1,1,0],所以包含第1类或第2类的都是正样本。
返回的topk | 图片7 | 图片2 | 图片5 | 图片1 | 图片3 | 图片6 | 图片4 |
标签 | [1,1,0] | [1,1,0] | [0,1,0] | [0,1,0] | [1,0,1] | [0,0,1] | [0,0,1] |
是否正样本 | 是 | 是 | 是 | 是 | 是 | 否 | 否 |
最后,计算AP值:
(1/1 + 2/2 + 3/3 + 4/4 + 5/5)/5 = 1.0
(3)对于query3([1,-1,-1,-1]):
首先query3与gallery图片求距离,然后按照距离进行排序,得到最近的topk(这里设为5)张图片。
gallery | 汉明距离(有几位不同) | 排序 |
[ 1,-1,-1,-1] | 0 | 1 |
[-1, 1, 1,-1] | 3 | 6 |
[ 1, 1, 1,-1] | 2 | 3 |
[-1,-1, 1, 1] | 3 | 7 |
[ 1, 1,-1,-1] | 1 | 2 |
[ 1, 1, 1,-1] | 2 | 4 |
[-1, 1,-1,-1] | 2 | 5 |
然后,看看返回的topk张图片中,哪些是正样本,哪些是负样本。query3的标签为 [0,0,1],所以包含第3类的都是正样本。
返回的topk | 图片1 | 图片5 | 图片3 | 图片6 | 图片7 | 图片2 | 图片4 |
标签 | [0,1,0] | [0,1,0] | [1,0,1] | [0,0,1] | [1,1,0] | [1,1,0] | [0,0,1] |
是否正样本 | 否 | 否 | 是 | 是 | 否 | 否 | 是 |
最后,计算AP值:
(1/3 + 2/4 + 3/7)/3 = 0.4206
(4)对所有的query的AP值,求平均
mAP = (0.3873 + 1 + 0.4206) /3 = 0.6026
二、代码实现
# @file name : test2.py
# @brief :
# @author : liupc
# @date : 2021/8/2import numpy as np#计算汉明距离。有几位不同,距离就为几。
def CalcHammingDist(B1, B2):q = B2.shape[1]distH = 0.5 * (q - np.dot(B1, B2.transpose()))return distH#计算mAP@k的值
def CalcTopMap(qB, rB, queryL, retrievalL, topk):#qB queryBinary, query数据集,都转成了哈希码#rB retrievalBinary,gallery数据集,都转成了哈希码#queryL queryLabel,query数据集的标签#retrievalL retrievalLabel,gallery数据集的标签num_query = queryL.shape[0] #共有多少个查询topkmap = 0for iter in range(num_query): #对每一个查询,求其AP@k的值#gnd:一个长度等于gallery数据集的0/1向量,1表示为正样本(即至少包含query的一个标签),0表示负样本(即,不包含query的标签)。gnd = (np.dot(queryL[iter, :], retrievalL.transpose()) > 0).astype(np.float32)hamm = CalcHammingDist(qB[iter, :], rB) #计算第iter张query图片与gallery数据集的汉明距离ind = np.argsort(hamm) #对汉明距离进行排序,返回下标,表示最相似的图片列表gnd = gnd[ind] #最相似的图片是否为正样本的列表tgnd = gnd[0:topk] #只看前topk个结果tsum = np.sum(tgnd).astype(int) #前topk个中有多少个预测对了if tsum == 0:continuecount = np.linspace(1, tsum, tsum)tindex = np.asarray(np.where(tgnd == 1)) + 1.0topkmap_ = np.mean(count / (tindex))topkmap += topkmap_topkmap = topkmap / num_queryreturn topkmap#计算mAP的值
def CalcMap(qB, rB, queryL, retrievalL):#qB queryBinary, query数据集,都转成了哈希码#rB retrievalBinary,gallery数据集,都转成了哈希码#queryL queryLabel,query数据集的标签#retrievalL retrievalLabel,gallery数据集的标签num_query = queryL.shape[0]map = 0# print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')for iter in range(num_query):gnd = (np.dot(queryL[iter, :], retrievalL.transpose()) > 0).astype(np.float32)tsum = np.sum(gnd).astype(int)if tsum == 0:continuehamm = CalcHammingDist(qB[iter, :], rB)ind = np.argsort(hamm)gnd = gnd[ind]count = np.linspace(1, tsum, tsum)tindex = np.asarray(np.where(gnd == 1)) + 1.0map_ = np.mean(count / (tindex))# print(map_)map = map + map_map = map / num_queryreturn map#计算topk准确率
def CalcTopAcc(qB, rB, queryL, retrievalL, topk):# qB: {-1,+1}^{mxq}# rB: {-1,+1}^{nxq}# queryL: {0,1}^{mxl}# retrievalL: {0,1}^{nxl}num_query = queryL.shape[0]topkacc = 0# print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')for iter in range(num_query):# gnd:一个长度等于gallery数据集的0/1向量,1表示为正样本(即至少包含query的一个标签),0表示负样本(即,不包含query的标签)。gnd = (np.dot(queryL[iter, :], retrievalL.transpose()) > 0).astype(np.float32)hamm = CalcHammingDist(qB[iter, :], rB) #计算第iter张query图片与gallery数据集的汉明距离ind = np.argsort(hamm) #对汉明距离进行排序,返回下标,表示最相似的图片列表gnd = gnd[ind] #最相似的图片是否为正样本的列表tgnd = gnd[0:topk] #只看前topk个结果tsum = np.sum(tgnd) #前topk个中有多少个预测对了if tsum == 0:continuetopkacc += tsum / topktopkacc = topkacc / num_queryreturn topkaccif __name__=='__main__':queryBinary = np.array([[1,-1,1,1],[-1,1,-1,-1],[1,-1,-1,-1]])galleryBinary = np.array([[ 1,-1,-1,-1],[-1, 1, 1,-1],[ 1, 1, 1,-1],[-1,-1, 1, 1],[ 1, 1,-1,-1],[ 1, 1, 1,-1],[-1, 1,-1,-1]])queryLabel = np.array([[1,0,0],[1,1,0],[0,0,1]], dtype=np.int64)galleryLabel = np.array([[0,1,0],[1,1,0],[1,0,1],[0,0,1],[0,1,0],[0,0,1],[1,1,0]], dtype=np.int64)topk = 5topkmap = CalcTopMap(queryBinary, galleryBinary, queryLabel, galleryLabel, topk)print("map@{}为:{}".format(topk, topkmap))map = CalcMap(queryBinary, galleryBinary, queryLabel, galleryLabel)print("map为:{}".format(map))topkacc = CalcTopAcc(queryBinary, galleryBinary, queryLabel, galleryLabel, topk)print("acc@{}为:{}".format(topk, topkacc))
运行结果:
三、代码详解
参考:https://yongyuan.name/blog/evaluation-of-information-retrieval.html
https://zhuanlan.zhihu.com/p/51955362
图像检索评价指标:mAP@k、mAP的计算相关推荐
- pytorch图像检索评价指标MAP
map是图像检索模型的一个评价指标 以图片中第一个计算AP值为例 P的分别是[1, 2/3, 3/6, 4/9, 5/10] R值分别是[1/5, 2/5, 3/5/, 4/5, 1] AP计算结果 ...
- 目标检测的评价指标P,R,mAP
目标检测的评价指标P,R,mAP 1 基本概念 1.1 IOU(Intersection over Union) 1.2 TP TN FP FN 2. 各种率 2.1 根据IOU计算Precision ...
- ap和map的计算,mAP@.5 mAP@.5:.95的含义
网络的输出有置信度和bbox的位置.根据这两个的综合评价得到一个准确的指标:ap,map. 参考:https://blog.csdn.net/qq_35916487/article/details/8 ...
- java1.8新增超实用Map方法——Map.getOrDefault()和Map.value()方法详解
1. Map.getOrDefault() 翻译一下官方解释: java.util.Map<K, V> V getOrDefault(Object key, V defaultValue) ...
- 【Groovy】map 集合 ( map 集合操作符重载 | 使用 << 操作符添加一个元素 | 代码示例 )
文章目录 一.使用 " << " 操作符添加一个元素 二.代码示例 一.使用 " << " 操作符添加一个元素 对 map 集合 使用 ...
- 【Groovy】map 集合 ( map 集合操作符重载 | - 操作符重载 | 代码示例 )
文章目录 一.map 集合 " - " 操作符重载 二.完整代码示例 一.map 集合 " - " 操作符重载 对 map 集合 使用 " - &qu ...
- 【Groovy】map 集合 ( map 集合操作符重载 | + 操作符重载 | 代码示例 )
文章目录 一.map 集合 " + " 操作符重载 二.代码示例 一.map 集合 " + " 操作符重载 对 map 集合使用 " + " ...
- 【Groovy】map 集合 ( map 集合遍历 | 使用 map 集合的 find 方法遍历 map 集合 | 代码示例 )
文章目录 一.使用 map 集合的 find 方法遍历 map 集合 二.代码示例 一.使用 map 集合的 find 方法遍历 map 集合 使用 map 集合的 find 方法遍历 map 集合 ...
- 【Groovy】map 集合 ( map 集合遍历 | 使用 map 集合的 each 方法遍历 map 集合 | 代码示例 )
文章目录 一.使用 map 集合的 each 方法遍历 map 集合 二.代码示例 一.使用 map 集合的 each 方法遍历 map 集合 遍历 map 集合 , 可以调用 map 集合的 eac ...
最新文章
- npm构建脚本_NPM脚本简介
- The 13th Zhejiang Provincial Collegiate Contest(2016年浙江省赛)
- python 计算累计人数_免费Python入门课程,看到就是赚到~
- el-tooltip位置不灵活_要提高步伐移动的灵活性,注意这5点,加以改正,步伐不再沉重...
- 同一域名端口下,通过nginx部署多个vue项目
- 程序人生--一个程序员对学弟学妹建议
- 如果财富都在部分人手里会怎样?
- cad细等线体不显示_CAD技法大全,如何在CAD中解决好部分图元无法正常显示的问题 ?...
- ms settings personalization
- linux脚本两个分号,Linux Shell中各种分号和括号的用法总结
- win32 字体 api学习总结
- 打造高大上的Canvas粒子动画
- 团队作业-Beta冲刺(周四)
- [索引]引用Balancing bike sharing systems with constraint programming的文章
- 数据运营与数据分析闲谈
- Scratch滚动的天空(2)
- 7. 数据的规整:分组、聚合、合并、重塑
- 大型企业局域网安全解决方案
- 神雕2暂无服务器信息,神雕侠侣2手游4月2日停服维护公告_神雕侠侣2手游4月2日更新了什么_玩游戏网...
- python怎么输出复数_python基础知识及应用(二)输入输出|递归|深浅拷贝|全局变量|复数...