以下链接是个人关于DG-Net(行人重识别ReID)所有见解,如有错误欢迎大家指出,我会第一时间纠正。有兴趣的朋友可以加微信:17575010159 相互讨论技术。若是帮助到了你什么,一定要记得点赞!因为这是对我最大的鼓励。 行人重识别0-00:DG-Net(行人重识别ReID)-目录-史上最新最全:https://blog.csdn.net/weixin_43013761/article/details/102364512
gen_update白话解说首先找到trainer.py中gen_update函数,我们可以看到,调用了:
# encode again (encoder is tuned, input is fixed)
# Es编码得到s_a_recon与s_b_recon即st code
# 如果是理想模型,s_a_recon=s_a, s_b_recon=s_b
s_a_recon = self.gen_b.enc_content(self.single(x_ab_copy))
s_b_recon = self.gen_a.enc_content(self.single(x_ba_copy))
这里做了一件什么事情呢?首先大家注意recon表示的是重构,多次提到,论文中重构,就是构建一个训练数据集已经存在的照片,是可以直接通过重构图像与原图,求得两张图像的像素差,计算像素loss。但是这里的重构,是对st cope进行重构,什么意思呢?就是把已经合成的图片中的st code份离出来,相当于论文图示中的红框操作。 可以很明显的知道s_a_recon,s_b_recon表示的是上图中绿框部分。拿到这个东西做什么呢?后续讲解(其实是为了计算loss)。我们接着往下看,找到代码:
# encode again (encoder is fixed, input is tuned)
# 对混合生成的图片x_ba,x_ab记行Es编码操作,同时对身份进行鉴别#
# f_a_recon,f_b_recon表示的ap code,p_a_recon,p_b_recon表示对身份的鉴别
f_a_recon, p_a_recon = self.id_a_copy(scale2(x_ba))
f_b_recon, p_b_recon = self.id_b_copy(scale2(x_ab))
通过前面的博客分析,可以知道,这里是进行了Ea编码,同时得到了身份鉴别(行人识别)的结果,再次啰嗦一下,Ea编码模型也是行人重识别的模型。上面的x_ba,x_ab表示的是合成的图片,对合成的图片进行编码,以及生成预测,相当如论文的如下步骤: 这里我们需要计算两个loss,一个是身份预测的loss,一个编码之后得到ap code(与真实图片的ap code)的loss。
下面我们继续看代码:
# 绝妙的设计,重点思想,重点思想,超级重点。也是我论文翻译的第二个红牌警告,具体细节看博客,注释讲解下来太恐怖了
elif hyperparameters['ID_style'] == 'AB':
# normal teacher-student loss
# BA -> LabelA(smooth) + LabelB(batchB)
# 合成的图片经过身份鉴别器,得到每个ID可能性的概率,注意这里取的是p_ba_student[0],主要身份特征
# 并且赋值给了p_a_student,用于和教师模型结合的,共同计算损失
_, p_ba_student = self.id_a(scale2(x_ba_copy))# f_a, s_b
p_a_student = log_sm(p_ba_student[0])
with torch.no_grad():
p_a_teacher = predict_label(self.teacher_model, scale2(x_ba_copy), num_class = hyperparameters['ID_class'], alabel = l_a, slabel = l_b, teacher_style = hyperparameters['teacher_style'])
# criterion_teacher = nn.KLDivLoss(size_average=False)
# 计算离散距离,可以理解为p_a_student与p_a_teacher每个元素的距离和,然后除以p_a_student.size(0)取平均值
# 就是说学生网络(Ea)的预测越与教师网络结果相同,则是最好的
self.loss_teacher = self.criterion_teacher(p_a_student, p_a_teacher) / p_a_student.size(0)
# 同样另外的合成图像,进行相同操作
_, p_ab_student = self.id_b(scale2(x_ab_copy)) # f_b, s_a
p_b_student = log_sm(p_ab_student[0])
with torch.no_grad():
p_b_teacher = predict_label(self.teacher_model, scale2(x_ab_copy), num_class = hyperparameters['ID_class'], alabel = l_b, slabel = l_a, teacher_style = hyperparameters['teacher_style'])
self.loss_teacher += self.criterion_teacher(p_b_student, p_b_teacher) / p_b_student.size(0)
# branch b loss
# here we give different label
# 求得学生网络(Ea)预测ID结果,与实际ID之间的损失,注意这里取的是p_ba_student[1],表示是细节身份特征
# 大家要细心的去体会p_ba_student[0],p_ba_student[1]
loss_B = self.id_criterion(p_ba_student[1], l_b) + self.id_criterion(p_ab_student[1], l_a)
# 网络中T_w=1, B_w=0.2
self.loss_teacher = hyperparameters['T_w'] * self.loss_teacher + hyperparameters['B_w'] * loss_B
可以知道这里主要求得两个loss self.loss_teacher:表示的是我们的学生网络(Ea,重识别模块)预测和教师网络预测结果的损失,ID分类损失。 loss_B:表示的是我们的学生网络(Ea,重识别模块)与真实标签之间的损失。
现在为大家解释一下其中的思想,为什么要一个真实标签的loss,还要一个教师网络的模型。要知道,我们的教师网络,训练时在train_all数据上训练的,这751个人中,基本都是衣服相同的,也就是说,对于这种AB混合成的图片,对于教师网络来说,其识别难度时很大很大的。教师网络会觉得又像A,然后又像B,也就说,他会觉得和这751个中的两个人都比较像。通过:
self.loss_teacher = self.criterion_teacher(p_a_student, p_a_teacher) / p_a_student.size(0)
损失的计算,我们的学生网络,也就是Ea行人重识别网络,跟着教师网络网络学坏。也就是p_a_student=p_a_teacher,那么此时学生网络计算出来的概率,和教师网络时一样的,他也傻乎乎的分不清楚,到底谁是谁,觉得751个人中,有两个人都和他预测的照片比较像,概率都很高。
但是,他真的被教坏了吗?是的,他是真的被教坏了,但是同时这个学生是有自己的思想的,如:
loss_B = self.id_criterion(p_ba_student[1], l_b) + self.id_criterion(p_ab_student[1], l_a)
这个loss的定义,可以看到,其和教师网络是完全没有关系的,他是自己在学习,学习到完全正确的东西。
下面再来看看:
# 网络中T_w=1, B_w=0.2
T_w是跟着教师网络学习的loss权重,占的比例比较大,B_w表示自我学习的权重,比较小,只有0.2。
说明了这样一个现象,学生网络先有模有样的照着教师网络学习。老师怎么猜测,他就怎么猜测。因为T_w=1,所以以他为主要。要是遇到复杂的情况,比如合成的这种难识别的图像,他就会自己再根据一些细节,去进行自己的判定。再老师的指导下,再加上自己判断,完成识别。
我不知道这样的讲解算不算形象。哎,如果不明白,你对不起我,我也对不起你啊。