文章目录
白化的不足[1][2]
【机器学习】最小最大值归一化,标准化,PCA白化,ZCA白化
白化能够去除数据特征之前的相关性并标准化数据。如果网络模型的输入经过白化,网络训练的会收敛得更快。对于多层神经网络,能否在每层都使用PCA白化处理呢?
这不行得通。因为白化需要计算协方差矩阵、矩阵分解等操作,计算量会很大。另外,在反向传播时,白化的操作不一定可微。
对于多层神经网络,可以使用批量标准化(Batch Normalization,BN)算法进行标准化。
BN算法
BN算法将传统机器学习中的数据标准化方法应用到深度神经网络中,对神经网络中隐藏层的输出进行标准化,从而使得网络训练准确率更高,训练更快。
深度线性网络对Mnist数据集分类,使用BN前后效果对比:
图片来源:[2]
深度卷积网络(inception网络)对ImageNet数据集分类,使用BN前后效果对比:
图片来源:[2]
BN的训练[3][4]
数据经过白化预处理后,满足两个条件:
a、特征之间的相关性降低;
b、数据被标准化,也就是使得每一维特征均值为0,标准差为1。
为了简化计算,BN算法忽略了第1个要求,仅仅使用了下面的公式进行近似白化处理:
(1)计算小批量均值:
μ
B
←
1
m
∑
i
=
1
m
x
i
\mu_{\mathcal{B}} \leftarrow \frac{1}{m} \sum_{i=1}^{m} x_{i}
μB←m1i=1∑mxi
(2)计算小批量方差:
σ
B
2
←
1
m
∑
i
=
1
m
(
x
i
−
μ
B
)
2
\sigma_{\mathcal{B}}^{2} \leftarrow \frac{1}{m} \sum_{i=1}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)^{2}
σB2←m1i=1∑m(xi−μB)2
(3) 标准化
x ^ i ← x i − μ B σ B 2 + ϵ \widehat{x}_{i} \leftarrow \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} x i←σB2+ϵxi−μB
需要注意的是,神经网络的训练大多采用小批量随机梯度下降,所以上面的均值和方差指的是一批训练数据的均值和方差。
x i − μ B σ B 2 + ϵ \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} σB2+ϵxi−μB这种强制转化可能会导致数据的分布发生破坏,因此还需要进行仿射变换。
(4) 仿射变换
y
i
←
γ
x
^
i
+
β
≡
B
N
γ
,
β
(
x
i
)
y_{i} \leftarrow \gamma \widehat{x}_{i}+\beta \equiv \mathrm{BN}_{\gamma, \beta}\left(x_{i}\right)
yi←γx
i+β≡BNγ,β(xi)
仿射变换就是在标准化的公式的基础之上使用两个参数
γ
、
β
γ、β
γ、β进行缩放和偏移。这样在训练过程中就可以反向传播学习这两个参数,调整分布。
全连接层的BN[5]
对于全连接层,加入BN算法前后如图所示:
加入前 | 加入后 |
---|---|
图片来源:[11] |
举个例子:
设一全连接网络训练时一个批次有 m m m个样本: x 1 , x 2 , . . . x m x_1,x_2,...x_m x1,x2,...xm。
对于样本 x 1 x_1 x1,全连接层的输出:
Y 1 = W x 1 Y_1=Wx_1 Y1=Wx1
其中第
k
k
k个神经元输出值为:
y
1
(
k
)
=
Y
1
[
k
]
y_1^{(k)}=Y_1[k]
y1(k)=Y1[k]
进行标准化:
y
^
1
(
k
)
=
y
1
(
k
)
−
E
[
y
(
k
)
]
Var
[
y
(
k
)
]
\widehat{y}_1^{(k)}=\frac{y_1^{(k)}-\mathrm{E}\left[y^{(k)}\right]}{\sqrt{\operatorname{Var}\left[y^{(k)}\right]}}
y
1(k)=Var[y(k)]y1(k)−E[y(k)]
E
[
y
(
k
)
]
\mathrm{E}\left[y^{(k)}\right]
E[y(k)],
Var
[
y
(
k
)
]
{\sqrt{\operatorname{Var}\left[y^{(k)}\right]}}
Var[y(k)]分别指的是一批训练数据,第
k
k
k个神经元输出值(
y
1
(
k
)
{y}_1^{(k)}
y1(k),
y
2
(
k
)
{y}_2^{(k)}
y2(k)…
y
m
(
k
)
{y}_m^{(k)}
ym(k))的平均值和标准差。
然后进行仿射变换:
z
1
(
k
)
=
γ
(
k
)
y
^
1
(
k
)
+
β
(
k
)
=
γ
(
k
)
y
1
(
k
)
−
E
[
y
(
k
)
]
Var
[
y
(
k
)
]
+
β
(
k
)
z_1^{(k)}=\gamma^{(k)} \widehat{y}_1^{(k)}+\beta^{(k)}\\ =\gamma^{(k)} \frac{y_1^{(k)}-\mathrm{E}\left[y^{(k)}\right]}{\sqrt{\operatorname{Var}\left[y^{(k)}\right]}}+\beta^{(k)}
z1(k)=γ(k)y
1(k)+β(k)=γ(k)Var[y(k)]y1(k)−E[y(k)]+β(k)
每一个神经元都会有一对这样的参数
γ
、
β
γ、β
γ、β,即
γ
、
β
γ、β
γ、β与神经元个数相等。
还可以注意到,当: β ( k ) = E [ y 1 ( k ) ] \beta^{(k)}=\mathrm{E}\left[y_1^{(k)}\right] β(k)=E[y1(k)], γ ( k ) − = Var [ y 1 ( k ) ] \gamma^{(k)^{-}}=\sqrt{\operatorname{Var}\left[y_1^{(k)}\right]} γ(k)−=Var[y1(k)]时, z 1 ( k ) = y 1 ( k ) z_1^{(k)}=y_1^{(k)} z1(k)=y1(k)。即BN是可以恢复出标准化处理前的数据分布的。
原论文中,BN层是接在激活函数之前的(下文会讨论BN层与激活函数的顺序问题),在没有采用BN的时候,激活函数 g ( ⋅ ) g(\cdot) g(⋅)计算公式是这样的:
g ( W x + b ) g(Wx+b) g(Wx+b)
采用BN算法后,计算公式变成:
g ( B N ( W x + b ) ) g(BN(Wx+b)) g(BN(Wx+b))
其实因为偏置参数
b
b
b经过BN层后会被均值标准化掉,所以
b
b
b这个参数就可以不用了,计算公式变成:
g
(
B
N
(
W
x
)
)
g(BN(Wx))
g(BN(Wx))
卷积层的BN[5]
对于卷积层,BN算法把一整张特征图当做一个神经元进行处理。
同样举个例子:
假设一个批次有 m m m个样本 x 1 , x 2 , . . . , x m x_1,x_2,...,x_m x1,x2,...,xm。每个样本经过三个卷积核卷积后得到三张特征图,对于 x 1 x_1 x1,可以得到: y 1 ( 1 ) , y 1 ( 2 ) , y 1 ( 3 ) {y}_1^{(1)},{y}_1^{(2)},{y}_1^{(3)} y1(1),y1(2),y1(3)。
其中
y
1
(
1
)
=
w
1
(
1
)
∗
x
1
y_1^{(1)}=w_1^{(1)}*x_1
y1(1)=w1(1)∗x1
进行标准化:
y
^
1
(
1
)
=
y
1
(
1
)
−
E
[
y
(
1
)
]
Var
[
y
(
1
)
]
\widehat{y}_1^{(1)}=\frac{y_1^{(1)}-\mathrm{E}\left[y^{(1)}\right]}{\sqrt{\operatorname{Var}\left[y^{(1)}\right]}}
y
1(1)=Var[y(1)]y1(1)−E[y(1)]
E
[
y
(
1
)
]
\mathrm{E}\left[y^{(1)}\right]
E[y(1)],
Var
[
y
(
1
)
]
{\sqrt{\operatorname{Var}\left[y^{(1)}\right]}}
Var[y(1)]指的是一批训练数据,第1个通道特征图(
y
1
(
1
)
{y}_1^{(1)}
y1(1),
y
2
(
1
)
{y}_2^{(1)}
y2(1)…
y
m
(
1
)
{y}_m^{(1)}
ym(1)
m
m
m张特征图)所有数据值的平均值,标准差。若特征图的尺寸是
p
×
q
p\times q
p×q,则计算每一个平均值和标准差需要处理的数据数就是:
m
×
p
×
q
m\times p\times q
m×p×q。
然后进行仿射变换:
z
1
(
1
)
=
γ
(
1
)
y
^
1
(
1
)
+
β
(
1
)
=
γ
(
1
)
y
1
(
1
)
−
E
[
y
(
1
)
]
Var
[
y
(
1
)
]
+
β
(
1
)
z_1^{(1)}=\gamma^{(1)} \widehat{y}_1^{(1)}+\beta^{(1)}\\ =\gamma^{(1)} \frac{y_1^{(1)}-\mathrm{E}\left[y^{(1)}\right]}{\sqrt{\operatorname{Var}\left[y^{(1)}\right]}}+\beta^{(1)}
z1(1)=γ(1)y
1(1)+β(1)=γ(1)Var[y(1)]y1(1)−E[y(1)]+β(1)
γ
(
1
)
,
β
(
1
)
\gamma^{(1)},\beta^{(1)}
γ(1),β(1)对应第1通道的特征图。特征图有几个通道就有几个
γ
\gamma
γ 和
β
\beta
β。也就是说
γ
\gamma
γ 和
β
\beta
β个数与特征图的通道数或者说卷积核的个数相等。
之后的激活函数与全连接类似,这里略过。
BN的测试[6]
测试阶段我们可能只输入一个或较少批量的测试样本。那么,上面的均值
u
B
u_{\mathcal{B}}
uB、标准差
σ
B
σ_{\mathcal{B}}
σB 要从哪里来?最后测试阶段,BN公式中的均值和方差不应该是针对某一个批次,而是要针对整个数据集。因此,在训练过程中除了正常的前向传播和反向求导之外,我们还要记录每一个批次的均值和方差,以便训练完成之后按照下式计算整体的均值和方差:
E
[
x
]
←
E
B
[
μ
B
]
Var
[
x
]
←
m
m
−
1
E
B
[
σ
B
2
]
\begin{aligned} \mathrm{E}[x] & \leftarrow \mathrm{E}_{\mathcal{B}}\left[\mu_{\mathcal{B}}\right] \\ \operatorname{Var}[x] & \leftarrow \frac{m}{m-1} \mathrm{E}_{\mathcal{B}}\left[\sigma_{\mathcal{B}}^{2}\right] \end{aligned}
E[x]Var[x]←EB[μB]←m−1mEB[σB2]
上面简单理解就是:对于均值来说直接计算所有批次
μ
B
\mu_{\mathcal{B}}
μB值的平均值;然后对于标准偏差采用每个批次
σ
B
σ_{\mathcal{B}}
σB均值的无偏估计。
实际实现时用 μ B \mu_{\mathcal{B}} μB和 σ B σ_{\mathcal{B}} σB的滑动平均去代替:
# running_mean 为均值的滑动平均,x_mean为当前批次的均值
running_mean = momentum *x_mean + (1 - momentum) * running_mean
# running_var 为方差的滑动平均,x_var为当前批次的方差
running_var = momentum * x_var + (1 - momentum) * running_var
动量值momentum
一般取0.1,0.01,0.001。
BN的原理
原论文[2][7][8][9]
BatchNorm提出的主要动机之一是减少所谓的内部协变量偏移(Internal Covariate Shift)(ICS)。在深度神经网络中,一个神经层的输入是之前神经层的输出.给定一个神经层 𝑙 𝑙 l,它之前的神经层 ( 1 , ⋯ , 𝑙 − 1 ) (1, ⋯ , 𝑙 − 1) (1,⋯,l−1)的参数变化会导致其输入的分布发生较大的改变。当使用随机梯度下降来训练网络时,每次参数更新都会导致该神经层的输入分布发生改变。越深的层,其输入分布会改变得越明显。这种变化会导致模型学习的分布不断变化,因此被认为会对训练过程产生不利影响。为了缓解这个问题,该论文对每一个神经层的输入进行归一化操作,使其分布保持稳定。把每个神经层的输入分布都归一化,可以使得不论低层的参数如何变化,高层的输入保持相对稳定。同时可以使得我们更加高效地进行参数初始化以及超参数选择。
BN的效果总结如下:
(1)BN使得网络中每层输入数据的分布相对稳定,加速模型学习速度
BN通过规范化与线性变换使得每一层网络的输入数据的均值与方差都在一定范围内,使得后一层网络不必不断去适应底层网络中输入的变化,从而实现了网络中层与层之间的解耦,允许每一层进行独立学习,有利于提高整个神经网络的学习速度。
(2) BN使得模型对网络中的参数不那么敏感,简化调参过程,使得网络学习更加稳定。
在神经网络中,我们经常会谨慎地采用一些权重初始化方法或者合适的学习率来保证网络稳定训练。使用BN后则可以大胆一点。
(3)BN缓解梯度消失问题,所以允许网络使用饱和性激活函数(例如sigmoid,tanh等)。
在不使用BN层的时候,由于网络的深度与复杂性,很容易使得底层网络变化累积到上层网络中,导致模型的训练很容易进入到激活函数的梯度饱和区;通过标准化操作可以让激活函数的输入数据落在梯度非饱和区,缓解梯度消失的问题;另外通过自适应学习
γ
\gamma
γ与
β
\beta
β 又让数据保留更多的原始信息。如图:
图片来源:[10]
(4)BN具有一定的正则化效果。
在BN中,由于我们使用小批量的均值与方差作为对整体训练样本均值与方差的估计,尽管每一个批次中的数据都是从总体样本中抽样得到,但不同批次的均值与方差会有所不同,这就为网络的学习过程中增加了随机噪音,与Dropout通过关闭神经元给网络训练带来噪音类似,在一定程度上对模型起到了正则化的效果。
BN算法的提出者认为BN算法解决了深度神经网络内部协方差偏移的问题,但后来的研究者发现并非如此。BN能取得很好的效果是因为它使得优化地形更平滑。
新研究:BN算法的效果只是一个偶然?[11][12][13]
这篇论文实验证明了BatchNorm的有效性与内部协方差偏移无关:在BN层后加入噪声使分布发生偏移,得到的效果与不加噪声的BN差不多。此外,“有噪声”的BatchNorm网络比普通的非BatchNorm网络具有更不稳定的数据分布,但它在训练方面仍然表现得更好。
还证明BatchNorm也没有明显减少ICS:用每一层在它之前所有层参数更新前后的损失梯度差异来衡量ICS的程度。实验得到添加BN后ICS反而更严重( l 2 − diff l_2-\text{diff} l2−diff 理想值是0, cos angle \cos \text{angle} cosangle理想值是1)。
备注:VGG是一种深度卷积网路,DLN是深度线性网络。
然后经过一系列实验和理论推导证明BN算法可以使得神经网络的优化地形(Optimization Landscape)更加平滑:
如下图视觉效果(右边为更平滑的优化地形):
图片来源:[14]
左图中,损失函数的优化地形不仅是非凸的,而且有大量的“扭结”、平坦区域和尖锐区域。这使得基于梯度下降的训练算法不稳定。类似右图,BN算法使得神经网络的优化地形(Optimization Landscape)更加平滑;这使得任何基于梯度的训练算法采取更大的步长,也不会有遇到平坦区域(对应于消失的梯度)或尖锐的局部最小值(导致梯度爆炸)。梯度更具可靠性、可预测性。因此,当我们在计算梯度的方向上使用较大的步长时,这个梯度方向在迈出那一步后仍然是对实际梯度方向的一个相当准确的估计。这反过来又使我们能够使用更大的学习率,并使训练速度显著加快。这意味着网络对超参数,网络初始化参数选择的敏感性降低了。
作者还发现,使用 l p l_p lp-范数进行标准化(不是正则化)也能有BatchNorm相当的性能,都提高了优化地形的平滑度。而且,对于深度线性网络, l 1 l_1 l1-范数标准化的性能甚至比BN算法更好。
深度卷积网络:
深度线性网络:
请注意, l p l_p lp–范数标准化比普通网络(即没有标准化的网络)有更大的分布偏移,但它们仍能提高优化性能。这表明BN算法能有这么好的效果可能是偶然的!因此,有必要对标准化方案的设计进行原理性的探索,因为可能还有更好的标准化方案。
BN的位置[15][16]
原论文将BN层置于卷积层之后,激活函数之前。下面这项研究用实验表明这种位置设定不一定是最好的。
该论文对BN层的三个不同位置进行了研究,这些位置是:
-
arrangement# 1:卷积层和非线性激活函数之间的BN层(原论文的顺序)
-
arrangement# 2:非线性激活函数之后的BN层
-
arrangement# 3:卷积层之前的BN层
数据集:
使用了 CIFAR10, CIFAR100 and Tiny ImagNet 这三个数据集,
数据集 | 种类 | 数目 | 图像大小 |
---|---|---|---|
CIFAR10 | 10类 | 每类6000张样本 | 32 ∗ 32 32*32 32∗32 |
CIFAR100 | 100类 | 每类600张样本 | 尺寸为 32 ∗ 32 32*32 32∗32 |
Tiny ImageNet | 200类 | 每类500样本 | 尺寸被resize到 32 ∗ 32 32*32 32∗32 |
可以看到数据集复杂度是逐渐上升的。
网络:
AlexNet、VGG16、ResNet-20,深度是逐渐增加的。
(1)AlexNet:
对于AlexNet,在每个Conv层之前使用BN层效果会更好。
(2)VGG-16:
对于不同的数据集,VGG-16使用的各种排列顺序都各有千秋。
(3)RESNET-20:
在比较复杂的ResNet网络里面,可以看到,简单数据集里面的表现,#1略优于#2,但是在复杂数据集里面,#1比#2提升很多
图片来源:[17]
结语:
本文提到的论文在公众号后台回复bnnb
即可获取。希望本文能抛砖引玉。
参考:
[1]https://blog.csdn.net/qq_37100442/article/details/81776191
[2] Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift https://arxiv.org/abs/1502.03167
[3]https://blog.csdn.net/hjimce/article/details/50866313
[4]https://blog.csdn.net/malefactor/article/details/51476961
[5]https://zhuanlan.zhihu.com/p/54171297
[6]https://blog.csdn.net/qq_41853758/article/details/82930944
[7]https://zhuanlan.zhihu.com/p/34879333
[8]https://zhuanlan.zhihu.com/p/55852062
[9] 《神经网络与深度学习》作者:邱锡鹏
[10]https://www.cnblogs.com/skyfsm/p/8453498.html
[11] How Does Batch Normalization Help Optimization? https://arxiv.org/abs/1805.11604
[12]https://zhuanlan.zhihu.com/p/64312433
[13]https://zhuanlan.zhihu.com/p/66683061
[14] Visualizing the Loss Landscape of Neural Nets https://arxiv.org/abs/1712.09913
[15]https://zhuanlan.zhihu.com/p/97557391
[16] An Empirical Study on Position of the Batch Normalization Layer in Convolutional Neural Networks https://arxiv.org/abs/1912.04259
[17] https://www.zcool.com.cn/work/ZMjI2NTA2MDg=.html