深度学习之批归一化Batch Normalization的原理和应用

目录

一、BN提出的背景意义

二、卷积神经网络(CNN)优化之BN使用

其他笔记

批量归一化的作用:

1. 环节梯度消失。

2.加速模型训练。

3.模型参数初始化可以比较随意。

4.learning rate可以稍微大一些。

BN使用的注意事项:

如果没有加BN,则学习率不能设置的太大。否则,可能导致训练出现NAN。因为训练过程中,如果遇到一个比较大的值(可能是异常值),会导致数据溢出,出现NAN。

训练过程中,如果出现NAN,应该把学习率调小,一般来说可以解决问题。

如果加了BN,包括DropOut,L1L2正则可以都不加。

全连接的时候,一般每一层都可以添加BN。

 

用RNN和LSTM的时候,千万不要添加BN,此时会有80%反向效果。因此输入数据长短不一,此时BatchSize不稳定。因为均值和方差是更具输入数据来的,所以效果不好。

 

 

 


一、BN提出的背景意义

本文的背景文献是:《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,Batch Normalization算法目前已经被大量的应用,最新的文献算法很多都会引用这个算法,进行网络训练,可见其强大之处。

随机梯度下降法是训练深度网络的首选。尽管随机梯度下降法对于训练深度网络简单高效,但是需要我们人为的去选择参数,比如学习速率、初始化参数、权重衰减系数、Drop out比例,等等。这些参数的选择对训练结果至关重要,以至于我们很多时间都浪费在这些的调参上。BN算法(Batch Normalization)其好处如下:

可以选择比较大的初始学习率,极大的提高训练速度。Batch Gradient Descent使用多个梯度的均值来更新权重,用相对少的训练次数遍历完整个训练集,也正是因为平均了多个样本的梯度,许多样本对神经网络的贡献就被其他样本平均掉了,相当于在每个epoch中,训练集的样本数被缩小了。batch中每个样本的差异性越大,这种弊端就越严重。BN首先是把所有的samples的统计分布标准化,降低了batch内不同样本的差异性,然后又允许batch内的各个samples有各自的统计分布。所以,BN的优点自然也就是允许网络使用较大的学习速率进行训练,加快网络的训练速度(减少epoch次数),提升效果。省去参数选择的问题。省去过拟合中drop out、L2正则项参数的选择问题,采用BN算法后,可以移除这两项了参数,或者可以选择更小的L2正则约束参数了,因为BN具有提高网络泛化能力的特性;为什么需要归一化?

神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低。

输入层的数据,已经人为的的归一化,后面网络每一层的输入数据分布是一直在发生变化的,前面层训练参数的更新将导致后面层输入数据分布的变化,因此必然会引起后面每一层输入数据分布的改变。而且,网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。我们把网络中间层在训练过程中,数据分布的改变称之为:"Internal Covariate Shift"。BN的提出,就是要解决在训练过程中,中间层数据分布发生改变的情况。

二、BN算法原理

1、BN层及使用位置

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

在网络的每一层输入的时候,又插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层。如果在每一层输入的时候,再加个预处理操作那该有多好啊,比如网络第三层输入数据X3(X3表示网络第三层的输入数据)把它归一化至:均值0、方差为1,然后再输入第三层计算,这样我们就可以解决前面所提到的"Internal Covariate Shift"的问题了。

关于BN的使用位置,在CNN中一般应作用与非线性激活函数之前,s型函数s(x)的自变量x是经过BN处理后的结果。因此前向传导的计算公式就应该是:

 

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

 

2、预处理操作选择

说到神经网络输入数据预处理,最好的算法莫过于白化预处理。白化其实跟PCA算法还是挺相似的。举例来说,假设训练数据是图像,由于图像中相邻像素之间具有很强的相关性,所以用于训练时输入是冗余的。白化的目的就是降低输入的冗余性。

经过白化预处理后,数据满足条件:

