BN也叫归一化,它和比如说CNN中的卷积层一样,也是网络中的一层,但它是一个数据的处理层。数据经过BN后,再交给其他层处理,可以极大地提升训练效率。
BN出自论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,这个算法目前已经被大量的应用。
举一个不太恰当的例子,假设有一块面板,上面有一些球,我们要把球挪在合适的位置,但是每次挪动一点球都,人距离面板的距离要加大。
面板初始,这个视角挪起来非常轻松。
然后距离大一点,也还好
再大一点呢,也还将就
再大一点,开始有点费劲了
然后,有点模糊了
颜色已经慢慢区分不开了
你是认真的吗?
哈哈通过这一系列图,我们可以发现,随着距离的增加,想挪动球也会变得复杂。主要体现在容易挪错挪过头。
在深度学习中也有类似的问题,随着层数(距离)的增加,前面的层观测后面层的数据时,极其不容易观测,通俗点说就是不够准备。这个时候容易产生两个问题,梯度爆炸和梯度消失。
梯度爆炸:说的是蝴蝶效应。一个直观的影响就是,前面层的学习率已经很小很小了,但是传播到后面,则会带来很大的步长,可能导致无法收敛。
梯度消失:和梯度爆炸相反,学习率对后面层的带来的步长几乎没有,这个时候,学习会很慢很慢很慢,上图的球就会变成蜗牛,甚至比蜗牛还慢,这几乎也可以认为是不可收敛的。
回到小球那个问题,怎么有效的解决挪球这个问题呢?
其实很简单,每次挪球前加一个标准的放大镜呗,BN就是我们要找的放大镜!
Batch Normalization顾名思义,叫批规范化,也就是说把零散的样本按一定的规范处理一遍。
其中处理的步骤如下(图片来自BN作者paper):
假设神经网络一共只有一层:
·不用BN,反向传播时便有:
如果有n层,很容易得到:
这个就是梯度的问题所在,因为网络很深,如果w<1,经过很次的n次方后,值会变得很小很小。反之会变得很大很大。
·如果用了BN(为了方便理解和计算,我们去掉分母中的ε):
模型就变成
反向传播时便有:
其中γ是一个训练参数,姑且认为它是常量。可以看的,每加一层BN后,分母就会多一个和y1的标准差σ。
如果w1很小,因为x是样本值,是固定的,那么y1的值必然很小,那么y1的标准差σ也必然很小。w1除一个很小的σ,那么就等于对w1进行了放大。对于这一层,梯度也相应变大,这样一定程度上避免了梯度消失。
同样w1很大,那么σ也必然很大,那就相当于w1进行了缩小,梯度也相应变小,这样一定程度上避免了梯度爆炸。
这里用了一个简单的数字识别demo来说明采用BN的差别。
网络模型由4个卷积层,一个全连接层。样本是随便11位以内的随机数字图片。如图
实验结果表明,如果在每个卷积层后面跟一个BN层的话,则在380个batch模型训练后,就能达到95%的准确度。而不带BN的话,模型则变得不可收敛了。
两者代码唯一的区别就在,输出的时候有没有做BN。
附件有全部代码,感兴趣的可以跑下试试。
运行环境:python3
必需库:Tensorflow、PIL。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。