《Clothes-Changing Person Re-identification with RGB Modality Only》

paper: https://arxiv.org/pdf/2204.06890v1.pdf

code: guxinqian/Simple-CCReID: Pytorch implementation of ‘Clothes-Changing Person Re-identification with RGB Modality Only. In CVPR, 2022.’ (github.com)

任务

换装人员重识别

出发点

提取与衣服无关的特征,如脸型、发型、体形和步态。目前大多数工作主要集中在从多模态信息(如剪影和草图)中建模身体形状,但没有充分利用原始 RGB 图像中与衣服无关的信息。

创新点

文章提出一种基于衣服的对抗性损失(CAL),通过惩罚 re-id 模型对衣服的预测能力(其实就是个分类器),从原始 RGB 图像中挖掘与衣服无关的特征

做法

首先通过最小化Lc来优化衣服分类器。然后固定衣服分类器的参数,最小化Lid和Lca,迫使backbone学习与衣服无关的特征。(每张图片对应一个一个身份标签和服装标签,将衣服类定义为细粒度标识类——所有同一身份的样本都根据他们的衣服被划分为属于该身份的不同类别,不同的人即使穿着相同的衣服也不会共享相同的衣服标签)

image-20220504092335366

Clothes-based Adversarial Loss

Training clothes classifier

Lc采用交叉熵损失

Learning clothes-irrelevant features

固定衣服分类器的参数,并强制主干学习与衣服无关的特征。为此,应该惩罚re-id模型对于衣服的预测能力

然而,由于衣服类被定义为细粒度类,因此惩罚re-id模型对于所有衣服类别的预测能力,也会降低其预测身份的能力,这对re-id是有害的。

那么最终的目的是使经过训练的服装分类器无法区分相同身份和不同服装的样本

所以,Lca是一个multi-positive-class classification loss,属于同一个身份的不同服装类互为正类。(把不同衣服的只要是属于同一个id身份的衣服类都视为衣服正类)

image-20220504101750986

Si+(Si-)是一个有相同身份的衣服标签fi的集合,K是S中的衣服类别数量,q(c)是第c个衣服类别的交叉熵损失的权重,同一件衣服同一个身份的正例,和不同衣服同一个身份的正例有相同的权重1/K。

同时,为了在不严重降低衣服一致性识别精度的情况下提高模型的换衣识别能力,等式(4)可替换为:

image-20220504105337953

image-20220504105427890

另外,穿着相同衣服的正例比穿着不同衣服的正例有更大的权重。

在优化CAL的同时,对身份分类器进行了优化。因此,第二步的优化过程是:

image-20220504105540307

当仅使用Lid进行训练时,该模型在优化的早期阶段倾向于学习简单样本(具有相同的衣服),然后逐渐学习区分困难样本(具有相同的身份和不同的衣服)。类似课程学习方式,但尽管如此(6)中并未抛弃Lid。其原因是,在优化的早期阶段,只有最小化Lca并迫使模型区分硬样本,才可能导致局部最优。相反,在我们的实验中,在第一次降低学习率后,增加了Lca用于训练。

``

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class ClothesBasedAdversarialLoss(nn.Module):
""" Clothes-based Adversarial Loss.

Reference:
Gu et al. Clothes-Changing Person Re-identification with RGB Modality Only. In CVPR, 2022.

Args:
scale (float): scaling factor.
epsilon (float): a trade-off hyper-parameter.
"""
def __init__(self, scale=16, epsilon=0.1):
super().__init__()
self.scale = scale
self.epsilon = epsilon

def forward(self, inputs, targets, positive_mask):
"""
Args:
inputs: prediction matrix (before softmax) with shape (batch_size, num_classes)
targets: ground truth labels with shape (batch_size)
positive_mask: positive mask matrix with shape (batch_size, num_classes). The clothes classes with
the same identity as the anchor sample are defined as positive clothes classes and their mask
values are 1. The clothes classes with different identities from the anchor sample are defined
as negative clothes classes and their mask values in positive_mask are 0.
"""
inputs = self.scale * inputs
negtive_mask = 1 - positive_mask
identity_mask = torch.zeros(inputs.size()).scatter_(1, targets.unsqueeze(1).data.cpu(), 1).cuda()

exp_logits = torch.exp(inputs)
log_sum_exp_pos_and_all_neg = torch.log((exp_logits * negtive_mask).sum(1, keepdim=True) + exp_logits)
log_prob = inputs - log_sum_exp_pos_and_all_neg

mask = (1 - self.epsilon) * identity_mask + self.epsilon / positive_mask.sum(1, keepdim=True) * positive_mask
loss = (- mask * log_prob).sum(1).mean()

return loss