这两年,行人再识别得到很多关注,仅cvpr 2018上,就录取了31篇文章。本文主要是对行人再识别的Baseline做一个总结、整理和改进,最终在market1501数据集上达到93.1的rank1和80.3的mAP,该Baseline已经超越2018年大多数顶会录取文章的性能。在实验中,以resnet50作为backbone,损失函数采用单个softmax loss。我们希望这个Baseline能促使整个领域更好地发展,也希望大家能够以此为基础做出更好的工作。
首先,我个人把reid baseline的发展分为三个阶段,70,80和90。
70阶段,
最早起源于郑良老师的综述文章中[1],使用一个普通的resnet50,只采用水平翻转这种扩增方式,采用sgd的方法,学习率为1e-3,即可得到此结果,大致是在73到75之间不等,后续也尝试更改结构并加入dropout,可以进一步做到78左右。具体代码可以参考这个链接https://github.com/zhunzhong07/IDE-baseline-Market-1501。该阶段其实就是是参照如何训练分类网络的方法在训练模型。
80阶段,
也是今年顶会中的部分文章的baseline,主要来自于两种核心技术:1.更大的学习率,使用sgd,通过把学习率从1e-3变为1e-1后,模型更容易收敛,性能也进一步提升,可以达到81左右。2.在抽取特征的层后面,使用一个batchnorm,可以大幅度提升性能,大致上是可以做到88左右的,我个人最早是在Tong Xiao的代码中https://github.com/Cysu/open-reid发现这个做法,也曾和张凯鹏聊过,他说人脸识别中很早就有这个trick,具体究竟谁最早提出,有待进一步补充,文章[2]中也讨论了此种做法。此外,该方法在reid中被大量使用应该是在郑哲东放出的pytorch reid baseline中https://github.com/layumi/Person_reID_baseline_pytorch。
90阶段,
该阶段是我个人近两年调参经验的大集合吧,通过大量trick的堆积,成功把baseline做到93左右,我把trick主要分为数据扩增,网络结构,训练方法三个大模块。
一.数据扩增
1.主要采用训练时水平翻转,测试时也同样水平翻转抽取两次特征并求平均。该思路在人脸识别问题中就被大量采用。
2.输入图像扩大,来自[3]中,将256*128的输入变为384*128,性能会提升不少,也有人尝试288*144[4],我个人实践的结果并不如384*128。
3.随机裁剪,很多人尝试过后会发现性能反而不好,这里有个技巧,就是先补0,然后再裁剪,我个人是把图片resize到384*128,然后补0至402*148,再次随机裁剪为384*128。具体做法来自于[5],该文章中是把图片resize到256*128,并补0至276*148,然后随机裁减至256*128。我个人的理解是这样既能减少图片过多裁减的信息丢失,又能通过黑边补全减少过拟合。
4.随机擦除,random erasing,通过随机擦除图中的一部分方形区域,减少模型过拟合的情况,具体来自于文章[7]中。
二.网络结构
1.去除最后一个block的下采样,使得feature map扩大四倍,该方法同样来自于[3],此做法能够大幅度带来性能提升。feature map变大,会使得更多的细节信息得以保留。
2.去掉之前文章中bottleneck的做法,直接将global average pooling的输出作为抽取特征,该方法会更好的保留局部信息,此方法来自于[5]。
3.使用batchnorm,但是去掉其中的beta参数,使其无偏移量,该方法使得特征整体分布依然以0为原点,会比直接使用batchnorm得到更好性能,实践中,gamma参数是否去除均可,该trick也曾出现在文章[2],但是文中的解释并不是很到位,需要做进一步探究。
4.对于抽取特征所在的层,不使用激活函数relu,relu会导致所有抽取的特征均为正值,相当于检索空间缩小一半。
5.对于分类所在的全连接层,去掉它的bias,该思路来自于sphereface[6],没有bias之后,损失函数对特征的监督信号会更强烈和直接。
三.训练方法
1.训练器的选择,根据[5],我们将sgd替换为adam算法,一切参数均为默认。对于sgd,一般采用1e-1的初始学习率,对于adam,可以大幅度减少,正常来说,2e-3到4e-3之间的初始学习率是比较合理的。
2.参照[4]以及gluoncv中提到的warm up策略,我们在前10个epoch中采用warm up,将学习率从3.5e-6逐渐变为3.5e-4。
3.学习率和epoch的选择。由于结构中已经没有了dropout,故而模型有很大可能在训练中会突然崩溃而导致大幅度降低性能,通过实验,我们大致选出了一组合适的超参,一般在warm up结束后,在30,55这两个点上缩小学习率为原来的0.1倍,总计训练80个epoch。
4.adam配合更小的batch size。关于batchsize的选择,对于sgd算法,一般使用更大的学习率搭配更大的batch size,可以使用128,而在本实验中,我们使用adam算法,adam收敛更快,但也容易进入不好的鞍点,故而我们需要用更小的batch size从而引入更强的随机性,实验中默认使用32的batch size。
5.各层的学习率一致。之前的不少文章中都提出,基础层的学习率小一些,新增层的学习率大一些会比较好,在很多分类网络中也较为常见,[3]中也采用这种方案,这样也能防止模型训练崩溃,而根据我们的实验结果,整个网络采用完全一致的学习率会取得更好的性能。