1、跨模态检索输入
- qB:查询输入的汉明码,m*bit(64/128)
- rB:检索集的汉明码,n**bit(64/128)
- query_L:查询输入的标签,m*21(21个类别)
- retrieval_L:检索集的标签,n*21
2、跨模态检索mAP公式
这个公式表示的就是如何计算Q个数据的检索,我们只需要计算每条数据的检索的Ap即可,也就是AveP(q)
AveP中,其中分母表示有几个相关文档,rel(k)表示排名第k的文档是不是相关文档,P(k)表示排名第k个文档的精准率。
3、跨模态检索代码实例
import torch
def calc_hammingDist(B1, B2):
q = B2.shape[1]
if len(B1.shape) < 2:
B1 = B1.unsqueeze(0)
distH = 0.5 * (q - B1.mm(B2.transpose(0, 1)))
return distH
def calc_map_k(qB, rB, query_L, retrieval_L, k=None):
# qB: {-1,+1}^{mxq}
# rB: {-1,+1}^{nxq}
# query_L: {0,1}^{mxl}
# retrieval_L: {0,1}^{nxl}
num_query = query_L.shape[0]
qB = torch.sign(qB)
rB = torch.sign(rB)
map = 0
if k is None:
k = retrieval_L.shape[0]
for iter in range(num_query):
q_L = query_L[iter]
if len(q_L.shape) < 2:
q_L = q_L.unsqueeze(0) # [1, hash length]
#计算检索和查询集有无共同的标签,如有就是1,没有就是0
gnd = (q_L.mm(retrieval_L.transpose(0, 1)) > 0).squeeze().type(torch.float32)
#计算总共有几个是有共同的标签的
tsum = torch.sum(gnd)
#如果一个也没有 直接返回
if tsum == 0:
continue
#计算查询和检索集中的汉明距离
hamm = calc_hammingDist(qB[iter, :], rB)
#排序并返回下标
print(hamm)
_, ind = torch.sort(hamm)
print(ind)
ind.squeeze_()
#根据下标重新给gnd赋值
#根据相关性对汉明距离进行重新排序
print(gnd)
gnd = gnd[ind]
print(gnd)
#计算总共有几个共同的标签
total = min(k, int(tsum))
count = torch.arange(1, total + 1).type(torch.float32)
#计算gnd的非零元素的索引,并且加上1
tindex = torch.nonzero(gnd)[:total].squeeze().type(torch.float32) + 1.0
if tindex.is_cuda:
count = count.cuda()
map = map + torch.mean(count / tindex)
break
map = map / num_query
return map
if __name__ == '__main__':
qB = torch.Tensor([[1, -1, 1, 1],
[-1, -1, -1, 1],
[1, 1, -1, 1],
[1, 1, 1, -1]])
rB = torch.Tensor([[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_L = torch.Tensor([[0, 1, 0, 0],
[1, 1, 0, 0],
[1, 0, 0, 1],
[0, 1, 0, 1]])
retrieval_L = torch.Tensor([[1, 0, 0, 1],
[1, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 0],
[1, 0, 0, 0],
[0, 0, 1, 0]])
map = calc_map_k(qB, rB, query_L, retrieval_L)
print(map)
- 对其中一些参数进行说明,gnd查询的元素和检索集中第几个数据是具有相关性的;hamn计算汉明距离,ind是对汉明距离进行排序后索引的索引,根据这个索引对gnd中的元素进行重复取值,得到新的gnd。然后可以计算出有几个相关数据,然后计算第k个的精准率,然后计算mAP。
gnd = tensor([0., 1., 1., 0., 0., 0.])
number of relevent document = torch.sum(gnd) = 2
hamn = tensor([[1., 2., 2., 3., 4., 2.]])
ind = tensor([[0, 1, 2, 5, 3, 4]])
根据ind取gnd中的元素得到新的gnd
gnd = tensor([0., 1., 1., 0., 0., 0.])
其中P(1) = 1/2; P(2) = 2/3
AveP = P(1)+P(2)/2
这样计算出来一个检索的AP,计算所有的然后除以Q即可得到所有查询集的mAP
REFERENCE
- https://blog.csdn.net/Flyingzhan/article/details/84779607
- https://blog.csdn.net/qq_40680309/article/details/115429280
- https://github.com/WangGodder/deep-cross-modal-hashing/blob/master/torchcmh/evaluate/hashing.py