本节摘要:把 SGD、动量、AdaGrad、RMSProp、Adam 放进一个可执行的决策流程:第一步"先默认 Adam"跑基线,第二步"遇到不理想再换成 SGD+动量"精修。本节给全流程的信号判断、参数初值、以及换优化器时的配套调整。
前面三节把优化器家族介绍全了。这一节不让你做选择困难,直接给一套能用的决策流程。核心思想是两阶段:先用省心的 Adam 快速看到结果,再用一个精修策略(通常是调好的 SGD)逼近上限。
拿到一个新任务,我几乎不会一上来就比谁收敛分更高,而是先要一份"能跑通、能看到曲线在下滑"的基线。这个位置 Adam 最合适:
一句话:先用 Adam 把目标的"地雷"趟平,而不是一上来就追求调参到炉火纯青。
基线跑通后,若你遇到下面任何一种信号,就该考虑切换:
切换的关键不是"选错弃",而是知道你要的是"快速探路"还是"精调上限",两者各自有主。
把这套逻辑写成表,直接按行走:
| 阶段 | 优化器 | 学习率参考 | 该干什么 |
|---|---|---|---|
| 基线探路 | Adam | 1e-3 | 跑通、看曲线、证数据与结构无误 |
| 常规训练 | Adam | 1e-3 到 1e-4 | 直接训练,省心 |
| 泛化不理想 | SGD + 动量 | 1e-1 到 1e-3 逐步试 | 精修上限,动量 ≈0.9 |
| 内存紧张 | SGD(可加动量) | 大一点 | 省显存、可复现 |
| 稀疏数据特吹 | Adam / AdaGrad | 1e-3 | 稀疏特征更友好 |
很多人只在代码里把 optimizer 那个参数改了,其他一概不动,然后抱怨"换了没用"。其实换优化器,学习率几乎必须跟着动(Adam 默认 1e-3 ↔ SGD 大概 1e-2 量级差一个量级);动量、批大小、正则也经常连坐。正确的做法是:换优化器时,把它当"重新装配一台车"而不是"换个引擎盖贴纸"。
# 概念片段:示意"换优化器 = 重新配一套关键参数" def pick(optimizer_name): if optimizer_name == "Adam": return dict(lr=1e-3, betas=(0.9, 0.999)) elif optimizer_name == "sgd": return dict(lr=1e-2, momentum=0.9) return dict(lr=1e-3)
项目 A(生产图像分类,要求稳定):用 Adam 基线跑通后,换 SGD+动量精修,最终在验证集上比 Adam 高 0.8 个点,且内存更低。这个成本是学习率从 1e-3 改到 1e-2 的来回试验。
项目 B(语言模型,跑不了太久):直接用 Adam + 学习率调度,把省下来的调参时间都花在数据清洗上,效果就够上线。
两个项目分别回答了"精调"与"省心"两条路,你根据资源与指标优先级选。
💡 关键直觉:优化器选型不是一次性的"终极答案",它往往是一个"先用谁探路 → 再换谁精修"的两步动作。把"省心"与"上限"分开想,你的选择就清晰了。
要不要从 Adam 换成 SGD+动量,最好不看感觉、而看曲线。给出两张常见的判别画面:
换句话说,换优化器是"我在意最终泛化上限"时的战术,而不该是"不知道怎么办"时的第一反应。 先把画面归因,再动引擎。
假设你手上是个图像分类,Adam 1e-3 已经跑到验证 78%。要冲到 80%,你决定试 SGD+动量。这笔账要算清楚,别以为只换一行:
你会看到,真正的成本不是"换名字"那一下,而是这一整套参数的重新磨合。能接受这个成本、指标压力也够大,才值得走;若只是"想看起来更正规",那 Adam 就够。
SGD 比 Adam 省内存,是因为它不需要维护一阶、二阶矩这两份和参数等大的状态。参数上亿的模型、或显存卡得厉害时,这个差距是实打实的——同样的显存,SGD 能多进一批数据,或用更大的 batch。这也是为什么大规模训练里 SGD、及其稀疏或融合变体(Adafactor / LAMB 一类)仍有一席之地。省内存不是玄学,是一份"参数 × 2"的状态账,在预算吃紧时能换算成实打实的吞吐。
优化器的方法论讲完了,还差一关悬而未决:那些"躲不过"的地形难题。下一节就是压轴的兜底难题——局部最优、鞍点、收敛速度。