作者:Hafidz Zulkifli
编译:ronghuaiyang
导读
把学习率用好,也能提升深度学习模型的性能,一起来看看吧!
这篇文章试图记录我对以下主题的理解:
- 学习率是什么?它的意义是什么?
- 如何系统地达到一个良好的学习率?
- 为什么我们在训练过程中要改变学习率?
- 在使用预训练的模型时,我们如何处理学习速率?
这篇文章大部分是基于过去fast.ai研究员写的东西。这是它的一个简洁版本,以一种让人快速接触到材料的实质的方式排列。请仔细阅读参考资料以了解更多细节。
首先,什么是学习率?
学习率是一个超参数,它控制着我们根据损失梯度调整网络权重的程度。值越低,我们沿着向下的斜率走得越慢。虽然这可能是一个好主意(使用低学习率),以确保我们不会错过任何局部最小值,但这也可能意味着我们将花费很长时间来收敛—特别是当我们陷入平稳地区。
下面的公式显示了这种关系。
new_weight = existing_weight — learning_rate * gradient
通常情况下,学习速率是由用户随机设置的。最好的情况是,用户可以利用过去的经验(或其他类型的学习材料)来获得关于在设置学习速率时使用什么是最佳价值的直觉。
因此,通常很难把它做好。下图演示了在设置学习率时可能遇到的不同场景。
此外,学习率影响我们的模型收敛到局部最小值的速度(也就是达到最佳精度的速度)。因此,从一开始就把它做好,意味着我们训练模型的时间会更少。
训练时间越少,花在GPU云计算上的钱就越少。:)
有没有更好的方法来决定学习率?
在“Cyclical Learning Rates for Training Neural Networks.”章节3.3中。Leslie N. Smith提出,你可以用一个非常低的学习率来训练模型,并在每次迭代中以线性或指数的方式增加它,从而估计出一个好的学习率。
如果我们记录每次迭代的学习情况,并绘制学习速率(log)与损失的关系图,我们会看到随着学习率的增加,会有一个点损失停止减少并开始增加。在实践中,理想情况下,我们的学习速率应该位于图的最左边(如下图所示)。这里是0.001到0.01。
上面那些东西看起来很有用,我们怎么用呢?
目前它作为函数在fast.ai包中支持,由Jeremy Howard开发的用于抽象pytorch的一个包(很像Keras是Tensorflow的抽象)。
在训练神经网络之前,只需要输入以下命令就可以开始寻找最优的学习速率。
# learn is an instance of Learner class or one of derived classes like ConvLearner learn.lr_find() learn.sched.plot_lr()
变得更好
在这一点上,我们已经讨论了学习率的意义,它的重要性,以及当我们开始训练我们的模型时,我们如何系统地得出一个最优值。
接下来,我们将讨论如何使用学习率来改进模型的性能。
传统的思想
通常,当一个人设定他的学习率并训练模型时,他只会等待学习率随着时间的推移而降低,并等待模型最终收敛。
然而,当梯度达到一个平稳区域,训练损失变得更加难以改善。Dauphin等人认为,损失最小化的困难来自鞍点,而不是糟糕的局部极小值。
我们如何从这里逃脱?
我们可以考虑几个选择。一般来说,
如果训练不再改善我们的损失,我们将根据循环函数f来改变每次迭代的学习率。根据迭代次数,每个周期都有一个固定的长度。该方法使学习速率在合理的边界值之间循环变化。这是有帮助的,因为如果我们被卡在鞍点上,增加学习率可以更快地遍历鞍点平缓区。
Leslie提出了一种“三角形”方法,每隔几次迭代就重新启动一次学习速率。
Leslie N. Smith提出的循环学习率的“三角”和“三角2”方法。在左边的图中,min和max lr保持不变。在右边,在每个周期之后,差值减半。
另一种同样流行的方法是由Loshchilov & Hutter提出的带有热重启的随机梯度下降法。该方法基本采用余弦函数作为循环函数,在每个循环中以最大的速度重新开始学习。“热启动”来自这样一个事实:当重新启动学习率时,它不是从头开始,而是从模型在最后一步中收敛到的参数开始。
虽然有一些变化,下面的图展示了它的一个实现,其中每个周期被设置为相同的时间间隔。
因此,我们现在有一种减少训练时间的方法,基本上是周期性地在“山脉”周围跳跃(见下图)。
除了节省时间,研究还表明,使用这些方法可以在不需要调整和更少迭代的情况下提高分类精度。
迁移学习中的学习率
在fast.ai课程中,在解决人工智能问题时强调利用预训练的模型。例如,在解决图像分类问题时,教授学生如何使用预训练的模型,如VGG或Resnet50,并将其连接到你希望预测的任何图像数据集。
在fast.ai中总结模型构建是如何快速完成的。以下是我们通常会采取的几个步骤:
- 使用数据增强,并且precompute=True
- 使用lr_find()来查找最高的学习率,在这个学习率下,损失仍在明显改善
- 在最后一层上使用预先计算的激活训练1-2个epoch
- 使用数据增强(即precompute=False)对最后一层进行训练,使用cycle_len=1进行2-3个epoch的训练
- 解冻所有层
- 将较早的层的学习率设置为比后面的层的学习率低3~10倍
- 再使用一次lr_find()
- 使用cycle_mult=2训练整个网络直到过拟合
从上面的步骤中,我们注意到步骤2、5和7与学习率有关。在本文前面的部分中,我们基本上已经讨论了上面提到的2个步骤—我们在这里讨论了如何在训练模型之前获得最佳的学习率。
在下一节中,我们将介绍如何通过使用SGDR来减少训练时间,并通过不时重新启动学习率来提高准确度,从而避免梯度接近于为零的区域。
在最后一节中,我们将讨论微分学习,以及如何使用它来确定带有预训练模型的训练模型的学习率。
什么是可微分学习?
这是一种方法,你可以在训练过程中为网络的不同层次设置不同的学习速率。这与人们通常配置学习速率的方式相反,人们通常在训练期间在整个网络中使用相同的速率。
在写这篇文章的时候,Jeremy和Sebastian Ruder一起发表了一篇论文,深入探讨了这个话题。所以我想微分学习率现在有了一个新名字—可分性微调。:)
为了更清楚地说明这个概念,我们可以参考下面的图,其中将一个预训练的模型分成3个组,其中每个组将配置一个递增的学习率值。
这种配置方法背后的直觉是,前几层通常包含非常细粒度的数据细节,比如线条和边缘—我们通常不希望对它们做太多更改,希望保留它们的信息。因此,不需要太多地改变它们的权重。
相比之下,在后面的层中,比如上面绿色的图层,我们可以得到详细的数据特征,比如眼球、嘴巴或鼻子,我们不一定要保留它们。
这与其他finetune方法相比如何?
在Fine-tuned Language Models for Text Classification中有人认为对整个模型进行finetune的成本太高,因为有些模型可能有超过100层。因此,人们通常做的是一次只对模型进行一层finetune。
然而,这引入了顺序需求,阻碍了并行性,并且需要多次遍历数据集,从而导致对小型数据集的过拟合。
同时也证明了Fine-tuned Language Models for Text Classification中引入的方法能够提高各种NLP分类任务的准确率和降低错误率(下图)。
英文原文:https://towardsdatascience.com/understanding-learning-rates-and-how-it-improves-performance-in-deep-learning-d0d4059c1c10
本文为专栏文章,来自:AI公园,内容观点不代表本站立场,如若转载请联系专栏作者,本文链接:https://www.afenxi.com/66213.html 。