优化算法 - 动量法

动量法

如何执行随机梯度下降,即只在嘈杂的梯度可用的情况下执行优化时会发生什么。对于嘈杂的梯度,我们在选择学习率需要格外谨慎。若衰减速度太快,收敛就会停滞。相反,若太宽松,我们可能无法收敛到最优解

1 - 基础

在本节中,我们将讨论更有效的优化算法,尤其是针对实验中常见的某些类型的优化问题

泄露平均值


其中,较大的β相当于长期平均值,而较小的β相对于梯度法只是略有修正。新的梯度替换不再指定特定实例下降最陡的方向,而是指向过去梯度的加权平均值的方向。这使我们能够实现对单批量计算平均值的大部分好处,而不产生实际计算其梯度的代价

上述推理构成了“加速”梯度方法的基础,例如具有动量的梯度。在优化问题条件不佳的情况下(例如,有些方向的进展比其他方向慢得多,类似狭窄的峡谷),“加速”梯度还额外享受更有效的好处。此外,它们允许我们对随后的梯度计算平均值,以获得更稳定的下降方向。诚然,即使是对于无噪声凸问题,加速度这方面也是动量如此起效的关键原因之一

正如人们所期望的,由于其功效,动量是深度学习及其后优化中一个深入研究的主题

条件不佳的问题

%matplotlib inline
import torch
from d2l import torch as d2l

eta = 0.4
def f_2d(x1,x2):
    return 0.1 * x1 ** 2 + 2 * x2 ** 2

def gd_2d(x1,x2,s1,s2):
    return (x1 - eta * 0.2 * x1,x2 - eta * 4 * x2,0,0)

d2l.show_trace_2d(f_2d,d2l.train_2d(gd_2d))
epoch 20, x1: -0.943467, x2: -0.000073


C:\Users\20919\anaconda3\envs\d2l\lib\site-packages\torch\functional.py:478: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at  C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\native\TensorShape.cpp:2895.)
  return _VF.meshgrid(tensors, **kwargs)  # type: ignore[attr-defined]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2EA5gO6B-1663327684951)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925190.svg)]

从构造来看,x2⽅向的梯度⽐⽔平x1⽅向的梯度⼤得多,变化也快得多。因此,我们陷⼊两难:如果选择较⼩的学习率,我们会确保解不会在x2⽅向发散,但要承受在x1⽅向的缓慢收敛。相反,如果学习率较⾼,我们在x1⽅向上进展很快,但在x2⽅向将会发散。下⾯的例⼦说明了即使学习率从0.4略微提⾼到0.6,也会发⽣变化。x1⽅向上的收敛有所改善,但整体来看解的质量更差了

eta = 0.6
d2l.show_trace_2d(f_2d, d2l.train_2d(gd_2d))
epoch 20, x1: -0.387814, x2: -1673.365109

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vMLbQvSe-1663327684951)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925191.svg)]

动量法

def momentum_2d(x1,x2,v1,v2):
    v1 = beta * v1 + 0.2 * x1
    v2 = beta * v2 + 4 * x2
    return x1 - eta * v1,x2 - eta * v2,v1,v2

eta,beta = 0.6,0.5
d2l.show_trace_2d(f_2d,d2l.train_2d(momentum_2d))
epoch 20, x1: 0.007188, x2: 0.002553

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EwOyfqCN-1663327684952)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925192.svg)]

正如所见,尽管学习率与我们以前使用的相同,动量法仍然很好地收敛了。让我们看看当降低动量参数时会发生什么,将其减半至β=0.25会导致一条几乎没有收敛的轨迹。尽管如此,它比没有动量时解将会发散要好得多

eta,beta=0.6,0.25
d2l.show_trace_2d(f_2d,d2l.train_2d(momentum_2d))
epoch 20, x1: -0.126340, x2: -0.186632

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YuAmqcQx-1663327684952)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925193.svg)]

