【BoT】《Bag of Tricks for Image Classification with Convolutional Neural Networks》

在这里插入图片描述

在这里插入图片描述

CVPR-2019



1 Background and Motivation

随着深度学习技术的发展,image classification 的精度也越来越高!

精度的提升不仅仅来自于 model architecture,也来自如下的 training procedure refinements

  • loss functions
  • data pre-processing
  • optimization methods
  • learn rate schedule
  • stride size of a particular convolution layer

然而 training procedure refinements 往往没有 model architecture 那样吸睛,都被冷落在论文中的 implementation details 部分 or only visible in source code

本文,作者翻牌 training procedure refinements

在这里插入图片描述

对各种 training procedure refinements 进行了详细的分析实验,通过组合拳,把 ResNet 在 ImageNet 上的 Top-1 ACC 从 75.3% 提到了 79.29%,这些技巧用在 object detection 和 semantic segmentation 任务中也能提升精度!

2 Advantages / Contributions

总结归纳各种 tricks,组合起来调 resnet,精度从 75.3 提到了 79.29(Top of ImageNet)

在这里插入图片描述

3 Baseline

提供了一种标准训练测试流程

训练

  • 32-bit,0~255
  • randomly crop,aspect ratio [3/4,4/3],scale [8%, 100%],最后 resize 到 224×224
  • 50% 水平翻转
  • hue,saturation,brightness 增强 [0.6,1.4](参考本博客附录部分)
  • PCA noise(参考本博客附录部分)
  • 减均值除以方差

在这里插入图片描述

测试

  • resize 短边到 256,保持 aspect ratio,从中心区域中截选出 224×224
  • 减均值除以方差

按照上述标准流程,得到的结果如下表所示

在这里插入图片描述

4 Efficient Training

4.1 Large-batch training

大 batch-size 的好处在于,会缩短训练时间

但是

For convex problems,convergence rate decreases as batch size increases

这里理解起来可能不是那么顺畅,再看看这个讨论(Rhett 的回答)

在这里插入图片描述

换句话说

for the same number of epochs,training with a large batch size(仅仅增大 batch-size,不做其他的改变) results in a modal with degraded validation accuracy compared to the ones trained with smaller batch sizes

想在不影响收敛速度(精度)的情况下,加快训练速度(增大batch),作者给出了如下的建议

1)Linear scaling learning rate

在这里插入图片描述

大的 batch-size 只会 reduce the noise in the gradient,并没有改变 expectation of stochastic gradient(个人感觉期望还是有改变的),因此采用大的 bath-size 后,可以采用大的学习率提升其收敛速度

eg:batch-size 为 256,采用 0.1 0.1 0.1 初始学习率
则:batch-size 为 b b b, 应该用 0.1 × b / 256 0.1 × b / 256 0.1×b/256


2)Learning rate warmup

在这里插入图片描述

训练刚开始时,参数都是随机初始化的,离 final solution 十万八千里,这个时候用太大的学习率容易导致 numerical instability

此时,比较好的处理方式时慢热,类似于热身,让网路通过几个 epoch 的学习后达到初始学习率

eg:初始学习率为 η \eta η,用 m m m 次 iteration 到初始学习率,那么第 i i i 次( 1 ≤ i ≤ m 1≤i≤m 1im)迭代的学习率应该为 i η / m i \eta /m iη/m

下图最左边部分即为 warmup

在这里插入图片描述


3)Zero γ \gamma γ

在这里插入图片描述

ResNet 的 bottleneck 部分可以表示为 X + F ( x ) X + F(x) X+F(x)

在这里插入图片描述

在每个 bottleneck 中, F ( x ) F(x) F(x) 以是以 batch-normalization 层结束的,batch-normalization 算法如下图所示(详细解析可以参考 【BN】《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》

在这里插入图片描述
常规操作中, γ \gamma γ β \beta β 初始化的值分别为 1 和 0,也即 X + 1 × F ( x ) + 0 X + 1×F(x) + 0 X+1×F(x)+0

Zero γ \gamma γ 策略中, γ \gamma γ 的初始化为 0,也即 X + 0 × F ( x ) + 0 X + 0×F(x) + 0 X+0×F(x)+0 F ( x ) F(x) F(x) 部分直接被砍了,仅返回 X X X

all residual blocks just return their inputs,mimics network that has less number of layers and is easier to train at the initial stage.


4)No bias decay

