type
status
password
date
slug
summary
category
URL
tags
icon
背景:Internal Covariate Shift
深层神经网络在做非线性变换前的激活输入值(就是那个 , 是输入。)随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近(对于Sigmoid函数来说,意味着激活输入值 是大的负值或正值),所以这导致后向传播时低层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因。
Batch Normalization
原理
在原paper中,BN被建议插入在(每个)神经元的激活层前面。其操作可以分成2步,
- Standardization:首先对 个 进行 Standardization,得到 zero mean unit variance的分布 。
- scale and shift:然后再对 进行scale and shift,通过新的权重 、偏差 ,缩放并平移到新的分布 。
我们知道BN层是对于每个神经元做归一化处理,也就是在每个神经元的激活函数前进行归一化。
正向传播
- Input: ,为m个样本组成的一个batch数据。
- Output: 需要学习到的是 和 ,在框架中一般表述成 weight 和 bias。
- 更新过程:
//得到batch中的统计特性之一:均值
//得到batch中的另一个统计特性:方差
//规范化,其中是一个很小的数,防止计算出现数值问题。
//这一步是输出尺寸伸缩和偏移。注意这不是一个全连接层,全连接层中的 是一个矩阵
反向传播
根据反向传播的顺序,首先求取损失 对BN层输出 的偏导 ,然后是对可学习参数的偏导 和 ,用于对参数进行更新,想继续回传的话还需要求对输入 偏导,于是引出对变量 、 和 的偏导,根据链式法则再求这些变量对 的偏导。
预测阶段
在预测阶段,所有参数的取值是固定的,对BN层而言,意味着 都是固定值。
- 和 比较好理解,随着训练结束,两者最终收敛,预测阶段使用训练结束时的值即可。
- 对于 和 ,在训练阶段,它们为当前mini batch的统计量,随着输入batch的不同, 和 一直在变化。在预测阶段,输入数据可能只有1条,就并没有batch的概念,因此,这个时候用的 和 是全量训练数据的均值和方差,这个可以通过移动平均法求得。
我们定义一个时间序列 ;拟合序列 这里的时间序列是每个训练迭代计算得到的mean和var,拟合序列是每个迭代,通过平滑算法计算的mean和var。那么,对于一阶指数平滑,有下式:
为什么使用BN网络
covariate shift
深层神经网络在做非线性变换前的激活输入值(就是那个 , 是输入。)随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近(对于Sigmoid函数来说,意味着激活输入值 是大的负值或正值),所以这导致后向传播时低层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因。
BN 就是通过一定的规范化手段,把每层神经网络任意神经元这个输入值的分布强行拉回到均值为 0 方差为 1 的标准正态分布,其实就是把越来越偏的分布强制拉回比较标准的分布,这样使得激活输入值落在非线性函数对输入比较敏感的区域,这样输入的小变化就会导致损失函数较大的变化,意思是这样让梯度变大,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。
为什么需要scale and shift
但是很明显,稍微了解神经网络的读者一般会提出一个疑问:如果都通过 BN,那么不就跟把非线性函数替换成线性函数效果相同了(因为sigmoid、ReLu、tanh函数的激活区都是线性的)。这意味着什么?我们知道,如果是多层的线性函数变换其实这个深层是没有意义的,因为多层线性网络跟一层线性网络是等价的。这意味着网络的表达能力下降了,这也意味着深度的意义就没有了。
所以 BN为了保证非线性的获得,对变换后的满足均值为 0 方差为 1 的 又进行了scale加上shift操作 ,每个神经元增加了两个参数 和 参数,这两个参数是通过训练学习到的,意思是通过 和 把这个值从标准正态分布左移或者右移一点并长胖一点或者变瘦一点,每个实例挪动的程度不一样,这样等价于非线性函数的值从正中心周围的线性区往非线性区动了动。本质上是将激活函数输出的数据进行标准化之后,又添加了一个神经元,进行线性变换。
BN 中 batch 的大小对网络性能有什么影响
由于 BN 在计算均值和方差时是在当前的 batch 上进行计算的,因此,当 batch 较小时,求出来的均值和方差就会有较大的随机性,从而导致效果下降,具体来说,当 batch 的大小低于 16 时 ,就不建议使用 BN,当 batch 低于 8 时,网络的性能就会有非常明显的下降。
BN的优点
- 缓解梯度消失,加速网络收敛。 BN层可以让激活函数的输入数据落在非饱和区,缓解了梯度消失问题。此外,由于每一层数据的均值与方差都在一定范围内,深层网络不必去不断适应浅层网络输入的变化,实现了层间解耦,允许每一层独立学习,也加快了网络的收敛。
- 简化调参,网络更稳定。在调参时,学习率调得过大容易出现震荡与不收敛, BN层则抑制了参数微小变化随网络加深而被放大的问题,因此对于参数变化的适应能力更强,更容易调参。
- 防止过拟合。 BN层将每一个batch的均值与方差引入到网络中,由于每个batch的这两个值都不相同,可看做为训练过程增加了随机噪音,可以起到一定的正则效果,防止过拟合。
实践结果
BN在CNN中的应用
我们知道BN层是对于每个神经元做归一化处理,也就是在每个神经元的激活函数前进行归一化。
既然BN是对单个神经元的运算,那么在CNN中卷积层上要怎么搞?假如某一层卷积层有6个特征图,每个特征图的大小是 ,这样就相当于这一层网络有 个神经元,如果采用BN,就会有 个参数 、,这样岂不是太恐怖了。因此卷积层上的 BN 使用,其实也是使用了类似权值共享的策略,把一整张特征图当做一个神经元进行处理。
卷积神经网络经过卷积后得到的是一系列的特征图,如果网络某一层输入数据可以表示为四维矩阵 , 为min-batch sizes, 为特征图个数,分别为特征图的宽高。在cnn中我们可以把每个特征图看成是一个特征处理(一个神经元)。一个Filter Map的所有神经元共享一对 参数,Mini-Batch里 个样本的均值和方差是在 个神经元里共享。当然在实际计算的时候每个神经元还是各算各的BN转换值,只不过采用的方差、均值和 参数用的都是共享的同一套值而已。下面是来自于keras卷积层的BN实现一小段主要源码:
BN在RNN中的应用
在自然语言项目中,序列的长度往往是不同的;batch中不同样本的有效序列长度各不相同,使用BN进行归一化的时候,该batch中的数据可能是
<padding>
,<padding>
会干扰原始数据;所以在RNN应用中经常使用Layer Normalization进行归一化。在transformer中只对隐含层进行了归一化,详情可以参考训练部分的代码。避免同一个batch中不同句子的有效长度问题
总结
原因
深层神经网络在做非线性变换前的激活输入值(就是那个 , 是输入。)随着网络深度加深或者在训练过程中,其分布逐渐发生偏移或者变动,之所以训练收敛慢,一般是整体分布逐渐往非线性函数的取值区间的上下限两端靠近(对于Sigmoid函数来说,意味着激活输入值 是大的负值或正值),所以这导致后向传播时低层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因。
原理
- 正向:
//得到batch中的统计特性之一:均值
//得到batch中的另一个统计特性:方差
//规范化,其中是一个很小的数,防止计算出现数值问题。
//这一步是输出尺寸伸缩和偏移。注意这不是一个全连接层,全连接层中的 是一个矩阵
- 预测:
- 和 比较好理解,随着训练结束,两者最终收敛,预测阶段使用训练结束时的值即可。
- 对于 和 ,在训练阶段,它们为当前mini batch的统计量,随着输入batch的不同, 和 一直在变化。在预测阶段,输入数据可能只有1条,就并没有batch的概念,因此,这个时候用的 和 是全量训练数据的均值和方差,这个可以通过移动平均法求得。
在预测阶段,所有参数的取值是固定的,对BN层而言,意味着 都是固定值。
我们定义一个时间序列 ;拟合序列 这里的时间序列是每个训练迭代计算得到的mean和var,拟合序列是每个迭代,通过平滑算法计算的mean和var。那么,对于一阶指数平滑,有下式:
为什么需要scale and shift
但是很明显,稍微了解神经网络的读者一般会提出一个疑问:如果都通过 BN,那么不就跟把非线性函数替换成线性函数效果相同了(因为sigmoid、ReLu、tanh函数的激活区都是线性的)。这意味着什么?我们知道,如果是多层的线性函数变换其实这个深层是没有意义的,因为多层线性网络跟一层线性网络是等价的。这意味着网络的表达能力下降了,这也意味着深度的意义就没有了。