机器学习中,模型最喜欢的数据就是服从独立同分布的数据(现实世界中几乎不存在)。“独立”是指各个特征相互独立,没有依赖关系;“同分布”是指各个特征服从相同的分布,常常是高斯分布。然而,我们从自然界中直接获取的数据往往与“独立同分布”相差甚远,使机器学习或深度学习模型难以拟合数据分布,因此人们提出normalization来缓解这一问题。
在深度学习中,数据的标准化(normalization)很常见,其目的是将数据按比例缩放,使之落入一个小的特定区间。
一般来说,normalization是指将初始数据集进行标准化。初始数据集中不同特征的数据分布一般都是不同的(例如房价分布在100000~10000000不等,房屋面积分布在10-500不等),如果不进行normalization,就可能导致神经网络过度甚至只关注值大的特征。常见的normalization有四种,如《opencv 读取图片 图片数据处理 笔记》一文的【2.3 归一化】
还有一个词standardization,一般是指将数据正态化,使平均值1方差为0. 因此normalization和standardization 是针对数据而言的,消除一些数值差异带来的特种重要性偏见。
设数据集形状为(N, C, H, W),normalization可以对所有数值一起进行标准化,也可以以C轴隔离(即C=1和C=2的数据分别标准化)。
MINMAX标准化:数值被平移缩放到一个指定的范围 [ α , β ] [\alpha,\beta] [α,β](常用[0,1]):
x i ′ = α + [ x i − m i n ( x ) ] × ( β − α ) m a x ( x ) − m i n ( x ) (1.1) x_{i}^{'}=\alpha + \frac{[x_{i}-min(x)]\times (\beta-\alpha)}{max(x)-min(x)} \tag{1.1} xi′=α+max(x)−min(x)[xi−min(x)]×(β−α)(1.1)
试想,数据在经过深度神经模型的某隐层之后,是否还保持着输入该隐层之前的数据分布?显然,难以避免会有细微的偏差。深度神经网络涉及到很多层的叠加,而每一层的参数更新会导致上层的输入数据分布发生变化,通过层层叠加,高层的输入分布变化会非常剧烈,这就使得高层需要不断去重新适应底层的参数更新。为了训好模型,我们被迫非常谨慎地去设定学习率、初始化权重、以及尽可能细致的参数更新策略。但当网络层数很大时,仍然无法训练得到泛化能力很好的网络模型。Google 将这一现象总结为 Internal Covariate Shift。
batch normalization很好地解决了这一问题。其思想是在每一层神经网络之后,对数据重新进行标准化(normalization),使数据分布恢复到尽量接近原分布。这里的“batch”是指模型在训练时,每次输入一个batch,只对这一个batch进行标准化。当然在具体实现时,也可以保留着以往batch的聚合值(均值和方差),从而尽可能地达到全局标准化。
顺便想到,网络层数过深时,往往也会引起梯度下降和梯度消失。
设每个batch的张量形状为(B, C, H, W),batch normalization将进行C次独立的标准化,每次标准化的数据为(B, H, W)。
μ i = 1 B H W ∑ t = 1 B ∑ j = 1 H ∑ k = 1 W x t i j k (2.1) \mu_i = \frac{1}{BHW} \sum_{t=1}^{B} \sum_{j=1}^{H} \sum_{k=1}^{W} x_{tijk} \tag{2.1} μi=BHW1t=1∑Bj=1∑Hk=1∑Wxtijk(2.1)
σ i 2 = 1 B H W ∑ t = 1 B ∑ j = 1 H ∑ k = 1 W ( x t i j k − μ i ) 2 (2.2) \sigma_i^2 = \frac{1}{BHW} \sum_{t=1}^{B} \sum_{j=1}^{H} \sum_{k=1}^{W} (x_{tijk} - \mu_i)^2 \tag{2.2} σi2=BHW1t=1∑Bj=1∑Hk=1∑W(xtijk−μi)2(2.2)
x t i j k ′ = γ i x t i j k − μ i σ i 2 + ϵ + β i (2.3) x^{\prime}_{tijk} = \gamma_i \frac{x_{tijk} - \mu_i}{\sqrt{\sigma_i^2 + \epsilon}} + \beta_i \tag{2.3} xtijk′=γiσi2+ϵxtijk−μi+βi(2.3)
t , i , j , k t,i,j,k t,i,j,k分别是(batch_size, C, H, W)这4个维度的下标。 μ i \mu_i μi, σ i 2 \sigma_i^2 σi2分别表示第 i i i个通道的均值和方差; γ i \gamma_i γi是可学习参数,表示数据缩放程度; β i \beta_i βi是可学习参数,表示偏移量。
batch normalization不适用于RNN等动态网络和batchsize较小的场景:
layer normalization的出现很好的解决了上述问题。layer normalization是对每个样本进行标准化,与batch的大小无关。
设每个batch的张量形状为(batch_size, C, H, W),layer normalization将进行batch_size次独立的标准化,每次标准化的数据为(C, H, W),也就是每个样本自己进行一次标准化。
μ t = 1 C H W ∑ i = 1 C ∑ j = 1 H ∑ k = 1 W x t i j k (3.1) \mu_t = \frac{1}{CHW} \sum_{i=1}^{C} \sum_{j=1}^{H} \sum_{k=1}^{W} x_{tijk} \tag{3.1} μt=CHW1i=1∑Cj=1∑Hk=1∑Wxtijk(3.1)
σ t 2 = 1 C H W ∑ i = 1 C ∑ j = 1 H ∑ k = 1 W ( x t i j k − μ t ) 2 (3.2) \sigma_t^2 = \frac{1}{CHW} \sum_{i=1}^{C} \sum_{j=1}^{H} \sum_{k=1}^{W} (x_{tijk} - \mu_t)^2 \tag{3.2} σt2=CHW1i=1∑Cj=1∑Hk=1∑W(xtijk−μt)2(3.2)
x t i j k ′ = γ t x t i j k − μ t σ t 2 + ϵ + β t (3.3) x^{\prime}_{tijk} = \gamma_t \frac{x_{tijk} - \mu_t}{\sqrt{\sigma_t^2 + \epsilon}} + \beta_t \tag{3.3} xtijk′=γtσt2+ϵxtijk−μt+βt(3.3)
t , i , j , k t,i,j,k t,i,j,k分别是(batch_size, C, H, W)这4个维度的下标。
作者指出在图像风格迁移任务中,生成式模型计算得到的 Feature Map 的各个 Channel 的均值与方差将影响到所生成图像的风格。故作者提出了 IN,在 Channel 层面对输入数据进行归一化,再使用目标图像的Channel 的均值与方差对结果进行 ‘去归一化’。一种更适合对单个像素有更高要求的场景的归一化算法(IST,GAN等)。
IN 与LN 类似,仅对单个样本进行归一化,但是 IN 并不进行仿射变换。
设每个batch的张量形状为(B, C, H, W),Instance Normalization将进行B×C次独立的标准化,每次标准化的数据为(H, W)。
μ t i = 1 H W ∑ j = 1 H ∑ k = 1 W x t i j k (4.1) \mu_{ti} = \frac{1}{HW} \sum_{j=1}^{H} \sum_{k=1}^{W} x_{tijk} \tag{4.1} μti=HW1j=1∑Hk=1∑Wxtijk(4.1)
σ t i 2 = 1 H W ∑ j = 1 H ∑ k = 1 W ( x t i j k − μ t i ) 2 (4.2) \sigma_{ti}^2 = \frac{1}{HW} \sum_{j=1}^{H} \sum_{k=1}^{W} (x_{tijk} - \mu_{ti})^2 \tag{4.2} σti2=HW1j=1∑Hk=1∑W(xtijk−μti)2(4.2)
x t i j k ′ = γ t i x t i j k − μ t i σ t i 2 + ϵ + β t i (4.3) x^{\prime}_{tijk} = \gamma_{ti} \frac{x_{tijk} - \mu_{ti}}{\sqrt{\sigma_{ti}^2 + \epsilon}} + \beta_{ti} \tag{4.3} xtijk′=γtiσti2+ϵxtijk−μti+βti(4.3)
t , i , j , k t,i,j,k t,i,j,k分别是(batch_size, C, H, W)这4个维度的下标。
GN的动机也是为了解决BN受限于batch size的问题。
可以直接看图理解与BN、LN、IN的区别,其实GN就相当于LN的拆分版、IN的组队版。(下图Layer Norm的所有蓝色格子就是一个样本)
BN 和 LN 均将规范化应用于输入的特征数据 x \mathbf{x} x ,而 WN 则另辟蹊径,对网络的参数进行标准化。
考虑普通的神经元 f ( x ) = w i ⋅ x f(\mathbf{x}) = \mathbf{w}_i \cdot \mathbf{x} f(x)=wi⋅x是两个向量的内积形式。分解 w i = g ⋅ v ^ = g ⋅ v ∥ v ∥ \mathbf{w}_i = g \cdot \hat{\mathbf{v}} = g \cdot \frac{\mathbf{v}}{\|\mathbf{v}\|} wi=g⋅v^=g⋅∥v∥v,标量 g g g表示 w i \mathbf{w}_i wi的模长, v ^ \hat{\mathbf{v}} v^表示与 w i \mathbf{w}_i wi同方向的单位向量。原先对参数 w i \mathbf{w}_i wi的优化转化为对参数 g g g和 v \mathbf{v} v的优化。
参考:Weight Normalization原理与使用
对输入数据 x \mathbf{x} x的变换已经做过了,横着来是 LN,纵着来是 BN。对模型参数 W \mathbf{W} W的变换也已经做过了,就是 WN。那还有什么可做的呢?大佬们盯上了神经网络运算过程中的内积计算,即 f ( x ) = w ⋅ x f(x)=\mathbf{w} \cdot \mathbf{x} f(x)=w⋅x中的“ ⋅ \cdot ⋅”。
在经过深层网络结构之后,可能数据分布的方差已经很大,从而内积计算的结果也会很大,进而导致梯度爆炸等一系列问题。IN的目的是将这个结果值标准化到一个特定的区间
考虑普通的神经元 f ( x ) = w i ⋅ x f(\mathbf{x}) = \mathbf{w}_i \cdot \mathbf{x} f(x)=wi⋅x,Cosine Normalization的做法是
f ( x ) = w i ⋅ x ∥ w i ∥ ⋅ ∥ x ∥ f(\mathbf{x}) = \frac{\mathbf{w}_i \cdot \mathbf{x}}{\|\mathbf{w}_i\| \cdot \|\mathbf{x}\|} f(x)=∥wi∥⋅∥x∥wi⋅x