『计算机视觉』各种Normalization层辨析

『教程』Batch Normalization 层介绍

知乎:详解深度学习中的Normalization,BN/LN/WN

一、两个概念

独立同分布(independent and identically distributed)

独立同分布的数据可以简化常规机器学习模型的训练、提升机器学习模型的预测能力

白化(whitening)

去除特征之间的相关性 —> 独立;

使得所有特征具有相同的均值和方差 —> 同分布。

二、问题

1、抽象程度高的层难以训练

深度神经网络涉及到很多层的叠加,而每一层的参数更新会导致上层的输入数据分布发生变化,通过层层叠加,高层(抽象程度高)的输入分布变化会非常剧烈,这就使得高层需要不断去重新适应底层的数据更新

Google 将这一现象总结为 Internal Covariate Shif:

统计机器学习中的一个经典假设是“源空间(source domain)和目标空间(target domain)的数据分布(distribution)是一致的”。如果不一致,那么就出现了新的机器学习问题,如 transfer learning / domain adaptation 等。

而 covariate shift 就是分布不一致假设之下的一个分支问题,它是指源空间和目标空间的条件概率是一致的,但是其边缘概率不同,即:对所有xin mathcal{X},

P_s(Y|X=x)=P_t(Y|X=x)\

但是

P_s(X)
e P_t(X)\

大家细想便会发现,的确,对于神经网络的各层输出,由于它们经过了层内操作作用,各层的输入信号的分布显然不同,而且差异会随着网络深度增大而增大,可是它们所能“指示”的样本标记(label)仍然是不变的,这便符合了covariate shift的定义。由于是对层间信号的分析,也即是“internal”的来由。

问题描述简而言之,每个神经元的输入数据不再是“独立同分布”。

  其一,上层参数需要不断适应新的输入数据分布,降低学习速度。

  其二,下层输入的变化可能趋向于变大或者变小,导致上层落入饱和区,使得学习过早停止。

  其三,每层的更新都会影响到其它层,因此每层的参数更新策略需要尽可能的谨慎。

2、问题挑战

我们以神经网络中的一个普通神经元为例。神经元接收一组输入向量

old{x}=(x_1, x_2, cdots, x_d)\

通过某种运算后,输出一个标量值:

y=f(old{x})\

由于 ICS 问题的存在, 对于某一特定层,不同批次的输入old{x} 的分布可能相差很大。

要解决独立同分布的问题,“理论正确”的方法就是对每一层的数据都进行白化操作。然而标准的白化操作代价高昂,特别是我们还希望白化操作是可微的,保证白化操作可以通过反向传播来更新梯度

三、解决思路:BN

1、通用框架

在将 old{x} 送给神经元之前,先对其做平移和伸缩变换, 将 old{x} 的分布规范化成在固定区间范围的标准分布。

通用变换框架就如下所示:

h=fleft(old{g}cdotfrac{old{x}-old{mu}}{old{sigma}}+old{b}
ight)\

(1) old{mu}平移参数(shift parameter), old{sigma}缩放参数(scale parameter)。通过这两个参数进行 shift 和 scale 变换:

old{hat{x}}=frac{old{x}-old{mu}}{old{sigma}}\

得到的数据符合均值为 0、方差为 1 的标准分布。

(2) old{b}再平移参数(re-shift parameter), old{g}再缩放参数(re-scale parameter)。将 上一步得到的 old{hat{x}} 进一步变换为: old{y}=old{g}cdot old{hat{x}} + old{b}\

最终得到的数据符合均值为 old{b} 、方差为 old{g}^2 的分布。

2、第二次变换的目的

1、目的一

第一次变换得到均值为 0、方差为 1 的标准分布,表达能力有限,下层神经元可能很努力地在学习,但不论其如何变化,其输出的结果在交给上层神经元进行处理之前,将被粗暴地重新调整到这一固定范围。为了更好的应用底层神经网络的学习结果,我们将规范化后的数据进行再平移和再缩放,使得每个神经元对应的输入范围是针对该神经元量身定制的一个确定范围(均值为 old{b} 、方差为 old{g}^2 )。rescale 和 reshift 的参数都是可学习的,这就使得 Normalization 层可以学习如何去适应底层的学习结果。

