在训练神经网络之前,必须对其进行初始化。然而,与深度学习的任何方面一样,初始化的方式有很多种。随机初始化神经网络的权重就是其中之一。事实上,它经常被建议作为初始化神经网络的方式。
然而,由于两个问题——梯度消失问题和梯度爆炸问题,这可能并不完全正确。在这篇文章中,我们将探讨这两个问题,并找到在很大程度上克服它们的方法。
在此之前,我们必须首先简要回顾一下为什么需要权重初始化。接下来,我们将讨论随机初始化以及如何实现它。一旦我们理解了神经网络的优化方式,我们就可以介绍这两个问题以及可能的解决方案。
权重初始化的必要性
我认为在深入细节之前,提供一些背景信息是必要的。
在这个情况下,背景信息如下:为什么首先需要权重初始化?
简单来说,神经网络由各种神经元组成。这些神经元是线性运算(我称之为向量点积加偏置)和可能的非线性运算(称为激活)的组合。
在后者,也称为激活函数中,向线性运算的线性输出中添加了非线性。如果不这样做,神经网络的表现将不会比线性模型更好——而过去几年所取得的所有进步也就不可能实现。
今天,我们感兴趣的是第一部分,即线性运算本身。在这个运算中,所谓的输入向量与权重向量相乘,然后在乘法结果上加上一个偏置值。让我们稍微更详细地分解一下这些向量:
然而,在训练过程开始之前,所有权重向量都必须用一些数字进行初始化或配置。它们不能是空的,因为空向量无法正确地进行乘法运算。你可能已经猜到了,有很多初始化器……其中随机初始化是最广为人知的一种。
随机初始化
随机初始化,顾名思义,就是随机地初始化权重。
有两种方法可以实现随机初始化:通过正态分布和通过均匀分布。
均匀分布
这就是均匀分布:
别担心,这其实很容易理解。
你所看到的是均匀分布的概率分布,它基本上表示的是:当我随机抽取一个数字时,该数字在范围a <= x <= b内的概率是1/(b-a),如果数字在这个范围之外,则概率为0。
有趣的事实:这是一个连续分布。也就是说,在上面指定的区间内有无限多个实数。因此,你找到某个特定数字的概率是0。
通常,在配置深度学习中的均匀分布时,可以输入以下变量:
在这种情况下,最小值是a,最大值是b。
正态分布
这是正态分布:
和均匀分布一样,正态分布也是一个连续分布。
事实上,它是使用最广泛的概率分布之一;如果配置得当,许多自然现象都可以根据这个分布来描述。
具体来说,你可以配置均值和标准差,并且再次为分布设定一个特定的(伪)随机数生成器的种子。
有趣的事实:与均匀分布中你需要手动配置可能的值范围不同,在正态分布中你不需要这样做。
理论上,这意味着你可能会得到任何实数作为结果。然而,正如你在上面的图片中看到的那样——例如,用红色显示的标准正态分布——你的数字最有可能落在[-3, +3]的范围内。
选择哪个分布?
现在你已经知道均匀分布和正态分布在深度神经网络中都经常被使用,你可能会想:那么我应该使用哪个分布呢?
……当然,这是在你选择随机初始化它们的情况下。
或者至少,目前还不清楚哪一个比另一个更好。
事实上,在那篇关于初始化问题的帖子中,作者提到,在Glorot等人以及He等人讨论随机初始化问题的论文中,他们分别使用了这两种分布:Glorot的论文使用的是均匀分布,而He的论文使用的是正态分布。
因此,选择哪个随机统计分布来初始化你的权重似乎取决于你自己。
但在某些条件下,随机初始化本身可能会成为问题:你可能会面临梯度消失和梯度爆炸的问题。在我们介绍这些问题之前,我们先简要看看大多数神经网络是如何优化的。
优化神经网络:梯度下降和反向传播
当你训练神经网络时,你本质上是在给它输入数据,让它做出预测,然后计算误差或损失。
这被称为数据的前向传播。
现在,你可以将损失视为高度依赖于你的数据的数学函数。函数可以被优化,即可以找到它们的最小值。
那么模型在哪里表现最好呢?当然是在损失最小的时候。
计算梯度
因此,通过计算损失函数的导数,你可以得到一个梯度,用于改进神经网络的最后一个隐藏层。通过稍微将权重向梯度的方向移动,你的模型预计会“走向”损失最小的方向,从而得到改进。
我们称这为梯度下降,而且我们经常使用随机梯度下降。
链式梯度
然而,神经网络由多层组成,而不仅仅是一层。
我们不能简单地再次为倒数第二层隐藏层取梯度,因为它与最后一层有内在联系。因此,在计算这一层的梯度时,你总是需要考虑给定梯度的损失函数的梯度。
对于下一层,你将重复这个过程,但这次也要包括倒数第二层隐藏层。
以此类推。
你本质上是在创建一个梯度链,通过相乘来找到改进当前层的梯度。
我们称这为反向传播。
如你所见,优化神经网络包括:
梯度消失
通过相乘来链接梯度以找到任意层的梯度,你会遇到一个奇怪的特性:所谓的梯度消失问题。
正如你从正态分布中看到的那样,举一个例子,大多数值都相对较低,比如在+3和-1之间。事实上,你随机选择一个大于-1且小于1的数字的概率是最大的,即-0.9999999999(…) < x < 0.99999999999(…)。
假设你所有的神经元输出都是0.1,这有点奇怪,但它让我们更容易理解梯度消失的问题。假设你有一些层,并且每层的梯度改进是0.03。那么,在五层上游,考虑到激活函数的输出范围在0到1之间,第六层相对于其他层的梯度改进可能是0.1 x 0.1 x 0.1 x 0.1 x 0.1 x 0.03这样的一个非常小的数字。
这就是梯度消失问题。它意味着你的上游层将学习得非常慢,因为由于梯度是通过链式法则相乘得到的,所以计算出的梯度非常小。
在实际操作中,这可能意味着你需要无限的时间和计算资源才能达到最优值,即最小损失。
但我们显然不希望这样——我们想要得到尽可能好的模型。
梯度爆炸
类似地,在训练过程中也可能发生梯度爆炸问题。基本上,某些神经元会因为经历所谓的溢出而失效。也就是说,数字太大,以至于计算机内存无法处理。
为什么会发生这种情况?
假设你随机初始化你的权重。使用哪种初始化器其实并不重要。你可以想象,在正向传播过程中,由随机权重产生的行为很可能会产生一个非常大的损失,因为它根本不匹配底层数据的分布。
会发生什么?权重的摆动,或者说梯度,可能会非常大。特别是当抽取的随机数大于1或小于-1时。由于输出是通过链式法则相乘得到的,我们就会遇到麻烦。我们不是观察到数字变得越来越小,而是观察到数字变得越来越大。
最终,这会导致数字溢出,结果是NaN(不是一个数字)。其影响是:你的学习过程会受到严重阻碍。
如何应对这些问题?
幸运的是,有解决方法。
Xavier和He初始化器
这些初始化器,即Xavier(或Glorot)和He初始化器,在Keras等工具中都有提供,它们主要做一件事:确保权重被设置为接近1。
这样,就可以在很大程度上避免这些问题。
它们在将抽取的权重调整为接近1的方式上有所不同。因此,它们最好与不同的激活函数一起使用。具体来说,He初始化是为基于ReLU的激活网络开发的,因此最好用于这类网络。对于其他网络,Xavier(或Glorot)初始化通常效果更好。
实验
尽管这些在理论上有效的缓解技术很好,但数据科学和机器学习项目通常有一条普遍适用的建议:实验!
找出什么有效,看看什么失败——并根据你的观察调整你的方法。同时,尝试理解你的黑盒内部发生了什么,从你的观察中得出更通用的见解,以便将来可以重复使用。
简而言之:所有理论都很好,但它必须对你有效。而要达到这一点,只有一条路,那就是通过实践来学习。
总结
在这篇文章中,我们了解了随机初始化是如何工作的,以及为什么它比全零初始化更好。我们也知道了为什么首先需要进行权重初始化。然而,我们也介绍了随机初始化的一些根本问题,即梯度消失和梯度爆炸问题。通过应用更先进的初始化器,如He初始化器或Xavier(或Glorot)初始化器,我们可能最终能够避免这些问题,并获得一个表现良好的模型。