在这里插入图片描述

正常情况下,weight-decay 会应用到 all learnable parameters,包括 weight,bias, batch normalization 算法中的 γ \gamma γ β \beta β

目的是进行 L2 regularization,drives their values towards 0

但 weight-decay 一般时为了防止过拟合才使用

no bias decay heuristic 中,除了 weight 用 weight-decay,其他的 learnable parameters 都没有使用 weight-decay!包括 batch normalization 算法中的 γ \gamma γ β \beta β

4.2 Low-precision training

New hardware, however, may have enhanced arithmetic logic unit for lower precision data types

比如 V100 显卡,32 bit 浮点运算提供 14T FLOPS,16 bit 浮点运算提供 over 100T FLOPS!算力越多,可以承载的运算量更大

在这里插入图片描述

上表展示了在不同算力下的结果(256 batch-size vs 1024 batch-size,还引入了 linear scaling learning rate 策略)

可以看出,低精度不仅加速,效果还很猛

下面看看 16bit 的代码实现

16bit 精度是将内存占用减半的惊人技术。大多数模型使用 32bit 精度数字进行训练。然而,最近的研究发现,16bit 模型也可以工作得很好。

混合精度意味着对某些内容使用16bit,但将权重等内容保持在 32bit。

要在Pytorch中使用16bit 精度,请安装NVIDIA的apex库,并对你的模型进行这些更改。

模型 / 优化器 / loss / back-propagation

# enable 16-bit on the model and the optimizer
model, optimizers = amp.initialize(model, optimizers, opt_level='O2')

# when doing .backward, let amp do it so it can scale the loss
with amp.scale_loss(loss, optimizer) as scaled_loss:                      
    scaled_loss.backward()

amp包会处理好大部分事情。如果梯度爆炸或趋向于0,它甚至会缩放loss。

英文原文:
9 Tips For Training Lightning-Fast Neural Networks In Pytorch

中文翻译:
9个技巧让你的PyTorch模型训练变得飞快!

但是要小心一些不安全的操作如 mean 和 sum,溢出fp16。(Pytorch有什么节省显存的小技巧? - 郑哲东的回答 - 知乎

pytorch混合精度训练

4.3 Experiment Results

在这里插入图片描述

感觉应该是每行单独加上第一行的结果,而不是累加的结果,可以看出,作者引出的 tricks 还是蛮实在的

PS:如果是累加的结果,感觉 No bias decay 的意义就失去了

5 Model Tweaks

5.1 ResNet Architecture

先看看 ResNet 原论文中的结构,注意 50-layer 这一列

在这里插入图片描述

下面看看作者对原始结构的描述
在这里插入图片描述

5.2 ResNet Tweaks

在实践和理论发展过程中,resnet 不断优化

1)ResNet-B
改进前 在这里插入图片描述 改进后在这里插入图片描述

在 Figure1 的 Down sampling 模块中,Path A 一上来就用 1×1 步长为 2 的 conv,会导致信息损失 3/4,

ResNet-B 在 ResNet-A 的基础上,将步长为 2 的操作后移到了 3×3 conv 中(3×3 配合步长 2 是会遍历到原始特征图所有空间位置的,所以很大程度上弥补了信息损失),一定程度上平滑了信息的过渡阶段

2)ResNet-C

改进前在这里插入图片描述 改进后在这里插入图片描述

在 Figure1 的 Input stem 模块中,采用的是 7×7 Conv

后续学者们发现,computational cost 与卷积核的大小是 quadratic 关系,所以 7×7 Conv ~5.4(49/9 ) more expensive than 3×3 Conv

为了效率,把 7×7 Conv 换成了 3 个 3×3 Conv

3)ResNet-D

改进前 在这里插入图片描述 改进后在这里插入图片描述

ResNet-B 结构基于 ResNet 中 path A 分支的不足进行了改进,作者进一步指出,path B 也出现了 1×1 Conv 搭配步长为 2,也会导致 3/4 information 流失,因此引入 average pooling 来缓解信息的流失,如 figure 2(C)所示

5.3 Experiment Results

