CNN图像分类的tricks
Baseline:
预处理:
-
随机抽取一张图片,解码成32位浮点型的[0,255]的像素值形式
-
随机在原图上裁剪一片比例在[3/4, 4/3],面积在[8%, 100%]的矩形区域,然后resize到224x224
-
按0.5的概率对上一步的图片水平翻转
-
在[0.6, 1.4]之间均匀采样系数用于缩放色调、饱和度和亮度(HSB)
-
按正态分布N(0, 0.1)采样系数,用于添加一个PCA噪声
-
在图片的RGB通道上分别减去123.68,116.779,103.939然后除以58.393,57.12,57.375进行归一化。
验证:
保持验证图片的比例不变,将短边缩放到256,然后在其正中裁剪一块224x224的区域,并按和预处理中一样进行归一化。
参数初始化:
卷积层和全连接层的参数都是用Xavier算法初始化,使用中会将参数在[-a,a]之间均匀随机选取,a又由输入输出通道数决定a=sqrt(6/(in_channels+out_channels))。所有的bias都初始化为0。BN层的γ初始化为全1向量,β初始化为全0向量。
训练过程:
梯度更新策略使用NAG,每个模型在8个V100上训练120个epoch,batch size为256,学习率初始化为0.1,每30epoch衰减为1/10。
充分利用硬件:
大批量训练:
-
线性缩放的学习率:大批量的训练样本,会减小更新梯度的variance而不改变其expectation,因此当增大batch size的时候,可以线性的增大学习率以加快更新的过程。比如batch size从256增大到b,那么学习率就应该变为0.1*b/256。
-
学习率预热:训练开始时,所有参数都离我们的答案很远,这是使用较大的学习率可能会导致数值不稳定,因此可以在训练开始的一段时间内,使用较小的学习率,待训练稳定后恢复。比如可以在开始的m轮,每次的学习率逐渐增大,直到第m轮,恢复到原本的学习率。
-
Zero γ:将所有残差block的最后面的BN层的γ初始化为0,相对于减少了网络层数,开始的阶段更好训练。
-
不要bias正则化:正则化仅仅需要对weight进行。
低精度训练:
低精度训练的计算会快很多,但是由于变量的范围变窄了,因此更有可能超出范围,从而扰乱训练。有人提出将参数和**值用FP16存储,并且用FP16计算梯度,同时所有的参数还会有一个FP32的副本用以更新。此外,给loss乘以一个标量来将梯度范围对齐到FP16中也是一个缓解上面所说的扰乱训练的办法。
模型的调整:
下图是ResNet-50的原始结构
本文测试了3中结构上的调整:
上图中a改变了降采样的block,b改变了input stem,c还是改变了降采样block。
效果如下:
训练过程的优化:
余弦衰减学习率:
在训练过程中调整学习率很关键,一个最简单常用的学习率动态调整办法是每隔固定数目的epoch就按一定比例衰减学习率。Loshchilov提出的余弦衰减的策略更复杂。简化版的就是在warm-up之后按余弦函数衰减学习率,T为总的batch数目,t为当前batch序号。
标签平滑:
普通的训练中,对于真实的概率向量,我们会将其类别对应的那一项设为1,其余的为0,标签平滑却是下面这样做
上式中ε是一个小常数,K是类别总数。
知识蒸馏:
使用一个teacher网络帮助训练student网络,比如使用ResNet-152帮助训练ResNet-50。利用知识蒸馏训练时,需要增加一个distillation loss,用student网络和teacher网络的softmax输出计算均方差得到,注意teacher网络的模型不变。同时我们还是保留原本的交叉熵损失,新的损失函数变为下式。
混合训练:
其实就是利用随机采样的两个样本,按照下式生成新的训练样本
λ是从一个β分布中采样的[0, 1]的随机数,并且在混合训练中,只使用新产生的样本。
迁移学习:
作者讨论了使用上面的trick训练的模型能否在目标检测和语义分割中作为backbone发挥更好的作用。目标检测中讨论了backbone为VGG-19的Faster-RCNN,语义分割则使用了FCN作为baseline。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:CNN中卷积神经网络的技巧trick总结(图像识别/目标检测/语义分割) - Python技术站