本节你会学到
- 说清楚「AdaGrad 与 RMSProp:学习率如何自动调整」解决的核心问题
- 知道它在「PyTorch 深度学习基础(43~58)」中的位置
- 把 DataLoader、Linear 层、Tensor 这些关键词联系起来
SGD 给所有参数同一个学习率。但有些参数变化剧烈、有些几乎不动,统一步长不合理。AdaGrad 和 RMSProp 让每个参数有自己的自适应学习率。
学习路线:PyTorch 深度学习基础(43~58) · 第 53 课
在前 20 篇 PyTorch 入门上继续深化,补齐张量操作、自动微分、优化器家族和训练排错能力。
学完本阶段你能做到:独立搭建一个 PyTorch 训练脚本,正确处理 Shape、device、梯度清空、优化器选择和学习率策略,并能根据 loss/accuracy 曲线诊断训练问题。
推荐读法:当前更新主线,建议跟更;每篇都要配合代码自检。
查看完整阶段 · 16 篇先看目标,再带着问题读正文。读完后用练习确认自己真的理解了。
先检查模型参数、输入 Tensor、标签 Tensor 是否在同一个设备上。常见修正是把它们统一 `.to(device)`。
因为训练是否正确经常取决于 shape、dtype、device 和梯度流,API 名字只能告诉你工具,不会保证数据契约正确。
`输入数据 → forward → loss → backward → optimizer.step()`,并知道本文主题位于这条链路的哪一环。
上一篇的 SGD 给所有参数用同一个学习率。但仔细想想——模型里有些参数对应的特征经常出现、梯度很大,有些特征很少出现、梯度很小。给它们同一个步子,大的撑死、小的饿死。
AdaGrad 和 RMSProp 就是来解决“每个参数该有不同学习率”这个问题的。它们是 Adam 的直接前身。
上一篇 SGD + Momentum 的核心是“用历史梯度的方向加惯性”。今天换一个角度:不调方向,调步子大小。第 51 篇讲初始化时提到不同参数需要不同对待,优化器也是同理。第 12 篇的梯度下降是所有优化器的共同祖先。
AdaGrad 让经常更新的参数学习率自动变小,很少更新的参数保持大学习率。RMSProp 改进了 AdaGrad 学习率只会越来越小的问题,用滑动平均让学习率能升能降。
一个参数如果一直收到大梯度,说明它“学得够多了”,学习率该调小。如果梯度一直很小,说明它“还没学好”,学习率该保持大。
怎么实现?累计历史梯度的平方和,用它来缩放学习率。
$$r_t = r_{t-1} + g_t^2$$
$$w_{t+1} = w_t - \frac{\alpha}{\sqrt{r_t} + \epsilon} \cdot g_t$$
分母 $\sqrt{r_t}$ 越大,有效学习率越小。
optimizer = torch.optim.Adagrad(
model.parameters(),
lr=0.01,
eps=1e-10
)
$r_t$ 只会累加,不会减小。训练后期 $r_t$ 变得很大,所有参数的学习率都趋近于 0,训练提前停滞。
适用场景:稀疏特征(如 NLP 词向量),因为稀疏特征出现少、梯度小、$r_t$ 不会很快膨胀。
RMSProp 把“累加和”换成“滑动平均”——只关注最近的梯度,老梯度逐渐遗忘。这样 $r_t$ 不会一直变大,学习率能升能降。
$$r_t = \alpha \cdot r_{t-1} + (1 - \alpha) \cdot g_t^2$$
$$w_{t+1} = w_t - \frac{\eta}{\sqrt{r_t} + \epsilon} \cdot g_t$$
optimizer = torch.optim.RMSprop(
model.parameters(),
lr=0.001,
alpha=0.99,
eps=1e-8
)
| 参数 | 常用值 | 作用 |
|---|---|---|
lr |
0.001 | 基础学习率 |
alpha |
0.99 | 滑动平均的衰减系数 |
eps |
1e-8 | 防除零 |
momentum |
0 或 0.9 | 可选加动量 |
| 特性 | AdaGrad | RMSProp |
|---|---|---|
| 累积方式 | 累加和(只增不减) | 滑动平均(能升能降) |
| 学习率趋势 | 只会变小 | 自适应升降 |
| 长期训练 | 提前停滞 | 稳定 |
| 稀疏特征 | 推荐 | 也可以 |
| RNN / 序列 | 一般 | 更推荐 |
想象一个推荐系统模型,“用户ID”这个特征有几百万个取值,但每个 ID 出现次数很少;“年龄”这个特征取值少、出现频繁。
如果用 SGD 统一学习率:
用自适应优化器:
每个参数都有自己的节奏。
| 优化器 | 擅长 | 不擅长 |
|---|---|---|
| AdaGrad | 稀疏特征、NLP 词向量 | 长期训练(学习率衰减到0) |
| RMSProp | RNN、时间序列、梯度不稳定任务 | Transformer(一般用 Adam) |
import torch
import torch.nn as nn
# 简单模型
model = nn.Sequential(nn.Linear(100, 50), nn.ReLU(), nn.Linear(50, 10))
# 三种优化器对比
configs = {
"SGD": torch.optim.SGD(model.parameters(), lr=0.01),
"AdaGrad": torch.optim.Adagrad(model.parameters(), lr=0.01),
"RMSProp": torch.optim.RMSprop(model.parameters(), lr=0.001),
}
# 实际训练时选一个用,不要同时用三个
optimizer = configs["RMSProp"]
练习 1:AdaGrad 训练到后期 loss 不降了,最可能的原因是什么?
练习 2:RMSProp 的 alpha=0.99 和 alpha=0.5 有什么区别?哪个更关注近期梯度?
练习 3:一个 NLP 词向量任务,词表 10 万,大部分词很少出现。选 AdaGrad 还是 RMSProp?为什么?
练习 1:AdaGrad 的梯度平方累加和 $r_t$ 一直增大,到后期 $\sqrt{r_t}$ 很大,有效学习率趋近于 0,参数几乎不更新。换 RMSProp 或 Adam 能解决。
练习 2:alpha=0.99 表示 99% 看历史、1% 看当前,滑动窗口很长,学习率变化平滑。alpha=0.5 表示一半看历史一半看当前,更关注近期梯度,学习率波动更大。alpha=0.5 更关注近期,但也更不稳定。通常用 0.9-0.99。
练习 3:AdaGrad。稀疏特征出现少、梯度小,AdaGrad 的累加机制让这些罕见词保持较大学习率,学得更好。RMSProp 也可以,但 AdaGrad 是为稀疏特征设计的经典选择。如果训练轮数多,RMSProp 更安全(不会学习率归零)。
下一篇把 Momentum 和自适应学习率合起来——Adam 和 AdamW 为什么成为现代深度学习的默认选择。
留言讨论