在这里插入图片描述
这里 ResNet-C 包含了 ResNet-B 的 tweaks,ResNet-D 包含了 ResNet-B 和 ResNet-C 的 tweaks

模型 B 到 C 的变换中, 可以观察到 FLOPs 增加了,作者这里应该是改变了 3 个 3× 3 Conv 的 channels,如果保持和 7×7 一样的话,FLOPs 是会减少的

6 Training Refinements

6.1 Cosine Learning Rate Decay

在这里插入图片描述

t t t 表示 t t t-th bath,T 表示训练中所有 batch 的数量(这里 batch 可以理解为 epoch), η \eta η 是初始的学习率

上面公式 cos 里的范围为 0 0 0~ π \pi π,cos 的范围为 1 1 1 ~ − 1 -1 1,加上外面的 1 然后除以 2 范围为 1 1 1 ~ 0 0 0,最后 × η \eta η,可以看出上述公式是在初始学习率的基础上,以 cos 函数的走势,降到 0,也即 cosine decay

下图展示了 warmup 和 cosine decay 策略

在这里插入图片描述

相比于 step decay,一开始下降比较快,后面缓慢下降

下面自己实现下公式(1)

import matplotlib.pyplot as plt
import numpy as np

T = 120
x = np.arange(T)

lr = 0.01
y1 = 1/2 * (1+ np.cos(np.pi * x / T)) * 0.01   # cosine decay

y2 = [0.01]*30 + [0.001]*30 + [0.0001]*30 + [0.00001]*30  # step decay

plt.plot(x, y1)
plt.plot(x, y2, "--")
plt.show()

在这里插入图片描述

6.2 Label Smoothing

原理可以参考 【Inception-v3】《Rethinking the Inception Architecture for Computer Vision》

softmax 的输出 q q q

在这里插入图片描述

原始 GT 分布为

