QUESTION

AdaGrad如何根据梯度平方和自动调整学习率?

A

区分基础学习率与每个参数的有效学习率,并解释AdaGrad为什么越训练越慢。

DETAILED ANSWER

直接结论

AdaGrad确实会调整步长,但不是随意修改你设置的基础学习率。它为每个参数分别累计历史梯度平方,再用这个累计值缩小该参数本轮的有效学习率。

历史梯度平方和越大
→ 分母越大
→ 当前参数的有效学习率越小

它为每个参数维护一份累计值

对某一个参数,设本轮梯度为g_t,累计值为s_t

s_t = s_(t-1) + g_t²

参数更新可以简化为:

新w = 旧w − η / (sqrt(s_t) + ε) × g_t

这里:

  • η:人工设置的基础学习率;
  • s_t:这个参数从训练开始到现在的梯度平方和;
  • ε:防止分母为0的小数;
  • η / (sqrt(s_t) + ε):这个参数当前真正使用的有效学习率。

不同教材可能把ε写在平方根内或平方根外,但“用历史梯度平方累计值缩小步长”的核心不变。

用数字看步长怎样变化

假设基础学习率η=0.1,某个参数连续两次梯度都是2,暂时忽略ε

第一次:

s_1 = 0 + 2² = 4
有效学习率 = 0.1 / sqrt(4) = 0.05
参数移动量 = 0.05 × 2 = 0.10

第二次:

s_2 = 4 + 2² = 8
有效学习率 = 0.1 / sqrt(8) ≈ 0.035
参数移动量 ≈ 0.035 × 2 = 0.071

梯度相同,但由于累计平方和变大,第二次移动距离更小。

为什么要平方

平方有两个作用:

  1. 正负梯度不会互相抵消,能稳定记录历史梯度的大小;
  2. 梯度长期较大的参数会得到更强的步长缩小。

方向并不是由平方和决定的。更新公式中仍然乘着未平方的g_t,因此参数往左还是往右仍由当前梯度的正负决定。

为什么后期可能走不动

AdaGrad的s_t只会累加,不会遗忘早期梯度。因此训练越久,分母通常越大,有效学习率就越小,后期可能几乎不再更新。这正是RMSProp改用“近期梯度平方平均”的原因。

参考

PyTorch AdaGrad官方文档