理解激活函数
了解在构建深度神经网络模型时激活函数的作用。
本章概述
深度网络本身并无特殊之处,它们与浅层神经网络类似,只是层数更多。然而,当人们开始尝试深度网络时,逐渐意识到:构建深度网络或许容易,但训练它们却并不简单。
在深度网络上进行反向传播会带来特有的挑战,例如梯度消失和神经元失效(死亡)。这些问题在浅层网络中很少出现。
多年来,研究人员发展出一系列策略来应对这些挑战,从而有效驾驭深度神经网络:
- 替代 Sigmoid 的新型激活函数
- 多种形式的梯度下降方法
- 更高效的权重初始化方式
- 更强的正则化技术以防止过拟合
- 其他行之有效但难以归类的方法
本章将快速浏览这些技术。我们将重点讨论激活函数,深入分析为何 Sigmoid 不适用于深度神经网络,以及如何用更好的函数替代它。最后,我们还将简要介绍上述其他类别中的一些选择和方法。
激活函数的作用
我们已经熟悉了激活函数——即神经网络各层之间那些青色的小方框,如下图所示:
到目前为止,除了输出层使用了 Softmax 函数外,我们所使用的激活函数都是 Sigmoid。
Sigmoid 已经伴随我们很长时间。最初它被引入是为了将感知机的输出压缩到 0 到 1 之间。后来我们又学习了 Softmax,用于调整神经网络输出使其总和为 1,从而可以解释为概率。但现在我们要构建的是深度神经网络,这些原始动机似乎已不再适用。激活函数让网络变得更复杂,看起来却没有带来相应的收益。
让我们看看如果从神经网络中移除激活函数会发生什么。没有激活函数的神经网络如下所示:
这个网络看起来确实更简单了。但它存在一个严重限制:所有操作都是线性的,也就是说,它们的图像都可以用直线表示。为了理解这种线性带来的后果,我们来做一点简单的数学推导。
在一个没有激活函数的网络中,每一层(共 n 层)都是前一层节点的加权和:
我们可以把这些公式合并起来,将最后一层表示为第一层与中间所有权重矩阵相乘的结果:
现在,如果我们把所有权重矩阵的乘积记作 w,那么上式就变为:
换句话说,整个神经网络被简化成了一个单一的加权和:
由此我们可以得出结论:无论堆叠多少线性操作,最终结果仍然是一个线性操作。具体来说,一个完全由线性运算构成的网络,最终会退化成一个微弱的线性回归模型,就像我们在“高维空间”一章中编写的程序那样。
激活函数之所以重要,正是因为它具有非线性特性——其图像不是直线。非线性是神经网络的根本所在。
我们刚刚认识到非线性激活函数至关重要。但这并不意味着我们必须固守 Sigmoid 和 Softmax。我们可以用其他非线性函数来替代它们,尤其是对于 Sigmoid 来说,这可能是个明智之举。接下来我们就来看看原因。
Sigmoid 及其问题
Sigmoid 函数如下图所示:
我们知道激活函数必须是非线性的——不能是直线。弯曲的 Sigmoid 看似满足这一要求。
初看之下,Sigmoid 也似乎很适合反向传播。还记得链式法则吗?神经网络的整体梯度是各个组件局部梯度的乘积。Sigmoid 提供了一个平滑的局部梯度,这条曲线非常光滑,没有任何断裂点、尖角或突变,不会干扰梯度下降过程。
然而,仔细观察后,Sigmoid 的缺陷就开始显现。下面我们来详细讨论这些问题。
再谈失效神经元
设想我们在训练过程中暂停网络,并读取其中各节点的值。之前我们学到一个重要原则:希望这些值保持较小。在“数值稳定性”部分我们了解到,大数值可能导致溢出;而在“失效神经元”部分我们进一步发现,大数值会减慢甚至完全停止网络的训练。让我们回顾一下什么是失效神经元。
如果神经网络中存在较大的数值,这些数值最终会传入 Sigmoid 函数。当 Sigmoid 接收到很大的正数或负数输入时,就会进入饱和状态——运行在其 S 形曲线两端的长尾区域。在这两个尾部区域,梯度接近于零,导致梯度下降几乎停滞。
下图展示了这种情况:
Sigmoid 的梯度最大值为 0.25,出现在中心位置。一旦偏离中心进入两侧尾部,梯度迅速下降。当 Sigmoid 输入较大时,就会陷入恶性循环:
- 输入越大,梯度越小;
- 梯度越小,梯度下降越慢;
- 梯度下降越慢,网络权重更新越少;
- 权重变化越少,Sigmoid 输入就越难回到零附近。
一旦进入这种循环,Sigmoid 前面的神经元就会变成失效神经元。梯度下降无法更新它们,学习过程就此停止。若网络中此类神经元过多,整个反向传播过程将变得极其缓慢。
这个问题还受到另一个细微因素的加剧:Sigmoid 的输出是偏置的。当输入接近零时,Sigmoid 会将其映射到接近 0.5 的值。而我们已知接近零的数值通常更有利,因此 Sigmoid 主动将网络中的数值推离零点,这是不利的。
总结来说,Sigmoid 只有在网络数值接近零时才能良好工作。这是一个苛刻的要求,尤其因为 Sigmoid 自身倾向于将数值推离零点。随着数值越来越远离零,它们会拖慢反向传播并导致神经元失效。网络越深,包含的 Sigmoid 越多,这个问题就越严重。
这些问题自人们开始在神经网络中使用 Sigmoid 起就已被知晓。但在深度网络中,它们引发了一个更严重的问题,困扰机器学习研究者多年。
梯度消失
我们再来回顾一下反向传播的工作机制:
反向传播从输出层 Softmax 的局部梯度开始,依次乘以前一层加权和(记作 )的梯度,再乘以前一个 Sigmoid 的梯度,如此往复,直到第一层。第一层的梯度等于所有累积的局部梯度的乘积。
如前文所述,Sigmoid 的局部梯度是一个介于 0 到 0.25 之间的很小的数。每当反向传播经过一个 Sigmoid,整体梯度就会被这个小数乘一次,从而变得更小。如果网络层数很多,含有大量 Sigmoid,则最前面几层接收到的梯度将极其微弱,其权重几乎不再更新。
随着梯度在网络中向后传递,其值逐渐趋近于零,这就是所谓的梯度消失问题。这使我们陷入两难境地:想要更强的模型就需要增加层数;但层数越多,前面层的梯度就越小,最终导致这些层停止学习。无论是否增加层数,我们都面临困境。
综上所述,我们发现了 Sigmoid 的两个主要问题:
- 失效神经元:当输入较大时,Sigmoid 的梯度趋于零;
- 梯度消失:每个 Sigmoid 都会使网络总梯度不断缩小,导致前面层接收到的梯度接近于零。
这两个问题都会导致极小的梯度,从而严重拖慢甚至彻底中断反向传播。
梯度消失还有一个对应的问题叫做梯度爆炸。在这种情况下,梯度的绝对值在反向传播过程中不断增大而非减小。网络中的大数值会引发各种问题,包括神经元失效和数值溢出。
与梯度消失类似,梯度爆炸也是由于链式法则将所有局部梯度相乘所致。如果这些局部梯度过大,网络的整体梯度就会急剧增长。这可能是由于初始权重设置过大,或者网络中使用了会产生大梯度的激活函数。尽管 Sigmoid 存在诸多缺点,但它在此问题中并非元凶,因为它的梯度始终很小。
有一些技术可以降低梯度爆炸的风险。
科学家们曾长期困惑于为何深度网络如此难以训练。直到他们真正理解了这些问题之后,才得以发明解决方案。我们花了一些时间来剖析 Sigmoid 的问题,但这与研究人员花费多年才识别出这些问题相比,已是微不足道。一旦理解了问题本质,研究者们便提出了有效的解决办法。