ResNet 训练 Bag of Tricks 精读笔记

最近读了一篇很实用的论文——《Bag of Tricks for Image Classification with Convolutional Neural Networks》,主要思路是把一堆训练技巧叠在一起,把 ResNet-50 在 ImageNet 上的 Top-1 精度从 75.3 提升到 79.29。整体内容按章节走,逐一记录。

标准训练流程(Baseline)

论文第 2 章先把标准训练流程讲清楚,作为后续比较的 baseline。

训练阶段数据预处理步骤:

  1. 将图片转换为 32 位 float,像素值放到 [0, 255] 范围内;
  2. 随机裁剪一个矩形区域,长宽比在 3/4 到 4/3 之间,裁剪后 resize 到 224×224;
  3. 以 0.5 的概率随机水平翻转;
  4. 调整亮度、饱和度等颜色属性;
  5. 加入 PCA 噪声,噪声系数从 N(0, 0.1) 中采样;
  6. 归一化。

验证阶段则是保持长宽比将短边缩放到 256,然后在中心 crop 出 224×224。

网络初始化统一使用 Xavier,优化器是 Nesterov Accelerated Gradient,硬件是 8×V100,共训练 120 个 epoch,batch size 256,初始学习率 0.1,在第 30、60、90 个 epoch 时各衰减为原来的 1/10。

面向新硬件平台的训练技巧

第 3 章讨论的是面向现代 GPU 硬件的工程层面 trick。

大 Batch 与学习率线性缩放

在凸优化中 batch size 越大收敛速度会下降,神经网络上也观测到类似现象:同等 epoch 下,小 batch size 往往能取得更好的验证集精度。把 batch size 从 256 调到 1024,大概会损失 0.x% 的 Top-1 精度。

增大 batch size 不改变随机梯度的期望,只会减小其方差,也就是降低梯度噪声。这时可以对应调大学习率——建议线性缩放:256 对应 0.1,512 对应 0.2,以此类推。

Warm-up

直接从很大的学习率起步容易不稳定,可以配合 warm-up:在训练最开始的 n 个 epoch(比如 5 个)将学习率从 0 线性增加到初始学习率。

Weight Decay 的施加范围

weight decay 最好只加在卷积层和全连接层的权重上,不要加在 bias 上,BN 层的参数(gamma、beta)也不要加 weight decay。

低精度训练(FP16)

在 V100 上从 FP32 切换到 FP16 计算,速度可以提升 2~3 倍——V100 的 FP32 算力约 14 TFLOPS,FP16 约 100 TFLOPS。

直接用 FP16 会干扰训练,一种方式是把所有参数和激活值存为 FP16,参数更新时使用 FP32 做累加。另一个实用办法是在 loss 上乘一个标量,将梯度数值限制在 FP16 可表示的范围内,同样可以加速。

网络结构上的微调

第 4 章是直接对 ResNet 做了几处细小的结构改动,并提出了一个改进变体,属于网络设计层面的调整,这里不展开。

训练过程的额外改良

第 5 章介绍了几个对精度提升比较明显的训练技巧。

Cosine 学习率衰减

原始 ResNet 用的是 step decay(阶梯式垂直下降),换成 cosine 衰减之后可以把精度提升将近一个点。

Label Smoothing

label smooth 同样能带来将近一个点的精度提升,实现简单,效果稳定。

Knowledge Distillation

利用 KD:在 softmax 输出的分类 loss 基础上,加上一项和 teacher 模型输出分布之间的 KD loss,让 student 从 teacher 的软标签中获取更多监督信号。

Mixup

mixup 数据增强也有效果,但需要注意:用了 mixup 之后要训练更长的时间,论文里是从 120 epoch 增加到了 200 epoch。

迁移学习效果

第 6 章讨论这些 trick 在迁移学习场景下的效果。最近接触这块不多,先暂时忽略。