从函数图像上我们还能看到,只有中间围绕零值的一小撮值才有作为梯度的意义,零值两侧的所有导数值都无限接近于零。我们把这两侧导数接近于零的部分,称为激活函数的饱和范围,一旦 Sigmoid 函数的输入值落在这个饱和范围内,其输入的数值大小对激活函数的输出结果的影响就极小了,换言之,我们可以说在这个范围内的激活函数对输入数据不再敏感。
另外,误差反向传播算法在神经网络初始化的时候,其权值 w 通常会小于1,譬如常用均值为 0、标准差为 1 的高斯分布来初始化网络权值。这样便使得 $\mid \partial ^ { \prime } ( x ) w \mid$ 整体将小于 0.25,再结合前面推导的连乘公式,使用链式法则求导,层数越多,势必会使得 $\cdot \frac { \partial E } { \partial x _ { 1 } }$ 的求导结果越小,这就引发了梯度消失问题的出现。类似地,梯度爆炸问题出现的原因就是出现了 $\mid \partial ^ { \prime } ( x ) w \mid > 1$ 的情况。到这里,我们就明白了梯度不稳定问题(梯度消失和梯度爆炸统称为梯度不稳定问题)产生的原因:前面的隐层梯度是后面的各个隐层梯度的连乘积,在神经网络的深度过深时,梯度在反向传播中的连乘效应会导致网络权值更新不稳定。
神经网络深度增加带来的训练上的困难,是深度学习在诞生前几年里难以充分发挥深度优势的主要原因之一。针对梯度不稳定问题,人们想了很多方法来补救。有从神经网络权值初始化着手的,使得 $\mid \partial ^ { \prime } ( x ) w \mid$ 整体尽可能避免梯度逐层减小或者增大,除了前文讲的辛顿的无监督预训练方法外,近几年还出现了一些效果很好的随机初始化方法,如 Xavier 初始化方法、MSRA 初始化方法等。也有从训练过程着手的,如谷歌在 2015 年提出的“批量规范化”(BatchNormalization)操作,这种方法是在训练过程中对隐层的数据进行规范化处理,避免训练过程里各网络层输入落入饱和区间进而导致梯度消失。还有一种易于操作的最简单方法,是直接从激活函数本身着手。既然梯度消失是由 Sigmoid函数的导数最大值仅为 0.25,且不饱和区间非常狭窄所导致的,那么就着手去寻找更好的代替函数。
第 7 章 深度学习时代
279