学习率(Learning Rate)通常用于控制梯度下降中参数的更新速度(或幅度)。通常情况下梯度下降优化器都要求设置一个学习率来控制参数的更新速度。
如果学习率过小,虽然最终能达到损失函数最小值,但训练过程会耗费太多时间,如果学习率过大,则训练速度会提升,但可能会出现参数在最优值旁边不停地来回“摆动”,而不会收敛到一个极小值。
(1)学习率过小的情况:
假设有一个损失函数 L ( w ) = w 2 L(w)=w^2 L(w)=w2,求导后 L ′ ( w ) = 2 w L'(w)=2w L′(w)=2w,并且设置学习率为0.1,梯度更新公式为 w n + 1 = w n − σ ∂ ∂ w L ( w ) w_{n+1}= w_{n}- \sigma \frac{\partial }{\partial w}L(w) wn+1=wn−σ∂w∂L(w),梯度更新过程如下:
轮数 | 当前轮数参数值 | 梯度×学习率 | 更新后参数值 |
---|---|---|---|
1 | 10 | 0.1×2×10=2 | 10-2=8 |
2 | 8 | 0.1×2×8=1.6 | 8-1.6=6.4 |
3 | 6.4 | 0.1×2×6.4=1.28 | 6.4-1.28=5.12 |
4 | 5.12 | 0.1×2×5.12=1.024 | 5.12-1.024=4.096 |
5 | 4.096 | 0.1×2×4.096=0.8192 | 4.096-0.8192=3.2768 |
然后把学习率设置成0.2
轮数 | 当前轮数参数值 | 梯度×学习率 | 更新后参数值 |
---|---|---|---|
1 | 10 | 0.2×2×10=4 | 10-4=6 |
2 | 6 | 0.2×2×=2.4 | 6-2.4=3.6 |
3 | 3.6 | 0.2×2×3.6=1.44 | 3.6-1.44=2.16 |
4 | 2.16 | 0.2×2×2.16=0.84 | 2.16-2.864=1.296 |
5 | 1.296 | 0.2×2×1.296=0.5184 | 1.296-0.5184=0.7776 |
可以看到,学习率设置为0.1时的参数更新速度比0.2时的慢。学习率过小带来的问题是,虽然能保证收敛性,但是会大大降低优化速度,往往需要更多轮的迭代才能达到比较理想的优化效果。
(2)学习率过大的情况
把学习率设置成0.9
轮数 | 当前轮数参数值 | 梯度×学习率 | 更新后参数值 |
---|---|---|---|
1 | 10 | 0.9×2×10=18 | 10-18=-8 |
2 | -8 | 0.9×2×-8=-14.4 | -8-(-14.4)=6.4 |
3 | 6.4 | 0.9×2×6.4=11.52 | 6.4-11.52=-5.12 |
4 | -5.12 | 0.9×2×-5.12=-9.216 | -5.12-(-9.216)=4.096 |
5 | 4.096 | 0.9×2×4.096=7.3728 | 4.096-7.3728=-3.2767 |
可以看到,经过5轮后,和学习率0.2的时候对比,参数总是在最小值两侧来回“摆动”,而且离最小值还存在着一定距离,也许经过多轮迭代后或许能达到最小值,但是这个可能性很低。
不过,在上面的例子中,我们发现其实在最初的时候学习率大一点的话参数收敛得稍微快一点,到后面的时候如果学习率还是那么大的话参数就不稳定了,这时候我们发现学习率小一点的话参数更新速度就没那么快了,不过也是在逐渐向最小值靠近,而且也不会存在参数更新“过头”的情况。
1.指数衰减学习率
TensorFlow提供了train.exponential_decay()函数,可以让学习率随着训练的进行逐步减少。
如果用decayed_learning_rate代表每一优化时使用的学习率,learning_rate为事先预定义的初始学习率,decay_rate为衰减系数,decay_steps为衰减步数,那么train.exponential_decay()函数会按以下公式返回decay_learning_rate的值:
d e c a y l e a r n i n g r a t e = l e a r n i n g r a t e ∗ d e c a y r a t e ( g l o b a l s t e p s d e c a y s t e p s ) decaylearningrate = learningrate*decayrate^(\frac{globalsteps}{decaysteps}) decaylearningrate=learningrate∗decayrate(decaystepsglobalsteps)
使用这个函数时,通常会将learning_rate设置为比较大的一个数(比1小)来获得一个比较快的参数更新速度,然后随着迭代的继续逐步减小学习率,这样会使模型在训练后期更加稳定。
这个函数的原型如下
exponential_decay(learning_rate,global_step,decay_steps,decay_rate,staircase,name)
当staircase的值被设置为True时,globa_steps/decay_steps会被向下取整,最终的学习率成为一个阶梯函数。如下图所示
作图代码
import math
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
x1 = np.linspace