深入理解规范化(机器学习,深度学习,神经网络)

深入理解规范化

==================================

1.Normalization

先看下基本概念。

Normalization 翻译为规范化、标准化、归一化

维基百科中给出:

  • min-max normailzation(常简称为 normailzation):

  • Mean normalization:

  • Standardization (Z-score Normalization):

我们这里的 Normalization 是指第三种——标准化

深度学习中的 Normalization 根据规范化操作涉及的对象不同可以大致分为两大类,

一类是对 l 层的激活后的输出值进行标准化,Batch Norm、Layer Norm、Instance Norm、Group Norm 就属于这一类;

另外一类是对神经元连接边的权重进行规范化操作,Weight Norm 就属于这一类。

3.1 Base

BN 翻译过来就是批标准化:

  • 批是指一批数据,通常为 mini-batch;

  • 标准化则是服从均值为 0、方差为 1 的正态分布。

BN 的核心思想在于使得每一层神经网络的输入保持相同的分布。

目前有两种插入 Norm 操作的地方,一种是 GN 论文中提出的,在激活函数之前进行 Norm;还有一种是后续研究提出的,放在激活函数之后进行,并且研究表明,放在激活函数之后的效果更好。但不论哪种,其规范化的目的都是一样的。

 

BN 的优点有哪些?

  • 首先,由于神经网络的分布相同,所以可以使用更大的学习率,从而加速模型的收敛;

  • 其次,我们不需要再去精心设计权值的初始化;

  • 再者,我们也不需要用 Dropout,或者说可以使用较小的 Dropout;

  • 然后,也不需要使用 L2 或者 weight decay;

  • 最后,也不需要使用 LRN(Local response normalization)。

可以说 BN 是一个相当强大的深度学习杀手锏了。

3.2 Algorithm

BN 的计算方式很简单,给定 d 维的输入,我们会对「特征的每一个维度」进行规范化:

我们来看下算法的具体实现方式:

 

  • 输入的是一个 Batch 数据,和两个可学习参数α, β

  • 首先计算 mini-batch 的均值和方差;

  • 然后计算 normalize,分母中的ε是为了防止除 0;

  • 最后利用 affine transform 来对 x 进行缩放和偏移,从而增强模型的表达能力,使得模型更加灵活、选择性更多,利用可学习参数将数据分布的改变权交给模型。

 

https://blog.csdn.net/qq_33431368/article/details/107328558

==================================

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

 

一、规范化(Normalization)

1、自协变量变化(Internal Covariate Shift,ICS)问题

简单来说,ICS问题就是在神经网络层次不断加深的过程中,浅层样本的分布波动会经过一层层神经网络的传递,严重影响深层神经网络接收到的特征的分布波动。

下面是引用一段别人的解说:

在统计机器学习中的一个经典假设是“源空间(source domain)和目标空间(target domain)的数据分布(distribution)是一致的”。如果不一致,那么就出现了新的机器学习问题,如 transfer learning / domain adaptation 等。而 covariate shift 就是分布不一致假设之下的一个分支问题,它是指源空间和目标空间的条件概率是一致的,但是其边缘概率不同。
大家细想便会发现,的确,对于神经网络的各层输出,由于它们经过了层内操作作用,其分布显然与各层对应的输入信号分布不同,而且差异会随着网络深度增大而增大,可是它们所能“指示”的样本标记(label)仍然是不变的,这便符合了covariate shift的定义。由于是对层间信号的分析,也即是“internal”的来由。

另外也有人解释:

Internal Covariate Shift(ICS),这个概念指神经网络中层之间由于相互作用,神经网络中任意两层的数据分布都保持一定的非线性关系(hi = g(hj))。这是神经网络的一个基本的性质,但这一性质会导致:浅层网络饱和(反向传播中无法有效进行浅层训练,实际上是由于梯度消失引起的)、深层网络隐层输入振荡(输入有细微的变化时,深层网络可能震荡激烈)。

▲ ICS所导致可能的问题

导致每个神经元的输入数据不再是“独立同分布”:

  1. 上层参数需要不断适应新的输入数据分布,降低学习速度。
  2. 下层输入的变化可能趋向于变大或者变小,导致上层落入饱和区,使得学习过早停止。
  3. 每层的更新都会影响到其它层,因此每层的参数更新策略需要尽可能的谨慎。

2、Normalization——规范化

首先来了解一下规范化的通用变换框架

简单来说就是利用均值方差将特征限制到标准分布上,再利用可训练的参数将其还原。这样放缩的目的是“为了保证模型的表达能力不因为规范化而下降

▲ Normalization为什么有效

