Bag of Tricks for Image Classification with Convolutional Neural Networks

Bag of Tricks for Image Classification with Convolutional Neural Networks

Abstract

最近大部分在图像分类研究上取得的进展都来自于训练程序的改进,比如数据增广和优化算法的改进。然而,在文献中,大部分的改进要么简单的提及一下,要么就是只在代码里实现。本文,我们将对一系列的改进方法进行评估和对照实验。我们发现将这些改进方法结合起来,能够对不同的CNN模型有很大的提升。比如,我们将ResNet-50在ImageNet的top-1 validation 准确率由75.3%提升到了79.29%。同时也展示出了图像分类上的提升能够很好的迁移到其他任务上,如目标检测,语义分割。

1.Introduction

随着AlexNet的出现,后续出现了很多更新更好的网络结构,然而它们带来的提升,其实不仅仅是来自于更好的模型。训练程序的改进,包括损失函数的变化,数据预处理和优化算法都起到了很大的作用。还有修改特定卷积层的步长,以及调整学习率的变化策略等。
在第二部分,我们会设定一个训练程序的baseline,然后在第三部分讨论一些有效提升训练的策略。在第四部分,回顾三个不同的ResNet变体,然后提出一个全新的。在第五部分,我们在额外讨论四个优化策略。

2.Training Procedures

训练网络的模板,是采用mini-batch的SGD来实现,具体算法如下图。每个iter,随机采样b张图进行梯度运算,然后来更新参数,一共训练K个iter。
Bag of Tricks for Image Classification with Convolutional Neural Networks

2.1. Baseline Training Procedure

我们使用了【8】中ResNet的实现来作为我们的baseline。训练和验证的数据预处理是不同的。训练的预处理我们遵循下面步骤:

  1. 随机采样一张图,然后将它编码到32位浮点数精度,且未处理过的像素值在[0,255]。
  2. 随机裁取一个矩形区域,它的纵横比在[3/4,4/3][3/4,4/3]之间随机采样一个值,然后区域大小在[8%,100%][8\%,100\%]之间随机采样一个值,然后将裁取出的图像缩放到224x224的大小。
  3. 0.5概率的水平翻转。
  4. 对图像的HSB空间(hue色相,saturation饱和度,brightness亮度)进行缩放,系数在[0.6,1.4][0.6,1.4]之间均匀采样。
  5. 添加PCA噪声,系数采样自正态分布N(0,0.1)\mathcal N(0,0.1)
  6. 对图像的RGB通道进行归一化,减去[123.68,116.779,103.939][123.68,116.779,103.939],再除以[58.393,57.12,57.375][58.393,57.12,57.375]

在validation的时候,我们将图像的短边缩放到256个像素,然后保持图像的纵横比。然后在图像的正中心裁取一个224x224的区域,然后使用和训练时同样的归一化。再val的时候,我们不使用任何的增广。
卷积层和全连接层的权重初始化都使用Xavier算法。尤其,我们随机从[a,a][-a,a]中取值来设置参数,这里a=6/(din+dout)a=\sqrt{6/(d_{in}+d_{out})}dind_{in}doutd_{out}分别代表输入和输出的通道数。所有的偏置项都初始化为0。对于BN层,γ\gamma向量初始化为1,β\beta向量初始化为0。
使用NAG(Nesterov Accelerated Gradient)优化算法进行训练。每个模型在8个Nvidia V100 GPU上使用256的batch训练120个epoch。学习率初始化为0.1,分别再30,60,90epoch的时候,衰减10倍。

2.2. Experiment Results

我们评估三个CNN模型:ResNet-50,Inception-V3,MobileNet。对于Inception-V3,我们将图像缩放到299X299。我们使用ISLVRC2012数据集,1.3M的训练集,1000个类别。验证集准确率如下表。可以看到我们的ResNet-50结果略微好于参考结果,然而Inception-V3和MobileNet的结果略低,因为不同的训练程序。
Bag of Tricks for Image Classification with Convolutional Neural Networks
表2:验证集准确率,参考模型和我们的baseline。

3. Efficient Training

硬件(尤其是GPU)的发展很快。那么在很多性能相关的选择的权衡发生了变化。例如,在训练中使用较低的数值精度和较大的batch会更加有效。在本节中,我们回顾一些技巧,能够在不损失模型准确率的情况下,进行低精度,大batch的训练。一些技巧甚至还可以提升准确率和训练速度。

3.1. Large-batch training

Mini-batch SGD将多个样本聚集到一个batch来增加并行运算和降低通信消耗。然而,使用大的batch也可能会减缓训练。对于凸问题来说,收敛的效率随着batch增加而降低。换句话说,对于训练同样的epoch数,用大batch训练出的模型的结果会比使用小batch训练处的模型的结果要差。
接下来我们会讨论四个方法来帮助提高batch大小。

Linear scaling learning rate. 在mini-batch SGD中,梯度下降是一个随机过程,因为每个batch中的样本是随机采样的。增加batch大小,并没有改变随机梯度的期望,但是减小了它的方差。换句话说,一个大的batch会减小梯度中的噪声,所以我们可以增加学习率来来在负梯度方向走更大的一段距离。跟随batch大小线性增加学习率已经在ResNet-50的训练上经验性地得到了证明是有效的(一小时训练ImageNet)。尤其,根据ResNet文章使用0.1的初始学习率和256的batch,如果增大batch到b,那么相应初始学习率到b/256。

Learning rate warmup. 在训练的开始,所有参数都是随机值,自然是原理我们的最终解的。使用太大的学习率可能会导致振荡(数值不稳定)。在warmup方法中,我们在一开始使用小的学习率,然后当训练稳定了,再调整回我们的初始学习率。(同样还是在一小时训练ImageNet中)提出一种普遍的warmup策略,线性的从0开始增加学习率到初始值。也就是,假设我们使用前m个batch来进行warmup,初始学习率是η\eta,那么在batch ii1im1 \le i \le m,我们设置学习率为 iη/mi\eta/m

Zero γ\gamma. ResNet网络包含了多个残差模块,每个模块都由多个卷积层组成。输入xx,假设 block(x)block(x) 为模块最后一层的输出,那么这个残差模块的输出就是x+block(x)x+block(x)。注意到模块的最后一层是BN层。BN层首先标准化它的输入,标识为x^\hat x。然后进行一个缩放变换γx^+β\gamma \hat x+\betaγ\gammaβ\beta都是要学习的参数,分别初始化为1和0。在0 γ\gamma方法中,我们将所有位于残差模块最后的一个BN层的γ\gamma初始化为0。这样,所有的残差模块仅仅返回它们的输出,这样网络的层数就相应的减少,使得网络初期的训练变得简单。

No bias decay. 权值衰减通常是应用到所有可学习的参数上的,包括所有的权重和偏置。这等同于在所有参数上施加一个L2的正则化,然后驱使它们向0靠近。【14】指出,推荐仅仅对权重施加正则化来避免过拟合。我们的No bias decay策略遵从这一点,仅仅对卷积和全连接层中的权重进行衰减。其他参数,包括BN层里的偏置,γ\gammaβ\beta是不正则化的。

3.2. Low-precision training

神经网络普遍是在32位浮点数精度下训练的。也就是,所有的数字都存储为32位浮点数,所有输入和输出的算术运算也是在32位浮点数精度下进行。然而,新的硬件提升了低精度数据的算术逻辑单元。例如先前提到的 Nvidia V100提供了FP32上14TFLOPS(这里T,表示101210^{12},FLOPS,是每秒浮点运算次数,那么14TFLOPS,就是每秒进行14万亿次的浮点数运算)的运算速度,而FP16上100TFLOPS的计算速度。下表,转换精度之后有了明显的提速(但是这里并不是一个完全的对照实验,也同时改变了batch大小)。
Bag of Tricks for Image Classification with Convolutional Neural Networks
表3:训练时间和验证集准确率的对比,左边是使用更有效的硬件设置(BS=1024,FP16),右边是(BS=256,FP32)

3.3. Experiment Results

评估结果在表三,比较下来使用1024的batch和FP16比256的FP32每个epoch的时间分别是4.4min和13.3min。除此之外,堆叠所有的上述方法,在top1上甚至还取的了0.5%的提升。
所有策略的对照实验在表4。
Bag of Tricks for Image Classification with Convolutional Neural Networks
表4:在ResNet-50上每个训练策略的分解效果。

4. Model Tweaks

模型调整指的是对网络结构进行很小的调整,比如改变某个卷积层的步长等。这样的一个小调整,不会改变计算复杂度,但是对于模型准确率确是有着不可忽视的影响。本节,我们使用ResNet来进行模型调整的分析。

4.1. ResNet Architecture

ResNet结构如下图,不赘述了。
Bag of Tricks for Image Classification with Convolutional Neural Networks
图1:ResNet-50的网络结构。

4.2. ResNet Tweaks

