【转载】BN(Batch Normalization) 原理与使用过程详解

目录

 

1. 卷积神经网络CNN(2)—— BN(Batch Normalization) 原理与使用过程详解

2. 神经网络之BN层

背景

BN

使用

BN在CNN上的使用。

 

https://blog.csdn.net/Fate_fjh/article/details/53375881

https://www.jianshu.com/p/fcc056c1c200

 


1. 卷积神经网络CNN(2)—— BN(Batch Normalization) 原理与使用过程详解

Fate_fjh 2016-11-28 11:56:32  82085  已收藏 178
分类专栏: 深度学习 文章标签: cnn 神经网络 BN
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Fate_fjh/article/details/53375881
收起
前言
Batch Normalization是由google提出的一种训练优化方法。参考论文:Batch Normalization Accelerating Deep Network Training by Reducing Internal Covariate Shift
网上对BN解释详细的不多,大多从原理上解释,没有说出实际使用的过程,这里从what, why, how三个角度去解释BN。

What is BN
Normalization是数据标准化(归一化,规范化),Batch 可以理解为批量,加起来就是批量标准化。
先说Batch是怎么确定的。在CNN中,Batch就是训练网络所设定的图片数量batch_size。

Normalization过程,引用论文中的解释:

输入:输入数据x1…xm(这些数据是准备进入激活函数的数据)
计算过程中可以看到,
1.求数据均值
2.求数据方差
3.数据进行标准化(个人认为称作正态化也可以)
4.训练参数γ,β
5.输出y通过γ与β的线性变换得到新的值
在正向传播的时候,通过可学习的γ与β参数求出新的分布值

在反向传播的时候,通过链式求导方式,求出γ与β以及相关权值


Why is BN
解决的问题是梯度消失与梯度爆炸。
关于梯度消失,以sigmoid函数为例子,sigmoid函数使得输出在[0,1]之间。

事实上x到了一定大小,经过sigmoid函数的输出范围就很小了,参考下图

如果输入很大,其对应的斜率就很小,我们知道,其斜率(梯度)在反向传播中是权值学习速率。所以就会出现如下的问题,

在深度网络中,如果网络的激活输出很大,其梯度就很小,学习速率就很慢。假设每层学习梯度都小于最大值0.25,网络有n层,因为链式求导的原因,第一层的梯度小于0.25的n次方,所以学习速率就慢,对于最后一层只需对自身求导1次,梯度就大,学习速率就快。
这会造成的影响是在一个很大的深度网络中,浅层基本不学习,权值变化小,后面几层一直在学习,结果就是,后面几层基本可以表示整个网络,失去了深度的意义。

关于梯度爆炸,根据链式求导法,
第一层偏移量的梯度=激活层斜率1x权值1x激活层斜率2x…激活层斜率(n-1)x权值(n-1)x激活层斜率n
假如激活层斜率均为最大值0.25,所有层的权值为100,这样梯度就会指数增加。

How to use BN
先解释一下对于图片卷积是如何使用BN层。

这是文章卷积神经网络CNN(1)中5x5的图片通过valid卷积得到的3x3特征图(粉红色)。这里假设通道数为1,batch为4,即大小为[4,1,3,3] (n,c,h,w)。特征图里的值,作为BN的输入,这里简化输出只有一个channel,也就是这一个4x3x3个数值通过BN计算并保存均值与方差,并通过当前均值与方差计算归一化的值,最后根据γ,β以及归一化得值计算BN层输出。

这里需要着重说明的细节:
网络训练中以batch_size为最小单位不断迭代,很显然,新的batch_size进入网络,由于每一次的batch有差异,实际是通过变量,以及滑动平均来记录均值与方差。训练完成后,推断阶段时通过γ, β,以及记录的均值与方差计算bn层输出。

结合论文中给出的使用过程进行解释

输入:待进入激活函数的变量
输出:
1.对于K个激活函数前的输入,所以需要K个循环。每个循环中按照上面所介绍的方法计算均值与方差。通过γ,β与输入x的变换求出BN层输出。
2.在反向传播时利用γ与β求得梯度从而改变训练权值(变量)。
3.通过不断迭代直到训练结束,得到γ与β,以及记录的均值方差。
4.在预测的正向传播时,使用训练时最后得到的γ与β,以及均值与方差的无偏估计,通过图中11:所表示的公式计算BN层输出。
至此,BN层的原理与使用过程就解释完毕,给出的解释都是本人觉得值得注意或这不容易了解的部分,如有錯漏,请指正。
BN层正向传播之前存在勘误,博文已经过修改
————————————————
版权声明:本文为CSDN博主「Fate_fjh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Fate_fjh/article/details/53375881

 

 

2. 神经网络之BN层

背景

BN,全称Batch Normalization,是2015年提出的一种方法,在进行深度网络训练时,大都会采取这种算法。
原文链接:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