1. 层层之间的一定程度的解耦。其一是使每层保持在了一个相对稳定的分布。其二使Sigmoid、Tanh等激活函数的偏微分对于梯度反向传播影响更小(保持在了导数非饱和区),缓解了梯度消失。

2. 使模型对网络中的参数不再敏感。对于Norm操作而言,假设W=aW’,显然Norm(W)=Norm(W’)。对于以下两个公式,对x进行微分进行的是链式传播中隐层之间的反向传播累乘因子,对w进行微分进行的是计算对于当前层W的更新梯度值(这部分理解对BP熟悉就不难)。

 

 

这两个公式使得:

1)参数权重的伸缩变化不会影响反向传播,缓解了反向传播中权重过大/过小引发的梯度爆炸/消失。(权重初始化更简单)

2)权重值越大,梯度就越小,参数变化趋于稳定,起到了一定的正则化作用。(自适应的梯度下降值,使学习率设定更简单)

3. BN对mini-batch随机的选取,使计算的均值和方差有区别,相当于引入噪声,起到了正则化作用。

3、主流Normalization方法

1、Batch Normalization——批次规范化

Batch Normalization 于2015年由 Google 提出,开 Normalization 之先河。其规范化针对单个神经元进行,利用网络训练时一个 mini-batch 的数据来计算该神经元

的均值和方差,因而称为 Batch Normalization。

 

其中M即为mini-batch的大小。

按上图所示,相对于一层神经元的水平排列,BN 可以看做一种纵向的规范化。由于 BN 是针对单个维度定义的,因此标准公式中的计算均为 element-wise 的。

BN 独立地规范化每一个输入维度xi ,但规范化的参数是一个 mini-batch 的一阶统计量和二阶统计量。这就要求 每一个 mini-batch 的统计量是整体统计量的近似估计,或者说每一个 mini-batch 彼此之间,以及和整体数据,都应该是近似同分布的。分布差距较小的 mini-batch 可以看做是为规范化操作和模型训练引入了噪声,可以增加模型的鲁棒性;但如果每个 mini-batch的原始分布差别很大,那么不同 mini-batch 的数据将会进行不一样的数据变换,这就增加了模型训练的难度。

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

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

2、Layer Normalization——横向规范化

层规范化就是针对 BN 的上述不足而提出的。与 BN 不同,LN 是一种横向的规范化,如图所示。它综合考虑一层所有维度的输入,计算该层的平均输入值和输入方差,然后用同一个规范化操作来转换各个维度的输入。

 

 

其中i 枚举了该层所有的输入神经元。对应到标准公式中,四大参数 , , ,均为标量(BN中是向量),所有输入共享一个规范化变换。

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

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

3、BN 和 LN 的区别

BN选取了一批mini-batch计算均值和方差,进行归一化;而LN是对单层神经元(单个样本的所有维度)进行归一化。抽象理解可以是BN为纵向归一化,LN横向。BN实现的放缩最后使不同的神经元被Norm到不同区间,且LN会强制是他们都被Norm到同一个区间,这更可能损失模型的表达能力。相对的,LN不需要保存mini-batch的均值方差,省了空间,且适用范围比BN大。

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

==================================

 https://blog.csdn.net/Teeyohuang/article/details/103756624

 

Normalization的分类
至于深度学习中的Normalization,因为神经网络里主要有两类实体:神经元或者连接神经元的边,

所以按照规范化操作涉及对象的不同可以分为两大类:
① 一类是对第L层每个神经元的 净激活值 进行Normalization操作,
比如BatchNorm/ LayerNorm/ InstanceNorm/ GroupNorm等方法都属于这一类;

② 另外一类是对神经网络中连接相邻隐层神经元之间的边上的权重进行规范化操作,比如Weight Norm就属于这一类。
广义上讲,一般机器学习里看到的损失函数里面加入的对参数的的L1/L2等正则项,本质上也属于这第二类规范化操作
L1正则的规范化目标是造成参数的稀疏化,就是争取达到让大量参数值取得0值的效果,
而L2正则的规范化目标是有效减小原始参数值的大小。
有了这些规范目标,通过具体的规范化手段来改变参数值,以达到避免模型过拟合的目的。

原文链接:https://blog.csdn.net/Teeyohuang/article/details/103756624

 ==================================

https://www.lmlphp.com/user/57792/article/item/1168868/

 

在机器学习领域中,有一个重要的假设:独立同分布假设,也就是假设训练数据和测试数据是满足相同分布的,否则在训练集上学习到的模型在测试集上的表现会比较差。而在深层神经网络的训练中,当中间神经层的前一层参数发生改变时,该层的输入分布也会发生改变,也就是存在内部协变量偏移问题(Internal Covariate Shift),从而造成神经层的梯度消失,模型收敛过慢的问题。

 

