美文网首页Machine Learning & Recommendation & NLP & DL
来,让你get到 Batch Normalization 的精髓

来,让你get到 Batch Normalization 的精髓

作者: CW不要无聊的风格 | 来源:发表于2020-01-25 17:01 被阅读0次

    Date: 2020/01/25

    Author: CW

    前言:

    如果你希望对Batch Normalization有更深入的理解,还请耐心阅读本文。CW会一步步为大家解析Batch Normalization,由浅至深,并且引出在具体使用中的一些关键点,供各位网友参考学习,如有不当之处,欢迎大家交流与指正,谢谢!


    Outline

    i). Why:为什么需要 Batch Normalization?

    ii). What:Batch Normalization 是什么东东?

    iii). How:Batch Normalization 干了什么?具体是怎么做的?

    iv). Key Point:关于 Batch Normalization,这些细节你都了解吗?

    v). Summary:Batch Normalization 起到了什么作用?


    Why:为什么需要 Batch Normalization?

    Original From:http://gradientscience.org/batchnorm

    上图表示的是神经网络每层的权重和激活函数,每层权重的更新其实是在假定其输入不变的情况下根据loss结合反向传播过程来进行的。但实际情况是,每层的输入是前面层的输出,而前面层的权重更新会导致它的输出变化,即当前层的输入数据就会跟着变化了,本来上次权重的更新对输入适应得不错了,但是由于输入分布又变化了,于是权重又得继续调整,而根据反向传播过程,前面层的权重也会更新,这样当前层的输入分布又再次变化,于是当前层的权重在下次更新时又需根据新的分布重新调整...你们说累不累?

    在此,顺便引入一个概念——Internal Covariate Shift,即内部协转移,它是指深层网络中由于参数变化而引起的内部数据分布变化,这会带来以下问题:

    i). 深层的网络需不断调整来适应浅层网络引起的数据分布变化,从而影响模型收敛;

    ii). 由于激活函数的存在,模型容易在训练过程中陷入梯度饱和区域。

    那么,如何减缓/规避这样的问题呢?

    以往机器学习的传统做法可以使用如PCA/ZCA这样的白化操作,但如果用在深度神经网络中,计算成本就太高了,伤不起!另外,反向传播时,白化操作还不一定可导。同时,由于这类操作改变了原数据分布,因而本身数据的表达能力被改变了,低层网络学习到的参数信息会被白化操作丢弃掉。

    于是,why batch normalization? cuz' we need it!

    Batch Normalization 就破蛋而出了。


    What:Batch Normalization 是什么东东?

    通过上一节我们知道,随着网络深度加深,输入分布会逐渐发生偏移和变动,于是激活函数的输入分布很容易处于线性饱和区域(即这时激活函数的输出值在向其取值区间的上下限两端靠近),从而后向传播浅层网络的梯度逐渐消失,进而导致模型收敛变慢。

    Sigmoid函数曲线

    Batch Normalization,即“批次归一化”,通常简称BatchNormBN,目前广泛作为神经网络模型中的一个网络层使用。顾名思义,它是基于一个个批次(相对的是全量数据)的数据来进行归一化操作的。它是这样的一种手段——把网络中每层各神经元的输入分布强行拉回到均值为0方差为1的分布(通常是正态/均匀分布),从而使激活函数的输入落在非线性饱和区域,进而避免梯度消失,最终使得模型可持续学习至收敛。

    BN

    HOW:Batch Normalization 干了什么?具体是怎么做的?

    总的来说,BN干以下两件事情:

    i). Normalization:即对每个批次的数据进行归一化操作,使其均值为0方差为1;

    ii). (可选)Scale & Shift:设置两个可学习参数\gamma \beta ,对归一化后的每个批次数据进行缩放和平移,使其变为另一种分布,均值为\beta ,方差为\gamma ^2

    BN操作,其中是一个极小值,如,用于防止分母为0;以上和的下标B代表是基于批次(Batch)进行计算的;下表i代表当前批次的第i个神经元的输入,即通常所说的第i个通道(在计计算机视觉中,就是第i个feature map)

    通过以上,你是否发现以下小秘密:

    1、\mu \sigma 为当前批次的统计量,不可学习

    2、\gamma \beta 为待学习的缩放(scale)和平移(shift)参数,分别用于控制方差和均值,即无论x_{i}原本的均值和方差是多少,通过BN后均值和方差将分别变为\gamma \beta (若感到疑惑,动动小手自己推一推哈);

    3、BN层中,x_{i}x_{j}(i\neq j)之间不存在信息交流。注意哦,这代表它们的\mu、 \sigma、 \gamma、 \beta 是分别计算和学习的

    以上就是BN的具体操作了,这部分会发生在前向反馈过程中,那么你们不免会问,后向传播呢?客观稍坐片刻,CW这就为您上菜!

    反向传播过程涉及的偏导

    根据反向传播的顺序,首先求取损失loss对BN层输出y的偏导,然后是对可学习参数\gamma 、\beta 的偏导,用于对参数进行更新。接着,继续回传上一层网络,于是需要求对该BN层输入x的偏导,从而用到对\mu 、\sigma ^2以及\hat{x} 的偏导,最终根据链式法则求它们对x的偏导。

    BN的前向反馈&反向传播

    Key Point:关于 Batch Normalization,这些细节你都了解吗?

    i). 预测阶段如何使用BN?

    我们知道,在训练过程中,\mu 、\sigma 、\gamma 和\beta 都是变化的,而在预测阶段,所有参数的取值都应该是固定的,那么这时,我们该如何使用BN?

    对于\gamma \beta ,随着训练结束,两者最终收敛,于是使用训练结束时的值即可。

    对于\mu \sigma ,在训练阶段时它们是当前mini-batch的统计量,而在预测阶段,输入数据可能只有1条,那么这时\mu \sigma 该如何取值呢?可以采用训练至收敛的最后几批mini-batch的 \mu \sigma ^2的期望作为这时的\mu和\sigma ^2

    预测阶段的均值和方差,x表示需要预测的输入数据,m表示训练过程最后几批mini-batch的大小,其中采用的是无偏估计

    从而,BN操作会时数据进行如下转换:

    预测阶段的BN操作:normalization, then scale & shift

    ii). 配合卷积层如何使用BN?

    我们知道,在卷积层中一个kernel(卷积核)对应一个feature map(特征图),为了保持卷积的性质与效果,因此处于同一feature map中的不同元素应当被施与相同的BN操作(包括归一化和缩放平移)。这样,同一feature map中的元素就应该共享一对\gamma和\beta 参数。于是,若卷积层有n个kernel,那么其后的BN层将有n对\gamma和\beta参数

    总的来说,可以将BN理解为基于通道来操作的:

    对于\gamma和\beta ,处于同一通道的数据它们的这两个值是相同的;

    对于\mu和\sigma ^2,处于同一通道并且是同一mini-batch的数据它们的这两个值是相同的。

    For convolutional layers, we additionally want the normalization to obey the convolutional property – so that different elements of the same feature map, at different locations, are normalized in the same way. To achieve this, we jointly normalize all the activations in a mini-batch, over all locations.

    so for a mini-batch of size m and feature maps of size p × q, we use the effective mini-batch of size m′= |B| = m · pq. We learn a pair of parameters γ(k) and β(k) per feature map, rather than per activation.

    —— Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

    iii). 归一化之后为何要缩放和平移?scale & shift存在的必要性?

    首先说明一点,可以不进行缩放和平移(在代码中也可以通过参数进行设置),但网络的表达能力会下降。

    由开篇的论述我们可知,深层神经网络中,每层网络的权重和输入分布会通过前向和反向过程而相互协调,那么强制把数据归一化到均值为0方差为1的分布并不一定是最好的选择。使用可学习的参数\gamma和\beta ,是为了让模型通过训练来学习什么样的分布才是合适的,利于输入分布和权重的相互协调,同时避免数据因这种统一均为0方差为1的“强硬”归一化而丢失过多原始信息,增强了网络的表达能力。

    特别地,\gamma =1且\beta =0的情况下等价于仅进行归一化(normalization)操作,不进行缩放和平移;而\gamma=\sigma \beta=\mu的情况下等价于没有使用BN操作(包括归一化和缩放平移)。

    iv). 為何说BN对网络中的参数不那么敏感,具有更强的鲁棒性(即学习过程更加稳定),并且可以放心使用大学习率进行训练从而加速收敛?

    举一例说明更形象生动:

    假设现在对网络中某层参数w进行缩放,使其变为aw,其中a为缩放系数,x为当前层的输入。那么,在没有进行缩放时,该层输出将是wx,记均值和方差将分别为\mu_{1}和\sigma _{1}^2;缩放后,该层输出将是(aw)x,记此时均值和方差分别为\mu_{2}和\sigma_{2}^2,则有:

    \mu_{2}=a\mu_{1}\sigma_{2}^2=a^2\sigma_{1}^2

    忽略\epsilon ,记缩放前后的BN操作分别为BN[wx]和BN[(aw)x],则有:

    BN[(aw)x] = \gamma\frac{(aw)x-\mu_{2}}{\sqrt{\sigma_{2}^2}} + \beta

                    = \gamma \frac{a(wx-\mu_{1})}{\sqrt{(a\sigma_{1})^2}} + \beta

                    = \gamma \frac{wx-\mu_{1}}{\sqrt{\sigma_{1}^2}}+ \beta

                    = BN[wx]

    咦!系数缩放之后对于BN层操作来说居然没有变化!这说明即使前面的网络层权重系数较之前进行了缩放,但是在经过BN层之后,数据的分布依旧稳定在一定范围内。

    同理,对于梯度,不难计算出以下关系:

    \frac{dBN[(aw)x]}{dx} = \frac{dBN[wx]}{dx}\frac{dBN[(aw)x]}{d(aw)} = \frac{1}{a} \times \frac{dBN[wx]}{dw}

    于是,我们知道,对于输入数据x在BN层的梯度计算没有发生变化,同时,缩放尺寸与权重的梯度更新成反比,可使得其梯度更新更稳定。

    综上,BN抑制了参数微小变化随着网络加深而被放大的情况,从而允许设置较大学习率,同时不易造成模型震荡或不收敛,较大学习率训练意味着可以加速收敛。

    v). 为何BN会具有一定的正则化效果,甚至可以不使用Dropout?

    要知道,在BN中我们使用的是mini-batch的均值与方差作为对整体训练样本均值与方差的估计,尽管每个mini-batch中的数据都是从总体样本中抽样得到,但不同mini-batch的均值与方差会有所不同(mini-batch size越小差异可能越大),这相当于在网络的学习过程中增加了随机噪音,与Dropout通过关闭神经元带来噪音的效果类似,因此在一定程度上起到了正则化的效果。

    另外,BN原paper的作者也通过实验证明网络加入BN后丢弃Dropout,模型也同样具有很好的泛化效果。

    vi). BN应该放在激活层(通常是ReLU)前面还是后面?

    原paper作者建议将BN层放置在ReLU前,因为ReLU激活函数的输出非负,不能近似为高斯分布。

    The goal of Batch Normalization is to achieve a stable distribution of activation values throughout training, and in our experiments we apply it before the nonlinearity since that is where matching the first and second moments is more likely to result in a stable distribution.

    —— Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

    但是,也有实验表明放在ReLU后效果更好,这相当于对下一层的输入作归一化。

    因此,BN应该放在激活层前面还是后面,以及与其他变量如初始化方法等如何组合,目前没有同一定论,通常凭直觉和经验性指导,具体效果还是得实验结果说了算。

    vii). 为啥使用了BN,就可以不对上一层的网络设置bias(对于卷积层conv,就是bias=0)?

    一句话:设不设置一个样,再见。

    开个玩笑,原因很简单,因为BN的归一化操作会将这个偏置分量移除掉:

    (x + b) - E(x + b) = x +b - [E(x) + b] = x - E(x)

    这么聪明的你肯定早就知道了,还请不要鄙视我以上这波操作...


    Summary:Batch Normalization 起到了什么作用?

    (1)使数据分布处于激活函数的非线性饱和区域,从而避免梯度消失;

    (2)如在归一化的同时进行了缩放和平移,则将数据分布的均值与方差从浅层网络的权重中解耦,只需调整\gamma和\beta 两个参数,使得数据分布和网络权重的相互协调变得更加容易;

    (3)对网络权重初始化不再那么敏感,对参数、激活函数具有更强的鲁棒性,一定程度上降低了调参和训练的复杂度;

    (4)允许设置较大学习率进行训练,加速模型收敛;

    (5)训练过程中的方差与均值基于每个mini-batch进行统计,相当于引入随机噪声,一定程度上起到了正则化效果。


    #彩蛋

    耐心的你居然看到了这里,我内心真的十分感动!

    品完这篇文,你对BN是否有了新的认识呢(大牛的话就默默别出声吧哈哈哈)?那么,你是否有思考过,若使用GPU多卡训练,BN会是怎样的一波操作?

    我们知道,BN的统计量是基于batch来计算的,在GPU多卡的情况下,一个batch会被均分成一个个mini-batch到不同卡上,每张卡会基于它所拿到的mini-batch进行计算。当batch size较大时,可能不会有什么不妥,但是对于像语义分割等之类的稠密估计(Dense Prediction)问题,batch size通常都很小,那么每张卡计算得到的统计量可能与整体数据样本具有较大差异,这...不就尴尬了吗!?

    嘿嘿!不急不急,别方,先把这篇文中的内容啃下去好好消化,下回CW再为您上菜!


    参考:

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

    https://blog.csdn.net/zhikangfu/article/details/53391840

    https://www.cnblogs.com/makefile/p/batch-norm.html?utm_source=debugrun&utm_medium=referral

    https://www.cnblogs.com/shine-lee/p/11989612.html#batch-normalization%E7%9A%84%E9%A2%84%E6%B5%8B%E9%98%B6%E6%AE%B5

    相关文章

      网友评论

        本文标题:来,让你get到 Batch Normalization 的精髓

        本文链接:https://www.haomeiwen.com/subject/tvcpzctx.html