热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Personreidentification行人重识别(一)

在做跟随车的时候需要考虑到这么一个问题:需要精准的识别要跟随的人,并且这个人是一个背向你的状态。那么在这就提到一个概念:Personre-

在做跟随车的时候需要考虑到这么一个问题:需要精准的识别要跟随的人,并且这个人是一个背向你的状态。那么在这就提到一个概念:Person re-identification。简单来说,就是在多摄像头的复杂场景中,快速定位查找指定目标的所有结果。基本思想其实就是相似度匹配。这个网络模型在很多场景是可以见到的,比如说监控跟踪人物,各种人脸识别闸机等等,首先先介绍几个常用的模型,至于使用我会后面部署到NVidia的Xavier上以及地平线的旭日x3上的。

目录

0x01 Person re-identification

(一)概述与挑战

(二)评估标准

(三)损失函数的定义

0x02 《Relation-Aware Global Attention》

(一)模型架构

(二)项目环境与数据集架构分析

(三)参数配置与整体架构分析

0x03 《Relation Network for Person Re-identification》

(一)整体框架

(二)特征分组方法

(三)GCP模块特征融合方法

(四)one Vs reset方法

(五)损失函数应用位置




0x01 Person re-identification


(一)概述与挑战

行人重识别,简单来说就是要在不同时间、地点或者相机上匹配到一个特定的人,属于图像检索的内容。其难点和核心便在于如何从杂乱的背景、姿态的多样性以及存在遮挡等各种复杂多变的情况下,有效地从人像图像中鉴别并提取视觉特征(即区分出不同的人)。

 

那么这个行人重识别,所面临的挑战有什么:


  • 低分辨率

  • 遮挡

  • 视角、姿态变化

  • 光照变化

  • 视觉模糊性


(二)评估标准


  • 基本所有论文都会提到两个概念:rank1map值。

  • 返回结果中包含了一系列的图像,rank1指的是第一张结果正确。


  • map值的计算:map要计算多次输入的综合ap结果,每张测试图片的计算其实可以简单概述为:一张正确图像本应该是第几个。

比如下面这个例子:

其中的ap计算为(1+2/3+3/6+4/9+5/10)。

之后进行第二次查询:

 


  • 可以得到下一个ap为(1/2+2/5+3/7)。

    那么我们就可以得到两个测试数据,ap分别为0.62,0.44,则map为(0.62+0.44)/2 = 0.53。


(三)损失函数的定义

通常是分类损失+Triplet loss(目标其实就是为了让特征提取的更好)

Triplet loss需要准备三份数据(可以从一个batch中选择),其中Anchor表示当前数据,Positive是跟A相同人的数据,Negative是不同人的数据。(三元组损失)

Triplet loss步骤如下:


  • 分别对3份数据进行编码。

  • 三份数据经过的网络是一样的。

  • 计算之间的差异,通过差异值来更新权重值。

 其目的也很简单,只需让A与P非常接近,A与N尽可能远离。公式:

 是否会存在问题呢?如果f把所有的输入都编码成0,依旧成立。所以这个目标需要重新修改一下:

 其中a通常叫做margin,也就是间隔,表示d(A,P)与d(A,N)至少得相差多少。所以我们就可以得到下面的这条公式:

对于约束条件d(A,P)&#43;a<&#61;d(A,N)&#xff0c;实际中用的最多的是hard negative方法&#xff0c;也就是在选择样本的时候&#xff0c;要让d(A,P)要约等于d(A,N)&#xff0c;这样可以给网络带来一些挑战&#xff0c;才能刺激它来学习&#xff0c;不要让它原封不动。


0x02 《Relation-Aware Global Attention》

在看这篇论文之前&#xff0c;我们可以想到如何通过提取好的照片来进行特征提取&#xff0c;可以有多种方法&#xff0c;比如对这张图片进行分割&#xff0c;分割为4个部分&#xff0c;之后对每个部分进行比对&#xff0c;这也是一个不错的提议&#xff0c;那么就看看RAG是怎么提取特征的叭&#xff1a;


&#xff08;一&#xff09;模型架构

 

论文地址&#xff1a;