Batch Normalization(BN,批量标准化)就是一种解决内部协变量偏移问题的方法,它通过对神经网络的中间层进行逐层归一化,让每一个中间层输入的分布保持稳定,即保持同一分布。

下面从以下四个方面来深入理解Batch Normalization的原理。

1、内部协变量偏移问题

2、训练时的Batch Normalization

3、推断时的Batch Normalization

4、Batch Normalization的优点

一、内部协变量偏移问题

1、内部协变量偏移问题的产生

在传统机器学习中,一个常见的问题是协变量偏移(Covariate Shift),大致的意思就是数据会随着时间而变化,用旧数据训练好的模型去预测新数据时,结果可能会不准确。输入数据可以看做是协变量,机器学习算法要求输入数据在训练集和测试集上满足同分布,这样把模型用来预测新的数据,才能有较好的结果。

而深层神经网络中的内部协变量偏移(Internel Covarian Shift)可以拆分为“中间”和“协变量偏移”两部分来理解。中间二字指的是神经网络的中间层(隐藏层),协变量偏移则与传统机器学习中的概念类似。在深层神经网络中,中间层的输入也就是前一层的输出,前一层的参数变化会导致该中间层的输入(WU+b)的分布发生较大的差异。在用随机梯度下降来训练网络时,每次参数更新都会导致神经网络中间层的输入分布发生变化。这就会造成同一次迭代时中间层与中间层之间的输入分布不一致,在不同的迭代轮次中同一中间层的输入分布也发生变化。而这就是内部协变量偏移问题。

传统机器学习的协变量偏移问题是源于测试集与训练集中输入分布的不一致,而深层神经网络中的内部协变量偏移问题的含义稍有不同,是不同中间层的输入分布不一致。

那么内部协变量偏移问题又是如何导致梯度消失的呢?

2、内部协变量偏移导致梯度消失

我们换一种说法,深层神经网络在做非线性变换之前的输入值(WU+b)随着网络深度的加深,或者在每一轮迭代中,其分布逐渐发生变动,一般是整体分布逐渐往非线性激活函数的y值区间的上下限两端靠近,从而导致反向传播时底层神经网络的梯度消失,从而使得神经网络收敛得越来越慢。

以sigmoid激活函数来举例,sigmoid函数是个两端饱和函数,也就是输入值(WU+b)是非常大的负值或者非常大的正值时,其导数会接近于0;而当输入值在0附近时,sigmoid函数近似于一个线性函数,导数在0.25以下,但远离0值。下面是sigmoid函数的导数。

首先假设输入值的分布在没有发生改变之前服从标准正态分布,即均值为0,方差为1,那么由概率论的知识可以得到,有95%的概率这个输入值落在[-2,2]的范围内,也就是sigmoid函数接近于线性变换的区域,从上图中目测(简陋点哈哈)导数在(0.1, 0.25)的范围内,因此不会发生梯度消失问题。

然后如果输入值的分布发生了偏移,服从均值为 -6,方差为 1 的正态分布,那么有95%的概率输入值落在[-8, -4]的区间中(均值加减两倍方差),从上图可以看到,sigmoid函数的导数在这个区间上明显趋近于0,也就是落在了梯度饱和区。那么梯度变化就会很小乃至消失。

同样,如果输入值的分布偏移到正态分布的右边,比如服从均值为 6,方差为 1 的正态分布,则sigmoid函数的值接近于 1,同样其导数值也趋近于 0。

明白了内部协变量偏移会导致梯度消失的原理,并且明白了如果输入值的分布满足均值为0,方差为1的条件,那么就可以比较好地解决梯度消失问题,那么一个当然的想法就是,对神经网络的每一个中间层进行标准归一化,把每一个中间层的输入值强行从越来越偏的画风中拉回到又红又专的状态(均值为0,方差为1的标准分布) ,使得输入值落在非线性函数对输入比较敏感的区域。这样就能让梯度保持在比较大的水平,加快学习和收敛的速度

二、训练时的 Batch Normalization

首先说明四点:

第一点是Batch Normalization是基于小批量随机梯度下降(Mini-Batch SGB)的;

第二点是Batch Normalization是放在激活函数之前,可以视为一层;

第三点是Batch Normalization在标准归一化之后,减弱了神经网络的非线性表示,需要附加缩放和平移来变换取值区间

第四点是由于附加了平移变换(加上一个常数),相当于给神经层加了偏置,因此标准归一化之前的输入值不用再加偏置(本来是WU+b,现在只要WU就行)。

那么,接下来慢慢说明。

1、标准归一化

对每个中间层的神经元的输入值做BN,可以视为在每个中间层之前加上了一个BN层,它位于计算输入值WU(第三点说明了这里不加偏置)之后,进行非线性变换之前。

 

