BN算法主要解决的问题是内部协变量偏移。
由于参数更新导致底层网络的输出分布不断发生改变,高层网络的参数需要不断的调整以适应新的底层输出分布,如果高层网络不能适应底层网络输出的分布,将会导致网络表现能力非常差(即不能很好的发现底层网络输出的规律,没有规律可循,表现能力自然下降了)一般来说,我们通过选择小的学习率以及优秀的初始化,从而避免梯度更新后,每层输出的分布发生非常大的改变,从而抵抗内部协变量偏移,但这也导致训练缓慢
为了避免底层网络输出的分布发生改变,一个想法便是能不能固定底层网络输出的分布?这也是BN算法的出发点。
LeCun等人的文章证明,如果网络的输入是白化的,那么网络的收敛速度将会加快,这说明白化操作将有助于实现底层网络输出分布的固定化,原文只说向实现输入分布固定化迈出一步,而不是完全实现,因此BN算法并不能说严格意义上的完全解决协变量偏移,原文如下:
By whitening the inputs to each layer, we would take a step towards achieving the fixed distributions of inputs that would remove the ill effects of the internal covariate shift.
底层网络的输出是高层网络的输入,如果能够实现每层输出的白化,将有帮助于网络的收敛
白化即输入的均值为0,方差为1,且样本各个特征之间的相关性较低,常用的白化操作包括PCA白化操作与ZCA白化操作,以ZCA白化操作为例,如果我们使用批量梯度算法,需要对每一层的输入都进行ZCA白化操作,将一个批度在该层的输出组织成矩阵 X X X, X X X中的每一列都是一个样本,每个样本进行ZAC白化后的输出为:
c o v ( x ) − 1 2 ( x − E ( x ) ) = ( X X T ) − 1 2 ( x − E ( x ) ) = U V − 1 2 U T ( x − E ( x ) ) ( 对 协 方 差 矩 阵 进 行 对 角 化 ) \begin{aligned} cov(x)^{-\frac{1}{2}}(x-E(x))&=(XX^T)^{-\frac{1}{2}}(x-E(x))\\ &=UV^{-\frac{1}{2}}U^T(x-E(x))(对协方差矩阵进行对角化) \end{aligned} cov(x)−21(x−E(x))=(XXT)−21(x−E(x))=UV−21UT(x−E(x))(对协方差矩阵进行对角化)
一、白化操作需要对协方差矩阵进行对角化,非常的消耗计算资源
二、假设让输入变为固定分布的操作为Norm,如果在计算梯度时,不考虑Norm,可能会出现梯度更新与Norm操作相抵消的情况,并且会出现梯度爆炸,而ZAC白化操作不可微
对每一层的输入数据进行标准化,均值和方差基于整个数据集计算,不理会不同特征之间是否存在相关,这不是严格的白化,但却有利于网络收敛(这是深度学习训练的一个trick)
如果一次训练基于一个数据集,即使用batch GD,那么简化一已经足够了,但是我们一般使用SGD或是mini-batch GD进行深度学习模型的训练,因此在简化一的基础上,BN算法做出了第二个简化,对一个批度进行标准化
基于上述两个简化,BN操作的具体步骤如下:
注意到在标准化后,紧接着进行了一个线性变化,即
y i = γ x ^ i + β y_i=\gamma\hat x_i+\beta yi=γx^i+β
由于强制将每层的输入变为0均值,1方差,这会限制该层的表达能力,以sigmoid激活函数为例,标准化后的输入将集中在0附近,而sigmoid函数在0附近的图像近似于直线,那么该层更近似于一个线性变换,为了防止这种情况出现,因此BN操作在每层中引入了两个可学习参数 γ , β \gamma,\beta γ,β
可以看到,BN操作并没有从数学角度证明该算法完全解决了内部协变量偏移,而是从白化操作可能可以抵抗协变量偏移角度出发,对白化操作进行了简化,同时为了不限制层的表达能力,给每层引入了两个可学习参数 γ , β \gamma,\beta γ,β,紧接着通过实验验证了这种操作有助于提高网络的训练速度,说到底,BN算法更像是一种trick。
网络某一层输入数据可以表示为四维矩阵 ( m , f , w , h ) (m,f,w,h) (m,f,w,h), m m m为批度大小, f f f为特征图个数, w 、 h w、h w、h分别为特征图的宽高。m个样例,同一个特征图会有m种取值,一共有 m ∗ w ∗ h m*w*h m∗w∗h个值,求这 m ∗ w ∗ h m*w*h m∗w∗h个值的均值与方差,接着对这 m ∗ w ∗ h m*w*h m∗w∗h个值进行标准化操作。每个特征图都有一对可学习参数:γ、β。
在训练过程中,对于一个神经元(特征图)而言,每一个大小为m的批度都会产生一个均值 u u u和一个方差 δ 2 \delta^2 δ2,记录这些均值与方差,测试样例输入该神经元(特征图)前进行标准化的均值与方差计算方式如下:
E ( x ) = E ( u ) V a r ( x ) = m m − 1 E ( δ 2 ) \begin{aligned} E(x)&=E(u)\\ Var(x)&=\frac{m}{m-1}E(\delta^2) \end{aligned} E(x)Var(x)=E(u)=m−1mE(δ2)
Var(x)是训练数据作为该神经元输入值(标准化前)的方差的无偏估计,E(x)是就是训练数据作为该神经元输入(标准化前)的均值,则测试数据与训练数据同时利用该均值进行标准化,就变为了0均值,1方差(多一个数据基本不会影响E(x)与Var(x))(具体原因未知,论文大致就是这个意思,大概也是一个trick)
可以对激活函数的输入进行BN操作,也可以对激活函数的输出做BN操作,论文建议对激活函数的输入做BN操作,原文:
We add the BN transform immediately before the nonlinearity, by normalizing x = Wu + b
一、可以使用较大的学习率:由于克服了内部协变量偏移,所以不需要使用较低的学习率来抵抗内部协变量偏移
二、正则化:一个样例通过标准化操作,结合了其他样例的情况,网络将不仅仅依靠这个样例产生结果
三、抵抗梯度消失:针对于sigmoid、tanh函数而言,标准化操作一定程度上将激活函数的输入集中在了0附近