1.特征之间相关性较低 2.所有特征具有相同的方差

由于计算量非常大,忽略了第1个要求,仅仅使用了下面的公式进行预处理,也就是近似白化预处理:

 

3.缩放和移位

减均值除方差得到的分布是正态分布,我们能否认为正态分布就是最好或最能体现我们训练样本的特征分布呢?

非也,如果激活函数在方差为1的数据上,没有表现最好的效果,比如Sigmoid激活函数。这个函数在-1~1之间的梯度变化不大。假如某一层学习到特征数据本身就分布在S型激活函数的两侧,把它归一化处理、标准差也限制在了1,把数据变换成分布于s函数的中间部分,就没有达到非线性变换的目的,换言之,减均值除方差操作后可能会削弱网络的性能。

 

 

不光是Sigmoid激活函数,Tanh函数在零附近也变成线性

 

而Relu activation函数,则将一半的输入清零。

 

因此,必须进行一些转换才能将分布从0移开。使用缩放因子γ和移位因子β来执行此操作。

随着训练的进行,这些γ和β也通过反向传播学习以提高准确性。这就要求为每一层学习2个额外的参数来提高训练速度。

这个最终转换因此完成了批归一算法的定义。缩放和移位是算法比较关键,因为它提供了更多的灵活性。假设如果我们决定不使用BatchNorm,我们可以设置γ=σ和β= mean,从而返回原始值。

三、BN算法过程

 

采用Normalization方法网络的训练速度快到惊人啊,感觉训练速度是以前的十倍以上。

BN在深层神经网络的作用非常明显:若神经网络训练时遇到收敛速度较慢,或者“梯度爆炸”等无法训练的情况发生时都可以尝试用BN来解决。同时,常规使用情况下同样可以加入BN来加速模型训练,甚至提升模型精度。

相关参考:https://baijiahao.baidu.com/s?id=1612936475591914473&wfr=spider&for=pc

二、卷积神经网络(CNN)优化之BN使用

前言

Batch Normalization是由google提出的一种训练优化方法。参考论文:Batch Normalization Accelerating Deep Network Training by Reducing Internal Covariate Shift

个人觉得BN层的作用是加快网络学习速率,论文中提及其它的优点都是这个优点的副产品。

网上对BN解释详细的不多,大多从原理上解释,没有说出实际使用的过程,这里从what, why, how三个角度去解释BN。

What is BN

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

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

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

 

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

在正向传播的时候,通过可学习的γ与β参数求出新的分布值

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

 

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

 

Why is BN

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

 

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

 

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

 

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

 

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

 

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

 

在深度网络中,如果网络的激活输出很大,其梯度就很小,学习速率就很慢。假设每层学习梯度都小于最大值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—— BN(Batch Normalization) 原理与使用过程详解

 

这是文章卷积神经网络CNN(1)中5x5的图片通过valid卷积得到的3x3特征图(粉红色)。特征图里的值,作为BN的输入,也就是这9个数值通过BN计算并保存γ与β,通过γ与β使得输出与输入不变。假设输入的batch_size为m,那就有m*9个数值,计算这m*9个数据的γ与β并保存。正向传播过程如上述,对于反向传播就是根据求得的γ与β计算梯度。
这里需要着重说明2个细节:
1.网络训练中以batch_size为最小单位不断迭代,很显然,新的batch_size进入网络,机会有新的γ与β,因此,在BN层中,有总图片数/batch_size组γ与β被保存下来。
2.图像卷积的过程中,通常是使用多个卷积核,得到多张特征图,对于多个的卷积核需要保存多个的γ与β。

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

 

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

 

