您的位置:首页 > 理论基础 > 计算机网络

训练深度网络的梯度弥散及梯度膨胀问题

2015-12-27 12:32 387 查看
在深度网络中,不同层的学习速度差异很大。尤其是在网络后面层学习的情况很好的时候,先前的层常常会在训练时停止不变,基本上学不到东西,这些原因是与基于梯度的学习方法有关。

我们用MNIST数字分类问题作为研究和实验的对象:

这个网络有784个输入神经元,对应于图片28*28=784个像素点,我们设置隐藏神经元为30个,输出层为10个神经元,对应于MNIST的10个数字(0~9),我们训练30epochs,使用minibatch大小为10,学习率为0.01,正则化参数为5.0。在训练时我们也会在验证集上监控分类的准确度。最总我们得到分类准确率为96.48%。

现在另外增加一个隐藏层,同样地是 30
个神经元,试着使用相同的超参数进行训练:

net([784, 30, 30, 10])
最终的结果分类准确度提升了一点,96.90%。结构表明:一点点的深度带来了效果。

那么就再增加一层同样的隐藏层:

net ([784, 30, 30, 30, 10])
这里并没有什么提升,反而下降到了96.57%,这与最初的浅层网络相差无几。

再增加一层:

net([784, 30, 30, 30, 30, 10])
分类准确度又下降了,96.53%。

额外的隐藏层应当让网络能够学到更加复杂的分类函数,然后可以在分类时表现得更好,但实验的结果似乎并不是这样的。为更加形象的解释这一现象,我们可以将网络学到的东西进行可视化。

下面,画出了一部分[784, 30, 30, 10] 的网络,也就是包含两层各有30 个隐藏神经元的隐藏层。图中的每个神经元有一个条形统计图,表示这个神经元在网络进行学习时改变的速度。更大的条意味着更快的速度,而小的条则表示变化缓慢。更加准确地说,这些条表示了每个神经元上的cost function关于偏置项b的偏导数,也就是代价函数关于神经元的偏差更变的速率delta。因为我们知道delta的数值不仅仅是在学习过程中偏差改变的速度,而且也控制了输入到神经元权重的变量速度。

为了让图里简单,只展示出来最上方隐藏层上的6 个神经元,这里所示的只是中间两个隐藏层,在网络初始化后立即得到训练前期的结果如下:



从上图中我们可以明显的发现这样一个规律,第二个隐藏层上的数值基本上都要比第一个隐藏层上的要大。所以,在第二个隐藏层的神经元将学习得更加快速。为了进一步解释上一结论,使用一种全局的方式来比较学习的速度。我们使用向量delta1和delta2分别表示第一个和第二个隐藏层的学习速率,向量中的每个元素表示该层上每个神经元的小学习速率:

所以,我们可以使用这些向量的长度作为全局衡量这些隐藏层的学习速度的度量。||delta1|| 就代表第一层隐藏层学习速度,而||delta2|| 就代表第二层隐藏层学习速度。
借助这些定义,在和上图同样的配置下,发现||delta1|| = 0.07而||delta2|| =0.31,所以通过数量上的计算也说明了在第二层隐藏层的神经元学习速度确实比第一层要快。

对于三个隐藏层的情况,比如在[784, 30, 30, 30, 10] 的网络中,那么对应的学习速度就是 0.012, 0.060, 0.283。也证明了我们上面的结论。假设我们增加另一个包含30 个隐藏神经元的隐藏层[784, 30, 30, 30, 30, 10] 对应的学习速度是:0.003,0.017, 0.070, 0.285。还是同样说明了前面的层学习速度低于后面的层。
上述的全局速度的计算是刚刚初始化之后的情况。随着训练的推移学习速度变化如下:
对于只有两个隐藏层时net([784, 30, 30, 10]),为了防止使用minibatch随机梯度下降对结果带来更多的噪声,我在 1000 个训练图像上进行了 500 轮 batch 梯度下降,而没有使用minibatch方法。

如图所示,两层在开始时就有着不同的速度。然后两层的学习速度在触底前迅速下落。在最后,我们发现第一层的学习速度变得比第二层更慢了。

对于只有三个隐藏层时net([784, 30, 30, 30, 10]),同样前面的隐藏层要比后面的隐藏层学习的更慢。

对于有四个隐藏层时net([784,
30, 30, 30, 30, 10]),也可以得到与前两种情况相同的结论:前面的隐藏层要比后面的隐藏层学习的更慢。这里,第一层的学习速度和最后一层要差了两个数量级,也就是比第四层慢了100倍,这就比较容易解释为什么在MNIST手写数字识别时,4个隐藏层的网络的效果并没有比2个隐藏层的要好,因为这种速度的下降从另一个角度看实际上是梯度的消失,即使隐藏层多了,但是却并没有学到知识。上述的现象就是我们在深度学习中经常会遇到的梯度弥散问题(vanishing
gradient problem
)或梯度消失问题

相似的,对于在前面的层中的梯度会变得非常的情况称为爆炸的梯度问题(exploding gradient problem)或梯度膨胀问题。更加一般地说,在深度神经网络中的梯度是不稳定的,在前面的层中或会消失,或会爆炸。这种不稳定性才是深度神经网络中基于梯度学习的根本问题。这就是我们需要理解的东西,如果可能的话,采取合理的步骤措施解决问题。

为了进一步弄清楚为何会出现消失的梯度,来看看一个极简单的深度神经网络:每一层都只有一个单一的神经元。下图就是有三层隐藏层的神经网络:

从第 j 个神经元的输出:aj = sigmoid(zj),其中zj为带权输入。

下面求目标函数C关于第一个神经元的梯度:

先看看下面的sigmoid 函数导数的图像:

也就是说sigmoid函数的导数在0出取得最大值1/4。现在,如果我们使用标准方法来初始化网络中的权重,那么会使用一个均值为0 标准差为 1 的高斯分布。因此所有的权重通常会满足|wj| < 1。所以权重与sigmiod函数导数的乘积是小于1/4的。并且在我们进行了所有这些项的乘积时,最终结果肯定会指数级下降:项越多,乘积的下降的越快。这里我们可以理解了消失的梯度问题的合理解释。

比较目标函数关于第三个神经元和第一个神经元的梯度值,两个表示式有很多相同的项。但是后者还多包含了两个项。由于这些项都是小于1/4的,所以后者的梯度值是前者的 1/16 或者更小。这其实就是消失的梯度出现的本质原因了。
如果乘积项变得很大超过 1,那么我们将不再遇到消失的梯度问题,这时候梯度会在我们 BP 的时候发生指数级地增长。也就是说,我们遇到了梯度爆炸或梯度膨胀的问题,但由于目前我们的初始化策略以及所使用的激活函数的关系,梯度膨胀问题很少出现。

梯度弥散和梯度膨胀都属于不稳定的梯度问题:根本的问题其实是在前面的层上的梯度是来自后面的层上项的乘积。当存在过多的层次时,就出现了内在本质上的不稳定场景。唯一让所有层都接近相同的学习速度的方式是所有这些项的乘积都能得到一种平衡。如果没有某种机制或者更加本质的保证来达成平衡,那网络就很容易不稳定了。简而言之,真实的问题就是神经网络受限于不稳定梯度的问题。所以,如果我们使用标准的基于梯度的学习算法,在网络中的不同层会出现按照不同学习速度学习的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: