Bag of Tricks for Image Classification with Con… – Python量化投资

Bag of Tricks for Image Classification with Con…

前言

自己很早就看到过这篇论文了,论文中的工作和我的一个项目也是有很多共通之处,但是自己实力不够也没有想法去把它们全部总结下来,只能在此膜拜一下大佬。

涉及到的方法总览

Tricks位置
Large-batch training3.1
Learning rate warmup3.1
Zero γ3.1
No bias decay3.1
Low-precision training3.2
ResNet模型微调4.2
Cosine Learning Rate Decay5.1
Label Smoothing5.2
Knowledge Distillation5.3
Mixup Training5.4

一、简介

自从2012年AlexNet在图像分类任务上大放异彩后,深度卷积神经网络已经成为图像分类任务上最有效的方法,在ImageNet上的准确率也从62.5%提升至82.7%。然而这些提升不仅仅是网络结构上的改进,还有很多训练策略上的改进,如损失函数、数据预处理、优化方法等,但是这些改进的关注度却非常低,有些重要的tricks甚至只能在源码中找到。本论文总结了一个技巧大礼包,通过和baseline对比,评估这些技巧的有效性。同样的,关于这些技巧的结论也适用于其他计算机视觉任务,比如目标检测、语义分割、实例分割等等。


官方实现的模型和我们的模型.png

二、Baseline

baseline的训练方法主要是参考Resnet的训练过程。

  1. 初始化及训练策略
    卷积和全连接的初始化采用Xavier algorithm,设置参数是[-a, a]的均匀分布,所有的bias设置为0,对于BN参数,γ设置为1,β设置为0。优化器采用NAG,总共训练120轮,学习率初始化为0.1,分别在[30,60,90] 10倍衰减,用了8块V100,总共的batch size是256。
    a = \sqrt{\frac{6}{d_{in} + d_{out}}}
    d_{in}和d_{out}是输入和输出的通道数数量

  2. 数据增强

    • 2.1 训练时:
      1、随机采样图像,值域在[0,255],float32类型。
      2、随机裁剪保持宽高比为[3:4, 4:3]的,面积采样为8%~100%的区域,然后resize到224×224。
      3、0.5的概率水平翻转。
      4、在[0.6,1.4]的均匀分布中抽样作为色度、对比度、明亮度的调整系数。
      5、从正态分布 N (0, 0.1) 中采样一个系数,以添加 PCA 噪声。
      6、图像分别通过减去(123.68, 116.779, 103.939),并除以(58.393, 57.12, 57.375)而获得标准化的 RGB 三通道图像。

    • 2.2 验证时:
      保持宽高比将短边resize到256,然后中心裁剪出224×224的区域,经过训练时方法6的标准化的图像。

  3. 结果
    分别训练了Resnet50,InceptionV3(299×299), MobileNet 三个网络,数据集使用ISLVRC2012,130万训练集,1000分类。Resnet结果略好于原论文结果,但是InceptionV3和MobileNet略差于原论文的结果,可能没有使用原论文的训练策略导致的。


    baseline.png

三、更高效的训练(这一节侧重于效率的提升)

近些年来,硬件(GPU)上发展迅速,所以在权衡性能上的选择也发生了改变。现在在训练时会去选择使用低数值精度和更大的batch size。

3.1、Large-batch training

对于同样个数的epoch,大的batch_size效果不如小的batch_size。可以用以下启发式方法来解决这个问题

  • Linear scaling learning rate
    使用随机梯度下降时,增大batch size并不会改变每一个batch的期望值,因为每一个样本都是随机抽样的,但是会减少一个batch内的方差。也就是说,相对大的batch size可以减少每一次梯度里的噪声,所以启发时的提出了线性缩放学习率的策略。当你的batch size为256,初始学习率为0.1时,当你把batch size调整为b,你的学习率需要调整为:lr = 0.1 \ast \frac{b}{256}

  • Learning rate warmup
    在训练的初期,由于所有的参数都是初始化的,直接使用大学习率可能会导致训练过程不稳定。我们可以采用学习率热身策略,在训练初期使用较小的学习率进行热身,逐渐增大到设置的初始学习率,在Facebook公开的一小时训练ImageNet中,他们是从0开始线性增长到初始学习率的。在前m个(例如5轮)batchs 使用warm up ,初始学习率是η,在第i个batch时,lr = \frac{i * \eta}{m}, 1\leq i \leq m

  • Zero γ
    ResNet网络由多个残差块组成,每个残差块都是由一系列卷积层组成。给定输入x,假设block(x)是残差块中最后一层卷积的输出,所以整个残差块的输出是x+block(x)。在block(x)中会有BN层,有两个参数分别是\gamma和\beta,其初始化分别为1和0,在Zero γ中,我们将位于残差块末尾的所有BN层的\gamma初始化为0,因此block(x)为0,这样可以模拟具有较少层数的网络,使得在网络的初始阶段更容易训练。

  • No bias decay
    只对卷积层和全连接层的weights使用weight decay,其他的包括bias和BN层的γ 和 β 均不使用weight decay。weight decay 相当于对所有参数使用L2正则(个人觉得此处论文观点有误,只有在SGD中才符合作者的描述,在Adam这类优化器中,weight decay并不等价于L2正则),但是并不是所有的参数都需要约束它。所以只对卷积层和全连接层的weights使用weight decay,其他的包括bias和BN层的γ 和 β 均不使用weight decay。