请注意,我们可以将动量法与随机梯度下降,特别时小批量随机梯度下降结合起来。唯一的变化是,在这种情况下,我们将梯度 g t , t − 1 g_{t,t-1} gt,t1替换为 g t g_t gt。为了方便期间,我们在时间t=0初始化为 v 0 = 0 v_0=0 v0=0

有效样本权重

d2l.set_figsize()
betas = [0.95,0.9,0.6,0]

for beta in betas:
    x = torch.arange(40).detach().numpy()
    d2l.plt.plot(x,beta ** x,label = f'beta = {beta:.2f}')
d2l.plt.xlabel('time')
d2l.plt.legend()
<matplotlib.legend.Legend at 0x164da1591f0>


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MIZMFrbF-1663327684952)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925194.svg)]

2 - 实际实验

让我们来看看动量法在实验中是如何运作的。为此,我们需要一个更加可扩展的实现

从零开始实现

相比如小批量随机梯度下降,动量方法需要维护一组辅助变量,即速度。它与梯度以及优化问题的变量有相同的形状。在下面的实现中,我们称这些变量为states

def init_momentum_states(feature_dim):
    v_w = torch.zeros((feature_dim,1))
    v_b = torch.zeros(1)
    return (v_w,v_b)
def sgd_momentum(params,states,hyperparams):
    for p,v in zip(params,states):
        with torch.no_grad():
            v[:] = hyperparams['momentum'] * v + p.grad
            p[:] -= hyperparams['lr'] * v
        p.grad.data.zero_()

让我们来看看它在实验中是如何运作的

def train_momentum(lr,momentum,num_epochs=2):
    d2l.train_ch11(sgd_momentum,init_momentum_states(feature_dim),
                  {'lr':lr,'momentum':momentum},data_iter,feature_dim,num_epochs)

data_iter,feature_dim = d2l.get_data_ch11(batch_size=10)
train_momentum(0.02,0.5)
loss: 0.246, 0.006 sec/epoch

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6qtTGfkr-1663327684953)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925195.svg)]

当我们将动量超参数momentum增加到0.9时,它相当于有效样本数量增加到 1 1 − 0.9 = 10 \frac{1}{1-0.9}=10 10.91=10。我们将学习率略微降至0.01,以确保可控

train_momentum(0.01,0.9)
loss: 0.242, 0.009 sec/epoch

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-06dYtCjS-1663327684953)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925196.svg)]

降低学习率进一步解救了任何非平滑优化问题的困难,将其设置为0.005会产生良好的收敛性能

train_momentum(0.005,0.9)
loss: 0.243, 0.006 sec/epoch

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Qw3hQda-1663327684953)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925197.svg)]

简洁实现

由于深度学习框架中的优化求解器早已构建了动量法,设置匹配参数会产生非常类似的轨迹

3 - 理论分析

lambdas = [0.1, 1, 10, 19]
eta = 0.1
d2l.set_figsize((6, 4))
for lam in lambdas:
    t = torch.arange(20).detach().numpy()
    d2l.plt.plot(t, (1 - eta * lam) ** t, label=f'lambda = {lam:.2f}')
d2l.plt.xlabel('time')
d2l.plt.legend()
<matplotlib.legend.Legend at 0x164da2e35b0>


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OJeWhktu-1663327684953)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209161925198.svg)]

4 - 小结

  • 动量法用过去梯度的平均值来替换梯度,这大大加快了收敛速度
  • 对于无噪声梯度下降和嘈杂的随机梯度下降,动量法都是可取的
  • 动量法可以防止在随机梯度下降的优化过程中停滞的问题
  • 由于对过去的数据进行了指数降权,有效梯度为 1 1 − β \frac{1}{1-\beta} 1β1
  • 在凸二次问题中,可以对动量法进行明确而详细的分析
  • 动量法的实现非常简单,但它需要我们存储额外的状态向量(动量v)
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值