深度学习权重初始化
深度学习其本质是优化所有权重的值,使其达到一个最优解的状态,这其中,需要更新权重的层包括卷积层、BN层和FC层等。在最优化中,权重的初始化是得到最优解的重要步骤。如果权重初始化不恰当,则可能会导致模型陷入局部最优解,导致模型预测效果不理想,甚至使损失函数震荡,模型不收敛。而且,使用不同的权重初始化方式,模型最终达到的效果也是很不一样的。因此,掌握权重的初始化方式是炼丹师必备的炼丹术之一。在这里,我介绍一下深度学习中,我们常用的几种权重初始化的方式。
Xavier初始化
Xavier初始化方法提出于2010年的《Understanding the difficulty of training deep feedforward neural networks》中。Xavier初始化的方式其基本思想是“方差一致性”,即保持激活值的方差一致或者梯度的方差一致,这样有利于优化。基于该基本思想,作者假设每层的输入位于激活函数的线性区域,且具备零点对称的分布。
-
保持激活值的方差一致
首先,对于每个卷积层,其响应结果为:
$$Y_l=W_lX_l+b_l \tag{1}$$
其中,$X_l$是每层的输入参数,其shape为$(k\times k\times c)$,$k$为特征图的尺寸,$c$是通道数;$W_l$是该层的卷积核参数,其shape为$(d\times k\times k\times c)$,$d$表示卷积核的数量;$b_l$是偏差,我们通常让其为0。从公式(1)中,可以得知,$X_l=f(Y_{l-1})$和$c_l=d_{l-1}$,其中$f()$表示激活函数。
假设每层的$W_l$是相互独立的,且同分布;每层的$X_l$是相互独立的,且同分布;$W_l$和$X_l$是相互独立的。因此,令$b_l=0$,可以得到:
$$Var[y_l]=n_lVar[w_lx_l] \tag{2}$$
其中,$y_l$,$w_l$和$x_l$表示$Y_l$,$W_l$和$X_l$的每个随机变量,$n_l=k^2c$表示神经元个数。令$w_l$具有零均值,且关于零点对称分布;$x_l$也具有零均值,且位于激活函数的线性区域,$x_l=f(y_{l-1})=y_{l-1}$,所以:
\begin{align*}
Var[y_l]&=n_lVar[w_lx_l] \\
&=n_lVar[w_l]Var[x_l] \\
&=n_lVar[w_l]Var[y_{l-1}] \tag{3}
\end{align*}
因此,对于L层的输出,有:
$Var[y_L]=Var[y_1]\left ( \prod _{l=2}^L n_lVar[w_l] \right ) \tag{4}$
所以,公式(4)是初始化设计的关键,如果每层的$n_lVar[w_l]$过大或者过小,都会导致最后输出的值会指数型的增加或减少。因此,对于所有层,都需要满足:
$$n_lVar[w_l]=1 \tag{5}$$
所以,每层权重的初始化服从零均值,方差为$\frac{1}{n_l}$的分布。
-
保持梯度的方差一致
对于后向梯度传播而言,每个卷积层的的梯度为:
$$\triangle X_l=\hat{W_l}\triangle Y_l \tag{6}$$
其中,$\triangle X_l$和$\triangle Y_l$分别表示梯度;$\triangle Y$的shape为$(k\times k\times d)$;$\hat{W}$的shape为$(c\times k\times k\times d)$,这里的$\hat{W}$和$W$可以变换形状进行转换。同样,这里假设$w_l$和$\triangle y_l$相互独立,$\triangle x_l$具有零均值,$w_l$关于零点对称分布。在公式(6)中,可以得到:
$$\triangle y_l=f'(y_l)\triangle x_{l+1} \tag{7}$$
由于假设位于线性激活区域,$f'(y_l)=1$,所以:
\begin{align*}
Var[\triangle x_l]&=\hat{n_l}Var[\hat{w_l}\triangle y_l] \\
&=\hat{n_l}Var[\hat{w_l}]Var[\triangle y_l] \\
&=\hat{n_l}Var[\hat{w_l}]Var[\triangle x_{l+1}] \tag{8}
\end{align*}
其中,$\hat{n_l}=k^2d$,与上述的$n_l=k^2c$不一样,但都表示神经元个数。
将L层结果堆积起来,得到
$$Var[\triangle x_2]=Var[\triangle x_{L+1}](\prod _{l=2}^L\hat{n_l}Var[w_l]) \tag{9}$$
同样,为了使公式(8)不会过大或者过小(过大或者过小会导致梯度爆炸或者梯度弥散),让每层梯度均满足:
$$\hat{n_l}Var[w_l]=1 \tag{10}$$
所以,每层权重的初始化服从零均值,方差为$\frac{1}{\hat{n_l}}$的分布。
上面从激活值的方差和梯度的方差进行了推导,对比公式(5)和公式(10),发现两者存在差异,但使用哪种方式进行权重初始化,都是可以接受的。假设我们使用使用公式(10)进行权重初始化,那么公式(9)中$\prod _{l=2}^L\hat{n_l}Var[w_l]=1$,代入公式(4)中,有$\prod _{l=2}^Ln_lVar[w_l]=\prod _{l=2}^L\frac{n_l}{\hat{n_l}}=\frac{c_2}{d_L}$,这样同样不会使输出的值过大或者过小。
作者为了同时满足公式(5)和公式(10),对两者进行取均值,因此,对所有层,权重初始化需要满足:
$$Var(w_l)=\frac{2}{n_l+\hat{n_l}} \tag{11}$$
其中,对于第$l$层而言,$n_l=k^2c$和$\hat{n_l}=k^2d$表示第$l$层与第$l-1$层的神经元数量关系,差异是输入通道$c$和输出通道$d$的区别。
因此,Xavier初始化方式需要服从零均值,方差为$\frac{2}{n_l+\hat{n_l}}$。在论文中,使用的是均匀分布,零点对称的均匀分布的方差为$\frac{a^2}{3}$,因此,Xavier初始化方式服从$W\sim U\left [-\sqrt{\frac{6}{n_l+\hat{n_l}}},\sqrt{\frac{6}{n_l+\hat{n_l}}} \right ]$的均匀分布。
He初始化
He初始化是由何凯明大神与2015年在《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》中提出的。其基本思想和Xavier一致,保持方差的一致性,且推导也是在Xavier初始化方式类似。
Xavier初始化方式中,其假设激活函数是线性的。但随着深度学习的发展,ReLU已经是常见的激活函数了,其不是线性的,所以Xavier初始化会对ReLU系列的激活函数失效。因此,何凯明在基于激活函数是ReLU的基础上,推导出He初始化方式。
-
保持激活值的方差一致
假设$w_l$具有零均值,$w_l$与$x_l$相互独立,所以$Var[w_l]=E[w_l^2]-E^2[w_l]=E[w_l^2]$。而激活函数是ReLU,有$x_l=max(0,y_{l-1})$,所以$x_l$不具备零均值,且$E[x_l^2]=\frac{1}{2}Var[y_{l-1}]$。因此,公式(2)可以得到
\begin{align*}
Var[y_l]&=n_lVar[w_lx_l] \\
&=n_l(E[(w_lx_l)^2]-E^2[w_lx_l]) \\
&=n_l(E[w_l^2]E[x_l^2]-E^2[w_l]E^2[x_l]) \\
&=n_lE[w_l^2]E[x_l^2] \\
&=n_lVar[w_l]E(x_l^2) \\
&=\frac{1}{2}n_lVar[w_l]Var[y_{l-1}] \tag{12}
\end{align*}
对比公式(3)和公式(12),可以发现,两者相差了$\frac{1}{2}$的系数,这个系数是由ReLU引起的。因此,将L层输出堆积在一起,可以得到
$$Var[y_L]=Var[y_1]\left ( \prod _{l=2}^L \frac{1}{2} n_lVar[w_l] \right ) \tag{13}$$
因此,对于每一层都需要满足:
$$\frac{1}{2}n_lVar[w_l]=1 \tag{14}$$
所以,每层权重的初始化服从零均值,方差为$\frac{2}{n_l}$的分布。
-
保持梯度的方差一致
由公式(7)可以得知,对于ReLU而言,$f'(y_l)$等于$0$或者$1$,两者的概率是相同的。而又假设$\triangle x_l$具有零均值,$f'(y_l)$与$\triangle x_{l+1}$是相互独立的,可以得到$E[\triangle y]=\frac{E[\triangle x_{l+1}]}{2}=0$和$E[(\triangle y)^2]=Var[\triangle y]=\frac{1}{2}Var[\triangle x_{l+1}]$。结合这些条件,可以从公式(7)导出:
\begin{align*}
Var[\triangle x_l]&=\hat{n_l}Var[w_l]Var[\triangle y_l] \\
&=\hat{n_l}Var[w_l](E[\triangle ^2y_l]-E^2[\triangle y_l]) \\
&=\frac{1}{2}\hat{n_l}Var[w_l]Var[\triangle x_{l+1}] \tag{15}
\end{align*}
公式(10)和公式(15)主要的差别也是$\frac{1}{2}$的系数,同样是由于ReLU引起的。因此将L层堆积起来,可以得到
$$Var[\triangle x_2]=Var[\triangle x_{L+1}](\prod _{l=2}^L\frac{1}{2}\hat{n_l}Var[w_l]) \tag{16}$$
因此,对于每一层都需要满足:
$$\frac{1}{2}\hat{n_l}Var[w_l]=1 \tag{17}$$
所以,每层权重的初始化服从零均值,方差为$\frac{2}{\hat{n_l}}$的分布。
同样,使用公式(14)或者公式(17)对网络权重进行初始化都可以,服从零均值、方差为$\frac{2}{n_l}$或者$\frac{2}{\hat{n_l}}$的分布。在论文中,作者选择使用了高斯分布,即服从$W\sim G\left [0,\sqrt{\frac{2}{n}} \right ]$的高斯分布。
预训练初始化
在实际中,我们大部分是在已有的网络上进行修改,得到预期结果后,再对网络进行裁剪等操作。而预训练模型是别人已经在特定的数据集(如ImageNet)上进行大量迭代训练的,可以认为是比较好的权重初始化。加载预训练模型进行初始化,能使我们进行更高频率的工程迭代,更快得到结果。而且,通常加载预训练模型会得到较好的结果。
但是要注意几个问题:
- 许多文章指出,当源场景与目标场景差异过大时,加载预训练模型可能不是一种很好的方式,会导致领域失配;
- 何凯明在2019年的《Rethinking ImageNet Pre-training》中指出,加载预训练模型并不能使准确率提高,只要迭代步数够多,随机初始化也能产生相同的效果。但实际中,我们无法得知得迭代多少次,模型才饱和;而且迭代步数越多,时间成本也就越大。
总体来说,如果初始版本的模型存在预训练模型的话,我们可以通过加载预训练模型来进行初始化,快速得到结果;然后再根据需求,对初始版本的网络进行修改。
综上所示,如果模型存在预训练模型,尽可能使用预训练进行初始化;而对于没有预训练模型或者新加了部分层,可以使用He初始化方式来进行初始化。
参考材料:
- https://blog.csdn.net/weixin_35479108/article/details/90694800
- https://www.zhihu.com/question/291032522/answer/605843215