3.2、Low-precision training

通常神经网络都是用32位浮点型(FP32)精度训练,也就是说所有参数的存储和运算都是用FP32。然而当前的新硬件支持更低精度的数据类型。比如V100用FP32能提供14TFLOPS,但是用FP16能提供100TFLOPS。在V100上从FP32切换到FP16后,整体训练速度加快了2到3倍。(本人不太了解混合精度训练,论文里也只是简单提了几句,大概看了一下百度的那篇混合精度论文,有误的话请指正)

尽管使用FP16可以大大加快训练速度,但是有些梯度在FP16范围之外,如果用FP16进行更新,梯度都会是0,无法正常训练。所以这里主要有两个方法:

  1. 维护一个FP32格式的权重的副本,用FP16权重来做正向和反向传播计算,优化器中的梯度更新会被添加到FP32副本里,用于参数更新,然后这个FP32副本会再舍入到FP16,在下一次训练中使用。
  2. 损失缩放(loss-scaling),这个操作原理是借助求导的链式法则,通过放大loss,进而放大整个反向传播过程的参数梯度,最后在更新时候再缩放回来,这个参数可以固定,也可以根据网络的学习的状态自适应的进行调整。

3.3、实验结果

  • 在ResNet50上,Baseline(BS=256 FP32)和Efficient(BS=1024 FP16)相比,每个epoch的时间由13.3分钟缩短至4.4分钟,此外通过上述提到的这些技巧的使用,准确率也高0.5%。


    Baseline(BS=256 FP32)和Efficient(BS=1024 FP16).png

  • 通过Linear scaling learning rate策略将BS从256增加到1024,准确率下降了0.7%,但是剩下的策略弥补了这一差距,并且使用FP16不会降低模型精度。(这里很好奇使用了No bias decay后精度下降了,但是作者没有说原因)


    启发式消融实验.png

四、模型调整

模型调整是对网络体系结构的微小调整,例如改变特定卷积层的步幅。这种调整通常几乎不会改变计算复杂性,但可能对模型精度产生不可忽略的影响。在本节中,我们将使用ResNet作为示例来研究模型调整的影响。

4.1、ResNet网络结构

ResNet由一个输入主干,后续的四个阶段和一个输出层组成。

  • 输入主干:一个7×7卷积,输出通道数为64,步幅为2,然后是一个3×3最大池化,输入主干将输入宽高减小四倍,通道数增加到64。
  • 四个阶段:每个阶段由一个下采样块和连续的几个残差块组成。
    1、下采样块:分为路径A和路径B,路径A有三个卷积,分别为1×1,3×3,1×1,第一个卷积步幅为2,将输入的高宽减半,最后一个卷积的输出通道比前两个大四倍。路径B使用1×1卷积,步幅为2,将输入的形状转换成路径A的输出形状,将路径A和路径B的结果求和得到下采样块的输出。(这里我查看了Pytorch的官方源码,在Stage 1 的下采样块中,步幅均为1,没有将输入下采样两倍。ResNet下采样32倍发生在输入主干两次,Stage 2-4 三次,总共五次。)
    2、残差块:残差块和下采样块类似,所有的1×1卷积步幅均为1,路径B中没有1×1卷积。通过堆加不同数量的残差块,可以得到不同深度的ResNet模型。


    ResNet.png

4.2、ResNet模型调整

ResNet有两个流行的调整,在这里我们分别成为ResNet-B和ResNet-C,我们也提出了一个新的模型调整,ResNet-D。

  • ResNet-B
    这个模型调整最初是在ResNet的Pytorch实现中,它改变了下采样块,将路径A中负责完成下采样功能的模块由1×1卷积换成3×3卷积,因为步幅为2的1×1卷积会忽略特征图的3/4区域。

  • ResNet-C
    这个模型调整最初是在Inception-v2中提出的,它可以在其他模型的实现中找到,例如SENet ,PSPNet ,DeepLabV3 和ShuffleNetV2。改变了输入主干的7×7卷积,用3个3×3卷积替代,不仅减少了参数量,也增加了非线性,前2个3×3的输出通道数为32,最后一个3×3的输出通道数为64。

  • ResNet-D
    受到ResNet-B的启发,我们注意到在下采样块的路径B中的1×1卷积也忽略了特征图的3/4区域,我们在卷积之前添加一个2×2的平均池化,将1×1卷积的步幅变为1。(个人认为加在1×1卷积之后会更好一点,因为平均池化已经丢失了一部分信息了。欢迎讨论。)


ResNet模型调整.png

4.3、实验结果

使用第三节提到的BS=1024,精度为FP16的ResNet50进行实验。ResNet50和ResNet50-D的浮点数计算成本差异在15%内,在训练过程中,ResNet50-D仅仅只慢了3%,精度提升了1%。我自己也大概计算了一下将用3个3×3替代一个7×7增加的FLOPs。(不包含bias,BN,ReLu等计算)
FLOPs_{7*7} =7*7*3*64*112*112=0.12 GFLOPs
FLOPs_{3*3} =3*3*3*32*112*112 + 3*3*32*32*112*112+3*3*32*64*112*112 = 0.36 GFLOPs


实验结果.png

五、训练改进(这一节侧重于精度的提升)

本节进一步介绍提高模型精度的四种训练策略的改进。

5.1、Cosine Learning Rate Decay

在训练过程中,学习率是一个至关重要的参数,在使用warm up后,我们通常会随着训练进程,逐步降低学习率。广泛使用的策略是学习率指数衰减。在ResNet中是每30轮降低0.1,称之为step decay;在Inception中是每两轮降低0.94。另一种策略是2016年提出的学习率余弦衰减。简化版本是通过余弦函数将学习速率从初始值降低到0。
{\eta}_t = \frac{1}{2} * (1 + cos( \frac{ t*{\pi}}{T}))*{\eta}

其中T是总batch数, t是当前batch的索引,{\eta}是初始学习率


(a)中是使用warm up的学习率step decay和cosine decay的过程;图(b)是step decay和cosine decay策略在验证集上TOP1的精度.png

从上图可以看出,起初余弦衰减的学习率缓慢下降,在中间部分几乎是线性下降,在最后又缓慢下降。(但是似乎准确率没有提升,而且也没有加速收敛,只是验证准确率曲线更加平滑)

5.2、Label Smoothing

图像分类网络的最后一层通常是全连接层。由z_i表示i类的预测得分,可以通过Softmax算子对这些得分进行归一化得到预测概率。总共有K类,i类的概率q_i可以通过以下公式计算:
q_i=\frac{exp(z_i)}{\sum_{j=1}^{K}exp(z_j)}

另外,如果图像的真实标签是y,我们可以得到分布p_i:
p_i =\begin{cases} 1 \qquad & i=y\\ 0 \qquad & else \end{cases}
负交叉熵计算(论文中此处公式有误):
l(p,q) = -{\sum_{i=1}^{K}p_ilog(q_i)}
通过训练,使得p_i和q_i两个分布越来越接近。损失计算也可以转换为下式:
l(p,q) = -log(q_y) = -z_y+{\sum_{j=1}^{K}exp(z_j)}
所以最优解是z_y^*=inf,同时保持其他值很小。换句话说,这样做也鼓励输出的分数有显著区别,从而可能导致过拟合(通过softmax学到的模型太自信了)。

标签平滑的想法首先被提出用于训练Inception-v2,它改变了真实概率q_i的分布:
q_i=\begin{cases} 1-\varepsilon \qquad & i=y\\ \frac{\varepsilon}{K-1} \qquad & else \end{cases}
其中\varepsilon是一个常数,所以最后的解为:
z_i^*=\begin{cases} log((K-1)(1-\varepsilon)/\varepsilon)+\alpha \qquad & i=y\\ \alpha \qquad & else \end{cases}
其中\alpha可以是任意实数。这样可以调整全连接层的输出,得到更好的泛化能力。


image.png

5.3、Knowledge Distillation

