Batch normalization
一.知识储备
1.1机器学习希望样本空间独立同分布:
就是样本的各个维度特征之间分布相同,且相互独立。
如果数据不服从独立同分布会造成什么?
- 首先讲 独立:各个特征相关性比较多,容易造成冗余,比如一个特征描述耳朵,另一个特征也是描述耳朵的,就相当于特征重复了,而我们希望只取其中一个特征就好,所以就造成了冗余,冗余比较严重的时候就会造成过拟合。
-
其次讲 同分布:为什么要同分布呢?假如各个维度的特征不同分布,也就会造成各个维度的特征尺度不一,即量纲不同,不同的量纲会造成训练速度减慢,局部最优等问题,具体原因看我这篇文章: 机器学习---之为什么要对数据进行归一化
解决办法:其实独立同分布是一个假设,一个设想,所以为了尽量的去靠近这个设想,就有了后来的PCA降维,PCA就可以可以尽可能的消除各个维度特征之间的相关性。关于PCA降维是什么看我这篇文章, 机器学习---之PCA降维
1.2源域和目标域同分布:
- 与上一个的独立同分布需要区分开来,独立同分布讲的是样本空间中的各个维度的特征独立同分布,而这里的源域指的是训练的样本空间,目标域是你想要去预测的样本空间,如果源域与目标域的概率分布都不同,你还预测什么嘛,通俗的话讲用一个都是猫的训练集来训练的模型,去预测狗,概率分布明显不同嘛,怎么预测的对?至于概率分布在图像预测以及分类过程中到底代表什么?看我这篇文章概率分布,独立同分布在图像分类与检测中到底代表什么?
1.3什是internal incovariate shift:
- 首先你要懂 incovariate shift:,看这篇文章 convariate shift 理解了这篇文章之后,interna incovariate shift 就是代表神经网络中内部的 incovariate shift。
二.Deep learing常见问题
1.如容易造成过拟合。
2.需要谨慎的调参数,包括学习率,以及权重的初始化等等。
3.训练速度慢,造成internal incovariate shift。
三.BN的作用
1.你可以加大训练的学习率,加快训练速度而不会导致收敛问题,解决 internal incovariate shift
2.一定程度防止过拟合,可以减少drop out的比例以及甚至不用正则化
3.能够预防梯度消失以及梯度爆炸
四.Batch normalizaton解决的问题
4.1解决internal incovariate shift:
1.先来考虑一个问题:在神经网络训练之前,要先对数据做归一化处理,为什么要做归一化处理呢?神经网络学习过程本质就是为了学习数据分布,
第一个原因:就是归一化可以提高模型的泛化能力,加快训练速度。
第二个原因就是因为我们有batch去训练神经网络的时候,我们的batch是从训练集中提取出来的,而提取出来的batch的分布跟全部的原始训练集的分布肯定会有一些不同,毕竟不是全部数据,每个提取的batch之间的分布也有差异(这里的分布指的不是特征维度的分布,而是不同batch之间的分布),通俗易懂的来讲就是由于分布的不同,比如第一个batch要你在z方向减2,第二个batch却要你在z方向加2,由于这样会导致神经网络的不稳定,所以要在把Batch喂给神经网络之前做一个归一化,使分布相似。
接下来说说internal incovariate shift:本部分摘取点击打开链接
1.internal incovariate shift指的分布是特征维度之间的分布,就是前面知识储备讲到的各个特征维度要独立同分布
对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。
2.我们知道网络一旦train起来,那么参数就要发生更新,除了输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的,因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化。以网络第二层为例:网络的第二层输入,是由第一层的参数和input计算得到的,而第一层的参数在整个训练过程中一直在变化,因此必然会引起后面每一层输入数据分布的改变。我们把网络中间层在训练过程中,数据分布的改变称之为:“Internal Covariate Shift”。Paper所提出的算法,就是要解决在训练过程中,中间层数据分布发生改变的情况,于是就有了Batch Normalization,这个牛逼算法的诞生。
总结:这一段其实讲的就是因为特征维度的分布不同,每次网络学习的效率就会很慢(为什么慢,要看前面知识储备所讲到的同分布问题),而深层的网络又会加大这种分布的不同,导致训练速度更慢。而解决这个问题最好的办法就是什么,batch normalization。
4.1.2为什么batch normalization可以解决internal incovariate shift:
因为internal incovariate shift的问题本质其实就是神经网络一层当中的特征维度的分布不同,经过多层后会放大这个分布的不同导致训练速度更慢,而bach normalization可以使每层中每个维度的特征归一化到均值为0,方差为1的分布,使得分布相同,解决问题,公式如下:
这里的均值和方差指的是每个batch内部,同一维度特征的均值和方差,而每一层神经网络当中会有很多的feature map,对于一个batch来说一共就有,batchsize*一层当中的feature map的数量,就有这么多的feature map,,然后就是对于每一层神经网络当中的同一个batch内的同一维度的feature map的所有像素点求和做均值,再对这些像素点做方差。
4.2 BN为什么可以解决梯度爆炸和梯度消失问题?
本部分参考:https://www.zhihu.com/question/38102762
4.3算法描述
1、BN算法概述
经过前面简单介绍,这个时候可能我们会想当然的以为:好像很简单的样子,不就是在网络中间层数据做一个归一化处理嘛,这么简单的想法,为什么之前没人用呢?然而其实实现起来并不是那么简单的。其实如果是仅仅使用上面的归一化公式,对网络某一层A的输出数据做归一化,然后送入网络下一层B,这样是会影响到本层网络A所学习到的特征的。打个比方,比如我网络中间某一层学习到特征数据本身就分布在S型**函数的两侧,你强制把它给我归一化处理、标准差也限制在了1,把数据变换成分布于s函数的中间部分,这样就相当于我这一层网络所学习到的特征分布被你搞坏了,这可怎么办?于是文献使出了一招惊天地泣鬼神的招式:变换重构,引入了可学习参数γ、β,这就是算法关键之处:
每一个神经元xk都会有一对这样的参数γ、β。这样其实当:
、
是可以恢复出原始的某一层所学到的特征的。因此我们引入了这个可学习重构参数γ、β,让我们的网络可以学习恢复出原始网络所要学习的特征分布。最后Batch Normalization网络层的前向传导过程公式就是:
上面的公式中m指的是mini-batch size。
2、源码实现
- m = K.mean(X, axis=-1, keepdims=True)#计算均值
- std = K.std(X, axis=-1, keepdims=True)#计算标准差
- X_normed = (X - m) / (std + self.epsilon)#归一化
- out = self.gamma * X_normed + self.beta#重构变换
3、实战使用
(1)可能学完了上面的算法,你只是知道它的一个训练过程,一个网络一旦训练完了,就没有了min-batch这个概念了。测试阶段我们一般只输入一个测试样本,看看结果而已。因此测试样本,前向传导的时候,上面的均值u、标准差σ 要哪里来?其实网络一旦训练完毕,参数都是固定的,这个时候即使是每批训练样本进入网络,那么BN层计算的均值u、和标准差都是固定不变的。我们可以采用这些数值来作为测试样本所需要的均值、标准差,于是最后测试阶段的u和σ 计算公式如下:
上面简单理解就是:对于均值来说直接计算所有batch u值的平均值;然后对于标准偏差采用每个batch σB的无偏估计。最后测试阶段,BN的使用公式就是:
(2)根据文献说,BN可以应用于一个神经网络的任何神经元上。文献主要是把BN变换,置于网络**函数层的前面。在没有采用BN的时候,**函数层是这样的:
z=g(Wu+b)
也就是我们希望一个**函数,比如s型函数s(x)的自变量x是经过BN处理后的结果。因此前向传导的计算公式就应该是:
z=g(BN(Wu+b))
其实因为偏置参数b经过BN层后其实是没有用的,最后也会被均值归一化,当然BN层后面还有个β参数作为偏置项,所以b这个参数就可以不用了。因此最后把BN层+**函数层就变成了:
z=g(BN(Wu))
本部分参考:http://blog.csdn.net/hjimce/article/details/50866313