行人reid ,AQE
Numpy中排序操作partition,argpartition,sort,argsort
>>> np.partition(a,range(1,5))
array([0, 1, 2, 3, 4, 8, 9])
>>> np.partition(a,5) #表示 从小到大排序的第5个位置也就是索引4,是小大顺序的是数组中的4,作为分界线
>比4小的和比4大的,左右顺序没有要求
array([0, 1, 3, 2, 4, 8, 9])
有range(1,5) 表示
第一个位置,是第一小的0
第二个位置是第二小的1
第三位置是第三小的2
第四位置是第四小的3
第五个位置是第五小的4
剩下的位置都是比第五位置大的元素
这就可以解释,负号是 大小排序,默认小大排序,这里的sim 是cos距离越大越相似所以
下面返回的是左半部分 第一个位置到 qe_k + 1位置 顺序的数据, 右半部分不管顺序,速度更快
只关注 topk 范围的数据就用这种犯方法
init_rank = np.argpartition(-sim, range(1, qe_k + 1))
AQE计算过程:
每张图片输出的特征,经过topK *weight,mean等操作变成一个新的均值特征,维度都不变,
但是对于该底库的查询,均值特征更具有代表性,因为这是排序前10 (qe_k: int = 10)的均值,而且有权重大小的均值,不相似的会更不相似
这样计算的均值特征是查询集和底库中存在的最相似图片的权重均值,所以用这个均值特征替代模型输出的特征,再后续的map rank 特征比对中,能找到更靠前的图片
1、计算相似度
合并所有query gallery 特征向量 变成一个 [n,2048]向量a, 然后自己和自己计算余弦距离相似度 a*aT
2、计算weight:
排序从大到小(余弦距离越大越相似),得到 topK 个距离, 然后开三次方(小的更小),这个权重意味着,非常相似的还是比较相似,不太相似权重会从小变得更小
3、计算前topk 的平均特征
现在是前 topK 个特征向量,都对应了一个权重
然后 np.mean(all_feat[init_rank[:qe_k], :] * weights, axis=0), [n,2048]特征对应topk 的特征[topk,2028] 乘以对应的权重,之后求平均,得到一个平均特征向量 【1,2048】
循环的是 一张图片 和所有查询集和底库图片,求得的前topk 的一个均值,
例如底库和查询集一共有10万图片,遍历10万次,每次获得一个前topK 平均特征向量,
返回的特征维度和输入的特征维度一样,但是特征是新的特征
norm_feat = F.normalize(torch.from_numpy(all_feat), p=2, dim=1)
query_feat = torch.from_numpy(all_feat[:num_query])
gallery_feat = torch.from_numpy(all_feat[num_query:])
# based on
# https://github.com/PyRetri/PyRetri/blob/master/pyretri/index/re_ranker/re_ranker_impl/query_expansion.py
import numpy as np
import torch
import torch.nn.functional as F
def aqe(query_feat: torch.tensor, gallery_feat: torch.tensor,
qe_times: int = 1, qe_k: int = 10, alpha: float = 3.0):
"""
Combining the retrieved topk nearest neighbors with the original query and doing another retrieval.
c.f. https://www.robots.ox.ac.uk/~vgg/publications/papers/chum07b.pdf
Args :
query_feat (torch.tensor):
gallery_feat (torch.tensor):
qe_times (int): number of query expansion times.
qe_k (int): number of the neighbors to be combined.
alpha (float):
每张图片输出的特征,经过topK *weight,mean等操作变成一个新的均值特征,维度都不变,但是对于该底库的查询,
均值特征更具有代表性,因为这是排序前10 (qe_k: int = 10)的均值,而且有权重大小的均值,相似还是比较相似
不相似的会更不相似,这样计算的均值特征是查询集和底库中存在的最相似图片的权重均值,所以用这个均值特征替代模型输出的特征
再后续的map rank 特征比对中,能找到更靠前的图片
"""
num_query = query_feat.shape[0]
all_feat = torch.cat((query_feat, gallery_feat), dim=0)
norm_feat = F.normalize(all_feat, p=2, dim=1)
all_feat = all_feat.numpy() #tensor to numpy
for i in range(qe_times):
all_feat_list = []
# 6行就是6个人特征,自己和自己做余弦距离,第一行,和所有行会得到6个值, 第二行和所有行得到6个值,
# (m,n) * (n,m) 得到 (m,m),一个特征向量得到一个距离值,和所有特征向量得到 m 个值
sims = torch.mm(norm_feat, norm_feat.t()) #矩阵乘积 列1=行2, 结果会变成 【行1,列2】,query行query列,
sims = sims.data.cpu().numpy()
for sim in sims:
#默认小大排序,现在cos 距离越大越相似,大小排序索引,只关心topk
init_rank = np.argpartition(-sim, range(1, qe_k + 1)) #返回第一大的元素,比第二个参数位置的小的一部分索引和大的一部分索引,比sort,argsort速度快,主要用来数组多少个大元素或者小元素
weights = sim[init_rank[:qe_k]].reshape((-1, 1)) #行变成列向量,二维,排序前k最大的元素
# 排序最相似的余弦距离例如【1,0.98,0.91,0.5】,再开3次方,是为了拉开这个值,变得更小,接近1基本不变
# 这个权重意味着,非常相似的还是比较相似,不太相似权重会从小变得更小
# 权重是前topk 数量个权重
weights = np.power(weights, alpha)
# 合并所有的查询和所有底库的数据,用前 topk 的余弦距离,进行权重的一个计算,再开三次方
# 排序的前qe_k个特征,乘以一个权重,完全相似,就是weight=1,特征不变,
# 前 topk 个特征,乘以对应权重,然后 求平均值,得到一个 平均特征向量 [1,2048]
# 循环的是 一张图片和本身及其他所有图片的,求得的前topk 得到一个均值
# 10万查询+底库图片,会得到10万个均值特征,就是把图片输出的特征,经过topK *weight,mean等操作变成一个新的特征
all_feat_list.append(np.mean(all_feat[init_rank[:qe_k], :] * weights, axis=0))
all_feat = np.stack(all_feat_list, axis=0)
norm_feat = F.normalize(torch.from_numpy(all_feat), p=2, dim=1)
query_feat = torch.from_numpy(all_feat[:num_query])
gallery_feat = torch.from_numpy(all_feat[num_query:])
return query_feat, gallery_feat
本文地址:https://blog.csdn.net/m0_37192554/article/details/107482947
上一篇: 菜椒辣吗?用菜椒可以做什么菜品呢?