10. 批量归一化
对于 “Kaggle比赛:预测房价” 的场景,可以对输入数据做标准化处理,使得:
处理后的任意一个特征在数据集中所有样本上的均值为0、标准差为1。
标准化处理输入数据使各个特征的分布相近:这往往更容易训练出有效的模型。
通常来说,数据标准化预处理对于浅层模型就足够有效了。
随着模型训练的进行,当每层中参数更新时,靠近输出层的输出较难出现剧烈变化。
但对深层神经网络来说,即使输入数据已做标准化,训练中模型参数的更新依然很容易造成靠近输出层输出的剧烈变化。
这种计算数值的不稳定性通常导致难以训练出有效的深度模型。
批量归一化的提出正是为了应对深度模型训练的挑战。
在模型训练时,批量归一化利用小批量上的均值和标准差,不断调整神经网络中间输出,从而使整个神经网络在各层的中间输出的数值更稳定。
批量归一化和下一节将要介绍的残差网络为训练和设计深度模型提供了两类重要思路。
10.1 批量归一化层
10.1.1 对全连接层
对全连接层做批量归一化,通常,是将批量归一化层置于全连接层中的仿射变换和激活函数之间。
设全连接层的输入为 u \boldsymbol{u} u,权重参数和偏差参数分别为 W \boldsymbol{W} W和 b \boldsymbol{b} b,激活函数为 ϕ \phi ϕ,批量归一化的运算符为 B N \boldsymbol{BN} BN。那么,使用批量归一化的全连接层的输出为:
ϕ ( BN ( x ) ) \phi(\text{BN}(\boldsymbol{x})) ϕ(BN(x))
其中,批量归一化输入由
x
\boldsymbol{x}
x仿射变换得到:
x
=
W
u
+
b
\boldsymbol{x} = \boldsymbol{W\boldsymbol{u} + \boldsymbol{b}}
x=Wu+b
考虑一个由m个样本组成的小批量。
仿射变换的输出为一个新的小批量 B = { x ( 1 ) , … , x ( m ) } \mathcal{B} = \{\boldsymbol{x}^{(1)}, \ldots, \boldsymbol{x}^{(m)} \} B={x(1),…,x(m)},它们正是批量归一化层的输入。
对于小批量 B \mathcal{B} B中任意样本 x ( i ) ∈ R d , 1 ≤ i ≤ m \boldsymbol{x}^{(i)} \in \mathbb{R}^d, 1 \leq i \leq m x(i)∈Rd,1≤i≤m,批量归一化层的输出同样是 d \boldsymbol{d} d维向量:
y ( i ) = BN ( x ( i ) ) \boldsymbol{y}^{(i)} = \text{BN}(\boldsymbol{x}^{(i)}) y(i)=BN(x(i))
并由以下几步求得:
(1) 对小批量 B \mathcal{B} B求均值及方差:
μ B ← 1 m ∑ i = 1 m x ( i ) \boldsymbol{\mu}_\mathcal{B} \leftarrow \frac{1}{m}\sum_{i = 1}^{m} \boldsymbol{x}^{(i)} μB←m1i=1∑mx(i)
σ B 2 ← 1 m ∑ i = 1 m ( x ( i ) − μ B ) 2 \boldsymbol{\sigma}_\mathcal{B}^2 \leftarrow \frac{1}{m} \sum_{i=1}^{m}(\boldsymbol{x}^{(i)} - \boldsymbol{\mu}_\mathcal{B})^2 σB2←m1i=1∑m(x(i)−μB)2
其中,平方计算是按元素求平方。
(2) 使用按元素开方和按元素除法对 x ( i ) \boldsymbol{x}^{(i)} x(i)标准化: x ^ ( i ) ← x ( i ) − μ B σ B 2 + ϵ \hat{\boldsymbol{x}}^{(i)} \leftarrow \frac{\boldsymbol{x}^{(i)} - \boldsymbol{\mu}_\mathcal{B}}{\sqrt{\boldsymbol{\sigma}_\mathcal{B}^2 + \epsilon}} x^(i)←σB2+ϵx(i)−μB
这里 ϵ > 0 \epsilon > 0 ϵ>0是一个很小的常数,保证分母大于0。
(3) 在上面标准化的基础上,批量归一化层引入了两个可以学习的模型参数:
拉伸(scale)参数
γ
\boldsymbol{\gamma}
γ和偏移(shift)参数
β
\boldsymbol{\beta}
β。
这两个参数和 x ( i ) \boldsymbol{x}^{(i)} x(i)形状相同,皆为d维向量。它们与 x ^ ( i ) \hat{\boldsymbol{x}}^{(i)} x^(i)分别做按元素乘法(符号 ⊙ \odot ⊙)和加法计算: y ( i ) ← γ ⊙ x ^ ( i ) + β . {\boldsymbol{y}}^{(i)} \leftarrow \boldsymbol{\gamma} \odot \hat{\boldsymbol{x}}^{(i)} + \boldsymbol{\beta}. y(i)←γ⊙x^(i)+β.
至此,得到了 x ( i ) \boldsymbol{x}^{(i)} x(i)的批量归一化的输出 y ( i ) \boldsymbol{y}^{(i)} y(i)。
值得注意的是,可学习的拉伸和偏移参数保留了不对 x ( i ) \boldsymbol{x}^{(i)} x(i)做批量归一化的可能:此时只需学出 γ = σ B 2 + ϵ \boldsymbol{\gamma} = \sqrt{\boldsymbol{\sigma}_\mathcal{B}^2 + \epsilon} γ=σB2+ϵ和 β = μ B \boldsymbol{\beta} = \boldsymbol{\mu}_\mathcal{B} β=μB。
可以对此这样理解:
如果批量归一化无益,理论上,学出的模型可以不使用批量归一化。
10.1.2 对卷积层
对卷积层来说,批量归一化发生在卷积计算之后、应用激活函数之前。
如果卷积计算输出多个通道,需要对这些通道的输出分别做批量归一化,且每个通道都拥有独立的拉伸和偏移参数,并均为标量。
设小批量中有 m个样本。在单个通道上,假设卷积计算输出的高和宽分别为 p和 q ,需要对该通道中 m×p×q个元素同时做批量归一化。
对这些元素做标准化计算时,使用相同的均值和方差,即该通道中 m×p×q个元素的均值和方差。
10.1.3 预测时
使用批量归一化训练时,可以将批量大小设得大一点,从而使批量内样本的均值和方差的计算都较为准确。
将训练好的模型用于预测时,希望模型对于任意输入都有确定的输出。
因此,单个样本的输出不应取决于批量归一化所需要的随机小批量中的均值和方差。
一种常用的方法是:
通过移动平均估算整个训练数据集的样本均值和方差,并在预测时使用它们得到确定的输出。
10.2 代码实现
见 tf.keras.layers.BatchNormalization
的使用