在知识蒸馏中,我们使用教师模型来帮助训练当前模型,这被称为学生模型。教师模型通常是具有更高准确度的预训练模型,因此通过模仿,学生模型能够在保持模型复杂性相同的同时提高其自身的准确性。一个例子是使用ResNet-152作为教师模型来帮助培训ResNet-50。

在训练期间,我们添加蒸馏损失来惩罚教师模型的Softmax出书和学生模型之间的差异。给定输入,假设p是真实概率分布,并且z和r分别是学生模型和教师模型最后全连接层的输出。我们之前是使用负交叉熵损失l(p,softmax(z))来衡量p和r之间的差异。加上只是蒸馏后,其损失函数变为:
Loss = l(p,softmax(z)) + T^2l(softmax(\frac{r}{T}),softmax(\frac{z}{T}))
其中T是超参数,使得Softmax输出更加平滑,从而从教师的预测中提取出真实标签的分布知识。

5.4、Mixup Training

2017年提出的mixup。每次随机选两个样本作为一个样本对(x_i,y_i)和(x_j,y_j),然后通过这一个样本对,生成一个新的样本:
\hat{x} = \lambda x_i + (1- \lambda)x_j \\ \hat{y} = \lambda y_i + (1- \lambda)y_j
其中\lambda \in [0,1],取自BeTa(\alpha, \alpha)分布
这里作者没有提及采用mix up后损失函数计算方法的改变,我补充一下:
Loss = \lambda * criterion(output, target_i) + (1 - \lambda ) * criterion(output, target_j)
知乎的讨论—如何评价mixup: BEYOND EMPIRICAL RISK MINIMIZATION?

5.5、实验结果

我们设置\varepsilon=0.1用于标签平滑,使用T=20用于知识蒸馏,对于ResNet152-D模型,同时使用余弦学习率衰减和标签平滑作为教师网络。在mix up 中,我们在Beta分布中选择\alpha=0.2,并且将训练轮数由120增加到200,因为mix up要求使用更多的轮数才能够更好的收敛。当我们同时使用mix up 和知识蒸馏时,教师网络也会使用mix up进行训练。

知识蒸馏在ResNet上运行良好,但是它在Inception-V3和MobileNet上运行不佳。我们的解释是,教师模型不是来自学生的同一个家庭,因此在预测中有不同的分布,并对模型带来负面影响。


实验结果.png

六、迁移学习

迁移学习是图像分类模型的一个主要用途,我们在选择了两个重要的计算机视觉任务:物体检测和语义分割,通过改变基本模型来评估他们的性能。

6.1、物体检测

我们分别使用VOC 2007 trainval和VOC 2012 trainval的联合集进行培训,并使用VOC 2007测试进行评估。我们在这个数据集上训练了Faster-RCNN,其中包括来自Detectron的改进,例如线性warm up 和 long training schedul。将Faster-RCNN的基础网络替换,保持其他设置相同,因此收益仅来自于模型。ImageNet上精度为79.29%的最佳基础模型在VOC上的最佳mAP为81.33%,优于标准模型4%


VOC 2007结果.png

6.2、语义分割

我们使用完全卷积网络FCN在ADE20K 数据集上训练模型,在Stage3和Stage4中使用扩张卷积。与我们在物体检测上的结果相矛盾,余弦学习速率表有效地提高了FCN性能,而其他改进则没有效果。对该现象的潜在解释是语义分割在像素级别中预测。虽然使用标签平滑,蒸馏和mix up 的模型有利于软化标签,但模糊的像素级信息可能会降低精度。


ADE20K结果.png

结论

在本文中,我们调查了十几个技巧,以训练深度卷积神经网络,以提高模型的准确性。这些技巧为模型架构,数据预处理,损失函数和学习速率进行了微小的修改。我们在ResNet-50,Inception-V3和MobileNet上的实证结果表明,这些技巧可以始终如一地提高模型精度。更令人兴奋的是,将所有这些堆叠在一起可以显着提高准确性。此外,这些改进的预训练模型在转移学习中显示出强大的优势,这改善了对象检测和语义分割。我们相信,这种优势可以扩展到更广泛的领域。

个人总结

作者总结了一大堆技巧,并且对于这些技巧都做了足够的实验,可以将其作为一本指导手册,帮助自己在以后训练网络的过程中少踩坑。其中每一个tricks在本文中也只是简单交代,想要了解更多的细节还需要去找相关论文继续深入。

https://www.jianshu.com/p/02a76ac73d48

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论