尽管梯度下降法训练神经网络很简单高效,但是需要人为地去选择参数,比如学习率,参数初始化,权重衰减系数,Dropout比例等,而且这些参数的选择对于训练结果至关重要,以至于我们很多时间都浪费到这些调参上。BN算法的强大之处在下面几个方面:

  1. 可以选择较大的学习率,使得训练速度增长很快,具有快速收敛性。
  2. 可以不去理会Dropout,L2正则项参数的选择,如果选择使用BN,甚至可以去掉这两项。
  3. 去掉局部响应归一化层。(AlexNet中使用的方法,BN层出来之后这个就不再用了)
  4. 可以把训练数据打乱,防止每批训练的时候,某一个样本被经常挑选到。(不是很理解啊)

首先来说归一化的问题,神经网络训练开始前,都要对数据做一个归一化处理,归一化有很多好处,原因是网络学习的过程的本质就是学习数据分布,一旦训练数据和测试数据的分布不同,那么网络的泛化能力就会大大降低,另外一方面,每一批次的数据分布如果不相同的话,那么网络就要在每次迭代的时候都去适应不同的分布,这样会大大降低网络的训练速度,这也就是为什么要对数据做一个归一化预处理的原因。另外对图片进行归一化处理还可以处理光照,对比度等影响。
另外,为什么要进行归一化还有一些原因,可以参考这里
网络一旦训练起来,参数就要发生更新,出了输入层的数据外,其它层的数据分布是一直发生变化的,因为在训练的时候,网络参数的变化就会导致后面输入数据的分布变化,比如第二层输入,是由输入数据和第一层参数得到的,而第一层的参数随着训练一直变化,势必会引起第二层输入分布的改变,把这种改变称之为:Internal Covariate Shift,BN就是为了解决这个问题的。

BN

 

 

和卷积层,激活层,全连接层一样,BN层也是属于网络中的一层。我们前面提到了,前面的层引起了数据分布的变化,这时候可能有一种思路是说:在每一层输入的时候,在加一个预处理多好。比如归一化到均值为0,方差为1,然后再送入输入进行学习。基本思路是这样的,然而实际上没有这么简单,如果我们只是使用简单的归一化方式:

 

 

对某一层的输入数据做归一化,然后送入网络的下一层,这样是会影响到本层网络所学习的特征的,比如网络中学习到的数据本来大部分分布在0的右边,经过RELU激活函数以后大部分会被激活,如果直接强制归一化,那么就会有大多数的数据无法激活了,这样学习到的特征不就被破坏掉了么?论文中对上面的方法做了一些改进:变换重构,引入了可以学习的参数,这就是算法的关键之处:这两个希腊字母就是要学习的。

 

每一个神经元x_k都会有这样的一对参数,当:

 

 

这样的时候可以恢复出原始的某一层学习到的特征的,因此我们引入这个可以学习的参数使得我们的网络可以恢复出原始网络所要学习的特征分布,最后BN层的前向传导公式为:

 

上面公式中的m指的是mini-batch size。也就是每一个batch来做一个这样的BN。代码对应也是四句话。

 

m = K.mean(X, axis=-1, keepdims=True)        #计算均值  
std = K.std(X, axis=-1, keepdims=True)           #计算标准差  
X_normed = (X - m) / (std + self.epsilon)         #归一化  
out = self.gamma * X_normed + self.beta           #重构变换  

上面的x是一个二维矩阵,对于源码的实现就是上面几行了。

使用

一旦网络训练结束,就没有了batch这个概念了,测试阶段的时候我们一般只输入一个样本来看一下预测结果。因此测试样本前向传导的时候,上面式子里的均值和标准差从哪里来?其实网络一旦训练完毕,参数都是固定的,这个时候即便是训练数据进来一个batch,BN层计算的均值和标准差都是基本不变的(网络趋于稳定),我们可以采用这些数值作为测试样本所需要的均值和标准差,于是最后测试阶段的均值和标准差为:

 

上面简单理解就是:对于均值来说直接计算所有batch u值的平均值;然后对于标准偏差采用每个batch σB的无偏估计。最后测试阶段,BN的使用公式就是

 

BN可以用于一个神经网络的任何一个神经元上,文献中主要是把BN变换放在激活函数层的前面,所以前向传导的计算公式应该是:z=g(BN(Wu+b)),因为偏置参数经过BN层其实是不起作用的,因为也会被均值归一化(平移),所以这个参数就可以不要了,可以写成:z=g(BN(Wu))

BN在CNN上的使用。

上面所说的是BN对于每一个神经元都做处理,对于卷积神经网络来说呢?比如某一层卷积层的维度是:1001006,如果对每一个神经元都进行BN的话,那就需要600万*2的参数,这是相当恐怖的,所以其实卷积神经网络使用BN的时候,也做了权重共享的策略,把一张特征图当做一个神经元来处理。
比如某层的特征维度是[m,f,p,q],分别是batch_num:m,维度: f,特征尺寸p,q。CNN中可把每个特征图看成是一个特征处理(神经元),因此在使用BN的时候,Mini-batch size的大小就是mpq,对于每一个特征图只有一对科学系的参数。说白了,就是相当于求所有样本(batch_num:m个)所对应的的一个特征图的所有神经元的平均值和方差,然后对这一个神经元做归一化,假设特征维度只有一维的话,就相当于一个batch的所有图片像素的均值和方差来对每一张图片来做归一化,也是容易理解的。



作者:和蔼的zhxing
链接:https://www.jianshu.com/p/fcc056c1c200
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(机器学习)