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的计算相关推荐

  1. 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计算结果 ...

  2. 目标检测的评价指标P,R,mAP

    目标检测的评价指标P,R,mAP 1 基本概念 1.1 IOU(Intersection over Union) 1.2 TP TN FP FN 2. 各种率 2.1 根据IOU计算Precision ...

  3. ap和map的计算,mAP@.5 mAP@.5:.95的含义

    网络的输出有置信度和bbox的位置.根据这两个的综合评价得到一个准确的指标:ap,map. 参考:https://blog.csdn.net/qq_35916487/article/details/8 ...

  4. java1.8新增超实用Map方法——Map.getOrDefault()和Map.value()方法详解

    1. Map.getOrDefault() 翻译一下官方解释: java.util.Map<K, V> V getOrDefault(Object key, V defaultValue) ...

  5. 【Groovy】map 集合 ( map 集合操作符重载 | 使用 << 操作符添加一个元素 | 代码示例 )

    文章目录 一.使用 " << " 操作符添加一个元素 二.代码示例 一.使用 " << " 操作符添加一个元素 对 map 集合 使用 ...

  6. 【Groovy】map 集合 ( map 集合操作符重载 | - 操作符重载 | 代码示例 )

    文章目录 一.map 集合 " - " 操作符重载 二.完整代码示例 一.map 集合 " - " 操作符重载 对 map 集合 使用 " - &qu ...

  7. 【Groovy】map 集合 ( map 集合操作符重载 | + 操作符重载 | 代码示例 )

    文章目录 一.map 集合 " + " 操作符重载 二.代码示例 一.map 集合 " + " 操作符重载 对 map 集合使用 " + " ...

  8. 【Groovy】map 集合 ( map 集合遍历 | 使用 map 集合的 find 方法遍历 map 集合 | 代码示例 )

    文章目录 一.使用 map 集合的 find 方法遍历 map 集合 二.代码示例 一.使用 map 集合的 find 方法遍历 map 集合 使用 map 集合的 find 方法遍历 map 集合 ...

  9. 【Groovy】map 集合 ( map 集合遍历 | 使用 map 集合的 each 方法遍历 map 集合 | 代码示例 )

    文章目录 一.使用 map 集合的 each 方法遍历 map 集合 二.代码示例 一.使用 map 集合的 each 方法遍历 map 集合 遍历 map 集合 , 可以调用 map 集合的 eac ...

最新文章

  1. npm构建脚本_NPM脚本简介
  2. The 13th Zhejiang Provincial Collegiate Contest(2016年浙江省赛)
  3. python 计算累计人数_免费Python入门课程,看到就是赚到~
  4. el-tooltip位置不灵活_要提高步伐移动的灵活性,注意这5点,加以改正,步伐不再沉重...
  5. 同一域名端口下,通过nginx部署多个vue项目
  6. 程序人生--一个程序员对学弟学妹建议
  7. 如果财富都在部分人手里会怎样?
  8. cad细等线体不显示_CAD技法大全,如何在CAD中解决好部分图元无法正常显示的问题 ?...
  9. ms settings personalization
  10. linux脚本两个分号,Linux Shell中各种分号和括号的用法总结
  11. win32 字体 api学习总结
  12. 打造高大上的Canvas粒子动画
  13. 团队作业-Beta冲刺(周四)
  14. [索引]引用Balancing bike sharing systems with constraint programming的文章
  15. 数据运营与数据分析闲谈
  16. Scratch滚动的天空(2)
  17. 7. 数据的规整:分组、聚合、合并、重塑
  18. 大型企业局域网安全解决方案
  19. 神雕2暂无服务器信息,神雕侠侣2手游4月2日停服维护公告_神雕侠侣2手游4月2日更新了什么_玩游戏网...
  20. python怎么输出复数_python基础知识及应用(二)输入输出|递归|深浅拷贝|全局变量|复数...

热门文章

  1. 欣向路由器:四大过人绝技的应用价值(转)
  2. 中兴新支点操作系统加入腾讯发起的OpenCloudOS开源社区:希望百花齐放
  3. 经典检验各种数据格式的正则表达式
  4. BERT是怎样炼成的--词向量发展史
  5. sandboxie的使用方法
  6. php 磁盘配额,Linux edquota命令:修改用户(群组)的磁盘配额
  7. 建筑五金件建筑材料英国UKCA认证—EN 179
  8. Microsoft Office 2003的安装
  9. 阿里云大模型通义千问申请入口,如何申请?
  10. 解决Win10找不到msvcr120_clr0400.dll问题