https://openaccess.thecvf.com/content_CVPR_2019/papers/He_Bag_of_Tricks_for_Image_Classification_with_Convolutional_Neural_Networks_CVPR_2019_paper.pdf
三遍论文法
目前深度学习在计算机视觉领域大放异彩,这不仅归功于网络结构的创新,也得益于训练策略的优化(损失函数、数据预处理、优化方法等)。但很多实现的细节和技巧在论文中并没有提及,或者是只简单提了一两句,这篇文章就是收集这些trick并进行了实验,将ResNet-50在ImageNet上的top1错误率从75.3%提升到79.29%。干货满满啊,调参侠狂喜。
本节主要描述了文章实验的具体设置,这里简单提及相关要点,具体设置请看原论文
Baseline的训练策略:① 随机采样编码为float32类型; ② 随机裁剪;③ 0.5的概率水平翻转; ④ 饱和度、对比度、亮度随机变化; ⑤ 增加PCA噪声。
测试不采用任何增广;模型参数初始化采用Xavier,使用NAG优化器。
主要讨论了低数值精度与大batch size的trick,目前常用半精度浮点类型+大batch size提升训练速度,同时提升准确率。
大的batch size不会改变随机梯度的期望但会降低方差,也就是说大batch size会降低梯度的噪声。但是随着batch size的增加,会降低训练的收敛速度(同样的epoch效果会变差)。为了解决这个问题,有以下的trick:
① Linear scaling learning rate:很简单,学习率随着batch size线性增加。比如开始的batch size=128,学习率=0.1。现在batch size=256,学习率就也增加2倍,变为0.2;
② Learning rate warm up:在训练一开始就使用很大的学习率可能会导致数值不稳定,因此先使用小学习率然后慢慢增加至设定学习率即可。一般的策略是从0开始,经过几个epoch线性增加到预设学习率,warm up的实现可以参加我另外一篇博客;
③ Zero γ:在BN层会涉及到收缩与偏移γx+β
,初始化时对所有residual block末尾的BN都设置γ=0,这使得网络在初始阶段的模拟层数较少且更容易训练。
④ No bias decay:只对卷积层和全连接的weight使用L2正则化,对于bias以及BN层中的参数不用。
LARS,对超大的batch size有效(大于16k),卡多的大佬可以了解一下…
关于低精度就是使用float16的半浮点精度进行数值运算,目前的显卡对于FP16类型已经很快了(还是1080Ti和2080Ti玩家的我眼泪掉下来),比如V100在FP32的训练速度是14TFLOPs,在FP16已经是100TFLOPS了。这部分我就不讲太多了,适合卡新卡多的大佬研究,提示一下1080Ti没有什么FP16运算能力…
最后贴个实验结果,大致可以看到哪些trick是比较鸡肋的,我个人建议只考虑warm up+Linear Scaling,性价比最高。
ResNet的架构就不多说了,见图1,没看过的同学也可以参考我的博客。作者讨论了结构上的一些小trick。
① ResNet-B:如图二所示,这也是Pytorch官方在实现时所采用的方法,主要是将PathA上的下采样放在了第2个3x3卷积上,避免了1x1
卷积直接跳过一些特征图内容。
② ResNet-C:将输入阶段的7x7
卷积改为3个3x3
卷积,感受野一致,降低了计算消耗。
③ ResNet-D:在ResNet-B、C的基础上将Path B改为平均池化下采样+1x1卷积,避免忽略特征图内容。
直接上结果,不过目前大家基本都是用的pre-trained的模型做初始化,所以我个人觉得这些trick也不太重要,但从头训练或者设计网络可以参考。
训练改进,重头戏来了哈哈哈
就是采用余弦衰减策略,常与Warm up一起服用。其在训练初期衰减较慢,中期类似线性衰减,后半段类又比较平衡。可以参加我另一博客的细节与实现(和warm实现同一篇)。这里贴上warm up+cosine与另一个Step衰减的方法对比图,如下:
从结果上来看两者准确率差不多,但是cosine可以避免Step的调参。
LabelSmooth从分类损失-交叉熵的角度分析,引入了一个较小的常数将目标标签由One-Hot
形式改为概率分布的形式(计算公式如下),从而起到防止过拟合的效果。细节与实现可参见我的博客。
知识蒸馏就是使用一个Teacher模型去训练Student模型,T模型通常是有着高性能的预训练模型,这种训练方式能使得S模型在不增加模型容量的情况下提升性能。实现也比较简单,额外增加了一个distillation损失,惩罚S输出与T输出之间的softmax概率差异:
T为温度系数,详见我另一篇博客,这可以使得softmax输出更平滑,使得S模型能从T模型的输出中学习到标签分布的知识。
Mixup也是一种数据增广形式,随机采样两个训练样本(xi, yi)
和(xj, yj)
,通过线性加权得到一个新样本:
λ属于[0,1],从Beta分布中采样获得,在后续的训练中只使用Mixup获得的新样本进行训练。
实验结果如下,个人推荐使用cosine decay+mixup,不过mixup我也没有实际试过,不知道效果怎么样。distillation一般用于模型压缩。
最后作者也在目标检测、语义分割等下游任务上检测了trick的有效性,这里就不放图了,大家自行参照原文理解。
李沐大佬团队的这篇调参文章其实早有耳闻,并且很多方法在比赛或者项目中都已经实际应用过来,但研一上课一直没抽出时间拜读总结一下。这几天花时间把这篇文章总结了一下,这种干货文章对于算法工程人员和打比赛的朋友们还是很有指导意义的。后续我也会继续读一些这方面的文章,分享给大家。