接下来,讨论两个模型调整,ResNet-B和ResNet-C,然后最后提出一个新模型ResNet-D。
ResNet-B. 对Down sampling进行调整,这个调整在【8】里有提到,考虑到path A上第一个卷积就使用步长2,会损失掉3/4的特征图信息,如图2a,所以考虑将步长2放到第二个卷积上。
ResNet-C. 由于卷积操作的计算量是卷积核长宽的平方,所以使用3个3x3来代替7x7会更加经济,第一,第二个3x3都是32的通道,第三个是64通道。(这一点早在VGG里就提出来了)。
ResNet-D. 由ResNet-B得到的启发,我们发现path B的卷积也是忽略掉了输入特征图的3/4的信息。经验性的,我们找到在卷积之前添加一个步长2的2x2的平均池化会有很大帮助,如图2c。
Bag of Tricks for Image Classification with Convolutional Neural Networks
图2:三种调整。B:修改了downsampling。C:修改了input stem。D:再次修改downsampling。

4.3. Experiment Results

我们采用第三部分的设定来进行模型调整的实验,1024的batch,FP16,实验结果如下表。
Bag of Tricks for Image Classification with Convolutional Neural Networks
表5:ResNet-50与三种模型调整的比较。

5. Training Refinement

本节我们讨论四种训练改进来进一步提高模型的准确率。

5.1. Cosine Learning Rate Decay

学习率调整对训练来说是至关重要的。在使用warmup策略之后,我们稳定的从初始学习率开始衰减。普遍运用的策略是step。
而【18】提出了一种余弦退火策略。一种简单的通过以下方程将学习率从初始值降到0的策略。假设总batch是TT(去除掉warmup的部分),那么batch tt 的学习率是ηt\eta_t
(1)ηt=12(1+cos(tπT))η\eta_t = \frac{1}{2}\left( 1+cos\left( \frac{t\pi}{T} \right) \right)\eta \tag 1
这里η\eta是初始学习率。我们称这种策略为“余弦”衰减。
step衰减和余弦衰减如图3a。在训练初期,当step衰减后,cosine的学习率依然很大,这会加快训练。
Bag of Tricks for Image Classification with Convolutional Neural Networks
图3:带warmup的学习率变化的可视化。上:1024batch的余弦和step策略。下:Top-1 验证集准确率曲线。

5.2. Label Smoothing