用小批量梯度下降来训练神经网络,假设batch size是m,在第 t 层的输入值 x=WU 的维度是 d,也就是一个输入值表示为 x = (x, x,..., x),那么首先对x的每一个维度的值都进行标准归一化:

 这个标准归一化的含义是:第 t 层中第 k 个神经元(即 x 的第 k 个维度)的输入值,减去 m 个样本在该层的输入值第 k 个维度的均值E(x),并且除以其标准差(Var(x)开方)来进行转换。

要注意的是,本来E(x)和Var(x)表示x的第k维度在整个数据集上的期望和方差,可是由于是使用小批量梯度下降算法,所以用m个样本在第k维度的均值和方差来估计。计算的方程如下:

 

2、缩放和平移变换

对输入值x进行标准归一化会使得取值集中在0附近,如果使用sigmoid函数或者tanh激活函数,那么这个取值区间刚好是接近线性变换的区间,这会减弱非线性激活函数的表示能力。因此,为了不让标准归一化对网络的表示能力产生不良影响,就需要附加缩放(scale)和平移(shift)变换来改变标准归一化后值的区间,在一定程度上恢复网络的非线性表示能力。那么每个神经元就会增加两个调节参数,分别用来进行缩放和平移操作,可以通过训练来学习这两个参数。

有意思的是,这个缩放和平移变换其实是标准归一化的反向操作,当缩放参数为 ,平移参数为 时,可以把值恢复到标准归一化之前的值x。

还要因为标准归一化后加了平移变换,相当于在计算输入值时加了偏置,因此在进行标准归一化之前的输入值不需要再加偏置,也就是输入值为WU,而不是WU+b。

那么Batch Normalization的算法流程如下:

 

当然,得到这个BN操作之后的值y,后面该干嘛干嘛,把它输入到非线性激活函数中得到该中间层的输出。

三、推断时的Batch Normalization

运用Batch Normalization对输入值进行调整的深层神经网络,在训练阶段,是用小批量梯度下降来进行优化的,也就是每轮迭代都把batch size 个样本喂给模型,通过计算这若干个样本的均值和方差,来进行BN操作。那么在推断(Inference,我觉得测试和预测都算推断吧)阶段,每次只输入一个样本,没有多个样本可以求均值和方差,那么如何对输入值做Batch Normalization呢?

也比较简单,因为幸运的是此时模型已经训练完毕了,那我们可以用整个数据集上的均值μ和方差σ来代替每次小批量样本的均值和方差,然后在推断阶段就使用这两个全局统计量来进行BN操作。

 

那整个数据集上的均值和方差如何得到呢?这样做,在小批量梯度下降的每轮迭代中,都会输入batch size 个样本,然后得到这些样本的均值和方差,那么每次都把这些样本的均值和方差记录下来。整个数据集都迭代完毕后,再对得到的所有均值和方差求数学期望,就可以得到全局的均值和方差:

 

用全局的均值和方差来进行标准归一化,就完成了BN操作的第一步。

那么还有第二步啊,对标准归一化后的输入值进行缩放和平移变换。由于在训练阶段结束后,中间层中每个神经元对应的缩放参数γ和平移参数β都已经求出来了,那么就可以直接用来进行变换。由于在推断阶段,无论是样本的均值和方差,还是缩放参数和平移参数都已经是常数了,不再变化了,那么为了计算更快速,就把标准归一化和缩放、平移变换这两步的参数整合到一起,存放起来,当输入新样本时,直接调用就好了。这也就是把公式进行了以下变换:

 

四、Batch Normalization的优点

1、通过标准归一化,使得输入值的均值为0,方差为1,而不是绝对值非常大的数(sigmoid的导数取值为0),就可以大大提升训练速度,加快模型收敛

2、带有轻微的正则化效果,与Dropout类似。Dropout通过给隐藏层的神经元以一定的概率乘以0或者1,而给隐藏层的激活值增加了噪音。相比之下,BN操作通过对输入值减去均值和进行缩放,也给隐藏层的神经元添加了轻微的噪音

3、使得调参过程简单了不少。使用梯度下降法对参数进行优化学习时,非常关键的一个问题是如何合理地初始化参数值,为此提出了Xavier初始化和He初始化等方法,而使用BN操作后,对于参数初始化的要求就没那么高了。而且也可以使用大的学习率。

4、使用饱和型激活函数,比如sigmoid函数和tanh函数,也不怕出现梯度消失问题了

 

参考资料:

1、邱锡鹏:《神经网络与深度学习》

2、深入理解Batch Normalization批标准化

https://i.cnblogs.com/EditPosts.aspx?postid=10756382

