深度学习优化算法:AdaGrad算法

AdaGrad是一种自适应学习率的优化算法,它根据每个维度的梯度历史平方和来调整学习率,使得在梯度变化大的维度上学习率减小,而在梯度变化小的维度上学习率保持较高。这有助于解决不同维度间学习率不适应的问题。然而,由于学习率的不断衰减,AdaGrad可能会在后期迭代中导致学习率过小,影响找到最优解。示例展示了不同学习率设置下,AdaGrad如何影响自变量的迭代轨迹和收敛速度。
摘要由CSDN通过智能技术生成

原文链接:动手学深度学习pytorch版:7.5 AdaGrad算法
github:https://github.com/ShusenTang/Dive-into-DL-PyTorch

原论文:
[1] Duchi, J., Hazan, E., & Singer, Y. (2011). Adaptive subgradient methods for online learning and stochastic optimization. Journal of Machine Learning Research, 12(Jul), 2121-2159.

AdaGrad算法

在动量法中我们看到当 x 1 x_1 x1 x 2 x_2 x2 的梯度值有较大差别时,需要选择足够小的学习率使得自变量在梯度值较大的维度上不发散。但这样会导致自变量在梯度值较小的维度上迭代过慢。动量法依赖指数加权移动平均使得自变量的更新方向更加一致,从而降低发散的可能。AdaGrad算法,它根据自变量在每个维度的梯度值的大小来调整各个维度上的学习率,从而避免统一的学习率难以适应所有维度的问题

算法

AdaGrad算法会使用一个小批量随机梯度 g t g_t gt 按元素平方的累加变量 s t s_t st。在时间步0,AdaGrad将 s 0 s_0 s0 中每个元素初始化为0。在时间步 t t t,首先将小批量随机梯度 g t g_t gt 按元素平方后累加到变量 g t g_t gt
s t ← s t − 1 + g t ⊙ g t {{\text{s}}_{t}}\leftarrow {{s}_{t-1}}+{{g}_{t}}\odot {{g}_{t}} stst1+gtgt

其中 ⊙ \odot 是按元素相乘。接着,我们将目标函数自变量中每个元素的学习率通过按元素运算重新调整一下:
x t ← x t − 1 − η s t + ε ⊙ g t {{x}_{t}}\leftarrow {{x}_{t-1}}-\frac{\eta }{\sqrt{{{s}_{t}}+\varepsilon }}\odot {{g}_{t}} xtxt1st+ε ηgt

其中 η η η 是学习率, ε \varepsilon ε 是为了维持数值稳定性而添加的常数,如 1 0 − 6 10^{-6} 106。这里开方、除法和乘法的运算都是按元素运算的。这些按元素运算使得目标函数自变量中每个元素都分别拥有自己的学习率。

特点

如果目标函数有关自变量中某个元素的偏导数一直都较大,那么该元素的学习率将下降较快;反之,如果目标函数有关自变量中某个元素的偏导数一直都较小,那么该元素的学习率将下降较慢。

缺点:
由于 s t s_t st 一直在累加按元素平方的梯度,自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。所以,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。

例子

下面以目标函数 f ( x ) = 0.1 x 1 2 + 2 x 2 2 f(x)=0.1x^2_1+2x^2_2 f(x)=0.1x12+2x22 为例观察 AdaGrad 算法对自变量的迭代轨迹。我们实现 AdaGrad 算法并设置学习率0.4。可以看到,自变量的迭代轨迹较平滑。但由于 s t s_t st 的累加效果使学习率不断衰减,自变量在迭代后期的移动幅度较小。

而且出现了上述问题,学习率初始设置太小,移动幅度到后面越来越小,很难接近最优解。

%matplotlib inline
import math
import torch
import sys
sys.path.append("..") 
import d2lzh_pytorch as d2l
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

def adagrad_2d(x1, x2, s1, s2):
    g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6  # 前两项为自变量梯度
    s1 += g1 ** 2
    s2 += g2 ** 2
    x1 -= eta / math.sqrt(s1 + eps) * g1
    x2 -= eta / math.sqrt(s2 + eps) * g2
    return x1, x2, s1, s2

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

eta = 0.4
d2l.show_trace_2d(f_2d, d2l.train_2d(adagrad_2d))

输出:

epoch 20, x1 -2.382563, x2 -0.158591

请添加图片描述
下面将学习率增大到2。可以看到自变量更为迅速地逼近了最优解。

eta = 2
d2l.show_trace_2d(f_2d, d2l.train_2d(adagrad_2d))

输出:

epoch 20, x1 -0.002295, x2 -0.000000

请添加图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值