p i = { 1 i = y 0 i ≠ y p_i = \left\{\begin{matrix} 1 & i=y\\ 0 & i\neq y \end{matrix}\right. pi={10i=yi=y

label smoothing 后的 GT 分布 p p p
在这里插入图片描述

交叉熵损失
在这里插入图片描述

原始输出最优解(导数为 0 时)为

z i ∗ = i n f z_i^* = inf zi=inf

缺点是太自信了

it encourages the output scores dramatically distinctive which potentially leads to overfitting

引入 label smoothing 后的最优解为
在这里插入图片描述

求导细节可以参考 label smoothing 如何让正确类与错误类在 logit 维度拉远的?


图 4 (a)展示了 K = 1000 K=1000 K=1000 时,最优解 z i ∗ z_i^* zi 随着 ϵ \epsilon ϵ 的变化的趋势

在这里插入图片描述

自己画画试试

import matplotlib.pyplot as plt
import numpy as np

K = 1000
x = np.arange(0.01, 1.0, 0.01)
y = np.log2((K-1)*(1-x)/x)
plt.plot(x, y)
plt.show()

在这里插入图片描述

图(b) 展示的是加 label smooth 和不加 label smooth 时, the gap between the maximum prediction and the average of the rest
在这里插入图片描述

可以看到引入 label smoothing 后,with label smoothing the distribution centers at the theoretical value and has fewer extreme values

GT 类和其他类预测的结果差距变小了(没那么自信了),而且比较集中,跨度没有那么大(优化空间减少了)

我们也可以看看理论的峰值

import math
K = 1000
alpha = 4  # 这里比较随意
x = 0.1
diff = math.log((K-1)*(1-x)/x, math.e) + alpha - alpha
print(diff)

output

9.103979355984773

和图中蓝色虚线峰值的横坐标相呼应

6.3 Knowledge Distillation

【Distilling】《Distilling the Knowledge in a Neural Network》

在这里插入图片描述
z z z r r r 分别为 student model 和 teacher model 的 logits

T T T 是温度

6.4 Mixup Training

randomly sample two examples,然后 weighted linear interpolation of these two examples

在这里插入图片描述

λ \lambda λ~ B e t a ( α , α ) Beta(\alpha,\alpha) Beta(α,α) 分布
在这里插入图片描述

使用时要配合更多的 epochs

increase the number of epochs from 120 to 200 because the mixed example ask for longer training progress to converge better

6.5 Experiment Results

在这里插入图片描述

Teacher 网络是 ResNet-152-D

Teacher 网络也使用了 cosine decay / label smoothing / mixup( α = 0.2 \alpha=0.2 α=0.2

观察到知识蒸馏在 Inception 和 mobilenet 上的表现并不是很好,作者的解释为

Our interpretation is that the teacher model is not from the same family of the student, therefore has different distribution in the prediction, and brings negative impact to the model.

在 MIT Places365 data-set 上验证一下泛化性,结果如下所示

在这里插入图片描述

7 Transfer Learning

7.1 Object Detection

在这里插入图片描述

基于 Faster RCNN 框架,在 VOC 数据集上训练测试,结果如 Table 8 所示

第一列是在 ImageNet 的上的训练结果

7.2 Semantic Segmentation

基于 FCN 框架,在 ADE20K 上进行结果评估

在这里插入图片描述

cosine decay 依然坚挺,
在这里插入图片描述

其他策略就疲软了! 作者相应的解释为

semantic segmentation provides dense prediction in the pixel level. While models trained with label smoothing, distillation and mixup favor soften labels, blurred pixel-level information and degrade overall pixel-level accuracy.

8 Conclusion(own)

  • 行文结构更像是实验报告,或者毕业论文
  • 大 batch-size 和大 learning rate 配对
  • 初始化 BN 层的参数都为 0
  • 仅权重做 weight decay
  • warm up
  • 16 bit
  • conv 1×1 配合 stride = 2,会丢失 3/4 的 information
  • Cosine Learning Rate Decay
  • Label Smoothing
  • Knowledge Distilling
  • Mixup
  • 截取一下大 batchsize 的缺点
    在这里插入图片描述
    深度学习中的batch的大小对学习效果有何影响? - 言有三的回答 - 知乎
    https://www.zhihu.com/question/32673260/answer/675161450

【附录A】

hue,saturation,brightness 数据增强

来自 SSD中的数据增强细节

在这里插入图片描述
在这里插入图片描述

PCA noise 数据增强方式

来自 《ImageNet Classification with Deep Convolutional Neural Networks》,也即 AlexNet,核心公式为

在这里插入图片描述

  • λ \lambda λ p ⃗ \vec{p} p 为协方差矩阵(3 × 3 covariance matrix of RGB pixel values)的特征值和特征向量

  • α \alpha α 是根据高斯分布产生的系数

具体实现如下,参考 【方法】数据增强(Data Augmentation)

import numpy as np
from PIL import Image
import random

import matplotlib.pyplot as plt

def pca_jitter(image_path):
    img = Image.open(image_path)
    img = np.asanyarray(img, dtype="float32")
    img = img / 255.0 # 0~1 之间
    img1 = img.reshape(img.size//3, 3)  # H*W*C to HW*C
    img1 = np.transpose(img1) # 转置
    img_cov = np.cov([img1[0], img1[1], img1[2]])  # covariance matrix
    lamda_cov, p_cov = np.linalg.eig(img_cov)  # eigenvector and eigenvalue of covariance matrix
    p_cov = np.transpose(p_cov)  # eigenvector
    
    alpha1 = random.gauss(0, 3) # 均值为0,方差为 3
    alpha2 = random.gauss(0, 3)
    alpha3 = random.gauss(0, 3)
    
    v = np.transpose((alpha1*lamda_cov[0], alpha2*lamda_cov[1], alpha3*lamda_cov[2])) # 核心公式

    add_num = np.dot(p_cov, v)

    img2 = np.array([img[:, :, 0] + add_num[0],
                     img[:, :, 1] + add_num[1],
                     img[:, :, 2] + add_num[2]])

    # bgr to rgb
    img2 = np.swapaxes(img2, 0, 2)
    img2 = np.swapaxes(img2, 0, 1)

    img2 = (img2-img2.min())/(img2.max()-img2.min()) # 归一化处理

    plt.subplot(1, 2, 1)
    plt.axis("off")
    plt.title("Original Image")
    plt.imshow(img)

    plt.subplot(1, 2, 2)
    plt.axis("off")
    plt.title("PCA jitter")
    plt.imshow(img2)
    plt.show()
    
    
pca_jitter("/home/Downloads/urban_beauty.jpg")

注意一些细节,

  • 论文中 α \alpha α N ∼ ( 0 , 0.1 ) N \sim (0,0.1) N(0,0.1) 高斯分布从产生,为了方便可视化效果,代码中的高斯分布为 N ∼ ( 0 , 3 ) N \sim (0,3) N(0,3)

  • 原图加上 PCA 扰动后,像素值会溢出(超过 1 或者说超过 255),为了可视化方便,我进行了归一化处理(归一化到 0~1 之间),实际训练的时候不需要归一化

效果图如下:

在这里插入图片描述


摘抄来自 无痛涨点:目标检测优化的实用Trick

1)数据增强

目标标注框比实际的物体紧缩框大大概几个像素时得到的检测结果统计精度和定位框的稳定性都会好,那么我们是不是可以认为,对anchor base的检测网络来说,目标物体的边缘也是很重要的,所以就想到了通过canny算子增强边缘的方式来增强训练数据。(PS:感觉应该是背景信息也很重要而不是边缘)

实际使用过程如下:
1)通过对输入数据的手动查验或自动化统计,确定较好的canny阈值
2)利用阈值对训练样本中10-20个batch的数据进行canny边缘增强。
3)增强方式为:原图转灰度提取到的canny边缘所对应的原图像素位置进行对比度增强或直接涂黑。加深程度可以由自定义的超参数alpha来指定。
4)用这10-20个batch的数据进行几个epoch的训练后再换成普通数据进行训练。

