CNN训练分类任务的优化策略(tricks)

CNN训练分类任务的优化策略(tricks)

CNN训练分类任务的优化策略(tricks)

 

最近读了论文Bag of Tricks for Image Classification with Convolutional Neural Networks 。这篇论文主要是描述了使用CNN训练图片分类器时可以用到的一些技巧,从提升训练速度、调整模型结构、训练过程几个方面提供了一些有用的tricks。自己尝试将论文中提到的tricks提炼出来,同时加上了一些知识补充。

提升训练效率:

在进行大batch_size训练的时候往往速度会变慢,文中提供了一些在不损失精度的情况下可以加速训练过程的tricks。

学习率热身:训练初期由于离目标较远,一般需要选择大的学习率,但是使用过大的学习率容易导致不稳定性。所以可以做一个学习率热身阶段,在开始的时候先使用一个较小的学习率,然后当训练过程稳定的时候再把学习率调回去。比如说在热身阶段,将学习率从0调到初始学习率。举个例子,如果我们准备用m个batches来热身,准备的初始学习率是 \eta ,然后在每个batch i, 1\leq i\leq m ,将每次的学习率设为 i\eta/m

将BN层的 \gamma 初始化0:对于ResNet来说,可以将残差块后面接的batch normalization层的 \gamma \hat{x} + \beta 中的 \gamma 初始化为0。这样做的好处是,在初始化阶段可以简化网络,更快训练。

No bias decay: 一般来说,权重衰减会用到网络中所有需要学习的参数上面。然而仅仅将权重衰减用到卷积层和全连接层,不对biases,BN层的 \gamma, \beta 做权重衰减,效果会更好。

低精度训练:一般来说神经网络以32位的浮点数进行训练,如果改为16位浮点数进行训练,速度会要快到2~3倍(如下表, baseline表示32位+batch 256, efficient表示16位+batch 1024)

 

模型微调技巧

对模型结构的微调往往会对结果造成影响。以ResNet50为例,对其下采样模块的结构进行微调,如ResNet-D, 原始的ResNet的下采样的卷积层1设置了步长s=2, 这样可能会损失一些信息,于是新的ResNet-D, 对换了卷积层1和卷积层2的步长设置,将卷积层1步长s设为1,卷积层2的步长虽然是2,但由于是用的3*3的卷积核,所以不会有信息损失,同时在另一条卷积路径的前面加了池化层,下表1显示对比起原始resnet, 这种结构对结果有一定的提升。(我自己觉得这种网络结构的改变估计还是要经过各种实验才能确定那种网络结构比较好,是一个工程问题)

其余的两种ResNet-B, ResNet-C的效果也比原始的好,大家有兴趣的可以回去看看原始论文

表1:各种ResNet结构的结果

训练过程的技巧

Cosine Learning Decay

学习率衰减大家都懂的,文中给出了一种可能更有效的衰减方式,我感觉之前在看一些代码的时候学习率衰减基本是step decay,多少个epoch后就除以一个数字这样子,论文里面提到的这种Cosine lr decay好像没怎么见到过,打算下次试一试,具体做法是,假设总batch size是T(忽略学习率热身阶段),初始学习率为 \eta ,那么在每个batch t, 将学习率设为:

\eta_{t} = \frac{1}{2}(1+cos(\frac{t\pi}{T}))\eta \\

这个lr decay我看了看,貌似tensorflow里面已经实现了,可以直接拿来用

Label Smoothing

正常的交叉熵损失在预测的时候,对于给定的数据集的label,将正例设为1,负例设为0,是一个one-hot向量。这样子会有一些问题,模型对于标签过于依赖,当数据出现噪声的时候,会导致训练结果出现偏差。同时,在数据量分布不均衡的时候,过度依赖某一类数量多的标签,会导致过拟合。所以label smoothing是说使用一个独立分布 u(y) ,将我们的label的真实标签 q(y|x) 和 u(y) 做一些混合,映射为 q'(k) ,将 q'(y|x) 重写为:

q'(y|x) = (1-\epsilon)*q(y|x) + \epsilon u(y) \\

其中 \epsilon 属于[0,1],这个公式的意思是,把label y的真实分布 q(y|x) 和独立分布 u(y) 按照一定比例混合到一起,形成新的分布 q'(y|x) ,为了方便计算,取 u(y) 为均匀分布, u(y)=1/K , K表示分类类别,则上式写为:

q'(y|x) = (1-\epsilon)*q(y|x) + \varepsilon/K \\

原始的交叉熵公式 H(p,q) = - \sum_{i=1}^Kq_ilogp_i , 我们将新的 q'(y|x) 代入,将得到:

H(q', p) = -\sum_{i=1}^Kq_i'logp_i = (1-\epsilon)H(q,p)+\epsilon H(u,p) \\

即相当于用两个loss, H(q,p), H(u,p) 来代替原先的交叉熵,可以认为loss函数一不同的权重对预测label与标注的label以及预测label与先验分布 u(y) 的label的差距进行惩罚。按照论文Rethinking the Inception Architecture for Computer Vision 里面的说法,这种对于分类效果有一定性能的提升。在商汤的这篇论文里面,他们将 \epsilon 设为0.1, 取得了不错的效果。

Knowledge Distillation

为什么英文名叫这个我也不知道,反正这个技术就是说用一个更优秀的model(称之为teacher)来辅助当前model训练。比如说,用ResNet152带动ResNet50训练,比如说我们现在用交叉熵作为损失函数,原始的loss是 l(p,softmax(z)) , p是真实的y的分布, z是我们要训练的model的全连接输出的结果,然后还有一个r,表示更优秀的model的全连接层输出的结果,我们把loss改为:

l(p, softmax(z)) + T^2l(softmax(r/T), softmax(z/T)) \\

T是一个临时参数,为了是的softmax的输出更加平滑,能从teacher model中学到一些关于标签分布的内容。在论文里面,将 T 设为了20

Mixup Training

这种办法是数据增量(data augmentation)的一种方法,每次随机取两个样本点 (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_i \\

\lambda \epsilon [0,1] , 是从 Beta(\alpha, \alpha) 分布中随机生成的。在mixup training中,只使用新的样本 (\hat x, \hat y) 进行训练。在论文里面, \alpha 被设为0.2, 然后epoch的次数从120提到200(因为mixed example需要更长的时间收敛)

刚刚说的这些训练过程中的tricks,商汤的论文里面给出了在分类任务中带来的提升:

 

论文把这些tricks迁移到目标检测任务,也非常有用;在语义分割任务上,cosine learning decay比较有用,其余的tricks似乎没有明显影响。

分割表现

参考文献

lqfarmer:优化策略5 Label Smoothing Regularization_LSR原理分析

深度学习中的各种tricks_1.0_label_smoothing - 兔角与禅 - CSDN博客

编辑于 11:18

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值