3、《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 》

https://arxiv.org/pdf/1502.03167.pdf

==================================

https://www.cnblogs.com/fydeblog/p/10689794.html

下面这张图很直观地解释了各种Normalization处理张量的不同之处。


给定一个四维张量X,四维依次代表[batchsize, channel, height, width),简单起见,表示为(N,C,H, W),上图中,张量的第三个维度以及第四个维度合起来组成了一个维度,方便展示。
BN∶可以看到BN是以C为滑动轴,对NHW三个维度求和取平均,所以期望的维度是(1,C,1,1),然后利用期望求出方差。

LN: LN与BN刚好是垂直的位置,是以N为滑动轴,对CHW三个维度求和取平均,期望的维度是(N,1,1,1)。
IN: IN则是LN和BN的交汇,以N和C双轴滑动,对HW两个维度求和取平均,期望的维度是(N,C,1,1)。
GN:GN则是IN和LN的一种折中考虑,对C维度进行了分组,上图中是分成了两组,所以最后期望的维度是(N,2,1,1)。

 

原理与使用

深度神经网络中的Normalization最先是出现在AlexNet网络中的LRN(local response normalization),而LRN计算的是像素局部的统计量,对加速收敛没有什么作用。开山加速收敛的Normalization方法是BN,那么它是怎么加速收敛的呢?首先要弄清楚为什么没有BN 收敛会慢,对于一个深层网络来说,会发生梯度弥散,这样在反向传播更新梯度时,会更新得非常慢,收敛也会变得慢,而BN将原来要变小的activation通过规范化操作,使activation的尺度变大,这样就消除了梯度弥散而导致参数更新慢的影响。
BN训练阶段与测试阶段: 训练阶段的期望和方差通过当前批数据进行计算,a和β则是BN层的可学习参数,由于BN层会减去期望,所以前一层是没必要加上偏置的。在测试阶段,一般是单例 forward,对单例求期望和方差是无意义的,所以BN的测试阶段的期望和方差是训练时每个批次的期望和方差的累计移动平均或者指数移动平均求得的.
从BN的训练阶段中知道,BN严重依赖批数据,通过批数据的统计信息来近似估计全局的统计信息,而在测试阶段,没有进行统计信息的计算,而是通过训练阶段的统计信息来估计新数据,当新数据来自未知的domain (风格迁移将每张图片当作一个domain,图像的生成结果主要依赖于某个图像实例,BN统计的近似全局信息并不会给任务带来收益,反而会弱化实例之间的特殊性[5]),训练的统计信息就用处不那么大了,另外大网络的大batchsize很占用GPU显存,对于缺少多GPU的人来说,这是不好办的,而减小batchsize会使计算的期望与方差不能代表整体分布,网络性能就会大大折扣。
为了消除batch的影响,LN,IN,GN就出现了。这三个规范化操作均对于batch都是不敏感的。BN是针对不同神经元层计算期望和方差,同一个batch有相同的期望和方差。
。LN是针对同层神经元计算期望和方差,不同样本有不同的期望和方差。
。IN是不同样本的不同神经元层有不同的期望和方差。
。GN是不同样本不同分组有不同的期望和方差。
这也导致了它们的用途不同。BN统计的是数据的整体分布,判别模型的结果主要取决于数据的整体分布,所以BN经常用于固定深度的DNN,CNN中。
对于RNN来说,序列的长度是不一致的,也就是深度不固定,不同时间保存的统计信息不同,这对于固定批次的BN是计算很麻烦的。而LN与输入序列的长度是没有关系的,因此LN在RNN中效果明显,但在cnn中不如BN。如下图所示[7],LSTM+LN更快收敛,学习得更好
 

 


在图像风格化任务中,生成结果主要依赖于单个图像实例,所以这类任务用BN并不合适,但可以对HW做规范化,可以加速模型收敛[6][8]。

GN根据传统的特征提取器组合特征的思路(例如HOG根据orientation分组),对channel进行分组,每一层的都有很多卷积核,被核学习到的特征不是完全独立的,有的特征可能属于频率,还有的属于形状,亮度等等,因此对特征进行分组处理是自然的思路,最后的结果也很好,与BN的效果相差无几,但对batch是无依赖的,适合小批量任务[2]。下图是BN与GN的对比效果。

 



==================================

 https://blog.csdn.net/Teeyohuang/article/details/103756624

 

4.0 根据集合S的不同的四种常见的 Normalization 方式

将输入的图像shape记为[N, C, H, W],根据选定的集合S的不同,即进行归整的神经元的选取方式的不同,有4种常见的Normalization方式如上,分别为 ,Batch Normalization(2015年)、Layer Normalization(2016年)、Instance Normalization(2017年)、Group Normalization(2018年)
4.1.1、 Batch Normalization

