跳到主要内容

2.4 梯度下降进阶:从山谷到沟壑

给山加一个维度​

0.4 节里你已经蒙着眼下过一次山——那座山只有一个方向可走(一个参数)。可是上一节的训练三件套里,随便一个小网络就有几十个参数,GPT 更是有几千亿个:每个参数都是一个可以移动的方向。

几千亿维的山没人画得出来,但从 1 维升到 2 维,已经足够暴露出一批一维世界里根本看不到的新麻烦。这次你不再站在山坡上,而是从上帝视角俯瞰整片地形:颜色越浅的地方损失越低,两个白圈就是谷底。

🎮 动手实验
二维损失面:颜色越浅,损失越低
现在「山」有两个参数(w₁ 横轴、w₂ 纵轴),你从上帝视角俯瞰。白圈是两个谷底。点击或拖动可以空降小球,然后让它下山。
位置 (w₁, w₂)
(1.90, 1.80)
损失 f
6.904
梯度大小
8.036
步数
0
💡 要点:注意之字形——纵向(陡)方向反复过冲、横向(缓)方向慢慢挪,这是梯度下降在「沟壑地形」里的经典步态,学习率大一点就先在陡方向爆炸。勾选「随机梯度噪声」模拟 SGD:每步只用一小批数据、梯度带手抖,反而可能抖出局部低谷。真实大模型的损失面有几千亿个维度,这里只是 2 维切片。

请按顺序做四个实验:

实验 ①:经典之字形。 保持默认起点和学习率 η = 0.1,点「▶ 自动下山」。仔细看橙色足迹:纵向(陡的方向)小球一步就冲过头、下一步又弹回来,来回横跳;横向(缓的方向)却每步只挪一点点。整条路径呈之字形——先在陡壁间弹够了,才慢悠悠沿着谷底爬向白圈。

实验 ②:一步跨进另一条谷。 点「↺ 重置」,把 η 调到 0.5 再自动下山。第一步就大得离谱——小球直接从右边山坡飞越中间山脊,掉进了左边的谷底。步子太大时,你甚至不知道自己会落在哪条谷里。

实验 ③:干脆飞出地图。 再重置,把 η 拉到最大(0.8)。这次连「换条谷」的运气都没有:每一步都跨得比整条沟还宽,越荡越高,💥 直接发散——0.4 节的 loss 爆炸,在高维地形里只会来得更容易。

实验 ④:手抖反而是好事。 重置后勾选「随机梯度噪声(SGD)」,用 η = 0.1 自动下山。足迹变得歪歪扭扭,但大方向不变,照样能进谷底——有时还能靠抖动翻过小坡换到更好的谷。

为什么会走出之字形?​

这片地形是一条沟壑:纵向坡度陡,横向坡度缓。而学习率只有一个,两个方向只能共用——

  • 想让陡方向不震荡,η 就得调小;
  • η 一小,缓方向就挪不动。

学习率只能迁就最陡的方向,于是缓方向被拖累,整体进度慢得令人心焦。数学上「最陡方向和最缓方向的陡峭比」有个名字叫条件数,条件数越大,之字形越严重。真实神经网络的损失面里,不同参数方向的陡峭程度可以相差成千上万倍——这正是本节深入层里 Adam 这类「智能步伐」优化器存在的理由。

为什么每步只用一小批数据?​

到目前为止我们默认:算一次梯度,要把全部训练数据过一遍。对 12 个点无所谓;可大模型的训练数据是十几万亿个 token——全过一遍才走一步,走几百万步等于天荒地老。

实际做法简单粗暴:每步只随机抽一小批(一个 batch,比如几百万 token)来估算梯度。这就是随机梯度下降(SGD):

  • 抽样估出来的坡度大致指向正确方向,但每次都带点误差——这就是实验 ④ 里的手抖;
  • 代价是路径歪歪扭扭,收益是每一步便宜了无数倍,还白送一个好处:噪声能帮小球晃出鞍点和小坑(0.4 节埋的伏笔,在这里兑现)。
这个类比在哪里不准确?

你看到的仍然只是千亿维地形的一张 2 维切片。真实损失面上,「沟壑」远比图里夸张——不同方向的陡峭程度能差出几个数量级,而且地形还会随着训练数据的批次不断轻微变化(每批数据画出的「山」都略有不同)。另外,图里的噪声是我们手工加的均匀抖动,真实 SGD 的噪声大小取决于 batch 大小:批越小,抖得越凶。

小结​

本节要点
  • 沟壑地形(有的方向陡、有的方向缓)让梯度下降走出之字形:学习率被最陡方向卡脖子。
  • 大模型不可能每步用全部数据算梯度:随机抽一小批来估算,就是 SGD——便宜、带噪声,而噪声常常是帮手。
  • 学习率过大在高维里更危险:轻则跨谷,重则发散。
  • 动量与 Adam 用「惯性 + 每参数自适应步长」驯服沟壑,AdamW 是当今大模型训练的标配。
📝 动手自测0/3
1. 实验 ① 里小球走出之字形,根本原因是什么?
2. 真实训练中每一步只用一小批(mini-batch)数据来算梯度,最主要的原因是?
3. 实验 ② 中 η = 0.5 时,小球从右坡出发却落进了左边的谷。这提示了什么?

延伸阅读​