https://arxiv.org/pdf/1904.02998v1.pdf

https://openaccess.thecvf.com/content_CVPR_2020/papers/Zhang_Relation-Aware_Global_Attention_for_Person_Re-Identification_CVPR_2020_paper.pdf

GitHub&#xff1a;GitHub - microsoft/Relation-Aware-Global-Attention-Networks: We design an effective Relation-Aware Global Attention (RGA) module for CNNs to globally infer the attention.


注意力机制通过关注重要特征和抑制不重要的特征来提到表示能力。从17年开始&#xff0c;这个注意力机制一直受到关注&#xff0c;不仅在NLP领域上&#xff0c;在CV领域上也得到了很多的关注。在卷积神经网络中&#xff0c;注意力通常是通过局部卷积来学习的&#xff0c;它忽略了全局信息和隐藏关系。如何有效的利用远程上下文信息来全局的学习注意力还没有得到充分的研究。但是在本文中提到了一个有效的关系感知全局注意力的模块&#xff0c;以充分利用全局相关性来推断注意。具体来说&#xff0c;在计算某个特征位置的注意力时&#xff0c;为了掌握全局范围的信息&#xff0c;我们建议这些关系&#xff0c;即它与所有特征位置的成对相关性/亲和性&#xff0c;以及特征本身堆叠在一起&#xff0c;以便通过卷积运算来学习注意力。给定一个中间特征图&#xff0c;我们已经验证了在空间和通道上的有效性


简单来说&#xff0c;本文主要提出了一个RGA(Relation-Aware Global Attention)模块&#xff0c;该模块可以提取空间上不同区域之间的关系向量&#xff0c;从而每个区域的特征能够抓住局部&#xff0c;同时把握全局&#xff1a;

那么a图我们可以理解为是一个空间维度&#xff0c;b图则是一个通道维度&#xff1a;


  • 空间注意力&#xff1a;

    对于一个输入为C×H×W的特征向量&#xff0c;在上图中&#xff0c;我们可以表示为C×3×3大小。分别输入到两个卷积层c1和c2。经过c卷积层后转化为向量[9,c]&#xff0c;两者矩阵相乘&#xff0c;等到[9×9]的矩阵&#xff0c;代表每个向量之间的关系。再将得到的9×9矩阵经过reshape操作分别得到两个[9,3,3]和[9,3,3]矩阵。得到的两个relation feature矩阵可以图书的理解为&#xff0c;我和你之间的关系&#xff0c;以及你和我之间的关系。原始的输入值再经过一个卷积层取所有通道特征图的均值得到一个[1,3,3]的矩阵&#xff0c;因为只需要提取空间信息&#xff08;所在位置&#xff09;&#xff0c;所以将通道数变为1。最后把这三个特征矩阵连接到一起[9&#43;9&#43;1,3,3]。因为卷积网络权值共享&#xff0c;将其压缩为[1,3,3]&#xff0c;从而得到每一个位置的权重值&#xff0c;最后与输入x相乘。


  • 通道注意力

    和空间注意力相似&#xff0c;只不过通道做卷积和reshape操作&#xff0c;获得每个通道的权重值&#xff0c;即判断哪一个特征图重要。

那么我们再看看之前学习过的attention的各种模型&#xff1a;

a图也就是我们常用的卷积神经网络&#xff0c;对于每一个特征x学习一个attention值&#xff0c;因此只能学习到局部特征&#xff0c;而忽视了全局特征。

b图使用全连接网络&#xff08;可以参照《Attention is all you Need》&#xff09;&#xff0c;学习到的attention值来自于所有特征向量的连接&#xff0c;虽然学习到了全局特征&#xff0c;但参数量过大&#xff0c;计算量太大。

c图通过考虑全局的相关信息学习attention的值&#xff0c;即对每一个特征向量&#xff0c;全局的关联信息用一个关系对ri &#61; [ri,1, · · · , ri,5, r1,i, · · · , r5,i]表示&#xff0c;其中其中ri,1表示第i个特征节点和第一个特征节点的关系&#xff0c;以此类推。用一个符号ri&j &#61; [ri,j , rj,i]表示,所有的ri&j组合可以得到x1一个关联特征&#xff0c;组合在一起得到下图中的特征向量r1&#xff0c;再和原始特征向量x1拼接&#xff0c;得到一个relation-aware feature y1, y1 &#61; [x1, r1 ],作为提取attention的特征向量。因此可以看出&#xff0c;基于特征x1得到的attention值a1既包含了局部特征x1&#xff0c;又包含了全局所有特征之间的关系。


