Neural Networks and Deep Learning(三·三)权重初始化及其他

权重初始化

在之前的章节中,我们都是用一个标准正态分布N(0,1^2)初始化所有的参数wb,但是当神经元数量比较多时,会出现意想不到的问题。

假设一个神经网络的输入层有1000个神经元,且某个样本的1000维输入中,恰好有500维是0,另500维是1。我们目前考察隐藏层的第一个神经元,则该神经元为激活的输出为z = \sum_j w_j x_j+b,因为输入中的500维是0,所以z相当于有501个来自N(0,1^2)的随机变量相加。因为w_jb的初始化都是独立同分布的,所以z也是一个正态分布,均值为0,但方差变成了\sqrt{501} \approx 22.4,即z\sim N(0,\sqrt{501}^2)。我们知道对于正态分布,如果方差越小,则分布的形状是高廋型的;如果方差越大,则分布的形状是矮胖型的。所以z有很大的概率取值会远大于1或远小于-1。又因为激活函数是sigmoid,当z远大于1或远小于-1时,\sigma (z)趋近于1或者0,且导数趋于0,变化缓慢,导致梯度消失。

请注意,这里的梯度消失和之前介绍得梯度消失稍有不同,之前是说在误差反向传播过程中,损失函数对权重的导数中包含梯度消失项,所以可以通过更换损失函数来解决。但是这里的梯度消失并不是在误差反向传播过程中产生的,而是在正向传播产生的,跟损失函数没关系。

解决这个问题的方法很简单,根据上面的分析,如果输入x_j全为1,wb都来自N(0,1^2),则z\sim N(0, \sqrt{n+1}^2),其中n为输入样本的维度。要减小z的方差,减小wb的方差就可以了。因为b只有一个,对整体的影响不大,可以不修改b的分布,b依然来自N(0,1^2)。把w_j的分布修改为N(0, (\frac{1}{\sqrt{n}})^2),此时z\sim N(0, \sqrt{2}^2)\sqrt{2}=1.414就非常接近1了,z的分布也变成了一个高廋型的,梯度消失问题也就不存在了。

如果是开头的例子,输入维度为1000,其中500为0,500为1,w_j\sim N(0, (\frac{1}{\sqrt{1000}})^2)b\sim N(0,1^2),则z\sim N(0, \sqrt{\frac{3}{2}}^2)\sqrt{3/2} = 1.22\ldots也是高廋型的,不会有梯度消失的问题。

由下图可知,在新的权重初始化策略下,网络很快就收敛了,比之前的方法快很多。

怎样选择超参数

大原则:在网络优化的前期,尽量使网络结构、问题简单,以便快速得实验结果,不断尝试超参数取值,当找到正确的优化方向后,再慢慢把网络和问题变复杂,精细调整超参数。比如MNIST问题,开始可以减少训练数据,只取0和1的图片,做二分类;同时可以减少网络层数,验证集大小等,以便快速得到网络输出,判断网络性能变化。这样可以快速尝试新的超参数。

学习率\eta

在误差反向传播中,学习率太大,虽然可以加速学习,但在后期可能导致网络震荡,无法收敛;学习率太小,导致学习速度太慢,训练时间过长。

确定学习率的方法是:首先随便选定一个值,比如0.01,然后不断增大10倍:0.1, 1, 10, 100...如果发现cost曲线在震荡,说明选大了,要降低,直到找到一个比较合适的值。这个过程只要找到合适的数量级就可以了,不一定要非常精确。比如发现0.1是比较合适的,那么可以再尝试0.2,0.3...,如果发现0.5不错,可以设学习率为0.5的一半0.25,这样可以使得在后续epoch中,不容易发生震荡。最好的方法是可变学习率,即前期学习率稍大(0.5),后期学习率稍小(0.1)之类的。

epoch

no-improvement-in-ten rule,就是说如果模型在最近的10个epoch中,验证集的accuracy都没有提高,则可以stop了。在早期实验中可以这么做,后续精细优化时可以改变ten,比如no-improvement-in-20/30等。

正则化参数\lambda

首先不要正则(\lambda=0),使用上面提到的方法确定学习率\eta,在确定的学习率情况下,正则\lambda=1开始进行优化,比如每次乘以10或者除以10,观察验证集上的accuracy指标,找到正则化所在的合适的数量级,然后再fine-tune。

Mini-batch size