2、目的二

除了充分利用底层学习的能力,另一方面的重要意义在于保证获得非线性的表达能力。

Sigmoid 等激活函数在神经网络中有着重要作用,通过区分饱和区和非饱和区,使得神经网络的数据变换具有了非线性计算能力。而第一步的规范化会将几乎所有数据映射到激活函数的非饱和区(线性区),仅利用到了线性变化能力,从而降低了神经网络的表达能力。而进行再变换,则可以将数据从线性区变换到非线性区,恢复模型的表达能力。

3、优势

不添加正则化, old{x} 的均值取决于下层神经网络的复杂关联;添加本层后,取值 old{y}=old{g}cdot old{hat{x}} + old{b} 仅由 old{b} 来确定,去除了与下层计算的密切耦合。新参数很容易通过梯度下降来学习,简化了神经网络的训练。

4、问题

a)BN的实际作用

标准白化操作的目的是“独立同分布”。独立就不说了,暂不考虑。变换为均值为 old{b} 、方差为 old{g}^2 的分布,也并不是严格的同分布,只是映射到了一个确定的区间范围而已(所以,这个问题仍然有研究空间)。

另外有人提出:BN其优势并非解决了独立同分布的问题(实际上它也没解决),其最大意义在于解决了梯度弥散问题,见论文:How Does Batch Normalization Help Optimization?(知乎上的一篇阅读笔记:为什么Batch Normalization那么有用?)。文章结论如下:

  1. 没有证据表明BN的work,是因为减少了ICS(Interval Covariate Shift)
  2. BN work的根本原因,是因为在网络的训练阶段,其能够让优化空间(optimization landscape)变的平滑。
  3. 其他的normalization技术也能够像BN那样对于网络的训练起到作用。

其作用为防止梯度爆炸或弥散、可以提高训练时模型对于不同超参(学习率、初始化)的鲁棒性、可以让大部分的激活函数能够远离其饱和区域。

b) BN对小批次训练效果不好

当单个小批次(minibatch)的数据不能代表整个数据的分布时,BN的表现就会不尽如人意,这意味着忘记将输入随机打乱顺序的情况下使用批归一化是很危险的,实际上batch过小的时候就不太适合开放BN的可训练性。具体讨论见论文:Batch Normalization: Accelerating Deep Network Training by Reducing

BN训练时为什么不使用全局均值/方差?

使用 BN 的目的就是为了保证每批数据的分布稳定,使用全局统计量反而违背了这个初衷;
BN 的作者认为在训练时采用移动平均可能会与梯度优化存在冲突

四、主流 Normalization 方法梳理

BatchNorm:batch方向做归一化,算N*H*W的均值

LayerNorm:channel方向做归一化,算C*H*W的均值

InstanceNorm:一个channel内做归一化,算H*W的均值

