点击上方“CVer”,选择加"星标"或“置顶”
重磅干货,第一时间送达
本文转载自:GiantPandaCV
★这篇论文整理了CNN分类任务中一些常用的Tricks,如改善模型结构,训练过程中的一些Refinements如修改损失函数,数据预处理等,有较大工程意义。
”
这篇论文的全名是:Bag of Tricks for Image Classification with Convolutional Neural Networks 。论文地址见附录。这篇论文是亚马逊团队对CNN网络调优的经验总结,实验基本是在分类网络实验上做的。目前,论文的复现结果都可以在GluonCV找到,地址为:https://github.com/dmlc/gluon-cv。可以将这篇论文理解为一堆经验丰富的工程师的调参技巧汇总,无论你是在做比赛,做学术,还是已经工作的AI开发者,相信都能从中受益。
下面的Table1展示了本文的一系列Tricks被用在ResNet50网络做分类任务上获得的结果。
可以看到使用本文的技巧,Top1准确率从75.3%提升到了79.29%。所以这一系列技巧还是非常给力的,接下来我们就一起来探索探索。
既然涉及到调参,那么第一步就得有一个BaseLine的结果作为参考,这一BaseLine并非直接截取之前对应的论文的结果,而是作者基于GluonCV复现的。关于复现的细节作者在论文2.1节中说的很清楚,包括数据预处理的方式和顺序,网络层的初始化方法,迭代次数,学习率变化策略等等。
下面的Table2展示了作者复现的ResNet-50,Inception-V3,MobileNet三个BaseLine。
介绍完BaseLine,接下来就来看看作者的优化方法。论文从加快模型训练,网络结构优化以及训练参数调优三个部分分别介绍如何提升模型的效果。
关于模型训练加速,论文提到了2点,一是使用更大的Batch Size,二是使用低精度(如FP16)进行训练(也是我们常说的混合精度训练)。关于使用更大的Batch Size进行训练加速,作者指出一般只增加Batch Size的话,效果不会太理想,例如FaceBook这篇大名鼎鼎的论文有证明:
Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour
然后本文总结了几个重要要的调参方案,如下:
epoch
),假设训练阶段的初始学习率是L,那么在第
个batch的学习率就设置为
。
接下来作者提到了使用低精度(16-Bit浮点型)来做训练加速,也即是我们常说的混合精度训练。但不是所有的NVIDIA GPU都支持FP16,我大概只知道V100和2080 Ti是支持混合精度训练的。
作者将上面的Tricks结合在一起进行训练,下面的Table3展示了使用更大的Batch Size和16位浮点型进行训练的结果,可以看到这俩Tricks相比于BaseLine训练速度提升了许多,并且精度也更好了。
而下面的Table4则进一步展示了这些Tricks的消融实验,证明确实是有效的。
这一小节以ResNet-50为例子展开,下面的Figure1表示ResNet网络的原始结构图,简单来说就是一个输入流加4个stage和一个输出流。其中输入流和每个stage的详细结构在Figure1中间那一列显示,而残差结构则在Figure1中最右边进行显示。
论文在网络结构部分进行改进获得的3种结构如Figure2(a),(b),(c)
所示:
最终关于这些改进的网络结构的效果如Table5所示,可以看到效果提升还是有的。
这部分作者提到了4个调参技巧:
而Figure3(b)则表示2种学习率衰减策略在效果上的对比。
代码实现可以简单表示为:
new_labels = (1.0 - label_smoothing) * one_hot_labels + label_smoothing / num_classes
完整的Pytorch代码如下:
import torch
import torch.nn as nn
class LabelSmoothing(nn.Module):
"""
NLL loss with label smoothing.
"""
def __init__(self, smoothing=0.0):
"""
Constructor for the LabelSmoothing module.
:param smoothing: label smoothing factor
"""
super(LabelSmoothing, self).__init__()
self.confidence = 1.0 - smoothing
self.smoothing = smoothing
def forward(self, x, target):
logprobs = torch.nn.functional.log_softmax(x, dim=-1)
nll_loss = -logprobs.gather(dim=-1, index=target.unsqueeze(1))
nll_loss = nll_loss.squeeze(1)
smooth_loss = -logprobs.mean(dim=-1)
loss = self.confidence * nll_loss + self.smoothing * smooth_loss
return loss.mean()
具体细节和公式可以再阅读原文,这里展示一下Lable Smooth的效果。
总结就一句话,one-hot编码会自驱的向正类和负类的差值扩大的方向学习(过度的信任标签为1的为正类),在训练数据不足的情况容易过拟合,所以使用Label Smooth来软化一下,使得没那么容易过拟合。
注意, 代表真实概率, 和 表示studnet model和techer model的最后一个全连接层的输出, 是超参数,用来平滑softmax函数的输出。
epoch
。式子中的
是一个超参数,用来调节合成的比重,取值范围是
。
最终,在使用了这4个Tricks后的消融实验结果如Table6所示。
当把上面的Tricks迁移到目标检测和语义分割任务同样是有效的,实验结果如Table8和Table9所示。
总的来说,这篇论文给了我们非常多的炼丹技巧,我们可以将这些技巧放迁移到我们自己的数据集上获得效果提升,是非常实用的一篇论文了。
推荐阅读
2020年AI算法岗求职群来了(含准备攻略、面试经验、内推和学习资料等)
重磅!CVer-学术微信交流群已成立
扫码添加CVer助手,可申请加入CVer大群和细分方向技术群,细分方向已涵盖:目标检测、图像分割、目标跟踪、人脸检测&识别、OCR、姿态估计、超分辨率、SLAM、医疗影像、Re-ID、GAN、NAS、深度估计、自动驾驶、强化学习、车道线检测、模型剪枝&压缩、去噪、去雾、去雨、风格迁移、遥感图像、行为识别、视频理解、图像融合、图像检索、论文投稿&交流、TensorFlow、PyTorch、图神经网络等群。
一定要备注:研究方向+地点+学校/公司+昵称(如目标检测+上海+上交+卡卡),根据格式备注,可更快被通过且邀请进群
▲长按加群
▲长按关注我们
麻烦给我一个在看!