在batch方向上,对N H W做归一化

Batch Normalization 于2015年由 Google 提出,开 Normalization 之先河。

其规范化针对单个神经元进行,利用网络训练时一个 mini-batch 的数据来计算该神经元 x_i 的均值和方差,

因而称为 Batch Normalization。

这个图把四维[N, C, H, W]输入数据以三维的方式画出来了,即把空间维度 H,W融合成一个维度,看起来可能稍微有点不好理解,没关系,我们可以通过深色格子的数量来分析。

我们可以看到,N那个方向上,深色格子是取满了的,即对mini-batch的N个实例都考虑到了,而空间维度H,W(竖着的方向)也是全部取满了的,即对输入图像的H * W的所有像素点都考虑到了,唯独通道方向C只取了1个格子,

这就说明通道方向上,是分开的,每次只考虑1个通道。

 

举个例子,如果如果我们有8张大小为256*256的RGB彩色图片,组合一个batch,得到[8, 3, 256, 256 ] 进行Batch Norm操作, 那么具体来说就是:

统计8张图片的 R 通道上的像素点做归一化,即考虑范围为8*1*256*256个像素点;

统计8张图片的 G 通道上的像素点做归一化,即考虑范围为8*1*256*256个像素点;

统计8张图片的 B 通道上的像素点做归一化,即考虑范围为8*1*256*256个像素点;

这个图片可以看作正在对 8张图片(实例)的 R 通道上的 所有像素点做归一化

这就是所谓的对NHW做归一化,即分开通道而统计图像(Batch方向上)来统计像素点。

BN 比较适用的场景是:每个 mini-batch 比较大,数据分布比较接近。

在进行训练之前,要做好充分的 shuffle. 否则效果会差很多。
4.1.2、Batch Norm的四大罪状:

局限1:如果Batch Size太小,则BN效果明显下降。

实验表明当BatchSize小于8的时候开始对分类效果有明显负面影响。

局限2:对于有些像素级图片生成任务来说,BN效果不佳;

对于图片分类等任务,只要能够找出关键特征,就能正确分类,这算是一种粗粒度的任务,在这种情形下通常BN是有积极效果的。但是对于有些输入输出都是图片的像素级别图片生成任务,比如图片风格转换等应用场景,使用BN会带来负面效果,

这很可能是因为在Mini-Batch内多张无关的图片之间计算统计量,弱化了单张图片本身特有的一些细节信息。

 

局限3:RNN等动态网络使用BN效果不佳且使用起来不方便

对于RNN来说,尽管其结构看上去是个静态网络,但在实际运行展开时是个动态网络结构,因为输入的Sequence序列是不定长的,这源自同一个Mini-Batch中的训练实例有长有短。对于类似RNN这种动态网络结构,BN使用起来不方便,因为要应用BN,那么RNN的每个时间步需要维护各自的统计量,而Mini-Batch中的训练实例长短不一,这意味着RNN不同时间步的隐层会看到不同数量的输入数据,而这会给BN的正确使用带来问题。假设Mini-Batch中只有个别特别长的例子,那么对较深时间步深度的RNN网络隐层来说,其统计量不方便统计而且其统计有效性也非常值得怀疑。另外,如果在推理阶段遇到长度特别长的例子,也许根本在训练阶段都无法获得深层网络的统计量。综上,在RNN这种动态网络中使用BN很不方便,而且很多改进版本的BN应用在RNN效果也一般。

局限4:训练时和验证/测试时统计量不一致

对于BN来说,采用Mini-Batch内实例来计算统计量,这在训练时没有问题,但是在模型训练好之后,在线推理(online inference)的时候会有麻烦。因为在线推理或预测的时候,是单实例的,不存在Mini-Batch,所以就无法获得BN计算所需的均值和方差,一般解决方法是采用训练时刻记录的各个Mini-Batch的统计量的数学期望,以此来推算全局的均值和方差,在线推理时采用这样推导出的统计量。虽说实际使用并没大问题,但是确实存在训练和推理时刻统计量计算方法不一致的问题。

上面所列BN的四大罪状,表面看是四个问题,其实深入思考,都指向了幕后同一个黑手,这个隐藏在暗处的黑手是谁呢?就是BN要求计算统计量的时候必须在同一个Mini-Batch内的实例之间进行统计,因此形成了Batch内实例之间的相互依赖和影响的关系。如何从根本上解决这些问题?一个自然的想法是:把对Batch的依赖去掉,转换统计集合范围。在统计均值方差的时候,不依赖Batch内数据,只用当前处理的单个训练数据来获得均值方差的统计量,这样因为不再依赖Batch内其它训练数据,那么就不存在因为Batch约束导致的问题。在BN后的几乎所有改进模型都是在这个指导思想下进行的。

 

