batch normalization是深度学习中常用的一种方操作,在深层网络的优化中,其可以说是一种标配,因为batch normalization带来的效果往往是显著的。
方式
batch normalization是针对一个batch的样本进行的操作。如果对于某一层,我们要对其进行batch normalization操作,那么实际上就是对该层的每个单元分别进行Z-score的计算。因为一个batch有多个样本,对于每个样本,都可以计算得到一个该单元对应的前向反馈值,然后对多个这样的值进行标准化(计算Z-score),就得到了该单元所谓的批标准化后的值,即下式中的。
经过BN操作后,还进行了一个rescale操作,即乘以可学习的参数,再加上可学习参数
,得到
,最后再经过该层的激活函数激活。i代表该层第i个单元。
原理
1. 通过缓解解决层之间的依赖性,从而减少梯度消失和爆炸的出现概率,从而缓解学习率难题
深度学习优化算法基本都是梯度下降法,并通过在负梯度方向步进一定长度来更新参数。例如,假设计算出的梯度为g,那么在负梯度方向步进一单位长度,损失函数值的近似下降为。假设学习率为
,则损失函数值的近似下降为
。当然,这里只是一种近似估计,只有当学习率足够小时,也即参数更新足够小时,这个近似才会更准确。那么什么才是足够小,这个是相对的,此时,如果选取一个固定的学习率,那么就是有问题的。
之所以是近似,是因为我们只使用了一阶导数进行近似,这个根据泰勒公式就可以理解,剩下的二阶以及以上的影响我们都没有考虑。当然,假如二阶以及以上的项都比较小,那么可以忽略不计,但是问题在于,在深度网络中,二阶以及以上的项很容易被放大。比如对于relu激活函数,会涉及多个单元激活后的值的连乘,那么一旦上式中的A值大于1,连乘之后会指数倍增加,这就导致损失函数真正变化的值相对于切面(梯度更新后的近似值所在平面)偏离过大,这意味损失函数相当崎岖,因此仅仅只用一阶导数的梯度来更新参数是不太恰当的,因为一阶已经不能较好的近似,容易引起振荡或者损失函数值下降缓慢,从而使得学习很慢,甚至停滞不前。这个一方面可以通过学习率自适应算法,但是现有的自适应算法也只是考虑到二阶情况,而且计算量也大,实际应用效果也不太好;另一方面就是直接避免这种情况本身的出现,这就是BN采取的方式。
BN通过在每层进行标准化,将值约束在了均值为0方差为1的分布范围内,因而单元激活后的值都比较小,这使得连乘效应不太明显;另一方面,每层的标准化显著降低了层与层之间的联系,降低了层之间值的协调效应(上一层具有较大值,下层也容易有较大值),增加了层之间的独立性,从而也会降低参数更新的噪音,让参数更新更加平稳,每层可以更好的学习自身层的性质,少受上层影响。
对于sigmoid激活函数,因为限制了输出值在0-1范围内,看起来似乎不会受连乘效应影响,实则不然,因为sigmoid激活会造成梯度消失问题,实际上,上文描述的问题和梯度消失梯度爆炸问题本质是一样的。在BN操作下,会将激活前的大部分值标准化到sigmoid的近线性部分,从而可以缓解梯度消失问题,这也是BN带来的另外一个益处。
因此,BN操作实际上可以较好的解决深层网络中,relu下可能引起的梯度爆炸的问题,部分解决sigmoid下梯度消失的问题;或者说可以较好的解决层与层之间参数协同更新带来的问题(实际上就是更容易引起梯度消失和爆炸),让层与层之间更加独立,激活前的值也更小。
2. 调整层分布,缓解分布漂移,提高学习效率
层的单元值即受样本影响,也受上层值的影响,从而会使得层不同单元之间的分布容易发生变化,这会使得学习效率不高,就像我们希望测试集和训练集的分布一样,不然发生变化就需要重新学习,因此,对于层不同单元分布容易发生改变这件事,也会使得学习不易,从而影响学习效率,我们希望可以将分布控制稳定,从而使得该层始终在某个分布下学习,这会使得学习更有效。对于BN,我们实际上并没有控制同层单元内分布的稳定,但是至少我们将每个单元的值控制在了均值为0方差为1的分布之内,这也会使得层内不同单元的分布在某个范围内波动,相当于局部控制了单元分布,缓解了原先分布容易变化的问题,从而使得学习更加高效。
3. 类似对原始输入不同特征标准化使得对不同特征学习更高效,对层内单元的标准化也有类似作用
Rescale
最后,如文章开头公式展示,我们还对标准化后的值加入了可学习的参数和
对其进行rescale。这是因为BN操作的代价是降低了网络的表达能力,因为某层进行BN操作之后,我们强制的改变了单元的值,这会丢失部分的前面的层学到的信息,但是加入了参数
和
之后,由于其是可学习的,因此网络会根据优化目标来自己学习,从而调整单元的值,也即调整单元在批样本里的均值方差,可以调到任意值,具体的值以优化目标而定,因此,加入了参数
和
,相当于提供了多于BN操作之前的值路径,不仅不会丧失网络的表达能力,反而还增加了网络表达能力。有人可能会觉得,BN之后再rescale,感觉是多此一举,实际上不然,原因是这里的参数
和
是可训练的、可学习的,所以rescale后的值不一定是原先BN之前的值(当然也可以是,取决于网络自己的优化选择),而且是在BN的基础上进一步的优化选择,相当于保留了BN带来的益处的同时,还不会丧失网络的表达能力,这点需要理解。