Batch Normalization 原理
1. Batch Normalization的提处背景
1.1 常见的帮助收敛的方法
在深度学习中,随着网络层数的加深,模型的收敛难度会越来越大。为了让模型更好的收敛,涌现出了各种各样的调参方法:
- 基于随机梯度下降的各种优化算法,即各种优化器
- SGD、Adgrad、Adadelta、Adam…
- 参数初始化方法
- 全零初始化、随机初始化、Xavier初始化、He初始化、预训练模型
1.2 收敛困难的原因
为什么随着网络层数的增加,网络会越来越难收敛呢?
假定:网络的输入层为网络的底层,输出层为网络的顶层
网络的层与层之间都是高度耦合相关的。反向传播中,网络中的参数随着梯度下降不断进行更新。误差从网络的输出层即顶层,逐层收集反向传播到底层。参数就这样在层与层之间进行更新。
- 在前向传播中,当底层网络中的参数发生微弱变化时,权重在网络间经过线性变化,再经过非线性的激活映射,微弱的变化随着网路的加深不断的被放大
- 在反向传播中,误差从输出层不断的向输入层进行更新,每一次更新都会调整网络中每一层的数据分布
综上,模型的训练变得越来越困难,这种现象叫做Internal Covariate Shift. 即内部数据分布方差发生移位。
1.3 Internal Covariate Shift
Internal Covariate Shift是Bath Normalization的原论文作者提出的一个概念,ICS的定义为:在深层网络的训练过程中,由于网络中参数变化而引起的内部数据分布变化的这种现象叫做内部方差偏移(Internl Covariate Shift)
以一个简单的三层网络为示例
在该网路进行反向传播的过程中, w h j , w i h w_{hj},w_{ih} whj,wih都会被更新,那么这样就意味着每一层的线性变化 n e t j k , n e t h k net_j^k,net_h^k netjk,nethk分布就会发生变化,进而经过激活函数的 y h k , z j k y_h^k, z_j^k yhk,zjk 的分布也会发生改变。前一层的输出结果发生变化,则网络后一层需要根据前一层的输入分布变化而进行变化。这种不断适应网络层中输入参数数据分布变化的过程叫做Internal Covariate Shift.
Internal Covariate Shift带来的影响:
- 上层网络,即靠近输出层的网络要不断调整来适应输入数据分布变化,导致网络学习速度下降
- 网络的训练过程容易陷入梯度饱和,减缓网络收敛速度
- 当激活函数采用类似sigmod(.)这类的饱和激活函数的时候,模型容易陷入梯度饱和区。即模型训练的过程中,参数 w h j , w i h w_{hj},w_{ih} whj,wih都会逐渐更新变大,相应的每一层线性变化 n e t j k , n e t h k net_j^k, net_h^k netjk,nethk也会变大,并且如果网络越深,线性变化层net的值就会越大。(在上述三层网络中 n e t j k > n e t h k net_j^k > net_h^k netjk>nethk) 。所以层数越深,激活层就越容易接近饱和区。这样在反向传播的过曾中,相邻两层的梯度就接近与0,这样参数的更新速度就会减慢,进而放慢网络的收敛速度。
- 所以对于陷入梯度饱和的问题,可以采用ReLU这类非饱和的函数作为激活函数。一定程度上可以缓解训练进入梯度饱和的状况。
解决梯度饱和的另一种思路就是将每一层线性层的输出,即激活函数的输入进Normalization,让输入数据分布在一个稳定的状态,且该状态能尽可能的避免陷入梯度饱和区。
1.4 缓解Internal Covariate Shift的方法
通过上述分析我们可以发现,ICS产生的原因为参数更新所带来的网络中每一层参数数据分布发生变化,并且随着网络层数的增加,数据分布变化越严重。
缓解方法1:白化
白化 (Whitening) 是机器学习里面常用的一种规范化数据分布的方法,主要有PCA白化和ZCA白化。
其实白化的目的就是让输入数据具有相同的特征分布、并去除特征之间的相关性
PCA白化:经过PCA白化之后,数据各维度的方差为1
通过PCA将数据X降维以后得到Z, 此时Z中的每一维数据都是独立的(去相关),这时再除Z中每一维对应的方差,得到每一维方差均为1。如果k<n,就是PCA降维,如果k=n,则降低特征间相关性。这里k是指PCA处理过后的特征数。
ZCA白化:经过ZCA白化之后数据各微蹙的方差相同
X Z C A w h i t e = U X P C A w h i t e X_{ZCA_{white}} = UX_{PCA_{white}} XZCAwhite=UXPCAwhite
ZCA白化只是再PCA白化的基础上做了一个旋转操作,使得白化后的数据更接近原始数据。
缓解方法2: Batch Normalization的提处
白化是可以解决数据分布变化的问题,但是白化的缺点也异常明显:
- 白化的计算成本过高
- 白化过程由于改变了网络的每一层分布,因而改变了网络层本身数据的表达能力。越靠近输入层的网络学习到的信息会被白化操作丢失掉
因此根据上述两个问题,提出了normalization的方法,简化白化的过程,并且还要保证规范后的数据能尽可能的保留原始的数据表达能力。Batch Normlization 就是简化后改进的白化操作。
2.Batch Normalization
2.1 白化操作的计算过程
以PCA过程为例:
- 特征中心化:每一维的数据减去该维的均值,每一维代表一个特征
- 求特征的协方差矩阵
- 计算协方差矩阵的特征值和特征向量,特征向量需要归一化
- 将特征值按照从大到小进行排序,选择其中最大的k个,将其对应的k个特征向量分别作为列向量,组成新的特征向量矩阵。
- 将样本点投影到选取的特征向量上,这样就将原始样例的n维特征变为k维,这k维就是原始特征再k维上的投影
2.2 Batch Normalization思路
-
白化计算复杂
因为白化的计算过于复杂,需要计算特征值和特征向量,而实际上我们想要的核心是数据分布尽可能少的变化。那么可以简化为尝试对每一个单独的特征进行normalization,让每一个特征都有均值为0,方差为1的分布即可
-
白化操作减弱了网络中每一层输入数据的表达能力
通过加入线性变化操作,让数据尽可能的恢复本身的表达能力
-
深度学习数据量大
在深度学习中如果一次加载所有的数据,即full batch进行训练,对显卡的显存要求即高。且每一轮的训练时间会过长。所以一般在训练不哦城中会对数据进行划分,一小批一小批的进行训练,即采用mini-btach的方式进行训练。所以Batch Normalization也是在mini-batch的基础上进行的
2.3 Batch Normalization计算过程
参数定义,定义网络总共有L层(不包含输入层),并定义如下符号:
- l l l: 网络中的层标号
- L L L: 网络中的最后一层,或者是总层数
- d l d_l dl:第 l l l层的维度,即神经元的结点数
- W [ l ] W^{[l]} W[l]: 第 l l l层的权值矩阵, W [ l ] ∈ R d l × d l − 1 W^{[l]}\in \mathbb{R}^{d_l\times d_{l-1}} W[l]∈Rdl×dl−1
- b [ l ] b^{[l]} b[l]: 第 l l l层的偏置向量, b [ l ] ∈ R d l × 1 b^{[l]}\in \mathbb{R}^{d_l\times 1} b[l]∈Rdl×1
- Z [ l ] : Z^{[l]}: Z[l]: 第 l l l 层的线性计算结果, Z [ l ] = W [ l ] × \quad Z^{[l]}=W^{[l]} \times Z[l]=W[l]× input + b [ l ] +b^{[l]} +b[l]
- g [ l ] ( ⋅ ) : g^{[l]}(\cdot): g[l](⋅): 第 l l l 层的激活函数
- A [ l ] : A^{[l]}: A[l]: 第 l l l 层的非线性激活结果, A [ l ] = g [ l ] ( Z [ l ] ) \quad A^{[l]}=g^{[l]}\left(Z^{[l]}\right) A[l]=g[l](Z[l])
样本相关:
- M : M : M: 训练样本的数量
- N : N: N: 训练样本的特征数
-
X
:
X:
X: 训练样本集,
X
=
{
x
(
1
)
,
x
(
2
)
,
⋯
,
x
(
M
)
}
,
X
∈
R
N
×
M
\quad X=\left\{x^{(1)}, x^{(2)}, \cdots, x^{(M)}\right\}, \quad X \in \mathbb{R}^{N \times M} \quad
X={x(1),x(2),⋯,x(M)},X∈RN×M (注意这里
X
X
X 的一列
是一个样本) - m : m: m: batch size, 即每个batch中样本的数量
-
χ
(
i
)
:
\chi^{(i)}:
χ(i): 第
i
i
i 个mini-batch的训练数据,
X
=
{
χ
(
1
)
,
χ
(
2
)
,
⋯
,
χ
(
k
)
}
,
\quad X=\left\{\chi^{(1)}, \chi^{(2)}, \cdots, \chi^{(k)}\right\},
X={χ(1),χ(2),⋯,χ(k)}, 其中
χ ( i ) ∈ R N × m \chi^{(i)} \in \mathbb{R}^{N \times m} χ(i)∈RN×m
算法步骤:
介绍算法思路沿袭前面BN提出的思路来讲。第一点, 对每个特征进行独立的normalization。我们考虑一个batch的训练, 传入m个训练样本,并关注网络中的某一层, 忽略上标
l
l
l 。
Z
∈
R
d
l
×
m
Z \in \mathbb{R}^{d_{l} \times m}
Z∈Rdl×m
我们关注当前层的第
j
j
j 个维度, 也就是第
j
j
j 个神经元结点, 则有
Z
j
∈
R
1
×
m
Z_{j} \in \mathbb{R}^{1 \times m}
Zj∈R1×m 。我们当前维度进行规范化::
μ
j
=
1
m
∑
i
=
1
m
Z
j
(
i
)
σ
j
2
=
1
m
∑
i
=
1
m
(
Z
j
(
i
)
−
μ
j
)
2
Z
^
j
=
Z
j
−
μ
j
σ
j
2
+
ϵ
\begin{array}{l} \mu_{j}=\frac{1}{m} \sum_{i=1}^{m} Z_{j}^{(i)} \\ \sigma_{j}^{2}=\frac{1}{m} \sum_{i=1}^{m}\left(Z_{j}^{(i)}-\mu_{j}\right)^{2} \\ \hat{Z}_{j}=\frac{Z_{j}-\mu_{j}}{\sqrt{\sigma_{j}^{2}+\epsilon}} \end{array}
μj=m1∑i=1mZj(i)σj2=m1∑i=1m(Zj(i)−μj)2Z^j=σj2+ϵZj−μj
其中 ϵ \epsilon ϵ 是为了防止方差为0产生无效计算。
下面再来结合个具体的例子来进行计算。下图我们只关注第
l
l
l 层的计算结果, 左边的矩阵是
Z
[
l
]
=
W
[
l
]
A
[
l
−
1
]
+
b
[
l
]
Z^{[l]}=W^{[l]} A^{[l-1]}+b^{[l]}
Z[l]=W[l]A[l−1]+b[l] 线性计算结果, 还未进行激活函数的非线性变换。此时每一列是一个 样本,图中可以着到共有8列, 代表当前训练样本的batch中共有8个样本,每一行代表当前
l
l
l 层 神经元的一个节点, 可以車到当前
l
l
l 层共有4个神经元结点, 即第
l
l
l 层维度为4。我们可以看到, 每行的数据分布都不同。
【直接借用了他人博客图】
对于第一个神经元,
[
1
,
1.5
,
1.2
,
0.9
,
1.7
,
2.1
,
3.1
,
1.7
]
[1,1.5,1.2,0.9,1.7,2.1,3.1,1.7]
[1,1.5,1.2,0.9,1.7,2.1,3.1,1.7]可以求得
μ
1
=
1.65
,
σ
1
2
=
0.44
,
其中
ϵ
=
1
0
−
8
\mu_1=1.65,\sigma_1^2=0.44,\text{其中}\epsilon=10^{-8}
μ1=1.65,σ12=0.44,其中ϵ=10−8,此时利用
μ
1
,
s
i
g
m
a
1
2
\mu_1,sigma_1^2
μ1,sigma12对第一行数据,即第一个维度进行normalization得到新的值
[
−
0.98
,
−
0.23
,
−
0.68
,
−
.
1.13
,
0.08
,
0.68
,
2.19
,
0.08
]
[-0.98,-0.23,-0.68,-.1.13,0.08,0.68,2.19,0.08]
[−0.98,−0.23,−0.68,−.1.13,0.08,0.68,2.19,0.08],同理我们可以计算其他输入维度归一化后的结果。得到如下图:
【直接借用了他人博客图】
通过上述变化,解决了第一个问题,即让输入数据的分布值均值为0,方差为1.但是这样虽然缓解了ICS问题,但是却导致了数据表达能力的丧失。所以此时需要引入两个可以学习的参数
γ
,
β
\gamma,\beta
γ,β。这两个参数的引入是为了恢复数据本身的表达能力对规范后的数据进行线性变化,即:
Z
^
j
=
γ
j
Z
j
+
β
j
\hat Z_j = \gamma_jZ_j+\beta_j
Z^j=γjZj+βj
根据公式$\hat{Z}{j}=\frac{Z{j}-\mu_{j}}{\sqrt{\sigma_{j}^{2}+\epsilon}}
$ 可知,当
γ
2
=
σ
2
,
β
=
μ
\gamma^2 = \sigma^2, \beta = \mu
γ2=σ2,β=μ的时候可以实现等价变换,保留原始输入特征的分布信息。
**通过上面的步骤,我们就在一定程度上保证了输入数据的表达能力。**以上就是整个Batch Normalization在模型训练中的算法和思路。
2.3.1 计算过程总结
所以综上,所有的计算过程公式如下:
对于神经网络中的第 l l l 层, 我们有:
-
Z [ l ] = W [ l ] A [ l − 1 ] + b [ l ] Z^{[l]}=W^{[l]} A^{[l-1]}+b^{[l]} Z[l]=W[l]A[l−1]+b[l]
-
μ = 1 m ∑ i = 1 m Z [ l ] ( i ) \mu=\frac{1}{m} \sum_{i=1}^{m} Z^{[l](i)} μ=m1∑i=1mZ[l](i)
-
σ 2 = 1 m ∑ i = 1 m ( Z [ l ] ( i ) − μ ) 2 \sigma^{2}=\frac{1}{m} \sum_{i=1}^{m}\left(Z^{[l](i)}-\mu\right)^{2} σ2=m1∑i=1m(Z[l](i)−μ)2
-
Z ~ [ l ] = γ ⋅ Z [ l ] − μ σ 2 + ϵ + β \tilde{Z}^{[l]}=\gamma \cdot \frac{Z^{[l]}-\mu}{\sqrt{\sigma^{2}+\epsilon}}+\beta Z~[l]=γ⋅σ2+ϵZ[l]−μ+β
-
A [ l ] = g [ l ] ( Z ~ [ l ] ) A^{[l]}=g^{[l]}\left(\tilde{Z}^{[l]}\right) A[l]=g[l](Z~[l])
2.3.2 测试过程中的BN
在预测阶段,我们都是预测少量甚至一个样本,不可能像训练数据那样有那么多的样本数。此时 μ , σ 2 \mu,\sigma^2 μ,σ2的计算一定是一个有偏估计。因此我们在利用BN训练模型后,会保留每组mini-batch训练数据在网络中每一层的 μ b a t c h , σ b a t c h 2 \mu_{batch},\sigma^2_{batch} μbatch,σbatch2。这样我们在测试的时候使用均值与方差的无偏估计来作为 μ t e s t , σ t e s t 2 \mu_{test},\sigma^2_{test} μtest,σtest2:
- μ t e s t = E ( μ b a t c h ) \mu_{test} = E(\mu_{batch}) μtest=E(μbatch)
- σ t e s t 2 = m m − 1 E ( σ b a t c h 2 ) \sigma_{test}^2 = \frac{m}{m-1}E{(\sigma^2_{batch})} σtest2=m−1mE(σbatch2)
那么对于test数据采用BN计算如下:
B
N
(
X
t
e
s
t
)
=
γ
⋅
X
t
e
s
t
−
μ
t
e
s
s
t
σ
t
e
s
t
2
+
ϵ
+
β
BN(X_{test})=\gamma\cdot \frac{X_{test}-\mu_{tesst}}{\sqrt{\sigma^2_{test}+\epsilon}}+\beta
BN(Xtest)=γ⋅σtest2+ϵXtest−μtesst+β
另外,除了采用整体样本的无偏估计外。
在吴恩达在Coursera上的Deep Learning课程指出可以对train阶段每个batch计算mean/variance采用指数加权平均来得到test阶段mean/variance的估计。
三、参考资料
https://zhuanlan.zhihu.com/p/34879333
https://www.cnblogs.com/guoyaohua/p/8724433.html