Pytorch 实现(2d情况):https://pytorch.org/docs/stable/nn.html#batchnorm2d

torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)

其中的参数 affine=True, 就是设置 对应的两个调节因子 γ 和 β,

track_running_stats=True, 就是在训练时 追踪 并统计各个batch的统计量(pytorch称之为:running_mean和running_var),如上面局限4谈到的

momentum=0.1 也是用于统计 running_mean 和 running_var 的一个指数衰减量
4.2、Layer Normalization

在通道方向上,对CHW归一化

我们可以看到,N那个方向上,深色格子是只取了1个,表示现在只考虑一个输入图像(实例),而空间维度H,W(竖着的方向)也是全部取满了的,即对输入图像的H*W的所有像素点都考虑到了,通道方向C现在是取满了的,这就说明通道方向上,是考虑了所有通道的。

仍然以我们的8张大小为256*256的RGB彩色图片,组合一个batch举例,得到[8, 3, 256, 256 ] 进行Layer Norm操作, 那么具体来说就是:

统计第1张图片的,R、G、B 3个通道上的像素点做归一化,即考虑范围为1*3*256*256个像素点;

统计第 i 张 图片······

统计第8张图片的,R、G、B 3个通道上的像素点做归一化,即考虑范围为1*3*256*256个像素点;

这张图片可以看作是正在对第一张图片的 R、G、B三个通道上的像素点做归一化

这就是所谓的对CHW做归一化,即分开图像(实例)而统计通道(Layer方向上)来统计像素点。

前文有述,BN在RNN中用起来很不方便,而Layer Normalization这种在同隐层内计算统计量,而不依赖batch size大小 的模式就比较符合RNN这种动态网络,目前在RNN中貌似也只有LayerNorm相对有效,但Layer Normalization目前看好像也只适合应用在RNN场景下,在CNN等环境下效果是不如BatchNorm或者GroupNorm等模型的。

Pytorch实现: https://pytorch.org/docs/stable/nn.html#layernorm,

torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True)

 
4.3、Instance Normalization

仅对HW做归一化,

我们可以看到,N那个方向上,深色格子是只取了1个,表示现在只考虑一个输入图像(实例),而空间维度H,W(竖着的方向)也是全部取满了的,即对输入图像的H*W的所有像素点都考虑到了,通道方向C现在是只取了1个的,这就说明通道方向上只是考虑了1个通道的。

仍然以我们的8张大小为256*256的RGB彩色图片,组合一个batch举例,得到[8, 3, 256, 256 ] 进行Layer Norm操作, 那么具体来说就是:

统计第1张图片的,R 通道上的像素点做归一化,即考虑范围为1*1*256*256个像素点;

统计第1张图片的,G 通道上的像素点做归一化,即考虑范围为1*1*256*256个像素点;

统计第1张图片的,B 通道上的像素点做归一化,即考虑范围为1*1*256*256个像素点;

 

后面依次统计第 i 张 图片······

 

这张图片可以看作是 在对第 i 张图片(实例)的 B 通道上的 所有像素点做归一化

这就是所谓的仅对HW做归一化

也就是既不像BatchNorm那样考虑一个batch内的多个实例,也不像Layer Norm那样考虑layer方向上的多个通道,它现在只限制在单个实例 单个通道上操作!

那么实际上,我们想一下卷积操作就会发现,这其实就是在对单个神经元的输出做归一化,因为单个神经元的卷积结果,就是 1个实例中的1个通道上的内容

图像风格化中,生成结果主要依赖于某个图像实例,所以对整个batch归一化不适合图像风格化中,因而对HW做归一化。可以加速模型收敛,并且保持每个图像实例之间的独立。所以很多GAN网络中其实比较喜欢用InstanceNorm来进行操作。

而且往往这些网络 BatchSize的大小是设置成1的,也就是每次都只有1个实例进行前传。那么这样可能会感觉到,如果把BatchNormalization中的BatchSize改为1,那岂不是就是InstanceNormlization了?

从数学运算上来看,二者应该是一样的,因为BatchSize等于1时,此时考虑的集合S范围内的神经元是一样的。

但是可能在深度学习框架中的具体实现会有差别。

 

比如在测试的时候,我们通常都是输入的单个样例,也就是BatchSize在测试阶段设置为1。

①如果训练阶段用的是BatchNorm,往往BatchSize都大于1,考虑的是一个batch内的实例的统计特性。所以在测试的时候,往往不计算测试集/验证集的单一输入实例的归一化参数,而是使用训练阶段保存下来的归一化参数:均值μ,标准差δ。