GroupNorm:将channel方向分group,然后每个group内做归一化,算(C//G)*H*W的均值

https://zhuanlan.zhihu.com/p/69659844

1、Batch Normalization

『TensorFlow』批处理类

『教程』Batch Normalization 层介绍

于2015年由 Google 提出,BN 独立地规范化每一个层不同批次的 x_i ,但规范化的参数是一个 mini-batch 的一阶统计量和二阶统计量。这就要求 每一个 mini-batch 的统计量是整体统计量的近似估计,或者说每一个 mini-batch 彼此之间,以及和整体数据,都应该是近似同分布的。分布差距较小的 mini-batch 可以看做是为规范化操作和模型训练引入了噪声,可以增加模型的鲁棒性;但如果每个 mini-batch的原始分布差别很大,那么不同 mini-batch 的数据将会进行不一样的数据变换,这就增加了模型训练的难度。训练时,网络会记录每一个batch滑动平均的均值和方差,训练结束的时候这四个参数就固定了供测试时直接加载使用

BN 比较适用的场景是:每个 mini-batch 比较大,数据分布比较接近。在进行训练之前,要做好充分的 shuffle,否则效果会差很多。

另外,由于 BN 需要在运行过程中统计每个 mini-batch 的一阶统计量和二阶统计量,因此不适用于 动态的网络结构 和 RNN 网络。不过,也有研究者专门提出了适用于 RNN 的 BN 使用方法,这里先不展开了。

2、Layer Normalization

LN 针对单个训练样本进行,不依赖于其他数据,因此可以避免 BN 中受 mini-batch 数据分布影响的问题,可以用于 小 mini-batch 场景、动态网络场景和 RNN,特别是自然语言处理领域。此外,LN 不需要保存 mini-batch 的均值和方差,节省了额外的存储空间。

但是,BN 的转换是针对单个神经元可训练的——不同神经元的输入经过再平移和再缩放后分布在不同的区间,而 LN 对于一整层的神经元训练得到同一个转换——所有的输入都在同一个区间范围内。如果不同输入特征不属于相似的类别(比如颜色和大小),那么 LN 的处理可能会降低模型的表达能力。

3、Instance Normalization

在GAN和style transfer的任务中,目前的IN norm要好于BN,IN主要用于对单张图像的数据做处理,而BN主要是对Bacth的数据做处理。由于BN在训练时每个batch的均值和方差会由于shuffle都会改变,所以可以理解为一种数据增强,而IN可以理解为对数据做一个归一化的操作。

换句话说,BN的计算是要受其他样本影响的,由于每个batch的均值和标准差不稳定,对于单个数据而言,相对于是引入了噪声,但在分类这种问题上,结果和数据的整体分布有关系,因此需要通过BN获得数据的整体分布。而instance norm的信息都是来自于自身的图片,相当于对全局信息做了一次整合和调整,在图像转换这种问题上,BN获得的整体信息不会带来任何收益,带来的噪声反而会弱化实例之间的独立性:这类生成式方法,每张图片自己的风格比较独立不应该与batch中其他的样本产生太大联系。

4、Group Normalization

group normalization是2018年3月份何恺明大神的又一力作,优化了BN在比较小的mini-batch情况下表现不太好的劣势。批量维度进行归一化会带来一些问题——批量统计估算不准确导致批量变小时,BN 的误差会迅速增加。在训练大型网络和将特征转移到计算机视觉任务中(包括检测、分割和视频),内存消耗限制了只能使用小批量的BN。事实上,GN的极端情况就是LN和IN,分别对应G等于C和G等于1。

tf实现并不复杂,如下

def GroupNorm(x,G=16,eps=1e-5):
    N,H,W,C=x.shape    
    x=tf.reshape(x,[tf.cast(N,tf.int32),
                    tf.cast(H,tf.int32),
                    tf.cast(W,tf.int32),
                    tf.cast(G,tf.int32),
                    tf.cast(C//G,tf.int32)])
    mean,var=tf.nn.moments(x,[1,2,4],keep_dims=True)
    x=(x-mean)/tf.sqrt(var+eps)
    x=tf.reshape(x,[tf.cast(N,tf.int32),
                    tf.cast(H,tf.int32),
            tf.cast(W,tf.int32),
            tf.cast(C,tf.int32)])
    gamma = tf.Variable(tf.ones(shape=[1,1,1,tf.cast(C,tf.int32)]), name="gamma")
    beta = tf.Variable(tf.zeros(shape=[1,1,1,tf.cast(C,tf.int32)]), name="beta")
    return x*gamma+beta

在深度学习没有火起来之前,提取特征通常是使用SIFT,HOG和GIST特征,这些特征有一个共性,都具有按group表示的特性,每一个group由相同种类直方图的构建而成,这些特征通常是对在每个直方图(histogram)或每个方向(orientation)上进行组归一化(group-wise norm)而得到。

从深度学习上来讲,完全可以认为卷积提取的特征是一种非结构化的特征或者向量,拿网络的第一层卷积为例,卷积层中的的卷积核filter1和此卷积核的其他经过transform过的版本filter2(transform可以是horizontal flipping等),在同一张图像上学习到的特征应该是具有相同的分布,那么,具有相同的特征可以被分到同一个group中,按照个人理解,每一层有很多的卷积核,这些核学习到的特征并不完全是独立的,某些特征具有相同的分布,因此可以被group。

原文地址:https://www.cnblogs.com/hellcat/p/9735041.html