图像分类网络的最后一层往往是一个单元数等于label数量(K)的全连接层,输出一个预测的置信分数。给一张图片,用ziz_i表示对于类别ii的预测结果。这个结果需要通过softmax进而转换为概率。用pp表示softmax的结果,p=softmax(z)p=softmax(z)。那么对于类别ii,pip_i
(2)pi=exp(zi)j=1Kexp(zj)p_i=\frac{\exp(z_i)}{\sum^K_{j=1}\exp(z_j)} \tag 2
显然pi>0p_i>0,并且i=1Kpi=1\sum^K_{i=1}p_i=1pp就是一个有效的概率分布。
另一方面,假设这张图片的gt label是yy,我们可以建立一个gt的概率分布qi=1q_i=1,如果i=yi=y,否则为0。在训练期间,我们最小化负交叉熵
(3)l(p,q)=i=1Kqilogpil(p,q)=-\sum^K_{i=1}q_i\log p_i \tag 3
来更新模型参数使得两个概率分布相似。l(p,q)=logpy=zy+log(i=1Kexp(zi))l(p,q)=-\log p_y=-z_y+\log \left( \sum^K_{i=1}\exp(z_i)\right)。最优解是zy=infz^*_y=\inf同时其他的分量要足够小(这里对这个最优解稍作解释,首先我们假设了数据里只有一个gt,那么除了i=yi=y,其他的都为0,那么loss里面就只剩一项 logpy-\log p_y,然后我们有py1p_y \le 1,那么最优解就是使我们的loss为0,也就是py=1p_y=1,然后通过这一点,我们带入到softmax里面就会得到上述结论)。也就是,模型会鼓励输出分数非常有辨识性,这就会倾向于过拟合。
label smoothing最先是在Inception-V2中提出的。它改变了gt概率的构造
(4)qi={1ϵ                 if  i=y,ϵ/(K1)        otherwise, q_i = \begin{cases} 1-\epsilon \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \text{if} \ \ i=y, \tag 4 \\ \epsilon/(K-1) \ \ \ \ \ \ \ \ \text{otherwise}, \\ \end{cases}
这里ϵ\epsilon是一个很小的常数。现在最优解就变为
(5)zi={log((K1)(1ϵ)/ϵ)+α          if  i=y,α                                                    otherwise, z^*_i = \begin{cases} \log((K-1)(1-\epsilon)/\epsilon)+\alpha \ \ \ \ \ \ \ \ \ \ \text{if} \ \ i=y, \tag 5 \\ \alpha \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \text{otherwise}, \\ \end{cases}
这里α\alpha是一个任意实数。这个能鼓励全连接层有一个有限的输出,并且能够提升泛化效果。
ϵ=0\epsilon=0,间隔log((K1)(1ϵ)/ϵ)\log((K-1)(1-\epsilon)/\epsilon)将会是\infty,随着ϵ\epsilon增加,这个间隔会下降。尤其当ϵ=(K1)/K\epsilon=(K-1)/K,所有的最优ziz^*_i相等。图4a,展示了在ImageNet上K=1000K=1000的gap随着ϵ\epsilon移动的改变。
我们训练了两个模型,一个模型是使用label smoothing的ResNet-50D,是一个是不使用的ResNet-50D,然后比较它们的输出值,并计算了最大预测值与其他值的平均值的gap。在ϵ=0.1\epsilon=0.1K=1000K=1000,理论间隔大约是9.1。图4b展示了两个模型在ImageNet验证集上间隔的分布情况。很明显label smoothing置中了分布,而且减少了极端值。
Bag of Tricks for Image Classification with Convolutional Neural Networks
图4:ImageNet上label smoothing的效果可视化。上:当ϵ\epsilon增加,zpz^*_p和其他的理论间隔。下:预测最大值与其他值的平均值之间的间隔。

5.3. Knowledge Distillation

在知识蒸馏里,我们使用一个教师模型来帮助我们训练当前的模型,我们叫做学生模型。教师模型通常是一个高准确的预训练模型,那么学生模型可以在保持模型复杂度不变的情况下来提高自己的准确率。一个例子就是使用ResNet-152作为教师模型来训练ResNet-50。
在训练中,我们添加一个蒸馏loss来惩罚教师模型和学生模型的softmax的不同。假设pp是数据的真实概率分布,zzrr是学生模型和教师模型的最后一层全连接层的输出。我们之前是使用负交叉熵损失l(p,softmax(z))l(p,\text{softmax}(z))来评估ppzz的不同,这里我们使用同样的loss来蒸馏。因此,loss变为:
(6)l(p,softmax(z))+T2l(softmax(r/T),softmax(z/T)),l(p,\text{softmax(z)})+T^2l(\text{softmax}(r/T),\text{softmax}(z/T)), \tag 6
这里TT是温度超参数,用来平滑softmax的输出,然后从教师模型的预测中蒸馏出标签分布的知识。

5.4. Mixup Training

在2.1中,我们描述了怎么进行训练前的图像增广。这里我们考虑另一种增广方法叫做mixup。在mixup里,每次我们随机采样两个样本(xi,yi)(x_i,y_i)(xj,yj)(x_j,y_j)。然后我们通过带权重的线性插值来得到一个新的样本:
(7)x^=λxi+(1λ)xj\hat x = \lambda x_i+(1-\lambda)x_j \tag 7
(8)y^=λyi+(1λ)yj\hat y = \lambda y_i+(1-\lambda)y_j \tag 8
这里λ[0,1]\lambda \in [0, 1]是一个随机从Beta(α,α)\mathbf{Beta}(\alpha, \alpha)分布选取的值。在mixup训练中,我们只使用新样本(x^,y^)(\hat x, \hat y)

5.5. Experiment Results

现在我们评估四个训练改进。label smoothing根据【26】ϵ=0.1\epsilon=0.1。模型蒸馏设置T=20T=20,使用带cosine衰减和label smoothing的预训练ResNet-152-D作为教师模型。在mixup训练中,选择α=0.2\alpha=0.2的Beta分布,从120个epochs增加到200,因为混合样本需要更长的训练时间来更好的收敛。当结合mixup和蒸馏进行训练时,我们也使用mixup来训练教师模型。
表6显示了不同方法的模型的准确率。蒸馏在ResNet效果很好,在别的模型上效果不好,我们认为是因为教师模型和学生模型不属于同一类导致的,不同的预测分布,会对模型有负面的影响。
Bag of Tricks for Image Classification with Convolutional Neural Networks
表6:ImageNet上验证集的准确率,依次堆叠训练改进方法。baseline是第三部分的模型。

Conclusion

本文试验了一系列训练深度卷积网络的技巧来提升模型准确率。这些技巧从模型结构,数据预处理,损失函数和学习率策略进行改进。