-
BatchNorm 最早在全连接网络中被提出,对每个神经元的输入做归一化。扩展到 CNN 中,就是对每个卷积核的输入做归一化,或者说在 channel 之外的所有维度做归一化。 BN 带来的好处有很多,这里简单列举几个:
-
防止过拟合:单个样本的输出依赖于整个 mini-batch,防止对某个样本过拟合。
-
加快收敛:梯度下降过程中,每一层的权重矩阵W和偏置b都会不断变化,导致输出结果的分布在不断变化,后层网络就要不停地去适应这种分布变化。用 BN 后,可以使每一层输入的分布近似不变。
-
防止梯度弥散:forward 过程中,逐渐往非线性函数的取值区间的上下限两端靠近,(以 Sigmoid 为例),此时后面层的梯度变得非常小,不利于训练。
-
-
BN 的数学表达为:
-
y = x − E ( x ) D ( x ) + η ∗ γ + β y=\frac{x-E(x)}{\sqrt{D(x)+\eta}}*\gamma+\beta y=D(x)+ηx−E(x)∗γ+β
-
这里引入了缩放因子 γ \gamma γ和平移因子 β \beta β,作者在文章里解释了它们的作用:
-
Normalize 到 均值为0,方差为1, 会导致新的分布丧失从前层传递过来的特征与知识。
-
以 Sigmoid 为例,加入 γ \gamma γ, β \beta β , 可以防止大部分值落在近似线性的中间部分,导致无法利用非线性的部分。
-
-
BatchNorm 默认打开
track_running_stats
,因此每次 forward 时都会依据当前 minibatch 的统计量来更新running_mean
和running_var
。-
r u n n i n g _ m e a n = r u n n i n g _ m e a n ∗ ( 1 − m o m e n t u n ) + E ( x ) ∗ m o m e n t u n r u n n i n g _ v a r = r u n n i n g _ v a r ∗ ( 1 − m o m e n t u n ) + V a r ( x ) ∗ m o m e n t u n running\_mean=running\_mean*(1-momentun)+E(x)*momentun\\ running\_var=running\_var*(1-momentun)+Var(x)*momentun running_mean=running_mean∗(1−momentun)+E(x)∗momentunrunning_var=running_var∗(1−momentun)+Var(x)∗momentun
-
momentum
默认值为 0.1,控制历史统计量与当前 minibatch 在更新running_mean
、running_var
时的相对影响。
-
-
其中E(x),Var(x) 、 分别表示x的均值、方差;需要注意这里统计方差用了无偏估计。
-
running_var = running_var * (1 - momentum) + momentum * inputs_var * n / (n - 1) running_mean = running_mean * (1 - momentum) + momentum * inputs_mean
-
-
-
γ , β \gamma,\beta γ,β的更新
- BatchNorm 的
weight
,bias
分别对应公式里的 γ \gamma γ, β \beta β , 更新方式是梯度下降法。
- BatchNorm 的
-
在train和eval不同模式上,batchNorm会有不同:
- train 模式下统计
running_mean
和running_var
,eval 模式下用统计数据作为 μ \mu μ 和 δ \delta δ 。track_running_stats
默认为True
,极为训练模式,设置为False
时,eval模式直接计算输入的均值和方差。
- train 模式下统计
-
SyncBatchNorm
-
BN 的性能和 batch size 有很大的关系。batch size 越大,BN 的统计量也会越准。然而像检测这样的任务,占用显存较高,一张显卡往往只能拿较少的图片(比如 2 张)来训练,这就导致 BN 的表现变差。一个解决方式是 SyncBN:所有卡共享同一个 BN,得到全局的统计量。
-
单卡上的 BN 会计算该卡对应输入的均值、方差,然后做 Normalize;SyncBN 则需要得到全局的统计量,也就是“所有卡上的输入”对应的均值、方差。一个简单的想法是分两个步骤:
-
每张卡单独计算其均值,然后做一次同步,得到全局均值
-
用全局均值去算每张卡对应的方差,然后做一次同步,得到全局方差
-
-
但两次同步会消耗更多时间,事实上一次同步就可以实现 μ \mu μ 和 δ 2 \delta^2 δ2 的计算:
-
δ 2 = 1 m ∑ i = 1 m ( x i − μ ) 2 = 1 m ∑ i = 1 m ( x i 2 − 2 x i μ + μ 2 ) = ? 1 m ∑ i = 1 m x i 2 − μ 2 = 1 m ∑ i = 1 m x i 2 − ( 1 m ∑ i = 1 m x i ) 2 μ = 1 m ∑ i = 1 m x i , 而不是 μ = ∑ j = 1 n ∑ i = 1 m x i j 吗?( n 为节点个数, m 为每个节点的批量样本数) \delta^2=\frac{1}{m}\sum_{i=1}^m(x_i-\mu)^2=\frac{1}{m}\sum_{i=1}^m(x^2_i-2x_i\mu+\mu^2)=?\frac{1}{m}\sum_{i=1}^mx_i^2-\mu^2\\ =\frac{1}{m}\sum_{i=1}^mx_i^2-(\frac{1}{m}\sum_{i=1}^mx_i)^2\\ \mu=\frac{1}{m}\sum_{i=1}^mx_i,而不是 \mu=\sum_{j=1}^n\sum_{i=1}^mx_{ij}吗?(n为节点个数,m为每个节点的批量样本数) δ2=m1i=1∑m(xi−μ)2=m1i=1∑m(xi2−2xiμ+μ2)=?m1i=1∑mxi2−μ2=m1i=1∑mxi2−(m1i=1∑mxi)2μ=m1i=1∑mxi,而不是μ=j=1∑ni=1∑mxij吗?(n为节点个数,m为每个节点的批量样本数)
-
只需要在同步时算好 ∑ i = 1 m x i \sum_{i=1}^mx_i ∑i=1mxi 和 ∑ i = 1 m x i 2 \sum_{i=1}^mx_i^2 ∑i=1mxi2 即可。这里用一张图来描述这一过程。
-
-
-
BatchNorm、LayerNorm、InstanceNorm、GroupNorm、Weight Standardization
-
BatchNorm:batch方向做归一化,算NHW的均值,对小batchsize效果不好;BN主要缺点是对batchsize的大小比较敏感,由于每次计算均值和方差是在一个batch上,所以如果batchsize太小,则计算的均值、方差不足以代表整个数据分布;
-
LayerNorm:channel方向做归一化,算CHW的均值,主要对RNN,transformer作用明显;
-
InstanceNorm:一个channel内做归一化,算H*W的均值,用在风格化迁移;因为在图像风格化中,生成结果主要依赖于某个图像实例,所以对整个batch归一化不适合图像风格化中,因而对HW做归一化。可以加速模型收敛,并且保持每个图像实例之间的独立。
-
GroupNorm:将channel方向分group,然后每个group内做归一化,算(C//G)H*W的均值;这样与batchsize无关,不受其约束。将channel分组,然后再做归一化, 在batchsize<16的时候, 可以使用这种归一化。
-
SwitchableNorm:将BN、LN、IN结合,赋予权重,让网络自己去学习归一化层应该使用什么方法。
-
Weight Standardization:权重标准化,2019年约翰霍普金斯大学研究人员提出。
-
-
数据归一化是深度学习数据预处理非常关键的步骤,可以起到统一量纲,防止小数据被吞噬等作用。把所有数据都转化为[0,1]或者[-1,1]之间的数,其目的是取消各维数据间数量级差别,避免因为输入输出数据数量级差别较大而造成网络预测误差较大。
-
线性归一化:也称为最小-最大规范化、离散标准化,是对原始数据的线性变换,将数据值映射到[0,1]之间。离差标准化保留了原来数据中存在的关系,是消除量纲和数据取值范围影响的最简单方法。
-
x ′ = x − m i n ( x ) m a x ( x ) − m i n ( x ) x'=\frac{x-min(x)}{max(x)-min(x)} x′=max(x)−min(x)x−min(x)
- 比较适用在数值比较集中的情况。
-
零-均值规范化:也称标准差标准化,经过处理的数据的均值为0,标准差为1。转化公式为:
-
x ′ = x − μ δ x'=\frac{x-\mu}{\delta} x′=δx−μ
-
标准差分数可以回答这样一个问题:"给定数据距离其均值多少个标准差"的问题,在均值之上的数据会得到一个正的标准化分数,反之会得到一个负的标准化分数。
-
-
局部响应归一化
- 局部响应归一化LRN 是一种提高深度学习准确度的技术方法。LRN 一般是在激活、池化函数后的一种方法。该方法是由AlexNet网络提出,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。LRN层模仿了生物神经系统的“侧抑制”机制。
。该方法是由AlexNet网络提出,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。LRN层模仿了生物神经系统的“侧抑制”机制。
- 局部响应归一化LRN 是一种提高深度学习准确度的技术方法。LRN 一般是在激活、池化函数后的一种方法。该方法是由AlexNet网络提出,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。LRN层模仿了生物神经系统的“侧抑制”机制。