本文只用作记录(摘抄),建议看参考原文,详细得多!
机器学习领域有个很重要的假设:IID独立同分布假设,就是假设训练数据和测试数据是满足相同分布的,这是通过训练数据获得的模型能够在测试集获得好的效果的一个基本保障。那BatchNorm的作用是什么呢?BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。
Internal Covariate Shift(ICS)
对于深度学习这种包含很多隐层的网络结构,在训练过程中,因为各层参数不停在变化,所以每个隐层都会面临covariate shift的问题,也就是在训练过程中,隐层的输入分布老是变来变去,这就是所谓的“Internal Covariate Shift”,Internal指的是深层网络的隐层,是发生在网络内部的事情,而不是covariate shift问题只发生在输入层。
理解:
定义每一层的线性变换为
Z
[
l
]
=
W
[
l
]
×
i
n
p
u
t
+
b
[
l
]
,
Z^{[l]}=W^{[l]} \times i n p u t+b^{[l]},
Z[l]=W[l]×input+b[l], 其中
l
l
l 代表层数
;
;
; 非线性变换为
A
[
l
]
=
g
[
l
]
(
Z
[
l
]
)
,
A^{[l]}=g^{[l]}\left(Z^{[l]}\right),
A[l]=g[l](Z[l]), 其中
g
[
l
]
(
⋅
)
g^{[l]}(\cdot)
g[l](⋅) 为第
l
l
l层的激活函数。随着梯度下降的进行,每一层的参数
W
[
l
]
W^{[l]}
W[l]与
b
[
l
]
b^{[l]}
b[l] 都会被更新,那么
Z
[
l
]
Z^{[l]}
Z[l] 的分布也就发生了改 变,进而
A
[
l
]
A^{[l]}
A[l] 也同样出现分布的改变。而
A
[
l
]
A^{[l]}
A[l] 作为第
l
+
1
l+1
l+1 层的输入,意味着
l
+
1
l+1
l+1 层就需要去 不停适应这种数据分布的变化,这一过程就被叫做Internal Covariate Shift。
进而使得每一层的线性与非线性计算结果分布产生变化。后层网络就要不停地去适应这种分布变化,这个时候就会使得整个网络的学习速率过慢。
对于激活函数梯度饱和问题,有两种解决思路。第一种就是更为非饱和性激活函数,例如线性整流函数ReLU可以在一定程度上解决训练进入梯度饱和区的问题。另一种思路是,我们可以让激活函数的输入分布保持在一个稳定状态来尽可能避免它们陷入梯度饱和区,这也就是Normalization的思路。
早期解决ICS: Whiten
之前的研究表明如果在图像处理中对输入图像进行白化(Whiten)操作的话——所谓白化,就是对输入数据分布变换到0均值,单位方差的正态分布。
图像是深度神经网络的输入层,做白化能加快收敛,那么其实对于深度网络来说,其中某个隐层的神经元是下一层的输入,意思是其实深度神经网络的每一个隐层都是输入层,不过是相对下一层来说而已,那么能不能对每个隐层都做白化呢?
对每层进行白化缺点:
白化过程计算成本太高
白化过程由于改变了网络每一层的分布
既然有了上面两个问题,那我们的解决思路就很简单,一方面,我们提出的normalization方法要能够简化计算过程;另一方面又需要经过规范化处理后让数据尽可能保留原始的表达能力。于是就有了简化+改进版的白化——Batch Normalization。
Z-Score标准化
零-均值规范化也称标准差标准化,经过处理的数据的均值为0,标准差为1。转化公式为:
x ∗ = x − x ˉ σ x^{*}=\frac{x-\bar{x}}{\sigma} x∗=σx−xˉ
其中 x ˉ \bar{x} xˉ为原始数据的均值, σ \sigma σ为原始数据的标准差,是当前用得最多的数据标准化方式。标准差分数可以回答这样一个问题:"给定数据距离其均值多少个标准差"的问题,在均值之上的数据会得到一个正的标准化分数,反之会得到一个负的标准化分数。
Batch Normalization
首先BatchNorm是基于Mini-Batch SGD:Mini-Batch SGD笔记
问题1:既然白化计算过程比较复杂,那我们就简化一点,比如我们可以尝试单独对每个特征进行normalizaiton就可以了,让每个特征都有均值为0,方差为1的分布就OK。
问题2:既然白化操作减弱了网络中每一层输入数据表达能力,那我就再加个线性变换操作,让这些数据再能够尽可能恢复本身的表达能力就好了。
问题1
结合Z-Score公式理解下面式子:
μ 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产生无效计算。
每个字母代表具体含义看原文章。
何谓让每个特征都有均值为0,方差为1的分布:
每个特征指的是下面横着的每一行,其中batch = 8
更新后:
通过上面的变换,我们解决了第一个问题,即用更加简化的方式来对数据进行规范化,使得第 [公式] 层的输入每个特征的分布均值为0,方差为1。
问题2
因此,BN又引入了两个可学习(learnable)的参数 \gamma 与 β \beta β 。这两个参数的引入是为了恢复数据 本身的表达能力,对规范化后的数据进行线性变换,即 Z ~ j = γ j Z ^ j + β j \tilde{Z}_{j}=\gamma_{j} \hat{Z}_{j}+\beta_{j} Z~j=γjZ^j+βj 。特别地,当 γ 2 = σ 2 , β = μ \gamma^{2}=\sigma^{2}, \beta=\mu γ2=σ2,β=μ 时,可以实现等价变换(identity transform) 并且保留了原始输入特征的分布信 息。
测试阶段使用Batch Normalization
利用BN训练好模型后,我们保留了每组mini-batch训练数据在网络中每一层的
μ
batch
\mu_{\text {batch }}
μbatch 与
σ
batch
2
\sigma_{\text {batch }}^{2}
σbatch 2 。
对Test数据进行归一化,具体来说使用均值与方差的无偏估计:
μ test = E ( μ batch ) σ test 2 = m m − 1 E ( σ batch 2 ) \begin{array}{l} \mu_{\text {test}}=\mathbb{E}\left(\mu_{\text {batch}}\right) \\ \sigma_{\text {test}}^{2}=\frac{m}{m-1} \mathbb{E}\left(\sigma_{\text {batch}}^{2}\right) \end{array} μtest=E(μbatch)σtest2=m−1mE(σbatch2)
得到每个特征的均值与方差的无偏估计后,我们对test数据采用同样的normalization方法:
B
N
(
X
test
)
=
γ
⋅
X
test
−
μ
test
σ
test
2
+
ϵ
+
β
B N\left(X_{\text {test}}\right)=\gamma \cdot \frac{X_{\text {test}}-\mu_{\text {test}}}{\sqrt{\sigma_{\text {test}}^{2}+\epsilon}}+\beta
BN(Xtest)=γ⋅σtest2+ϵXtest−μtest+β
BatchNorm的好处
BatchNorm为什么NB呢,关键还是效果好。①不仅仅极大提升了训练速度,收敛过程大大加快;②还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果;③另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等。总而言之,经过这么简单的变换,带来的好处多得很,这也是为何现在BN这么快流行起来的原因。
参考
Batch Normalization原理与实战 强烈推荐看这篇文章
【深度学习】深入理解Batch Normalization批标准化
数据规范化(归一化)、及Z-score标准化