深度学习优化算法入门:一、梯度下降
精品文章,第一时间送达
来源:paperspace
编译:weakish
转载自:论智,未经允许不得二次转载
编者按:DRDO研究人员Ayoosh Kathuria深入浅出地介绍了梯度下降这一概念。
图片来源:O’Reilly Media
深度学习在很大程度上是在解决大规模的烦人的优化问题。神经网络不过是一个包含数百万参数的非常复杂的函数。考虑图像分类的例子。AlexNet是一个数学函数,接受表示图像的RGB值的数组作为输入,产生一组分类评分作为输出。
我们所说的训练神经网络,基本上是指最小化一个损失函数。损失函数的值为我们提供了网络在给定数据集上的表现离完美有多远的测度。
损失函数
为了简化问题,假定我们的网络只有两个参数。在实践中,网络可能有上亿参数,不过在本文中,我们将一直使用两个参数的网络作为例子,以便可视化。一个非常好的损失函数的等值曲面看起来可能是这样。
为什么我要说非常好的损失函数?因为具备上图这样的等值曲面的损失函数就像圣人一样,基本上是不存在的。不过,它在教学上能起到很好的作用,可以帮助我们理解梯度下降最重要的一些想法。所以,让我们开始吧!
图中的x轴和y轴表示两个权重的值。z轴表示损失函数的值。我们的目标是找到损失值最小的权重值。
刚开始,我们随机初始化权重,所以神经网络大概就像一个醉汉,将猫的图像识别成人类。也就是下图中的A点,网络表现很差,损失很高。
我们需要找到一种到达“谷底”B点(损失函数最小值)的方法。我们该怎么做呢?
梯度下降
初始化权重时,我们在损失曲面的A点。我们首先要做的,是检查一下,在x-y平面上的所有可能方向中,沿着哪个方向移动能带来最陡峭的损失值下降。这就是我们需要移动的方向。这一方向恰好是梯度的反方向。梯度,导数的高维表兄弟,为我们提供了最陡峭的上升方向。
下图可以帮助你理解这一点。在曲面的任一点,可以定义一个正切的平面。在更高维情形下,我们可以定义一个超平面。不过现在还是让我们保持三维吧。我们在这个平面上有无穷方向,其中正好有一个方向能提供函数最陡峭的上升。这个方向就是梯度的方向。这也正是算法得名的原因。我们沿着梯度反向下降,所以称为梯度下降。
现在,有了移动的方向,我们需要决定移动的步幅。这称为学习率。我们必须仔细选择学习率,以确保达到最小值。
如果学习率过快,我们可能越过最小值,在谷“脊”不断反弹,再也到不了最小值。如果学习率过慢,训练可能过于漫长而不再可行。即便不是这样,非常低的学习率可能使优化算法更容易陷入局部极小值(我们稍后将介绍局部极小值)。
一旦确定了梯度和学习率,我们开始训练一步,然后在停留处重新计算梯度,接着重复这一过程。
梯度的方向告诉我们哪个方向有最陡峭的上升,而它的数量则告诉我们最陡峭的上升/下降有多陡。所以,在最小值处,等值曲面几乎是平的,相应地,梯度几乎是零。事实上,最小值处的梯度正好是零。
梯度下降中
学习率过大
在实践中,我们也许从未恰好达到最小值,而是在最小值附近的平面区域反复振荡。在这一区域振荡时,损失几乎是我们可以达到的最小值,因为我们在实际最小值附近反复回弹,所以损失值几乎没什么变化。当损失值在预定义的迭代次数(比如,10次或20次)后没有改善时,我们常常停止迭代。这时我们称训练收敛了。
常见误解
让我稍稍停顿一下。如果你上网搜索梯度下降的可视化图像,你大概会看到从某一点开始,朝向最低点的一条轨迹,就像前面的动画一样。然而,这只是一个不精确的示意。实际上,轨迹完全被限制在x-y权重平面上,完全不涉及z轴上的移动。这是因为权重是唯一的自由参数。
x-y平面的每一点表示权重的一种独特组合,我们想要找到损失值最小的权重组合。
基本等式
描述梯度下降更新规则的基本等式是:
每次迭代均进行这样的更新。上式中,w是位于x-y平面的权重向量。我们从这个向量减去损失函数在权重上的梯度乘以alpha,学习率。梯度也是一个向量,提供损失函数上升最陡峭的方向。最陡峭下降的方向正好是梯度的反方向,所以我们从权重向量中减去梯度向量。
如果想象向量对你来说有点难,你可以想像梯度下降同时应用于网络的所有权重,按照几乎一样的更新规则。唯一的不同是,由于我们现在为每个权重分别应用更新,上式中的梯度替换为梯度向量在表示具体权重的方向上的投影。
我们乘上了学习率,对应我们之前提到的步幅。注意,即使学习率是常数,由于梯度数量(损失曲面的陡峭程度)的变动,步幅仍然会改变。当我们逼近最小值时,梯度逼近零,我们以越来越小的步子迈向最小值。
理论上这很好,因为我们希望算法在逼近最小值时采用较小的步幅,以免过大的步幅导致越过极小值,并在极小值周围的谷脊间反复回弹。
梯度下降中广泛采用的一项技术是使用可变学习率,而不是固定学习率。刚开始,我们可以接受较大的学习率。之后,随着训练进行,我们渐渐接近最小值,这时我们想要放慢学习率。实现这一策略的一种方法是模拟退火,又称学习率衰减。在这种方法中,学习率在固定数目的迭代之后衰减。
梯度下降的挑战之一:局部极小值
好吧,目前为止,梯度下降看起来是一个非常美好的童话。不过我要开始泼凉水了。还记得我之前说过,我们的损失函数是一个非常好的函数,这样的损失函数并不真的存在?
首先,神经网络是复杂函数,具有大量非线性变换。由此得到的损失函数看起来不像一个很好的碗,只有一处最小值可以收敛。实际上,这种圣人般的损失函数称为凸函数,而深度网络的损失函数几乎总是非凸的。事实上,损失函数可能是这样的:
上图中有一个梯度为零的局部极小值。然而,我们知道那不是我们能达到的最低损失(全局最小值)。如果初始权重位于点A,那么我们将收敛于局部极小值,一旦收敛于局部极小值,梯度下降无法逃离这一陷阱。
梯度下降是由梯度驱动的,而梯度在任何极小值处都是零。局部极小值,顾名思义,是损失函数在局部达到最小值的点。而全局最小值,是损失函数整个定义域上可以达到的最小值。
让事情更糟的是,损失等值曲面可能更加复杂,实践中可没有我们考虑的三维等值曲面。实践中的神经网络可能有上亿权重,相应地,损失函数有上亿维度。在那样的图像上梯度为零的点不知道有多少。
事实上,可视化这样的高维函数很难。然而,因为现在有很多极具天赋的人从事深度学习研究,人们找到了以3D形式可视化损失函数的等值曲面的方法。最近的一篇论文提出了过滤器归一化(Filter Normalization)技术,本文就不解释它的具体做法了。我们只要知道,它能够为我们提供呈现损失函数复杂性的视图。例如,下图表示VGG-56深度网络在CIFAR-10数据集上的损失函数:
图片来源:cs.umd.edu/~tomg
如你所见,上面遍布局部极小值。
梯度下降的挑战之二:鞍点
我们碰到的另一种问题是鞍点,看起来是这样的:
之前的图片中,双“峰”交汇处也有一个鞍点。
鞍点因形状像马鞍而得名。鞍点处,梯度在一个方向(x)上是极小值,在另一个方向上则是极大值。如果沿着x方向的等值曲面比较平,那么梯度下降会沿着y方向来回振荡,造成收敛于最小值的错觉。
随机性是救星!
所以,我们该如何逃离局部极小值和鞍点,努力收敛于全局最小值呢?答案是随机性。
目前为止,我们进行梯度下降时计算的损失函数累加了训练集中所有可能样本上的损失。如果我们碰到局部极小值或鞍点,我们便陷入其中。帮助梯度下降摆脱这些的一种方法是使用随机梯度下降。
随机梯度下降并不通过累加所有损失函数计算损失,而是计算随机取样(无放回)的样本的损失。和随机选取一个样本的随机梯度下降不同,我们之前的方法在一个batch内处理所有样本,因此称为批量梯度下降。
相应地,随机梯度下降的更新规则为:
基于“单样本损失”计算出的梯度,方向和基于“全样本损失”计算出的梯度可能略有不同。因此,当“全样本损失”可能将我们推入局部极小值,或让我们陷于鞍点时,“单样本损失”梯度可能指向不同的方向,也许能帮助我们避开局部极小值和鞍点。
即使我们陷入了“单样本损失”的局部极小值,下一个随机取样的数据点的“单样本损失”可能不一样,让我们得以继续移动。
当它真的收敛时,它收敛于根据几乎所有“单样本损失”计算得出的最小值。同时,经验表明,鞍点极为不稳定,小小的轻推可能就足以逃离鞍点。
所以,这是否意味着,在实践中,我们应该总是进行这样的单样本随机梯度下降?
batch大小
答案是否。尽管理论上,随机梯度下降也许能为我们提供最好的结果,从算力上看,它是一个不太可行的选项。随机梯度下降时,我们需要一步一步地计算损失,而在批量梯度下降时,单独损失的梯度可以并行计算。
因此,我们在这两种方法之间寻找一个平衡。我们既不使用整个数据集,也不仅仅基于单个样本构造损失函数,我们使用固定数量的样本,比如,16、32、128,这称为mini-batch。之所以称为mini-batch,是为了区别批量(batch)梯度下降。选择合适的mini-batch大小,可以确保我们既能有足够的随机性以摆脱局部极小值,又能充分利用并行处理的算力优势。
重新审视局部极小值:它们并没有你想像的那么糟糕
在你仇视局部极小值之前,先看下最近的研究吧。最近的研究表明,局部极小值并不一定不好。在神经网络的损失曲面上,有太多的极小值了。“良好”的局部极小值表现可能和全局最小值一样好。
为什么我说“良好”?因为我们仍然可能陷入难以预测的训练样本导致的“糟糕”的局部极小值。“良好”的局部极小值,文献中常称为最优局部极小值,在神经网络的高维损失函数中,可以有相当多个。
另外,许多神经网络进行的是分类任务。如果局部极小值对应的正确标签的分值在0.7-0.8之间,而同一样本全局最小值对应的正确标签的分值在0.95-0.98之间,最终得到的输出分类预测是一样的。
我们希望极小值具有的性质是它位于较平坦的一边。为什么?因为平坦极小值更容易收敛,跳过极小值、在极小值周围的“谷脊”反复回弹的概率更低。
更重要的是,预测集的损失曲面一般和训练集的略有不同。平坦宽阔的极小值,从训练集到预测集的切换不会改变太多损失,而狭窄的极小值则不然。更平坦的极小值推广性更好。
重新审视学习率
最近涌现了一堆学习率规划的研究,以避免收敛于损失曲面的次优极小值。即使使用学习率衰减,仍有可能陷入局部极小值。传统上,训练或者在固定数目的迭代之后结束,或者在损失没有改善的10个(比方说)迭代后结束(文献中称为及早停止)。
更高的学习率也有助于帮助我们在训练早期逃离局部极小值。
也有人组合了及早停止和学习率衰减,每次遇到10个损失没有改善的迭代,就降低学习率,并在学习率低于某个预订的阈值时停止训练。
近年来也曾流行周期学习率,缓慢增加学习率,然后降低学习率,循环往复。
图片来源:Hafidz Zulkifli
还有称为热重启随机梯度下降的技术,基本上就是学习率退火至下界后,还原学习率为原值。
还有不同的学习率衰减的规划方案,从指数衰减到余弦衰减。
余弦衰减搭配重启
最近的一篇论文又引入了随机权重平均的技术。作者研发了一种新方法,首先收敛于一个极小值,缓存权重,然后还原到较高的学习率。这一较高的学习率将算法推离极小值,到损失曲面上的一个随机点。接着算法收敛于另一个极小值。重复几次后,对所有缓存的权重取平均,基于平均权重作出预测。
结语
梯度下降就介绍到这里了。不过我们还漏了一点没讲,如何应对病态曲率。随机梯度下降的一些扩展,如动量、RMSProp、Adam可以用来克服这一问题。
不过我觉得我们介绍的内容对一篇博客文章来说已经够多了,剩余的内容将在另一篇文章中介绍。
参考资料
-
可视化神经网络的损失曲面(论文): arXiv:1712.09913
-
Hafidz Zulkifli关于学习率规划的文章:https://towardsdatascience.com/understanding-learning-rates-and-how-it-improves-performance-in-deep-learning-d0d4059c1c10
-
随机权重平均(论文): arXiv:1704.00109
原文地址:https://blog.paperspace.com/intro-to-optimization-in-deep-learning-gradient-descent/
你也许还想看:
● 快速学习 Python 的全套 14 张思维导图(附高清版下载)
● 教程 | 计算任意视频中各人物的出镜时间(附Python实现)
欢迎扫码关注:
原创文章,作者:fendouai,如若转载,请注明出处:https://panchuang.net/2018/10/18/91355f0f79/