LESSON 12 · 卷 神经网络

梯度下降与优化器

知道了往哪边走是下坡,一步该迈多大?

第 1 站

更新一步,损失反而涨了

上一课,那台猜水果的机器终于有了损失——知道自己每次猜得有多差。这一课就来干正事: 调参数把损失降下去,也就是真正地训练它。用的就是第 5 课《梯度》学过的蒙眼下山。

回忆一下:梯度 ∇L 指出最陡的上坡方向,朝它的反方向迈步就是下坡。写成更新公式:

听上去万无一失,可真迈一步就翻车。为了把账算清楚,我们盯住其中一个权重 , 把「 取不同值时、损失有多大」画成一条山谷曲线。假设这台机器的损失随 变化恰好长这样:

这是一条开口向上的抛物线,谷底在 (那里损失为 0),离谷底越远、损失越大。 训练要做的就是把 一步步挪向谷底。现在机器的权重停在 ,先算它此刻的损失——把 0.5 代进去:

再算梯度(也就是这条曲线在 处的斜率)。对 求导 (第 5 课的法则:平方求导、再乘内层那项的导数 1)得 ,代入

负号说明「往右( 变大)是下坡」。按更新公式 迈一步:

这一步把 从 0.5 直接甩到了 12.5。它到底落到山谷的哪儿?再把 12.5 代回损失:

损失从 24 不降反升、飙到了 96!方向其实没错(确实朝着下坡迈), 问题出在步子:一步迈了整整 12,直接飞过谷底(),冲到对面更高的山坡上。 看来「方向对」不等于「走得到谷底」——还得管住步幅。把刚才这一步画到那条山谷曲线上,就一目了然:

图 12-1梯度方向对了,但步长 = 整个梯度值,直接飞过最低点落到对面的山坡上,损失反而更大。
很简单的修补——不用整个梯度值,用梯度的一个比例。你会怎么写这个公式?
第 2 站

学习率 α:步子迈多大

加入学习率后,更新公式变为:

通常是 0.001 到 0.1 之间的一个小数。但选多大,是整个训练过程中最重要也最棘手的决定:

α 太大:震荡训练步数 →α 太小:极慢训练步数 →
图 12-2α 太大,损失曲线震荡无法收敛;α 太小,损失下降极缓慢。好的学习率让曲线稳定地下降。

实践中用学习率调度(LR scheduling):训练初期用较大的学习率快速接近最优区域, 后期逐渐降低——如余弦退火(cosine annealing)或线性预热(linear warmup)。

光说不练没感觉。下面把那台猜水果的机器缩到只看「颜色」一个特征(这样整台机器和每一步都看得清清楚楚), 给它 8 个已知答案的水果当训练数据,让你亲手一步步训练它

学习率 α = 2.0
🍎 颜色 x0.92× w = 0.00z = w·x + b0.00b = 0.00激活 σ把 z 压成 0~1softmax(2 类)🍎 eᶻ = 1.00🚫 e⁰ = 1和 = 2.00P(苹果)50%
把上面两个 e 值各除以「和 = 2.00」就得到两类概率——这一步就是 softmax 的归一化,两类相加正好 100%:
🍎 苹果50%
🚫 非苹果50%
📉 这一步的损失(loss)是怎么算出来的
① 拿一颗真苹果(颜色 0.92、真值 y=1)走一遍机器:上面算出 P(苹果) = 50%
② 它本该是 1、机器只猜了 p,这一个的损失 = −ln(p) = 0.693(越接近 1 越小)。
③ 8 个训练水果都这样算一遍、再取平均,就是这一步的总损失 ↓
当前总损失 L = 0.693训练就是要把它一路压小
0w = 0.00b = 0.00
损失随训练步数下降
wb总损失
00.000.000.693
起点 w=b=0 时机器对谁都只猜 50%,损失最高。点「训练一步」或「自动训练」:每点一次都按 w ← w − α·∂L/∂w 微调一次 w、b,上方机器里的数字随之变化,下面的记录表也追加一行——w、b 怎么挪、总损失怎么一步步降,全程都看得见。把 α 拉到 6 看震荡、拉到 0.2 看龟速,就是第 2 站说的学习率。
互动 12-A单神经元的梯度下降全过程,把完整链条都画了出来:颜色 →()加权求和 激活函数 曲线 压成 0~1 → 归一化成「苹果 / 非苹果」概率(二分类 softmax)→ 再算损失。每点一步「训练」,参数按 更新一次,下方记录表就追加一行——w、b 怎么挪、总损失怎么一路降,整个过程看得清清楚楚。拖动 α 亲历「太大震荡 / 太小龟速」。

