这份讲义怎么用
这是老师的草稿,不是给学员的材料。学员看
课件,你看这一份。
课程作者 Chris Yang · Google Cloud AI Infra 架构师。
| 🎯 | 这一节要留下什么 讲完之后台下脑子里该剩的那一句。 |
| 🗣 | 讲稿 黄底的可以照着念。 |
| 🖥 | 屏幕 该滚到课件的哪张图、放大哪一格。
⭐ 这些提示挂了 class="board",构建时逐条对账 ——
指了不存在的图或小节号会当场报出来。 |
| ⚠️ | 别讲什么 这一节最容易跑偏的方向。 |
⏱ 时间:主线 80′
⭐⭐ 这一讲跟专题三不一样:它可以跳着讲。 专题三是一条故事线,跳一章下一章就没来处;这一讲是一张账单, 每一节回答的都是同一个问题的不同栏目。
⛔ 但有一处顺序不能倒:§1 必须在 §2 之前 —— 「激活为什么扔不掉」这句话不立住,第二节那笔交易就变成了凭空出现的技巧。
| 段落 | 分钟 | 能不能砍 | 说明 |
|---|---|---|---|
| 零 开场 | 3 | 不能 | ⭐ 那个「你猜哪个最大」的停顿很便宜但很有效 |
| 一 反向在干什么 | 15 | 不能 | ⭐⭐ 全讲唯一讲原理的一节,也最容易讲砸。 2026-09-17 从 12 加到 15:多了 fig-circuit 那个小电路
—— ⛔ 它不是补充材料,它是这一节唯一一次「台下能自己验一遍」的机会 |
| 二 拿算力换显存 | 15 | 可压到 10 | ⭐ 砍就砍名次表,交叉点那张图不能砍。 ⚠️ 2.5b(重算的静默风险)现场一句话带过即可,它主要是给自学的人看的 |
| 三 优化器 | 22 | 可独立成课 | ⭐⭐⭐ 最长。学习率那一段是台下最想听的。 +3 给 LoRA —— ⭐ 这是台下唯一会亲手跑的那种训练,性价比最高的三分钟 |
| 四 并行策略的来处 | 5 | 可压到 3 | ⭐ 有了 fig-zero 之后这一节快了
—— 还是先让台下自己推,再上图对答案 |
| 五 总账 | 11 | 可压到 8 | ⭐ 「6ND 会骗你」别砍; 5.4 那个小例子(125M、一张卡)能砍但最好别 —— 它是全讲唯一能手算的一格 |
| 六 训不崩 + 收尾 | 9 | 收尾不能砍 | ⛔ 最后那四条判据是全讲的落点 |
| 合计 | 80 | ⚠️ 附录(§7)不进课堂,它是给会后自己查的 |
⛔⛔ 上面那张表是愿望,下面这张是地板。 「地板」= 把这一节的讲稿一个字不落地念完、再加切图滚动的时间, 一句现场发挥都没有。每次 build 现数,不是估的。
| 节 | 台词汉字 | 切图 | 地板 | 80′ 版给的 |
|---|---|---|---|---|
| 第零节 开场:先把那句「装不下」拆开 | 252 | 1 | 1.5′ | 3′ |
| 第一节 反向到底在干什么 —— 以及激活为什么扔不掉 | 3,513 | 16 | 21.6′ | 12′ |
| 第二节 第一个真正的决策:拿算力换显存 | 1,096 | 5 | 6.7′ | 15′ |
| 第三节 真正的大头:优化器 | 6,342 | 24 | 37.7′ | 20′ |
| 第四节 这张账单直接决定了并行策略 | 538 | 2 | 3.2′ | 8′ |
| 第五节 总账、两个峰,以及交棒 | 999 | 3 | 5.7′ | 12′ |
| 第六节 训不崩:loss 飞了怎么办 | 1,101 | 7 | 7.3′ | 10′ |
| 七节合计 | 84′ | 80′ | ||
⛔⛔ 时间账(每次 build 现数)
讲稿台词 13,841 汉字(按 200 字/分 = 69 分钟) + 58 次切图(每次滚动定位按 15 秒 = 14.5 分钟) —— 合计 84 分钟,而这里面还没算任何讲图、互动、答问的时间。
⭐ 80′ 版:剩 -4 分钟给讲图和现场发挥。
🧵 上台之前:把三条暗线记在心里
⭐ 这一讲会报出几十个数字,但只有三条线。 讲的时候每碰到一次就点一次名 —— 台下记住的会是这三条。
① 每一个「怎么办」,都是从「有多大」里长出来的。 §2 的重算是因为激活最大、§4 的 ZeRO 顺序是因为优化器状态最大 —— ⛔ 这一讲从不介绍工具,只推结论。一旦讲成「接下来介绍 ZeRO」,这条线就断了。
② 同一条判据,换个前提就翻转。 §2 那篇 2022 年的论文(序列长度从 2K 到 128K,结论反过来)、 §5 那个 6ND(短序列好用、长序列低估五六倍)—— 两次都是「公式没错,前提变了」。
③ 查来的 vs 推来的,每次都要说清楚。
GPT-3 的学习率表、V3 的 schedule、ZeRO 的 16 字节 —— 都是查来的;
4.15 TiB、82.1%、94 条序列、六倍反推 —— 都是自己推的。
⛔ 台上把这两类混着报,是这一讲最容易掉的坑。
⭐ 课件最后新加了一节附录,把这两类逐条列了出来
—— 台上不用念,但上台前自己扫一遍;
被追问某个数从哪来的时候,直接翻到那一页。
🖥 投屏怎么放
⭐⭐ 这一讲的图大多是「一格一格讲」的, 整张投到 1280×720 上,最小字会掉到个位数 px。 正确的放法:点开单独一张,用 Ctrl/⌘ + 滚轮放到只剩一格,讲完横向平移。
⭐ 需要整张投的三个时刻(其余一律放大到只剩一格): 第一节的fig-act-bill(那座山要一眼看完)、
第二节那张交叉点图(fig-per-byte ——
它的全部意义就在两个模型的交点不在同一处这个画面上,拆开看就没有了)、
以及第五节开头的总账图(fig-step ——
先整张停三秒,让「四项摆在同一条时间轴上」这个画面落地,再放大)。
⭐ 另外记得课件右上角有个「只看图」开关。 投屏之前打开它。⚠️ 它收的是正文、列表和图注 —— 小节导语和落点带是刻意留着的(那是骨架)。 ⛔ 不开的话,台下会低头读字,不听你讲。
第零节 开场:先把那句「装不下」拆开(3′)
🎯 这一节只留一句:最大的那一块不是权重,也不是激活。
「专题一那一讲,我们跟着一个 token 走完了前向,
最后算出来一句话 —— 装不进任何一块卡。
今天我要说的是:那句话说得太客气了。
因为前向只是半张账单。」
「训练一步,显存里是同时压着四样东西的:
权重、梯度、优化器状态,外加一大堆不能算完就扔的中间结果。
—— 我现在请各位心里排个序:这四样,你觉得哪个最大?」
⭐ 停两秒,让台下真的猜。 这个悬念很便宜但很有效 —— 绝大多数人会猜权重或者激活。
「答案是优化器状态。
一个 671B 的模型,权重占 1.22 TiB,优化器状态占 7.32 TiB —— 六倍。
而它既不参与前向,也不参与反向,只在每一步的最后那一瞬间被用一次。」
⭐⭐ 然后交代这一讲的排法,这句话必须说。
「所以今天不按训练流程讲。
流程的顺序是前向、反向、更新 —— 那个顺序会让最大的那一块最后才出场。
我们按「谁最大」讲。每一节只回答同一个问题:
这一项有多大,能不能省,省它要拿什么去换。」
🖥 屏幕:课件 s零 那一屏就够,
不要提前翻到任何一张图。这三分钟全靠嘴。
⚠️ 也不要解释「优化器状态是什么」—— 第三节会花十分钟拆它。这里只报大小。
🖥 本节主屏:课件 第零节 开场:先把那句「装不下」拆开 · 本节无图(故意的)
第一节 反向到底在干什么 —— 以及激活为什么扔不掉(12′)
🎯 这一节留两样:三倍算力的出处,以及「反向必须用前向的值」这个枢纽。
⛔⛔ 这一节是全讲唯一一处「讲原理」的地方,而它极容易讲砸。 砸法是固定的:一上来写链式法则。⭐ 别那么开始 —— 先让台下感受到笨办法有多笨。
「先问一个笨问题:我怎么知道某一个参数该往哪边调?
最直接的办法 —— 把它动一丁点,整个网络重跑一遍,看 loss 变了多少。
……那三千亿个参数,就是三千亿次前向。
一次前向按一秒算,跑完要将近一万年。而这还只是一步。」
⭐⭐⭐ 这句是这一节的地基,念完停一下:
「所以反向传播真正解决的问题,不是「怎么求导」 ——
求导是高中的事。
它解决的是:怎么把三千亿次前向,压成一次。」
⭐⭐⭐ 但在讲笨办法之前,先补一格 —— 这一格决定了后面有多少人跟得上。 ⛔ 「求导是高中的事」这句话说完,台下会分成两半: 一半点头,一半心里想「我高中就没学明白」。⭐ 而这一讲后面**全部**建立在 三个词上:导数、偏导数、链式法则。花三分钟把它们说完,后面一路顺。 —— 不讲极限,不写公式,就一个词:兑换率。
🖥 屏幕:fig-slider,先只放 Ⓐ。
「把一个参数想象成调音台上的一个推子。
右边那个读数就是 loss —— 你可以理解成「现在有多难听」。
现在我把这个推子往上推一点点,推了零点零一。
读数从 5.00 变成了 5.03,变了零点零三。
⭐ 那这个推子的导数就是 0.03 除以 0.01,等于 3。
读作:你动一格,它动三格。」
⛔⛔ 这里要专门停一下强调,这是最容易混的一点。
「注意 —— 导数不是「读数是 5.00」。
5.00 是值。3 是兑换率。这是两件完全不同的事。
⭐ 本讲后面每次说「这个梯度大」,说的都是兑换率大,
不是说这个参数本身大。」
🖥 屏幕:平移到 Ⓑ。 ⭐ 指着那排推子讲,手真的按在屏幕上效果最好。
「那「偏导数」的「偏」是什么意思?就三个字:按住不动。
你看这一排推子 —— 我只动中间这一个,其余全按住。
在这个前提下量出来的兑换率,就叫偏导数。
⭐⭐⭐ 而这台调音台有三千亿个推子。
把它们各自的那个数排成一列 —— 那一列,就叫「梯度」。
⛔ 所以记住:梯度不是一个数,是三千亿个数。」
🖥 屏幕:平移到 Ⓒ。
「最后一个词:链式法则。
问题在于,推子不直接连到喇叭,中间隔着好几级。
第一级:推子动一格,中间量甲动两格 —— 兑换率 2。
第二级:甲动一格,乙只动半格 —— 兑换率 0.5。
第三级:乙动一格,难听程度动三格 —— 兑换率 3。
⭐ 那推子到难听程度,总兑换率是多少?二乘零点五乘三,等于三。」
⭐⭐⭐ 然后给那个比喻 —— 这一句讲完,链式法则这个词就再也不吓人了。
「这件事你其实天天在做:换汇。
人民币换港币一个汇率,港币换美元一个汇率 ——
人民币到美元的总汇率是多少?当然是乘起来。
⭐⭐ 链式法则就这一件事,没有别的。
⛔ 而有意思的是下一句:这一串数,从哪一头开始乘?
结果完全一样,可代价 —— 差一万年。
这就是我们接下来要讲的东西。」
⭐ 收这一格,只要一句:
「所以这一讲后面所有的东西,只用到这三句话:
导数,是你动一格它动几格;
偏导数,是其余全按住时的那个数;
链式法则,是中间每一级乘起来。
没有极限,没有 ε,没有要背的公式。」
然后给种子。这一段是全讲最好懂的一段,讲慢一点,它能买到后面的耐心。
「起点特别朴素:loss 是一个数。
那第一个梯度长什么样?网络最后吐出一个概率分布 ——
下一个字是「的」的概率零点三、是「了」的概率零点二;
而正确答案是一个只有一格是 1、其余全是 0 的东西。
第一个梯度,就是你猜的减去正确答案。
猜高了的地方是正数,该高没高的地方是负数。这个差,就是整条链的种子。」
⭐⭐⭐ 趁台下还跟得上,把整件事用一句大白话收一次 —— 这一格不要跳。 ⛔ 「梯度」这两个字会把一半的人吓住,而它的本意真的只是「一屋子人各提各的要求, 最后取个平均」。⭐ 先给这句人话,后面那些张量和矩阵乘才会被当成「实现方式」, 而不是「另一件更难的事」。
🖥 屏幕:fig-vote,先只放 Ⓐ。
「一条训练样本看完网络的输出,其实只会提一个要求:
该是「的」,那就把「的」推上去,别的推下去。
而且 —— 推多少,看差多远。 差得越离谱,要求越强烈。
⭐ 这就是刚才那颗种子,「预测减真值」,换成人话就是这一句。
⛔ 但注意:它只是希望。没有人能直接去改输出。」
🖥 屏幕:平移到 Ⓑ。 ⛔ 第②格那句「上游越亮的那根线,加粗越划算」—— 手指按住它,停三秒。 这一讲后面整本显存账,全挂在这一句上。
「输出改不了,那怎么办?想让一个数变大,其实只有三条路:
一,改偏置,直接给它加一点 —— 省事,但能调的余地很小。
二,改权重,把连过来的线加粗。
⭐⭐ 这里有一句最值钱的:上游越亮的那根线,加粗越划算。
花同样的力气,接在一个很亮的输入上,回报大得多。
三,让上一层更亮 —— 可上一层也改不了啊。
⭐⭐⭐ 所以这条要求就往回递了一层。
—— 「反向传播」这个名字,全部含义就在这儿。」
⛔⛔ 然后把第二条路和这一讲的主题接上。这是本节最重要的一次接头。 ⭐ 讲完这句,后面所有关于「激活为什么扔不掉」的话都不用再论证了。
「回头想想第二条路那句「上游越亮越划算」。
要知道改哪根线回报最大,你得先知道那根线的上游当时有多亮。
—— 而那个亮度,是前向算出来的。
⭐⭐⭐ 所以反向必须回头看前向留下的东西。
这一讲后面要讲的那一大笔显存,根子就在这一句话上。」
🖥 屏幕:平移到 Ⓒ。 ⭐ 这一格是全讲最适合让台下笑一下的地方,别讲得太严肃。
「但是 —— 不能只听一个人的。
你要是只听那条样本的,它说「把『的』推上去」,你就照做;
再来一条,它说「把『了』推上去」……
⭐ 要是从头到尾只听第一个人的,这个网络最后会学会什么?
不管你问什么,它都答「的」。
⭐⭐⭐ 所以只能把所有人的要求加起来,取个平均。
那个平均,就是梯度。」
⭐⭐ 最后这一句是给后面几节埋的,一定要说:
「顺便说一句,后面讲多卡训练的时候,会有一道叫「跨卡汇总」的东西。
它干的就是这个平均 —— 每张卡先收自己那批人的意见,再凑到一起。
⭐ 所以 batch 这个东西,不是为了把卡喂饱才有的。
它首先是「别只听一个人的」。」
⭐ 接着是最多人卡住的一处,必须专门点破:
「往回传的不是一个数。
是一整个张量,形状跟这一层的输出一模一样。
它的意思是:loss 对我这一层输出的每一个位置,各有多敏感。」
🖥 屏幕:翻到 fig-3x,
放大 Ⓐ,一格一格念那三次矩阵乘。
⛔ 第②格那句「用前向存下来的输入」—— 用手指着它多停三秒,
这一讲后面全挂在这一句上。
⭐⭐ 然后跳到 Ⓑ。这是这张图的钥匙,也是本节的高点。
「为什么反向是两次,不是一次?
不是因为它「比较慢」。是因为它要回答两个不同的问题:
一,我这块权重该怎么改;二,我前面那一层该收到什么。
两个问题,两次乘法。所以一加二等于三 ——
训练比推理贵三倍,就是这么数出来的,不是估的。」
⭐⭐⭐ 在讲「偏导数」之前,先上那张小电路 —— 这一步不要省。 ⛔ 前面这几分钟全是道理,台下会点头,但点头不等于懂了。 ⭐ 这张图小到能用眼睛跟着走,它是这一节唯一一次「你可以自己验一遍」的机会。
🖥 屏幕:fig-circuit,放大 Ⓐ。
⭐ 先只念黑字,把前向走一遍;红字先不提。
「看这个式子:f 等于 a 加 b,再乘 c。
a 是 2,b 是负 3,加起来 q 等于负 1。
q 再乘 c 等于 4 —— f 等于负 4。
这就是前向,从左往右一遍走完。」
⭐ 现在回头走,一个门一个门地念红字。 ⛔ 这里要慢,每个数都让台下自己先想一秒。
「反向从最右边起步,f 对自己的梯度是 1。
先看乘法门。c 的梯度是多少?……是 q,也就是负 1。
q 的梯度是多少?……是 c,也就是 4。
⭐ 看出来了吗 —— 它俩换过来了。
再看加法门:上游给了 4,a 和 b 各拿走 4,原样分。」
🖥 屏幕:平移到 Ⓑ。
「所以常见的门就三种脾气,记脾气比记公式管用:
加法门是个分发器 —— 上游给多少,两边原样各拿一份。
乘法门是个交换器 —— 各自拿对方的前向值。
max 门是个路由器 —— 全给赢的那个,输的拿零。」
⭐⭐⭐ 然后是这一格的真正用处。讲之前停一拍。 —— 这一整讲后面所有关于「激活」的话,都从这一句长出来。
🖥 屏幕:平移到 Ⓒ。
「再看一眼乘法门。算 c 的梯度,我用到了 q。
而 q 是前向算出来的。
—— 所以 q 不能扔。
⭐ 把这一个门乘以几百亿次,就是我们后面要算的那张「激活」账单。
激活不是框架顺手缓存的东西。是反向的数学,要求它在场。」
⭐ 「偏导数为什么让这件事变容易」—— 这是台下最想听、最少人讲清的一段。
「关键只有两个字:局部。
每一个算子只需要知道我自己是怎么把输入变成输出的,就能写出自己的反向规则。
它完全不需要知道整个网络长什么样。
—— 这就是为什么自动微分能做成一个通用库:
矩阵乘写一个 backward,softmax 写一个 backward,
然后框架只干一件事,按顺序倒着串一遍。
没有任何人需要手推整个网络的导数。」
「反过来想才知道有多可怕:
你要真去写「loss 对第一层某个权重」的解析式,那个式子要穿过六十一层展开,
项数是天文数字,写不出来。
⭐ 链式法则真正的意思是:你永远不用把它展开。」
⭐⭐⭐ 「按顺序乘起来」这句话说完,必须马上接下一句。 ⛔ 刚说完「把六十一个小导数按顺序乘起来」, 台下有人已经在想「那乘起来会怎样」。这一问是深度学习史上最出名的那个问题, 不接,后面讲归一化、讲残差、讲裁剪,全是无源之水。
🖥 屏幕:fig-vanish,先只放 Ⓐ。
「把六十一个数乘起来 —— 那乘起来会怎样?
看这张图。同一个六十层的网络,我只改一件事:每层的兑换率。
蓝色那条,每层一点二。你看它 —— 从右往左,直接冲出画面。
红色那条,每层零点八。它贴在轴上。
⛔ 我要专门说一句:那不是我画漏了,是它真的小到画不出来。」
🖥 屏幕:平移到 Ⓑ。 ⭐ 这一格换了对数轴,先解释一句为什么要换,不然台下会觉得你在换尺子糊弄人。
「线性的轴装不下这两头,得换成对数轴。
左边这个点,是零点八那条最靠输入的那层:一百万分之一点九。
右边这个点,是一点二那条:四万七千。
⭐⭐⭐ 中间隔着十个数量级。
而这两个兑换率 —— 零点八和一点二,只差两成。
所以这一格真正要留下的是这句:被指数放大的不是梯度,
是「每层偏离一多少」那个微小的偏差。」
⭐⭐ 然后 Ⓒ —— 台下一定会问「那这个兑换率是谁定的」。
「那每层的兑换率从哪来?有好几截,其中一截是激活函数的导数。
看这两条曲线。红的是 sigmoid 的导数 —— 它的峰值就这么高。
这个数是算得出来的:sigmoid 的导数等于 σ 乘以一减 σ,
在 σ 等于二分之一的时候最大,恰好是零点二五。
⛔ 也就是说,光是 sigmoid 那一下,每层就先乘了个不超过四分之一的数。
再看绿的,ReLU 的导数:正半轴恒等于一。
⭐⭐⭐ 这就是为什么 ReLU 一换上来,深网络忽然就训得动了
—— 它把每层那个「先天往下压」的系数,从四分之一变回了一。
⚠️ 我得补一句准的:权重那一乘还在外面,
所以不能说「一定衰减四倍」,只能说它先天就往下压。」
⭐⭐⭐ 最后讲这段历史 —— 这是全讲最好听的一个故事,值一分半钟。 ⭐ 讲的时候不要念论文题目的德文,说「一篇德文的硕士论文」就够了, 效果全在那个反差上。
「顺便说说这件事是怎么被发现的。
一九九一年,慕尼黑工业大学,一篇硕士论文。
⭐ 它是用德文写的,从来没有在任何英文期刊上发表过。
可就是这篇论文,第一次把「深网络为什么训不动」形式化地说清楚了。
三年后,大西洋另一边,Bengio 他们在 IEEE 上发了一篇 ——
标题叫《用梯度下降学长程依赖是困难的》。标题就是结论。」
⭐⭐ 然后给那个结尾。停一拍再说。
「这两拨人当时是各发各的,谁先谁后到今天还有争议。
⭐ 但故事的结尾挺好的:二〇〇一年,这四个人合写了一章,
题目叫《循环网络里的梯度流》。
当年分头发现同一件事的两拨人,十年之后坐到一起,把它总结了。」
⭐ 收这一格,一句话接回主线:
「最后提一个口径:这个问题最早是在循环网络上发现的,
不是在我刚才画的前馈网络上。
⭐ 但它们是同一件事 —— 循环网络按时间展开,
就是一个「层数等于序列长度」的超深网络。
当年那批实验的时间跨度是一千步,换算过来就是一千层。
⛔ 还有一条实用的:这两头的症状完全不同。
爆炸是吵闹的 —— loss 直接飞掉或者变 NaN,一眼看得见。
消失是静悄悄的 —— loss 就是不降,前面几层跟没训一样,
而且没有任何报错。⭐ 所以爆炸好查,消失难查。」
⭐⭐⭐ 最后一记,这是全节最深的一句,也是最容易被略过的一句。 ⛔ 这一段不要只用嘴讲 —— 上图,让台下自己数。
🖥 屏幕:fig-reverse,整张投,
先只指 Ⓐ 和 Ⓑ 两排,别急着说话。
⭐ 两排画的是同一条链,唯一的差别是箭头方向和种子插在哪一头
—— 这件事让人自己看出来,比讲出来有效得多。
「还有一个问题很少有人问:为什么是从后往前?
数学上两个方向都成立,算出来的结果一模一样。
区别只有一个 —— 你得把整条链走多少遍。」
「看上面这排。这叫正向模式:你想知道某个参数的梯度,
就在它身上插一个扰动,顺着链走到 loss。
可这一遍走完,你只拿到了这一个参数的梯度 ——
因为你这一遍只扰动了它一个。
三千亿个参数,就是三千亿遍。」
「再看下面这排。种子插在右边 ——
而右边只有一个数,就是 loss。
所以只插一次。
⭐⭐⭐ 关键在每个方块底下那个勾:往回走的路上,每一层的梯度顺手就到手了
—— 不是走完再统一算。
走到最左边的时候,三千亿个梯度已经全部在手里了。而你只走了一遍。」
⭐⭐ 这一条光说不够 —— 放那段九秒的动画,让他们看着等。
🖥 屏幕:anim-reverse。
「两条链一模一样,同时开跑。
上面那条是正向的算法:小球一次只能为一个参数跑一趟,跑完才点亮那一个。
下面那条是反向的:小球从 loss 出发往回走一趟,沿途所有参数一起点亮。
⭐ 现在注意看右边那摞方块 —— 跑一趟堆一块。
下面那条早就停了,只有一块;上面那条还在吭哧,一直堆到八块。
而真实模型里,那个『八』是三千亿。」
⭐ 让它循环两遍再往下讲 —— 那份等待本身就是论点。
🖥 屏幕:平移到 Ⓒ。 ⛔ 这一格是防止台下把结论记歪的 —— 不要跳过。
「所以规则只有一句:从窄的那一头起步。
⛔ 注意不是「反向传播永远更好」。
右边那个反例:十个参数、一百万维输出 ——
这时候你该从前往后,反向传播反而亏。
⭐ 我们之所以用反向,只是因为我们这一边正好是三千亿进、一个出。」
⭐ 收口回到账单 —— 这一句是给第二节的接口,不许省:
「回头看刚才第②步:算权重梯度,要用前向时存下来的输入。
—— 这就是激活扔不掉的根本原因。
不是谁设计得不好,是反向的数学本身要求它在场。」
⭐ 再补一小段,它是这一讲边界最正中间的一块。 —— ⛔ 时间紧可以整段跳,但跳之前先看一眼「不省算力」那条。
「刚才说的是梯度算出来那一刻。可它离被用掉还隔着好几道:
跨卡汇总、裁剪、也许还要累积几次,然后才交给优化器,用完扔掉。
—— 这几道每一道,推理里都没有。」
「其中那笔跨卡汇总有个反直觉的性质,值得单说:
它的量是参数量乘以每参数字节数 —— 跟 batch 完全无关。
你喂一条序列和喂一千条,传的是同样多的字节。
⭐ 而计算量是随 batch 线性涨的。所以 batch 越大,这笔通信被摊得越薄
—— 这就是为什么那些模型全都在往上爬 batch。」
「还有一件事:梯度是从后往前陆续出来的。
所以最后几层的梯度早就算好了,而前面几层还在算 ——
这段时间正好拿来传。
⭐ 算和传叠在一起,通信被藏进计算里 ——
这是训练里最重要的一类优化,而推理侧没有对应物。」
🖥 屏幕:切到 fig-act-bill,整张投。
这张图不用讲,指一下山顶那一竖说「峰值在这儿」,然后念两个数就走。
「一条十二万八千长度的序列,不开重算,激活要 4.15 TiB;
开了重算还要 106.75 GiB。
⚠️ 这两个数是我们自己按算子推的,没有第三方背书,当量级听。
但就算差一倍,结论也不变:这个规模上,装不下。」
⛔ 不要讲 forward-mode AD 的应用场景(雅可比向量积那一套)。 提一句「输出多的时候反过来更划算」就够,展开就是另一门课。
⚠️ 课件 1.7 那两张逐项拆解的表,整段跳过 —— 它是给会后自己算的人看的;台上提一句「拆解在课件里」就够。
⚠️ 4.15 TiB 报的时候必须带「自己推的」四个字。 这一讲后面还有好几个这样的数,第一次报就把规矩立住,后面省事。
🖥 本节主屏:课件 第一节 反向到底在干什么 —— 以及激活为什么扔不掉 · 主图 fig-3x
第二节 第一个真正的决策:拿算力换显存(15′)
🎯 这一节留一条判据(每省一字节付多少 FLOPs),和一个故事(判据没变,结论翻转)。
「上一节结束时,我们欠下一整条从头挂到尾的激活。
这一节要做的事很简单:拿第一样东西,去换第二样。
—— 这也是这门课到目前为止,第一次出现真正的取舍:
不是「有没有更好的办法」,是两样只能选一样,你选哪个。」
⭐ 账讲完了,回头把「梯度这一路都经过什么」串一遍。
🖥 屏幕:fig-gradlife。
「一个梯度从算出来到被扔掉,中间要过五道。
每一道都有人在上面做文章 —— 要么省显存,要么省通信,要么省时间。
⭐ 记住这张图的用法:后面每讲一个优化,都能在这五道里指出它动的是哪一道。」
⭐⭐ 顺手把一个流传很广的说法校准一下。
🖥 屏幕:fig-batch。
「『batch 开大就更快』—— 这句话有前提。
看 Ⓐ 这条曲线:左半段成立,右半段不成立。
左边并行度还没吃满,batch 大了步数少、每步没变贵,所以真的快。
⛔ 右边并行度吃满了,每步变贵的倍数,正好抵掉步数少的倍数。
⭐ 而几百亿参数、几百张卡的训练,基本都在右边这一段。」
🖥 屏幕:fig-recompute,
只放 Ⓐ 那两组条。⭐ 这张图讲的是形状,不是数字 ——
让台下自己看出「上面那根只长了一小截,下面那根几乎归零」。
「重算是什么?一句话:不存过程,只存存档点。
前向算出来的中间结果我不留了;反向要用的时候,从这一层的入口再往前跑一遍。
代价是多跑一次前向,算力从三倍变四倍 —— 多三分之一。
换回来的是:4.15 TiB 变成 106.75 GiB,四十倍。」
「⭐ 这个兑换比例夸张到不像是个权衡。
所以在大模型训练里,它默认就是开着的 ——
值得讨论的从来不是开不开,是开到哪一档。」
⭐⭐ 然后进本节的核心:判据。这一段要讲透,宁可砍后面也别砍它。
「怎么挑?只有一个数。
对每一个中间张量问同一句话:把它扔掉、反向时重算回来,每省一个字节要付多少次浮点运算?
比值小的扔,比值大的留。就这一个数,整张排序表自己就出来了。」
「而对线性层,这个数有个漂亮得出乎意料的闭式解 ——
它正好等于这个矩阵乘的输入宽度。
序列长度约掉了,输出宽度也约掉了。
⭐ 所以「哪个线性层最该重算」这个问题,不用算 —— 扫一眼 config 看谁输入最窄就行。」
🖥 屏幕:fig-per-byte,整张投。
⭐ 这是那三张要整张投的之一 —— 它的全部意义就在
两个模型的「交点各不相同」这个画面上,拆开看就没有了。
「看这张图。水平的那几条,是线性层 ——
水平的意思是它们的代价跟序列长度无关。
往上爬的那条,是 attention,它的代价随序列长度线性上升。
⭐ 关键在这儿:一条是常数,一条在往上爬 —— 那它们必然相交。」
🖥 屏幕:fig-per-byte,指两个交点
(紫色实线一组、橙色虚线一组)。
「但这张图上画了两个模型,而它们的交点不在同一个地方。
DeepSeek-V3 在五千七就交了;GPT-3 要到一万二才交。
⭐ 为什么?因为斜率不一样。那条斜线的斜率,是模型自己的头维度定的
—— 换个模型,你要重画的是两条线,而不是把这条挪个位置。
⛔ 这一格我原来就画错过:把 V3 的斜率直接套在 GPT-3 上,
交点标错了四千。—— 而这一讲从头到尾在讲「别拿 A 的常数套 B」。」
⭐⭐⭐ 接下来是全讲最好的那个故事。讲之前先停一拍。
「「选择性重算」这个概念,出自英伟达二〇二二年的一篇论文。
它的判据跟我刚才说的一模一样 —— 挑那些「占显存不少、但重算起来不贵」的扔。
……而它选出来要重算的,恰恰就是 attention。
收益还很漂亮:GPT-3 省 70% 的激活显存,只付 2.7% 的算力。」
「为什么反过来了?
因为它的序列长度是两千零四十八。
你看图上 GPT-3 那根竖线 —— 它落在交点左边。
在那儿,attention 比图上每一条线性层都便宜。
论文没错。是前提变了。」
「⭐⭐ 所以这件事值钱的不是结论,是这句话:
同一条判据、同一个模型族、判据一个字没改,结论翻转 —— 变的只有序列长度。」
⭐ 收口两句,一句实用一句通用:
「实用的那句:这事今天不用你操心了。 FlashAttention 天生就不把分数矩阵写进显存、反向时现算 —— 等于把论文那条建议做成了默认行为。 所以现代框架的候选名单里,attention 根本不出现。」
「通用的那句,请记住,它不只对重算成立:
凡是会改变数据分片形状的参数,都不能跨规模照抄。
—— 刚才那个例子说明这条规则比听起来更狠:
序列长度也在这个名单里,而且它翻转的不是收益的大小,是收益的正负号。」
⛔ 不要念那张名次表的每一行(课件 2.4 现在是一张八行的真表)。 只说三档:「白捡的、划算的、绝不动的」—— 要细的人自己看, 台上念表是最快的催眠方式。
⚠️ 不要把 FlashAttention 讲成「一个优化」。 它在这里的角色是「把论文那条建议内建了」—— 讲成优化就跟这条线断开了。
🖥 本节主屏:课件 第二节 第一个真正的决策:拿算力换显存 · 主图 fig-per-byte
第三节 真正的大头:优化器(20′)
🎯 本节留三样:16 字节是哪五样、高精度的判据、以及学习率的量纲。
⭐⭐ 这是全讲最长、也最独立的一节。 时间紧的时候,前两节压缩、这一节保住 —— 它单独拎出来就是完整的一课。
「现在说那个从开场就悬着的角色。
每一个参数,训练时身上挂着十六个字节。」
🖥 屏幕:fig-optimizers,先放大 Ⓑ 那根尺子
—— ⛔ 不要先放 Ⓐ 那条谱系,会让人以为这一节在讲优化器历史。
「两字节 bf16 权重、两字节 bf16 梯度,再加十二字节 fp32 的三份:
主权重、动量、二阶矩。
权重只占 2,优化器那边占 12 —— 六倍。」
⭐⭐⭐ 然后是本节第一个判据。这一段是现场问出来的,讲法照抄现场:
「有人会问:为什么有三格是 fp32、两格是 bf16?
—— 不用一格一格记,它们服从同一条判据:
看这个量,老的贡献走不走。」
⭐⭐⭐ 别用嘴讲这条判据 —— 把图放上去,让它当场算给台下看。 ⛔ 「小的加上去会被舍掉」是一句算术, 听众只能选择信或者不信。⭐ 而这张图里的数是脚本真算出来的, 你可以当场说这一句,它特别管用。
🖥 屏幕:fig-precision,先放 Ⓐ。
「先看一个小数在机器里是怎么存的:分成两段。
指数那段管「能多大」,尾数那段管「能多细」。
⭐ 现在看中间这行 bf16 —— 它的指数段跟上面 fp32 一样长。
所以 bf16 能表示的范围跟 fp32 一模一样,掉的只是精细程度。
⭐⭐ 再看最下面 fp16。同样是十六位,可它把三位从指数挪给了尾数。
于是它更精细,但范围小了一大截 ——
小的梯度直接掉到零。这才是 fp16 需要 loss scaling 的原因,
跟「十六位不够用」一点关系都没有。」
🖥 屏幕:平移到 Ⓑ。 ⛔ 这一格是整节的高点,慢讲,中间要停两次。
「现在做一件事。假设一个权重是 1.0,
每一步要给它加 万分之三 —— 训练后期这是很典型的量级。
看这根数轴:bf16 在 1.0 附近,相邻两个能表示的数之间隔着零点零零七八。
⭐ 中间什么都没有 —— 不是精度差,是那些数压根存不下来。
而我们要加的那个万分之三,只有一格的百分之三点八。
⛔ 四舍五入 —— 直接舍回原地。」
⭐⭐⭐ 停一拍,然后抛那个问题。台下一定会答错。
「有人会想:那多加几次不就行了?加二十六次就够一格了嘛。
—— 我真的跑了一千次。
⭐⭐⭐ 结果是 1.0。一步都没动。
因为每一次都是从 1.0 开始加,每一次都被舍回 1.0。它跨不过去。
右边那格是对照:同样一千次,改用 fp32 —— 1.0 变成 1.3。」
⭐ 然后收这一句 —— 它把「保险起见」这个误解直接掐掉。
「所以「主权重要留一份 fp32」不是保险起见。
不留,训练到后期就真的停在原地了 —— loss 不降,而你查不出哪儿错了。
⭐ 顺便说:这些数不是我从哪篇论文引来的,
是画这张图的脚本里真写了一个 bf16 舍入函数当场算的,
还有三条断言盯着。你可以自己跑一遍。」
🖥 屏幕:平移到 Ⓒ。
「有了这个画面,那条判据就不用背了:
看这个量,老的贡献会不会永远不走。
主权重 —— 跨十万步不断加进微小增量,老的一直在里面。必须 fp32。
梯度和激活 —— 算出来、用掉、扔掉,根本没有「老的」。bf16 就够。」
⛔ 紧接着给那个第一方反例 —— 不给的话这条判据会被听成过度简化。
「不过这条判据我原来说得太粗了,有一条第一方证据把它逼得更准了。
DeepSeek-V3 的报告里明写:他们把一阶矩和二阶矩都放成了 bf16,没有可观察的性能退化;
而主权重和梯度仍然保 fp32。
为什么?因为动量和二阶矩是滑动平均 ——
每一步都乘一个小于一的系数再掺新值,老的贡献会被衰减掉。
⭐ 滑动平均不是累加。真正的分界不是「累不累加」,
是「老的贡献会不会永远不走」。」
⭐ 第二段:那条谱系。这一段讲得轻快一点,它是过渡不是重点。
🖥 屏幕:同一张图,平移到 Ⓐ。
「这张图不按算法怎么算排,按每个参数挂几份状态排。
SGD 零份 → 加动量一份 → AdaGrad、RMSProp 各一份 →
Adam 和 AdamW 两份都要。
三十年一路往上加 —— 直到 2024 年,有人往回走了一步。
Muon 把二阶矩那一整份拿掉了,十六字节变十二。」
⭐⭐⭐ 但按字节排只是一种看法。再给一张图,换一条线看 —— 因果。 ⛔ 光念名字,台下只会记住「有这么几个」。 ⭐ 而这几个名字是一条链:每一个都在补上一个留下的洞。 讲完这一格,他们不用背了。
🖥 屏幕:fig-lineage,先只放 Ⓐ。
「我做了一件很简单的事:喂同一串恒定的梯度进去,
看每一家给出的有效学习率长什么样。
⭐ 梯度都不变了,那么一个健康的优化器应该给出一条平线。
凡是不平的,那就是它自己的毛病,赖不到数据头上。
看这四个小框里的曲线 —— 只有第一个和最后一个是平的。」
⭐⭐ 讲完这一串优化器,给他们一把随时能用的尺子。
🖥 屏幕:fig-updratio。
「怎么知道学习率设对没有?有一条能用眼睛对齐的线。
量的是更新量除以参数本身 —— 注意是更新量,不是梯度。
经验值是千分之一,图上那条黑线就是它。贴着线就大致合适。
⛔ 但 Ⓑ 那一格必须讲:太大那条的 loss 反而更低。
⭐ 代价在别处 —— 权重被撑到四倍多、抖动大了近十倍,
而学习率再乘 2.1 就直接 NaN。
所以这条比值不是让 loss 最低的指标,是看你离悬崖多远的指标。」
🖥 屏幕:平移到 Ⓑ。
「先看 AdaGrad,它的病在后期。
它的分母是「历史梯度平方的累加和」—— 只增不减。
于是有效学习率一路往下掉,跑到第六百步只剩稳态的百分之四。
⛔ 再强调一次:喂进去的梯度自始至终是同一个数。
不是数据变了,是那个只增不减的分母把它自己压死的。」
🖥 屏幕:平移到 Ⓒ。
「RMSProp 把「累加」换成「滑动平均」—— 分母会遗忘了,后期的病治好了。
⛔ 可它落下了新的:滑动平均是从零起步的。
头几步样本还没攒够,分母被严重低估 ——
第一步的更新被放大了三十二倍,直接冲出画面。
⭐ Adam 的偏差校正就是来修这一下的。你看绿线 —— 从第一步起就是平的。
⭐⭐ 还有一个细节挺妙:如果 Adam 只加动量、不做校正,
峰值只有六点六倍,不是三十二倍 ——
因为动量那一项自己也有偏差,两个偏差部分抵消了。」
⭐⭐⭐ 然后讲这三则出处。这一段是整节最好听的,值两分钟。 ⭐ 讲法:三个并排着讲,反差全在「出版物的规格」上。
「顺便说说这三个东西是怎么发表的,对比很有意思。
AdaGrad:正经的 JMLR 长文,整整三十九页。
⭐ 而且你去看题目 —— 《面向在线学习与随机优化的自适应次梯度方法》。
它根本不是为深度学习写的。」
「RMSProp —— ⭐⭐⭐ 它没有论文。
它唯一的「出版物」,是 Hinton 那门 Coursera 网课里的一页 slide。
今天所有引用它的论文,引的都是「第 6.5 讲」。
⭐ 而那页 slide 的副标题,本身就是这个算法的完整定义:
—— 「把梯度,除以它近期幅度的滑动平均。」
一句话,一页片子,成了这条链的中间一环。」
「Adam —— 这篇有两个地方我很喜欢,都印在论文里。
首页有个脚注:「作者顺序,由 Google Hangout 上掷硬币决定。」
⭐ 致谢里还有一句:「特别感谢 Ivo Danihelka 和 Tom Schaul 起了 Adam 这个名字。」
—— 这个名字不是作者自己起的。」
⭐⭐ 收这一格,用这一句。
「所以这条链最有意思的地方是 ——
一条改变了整个领域的技术链,中间那一环连篇论文都没有。
⭐ 而它成立的最硬的证据,是 Adam 论文自己证的:
AdaGrad 就是 Adam 的一个特例。
—— 后面那个能把前面那个含进去,这才叫链。」
⭐⭐⭐ 第三段:折算系数。这一段是本节的高点,也是最少人讲过的角度。
「现在问一个看起来很蠢的问题:
梯度是怎么变成权重更新的?
最朴素那版只有一行:新权重等于老权重减去学习率乘梯度。
—— 可这一行凭什么成立?」
「你仔细看:两边的单位对不上。
梯度的意思是「这个参数变一点,loss 变多少」,单位是 loss 除以参数;
可你要的是「参数该挪多少」,单位是参数本身。
所以中间必须乘一个东西把它折过来 —— 那就是学习率。
反推它的单位:参数的平方,除以 loss。」
「⭐ 所以学习率不是一个纯数字。
它跟你的 loss 有多大、权重有多大,全绑在一起 ——
这就是为什么换个模型、换个 batch,学习率就得重调。它压根不是通用常数。」
⭐⭐⭐ 先把「本源」那一格讲了 —— 它比后面所有技巧都重要。 ⛔ 台下多半从没被人正经讲过为什么顺着梯度走就能变好。 不讲这一格,后面整节优化器就是一堆没有地基的技巧。
🖥 屏幕:fig-descent,先只放 Ⓐ。
⭐ 那两串球是真跑了一遍梯度下降算出来的,不是摆上去的
—— 可以直说这一句,台下会更认。
「先看最简单的情况:只有一个参数。
规则只有一句 —— 看看脚下的坡,往下坡那边挪一点。
斜率是正的就往左,是负的就往右。反复做。
脑子里放一个画面:一个球,从山上滚下来。」
⭐⭐ 然后指红色那一串,这是第一个「免费的好东西」。
「注意看红色这几个球之间的间距。
第一步跨得最大,然后一步比一步小。
—— 为什么?因为我们把步长取成跟斜率成正比。
越接近谷底,坡越平;坡越平,步子自然越小。
⭐ 没有人让它慢下来,是坡自己变平了。
所以它不会在谷底来回冲过头 —— 这一条是白送的。」
⛔⛔ 接着指绿色那一串。这是这一格最该留下的一句。 讲完停一拍。
「现在看绿色那串,它从右边出发。
两串球用的是一模一样的规则。
可是 —— 红色落进了浅的那个谷,绿色落进了深的。
⭐⭐⭐ 差别只有一个:它们从哪儿出发。
所以要说清楚:梯度下降从来没承诺过最优。它只承诺,每一步都在变好。」
🖥 屏幕:平移到 Ⓑ,再到 Ⓒ。
「加到两个参数,「斜率」这个词就不够用了 ——
一个数说不清方向,得用一个向量。那个向量就叫梯度。
它指的是上坡最快的方向,所以下坡就取它的相反数。
⭐ 而它的长度还顺带告诉你:这个坡有多陡。」
「到了三千亿个参数 —— 别再想「山」了,山画不出来。
换个读法:那就是一列三千亿个数。
每一项告诉你两件事:正负,说这个参数往上推还是往下推;
⭐⭐⭐ 相对大小,说哪一项改起来更要紧。
—— 它不只告诉你往哪走,还告诉你该先动谁。」
⭐⭐⭐ 紧接着把 fig-saddle 放上来 —— 这一格是用来「解毒」的。
⛔ 上一格刚说完「落在哪个谷取决于起点」,台下现在心里是发虚的:
那不就是碰运气吗?⭐ 如果不把这个印象拆掉,后面讲什么调参他们都会半信半疑。
🖥 屏幕:fig-saddle,先只放 Ⓐ。
「刚才那张图留了个阴影:满眼都是坑,掉哪个算哪个。
现在我要说的是 —— 那个画面,是一维骗你的。
看这三格。坡度为零的地方,其实不止一种。
第一种,两个方向都往上 —— 这才是真谷底,往哪走都变差,真卡住了。
第二种,两个方向都往下,那是山顶,一推就走,训练里基本遇不到。
⭐⭐ 第三种最要紧:一个方向往上,另一个方向往下。」
⭐ 这时候给那个比喻 —— 它比任何数学都好使。 ⭐ 如果台下有爬过山的,这一句一说完他们就懂了。
「第三种有个特别贴切的名字:垭口。
就是翻山时那个豁口。
沿着翻山的那条路走,它是整条路的最高点;
可你要是横过来、沿着山脊走,它又是最低点。
—— 站在那儿,脚下确实是平的。但它根本没封死,路就在旁边。
⭐ 中文管这种地形,就叫鞍部。数学上这个点就叫鞍点。」
⭐⭐⭐ 剖面图讲完,把它转起来 —— 三维的形状二维画不出来。
🖥 屏幕:anim-saddle。
「刚才那张图是切了两刀给你看剖面。
而它真正的形状是这样的:红线沿一个方向往上翘,绿线沿另一个方向往下沉,
两条在中间那个黑点交叉。
⭐ 站在那个点上,脚下确实是平的 —— 可绿色那条路一直都在。」
🖥 屏幕:平移到 Ⓑ。 ⛔ 这一格是整张图的论证,三行要一行一行念,别一口气扫过去。
「接下来这一步,是这一整格的关键。
要当真谷底,条件是「所有方向都得往上」。
一维图上只有两个方向 —— 两个都往上,很容易凑齐。
所以图上才会坑一个接一个。
可我们谈的是几千亿个参数,那就是几千亿个方向。
⭐⭐⭐ 要它们全都往上 —— 只要漏掉一个,它就只是个垭口,还能接着走。」
⛔ 这里必须自己踩一句刹车 —— 不然就讲过头了。 ⭐ 台下里但凡有数学背景的,此刻正想举手。你先说,比被问住强。
「我得说清楚:这是定义层面的话,不是概率论证。
各个方向的弯曲方向并不彼此独立,所以我不会给你一个
「罕见到十的负多少次方」那种数字 —— 那个数是编的。」
🖥 屏幕:平移到 Ⓒ。
「而且这不只是推理,有人真去量过。
把训练一直跑到梯度为零,然后数一数:这个点有多少方向是往上的?
⭐ 结果是 —— 那个比例从来没到过 1。
换句话说:训练停下来的那些地方,总还剩一批方向是往下的。
它没走,不是因为没路,是因为坡太平了。」
⭐⭐⭐ 最后这个转折一定要讲 —— 它是整个第三节的引子。 ⛔ 只讲好消息,台下会觉得「那还调什么参」。
「所以「梯度下降为什么可以」,最深的那半个答案是这样的:
✅ 参数越多,它反而越不容易真卡住。
—— 顺带回答一个常见困惑:「参数多不是更难训吗?」
显存和算力上确实更难,但在「会不会卡死」这一项上,恰恰相反。
两件事各论各的。
⛔ 可坏消息是:卡不住,不等于走得快。
垭口附近坡极平、梯度极小,而我们的步长又是「跟坡度成正比」的 ——
那就会在那儿磨很久很久。
⭐⭐⭐ 记住这句 —— 我们接下来一整节要讲的那些优化器,
一多半就是在治这个。」
⭐⭐⭐ 话音刚落就上动量 —— 它是那句话的第一个答案,别隔开讲。 ⛔ 刚说完「卡不住但走得慢」,台下正等着「那怎么办」。 ⭐ 这一格只需要一个画面:一个球,一个浅坑,两条轨迹。
🖥 屏幕:fig-momentum,先只放 Ⓐ。
「办法叫动量。一句话就能说完:
这一步怎么动,不只看当前的梯度,还要看上一步是怎么动的。
—— 说白了就是给它一点惯性。
看这张图。同一条 loss、同一个起点,唯一的差别就是有没有惯性。
灰的那条,滚到半路这个浅坑就停了。
⭐ 而且我要强调:它是真停 —— 那一点的梯度已经归零,它动不了。
绿的那条,带着上一步的速度冲了过去,落进了后面那个更深的谷。
它还冲过了头,然后荡回来 —— 你看那几个点。」
⭐⭐ 然后 Ⓑ。这一格是机关,慢讲。 ⭐ 讲之前可以先问一句「它凭什么冲得过去」,让台下想三秒。
🖥 屏幕:平移到 Ⓑ。
「它凭什么冲得过去?
我把它刚越过坑底那一刻的账,拆成两项摆在这儿 ——
箭头的长度和方向,都是按真实数值画的。
第一项,梯度这一项:零点零九二,朝右。
⛔ 注意方向 —— 它在把球往回拉。因为球刚越过坑底,坡正拽着它回去。
第二项,惯性这一项:一点三零四,朝左。
两个加起来,净移动一点二一三,朝左 —— 继续往前。
⭐⭐⭐ 所以看清楚这一刻在发生什么:梯度是反对它继续走的。
是惯性把它带出去的。」
⭐⭐⭐ 然后讲历史。这段特别值,一分半钟。 ⭐ 它的杀伤力全在那个年份上,先把年份说出来再说别的。
「这个主意有多老?
一九六四年。
⭐ 比反向传播那篇 Nature 论文还早二十二年。
一位叫 Polyak 的苏联数学家,论文题目平平无奇,叫《加速迭代法收敛的一些方法》。
⭐⭐ 而他给这个方法起的名字是 —— 「小重球法」。
所以我刚才让你们脑子里放一个球,那个球不是我想出来的,是他起的名字。」
⭐⭐ 接着念那句原文 —— 它跟你刚讲完的 Ⓑ 一字不差。
「更妙的是,我刚才讲 Ⓑ 那段话,他在一九六四年就逐字写下来了:
—— 「运动不沿着力,也就是不沿着负梯度的方向走,因为有惯性。」
他还说,那一项会让它沿着谷底走。
⭐ 六十年前的一句话,说的就是我们刚才那三个箭头。」
🖥 屏幕:平移到 Ⓒ。
「最后一件事:那个 β 是什么。
「上一步的移动」里其实装着过去所有步,只是越老越轻 ——
每往前追一步就再乘一个 β。就是这排柱子。
所以它的有效窗口大约是 1 除以(1 减 β)。
β 等于零点九,就是十步左右。
⭐ β 不是玄学,它是一个「记多久」的旋钮。」
⭐⭐⭐ 然后抛这个包袱收尾。效果很好。
「顺便说 —— Polyak 在一九六四年给的经验取值是零点八到零点九九。
而今天 Adam 的默认 β₁ 是多少?零点九。
⭐ 六十年过去了,我们还在他给的那个区间里。
他甚至连调参顺序都写好了:先把动量关掉,把学习率调好;
等收敛慢下来了,再把动量加上。」
⛔⛔ 但收尾一定要踩这脚刹车,不然这一格会被听成「万能药」。
「不过我得说准一点。
⛔ 动量能冲过去的是「浅坑」,不是所有的坑。
图上那条能出来,是因为那个坑够浅;换个更深的坑,它一样出不来。
⭐ 所以它降低的是「从哪儿出发决定一切」的程度,不是消除它。
—— 它治的是「慢」,不是「最优」。」
⭐⭐ 最后这一句是本节的接头,一定要说。
「而那一整列数是从哪来的?
—— 就是第一节里,反向传播走一遍算出来的那一份。
⭐ 所以第一节和第三节,接头就在这儿。」
⭐⭐⭐ 在讲「怎么修」之前,先让台下亲眼看见那个痛。 ⛔ 「不同参数的梯度尺度差好几个数量级」这句话,说出来人人都点头, 可没人知道它长什么样。⭐ 这张图就是把那句话画出来 —— 讲完它,后面所有优化器都有了动机。
🖥 屏幕:fig-onelr,先只放 Ⓐ。
⭐ 先说清楚坐标:竖着弹的是陡的那个参数,横着爬的是平的那个,
谷底在右边。
「这是一个一边陡、一边平的谷。两条轨迹,
同一个谷、同一套规则,唯一的差别是学习率。
先看红色。它每弹一次幅度更大,弹着弹着就出画面了。
再看蓝色。它弹幅在收,最后是走到谷底了。
⭐⭐ 现在我告诉你这两个学习率差多少 —— 差一成。
红色比蓝色大百分之十。就这么点,一个炸了,一个没炸。
⛔ 你能下手的区间,就这么窄。」
⭐⭐ 然后指着蓝色那串锯齿 —— 这一句是这张图真正的收获。 ⭐ 大多数人看到「蓝色到底了」就以为它没问题。让他们再看一眼。
「可蓝色也不好。你看它那串锯齿 ——
每一步大半的力气,都花在左右横跳上了。
真正朝谷底去的,只有那一丁点横向的位移。
⭐ 它不是在走,它是在蹭。」
⭐⭐⭐ 那「到底该迈多大」有没有答案?—— 有,而且能算。
🖥 屏幕:fig-beststep。
「在一条抛物线上,最优步长是可以算出来的:梯度除以二阶导,一步到底。
⭐ Ⓑ 是这张图的机关:只看梯度会判断错。
陡谷的梯度是 2、平谷是 1,看起来陡谷离得更远该迈大步 ——
⛔ 错了,它其实离底更近。除以二阶导之后,两个才可比。
⭐ Ⓒ 回答为什么没人真去算:二阶导每两个参数之间就有一个,几千亿参数根本存不下。
于是只好去估它 —— 而那就是 Adam 分母那一坨的来历。」
🖥 屏幕:平移到 Ⓑ。 ⛔ 这三行是本讲自己的落点,一行一行念,第三行要停一下。
「那有人会说:取个中间值不就行了。
⭐⭐⭐ 问题就在这儿 —— 中间也没有好的。
第一行:再大一点,陡的方向直接发散。这个门槛是死的,
等于二除以陡峭程度,跟你想不想快一点毫无关系。
第二行:那就取最大的安全值。这时候平的那个方向走完一半,
要零点三七乘以陡峭比那么多步。图上这个谷陡峭比是二十五,所以九步。
⛔ 第三行 —— 真实模型上,这个比值是几个数量级。
按一千算,同一条公式给出三百六十四步。而这已经是最快的了。」
⭐⭐⭐ 收这一格,用这一句,然后直接进下一张图。
「所以我要说清楚:这不是参数没调好。
是这个谷的形状决定的 —— 而形状是模型给你的,不是你能选的。
⭐ 结论只有一条:别再找那个「最好的全局学习率」了,它不存在。
得给每个参数配它自己的那一个。
⛔ 而代价马上就来:「每个参数一个」,意味着你得为每个参数存东西
—— 这一讲开头那笔十二字节的优化器状态,根子就是这张图逼出来的。」
⭐ 然后一口气把自适应那条线串下来 —— 有了量纲这个框,它会讲得特别顺。
「所以自适应那条线的核心想法只有一句:
别用梯度的大小,只用梯度的方向 ——
把每个参数自己的尺度先除掉。」
「关键的一步在 Adam:它的更新量大约是动量除以二阶矩的根号 ——
分子分母的量纲互相抵消。
也就是说 Adam 把梯度的量纲给除掉了,这一步的大小大概就在 1 附近。
⭐⭐ 所以学习率在 Adam 里身份变了:它不再是折算系数,
它近乎直接就是「这一步每个参数挪多远」的上限。
—— 这就是为什么 Adam 的学习率那么好调、那么通用。不是玄学,是量纲被消掉了。」
⭐ 第四段:学习率怎么调。台下最想听这一段,但它最容易讲成玄学 —— 所以全程只报有出处的数。
🖥 屏幕:fig-lr-curve,先放大 Ⓐ。
「整条曲线只有三段:升上去、稳住、降下来。
先说 warmup —— 这里有个流行的解释是错的。
大部分教程说:Adam 一开始样本太少、二阶矩估不准。
二〇二四年有一篇专门做系统实验的论文,明确说这不是主因。
真正的机制是:warmup 让网络能承受一个更大的目标学习率,
它把网络推到 loss 曲面上条件更好的区域去。」
「而且还有一条反直觉的:目标学习率固定的话,warmup 拉长基本没收益。
决定效果的是峰值本身;warmup 的价值是让你敢把峰值设高。
实际用多长?GPT-3 是头三亿七千五百万个 token,占总量的千分之一点二五。
—— 这一段短到可以不当成超参看。」
「峰值设多少?这个有现成的表可以抄,不用猜。
GPT-3 论文表 2.1 把七个规模一起列了:三亿五千万用三乘十的负四次方,
一路到一百七十五 B 的零点六。
⭐ 规律肉眼可见:模型越大,学习率越小、batch 越大。
而且幅度很温和 —— 五百倍的规模差,学习率只差五倍。
⛔ 注意那张表里 batch 和学习率是一起变的 ——
这是最容易漏的一条:你不能只调学习率不看 batch。」
🖥 屏幕:平移到 fig-lr-curve 的 Ⓑ。
「怎么降?两个流派。
老派是余弦:GPT-3 在两千六百亿 token 内降到峰值的百分之十,之后一直保持。
新派是先恒定、最后才降:DeepSeek-V3 升到峰值之后一路平着跑,
跑到十万亿 token 才开始降。
⭐ 新派流行的理由特别实在:余弦要求你一开始就知道总共训多少步,
因为曲线形状依赖终点;而恒定段可以随时截断,接一小段衰减就能出一个能用的
checkpoint。它把「训多久」这个决定,从开局推迟到了随时。」
「⭐⭐ 最后指一下图上那条横贯全场的虚线:
两派的终点,都落在峰值的十分之一附近。
⚠️ 两个样本不构成定律 —— 但足以说明「降到零」不是默认做法,
这一点跟很多人的印象相反。」
⭐ 然后两小段,各一分钟 —— 它们不是重点,但不说会留问号。 ⛔ 台下一定有人在想「那 β₁ β₂ 呢」「checkpoint 为什么那么大」。 ⭐ 这两个问题都能用已经讲过的东西一句话答完, 所以别跳过,也别展开。
「先补一句 β₁ 和 β₂。大家一般当成「用默认值就行」——
其实它们的含义特别清楚:β 决定「老的贡献能活多久」。
滑动平均每步乘一个 β 再掺新值,所以有效窗口大约是一除以(一减 β)步。
β₁ 等于 0.9,窗口约十步 —— 它只负责把方向的抖动抹平。
β₂ 等于 0.99,窗口约一百步。
⭐ 所以 β₂ 调大 = 分母更平稳但反应慢,调小 = 跟得紧但噪声大。
不是玄学,就是一个「记多久」的旋钮。」
⭐⭐ 如果时间够,再加这一句 —— 它把前面那条精度判据往回咬了一口。 ⚠️ 这是我们自己推的,说的时候必须带上「这是猜想」。
「有意思的是 PaLM 让 β₂ 随步数变,越往后窗口越长 ——
到十万步的时候窗口能到一万步。
⛔ 那就跟我们前面那条判据打架了:我们说
「滑动平均有遗忘,所以 bf16 扛得住」。
可 β₂ 一路涨到 0.9999,那个遗忘就慢得快要不遗忘了 ——
v 越来越像一个真的累加器。
⚠️ 所以那条判据得带个前提:它成立的条件是「β 不随步数趋近 1」。
⛔ 这一条是我推的,不是论文说的 —— 当猜想听。」
「第二小段:checkpoint 要存什么?
—— 答案不用查文档,刚才那张十六字节的表直接就能推出来。
一格一格问「丢了能不能重建」:
bf16 权重,不用存,它是主权重的投影,转一下就有。
bf16 梯度,不用存,下一步重新算一份。
fp32 主权重、动量、二阶矩 —— 三个都得存,它们是历史,丢了只能从零重来。
⭐⭐⭐ 所以 checkpoint 的大小,正好就是那十二字节。
671B 的模型,一份七点三个 TiB。」
⭐ 然后这两句要说 —— 它们解释了两件工程上人人遇到过的事。
「这一下就解释了:
一,为什么 checkpoint 这么大、存这么慢 ——
它存的不是模型,是优化器。模型本身只占三分之一。
二,为什么「发布的模型权重」比 checkpoint 小得多 ——
发布只要那两字节的推理权重。一比六。
⛔ 最后提醒一句:只存这十二字节还不够,还有三样 ——
步数、数据读到哪儿了、随机数状态。
⭐ 第二样最容易漏,而且漏了最隐蔽:恢复之后把同一批数据重训一遍,
loss 曲线看着完全正常。」
⭐⭐⭐ 收口之前,加一段 LoRA —— 这是台下唯一会亲手跑的那种训练。 ⛔ 别把它讲成「一个新方法」。它不需要任何新概念, 就是刚才那张 16 字节的账换个算法重算一遍 —— 所以它只要三分钟。
「在收口之前插一段,因为这一段跟在座各位关系最大。
前面算的全是从零开始训。可各位这辈子真正会亲手跑的训练,
多半是拿别人训好的模型接着调。
—— 那 LoRA 到底省了什么?就用刚才那三本账,一本一本对。」
「第一本,常驻。底座冻住,只在旁边挂一对很瘦的小矩阵。
七十亿参数的模型:全量微调要一百 G,LoRA 只要十二点七 G
—— 差了将近八倍。
⭐ 为什么差这么多?因为那十六字节里,有十四字节是「只有要被更新的参数才需要」的。
冻住的参数只留两字节权重 —— 它退回成了推理的样子。」
「第二本,算力。这一条直接来自第一节。
还记得反向要付两笔乘法吗 —— 算输入的梯度、算权重的梯度。
冻住的那些层,第二笔可以整个不算:它的权重根本不更新,算出来也没人用。
所以前向一,反向只剩一 —— 三倍变两倍。」
⛔⛔ 第三本是这一段的重点,也是台下最容易误会的一条。讲之前停一拍。
「第三本,激活。很多人以为「只训千分之一的参数,训练就变得很轻」。
—— 显存上不是。
因为 adapter 是挂在每一层上的。最前面那层的 adapter 也要梯度,
而梯度只能从 loss 一路传回去。
所以整条链的激活,该在场的还得在场。
⭐ 结论很具体:LoRA 之后,激活往往成了新的大头 —— 所以 LoRA 还是要开重算。
这两件事不是替代关系,是叠加关系。」
「一句话收:LoRA 改的是「有多少参数带着那十六字节」, 它没有改变「反向要穿过整个网络」这件事。」
⭐⭐ 收口之前,给 Muon 一分钟 —— 而这一分钟只放一格。
⛔ fig-muon 有四格,Ⓐ Ⓑ Ⓓ 这次都别放。
⭐ 只有 Ⓒ 值这一分钟:它是台下唯一能看见的那个答案,
其余三格都得靠讲,而讲就超时。
🖥 屏幕:fig-muon,只放 Ⓒ,
一分钟后就切走。
「最后花一分钟说 Muon,只讲一个画面。
我们前面说「一步不许迈太大」—— 可「太大」得先有把尺子量。
⭐ 用一把尺量,「不许超过一格」圈出来的是个圆;
换另一把尺,圈出来的是个方。
同一个梯度方向,在圆上走到最远,是延长线上那一点 —— 那就是 SGD。
⭐⭐ 可在方上走到最远,落在角上 —— 那个角就是 Muon。」
⭐⭐⭐ 然后用这一句把整节接回去,讲完就切走。 ⭐ 这句话跟前面「最快是相对于你怎么量一步」那条前提是同一件事, 说出来台下会有「哦」的那一下。
「所以 Muon 不是「又一个新优化器」。
它跟 SGD 是同一个问题的两个答案 —— 区别只在你拿哪把尺子量「一步」。
⛔ 至于那把尺子怎么算出来的、Newton-Schulz 是什么 —— 今天不讲,超纲。」
⭐ 本节收口,三句话,念完就走:
「这一整条线可以用一句话收:
梯度只告诉你往哪走,优化器决定走多远。
而几十年的演化全都在回答同一个问题 —— 这个「多远」该由谁说了算:
SGD 说由你说了算;Adam 说由梯度自己的历史尺度说了算;Muon 说由矩阵的几何说了算。」
⛔ 不要比较哪个优化器收敛快。本课没有这些优化器的对照实测 —— 说了就是编。课件里那张图刻意不含任何收敛曲线,台上也要守住。
⚠️ Muon 那一段控制在一分钟。它在这一讲里的角色只是「有人往回走了一步」, 展开讲 Newton-Schulz 会把节奏带偏。
⚠️ 报学习率数字时,一定要连 batch 和 schedule 一起报。 单报一个数是没有意义的,而且台下真的会抄回去用。
⛔ LoRA 那一段不要展开讲「秩怎么选」「挂哪几个矩阵」。 那是另一门课。这里它的角色只有一个:同一张账换个算法重算一遍 —— 三分钟,到「激活不省」那句就收。
🖥 本节主屏:课件 第三节 真正的大头:优化器 · 主图 fig-optimizers
第四节 这张账单直接决定了并行策略(8′)
🎯 这一节只留一件事:ZeRO 的三级不用背,它是从账单里推出来的。
「把前面三节的东西摆在一起,按占多少排个序 ——
这个顺序本身就是这一节的全部内容。
① 优化器状态,每参数十二字节,最大 —— 而且只在更新那一刻用一次。
② 激活,随 batch 乘序列长度涨 —— 长上下文下它可以反超优化器状态。
③ 权重,每参数两字节 —— 但每一层前向都要用它。
④ 梯度,两字节 —— 反向结束时才需要完整的一份。」
⭐⭐⭐ 然后是本节唯一的动作:把这个顺序倒过来读。 讲到这里可以停半拍,让台下自己往下接 —— 很多人会自己说出来。
「现在把这个顺序倒过来读一遍,ZeRO 的三级你就自己推出来了。
原则只有一条:谁最大、谁最少被用到,就先切谁。
ZeRO-1 切优化器状态 —— 最大,而且只在更新时用一次,切了几乎不增加通信。
先切它,性价比最高。
ZeRO-2 再切梯度 —— 次大,反向结束前它可以是散着的。
ZeRO-3 最后才切参数 —— 因为每一层前向都要用它,一切开,
每层都得先把它拼回来。通信代价是三级里最高的。」
「⭐⭐ 所以这个顺序不是随意的,也不是历史巧合。
它是「大小」和「被用到的频率」这两个量排出来的。」
🖥 屏幕:到这里才上图 —— fig-zero,
先只放 Ⓐ。
⭐⭐⭐ 顺序很重要:先让台下自己推出来,再给图当答案。
—— 反过来先放图,那八分钟里最值钱的那个「自己推出来」的动作就没了。
「对一下答案。同一根条,被削掉三次。
基线每张卡要装 120 GB —— 这还只是七十五亿参数的模型。
切完优化器状态:31.4。再切梯度:16.6。最后连权重也切:1.9。
⭐ 从 120 到 1.9,而模型一个字节都没变小。」
「右边那一列是价签 —— 通信量。
前三行都是 2Ψ,跟不切的时候一模一样:
所以前两级基本是白捡的。
只有最后一级涨到 3Ψ,也就是 1.5 倍。
⛔ 这三个数指一下就走,怎么算出来的是下一讲的事。」
⭐ 然后把别的名词也摆回同一张账单 —— 这一下会让整讲收得很紧:
「顺手把其它几个常听见的名词也摆回这张账单上:
重算,针对激活那一项;offload,针对「暂时用不到」的那些项 ——
注意它切的不是「哪一类」,是「哪一段时间」;
上下文并行,针对激活里随序列长度涨的那一块。
⭐ 所以这几个名词不是几种优化技巧 ——
是同一张账单上四个栏目各自的对策。」
🖥 屏幕:平移到 fig-zero 的 Ⓑ 收尾。
⭐ Ⓑ 就是刚才那句「大小 × 用到的频率」画出来的样子 ——
讲完这一节,台下应该能指着 Ⓑ 把 Ⓐ 重推一遍。
⛔ 不要把 FSDP 说成「另一种方案」。它约等于 ZeRO-3,说成两种会让台下多记一个名词。
⚠️ 如果有人问「那 TP / PP 呢」—— 答「它们切的是另一个维度,下一讲」,别展开。
🖥 本节主屏:课件 第四节 这张账单直接决定了并行策略 · 本节无图(故意的)
第五节 总账、两个峰,以及交棒(12′)
🎯 收尾。留三条判据,比留任何一个数都重要。
🖥 屏幕:fig-step,先整张投三秒,
再放大 Ⓐ。⭐ 这是全讲第一次把四项画在同一条时间轴上,让那个画面先落地。
「先把显存的总账封口。算式短到可以口算:
六千七百一十亿参数 × 十六字节 ÷ 1024 的四次方 = 9.76 TiB。
换算一下就知道是什么量级 —— 按每张卡 80 GiB 算,光这一块就要 125 张,
还没算激活、没算任何冗余。」
⭐⭐ 然后是算力那一段。这一段是写课件时自己撞出来的,讲出来效果很好:
「算力这边有个人人都在用的估法,叫 6ND ——
每个参数、每个 token 大约六次浮点运算。
代进去:一条十二万八千的序列,约 29 PFLOP。
……但这个数在这儿是错的,而且错得很多。」
「因为 6ND 数的是「跟权重相乘」那部分。
而 attention 里那两步没有权重参与 —— 它们根本不在这个公式的账里。
而第二节我们算过:在这个长度上,attention 占一层前向算力的 82%。
⭐ 反推一下:真实算力大约是 6ND 的五到六倍。」
「⭐ 反过来说,6ND 在短序列上是很好用的 ——
GPT-3 那个两千零四十八,attention 只占百分之一点几,漏掉完全无所谓。
又是同一件事:不是公式错了,是前提变了。」
⭐⭐⭐ 然后是本节最漂亮的一处 —— 它顺手修正了第一节给过的一个答案。 当着台下承认这一点,比假装一开始就说全了要好。
「第一节我给过一个答案:峰值在前向末尾。
—— 那句话只在谈激活的时候成立。
你看这张图:激活的峰在前向末尾,梯度的峰在反向末尾 ——
两个峰根本不在同一时刻。」
「⭐ 推广出去,这是一条到处能用的判据:
把几条形状不同的曲线叠起来之后,总和的峰未必落在任何一条单独的峰上。
所以「什么时候最挤」这个问题,必须连着「挤的是哪一项」一起问。
工程上的直接后果:查 OOM 的时候,光知道「峰值多少 GiB」没用 ——
要知道那一刻是哪一项最大,才知道该动哪个开关。」
⭐⭐ 静态的账讲完,放那段动画看它在一步之内怎么涨怎么落。
🖥 屏幕:anim-memtime。
「显存不是一个常数,它在一步之内就有起伏。
前向往上堆激活,反向一边用一边放,更新那一下优化器状态全在场 ——
⭐ 峰值出现在某一个特定时刻,而你要买的是那个峰值。」
🖥 屏幕:平移到 fig-step 的 Ⓑ。
「最后一个问题:激活大,还是优化器状态大?
—— 这个问题没有固定答案。
常驻那一块不随 batch 变,而激活线性地随 batch 涨。
对这个模型,要约九十四条十二万八千的序列,激活才追平常驻块。
⭐⭐ 所以「谁最大」不是模型的属性,是这次训练配置的属性 ——
换个 global batch,答案就换了。」
⭐ 交棒。这两句是给专题五的接口,不许省:
「专题一算完前向,结论是「装不下」。
今天把账补全之后,那句话变具体了 ——
不是「装不下」,是四项各自装不下,而且各有各的治法:
优化器状态切、梯度切、权重最后才切、激活重算或者按序列切。
⭐ 你会注意到四条里有三条写着同一个字 —— 切。
那就是下一讲整讲要做的事:切这件事本身,也是要算账的。」
⭐⭐⭐ 最后一段,这是全讲真正的收尾。念完就停,别补话。
「今天报了很多数。但我真正想留下的不是那些数,是四条判据:
一,要不要高精度,比的是两个数 ——
「这一项每一步挪动的相对幅度」,对上「尾数能分辨的最小格」。
bf16 那一格大约是二百五十六分之一。
滑动平均每步都在遗忘,挪得动;主权重跨十万步累加、单步只挪千分之几,挪不动。
二,该不该重算,看「每省一字节要付多少 FLOPs」。
线性层的这个数恰好等于输入宽度;attention 的随序列长度线性上升
—— 两条斜率不同,必然相交。
三,两个量如果对同一个变量的增长速度不同,那它们的排序必然在某一点翻转。
所以任何「A 比 B 划算」的结论,都得带上它成立的那一段区间
—— 脱离区间的排序是没有意义的。
四,评价任何一个稳定性手段,要同时看「稳没稳」和「质量掉没掉」。
只看前者的话 —— 把学习率设成零是最优解。
数字会过期,这四条不会。」
⛔ 不要把 9.76 TiB 说成「需要 125 张卡」当结论。 那个 80 GiB 是随手设的换算基准,不是在说某款具体的卡; 而且真实部署还要算冗余、通信缓冲、碎片。只报量级。
⚠️ 「五到六倍」那个反推数,报的时候要说清它是从 82% 推的,而 82% 是自己算的。 这一讲从头到尾都在守这条规矩,最后一节别破功。
🖥 本节主屏:课件 第五节 总账、两个峰,以及交棒 · 主图 fig-step
第六节 训不崩:loss 飞了怎么办(10′)
🎯 这一节留一条:评价任何稳定性手段,都要同时看「稳没稳」和「质量掉没掉」。
⭐⭐ 这一节的位置很特别 —— 它是唯一一节讲「出事了怎么办」的。 前面六节都在算账,可账算得再清楚,也回答不了训练现场最常问的那一句。
「前面我们把账算完了。
但真到了机器上,最常听见的一句话不是「显存不够」,而是 ——
「哎,loss 飞了。」」
🖥 屏幕:fig-spike,先只放 Ⓐ,停三秒不说话。
⭐ 这张图的作用是让没见过训练曲线的人先有画面 ——
台下有一半人这辈子没盯过 loss 曲线,你直接讲「spike」他们脑子里是空的。
「上面这条红的,是 PaLM 训 540B 的时候,loss 大概长的样子。
一路往下走,那是它在变好。可你看这些往上扎的尖 ——
大约二十次。
再看下面这条绿的:同一套配方,换个小一点的模型,一个尖都没有。」
⭐ 这里要提醒台下两件事,都在图上写着。
「第一,这些尖出现的时刻完全没有规律 ——
挤在一起的有,隔很久才来一个的也有,训到很晚了还会来。
所以不要以为「开头挺过去就没事了」。
第二,纵轴上我一个刻度都没画,这是故意的。
论文只描述了这些尖长什么样,没给具体的数
—— 没有刻度的曲线是示意,有刻度的才是数据。」
⭐⭐⭐ 治法二:治结构。而这一格顺带把 3.5 那个悬案收了。
🖥 屏幕:fig-prepost。
「Post-LN 里,归一化本身就是梯度消失的元凶之一。
为什么?初始化那一刻,x 和 F(x) 的方差各是 1,加起来是 2,
而 Norm 要把它拉回 1 —— 所以它相当于除以根号二。
一层一层递归下去,最初那个输入在第 l 层只剩二的负 l 除以二次方。
看这张图:到第 24 层,只剩四千零九十六分之一。
⭐⭐ 现在看左右两半 —— 曲线一模一样,连坐标都没动,变的只有底下那个结论。
预训练时这叫『残差名存实亡』;可微调的时候,它正好替你把前面的层按住了。
同一条曲线,两种价值。」
⭐⭐ 最后清掉一个常见误解 —— 这张图只有一根真数轴。
🖥 屏幕:fig-underflow。
「『bf16 要不要 loss scaling』—— 不用。
但理由不是『16 位够用』—— fp16 也是 16 位,而且尾数比 bf16 还多。
⭐ 看这根对数轴:fp16 的归零线在这儿,bf16 的下界远在左边 33 个数量级之外。
中间那一大片绿,全是 bf16 存得下、fp16 存不下的。
⭐⭐ 所以 fp16 的毛病不是『不够细』,是『下不去』—— 它的指数位只有 5 位。
而 loss scaling 做的事,就是把整条分布在这根轴上往右推。」
🖥 屏幕:平移到 fig-spike 的 Ⓑ。
⭐⭐⭐ 这一格是整节的钩子,讲完要停一拍。
「而这一节真正刺耳的,是括号里那半句话 ——
梯度裁剪是开着的。
裁剪管的是「这一步最多迈多大」,它是所有人心里的那道保险。
保险开着,还是飞了二十次。
⭐ 所以问题不是「某一步迈太大」这么简单。
那到底是为什么?—— 论文自己说:不知道。
原话是训练成本太高,没能找到一个有原则的缓解办法。」
⛔ 这句「不知道」要原样讲出来,不要圆场。 ⭐ 台下将来自己训模型遇到 spike,会一遍遍去找自己哪个参数配错了 —— 告诉他们这是开放问题,比给他们三个技巧更有用。
🖥 屏幕:切到 fig-stability,先放大 Ⓑ。
⛔ 不要从 Ⓐ 开始 —— 先讲那个反直觉的实验,台下才会认真听后面的分类。
⭐⭐⭐ 然后是这一节的钩子。讲之前停一拍,让台下先给出第一反应。
「第一反应是什么?肯定是那批数据有问题。
他们去验了。做法很干净:把 spike 前后那几批数据单拎出来,
从另一个更早的 checkpoint 重新喂一遍。
……不飞。」
「⭐ 所以 spike 不是坏数据造成的。
是这批数据,和当时那个参数状态,两样撞在一起才出的事。
缺一样,都不会飞。」
「这一下就解释了他们那个看起来很土的办法为什么管用 ——
回滚到 spike 之前大约一百步,跳掉那两三百批数据,接着跑。
之后同一个点就不再飞了。
⛔ 但要说清楚:这不是修好了,是绕过去了。
论文自己也写着:由于训练成本太高,他们没能找到一个有原则的办法。」
🖥 屏幕:平移到 Ⓐ。
「知道了这一点,再看治法就有框架了。三类,治的是三个不同的位置。
治结构 —— 改网络本身,让它天生不容易飞:归一化放进残差块里、QK-norm、初始化。
治数值 —— 不让某些量长太大:z-loss、梯度裁剪。
治现场 —— 已经飞了怎么救:回滚加跳数据。
⭐ 越左越治本,越右越应急。所以「先动哪个」是有顺序的。」
⭐ 然后是本节的落点,也是全节最该带走的一句。
🖥 屏幕:平移到 Ⓒ。
「不过这一节真正的难点不是「怎么让它稳」。
让它稳太容易了 —— 学习率设成零,保证不飞。
难的是:稳住,而且不掉质量。」
「ST-MoE 那篇论文把这件事量出来了。同一个配置跑三次:
基线,六次里崩两次,质量负一点七五五。
收紧 update clipping —— 三次全稳,质量负四点二零六。
router z-loss —— 也是三次全稳,质量负一点七四一,还略好一点。
⭐⭐ 中间那一行是这张表的全部价值:「稳定 3/3」看着完美,可它是拿质量换来的。」
⭐ 最后给一句可迁移的:
「所以记住这条 ——
评价任何一个稳定性手段,都要同时看两栏:稳没稳,以及质量掉没掉。
只看前一栏的话,「把学习率设成零」是最优解。」
⛔ 不要在这里讲 Pre-LN 的证明。课件 6.5 有,而且它顺带回答了 3.5 的 warmup 悬案 —— 如果第三节讲得顺、时间还够,才回头补那一句;时间紧就跳。
⚠️ 「小模型上没出现过」这句不要滑过去。 它是这一节跟 2.6 那条判据的接点 —— 这一讲里「不能跨规模照抄」已经是第三次出现了。
⚠️ 这一节没有任何我们自己的实测,全部来自公开论文。 被追问的时候可以直说 —— 这是有意为之。
🖥 本节主屏:课件 第六节 训不崩:loss 飞了怎么办 · 主图 fig-stability
🚧 这份讲义还薄的地方
⭐ 诚实记一下,免得下次开课时把它当成成品。
- [ ] 没真讲过,时间表全是估的。第一次讲完请按实际用时回来改那张表 —— ⛔ 过期的时间表比没有时间表更糟。
- [ ] 没有课前题、也没有课后题。 这一讲其实很适合在第二节末尾问一句:「如果序列长度砍到 4K, 刚才那张排序表会怎么变?」—— 答案就在那张图上,但要台下自己说出来。
- [ ] 第三节 20 分钟是个危险的长度。 它内部有四段(16 字节 / 谱系 / 折算系数 / 学习率), 目前没有设计任何换气点。真讲的时候大概率会在第三段掉节奏。
- [ ] 「6ND 低估五六倍」那一条还没有第三方佐证。 它是从我们自己算的 82.1% 反推的。能找到一篇实测就该补上出处, 在那之前台上必须说清它是推的。
📌 想清楚一条就从这儿划掉一条,并把结论写进对应小节。 ⛔ 别在课件里回答这些 —— 课件只呈现结论。