&#xff08;二&#xff09;项目环境与数据集架构分析

数据集的下载&#xff1a;CUHK Re-ID

在这我下载的是第三个数据集。之后根据GitHub下所说的&#xff1a;


  1. 创建一个名为 的文件cuhk03//YOUR_DATASET_PATH//YOUR_DATASET_PATH/cuhk03/从CUHK Re-ID下载数据集并提取cuhk03_release.zip. 然后你会有/YOUR_DATASET_PATH/cuhk03/cuhk03_release.

  2. 从person-re-ranking下载训练/测试拆分协议。将两个 matcuhk03_new_protocol_config_detected.mat文件cuhk03_new_protocol_config_labeled.mat放在data/cuhk03. 在默认模式下&#xff0c;我们使用这个新的拆分协议 (767/700)。最后&#xff0c;数据结构看起来像

cuhk03/cuhk03_release/cuhk03_new_protocol_config_detected.matcuhk03_new_protocol_config_labeled.mat...

对于香港科技大学的数据集&#xff0c;我们可以得到&#xff1a;数据集1_001_1_02.png&#xff0c;1为摄像头的id&#xff0c;001为人的id&#xff0c;1为这么一对摄像头中&#xff0c;是前面那个还是后面那个&#xff0c;最后一个数为第几个图。对于数据集的处理&#xff0c;在源码中有这么一段是用于处理.mat文件的&#xff0c;这个文件就是你下载下来的数据集中附带的&#xff0c;它可以对数据集进行区分&#xff1a;

def _process_images(img_refs, campid, pid, save_dir):img_paths &#61; [] # Note: some persons only have images for one viewfor imgid, img_ref in enumerate(img_refs):img &#61; _deref(img_ref)# skip empty cellif img.size &#61;&#61; 0 or img.ndim <3: continue# images are saved with the following format, index-1 (ensure uniqueness)# campid: index of camera pair (1-5)# pid: index of person in &#39;campid&#39;-th camera pair# viewid: index of view, {1, 2}# imgid: index of image, (1-10)viewid &#61; 1 if imgid <5 else 2img_name &#61; &#39;{:01d}_{:03d}_{:01d}_{:02d}.png&#39;.format(campid&#43;1, pid&#43;1, viewid, imgid&#43;1)img_path &#61; osp.join(save_dir, img_name)imsave(img_path, img)img_paths.append(img_path)return img_paths

最后他会生成两个文件夹&#xff1a;images_detected\images_labeled&#xff0c;并且在main.imgreid.py中进行处理&#xff1a;

