参考博客
大神链接:
1、https://blog.csdn.net/weixin_44791964?type=blog
2、https://www.jianshu.com/p/b05282e9ca57
文章目录
学习神经网络的时候,发现了很多的算法在输入层之前加上了Batch Normalization 算法,记录一下自己的学习。
背景
Batch Normalization论文是2015年深度学习领域,超级火的一篇论文,论文的全称为《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》
论文的原文链接如下:
链接一 https://arxiv.org/abs/1502.03167v3
链接二 http://proceedings.mlr.press/v37/ioffe15.pdf
在BN算法出现之前,当前深度学习网络虽然发展迅速,但也面临着参数过多,类似于学习率、参数初始化、权重衰减系数、Drop out比例等,都是需要人为的去选择参数,经常需要大量的时间进行调参,BN算法帮助人们加速这一过程,使得在各类超参的选择上不需要那么多精力。
前景知识
为了减少数据值的大小,还要保留数据的分布特性,减少网络对不同批次数据分布类型的依赖,我们一般情况下们都会对数据进行归一化操作。归一化操作成了我们把数据送入神经网络的标准操作。
虽然我们在将数据送入神经网络之前进行了归一化操作,但是后续神经节点,却没有归一化,虽然我们有各类激活函数使得网络呈现非线性,防止网络节点输出过大,但深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。
也就是因为神经网络中间层之间没有进行数据的归一化,所以每次的数据分布在训练过程中都不一样,会很大的影响下一层的输出的数据分布,直接会影响到参数的训练过程,我们把网络中间层在训练过程中,数据分布的改变称之为:“Internal Covariate Shift”。对Google提出的“Internal Covariate Shift”的理解可以参考这个。
那么什么方法可以解决这个问题呢?
就是对中间层也进行数据归一化操作,使得中间层输出的数据分布较为稳定。说起来好像是挺容易的,不就是归一化操作嘛,容易,但是实现起来却没有那么容易,细看在此文章之前的文章,却没有人实现过。原因为:如果渐渐单单对中间层的数据使用已有的归一化方法,会强制的改变数据的分布结构,有一种强行将数据全部扭到一种分布模式的感觉。
比如强行变成均值为零、标准差为1的分布。这样的话,会影响到下一层网络可以学习到的东西,无论上一层网络给啥,归一化之后都一样,下一层还学啥,直接摆烂了。
所以我们需要一种算法,能够对中间层数据进行归一化,且最大程度上保留数据的分布特征。我们的厉害的BN算法横空出世(BN算法NB)。
BN算法原理
将BN算法之前,我们还需要了解一种归一化算法–白化算法,这个算法在论文中也有提及到。
白化算法:
白化的目的是去除输入数据的冗余信息。假设训练数据是图像,由于图像中相邻像素之间具有很强的相关性,所以用于训练时输入是冗余的;白化的目的就是降低输入的冗余性。
输入数据集X,经过白化处理后,新的数据X’满足两个性质:
(1)特征之间相关性较低;相当于PCA过程。
(2)所有特征具有相同的方差。
具体公式:
公
式
一
:
C
o
v
[
x
]
=
E
x
∈
X
[
x
x
T
]
−
E
[
x
]
E
[
x
]
T
公式一:Cov[x] = E_{x∈X} [xx^T] − E[x]E[x]^T
公式一:Cov[x]=Ex∈X[xxT]−E[x]E[x]T
公
式
二
:
C
o
v
[
x
]
−
1
/
2
(
x
−
E
[
x
]
)
公式二:Cov[x]−1/2(x − E[x])
公式二:Cov[x]−1/2(x−E[x])
从公式可以看出来,它需要公式一计算协方差矩阵Cov[x],以及产生白花激活的公式二,以及这些变换的导数用于反向传播。要进行完上述的所有过程,我们需要计算的数据量十分的大,这促使我们寻求一种替代方法,以一种可微分的方式执行输入规范化,并且不需要在每次参数更新后分析整个训练集。
论文作者为了减少计算量和方便后向计算仅仅使用了下面的公式进行预处理,也就是近似白化预处理:
公
式
三
:
x
^
(
k
)
=
x
(
k
)
−
E
[
x
(
k
)
]
V
a
r
[
x
(
k
)
]
公式三:\widehat{x}{^{(k)}} =\frac{x(k) − E[x^{(k)}]}{\sqrt{Var[x^{(k)}]}}
公式三:x(k)=Var[x(k)]x(k)−E[x(k)]
训练过程中采用batch 随机梯度下降,上面的
E
[
x
(
k
)
]
E[x^{(k)}]
E[x(k)]指的是每一批训练数据神经元
x
(
k
)
x^{(k)}
x(k)的平均值;然后分母就是每一批数据神经元
x
(
k
)
x^{(k)}
x(k)激活度的一个标准差了。
但是直接这样做的话也会强制的使得数据的分布特征为同一类型,作者为了解决这样的问题,提出了一种开创性的想法,如下:
公
式
四
:
y
(
k
)
=
γ
(
k
)
x
^
(
k
)
+
β
(
k
)
公式四:y^{(k)} = γ^{(k)}\widehat{x}^{(k)} + β^{(k)}
公式四:y(k)=γ(k)x(k)+β(k)
其中
γ
(
k
)
=
V
a
r
[
x
(
k
)
]
γ^{(k)} =\sqrt{Var[x^{(k)}]}
γ(k)=Var[x(k)] 和
β
(
k
)
=
E
[
x
(
k
)
]
β^{(k)} =E[x^{(k)}]
β(k)=E[x(k)];
每一个神经元
x
(
k
)
x^{(k)}
x(k)都会有一对这样的参数
γ
(
k
)
γ^{(k)}
γ(k)、
β
(
k
)
β^{(k)}
β(k),这样做的目的是让归一化之后的数据特性的分布特性由数据自己来决定,是可以恢复出原始的某一层所学到的特征的。
这样就完美的解决了怎么对数据进行归一化,以及最大程度不改变数据分布特性的两个问题。
论文中给出了算法的具体计算流程如下:
即主要分为了四个步骤,也就是我们在上面所提到的那些步骤:
从步骤中可以得知,为小批量的训练方法。
1、计算每一批次的输入数据的平均值。
2、利用步骤一所求得的平均值进行输入数据方差的求取。
3、步骤三中所用的公式和我们上述公式三不一样的地方是加上了
ϵ
\epsilon
ϵ。
ϵ
\epsilon
ϵ是一个极小值,是为了防止方差为零、或者无线接近于零的情况发生,使得结果无限大的情况发生。
4、利用公式四进行消除归一化所带来的标准化的影响,也可以说是反标准化的一步。
至此,基本的BN的算法就这么多,但是我们上述的
x
(
k
)
x^{(k)}
x(k)是针对于每一批的小样本来说,我们训练完了我们的模型之后,输入很有可能的是单个样本,那个时候我们该如何计算平均值和方差呢?
论文中的方法为:
在训练结束后,参数都是固定化的,BN的参数也是固定化了。一旦固定化,就要有一个确切的值,论文中的最终BN阶段的平均值和方差来自于所有训练样本的平均值和方差,也就是所有小批次的平均值和方差。
具体公式如下:
对于均值来说直接计算所有batch的平均值:
平
均
值
:
E
[
x
]
←
E
B
[
µ
B
]
平均值:E[x] ← E_B[µ_B]
平均值:E[x]←EB[µB]
对于标准偏差采用每个batch的无偏估计:
方
差
:
V
a
r
[
x
]
←
m
m
−
1
E
B
[
σ
B
2
方差:Var[x] ← \frac{m}{m−1}E_B[σ^2_B
方差:Var[x]←m−1mEB[σB2
最后测试阶段,BN的使用公式就是:
y
=
γ
V
a
r
[
x
]
+
ϵ
x
+
(
β
−
γ
E
[
x
]
V
a
r
[
x
]
+
ϵ
)
y = \frac{γ}{\sqrt{Var[x]+\epsilon}}x +(β-\frac{γE[x]}{\sqrt{Var[x]+\epsilon}})
y=Var[x]+ϵγx+(β−Var[x]+ϵγE[x])
以上就是BN算法的大致思想和步骤。具体内容,可以深入阅读一下文章。
BN算法的优点
1、Batch Normalization 对每层数据规范化后,可以使用更高的学习率(因为不加以规范之前,每层的数据的分布特性复杂,采用较高学习率容易不收敛),所以网络训练时可以设置较高的初始学习率,加快收敛。
2、你再也不用去理会过拟合中drop out、L2正则项参数的选择问题,采用BN算法后,可以选择更小的L2正则约束参数了,因为BN具有提高网络泛化能力的特性;也不需要使用使用局部响应归一化层了,因为BN本身就是一个归一化网络层;
3、防止过拟合。在网络的训练中,Bn使得一个minibatch中所有样本都被关联在了一起,因此网络不会从某一个训练样本中生成确定的结果,这样就会使得整个网络不会朝这一个方向使劲学习。一定程度上避免了过拟合。
4、防止梯度爆炸和梯度消失,因为规范化之后,数据较为标准,在各个点的梯度都不会过大或者过于小,
BN的代码实现
代码可以参考这里 和 这里
代码为Pytorch实现的,和上面公式很贴切
版权归原作者 浅冲一下 所有, 如有侵权,请联系我们删除。