更进一步,我们在训练阶段使用BatchNorm的时候,每一个mini-Batch计算完归一化参数之后,会使用指数加权平均 来进行累加,通常会有一个momentum参数,默认值为0.1,即当前mini-batch的统计值占比0.1,加上历史积累的mini-batch的统计值占比0.9。所以最后训练完成后保存下来的模型中的 均值μ和 标准差δ 是对所有mini-batch的一个加权平均统计值,可以看作是照顾到了所有的训练集数据。

②如果训练阶段用的就是InstanceNorm,本身的BatchSize在训练时就是1,即只考虑当前输入实例的影响。那么在测试时,也就需要即时计算 测试集/验证集 的单一输入实例的归一化参数。并不使用训练阶段保存的归一化参数,而且训练阶段也不需要保存归一化参数,因为每个batch都是独立的。

Pytorch实现(2d情况):https://pytorch.org/docs/stable/nn.html#instancenorm2d

torch.nn.InstanceNorm2d(num_features, eps=1e-05, momentum=0.1, affine=False, rack_running_stats=False)

可以看到,pytorch实现时,affine=False,即不设置 两个调节因子 γ 和 β,

rack_running_stats=False, 也不追踪和统计 各个批次的统计量

也就是说,并不是单纯的把batchnorm2d的batchsize改成1就完全等价
4.4、Group Normalization

将channel分组,然后再做归一化

 

是Facebook何凯明研究组2017年提出的。这是一种介于前面的Layer Norm 和Instance Norm 之间的Norm操作,我们可以看到,batch方向上仍然只取1个,H*W方向上取满,通道方向上,C现在既不是取满(Layer Norm的操作),也不是只取1个通道(Instance Norm的操作),而是取了介于二者之间的几个通道。相当于把这几个通道分成了一组!

上面举彩色图片的例子这里稍微修改一下,假设我们在彩色图片后面再加两个通道,表示每个像素点的坐标,即现在每个像素点的值为(r, g, b, x, y),那么这时图像就是5个通道的图像了,所谓group norm, 可以理解为:

对某一张图片,我对其R,G,B 3个通道上的像素点做归一化,共有1*3*256*256个像素点;

然后我再对剩下的 X,Y 2个通道上的像素点做归一化,共1*2*256*256个像素点;

这就是所谓通道分组的概念,我这个例子中,我分组的依据是,R、G、B这3个通道是颜色信息,它们之间关系更大一些; 而后两个通道X,Y是表示位置信息的,它们关系要大一些,所以我这么分组。 这只是我这里举了个例子而已,为了说明通道分组的概念。

这张图片也阐述了通道分组的意思。

Pytorch实现:https://pytorch.org/docs/stable/nn.html#groupnorm

 torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)
5、第二类Normalization

上面讲的第一类,其实都是对神经元的输出进行规范化,只是选取的神经元的范围S不同,或者说选的经过卷积之后的特征图的数据的区域不同,其实这不同的区域就是对应着前面不同的神经元的输出。

这里讲另一种方式:

Weight Normalization —— 参数规范化, 则另辟蹊径,将规范化应用于线性变换函数的权重 w ,这就是 WN 名称的来源。

 

我浏览过很多写WN的文章,知乎上这篇文章我觉得是写的比较好的:https://zhuanlan.zhihu.com/p/55102378,里面的推导过程是比较详细的。

这里我就不重复了,而且我也觉得让我重新推导写出来也不会超过这篇文章,所以我这里就简单的说几个结论性内容:

具体而言,WN 提出的方案是,将权重向量 w 分解为 向量方向 v 和向量模 g 两部分。后使用SGD分别优化这两个参数。

WN也是和样本量无关的,所以可以应用在batchsize较小以及RNN等动态网络中;另外BN使用的基于mini-batch的归一化统计量代替全局统计量,相当于在梯度计算中引入了噪声。而WN则没有这个问题,所以在生成模型,强化学习等噪声敏感的环境中WN的效果也要优于BN。

WN没有一如额外参数,这样更节约显存。同时WN的计算效率也要优于要计算归一化统计量的BN。

Weight Normalization的优点:

更快的收敛速度;

更强的学习率鲁棒性;

可以应用在RNN等动态网络中;

对噪声更不敏感,更适用在GAN,RL等场景中

原文链接:https://blog.csdn.net/Teeyohuang/article/details/103756624

 

==================================

 什么使用要加规范化,什么时候要用规范化

 

 

==================================

torch.nn.LayerNorm

 

==================================

 

 

==================================

 

posted @ 2023-07-26 20:51  emanlee  阅读(29)  评论(0编辑  收藏  举报