def get_data(name, split_id, data_dir, height, width, batch_size, num_instances,workers, combine_trainval, eval_rerank&#61;False):## Datasetsif name &#61;&#61; &#39;cuhk03labeled&#39;:dataset_name &#61; &#39;cuhk03&#39;dataset &#61; data_manager.init_imgreid_dataset(root&#61;data_dir, name&#61;dataset_name, split_id&#61;split_id,cuhk03_labeled&#61;True, cuhk03_classic_split&#61;False,)dataset.images_dir &#61; osp.join(data_dir, &#39;/CUHK03_New/images_labeled/&#39;)elif name &#61;&#61; &#39;cuhk03detected&#39;:dataset_name &#61; &#39;cuhk03&#39;dataset &#61; data_manager.init_imgreid_dataset(root&#61;data_dir, name&#61;dataset_name, split_id&#61;split_id,cuhk03_labeled&#61;False, cuhk03_classic_split&#61;False,)dataset.images_dir &#61; osp.join(data_dir, &#39;/CUHK03_New/images_detected/&#39;)## Num. of training IDsnum_classes &#61; dataset.num_train_pids

&#xff08;三&#xff09;参数配置与整体架构分析

以上就是在进行训练的过程。其中进行了很多次卷积处理&#xff0c;并且进行残差连接&#xff0c;不断地进行特征提取。那么接下来就是核心的步骤了&#xff0c;判断你和我之间的关系&#xff0c;我和你之间的关系&#xff1a;

Spatial Relation-Aware Attention 空间关系感知注意力—RGA-S

可以注意到它构建了两个大小一样的辅助特征图&#xff0c;用于存储关系。之后进行resize&#xff0c;更改维度&#xff0c;调换顺序&#xff0c;以便于计算你我关系&#xff0c;使矩阵可以更好的计算。做完乘积的操作后&#xff0c;即可以得到我跟你的关系&#xff0c;以及你跟我的关系&#xff0c;将其拼接在一起&#xff0c;resize回去&#xff0c;resize为256个特征的向量图&#xff0c;最后我们将每个特征都求取平均&#xff0c;获得一个平均值&#xff0c;得到一个矩阵&#xff0c;然后拼起来&#xff0c;再浓缩起来&#xff0c;最后乘以x&#xff0c;变换为原来的大小。以上就是空间注意力机制的处理。


通过CNN层得到的特征图为的shape为HWC&#xff0c;设计的RGA-S空间关系感知注意力来学习大小为H*W的空间注意力图&#xff0c;取每个空间位置的C维特征向量作为特征节点。所有的空间形成位置形成一个有N&#61;WxH个节点的图形&#xff0c;通过建立空间中节点之间的相似性矩阵&#xff0c;即NxN的矩阵&#xff0c;来表示节点之间的成对关系。 为了方便解释RGA-S如何具体实现&#xff0c;我们以经过第一个残差块res1_layer的RGA-S1为例来给予说明&#xff0c;其它的RGA-S实现于此一样&#xff0c;只不过是特征图的H和W不一样而已。经过数据增强输入图片的shape为3x256x128&#xff0c;首先经过Zeropadding&#xff0c;然后是步长stride&#61;2的卷积块(Conv&#43;BN&#43;Relu)&#xff0c;得到的shape为64x128x64&#xff0c;再经过stride&#61;2的MaxPooling&#xff0c;得到的shape为64x64x32&#xff0c;经过残差网络的第一个残差块&#xff0c;其中的卷积步长stride&#61;1&#xff0c;得到res1_layer的shape为256x64x32&#xff0c;作为RGA-S1的输入。

RGA-S1的输入input为256x64x32&#xff0c;两个去向&#xff0c;如上图所示&#xff0c;一个是向右做embedding操作&#xff0c;即嵌入全局信息。具体做法是经过一个1x1卷积进行降维&#xff0c;将通道数减少为 256/8 &#61;32&#xff0c;得到g_xs&#xff0c;此时shape为32x64x32&#xff0c;由于我们需要实现的是空间注意力机制&#xff0c;因此沿着通道数方向&#xff0c;进行mean求平均操作&#xff0c;将64维通道数使用其均值进行替代&#xff0c;此时g_xs的shape维1x64x32。第二个去向向下的操作&#xff0c;首先经过一个1x1卷积进行降维&#xff0c;将通道数减少为 256/8 &#61;32&#xff0c;此时shape为32x64x32&#xff0c;记为theta_xs&#xff1b;进行了两次这样的操作&#xff0c;另一个记为phi_xs&#xff0c;shape同样为32x64x32。然后我们将theta_xs和phi_xs进行reshape操作&#xff0c;reshape为32x(64x32)&#61;32x2048&#xff0c;然后再将theta_xs经过一次维度的调换permute&#xff0c;故此时的shape为2048x32&#xff0c;而phi_xs的shape为32x2048&#xff0c;于是将theta_xs和phi_xs进行矩阵的乘法&#xff0c;得到Gs&#xff0c;shape为2048x2048&#xff0c;至此Gs表示的就是该特征图空间中2048个特征节点之间的成对关系。首先找到我和别人的成对关系&#xff0c;将Gs进行reshape操作得到Gs_out&#xff0c;shape为 2048,64,32。其次&#xff0c;找到别人和我之间的成对关系&#xff0c;于是将Gs进行维度调换permute操作&#xff0c;得到的shape为2048x2048&#xff0c;再进行reshape操作得到Gs_in&#xff0c;shape为2048,64,32&#xff0c;进行关系对的堆叠cat操作&#xff0c;得到Gs_joint&#xff0c;shape为2048&#43;2048&#61;4096,64,32&#xff0c;然后再将Gs_joint进行1x1操作将4096浓缩成2048/8&#61;256&#xff0c; 使用256维来代表空间成对关系&#xff0c;此时Gs_joint的shape变为256,64,32。于是&#xff0c;将全局的信息与空间中特征点之间的关系进行堆叠操作&#xff0c;得到ys&#xff0c;shape为257,64,32&#xff0c;再将关系维度使用1x1卷积进行浓缩&#xff0c;先将维度压缩成257/8&#61;32&#xff0c;再使用1x1卷积压缩为1&#xff0c;shape为1,64,32&#xff0c;即我们得到了1个特征图上空间中特征节点之间的关系&#xff0c;输入input的shape为256,64,32&#xff0c;我们直到空间中的特征节点在即使在不同的特征图中其位置是不变的&#xff0c;于是我们将上述得到的一个特征节点关系特征图进行repeat操作&#xff0c;得到256个关系特征图&#xff0c;shape变为1,64,32->256,64,32&#xff0c;然后求sigmoid&#xff0c;转化为0-1之间的概率值&#xff0c;最后于输入input进行相乘操作&#xff0c;得到最后的输出256,64,32&#xff0c;即输出带有空间注意力的特征节点值。 引用&#xff1a;行人重识别—Relation-Aware Global Attention模型介绍及代码实现_ManManMan池的博客-CSDN博客_行人重识别代码实现


主要代码&#xff1a;

def forward(self, x):b, c, h, w &#61; x.size()if self.use_spatial:# spatial attentiontheta_xs &#61; self.theta_spatial(x) phi_xs &#61; self.phi_spatial(x)theta_xs &#61; theta_xs.view(b, self.inter_channel, -1)theta_xs &#61; theta_xs.permute(0, 2, 1)phi_xs &#61; phi_xs.view(b, self.inter_channel, -1)Gs &#61; torch.matmul(theta_xs, phi_xs)Gs_in &#61; Gs.permute(0, 2, 1).view(b, h*w, h, w)Gs_out &#61; Gs.view(b, h*w, h, w)Gs_joint &#61; torch.cat((Gs_in, Gs_out), 1)Gs_joint &#61; self.gg_spatial(Gs_joint)g_xs &#61; self.gx_spatial(x)g_xs &#61; torch.mean(g_xs, dim&#61;1, keepdim&#61;True)ys &#61; torch.cat((g_xs, Gs_joint), 1)W_ys &#61; self.W_spatial(ys)if not self.use_channel:out &#61; F.sigmoid(W_ys.expand_as(x)) * xreturn outelse:x &#61; F.sigmoid(W_ys.expand_as(x)) * x

Channel Relation-Aware Attention 通道关系感知注意力—RGA-C

那么下面则对应的是channel的处理&#xff1a;

if self.use_channel:# channel attentionxc &#61; x.view(b, c, -1).permute(0, 2, 1).unsqueeze(-1)theta_xc &#61; self.theta_channel(xc).squeeze(-1).permute(0, 2, 1)phi_xc &#61; self.phi_channel(xc).squeeze(-1)Gc &#61; torch.matmul(theta_xc, phi_xc)Gc_in &#61; Gc.permute(0, 2, 1).unsqueeze(-1)Gc_out &#61; Gc.unsqueeze(-1)Gc_joint &#61; torch.cat((Gc_in, Gc_out), 1)Gc_joint &#61; self.gg_channel(Gc_joint)g_xc &#61; self.gx_channel(xc)g_xc &#61; torch.mean(g_xc, dim&#61;1, keepdim&#61;True)yc &#61; torch.cat((g_xc, Gc_joint), 1)W_yc &#61; self.W_channel(yc).transpose(1, 2)out &#61; F.sigmoid(W_yc) * xreturn out

做法跟之前一样&#xff0c;新建两个辅助的特征向量图&#xff0c;之后进行乘积&#xff0c;拼接&#xff0c;在通过卷积层浓缩 &#xff0c;然后再进行拼接&#xff0c;得到总的特征图&#xff0c;在使用两个卷积&#xff0c;将其转为256个图中的权重分配&#xff0c;再乘上x即可。


给定一个中间特征图为的shape为HWC&#xff0c;设计的RGA-C空间关系感知注意力来学习一个通道数为C的通道注意力向量&#xff0c;将每个通道数上的d&#61;HxW维特征向量作为特征节点&#xff0c;所有通道形成C个节点的图形&#xff0c;通过建立节点之间的相似性矩阵&#xff0c;即CxC的矩阵&#xff0c;来表示节点之间的成对关系。

RGA-C1的输入input为256x64x32&#xff0c;先对input进行reshape操作&#xff0c;shape为256x2048&#xff0c;再进行维度的调换permute操作&#xff0c;shape为2048x256&#xff0c;unsqueeze操作&#xff0c;得到xc&#xff0c;shape为2048,256,1。由于我们是在通道上实现关系感知全局注意力&#xff0c;因此需要将特征形式转化为与RGA-S1类似的输入形式。得到的新输入xc有两个去向&#xff0c;如上图所示&#xff0c;一个是向右做embedding操作&#xff0c;即嵌入全局信息。具体做法是经过一个1x1卷积进行降维&#xff0c;将通道数减少为 256/8 &#61;32&#xff0c;得到g_xc&#xff0c;此时shape为32x256x1&#xff0c;由于我们需要实现的是空间注意力机制&#xff0c;因此沿着空间的方向&#xff0c;进行mean求平均操作&#xff0c;将32维空间特征使用其均值进行替代&#xff0c;此时g_xc的shape维1x256x1。第二个去向向下的操作&#xff0c;首先经过一个1x1卷积进行降维&#xff0c;将通道数减少为 256/8 &#61;32&#xff0c;此时shape为32x256x1&#xff0c;记为theta_xc&#xff1b;进行了两次这样的操作&#xff0c;另一个记为phi_xc&#xff0c;shape同样为32x256x1。将theta_xc和phi_xc进行squeeze操作&#xff0c;去掉最后一个维度&#xff0c;因为我们计算关系矩阵时只需要二维的&#xff0c;此时theta_xc和phi_xc的shape都为32x256&#xff0c;再将theta_xc进行permute维度调换操作&#xff0c;shape为256x32&#xff0c;为了进行矩阵乘法操作&#xff0c;然后将theta_xc和phi_xc进行矩阵的乘法&#xff0c;得到Gc&#xff0c;shape为256x256&#xff0c;至此Gc表示的就是该特征图通道上256个特征节点之间的成对关系。首先找到我和别人的成对关系&#xff0c;将Gc进行unsqueeze操作得到Gc_out&#xff0c;shape为 256,256,1。其次&#xff0c;找到别人和我之间的成对关系&#xff0c;于是将Gs进行维度调换permute操作&#xff0c;得到的shape为256x256&#xff0c;再进行unsqueeze操作得到Gc_in&#xff0c;shape为256,256,1&#xff0c;进行关系对的堆叠cat操作&#xff0c;得到Gc_joint&#xff0c;shape为256&#43;256&#61;512,256,1&#xff0c;然后再将Gc_joint进行1x1操作将512浓缩成256/8&#61;32&#xff0c; 使用32维来代表通道上特征节点间关系&#xff0c;此时Gc_joint的shape变为32,256,1 。最后&#xff0c;将全局的信息与空间中特征点之间的关系进行堆叠操作&#xff0c;得到yc&#xff0c;shape为33,256,1&#xff0c;再将关系维度使用1x1卷积进行浓缩&#xff0c;先将维度压缩成33/8&#61;4&#xff0c;再使用1x1卷积压缩为1&#xff0c;shape为1,256,1&#xff0c;最后再进行维度的调换permute&#xff0c;shape变为 256,1,1,。即我们得到了在通道维度上256个特征节点之间的关系&#xff0c;然后求sigmoid&#xff0c;转化为0-1之间的概率值&#xff0c;最后与输入input256x64x32进行相乘操作&#xff0c;得到最后的输出256,64,32&#xff0c;即输出带有通道注意力的特征节点值。 引用&#xff1a;行人重识别—Relation-Aware Global Attention模型介绍及代码实现_ManManMan池的博客-CSDN博客_行人重识别代码实现


损失函数loss

当进行网络的训练时&#xff0c;网络的输出结果应该是两个&#xff0c;即输入图像的编码特征向量类别的分类结果。编码的特征向量用于计算三元组损失Triplet loss&#xff0c;类别的结果用于计算类别损失。


  • 分类损失&#xff1a;采用了平滑标签的交叉熵损失函数。具体实现的代码&#xff1a;

class CrossEntropyLabelSmoothLoss(nn.Module):"""Cross entropy loss with label smoothing regularizer.Reference:Szegedy et al. Rethinking the Inception Architecture for Computer Vision. CVPR 2016.Equation: y &#61; (1 - epsilon) * y &#43; epsilon / K.Args:num_classes (int): number of classes.epsilon (float): weight."""def __init__(self, num_classes, epsilon&#61;0.1, use_gpu&#61;True):super(CrossEntropyLabelSmoothLoss, self).__init__()self.num_classes &#61; num_classesself.epsilon &#61; epsilonself.use_gpu &#61; use_gpuself.logsoftmax &#61; nn.LogSoftmax(dim&#61;1)def forward(self, inputs, targets):"""Args:inputs: prediction matrix (before softmax) with shape (batch_size, num_classes)targets: ground truth labels with shape (num_classes)"""log_probs &#61; self.logsoftmax(inputs)# 进行one-hot编码 batch,num_classestargets &#61; torch.zeros(log_probs.size()).scatter_(1, targets.unsqueeze(1).cpu(), 1)if self.use_gpu: targets &#61; targets.cuda()# 进行标签平滑targets &#61; (1 - self.epsilon) * targets &#43; self.epsilon / self.num_classesloss &#61; (- targets * log_probs).mean(0).sum()return loss&#96;&#96;&#96;c

  • 三元组损失

三元组损失需要准备3份数据&#xff0c;我们都是从一个batch中选取的&#xff0c;其中包含 了Anchor Positive Negative的信息&#xff0c;之后使用AP AN对map值进行计算。可以看看上面的有关计算&#xff1a;

 f表示的就是CNN进行特征提取&#xff0c;a通常叫做margin&#xff0c;也就是间隔&#xff0c;表示d(A,P)和d(A,N)至少得相差多少&#xff0c;但是我们直到A和P是相同的数据&#xff0c;它们的距离肯定很小&#xff0c;而A和N是不同的数据&#xff0c;距离自然很大。因此在实际中&#xff0c;我们在三元组损失中添加了hard negative mining的方法&#xff0c;具体做法就是&#xff0c;假设我们的一个batch中共8张图像&#xff0c;其中前四张是同一个人的一组图像&#xff0c;而后四张与前四张不是同一个人的一组图像&#xff0c;我们假设第一章图像就是当前的数据&#xff0c;对于hard negative&#xff0c;我们就是在第2-4张图像中&#xff0c;找到与当前数据距离最大的图像&#xff0c;即使||f(A)-f(P)||尽可能的很大&#xff0c;而在后四张图像中找到与当前数据距离最小的图像&#xff0c;即使||f(A)-f(N)||尽可能的很小。也就是在选择样本的时候让d(A,P)和d(A,N)尽可能相等&#xff0c;给网络一些挑战&#xff0c;才能刺激它来学习。

class TripletHardLoss(object):def __init__(self, margin&#61;None, metric&#61;"euclidean"):self.margin &#61; marginself.metric &#61; metricif margin is not None:self.ranking_loss &#61; nn.MarginRankingLoss(margin&#61;margin)else:self.ranking_loss &#61; nn.SoftMarginLoss()def __call__(self, global_feat, labels, normalize_feature&#61;False):# global_feat N&#xff0c;2048if normalize_feature:global_feat &#61; normalize(global_feat, axis&#61;-1)if self.metric &#61;&#61; "euclidean":# 计算batch之间的相互距离dist_mat &#61; euclidean_dist(global_feat, global_feat)elif self.metric &#61;&#61; "cosine":dist_mat &#61; cosine_dist(global_feat, global_feat)else:raise NameErrordist_ap, dist_an &#61; hard_example_mining(dist_mat, labels)y &#61; dist_an.new().resize_as_(dist_an).fill_(1)if self.margin is not None:loss &#61; self.ranking_loss(dist_an, dist_ap, y)else:loss &#61; self.ranking_loss(dist_an - dist_ap, y)prec &#61; (dist_an.data > dist_ap.data).sum() * 1. / y.size(0)return loss

其他的东西&#xff0c;就是类似于resnet50了。

训练传入参数&#xff1a;

 


0x03 《Relation Network for Person Re-identification》

论文地址&#xff1a;https://arxiv.org/pdf/1911.09318.pdf

GitHub&#xff1a;GitHub - cvlab-yonsei/RRID: An official implementation of "Relation Network for Person Re-identification" (AAAI 2020) in PyTorch.

 


&#xff08;一&#xff09;整体框架

局部特征与全局关系的计算方法

 


  • 特征图局部特征提取&#xff0c;对图像进行切割。&#xff08;假设六份&#xff09;

  • maxpooling&#xff1a;六个局部特征代表&#xff0c;再求一个整体特征&#xff0c;之后就可以求得局部与整体的关系。&#xff08;GCP&#xff09;

  • 再计算当前的这个特征与其他特征之间的关系&#xff0c;形成一个向量。


&#xff08;二&#xff09;特征分组方法


  • 首先对整体进行特征提取&#xff0c;先将输入数据resize&#xff0c;然后输入到resnet中。基本所有的ReID模型都是先进行这一步&#xff0c;加载imagene预训练的resnet50模型。


  • 将特征图分块&#xff0c;直接在h维度进行截取&#xff0c;并没有利用其他辅助信息&#xff0c;为了得到更综合的特征&#xff0c;源码分了三组实验。


&#xff08;三&#xff09;GCP模块特征融合方法


  • 计算GCP特征&#xff0c;avgPool会引入局部与背景信息&#xff0c;其差异特征可以更好的描述局部搞关系&#xff0c;一定程度上去掉了一些噪音特征的干扰。&#xff08;光照、遮挡等&#xff09;

 为什么要使用avgPool求得平均特征&#xff1f;不妨想想maxPool所带来的利弊&#xff0c;maxPool会把这个特征进行放大&#xff0c;但是会忽略掉一些小特征。如果加了avgPool会带进去一些噪音&#xff0c;比如背景。所以我们综合一下&#xff0c;各取所长&#xff0c;使用&#xff08;Avg-max&#xff09;即可体验局部之间的关系。怎么理解呢&#xff0c;max可以理解为各个核心&#xff0c;之后使用分散的特征来区别之间的关系&#xff0c;即可很好的描述了局部关系。

GAP则相对于全局都有了&#xff0c;GMP相当于最核心那一块&#xff0c;GCP之后相对于各个关键点的信息了(contrastive)。


&#xff08;四&#xff09;one Vs reset方法

我们以p1为例子&#xff0c;我们将除了p外的其他特征做一次avgPool&#xff0c;在做一层conv&#xff0c;再把p1传进来做一次conv&#xff0c;之后将其特征融合&#xff0c;即可知道p1与其他人之间的关系。之后我们再加入p1&#xff0c;就可以得到q1。之后p2.....pn都是做一样的处理。

出发点在于别把局部信息孤立来算&#xff0c;有点类似于attention的方法。


&#xff08;五&#xff09;损失函数应用位置

损失有分类损失以及三元组损失&#xff0c;他们可以加在这些地方&#xff1a;

 


推荐阅读
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 标题: ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • 人工智能推理能力与假设检验
    最近Google的Deepmind开始研究如何让AI做数学题。这个问题的提出非常有启发,逻辑推理,发现新知识的能力应该是强人工智能出现自我意识之前最需要发展的能力。深度学习目前可以 ... [详细]
author-avatar
灬处男求包养灬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有