往哪边改、改多少?
本课一问:第 2 课有了尺子:「小猫 喜欢 吃 → 鱼」这一个例子,loss = −ln 0.0526 = 2.944。现在要改参数让它变小。60 个数,每个该往上还是往下?挪多少?
这一课先不碰:梯度怎么高效算出来(第 4 课,这一课先当它已知);动量、Adam、学习率调度这些更聪明的走法(C5);一次看多少例子(C5 岔路课)。
从已有出发
对话样本里,老师把这一步说得很具体:「反向传播算出来,猫这个向量应该第一维 +0.01、第二维 −0.02」,于是「训练前 猫 = [0.20, 0.70] → 训练后 [0.21, 0.68]」,并强调一次训练只改变一点点。这一课就在迷你模型上把这组数真算一遍,顺便回答两个问题:方向凭什么是这个方向;为什么只改一点点。
- 手写规则 / 把例子背成一张表
- 带参数的模型:用例子调数字
- 交叉熵:正确答案概率的负对数
- 梯度下降
- 反向传播(反向模式自动微分)
- 非线性多层网络
- 验证集、早停与正则化
- 深度学习为什么是经验性的
- 词向量:按编号查表
先自己设计:随便挑一个方向试
不会算方向,最朴素的办法是试:随机挑一个方向,沿它走一小步,loss 变小就留下,变大就退回。只有两个参数时,这招挺管用——一半的方向是下坡。可参数一多:
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
数字来源:浏览器实时训练(纯 JS,Float64)。模型、语料、种子写在上方;同一组对照里所有 run 共用初始化和取批顺序,只改被比较的那一项。换种子重跑能看到噪声多大——差异小于种子间波动时不下结论。
梯度 ∇L 是一个和参数一样长的向量,第 j 个分量是 ∂L/∂θj:「第 j 个数往上挪一点点,loss 变化多少」。在所有长度相同的小步里,沿 −∇L 走让 loss 下降得最多(一阶近似下)——它就是「最陡的下坡方向」。不用试,算出来就是。
维数越高,随机方向越接近和梯度垂直:余弦的典型大小约 1/√n。n = 2 时随机方向常常蒙对;n = 24,896 时几乎白走;锚点 Qwen3.8 有两百七十多亿个参数,1/√n 约 6 × 10−6。
改进一:方向 = 负梯度
在迷你模型上看清楚。只让「小猫」那两个数动(其余 58 个数固定在开局的值),「小猫 喜欢 吃 → 鱼」的 loss 就是这两个数的函数,可以画成一张地形图:
数字来源:浏览器实时计算(纯 JS,Float64)。例子、初始化与种子写在组件说明里;按词切只为演示,真实切分见 C1。已用 Python 独立实现逐位核对默认设置下的全部读数。
试三件事:① 默认 η = 0.1:读「梯度 ∇L = [−0.1912, 0.3736]」——第一维的梯度是负的,所以该往上加;第二维是正的,该往下减,和对话样本说的「第一维 +、第二维 −」一致;点常用里的 0.05,「走完」一栏正好是 [0.2096, 0.6813] ≈ [0.21, 0.68];② 点「对照:随机方向走同样长」几次:只有 2 个数时,随机方向也常常下坡,但余弦为负时 loss 会升;③ 点「走一步」「连走 10 步」,看灰线沿着等高线的垂直方向往谷底走。
把这一步写成式子:
改进二:步长 = 学习率,只改一点点
梯度是在当前这一点量出来的坡度。坡在一小片范围里可以当成平的(一阶近似):走 η·∇L 这一步,loss 应该下降约 η·‖∇L‖²。步子一大,落点离开了这片范围,近似就不准了。回到上面的组件,把 η 换成 1、3、10,对比「一阶近似预测的降幅」和「实际变化」:
| η | 预测降幅 −η‖∇L‖² | 实际变化 | 判断 |
|---|---|---|---|
| 0.1 | −0.0176 | −0.0175 | 很准 |
| 1 | −0.176 | −0.164 | 差不多 |
| 3 | −0.528 | −0.401 | 开始不准 |
| 10 | −1.761 | +0.375 | loss 反而升了 |
(迷你模型,种子 3,「小猫 喜欢 吃 → 鱼」这一个例子,只动「小猫」的两个数;表里的数都能在上面的组件里点出来。)
这就是「一次只改一点点」的真正原因:不是为了稳重,是因为梯度只在附近可信。走一小步,重新算梯度,再走一小步。
真语料上,学习率的影响更直接。先猜,再训练:
数字来源:浏览器实时训练(纯 JS,Float64)。模型、语料、种子写在上方;同一组对照里所有 run 共用初始化和取批顺序,只改被比较的那一项。换种子重跑能看到噪声多大——差异小于种子间波动时不下结论。
试三件事:① 先在紫色框里选一个猜测,再看结果:η = 0.001 太小,600 步只到 4.602;η = 1 最低,3.606;② 看左图(对数纵轴):η = 3 的前几步 5.55 → 9.07 → 11.26,冲高后又落回来,最终 3.796;η = 10 第 2 步 30.5,第 3 步一万多,第 9 步变成 NaN——数值溢出,训练报废;③ 换种子 2、3:具体数字变,排序不变。
常见误解一:「梯度指向最优解。」
梯度只指向此处最陡的下坡。上面的地形图里,从 [0.20, 0.70] 出发的负梯度方向并不正对谷底,灰线是弯着走过去的;在更复杂的地形里,最陡的下坡可能通向一个不怎么好的低洼(岔路课会看到这种「卡住」)。
常见误解二:「学习率越大,学得越快。」
η 从 0.001 加到 1 确实更快;再加到 3 就开始乱跳,到 10 直接发散。好的学习率在「够快」和「不炸」之间,而且会随模型、数据、批大小变化。
常见误解三:「每一步训练 loss 都会下降。」
真语料小网络每一步只看 32 条例子,算的是这一小批上的梯度;对这一批下坡,对全体数据不一定。所以训练 loss 曲线总是毛糙的,要看趋势。这个「随机」是随机梯度下降里的随机,C5 第 1 课细讲。
🔍 负梯度为什么是「最陡」的方向?
一阶近似:走一小步 d,loss 变化约 ∇L·d = ‖∇L‖·‖d‖·cos α,α 是 d 和 ∇L 的夹角。步长 ‖d‖ 固定时,cos α = −1(d 正对 −∇L)下降最多,这是柯西-施瓦茨不等式的直接结论。随机方向在高维里 cos α 集中在 0 附近,典型大小约 1/√n——所以上面 24,896 维的随机试几乎白走。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 在几万、几百亿个参数里找到「往哪边改」:随机试在高维里几乎白走 |
| ② 数学上为什么可能有效? | 负梯度是一阶近似下的最速下降方向 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条柯西-施瓦茨不等式;只在「小步」的前提下成立。 出处待补 ;若 loss 足够光滑(梯度变化有上界 L),η < 2/L 时每一步都保证下降 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条下降引理;前提是 L-光滑。深度网络整体上不满足一个已知的全局 L,所以它只说明「步子要小」,给不出具体的 η。 出处待补 |
| ③ 实验上为什么这样选? | η 的具体取值靠试:真语料小网络上 0.001 太慢、1 最好、3 抖、10 发散 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条浏览器实训,种子 1–3;换模型、换批大小,最好的 η 会变。 出处待补 |
一句话
梯度告诉你此处哪个方向下坡最陡;学习率决定沿它走多远——梯度只在附近可信,所以一次只改一点点,走一步再重新算。
先停在这里:记住 θ ← θ − η∇L:方向由梯度定,步长由 η 定。
再深一层:展开「为什么是最陡」的 Dig;想看这条路在更难的地形(峡谷)里怎么走、怎么加速,直接跳到 C5 第 1 课。
下一个缺口
梯度要对每个参数都算一遍——两万多个、两百多亿个参数,怎么算得过来? → 第 4 课:参数一多,梯度怎么算?
这一课的梯度 [−0.1912, 0.3736] 是组件直接算好给你的。第 4 课从 loss 开始,一格一格往回推,把它亲手算出来。
你可能会问
- 「对话样本的 +0.01、−0.02 是真的吗?」 是老师随手举的例子,没有对应的模型。在我们这个迷你模型(种子 3)上真算,方向恰好一致(第一维加、第二维减),大小取决于 η:η = 0.05 时是 +0.0096 与 −0.0187,四舍五入正好是 [0.21, 0.68]。换一个种子,方向就可能不同——方向由模型当前的其他参数决定。
- 「为什么不一步跳到谷底?」 因为只知道此处的坡度,不知道谷底在哪。只有 loss 是简单的二次函数时才能一步算出谷底;深度网络的 loss 没有这样的形式。
- 「学习率为什么不能用公式算出来?」 能算出来的只是「足够小就一定下降」这种保证,真实训练要的是「尽量大又不炸」,这取决于模型、数据、批大小——只能试。这类「数学给边界、实验定数值」的情况在深度学习里很常见,岔路课专门讲:深度学习为什么是经验性的?