2)anchor的调整
核心思路就是:anchor的分布也要满足对全集的稀疏覆盖而不仅仅是你的当前数据集(但是在实际训练的时候,并不是说大目标就一定由yolov3的最初设计的大目标输出层输出的。很可能就是由中间目标层输出的,而因为anchor的设计过大,导致训练的网络不收敛的有之,明明收敛了,却检测不到目标的情况也有之)。

3)后处理的优化
比如海思的NPU部署的时候,会限制比较大的pool核,所以最好训练的时候就把大的pooling切换为几个小的连续pooling,实测虽然理念上两者应该是差不多的,但是实际上还是差了0.3%的精度。(指的是直接多层的pooling转换到板子和训练时是一个大的pooling,到转换时候再改结构成几个小的pooling)

还有一个就是nms部分,这部分也有同学问过我说因为我的数据集有遮挡,可能两个离的比较近的,nms就把有遮挡的那个小目标去掉了。这部分分享一个小技巧就是,你在算nms的时候,也关注一下两个框的中心点距离可以设置中心点距离超过多少的两个框,不做nms。这样就能避免nms的一部分武断删除检测结果bbox。

4)大模型的训练技巧
有一位同学问过我,就是为啥同样的模型,用比较少的数据训练的时候很快到了97%的MAP,但是换300w的大数据集的训练以后,卡在93%上不去了。这里面有一个技巧叫warm up,也就是说在大数据下训练模型的时候,可以先从大数据集上取一部分数据训练模型,然后以这个训练的模型为预训练模型,在大数据集上,增大batch_size再进行训练,至少没卡在93%这个问题上了。

模型的调参训练技巧其实说白了就是怎么让模型得到的是数据全集的稀疏分布,且和别的类别有比较好的区分,也就是类内差小类间差则尽量大。以这个为核心,告诉模型应该关注什么,少关注什么,既然是数据的科学,多关注数据的分布和呈现的状态,祝大家在训练的时候都得到自己满意的结果。


数据集很少、数据分布不均衡且数据类别间的差距较小时,可以用对比学习的方法来替代图像分类.


风格迁移GAN

《IMAGENET-TRAINED CNNS ARE BIASED TOWARDS TEXTURE; INCREASING SHAPE BIAS IMPROVES ACCURACY AND ROBUSTNESS》(ICLR-2019)

We show that ImageNettrained CNNs are strongly biased towards recognising textures rather than shapes, which is in stark contrast to human behavioural evidence and reveals fundamentally different classification strategies
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

想读懂YOLOV4,你需要先了解下列技术(一)
在这里插入图片描述

【附录B——More tricks】

来自:

学习率

(1)Backbone 和 Heads 的不同学习率 (LR)

因为Backbone和Heads在结构上的差异,使用不同的学习率是可以有效的使得网络整理达到更好,更稳定的收敛效果。

(2)with flooding
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值