输入:待进入激活函数的变量
输出:
1.对于K维的输入,假设每一维包含m个变量,所以需要K个循环。每个循环中按照上面所介绍的方法计算γ与β。这里的K维,在卷积网络中可以看作是卷积核个数,如网络中第n层有64个卷积核,就需要计算64次。
需要注意,在正向传播时,会使用γ与β使得BN层输出与输入一样。
2.在反向传播时利用γ与β求得梯度从而改变训练权值(变量)。
3.通过不断迭代直到训练结束,求得关于不同层的γ与β。如网络有n个BN层,每层根据batch_size决定有多少个变量,设定为m,这里的mini-batcherB指的是特征图大小*batch_size,即m=特征图大小*batch_size,因此,对于batch_size为1,这里的m就是每层特征图的大小。
4.不断遍历训练集中的图片,取出每个batch_size中的γ与β,最后统计每层BN的γ与β各自的和除以图片数量得到平均直,并对其做无偏估计直作为每一层的E[x]与Var[x]。
5.在预测的正向传播时,对测试数据求取γ与β,并使用该层的E[x]与Var[x],通过图中11:所表示的公式计算BN层输出。
注意,在预测时,BN层的输出已经被改变,所以BN层在预测的作用体现在此处

至此,BN层的原理与使用过程就解释完毕,给出的解释都是本人觉得值得注意或这不容易了解的部分,如有錯漏,请指正。

相关参考:
https://blog.csdn.net/Fate_fjh/article/details/53375881

其他笔记

相关参考:

CNN中batch normalization应该放在什么位置?

https://www.zhihu.com/question/45270958
Batch Normalization 学习笔记

https://blog.csdn.net/hjimce/article/details/50866313

WHY Batch Normalization ?

前面介绍的都是数据预处理的方法,但是在 DNN 中,除了面对量纲、GD 速度慢、Covariate Shift 这些 ML 共有的问题,还有一个独特的问题,就是 Internal Covariate Shift。

1. Internal Covariate Shift 是作者在 Batch Normalization 论文中,仿照 Covariate Shift 提出的概念。具体来说,对 DNN 某一层,随着 GD 训练的过程中参数的改变,该层的输出数据的分布可能会改变;此时,对于下一层,相当于输入数据的分布改变了,这就类似于 Covariate Shift。这种输入数据分布的改变,可能会使 DNN 的难以学习到好的参数,从而影响 DNN 的效果

2. 同时,DNN 为了补偿输入数据分布改变带来的损失,需要更多的时间来调整参数,这可能会使 GD 的速度下降

3. 同时,DNN 还有 Gradient Vanish 的问题(参考当我们在谈论 Deep Learning:DNN 与它的参数们(壹))。当输入分布改变,可能使本层的 Activation Function 饱和,进而导致 Gradient Vanish。而随着深度的增加,较深的层会受到前面层参数变化的影响叠加,它输入分布的改变可能会更明显

理解 Internal Covariate Shift:对 DNN 每一层,经过了该层的变换,其输出数据与输入数据的分布一般是不会一样的,这种分布的差异随着深度的增加会越发明显,但是它们描述的样本与标记仍然是一样的。

BN 步骤

近年来深度学习捷报连连、声名鹊起,随机梯度下架成了训练深度网络的主流方法。尽管随机梯度下降法对于训练深度网络简单高效,但是它有个毛病,就是需要我们人为的去选择参数,比如学习率、参数初始化、权重衰减系数、Drop out比例等。这些参数的选择对训练结果至关重要,以至于我们很多时间都浪费在这些的调参上。那么学完这篇文献之后,你可以不需要那么刻意的慢慢调整参数。

BN算法(Batch Normalization)其强大之处如下:

(1)你可以选择比较大的初始学习率,让你的训练速度飙涨。以前还需要慢慢调整学习率,甚至在网络训练到一半的时候,还需要想着学习率进一步调小的比例选择多少比较合适,现在我们可以采用初始很大的学习率,然后学习率的衰减速度也很大,因为这个算法收敛很快。当然这个算法即使你选择了较小的学习率,也比以前的收敛速度快,因为它具有快速训练收敛的特性;

