Invariance Matters: Exemplar Memory for Domain Adaptive Person Re-identification

1、论文:Invariance Matters: Exemplar Memory for Domain Adaptive Person Re-identification
2、代码: https://github.com/zhunzhong07/ECN

无监督的域自适应(UAD):源域的训练集有标签,目标域的训练集无标签,在目标域的测试集进行验证。

由于行人的镜头是容易确认的,论文中使用了目标域的行人镜头信息。

文章的网络框架:
在这里插入图片描述
Exemplar Memory:利用Exemplar Memory保存训练样本的所有特征。

本文提出了三种不变形:
Exemplar-invariance (样本不变性):每个图像之间都是不同的,将每个图像认为是单独的一类,增大了所有图像之间的差距。
Camera-invariance(相机不变性):同一类别由多个相机获得,经过stargan对相机风格进行转化,他们仍具有相同的标签。
Neighborhood-invariance(近邻不变性):由于样本不变性增大了样本之间的差距。对于每一个样本,寻找K个最近邻的图像,认定为具有相同标签。

风格转化图像:以market为例,该数据库有6个摄像机拍摄,对每一幅图像产生对应的另外5种镜头的风格。该数据库训练集有12936张图像,使用starGAN总共产生了64680张图像。

代码实现解析:

网络中的第一个分支简单使用监督学习进行优化;
网络中的第二个分支首先初始化所有的特征为0,存储在Exemplar Memory中。

目标域的数据获取方式:随机在目标域中选取batch个索引。获得对应索引的图像镜头A。以market为例,在6个镜头中随机选取一个镜头,如果该镜头正好是A,则获得该图像,如若该镜头不是A,则获取对应产生的假图像。最后获得的batch中既包含了真图像,也包含了生成的假图像。

对batch计算损失:
在这里插入图片描述
公式(3)计算每幅图像属于12936中的每一类的概率。K的维度是4096 * 12936;f()获得的维度是4096 * 1。然后利用公式(4)求交叉熵损失:
在这里插入图片描述
经过几个epoch之后开始约束近邻不变:
在这里插入图片描述
获得的k个近邻图像如果标签与目标图像标签一直,权重为1,否则为1/k,获得对应权重的代码:

    def smooth_hot(self, inputs, targets, k=6):
        # Sort
        _, index_sorted = torch.sort(inputs, dim=1, descending=True)

        ones_mat = torch.ones(targets.size(0), k).to(self.device)
        targets = torch.unsqueeze(targets, 1)
        targets_onehot = torch.zeros(inputs.size()).to(self.device)

        weights = F.softmax(ones_mat, dim=1)
        targets_onehot.scatter_(1, index_sorted[:, 0:k], ones_mat * weights)
        targets_onehot.scatter_(1, targets, float(1))

        return targets_onehot

然后使用交叉熵计算损失,对应代码为:

    def smooth_loss(self, inputs, targets):
        targets = self.smooth_hot(inputs.detach().clone(), targets.detach().clone(), self.knn)
        outputs = F.log_softmax(inputs, dim=1)
        loss = - (targets * outputs)
        loss = loss.sum(dim=1)
        loss = loss.mean(dim=0)
        return loss

Exemplar Memory 中的每个特征更新方式:
在这里插入图片描述
即每次只更新batch中每个图像对应的索引,对应的更新代码:`

    def backward(self, grad_outputs):
          inputs, targets = self.saved_tensors
          grad_inputs = None
          if self.needs_input_grad[0]:
                 grad_inputs = grad_outputs.mm(self.em)
          for x, y in zip(inputs, targets):
                 self.em[y] = self.alpha * self.em[y] + (1. - self.alpha) * x
                 self.em[y] /= self.em[y].norm()
          return grad_inputs, None
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值