参考论文
Batch Normalization
Layer Normalization
白化:
- 独立同分布数据:机器学习界最喜欢的数据莫过于独立同分布数据. 独立同分布并非所有机器学习模型的必然要求,比如Naïve Bayes模型就建立在特征彼此独立的基础之上,而逻辑回归 和神经网络中则在非独立的特征数据上依然可以训练出很好的模型,但独立同分布的数据可以简化常规机器学习模型的训练、提升机器学习模型的预测能力,已经是一个共识。
- 白化: 因此,在把数据喂给机器学习模型之前,将数据独立同分布化是一个重要的数据预处理步骤。白化指定就是将数据独立同分布化的这个过程,白化一般包含两个目的:
- 去除特征之间的相关性 —> 独立;
- 使得所有特征具有相同的均值和方差 —> 同分布。
- 白化最典型的方法就是PCA。
Internal Covariate Shift:
- 深度神经网络涉及到很多层的叠加,而每一层的参数更新会导致上层的输入数据分布发生变化,通过层层叠加,高层的输入分布变化会非常剧烈,这就使得高层需要不断去重新适应底层的参数更新;Google将这一现象总结为 Internal Covariate Shift,简称 ICS。为了训好模型,我们需要非常谨慎地去设定学习率、初始化权重、以及尽可能细致的参数更新策略。
- Batch Normalization的原论文作者给了Internal Covariate Shift一个较规范的定义:在深层网络训练的过程中,由于网络中参数变化而引起内部结点数据分布发生变化的这一过程被称作Internal Covariate Shift。
- ICS 会导致的问题: 简而言之,每个神经元的输入数据不再是独立同分布。
- 1.上层参数需要不断适应新的输入数据分布,降低学习速度。
- 2.下层输入的变化可能趋向于变大或者变小,导致上层落入饱和区,使得学习过早停止。
- 3.每层的更新都会影响到其它层,因此每层的参数更新策略需要尽可能的谨慎。
- 3.每层的更新都会影响到其它层,因此每层的参数更新策略需要尽可能的谨慎。
- 我们以神经网络中的一个普通神经元为例。神经元接收一组输入向量:
通过每个神经元后,输出一个标量值:
由于ICS问题的存在,x的分布可能相差很大。要解决ICS问题我们必须使的神经网络的每一层的输入独立同分布,理论正确的方法就是对每一层的输入数据都进行白化操作。但是由于白化操作具有以下缺点:
- 白化过程计算成本太高,并且在每一轮训练中的每一层我们都需要做如此高成本计算的白化操作;特别是我们还希望白化操作是可微的,保证白化操作可以通过反向传播来更新梯度
- 白化过程由于改变了网络每一层的分布,因而改变了网络层中本身数据的表达能力。底层网络学习到的参数信息会被白化操作丢失掉。
Batch Normalization (纵向规范化)
思路:
- 既然白化计算过程比较复杂,那我们就简化一点,比如我们可以尝试单独对每个特征(每个神经元)进行normalizaiton就可以了,让每个特征都有均值为0,方差为1的分布就OK。
- 另一个问题,既然白化操作减弱了网络中每一层输入数据表达能力,那我就再加个线性变换操作,让这些数据再能够尽可能恢复本身的表达能力就好了。
模型:
- 在深度学习中,由于采用full batch的训练方式对内存要求较大,且每一轮训练时间过长;我们一般都会采用对数据做划分,用mini-batch对网络进行训练。因此,Batch Normalization也就在mini-batch的基础上进行计算。
- 假定网络的层数为L(不包含输入层):
- 其中参数有:
:网络中的层标号
:网络中的最后一层或总层数
:第l层的维度,即神经元结点数
:第l层的权重矩阵,
:第 l 层的偏置向量,
:第 l 层的线性计算结果,
:第l层的激活函数
:第 l 层的非线性激活结果,
:训练样本的数量
:训练样本的特征数
:训练样本集, (注意这里X的一列是一个样本)
:batch size,即每个batch中样本的数量
:第 i 个mini-batch的训练数据, ,其中
- 步骤:
- 假定我们现在考虑深度神经网络的的第
层,则:神经元的个数为:
,这一层的输出为:
,这一层第j个神经元的输出为:
分别表示batch中的每个样本用过 第
个神经元的输出。由于我们只考虑某一层所以
将在下面被省略,所以表示为:
。
- 其中ϵ是为了防止方差为0产生无效计算
- 假定我们现在考虑深度神经网络的的第
层,则:神经元的个数为:
,这一层的输出为:
,这一层第j个神经元的输出为:
分别表示batch中的每个样本用过 第
个神经元的输出。由于我们只考虑某一层所以
将在下面被省略,所以表示为:
。
- 具体例子:下图我们只关注第l层的计算结果,左边的矩阵是
线性计算结果,还未进行激活函数的非线性变换。此时每一列是一个样本,图中可以看到共有8列,代表当前训练样本的batch中共有8个样本,每一行代表当前l层神经元的一个节点,可以看到当前l层共有4个神经元结点,即第l层维度为4。我们可以看到,每行的数据分布都不同
如同上面提到的,Normalization操作我们虽然缓解了ICS问题,让每一层网络的输入数据分布都变得稳定,但却导致了数据表达能力的缺失。也就是我们通过变换操作改变了原有数据的信息表达,使得底层网络学习到的参数信息丢失。另一方面,通过让每一层的输入分布均值为0,方差为1,会使得输入在经过sigmoid或tanh激活函数时,容易陷入非线性激活函数的线性区域。
因此,BN又引入了两个可学习的参数 与 。这两个参数的引入是为了恢复数据本身的表达能力,对规范化后的数据进行线性变换,即 。特别地,当 时,可以实现等价变换并且保留了原始输入特征的分布信息。通过上面的步骤,我们就在一定程度上保证了输入数据的表达能力 - 公式总结: 对于神经网络中的第
层,我们有:
BN的优点:
- BN使得网络中每层输入数据的分布相对稳定,加速模型学习速度
- BN使得模型对网络中的参数不那么敏感,简化调参过程,使得网络学习更加稳定:
- 例子: 当学习率设置太高时,会使得参数更新步伐过大,容易出现震荡和不收敛。但是使用BN的网络将不会受到参数数值大小的影响。假设我们对参数 进行缩放得到 。对于缩放前的值 ,我们设其均值为 ,方差为 ;对于缩放值 ,设其均值为 ,方差为 ,则我们有: 我们忽略ϵ ,则有: 注:公式中的 u 是当前层的输入,也是前一层的输出;
- 我们可以看到,经过BN操作以后,权重的缩放值会被“抹去”,因此保证了输入数据分布稳定在一定范围内。另外,权重的缩放并不会影响到对u的梯度计算;并且当权重越大时,即 越大, 越小,意味着权重 的梯度反而越小,这样BN就保证了梯度不会依赖于参数的scale,使得参数的更新处在更加稳定的状态。因此,在使用Batch Normalization之后,抑制了参数微小变化随着网络层数加深被放大的问题,使得网络对参数大小的适应能力更强,此时我们可以设置较大的学习率而不用过于担心模型divergence的风险
- BN允许网络使用饱和性激活函数(例如sigmoid,tanh等),缓解梯度消失问题: 在不使用BN层的时候,由于网络的深度与复杂性,很容易使得底层网络变化累积到上层网络中,导致模型的训练很容易进入到激活函数的梯度饱和区;通过normalize操作可以让激活函数的输入数据落在梯度非饱和区,缓解梯度消失的问题;另外通过自适应学习 与 又让数据保留更多的原始信息。
- BN具有一定的正则化效果: 在Batch Normalization中,由于我们使用mini-batch的均值与方差作为对整体训练样本均值与方差的估计,尽管每一个batch中的数据都是从总体样本中抽样得到,但不同mini-batch的均值与方差会有所不同,这就为网络的学习过程中增加了随机噪音,与Dropout通过关闭神经元给网络训练带来噪音类似,在一定程度上对模型起到了正则化的效果。
BN的缺点:
- 不适合Batch Size比较小: BN是按照样本数计算归一化统计量的,当样本数很少时,这时样本的均值和方差便不能反映全局的统计分布,所以基于少量样本的BN的效果会变得很差。
- 不适用于RNN: BN实际使用时需要计算并且保存某一层神经网络mini-batch的均值和方差等统计信息,对于对一个固定深度的前向神经网络(DNN,CNN)使用BN,很方便;但对于RNN来说,sequence的长度是不一致的,换句话说RNN的深度不是固定的,可能存在一个特殊sequence比其的sequence长很多,这样training时,计算很麻烦
测试阶段的用法:
- 我们知道BN在每一层计算的 与 都是基于当前batch中的训练数据,但是这就带来了一个问题:我们在预测阶段,有可能只需要预测一个样本或很少的样本,没有像训练样本中那么多的数据,此时μ 与 σ^2的计算一定是有偏估计。
- 为了解决这个问题,一般都是训练的时候在训练集上通过滑动平均预先计算好平均-mean,和方差-variance参数,在测试的时候,不在计算这些值,而是直接调用这些预计算好的来用。
- 具体的说就是:我们在BN训练过程中保留了每组mini-batch训练数据在网络中每一层的
与
。此时我们使用整个样本的统计量来对Test数据进行归一化,具体来说使用均值与方差的无偏估计:
得到每个特征的均值与方差的无偏估计后,我们对test数据采用同样的normalization方法:
Layer Normalization(横向规范化)
- LN主要是为了解决BN的两个大缺点。
MLP中的LN:
- 对于BN的正则化对象是每个神经元的输出,LM刚好相反,它正则化的对象是每个样本经过某一层网络后输出。对比如下图:
- 参数使用BN中的参数。
- 现在我们考察第l层的计算过程,假定某个样本的输入为: ,该层神经元个数为 ,则该样本经过这一层后输出: ;其中 是 经过第 个神经元的输出。现在我们对 进行正则化:
- 在LN中我们也需要一组参数来保证归一化操作不会破坏之前的信息,在LN中这组参数叫做增益 和偏置 (等同于BN中的 和 )。假设激活函数为 ,最终LN的输出为:
RNN中的LN:
- 在RNN中,我们可以非常简单的在每个时间片中使用LN,对于RNN时刻 时的节点,其输入是 时刻的隐层状态 和 时刻的输入数据的一个样本 ,可以表示为:
- 与上面相同对 进行正则化
总结:
- 上面的统计量 的计算是和样本数量没有关系的,它的数量只取决于隐层节点的数量,所以只要隐层节点的数量足够多,我们就能保证LN的归一化统计量足够具有代表性.