(2)你再也不用去理会过拟合中drop out、L2正则项参数的选择问题,采用BN算法后,你可以移除这两项了参数,或者可以选择更小的L2正则约束参数了,因为BN具有提高网络泛化能力的特性;

(3)再也不需要使用使用局部响应归一化层了(局部响应归一化是Alexnet网络用到的方法,搞视觉的估计比较熟悉),因为BN本身就是一个归一化网络层;

(4)可以把训练数据彻底打乱(防止每批训练的时候,某一个样本都经常被挑选到,文献说这个可以提高1%的精度,这句话我也是百思不得其解啊)。

开始讲解算法前,先来思考一个问题:我们知道在神经网络训练开始前,都要对输入数据做一个归一化处理,那么具体为什么需要归一化呢?归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。

对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。

我们知道网络一旦train起来,那么参数就要发生更新,除了输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的,因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化。以网络第二层为例:网络的第二层输入,是由第一层的参数和input计算得到的,而第一层的参数在整个训练过程中一直在变化,因此必然会引起后面每一层输入数据分布的改变。我们把网络中间层在训练过程中,数据分布的改变称之为:“Internal  Covariate Shift”。Paper所提出的算法,就是要解决在训练过程中,中间层数据分布发生改变的情况,于是就有了Batch  Normalization,这个牛逼算法的诞生。

 

2、源码实现

            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#重构变换

说明:下面的m是Batchsize的大小

 

四、Batch Normalization在CNN中的使用

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


卷积神经网络经过卷积后得到的是一系列的特征图,如果min-batch sizes为m,那么网络某一层输入数据可以表示为四维矩阵(m,f,p,q),m为min-batch sizes,f为特征图个数,p、q分别为特征图的宽高。在cnn中我们可以把每个特征图看成是一个特征处理(一个神经元),因此在使用Batch Normalization,mini-batch size 的大小就是:m*p*q,于是对于每个特征图都只有一对可学习参数:γ、β。说白了吧,这就是相当于求取所有样本所对应的一个特征图的所有神经元的平均值、方差,然后对这个特征图神经元做归一化。下面是来自于keras卷积层的BN实现一小段主要源码:
 

           input_shape = self.input_shape
            reduction_axes = list(range(len(input_shape)))
            del reduction_axes[self.axis]
            broadcast_shape = [1] * len(input_shape)
            broadcast_shape[self.axis] = input_shape[self.axis]
            if train:
                m = K.mean(X, axis=reduction_axes)
                brodcast_m = K.reshape(m, broadcast_shape)
                std = K.mean(K.square(X - brodcast_m) + self.epsilon, axis=reduction_axes)
                std = K.sqrt(std)
                brodcast_std = K.reshape(std, broadcast_shape)
                mean_update = self.momentum * self.running_mean + (1-self.momentum) * m
                std_update = self.momentum * self.running_std + (1-self.momentum) * std
                self.updates = [(self.running_mean, mean_update),
                                (self.running_std, std_update)]
                X_normed = (X - brodcast_m) / (brodcast_std + self.epsilon)
            else:
                brodcast_m = K.reshape(self.running_mean, broadcast_shape)
                brodcast_std = K.reshape(self.running_std, broadcast_shape)
                X_normed = ((X - brodcast_m) /
                            (brodcast_std + self.epsilon))
            out = K.reshape(self.gamma, broadcast_shape) * X_normed + K.reshape(self.beta, broadcast_shape)

https://stackoverflow.com/questions/38553927/batch-normalization-in-convolutional-neural-network 其实就是卷积层一共有C个滤波器,输出就是[B, C, H, W]这个维度的tensor,既然只有C个滤波器,那就干脆只有C个BN,每个BN去作用在每个滤波器上。因此就是对每个C(i = range(0,C)),求B*W*H个特征的均值方差,所以最后均值和方差的个数就各有C个。

  • 13
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值