【转载】 BN(batch normalization)

原文地址:

https://blog.csdn.net/qq_35608277/article/details/79212700

-------------------------------------------------------------------------------------------------------

算法本质解决梯度弥散,加入了BN层,减少了Internal Covariate Shift(内部neuron的数据分布发生变化),使每一层的输出都规范化到一个N(0, 1)的高斯

优势:

     (1) 可以使用更高的学习率 
如果每层的scale不一致,实际上每层需要的学习率是不一样 的,同一层不同维度的scale往往也需要不同大小的学习率,通常需要使 用最小的那个学习率才能保证损失函数有效下降,Batch Normalization将每层、每维的scale保持一致,那么我们就可以直接使用较高的学习率进行优化。

    (2) 移除或使用较低的dropout。
dropout是常用的防止overfitting的方法,而导致overfit的位置往往在数据边界处,如果初始化权重就已经落在数据内部,overfit现象就可以得到一定的缓解。论文中最后的模型分别使用10%、5%和0%的dropout训练模型,与之前的40%-50%相比,可以大大提高训练速度。
 
  (3) 降低L2权重衰减系数。
还是一样的问题,边界处的局部最优往往有几维的权重(斜率)较大,使用L2衰减可以缓解这一问题,现在用了Batch Normalization,就可以把这个值降低了,论文中降低为原来的5倍。

       (4) 取消Local Response Normalization层。
由于使用了一种Normalization,再使用LRN就显得没那么必要了。而且LRN实际上也没那么work。
  


  (5) 减少图像扭曲的使用。
由于现在训练epoch数降低,所以要对输入数据少做一些扭曲,让神经网络多看看真实的数据。

1.Motivation

网络训练过程中参数不断改变导致后续每一层输入的分布也发生变化,而学习的过程又要使每一层适应输入的分布,作者将分布发生变化称之为internal covariate shift。因此我们不得不降低学习率、小心地初始化。
为了加快训练,在训练网络的时会将输入减去均值,还有些人甚至会对输入做白化等操作。相当于在网络的每一层输入的时候,又插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层。

常用PCA白化:即对数据进行PCA操作之后,再进行方差归一化。
基本满足0均值、单位方差、弱相关性

但是,对每一层数据都使用白化操作,分析认为这是不可取的。因为白化需要计算协方差矩阵、求逆等操作,计算量很大,此外,反向传播时,白化操作不一定可导。

因此,提出了新的预处理层BN

2.Normalization via Mini-Batch Statistics

就像激活函数层、卷积层、全连接层、池化层一样,BN(Batch Normalization)也属于网络的一层。

数据归一化方法很简单,近似白化预处理:

就是要让batch数据具有0均值和单位方差
(每一维度减去自身均值,再除以自身标准差)。

但结果都在0-1之间,相当于只使用了激活函数中近似线性的部分,线性模型会降低模型表达能力。(会影响到本层网络A所学习到的特征的。
比如网络中间某一层学习到特征数据本身就分布在S型激活函数的两侧,你强制把它给我归一化处理、标准差也限制在了1,把数据变换成分布于s函数的中间部分,这样就相当于这一层网络所学习到的特征分布被你搞坏了)
算法关键在于作者又为BN增加了2个参数,得到前向传导过程公式,

u为一个batch的输入二维矩阵

 
m = K.mean(u, axis=-1, keepdims=True)#计算均值  
std = K.std(u, axis=-1, keepdims=True)#计算标准差  
X_normed = (u - m) / (std + self.epsilon)#归一化  
BNout = self.gamma * u_normed + self.beta#重构变换
z=g(BN(Wu_norm+b))

其实因为偏置参数b经过BN层后其实是没有用的,最后也会被均值归一化,当然BN层后面还有个β参数作为偏置项,所以b这个参数就可以不用了。 
最后为:

z=g(BN(Wu_norm))

用来保持模型的表达能力(至少可以恢复原数据)。

测试时,均值方差换成整个数据集的,不再是一个batch的。 
因此,在训练过程中我们要记录每一个Batch的均值和方差,以便训练完成之后按照下式计算整体的均值和方差:

均值计算所有batch u值的平均值;
标准偏差采用每个batch σB的无偏估计

BN before or after Activation?
作者在文章中说应该把BN放在激活函数之前,这是因为Wx+b具有更加一致和非稀疏的分布。但是也有人做实验表明放在激活函数后面效果更好。

这是实验链接,里面有很多有意思的对比实验:https://github.com/ducha-aiki/caffenet-benchmark

3-BN on CNN

通过上面的学习,我们知道BN层是对于每个神经元做归一化处理,甚至只需要对某一个神经元进行归一化,而不是对一整层网络的神经元进行归一化。既然BN是对单个神经元的运算,那么在CNN中卷积层上要怎么搞?
假如某一层卷积层有6个特征图,每个特征图的大小是100*100,这样就相当于这一层网络有6*100*100个神经元,如果采用BN,就会有6*100*100个参数γ、β,这样岂不是太恐怖了。
因此卷积层上的BN使用,其实也是使用了类似权值共享的策略,把一整张特征图当做一个神经元进行处理,计算该特征图对应数据的均值和方差进行归一化。


网络某一层输入数据可以表示为

四维矩阵(m,f,p,q),
  m为min-batch sizes,
  f为特征图个数,
  p、q分别为特征图的宽高

mini-batch size 的大小就是:m*p*q,于是对于每个特征图都只有一对可学习参数:γ、β。

像卷积层这样具有权值共享的层,x=Wu+b的均值和方差是对整张map求得的,在batch_size * channel * height * width这么大的一层中,对总共batch_size*height*width个像素点统计得到一个均值和一个标准差,共得到channel组参数。

reference
http://blog.csdn.net/app_12062011/article/details/57083447
http://blog.csdn.net/hjimce/article/details/50866313
http://blog.csdn.net/happynear/article/details/44238541
https://www.zhihu.com/question/38102762

猜你喜欢

转载自www.cnblogs.com/devilmaycry812839668/p/10634485.html