太小了,无法利用现有软件包的矩阵操作的优势,速度会很慢。极端情况下,如果mini-batch size=1,就是说每次只用一个sample做BP,则100次mini-batch=1会比一次mini-batch=100操作慢很多,因为很多软件包对矩阵操作有优化,而没有对for循环优化。太大了,则一次BP要很久,参数更新的次数也比较少。

其他技术

随机梯度下降SGD的变种

海森矩阵法

SGD优化的目标就是最小化损失函数CC是所有参数w = w_1, w_2, \ldots的函数,即C=C(w)。希望能够通过改变w,不断最小化C,即找一个\Delta w,使得C(w+\Delta w)最小化。把C(w+\Delta w)泰勒展开得到:

\begin{eqnarray}C(w+\Delta w) & = & C(w) + \sum_j \frac{\partial C}{\partial w_j} \Delta w_j\nonumber \\ & & + \frac{1}{2} \sum_{jk} \Delta w_j \frac{\partial^2 C}{\partial w_j\partial w_k} \Delta w_k + \ldots\tag{1}\end{eqnarray}

写成矩阵形式就是:

\begin{eqnarray}C(w+\Delta w) = C(w) + \nabla C \cdot \Delta w +\frac{1}{2} \Delta w^T H \Delta w + \ldots,\tag{2}\end{eqnarray}

其中的\nabla C就是常规的梯度向量,H就是著名的海森矩阵,其中H_{jk}=\partial^2 C / \partial w_j \partial w_k。如果把(2)中的高阶项扔掉,得到如下的近似等式:

\begin{eqnarray} C(w+\Delta w) \approx C(w) + \nabla C \cdot \Delta w +\frac{1}{2} \Delta w^T H \Delta w.\tag{3}\end{eqnarray}

最小化(3)的右边,得:

\begin{eqnarray}\Delta w = -H^{-1} \nabla C.\tag{4}\end{eqnarray}

所以我们可以通过如下方式更新w已达到最小化C的目的,当然也可以给\Delta w乘上学习率\eta

海森矩阵法有点像通过解析的方式最小化C,感觉上比SGD方法更精确靠谱。事实上,海森矩阵法确实比SGD方法收敛速度更快,但是因为在公式(4)中需要求解海森矩阵H的逆矩阵H^{-1},当网络的参数量很大时,求解过程会非常慢,导致海森矩阵法不实用。

基于动量的梯度下降

增加速度这个变量,个人不是太理解:

\begin{eqnarray} v & \rightarrow & v' = \mu v - \eta \nabla C \tag{5}\\w & \rightarrow & w' = w+v'.\tag{6}\end{eqnarray}

不同的激活函数

tanh是和sigmoid很像的一个激活函数,其函数形式为:

\begin{eqnarray}\tanh(z) \equiv \frac{e^z-e^{-z}}{e^z+e^{-z}}.\tag{7}\end{eqnarray}

事实上,sigmoid函数\sigma(z)\tanh(z)有线性关系:

\begin{eqnarray} \sigma(z) = \frac{1+\tanh(z/2)}{2},\tag{8}\end{eqnarray}

\tanh(z)的函数图像如下,和sigmoid非常类似:

\tanh(z)和sigmoid的主要区别就是值域不一样,前者值域为[-1,1],后者值域为[0,1]。这会导致什么差异呢?观察(BP4)这个公式,对于第l层的第j个神经元和第l-1层的所有神经元的连接权重w_{jk}^l,如果使用sigmoid激活,则a_k^{l-1}都是非负的,而这些梯度共用一个\delta_j^l,所以对于固定的j,不同的k,所有的梯度\frac{\partial C}{\partial w^l_{jk}}方向是一样的!这在无形中就减小了搜索空间。而如果用\tanh(z)激活的话,不同的ka^{l-1}_k正负号可能就不一样,搜索空间更大,跟容易收敛。

另一个比较常见的激活函数是ReLU激活函数,其函数形式如下:

ReLU(z)=max(0, z)\tag{9}

函数图像如下:

ReLU和Sigmoid、tanh很不一样,ReLU在z>0的方向上不会有梯度消失的问题。

好了,第三章的内容就全部介绍完毕了,这一章介绍了很多调试神经网络的经验法则,没有太多的理论基础,相信随着这个领域的发展,神经网络的黑盒子会被慢慢打开。

Leave a Reply

Your email address will not be published. Required fields are marked *