解读技术 |学习率及其如何改善深度学习算法

2020-08-04 12:02:27 浏览数 (1)

这篇文章主要是介绍我对以下问题的理解:

(1)什么是学习率(learning Rate)?它的意义是什么?

(2)如何系统的达到一个好的学习率?

(3)为什么在模型训练过程中要改变学习率?

(4)应用已训练的模型时,如何处理学习率问题?

本文的内容基于fast.in的工作人员撰写的文章[1]~[3]、[5],并在其基础上提炼了其中的主要内容。如果您想了解更多,请参考原文。

首先,什么是学习率?

学习率是一个超参数(hyper-parameter),它根据损失梯度(Loss gradient)来控制神经网络权重的调整步长。梯度值越低,我们沿着下降斜率调整的越慢。这能确保我们不会错失任何一个局部最小值(local minima),但也可能导致收敛速度变慢-尤其是在平稳段的时候。

代码语言:javascript复制
new_weight = existing_weight — learning_rate * gradient

图1 梯度下降情况:小学习率(上)、大学习率(下)

通常,学习率被简单的设置成随机数。当然,如果能利用过去的经验(或者其他资料)来确定学习率的最优值是最理想的了。但光凭经验,往往很难凭直觉获得合适的学习率。图2证明了不同学习率对网络训练的影响。

图2 不同学习率对收敛的影响

也就是说,学习率决定了我们的模型能以多快的速度收敛到最优值(也就是达到最佳精度)。因此,从开始就设置适宜的学习率能让我们用更少的时间训练模型。

代码语言:javascript复制
Less training time, lesser money spent on GPU cloud compute. :)

是否有更好的方法来确定学习率?

在《Cyclical Learning Rates for Training Neural Networks》的3.3节[4],Leslie N.Smith指出可以通过在训练开始时设置较小的学习率,然后在每步迭代中逐渐增加(线性或指数)的方法来获得合适的学习率。

图3 学习率在每步迭代后逐渐增加(对数形式)

可以看到,随着学习率的增加,存在着一个确定的拐点,损失函数在该点停止下降,开始上升。在实际应用中,学习率应设置在拐点偏左一点,如图4中,可以设为0.001至0.01。

图4 学习率(对数坐标)

如何开始应用上述方法

如今,该方法可以作为fast.ai工具包的一个函数进行调用。使用时,只需输入以下命令,就可以寻找最优学习率,并用于神经网络训练。

代码语言:javascript复制
1  # learn is an instance of Learner class or one of derived classes like ConvLearner
2  learn.lr_find()
3  learn.sched.plot_lr()

现在,我们了解了什么是学习率以及如何系统的确定其初始最优解。接下来,我们来学习如何应用学习率来提高模型的性能。

经典方法

通常,当我们设置好学习率,并开始训练模型后,只需要等待学习率不断减小,直到模型最终收敛。但是,当梯度达到一个鞍点时,模型的训练误差很难再进一步改进[3]。在鞍点上,误差平面的各方向的导数均为0,但该点并不是各轴的局部极值点。

图5 误差平面上的鞍点(saddle point)

如何脱离鞍点

以下一些方法,可以用来脱离鞍点。比如文献[1]中提到:

“除了采用固定的学习率然后随时间递减的方法,当误差函数不再继续优化时,可以采用根据周期函数改变学习率的方法进行迭代,每个周期根据迭代次数设置确定的步长。该方法允许学习率在合理的范围内进行变化。该方法之所以有效,是因为在鞍点位置,适当的增大学习率可以更加快速的越过鞍点区域(saddle point plateaus)。”

在文献[2]中,Leslie提出了“Triangluar”方法,该方法中学习率经过一定迭代步数后重新进行设置。

图6 “Triangular”和“Triangular2”方法

“Triangular”方法中学习率的最大、最小值保持一致;“Triangular2”方法中每个周期后学习率衰减一半。

另一个比较受欢迎是Loshchilov&Hutter提出的“Stochasitc Gradient Desent with Warm Restarts(SGDR)”方法。该方法采用余弦函数作为周期函数,并在学习率达到最大值时重新启动。

图7 SGDR方法

因此,我们可以利用以上方法来周期性的翻越“山峰”,从而缩减模型的训练时间。

图8 固定学习率和周期学习率的比较

迁移学习中的学习率问题

在fast.ai的课程中,许多的实例都是应用已经训练好的模型去解决AI问题(迁移学习问题)。比如,在解决图像分类问题时,学员会学习如何使用已训练模型(如VGG或Resnet50),并将其与任一图像数据集连接,用于解决你想预测的问题。

以下是fast.ai中建模的几个典型步骤:

[1] 打开data augmentation,设置precompute=Ture;

[2] 使用lr_fine()命令,寻找最大的学习率;

[3] 从已定义的激活函数开始训练上一层,训练1~2个周期;

[4] 用增强数据来训练上一层2~3个周期,设置cycle_len=1;

[5] 解冻所有层;

[6] 前期层的学习率应设置为后面层的3~10倍;

[7] 再次应用lr_fine();

[8] 训练整个神经网络,设置cycle_mult=2,直至over-fitting。

以上的几个步骤中,步骤2、5和7都是有关学习率的。步骤2其实就是我们前面讲到的,如何在训练模型前找到最佳的学习率。

下面介绍可微分编程(Differential Learning),以及如何确定其最佳学习率。

什么是可微分编程

可微分编程是一种可以根据不同层(layer)设置不同学习率的神经网络设计方法。不同于以往的神经网络训练方法,该方法可以更快的收敛。

为了更清晰的解释这个概念,我们可以看下面的示意图。图中的神经网络被分为3组,每一组被设置逐渐增加的学习率。

该方法的意义是:最初的几层网络包含数据的详细信息,如线条和边缘信息,这些信息往往是我们希望保留的。因此,没有必要过快的改变它们的权重。而在最后的网络中(如绿色的层),往往代表的是局部的细节特征(如眼球、嘴和鼻子等),这些信息不是我们关心的,因此没必要保留。所以设置较大的学习率快速的进行迭代。

文献[9]中提到fine-tuning(微调)整个神经网络的代价非常 大,因为有些网络可能高达100层。但是,通过每一次只调节一层网络,但对于小数据集又会带来过拟合的问题。

文献[9]中证明了可微分编程的方法对于自然语言处理任务,可以提高精度,减小误差率。

参考文献:

[1] Improving the way we work with learning rate.

[2] The Cyclical Learning Rate technique.

[3] Transfer Learning using differential learning rates.

[4] Leslie N. Smith. Cyclical Learning Rates for Training Neural Networks.

[5] Estimating an Optimal Learning Rate for a Deep Neural Network

[6] Stochastic Gradient Descent with Warm Restarts

[7] Optimization for Deep Learning Highlights in 2017

[8] Lesson 1 Notebook, fast.ai Part 1 V2

[9] Fine-tuned Language Models for Text Classification

0 人点赞