Daily Paper 04 - Cyclical Learning Rates for Training Neural Networks
Tilden Ji 菜鸟Lv3

找来了 15 年的一篇自动寻找学习率的经典论文来学习一下,论文发表于 WACV 2017,主要工作是提出了一种周期性变化的学习率策略。

「」

介绍

学习率是深度学习炼丹中最最最重要的一个超参数,而如何选择一个好的学习率往往是一个费时费力的事情。

本文基于这样一个观察,「提高学习率可能会产生短期的负面效应,但却能达到长期的有益效果」。在深度学习里面有一个常见的误解 ,大家误以为在较大的神经网络中包含很多局部极小值(local minima),使得算法容易陷入到其中某些点,但实际情况很可能是高维优化问题中根本没有那么多局部极值。如在 14 年一篇论文 中作者依据统计物理,随机矩阵理论和神经网络理论的分析,以及一些经验分析提出高维非凸优化问题之所以困难,是因为存在大量的鞍点(梯度为零并且 Hessian 矩阵特征值有正有负)而不是局部极值。因此在鞍点附近增加学习率,能让训练逃出鞍点。

回到本文,本文的重点在于两个方面:一是提出了一个周期性学习率策略(Cyclical Learning Rates),另外是提供了一个选择学习率的使用方法(Learning Rate Range Test)。

方法

周期性学习率 Cyclical Learning Rates

周期性学习率方法很简单,就是让学习率在一个周期(Cycle Length)里,学习率先增再降:base_lr -> max_lr -> base_lr。

作者实验发现不同的学习率变化方式效果都差不多,最后采用了一个简单的实现方式如下:

从图中可以看出,该策略一共需要提供三个参数:stepsize、max_lr 和 base_lr。

作者建议 stepsize 设置为一个 epoch 所需迭代次数的 2~10 倍(对于 CIFAR,作者设置为 8*epoch),另外作者建议在周期末结束训练。那 max_lr 和 base_lr 怎么选择呢?作者提供了一个叫做 Learning Rate Range Test 通过测试得到一个好的学习率范围。

学习率范围测试 Learning Rate Range Test

LR Rate Range Test(也称为 Learning Rate Finder)的流程为:测试训练一个小的 epoches,训练过程中,学习率在某个大的预设范围内线性(或者指数)增加。画出训练过程中的精度 - 学习率曲线,分别设置 base_lr 和 max_lr 为 精度开始上升 精度上升缓慢并且开始波动甚至下降 的点。

下图是在 CIFAR-10 上的一个例子,按照上述方法,base_lr 和 max_lr 分别选取为 0.001 和 0.006。

Learning Rate Finder

之所以看这篇论文,主要是想要知道如何寻找一个好的学习率。这一个复杂并且 尚未解决 的问题,不过本文的方法稍微修改一下不失为一种可行的方法。

根据这篇博客,一个自动寻找学习率的函数设计如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def find_lr(init_value = 1e-8, final_value=10., beta = 0.98):
num = len(trn_loader)-1
mult = (final_value / init_value) ** (1/num)
lr = init_value
optimizer.param_groups[0]['lr'] = lr
avg_loss = 0.
best_loss = 0.
batch_num = 0
losses = []
log_lrs = []
for data in trn_loader:
batch_num += 1
#As before, get the loss for this mini-batch of inputs/outputs
inputs,labels = data
inputs, labels = Variable(inputs), Variable(labels)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
#Compute the smoothed loss
avg_loss = beta * avg_loss + (1-beta) *loss.data[0]
smoothed_loss = avg_loss / (1 - beta**batch_num)
#Stop if the loss is exploding
if batch_num > 1 and smoothed_loss > 4 * best_loss:
return log_lrs, losses
#Record the best loss
if smoothed_loss < best_loss or batch_num==1:
best_loss = smoothed_loss
#Store the values
losses.append(smoothed_loss)
log_lrs.append(math.log10(lr))
#Do the SGD step
loss.backward()
optimizer.step()
#Update the lr for the next step
lr *= mult
optimizer.param_groups[0]['lr'] = lr
return log_lrs, losses

运行并画出 smoothed 后的 Loss-Step 图:

1
2
logs,losses = find_lr()
plt.plot(logs[10:-5],losses[10:-5])

选择图像最低点左边的一个合适的 learning rate 就好了~

实验


Reference

[1]L. N. Smith, “Cyclical Learning Rates for Training Neural Networks,” arXiv:1506.01186 [cs], Apr. 2017, Accessed: Jun. 13, 2021. [Online]. Available
[3]Y. Dauphin, R. Pascanu, C. Gulcehre, K. Cho, S. Ganguli, and Y. Bengio, “Identifying and attacking the saddle point problem in high-dimensional non-convex optimization,” arXiv:1406.2572 [cs, math, stat], Jun. 2014, Accessed: Jun. 14, 2021. [Online]. Available
  • 本文标题:Daily Paper 04 - Cyclical Learning Rates for Training Neural Networks
  • 本文作者:Tilden Ji
  • 创建时间:2021-06-14 12:50:00
  • 本文链接:https://itiandong.com/2021/daily-paper-04/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论