盯着 和损失这三个数字跳动,你看到的就是训练的全部秘密: 算梯度 → 朝反方向挪一小步 → 重复。几亿个参数的大模型,做的也只是同一件事,只是数字更多。

但学习率还不是最大的问题。有一个更基本的困难正在等着我们。

第 3 站

另一个问题:梯度算在哪些数据上?

目前为止,∇L 是基于所有训练样本的平均损失算出来的。 更新一次参数,需要把整个训练集都喂给网络跑一遍。 GPT-3 的训练集有 3000 亿个 token——每次更新参数前要扫完 3000 亿条数据, 一天下来可能只更新几次,这显然行不通。

全量梯度的代价

假设你有 10 亿条训练数据,每条数据做一次前向传播需要 1ms, 那仅仅算一次梯度就需要 10 亿 ms = 277 小时。 更新一次参数就要等 11 天——这完全没有实用价值。

不用全部数据,也不用一条数据,有没有折中方案?两个极端各有什么问题?
第 4 站

Mini-batch SGD:用噪声换速度

每次从训练集随机抽取 B 条样本(一个 batch),计算这 B 条的平均梯度,更新一次参数。 B 通常是 32、64、128——随 GPU 显存大小调整。

这叫 Mini-batch 随机梯度下降。「随机」指的是每次随机抽取一个 batch—— 每次算出的梯度不是真正的全量梯度,有一定噪声。

噪声有时反而有好处:它帮助模型跳出「小坑」(局部最小值), 找到泛化能力更好的参数区域。纯全量梯度太精确,反而更容易陷入局部最优。

全批量(稳但慢)Mini-batch(折中)最低点
图 12-3全批量路径平滑但每步代价极高;Mini-batch 路径有轻微抖动,但每步只需少量数据,整体更快。

一个 epoch 是扫完整个训练集一遍。完整训练通常需要几十到几百个 epoch, 每个 epoch 里有「数据集大小 / B」次参数更新。

第 5 站

还不够好:峡谷地形与 Adam

Mini-batch SGD 还有一个麻烦:在「峡谷地形」(某方向坡度很陡、另一方向很平缓)里, 参数会沿陡峭方向来回震荡,沿平缓方向却走得极慢。

修补:加入动量(Momentum)——给更新加入惯性, 用历史梯度的加权平均代替单步梯度:

β ≈ 0.9

90% 保留上一步的方向,10% 接受新梯度。陡峭方向的来回震荡相互抵消, 平缓方向的梯度逐步积累速度——轨迹更平滑,收敛更快。

现代训练几乎都用 Adam(Adaptive Moment Estimation): 在动量的基础上,还为每个参数维护一个自适应的学习率—— 更新频繁的参数自动降低学习率,稀疏参数自动提高。

Adam ≈ 动量(一阶矩)+ 每参数自适应 α(二阶矩)

Adam 的默认参数(α=0.001, β₁=0.9, β₂=0.999)在绝大多数任务上开箱即用, 不需要精细调节。Transformer 几乎清一色用 Adam 或其变种 AdamW。

第 6 站

总结

本课核心 · TAKEAWAY

梯度告诉方向,学习率 α 控制步长。 全量太慢,单样本太抖,Mini-batch 折中。Adam 把动量和自适应学习率合二为一, 是现代深度学习训练的事实标准。

这一课你亲手发现了

  • 学习率 α:控制每次更新步长;太大震荡,太小极慢。
  • 全批量 GD:梯度精确但每步代价极高,不可行。
  • Mini-batch SGD:每次用 B 个样本估算梯度,速度和精度的折中。
  • 动量:用历史梯度加权平均,平滑轨迹,加速收敛。
  • Adam:动量 + 自适应学习率;开箱即用,现代训练标配。
小测验

学习小测验

做完这一课,来检测一下核心知识点。选出你的答案后点击「提交」,即可看到正确选项与讲解。

Q1梯度告诉我们「往哪个方向是下坡」,而「学习率」决定的是什么?
Q2「随机梯度下降(SGD)/ 小批量(mini-batch)」相比每次都用全部数据算梯度,主要好处是?
NEXT · 第 13 课

反向传播

有了 Adam,但梯度怎么算?对几亿个参数逐个试探需要几亿次前向传播——肯定有更好的办法。

0 人点赞,0 人看过