ICML-2015
在 CIFAR-10 上的小实验可以参考如下博客:
【Keras-Inception v2】CIFAR-10
文章目录
1 Background and Motivation
机器学习中存在一个training data 和 testing data 分布不一致的问题,叫做 Covariate Shift
我们讲的规范一点(【机器学习】covariate shift现象的解释):
假设q1(x)是测试集中一个样本点的概率密度,q0(x)是训练集中一个样本点的概率密度。最终我们估计一个条件概率密度p(y|x,θ),它由x和一组参数θ={θ1,θ2…θm}所决定。对于一组参数来说,对应loss(θ)函数评估性能的好坏
综上,当我们找出在q0(x)分布上最优的一组θ’时,能否保证q1(x)上测试时也最好呢?
传统机器学习假设训练集和测试集是独立同分布的,即q0(x)=q1(x),所以可以推出最优θ’依然可以保证q1(x)最优。但现实当中这个假设往往不成立,伴随新数据产生,老数据会过时,当q0(x)不再等于q1(x)时,就被称作covariate shift
作者注意到
The distribution of each layer’s inputs changes during training(这也就是 Internal Covariate Shift)
缺点如下:
- slows down the training by requiring lower learning rates and careful parameter initialization
- hard to train models with saturating nonlinearities
作者的解决方法:normalization for each training mini-batch
代码见附录
初始化不好,Wx+b 偏大或者偏小,Sigmoid’(Z)很小,梯度消失,网络越深越明显(反向传播的时候,激活函数的导数和W会随着网络的向前深入一直连乘下去)
解决办法:
- Relu
- careful initialization
- small learning rate
作者的解决办法
ensure that the distribution of nonlinearity inputs remains more stable as the network trains
注意一个前提
It is based on the premise that convariate shift also applies to sub-network and layers.
2 Advantages
- reaching 4.9% top-5 validation error (and 4.8% test error), exceeding the accuracy of human raters.
3 Innovations
注意到了 Internal Covariate Shift 的问题,并提出BN,大大加速训练速度
4 Method
4.1 Batch Normalization
x = Wu+b
可导性证明
y y y 和 l l l 的关系就是损失函数,用链式求导法则感觉怪怪的,比如 ∂ l ∂ μ B \frac{\partial l}{\partial \mu_{B}} ∂μB∂l 中, x ^ i = f 1 ( μ B , σ B 2 ) \hat{x}_{i} =f_1(\mu_{B}, \sigma_{B}^{2}) x^i=f1(μB,σB2) , σ B 2 = f 2 ( μ B ) \sigma_{B}^{2} = f_2(\mu_{B}) σB2=f2(μB) ,按链式求导法则应该是
∂ l ∂ μ B = ∂ l ∂ x ^ i ⋅ ( ∂ x ^ i ∂ σ B 2 ⋅ ∂ σ B 2 ∂ μ B + ∂ x ^ i ∂ μ B ) + ∂ l ∂ σ B 2 ⋅ ∂ σ B 2 ∂ μ B \frac{\partial l}{\partial \mu_{B}} = \frac{\partial l}{\partial \hat{x}_{i} } \cdot (\frac{\partial \hat{x}_{i} }{\partial \sigma_{B}^{2} } \cdot \frac{\partial \sigma_{B}^{2} }{\partial \mu_{B} }+ \frac{\partial \hat{x}_{i} }{\partial \mu_{B} }) + \frac{\partial l}{\partial \sigma_{B}^{2} } \cdot \frac{\partial \sigma_{B}^{2} }{\partial \mu_{B} } ∂μB∂l=∂x^i∂l⋅(∂σB2∂x^i⋅∂μB∂σB2+∂μB∂x^i)+∂σB2∂l⋅∂μB∂σB2
而论文的做法是
∂ l ∂ μ B = ∂ l ∂ x ^ i ⋅ ∂ x ^ i ∂ μ B + ∂ l ∂ σ B 2 ⋅ ∂ σ B 2 ∂ μ B \frac{\partial l}{\partial \mu_{B}} = \frac{\partial l}{\partial \hat{x}_{i} } \cdot \frac{\partial \hat{x}_{i} }{\partial \mu_{B} } + \frac{\partial l}{\partial \sigma_{B}^{2} } \cdot \frac{\partial \sigma_{B}^{2} }{\partial \mu_{B} } ∂μB∂l=∂x^i∂l⋅∂μB∂x^i+∂σB2∂l⋅∂μB∂σB2
∂ l ∂ x i \frac{\partial l}{\partial x_i} ∂xi∂l 也是这样处理的,不晓得是我记错了还是神经网路的求导不一样,有待我进一步否定自己
注意测试的时候 μ \mu μ 和 σ \sigma σ 要固定下来,固定的方法如下(参考 【深度学习】深入理解Batch Normalization批标准化):
因为每次做Mini-Batch训练时,都会有那个Mini-Batch里m个训练实例获得的均值和方差,现在要全局统计量,只要把每个Mini-Batch的均值和方差统计量记住,然后对这些均值和方差求其对应的数学期望即可得出全局统计量。也即步骤10所示!
Q:疑问?为什么要来个
m
m
−
1
\frac{m}{m-1}
m−1m?
m
m
m 是 batch size
A:在概率统计里,当计算方差时,如果期望已知,则除以
m
m
m,如果期望需要用样本的均值估计出来,则除以
m
−
1
m-1
m−1
训练的时候方差已知,除以 m m m,现在方差是估计值,除以 m − 1 m-1 m−1
11 由如下表达式推导得来
y
=
γ
⋅
x
−
E
[
x
]
V
a
r
[
x
]
+
ε
+
β
y = \gamma \cdot \frac{x-E[x]}{\sqrt{Var[x]+\varepsilon }} + \beta
y=γ⋅Var[x]+εx−E[x]+β
4.2 Inception-v2
有些人总结 v2和v3都出自一篇论文(【Inception-v3】《Rethinking the Inception Architecture for Computer Vision》),结构一样,只是穿上了钢铁侠的盔甲,v3 = v2 + RMSProp + LSR + BN auxiliary
也有些人认为 v2 是出自本片博客讲述的论文(《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》),此论文对 Inception-v1 做了一点点小改进。
- 5×5 to 两个 3×3
- parameters 增加 25%,computational cost 增加 30%
- 28×28 的 Inception 数量 2 to 3
- average pooling + max pooling 交替,v1中最后用 average pooling,中间都是 max pooling
- 有 pass through 结构
个人还是倾向于 BN+小改进的 Inception-v1 = Inception-v2,结构如下
【Inception-v1】《Going Deeper with Convolutions》 的结构见表1
5 Datasets
LSVRC 2012
6 Experiments
1)小试牛刀——MINIST
分布看不懂可以想想成是高斯分布,面积的15%,50%,80%
2)加速版 BN
加速技术
- Increase learning rate
- Remove Dropout
- Reduce the L2 weight regularization
- Accelerate the learning rate decay
- Remove Local Response Normalization
- Shuffle training examples more thoroughly
- Reduce the photometric distortions
加速版本
- Inception-v1
- BN-baseline = Inception-v1 + BN,initial learning rate is 0.0015
- BN-x5:learning rate*5 = 0.0075
- BN-x30:learning rate*30 = 0.045
- BN-x5-Sigmoid:Sigmoid instead of Relu
3)华山论剑(掌门solo)
不得不佩服的是 BN使得 Sigmoid 都能收敛,而且精度相当高(Without Batch Normalization, Inception with sigmoid never achieves better than 1/1000 accuracy.)霸气如斯!!!
需要注意的是 BN-x30 反而比 BN-x5 慢,但是最终精度高
BN 大大的提升了训练的速度
4)决战光明顶(门派混战——ensemble)
7 Conclusion / Future work
7.1 Conclusion
BN 是加在 activation function 之前的,而且是以 mini-batch 来计算,不像之前的有些工作加在activation function 之后。
BN 能使得训练更稳定,网络能用更大的 learning rate(会快许多),不那么 care initial 的质量,有些 regularization 的味道,in some case eliminating the need for Dropout.
Q1:链式求导法则的疑惑
Q2:Algorithm 2 的通透理解
Q3:归一化后
γ
\gamma
γ (scale)and
β
\beta
β (shift)的作用以及意义
Q4:Batch Normalization also makes training more resilient to the parameters scale. 公式证明的理解
参考学习来自 [深度学习框架]PyTorch常用代码段
当使用 torch.nn.DataParallel 将代码运行在多张 GPU 卡上时,PyTorch 的 BN 层默认操作是各卡上数据独立地计算均值和标准差,同步 BN 使用所有卡上的数据一起计算 BN 层的均值和标准差,缓解了当批量大小(batch size)比较小时对均值和标准差估计不准的情况,是在目标检测等任务中一个有效的提升性能的技巧。
sync_bn = torch.nn.SyncBatchNorm(num_features, eps=1e-05, momentum=0.1, affine=True,
track_running_stats=True)
将已有网络的所有BN层改为同步BN层
def convertBNtoSyncBN(module, process_group=None):
'''Recursively replace all BN layers to SyncBN layer.
Args:
module[torch.nn.Module]. Network
'''
if isinstance(module, torch.nn.modules.batchnorm._BatchNorm):
sync_bn = torch.nn.SyncBatchNorm(module.num_features, module.eps, module.momentum,
module.affine, module.track_running_stats, process_group)
sync_bn.running_mean = module.running_mean
sync_bn.running_var = module.running_var
if module.affine:
sync_bn.weight = module.weight.clone().detach()
sync_bn.bias = module.bias.clone().detach()
return sync_bn
else:
for name, child_module in module.named_children():
setattr(module, name) = convert_syncbn_model(child_module, process_group=process_group))
return module
7.2 Future work
- BN+RNN
- domain adaptation
We believe that further theoretical analysis of the algorithm would allow still more improvements and applications.
8 Other normalizations
更形象化的理解,四种 normalization 如下所示
9 附录 sigmoid
import matplotlib.pyplot as plt
import numpy as np
import math
x = np.arange(-10,10,1)
y = 1/(1+ math.e**-x)
z = y*(1-y)
plt.plot(x,y)
plt.plot(x,z)
plt.xlabel("z = Wx+b")
plt.ylabel("Sigmoid")
ax = plt.gca()
#去掉边框
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
#移位置 设为原点相交
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
plt.legend(["Sigmoid (z)", "Sigmoid' (z)"])# 图例
plt.grid()#网格
plt.savefig('1.jpg')
plt.show()
《How does batch normalization help optimization?》(NIPS-2018)
参考
【1】当我们的经验无法适应新环境的时候该怎么办? Covariate Shift(★★★)
【2】深度学习中 Batch Normalization为什么效果好? - 我不坏的回答 - 知乎
https://www.zhihu.com/question/38102762/answer/391649040 (★★★★★,防止梯度消失爆炸)