大模型训练原理(18)|梯度只是指路:真正让几百亿参数开始“学习”的,是 AdamW
2026/9/23 17:50:14 网站建设 项目流程

上一课结束以后,我们其实已经走到了一个非常微妙的位置。

模型预测:

今天天气真 → 冷

训练数据告诉它:

正确答案应该是“好”。

于是 Cross Entropy(交叉熵)算出了 Loss。

然后 Backpropagation(反向传播)一路往回算。

LM Head 有 Gradient。

MLP 有 Gradient。

Attention 有 Gradient。

W_QW_KW_V也可能有 Gradient。

甚至最前面的 Embedding,都可能收到属于自己的梯度信号。

到这里,一个很容易让人产生错觉的念头就出现了:

梯度都有了,训练是不是已经结束了?

还真没有。

因为 Gradient(梯度)解决的只是:

往哪边改。

可真正训练一个模型,还必须回答另一个问题:

到底改多少?

这两个问题看起来只差几个字,实际上隔着整个 Optimization(优化)世界。

先记住今天第一句话:

梯度只负责告诉你“哪边是下坡”,优化器负责决定“这一步到底怎么下”。

这就是我们今天要讲的东西。

SGD、Momentum、Adam、AdamW,看起来像四个算法。

但如果真的从第一性原理往下推,你会发现:

它们不是四个孤立的名词。

而是一条非常自然的进化路线。

前一个方案暴露一个问题。

下一个方案来补这个洞。

继续暴露问题。

再继续修。

学会这条推导链以后,你基本不需要死背 AdamW 的公式。

把整条优化器演化路线压缩成一眼能看懂的关系:

SGDMomentumAdamAdamW
看当前梯度加入方向历史再加入尺度历史解耦 Weight Decay

一、先别想几百亿参数,我们把整个大模型压缩成一个数字

假设现在模型只有一个 Parameter(参数):

θ

当前:

θ = 2

经过前向传播、Loss、反向传播以后,我们算出:

∂L / ∂θ = 0.3

上一课已经知道,这个0.3并不是在说:

“参数错了 0.3。”

它真正表达的是:

站在当前这个位置附近,如果 θ 往增大的方向移动,Loss 倾向于上升。

那我们想让 Loss 下降怎么办?

当然应该反方向走。

所以最自然的更新:

θ_new = θ_old − η · ∂L / ∂θ

这里出现了一个以后几乎会贯穿整个训练过程的符号:

η

Learning Rate。

中文叫:

学习率。

假设:

η = 0.1

那么:

θ_new = 2 − 0.1 × 0.3 = 1.97

就这么一下。

参数从:

2

变成:

1.97

训练真正发生了。

注意这里特别容易被忽略的一件事:

Gradient 是:

0.3

但 Parameter 并没有直接:

2 → 1.7

而是:

2 → 1.97

为什么?

因为:

Gradient ≠ Parameter Update

Gradient 是坡度。

Learning Rate 是步幅。

所以第一层关系一定分清:

梯度决定方向,学习率决定你敢走多大一步。


二、Optimizer 到底是什么?把它从“神秘算法”还原成一句人话

很多人第一次接触 Optimizer(优化器),容易觉得它非常玄学。

Adam。

AdamW。

Momentum。

名字一个比一个像论文黑话。

其实站在最底层看:

Optimizer 干的事情非常朴素。

它拿到:

当前 Parameter。

当前 Gradient。

以及自己保存的一些历史状态。

然后计算:

Δθ

最后执行:

θₜ₊₁ = θₜ + Δθ

仅此而已。

它不知道什么叫中文。

不知道什么叫 Attention。

也不知道模型刚刚是在预测天气,还是在写 Python。

它甚至不知道自己正在训练一个 Large Language Model。

对 Optimizer 来说:

W_Q

和:

MLP Weight

本质上都是 Tensor。

它真正做的是:

把 Gradient 翻译成 Parameter Update。

这也是今天非常重要的一句话:

Loss 决定“错得多严重”,Gradient 决定“往哪里改”,Optimizer 决定“具体怎么改”。


三、如果 Gradient 已经有方向,最简单的方法当然是直接走

最朴素的更新就是:

θₜ₊₁ = θₜ − ηgₜ

其中:

gₜ = ∇θ Lₜ

这就是 Gradient Descent:

梯度下降。

如果每一次更新都使用完整训练集计算 Gradient,我们可以把它理解成普通 Gradient Descent。

但大模型训练显然不可能这么干。

想象一下。

如果你的预训练数据有:

几万亿 Token。

每修改一次 Parameter 之前,都要求:

“先把几万亿 Token 全跑一遍,算出整个 Dataset 的精确 Gradient。”

训练基本不用做了。

所以真实训练会把数据切成一个个:

Batch。

甚至是更小的:

Micro Batch(微批次)。

当前这个 Batch 计算一个 Loss:

L_B

然后得到:

gₜ = ∇θ L_B

用这个 Gradient 更新 Parameter。

下一批再重新算。

这就是为什么我们经常看到:

SGD。

Stochastic Gradient Descent。

随机梯度下降。

这里的“随机”不是:

Optimizer 随便猜方向。

而是:

每一次更新看到的只是整个训练数据的一部分。

这一点一旦理解,下面所有问题就自然出来了。


四、麻烦来了:一个 Batch 说往左,下一个 Batch 可能叫你往右

假设某个 Parameter 连续收到四次 Gradient:

第一次:

+0.8+0.8

第二次:

+0.7+0.7

第三次:

+0.9+0.9

第四次突然:

−0.1-0.1

如果使用最朴素的 SGD:

前三步一直往一个方向走。

第四步看到:

−0.1-0.1

马上掉头。

这里就出现了一个特别值得想的问题:

前三批都说:

往这边。

第四批只是轻轻说了一句:

好像应该反过来一点。

你真的应该立刻掉头吗?

不一定。

因为当前 Batch 给出的 Gradient 并不是“宇宙真理”。

它只是:

这一批数据的意见。

换一批样本,意见就可能发生变化。

换句话说:

Mini-Batch Gradient 天生带 Noise:

噪声。

于是最朴素 SGD 的第一个问题出现了:

它太健忘。

每一步都像刚出生一样。

只看现在。

不看过去。

这就很奇怪了。

如果过去连续十步都在告诉你:

“这个方向是对的。”

为什么第十一步来了一点小波动,你就立刻把前面的历史全部推翻?

于是,人们给 Optimizer 加了第一种“记忆”。

Momentum。


五、Momentum:别让优化器每走一步都失忆

Momentum:

动量。

名字其实取得特别好。

想象一个球正在山坡上滚。

如果它已经连续往东滚了很长一段距离,突然撞上一颗很小的石头。

它不会瞬间掉头往西飞。

因为它有:

Inertia。

惯性。

优化也是一样。

我们不希望 Parameter Update 只取决于:

“当前 Batch 刚刚说了什么。”

我们还希望它参考:

“最近很多 Batch 一直在说什么。”

于是可以维护一个历史状态:

mₜ = βmₜ₋₁ + (1 − β)gₜ

然后:

θₜ₊₁ = θₜ − ηmₜ

不要急着背公式。

先看:

mₜ

和:

gₜ

有什么区别。

g_t

这一轮 Gradient。

m_t

最近一段时间 Gradient 的平滑趋势。

这就是 Momentum。

它第一次让 Optimizer 拥有了:

历史。


六、Momentum 最厉害的地方,不是“更快”,而是能压住无意义震荡

想象一个狭长山谷。

左右两侧特别陡。

真正的谷底却在前方。

如果你每一步完全按照当前 Gradient 走,很可能出现:

左。

右。

左。

右。

左。

右。

一边向前。

一边疯狂横跳。

为什么?

因为左右方向很陡。

只要稍微偏一点,Gradient 就会猛烈把你往另一边推。

于是很多计算都消耗在:

来回震荡。

Momentum 会发生什么?

如果某个方向:

这一轮向左。

下一轮向右。

再下一轮又向左。

长期来看:

互相抵消。

反过来,如果另一个方向:

连续十几步都指向前方。

它就会不断积累。

于是:

不稳定方向被削弱。

长期一致方向被强化。

这时候再看 Momentum,就不应该只记:

“它可以加速 SGD。”

更值得记住的是:

当前 Gradient 是现场投票,Momentum 开始统计长期民意。

这句话基本就是 Momentum 的灵魂。


七、可 Momentum 只解决了“方向”,还没解决“尺度”

现在模型稍微聪明了一点。

它知道:

“不能只看这一批,要看看前面很多批是不是都支持这个方向。”

可马上又会碰到第二个问题。

假设模型只有两个 Parameter:

θ₁

和:

θ₂

它们长期 Gradient 大概分别是:

g₁ ≈ 100

和:

g₂ ≈ 0.001

两者差了:

十万倍。

如果统一用:

η = 0.001

那么粗略来看:

第一个 Parameter:

Δθ₁ ≈ 0.1

第二个 Parameter:

Δθ₂ ≈ 0.000001

一个迈大步。

一个几乎没动。

问题就来了:

几十亿个 Parameter,凭什么必须拿同一把尺子解释 Gradient?

不同 Parameter:

所在层不同。

承担功能不同。

Gradient 的典型 Scale(尺度)也可能完全不同。

能不能让 Optimizer 自己学会判断:

对这个 Parameter 来说,

当前的 Gradient 到底算大,

还是算小?

这就是 Adaptive Learning Rate:

自适应学习率

真正想解决的问题。

而这条路线最后把我们带到了:

Adam。


八、第一次学 Adam,千万别从公式开始

Adam:

Adaptive Moment Estimation。

翻译过来:

自适应矩估计。

看到“矩”这个字,很多人已经开始感觉:

高数要来了。

其实如果只是理解 Adam 的工作原理,你先不用管严格概率统计定义。

把 Adam 想成:

每个 Parameter 旁边放了两本账。

第一本账记录:

最近大家总体让我往哪边走。

第二本账记录:

我这里的 Gradient 平时到底有多大。

就这两件事。

只要把这两本账看懂,Adam 已经懂了七成。


九、第一本账:最近到底一直在往哪走?

Adam 会维护:

mₜ = β₁mₜ₋₁ + (1 − β₁)gₜ

这其实和刚才的 Momentum 非常接近。

它追踪的是:

First Moment。

一阶矩。

在这里可以先粗略理解为:

Gradient 的平滑平均方向。

假设最近几步:

0.50.5 0.60.6 0.40.4 0.70.7

虽然每一批具体数字不同,

但总体趋势非常明显:

都是正。

那:

mₜ

就会告诉 Optimizer:

这个 Parameter 最近长期看,Gradient 偏正。

于是更新应该长期倾向于:

负方向。

所以 Adam 第一只眼睛看的是:

方向。


十、第二本账:这个 Parameter 平时的 Gradient 有多大?

Adam 还会维护:

vₜ = β₂vₜ₋₁ + (1 − β₂)gₜ²

这里最关键的是:

gₜ²

为什么平方?

因为:

(+10)2=100(+10)^2=100 (−10)2=100(-10)^2=100

方向没了。

留下的是:

Magnitude。

大小。

所以:

vₜ

可以先理解成:

这个 Parameter 最近 Gradient 的典型平方尺度。

于是 Adam 第二只眼睛回答的是:

这里平时的坡到底有多陡?

现在两本账就齐了。

第一本:

最近往哪走。

第二本:

这里的 Gradient 平时有多大。

Adam 真正有意思的地方,就从这里开始。


十一、Adam 并不只问“Gradient 大不大”

它还会问一句更聪明的问题:

这个 Gradient 对你来说算不算大?

假设:

Parameter A

长期 Gradient 都在:

10

附近。

今天来了一个:

12

Parameter B

长期 Gradient 都在:

0.01

附近。

今天来了一个:

0.03

如果只看绝对值:

12 比 0.03 大了不知道多少。

可如果看相对于自己历史的变化:

A:

10 → 12。

B:

0.01 → 0.03。

B 今天的 Gradient 相对自己的正常水平,反而变化得更明显。

Adam 就是在试图捕捉这种东西。

它最终的核心更新形式:

θₜ₊₁ = θₜ − η · m̂ₜ / (√v̂ₜ + ε)

第一次看到这个公式,不要去盯:

帽子。

平方根。

epsilon。

先把它压缩成一句话:

历史方向 / 历史尺度

Adam 会根据这个 Parameter 自己过去的 Gradient Scale,对当前更新进行重新缩放。

这叫:

Adaptive Scaling。

自适应缩放。

所以一个很值得记住的理解是:

SGD 看 Gradient 有多大;Adam 还会问,这个 Gradient 相对于你自己的历史,到底算不算大。

这就是 Adaptive。


十二、为什么公式里还要有两个“帽子”?

Adam 里经常看到:

m̂ₜ = mₜ / (1 − β₁ᵗ)

以及:

v̂ₜ = vₜ / (1 − β₂ᵗ)

这叫:

Bias Correction。

偏差修正。

为什么需要?

因为 Adam 的两本账刚开始时都是:

m₀ = 0,v₀ = 0

可问题是:

刚开始根本没有历史。

你只是人为把历史初始化成了:

0。

例如:

β₁ = 0.9

第一步:

m₁ = 0.9 × 0 + 0.1g₁ = 0.1g₁

看到了吗?

Gradient 明明是:

g₁

结果历史统计只有:

0.1g₁

并不是 Gradient 突然变小了。

而是:

你的历史账本刚开张。

所以 Bias Correction 本质是在修正:

初始值为 0 带来的早期低估。

如果一定要用人话说:

新店刚开张时,不能因为“过去没有客人”,就说这家店历史平均客流特别低。

这就是帽子。

没有想象中神秘。


十三、现在把 SGD、Momentum、Adam 摆在一起,事情已经非常清楚了

SGD:

我看当前 Gradient。

Momentum:

我不只看现在,我还记得过去很多步大概往哪走。

Adam:

除了过去的方向,我还记住这个 Parameter 的 Gradient 平时是什么尺度。

所以它们的演化并不是:

算法越来越花哨。

而是 Optimizer 获得的信息越来越多。

SGD:

Current Gradient。

Momentum:

Current Gradient + Direction History。

Adam:

Current Gradient + Direction History + Scale History。

这也是为什么我不建议死背 Adam。

一旦把问题链理解了,它的设计几乎是顺着逻辑自己长出来的。


十四、可事情到 Adam 还没结束

Adam 已经很好用了。

为什么现代 Transformer Training Recipe 中又经常出现:

AdamW?

那个 W:

Weight Decay。

权重衰减。

到底又出了什么问题?

我们先不碰 Adam。

先理解 Weight Decay 本身。

假设一个 Parameter:

θ = 10

除了正常 Gradient Update 以外,我们额外希望它每一步稍微往:

0

收一点。

最直观可以写成:

θ ← (1 − ηλ)θ

其中:

λ

控制衰减强度。

例如只是非常轻微地:

10

变成:

9.999。

再变:

9.998。

不是把 Parameter 清零。

而是持续给它一点:

向 0 收缩的压力。

这就是 Weight Decay 最直观的理解。


十五、为什么要让 Parameter 稍微往 0 收?

这里别把它说成玄学。

Training Loss 只关心:

怎样把当前训练目标做得更好。

理论上 Parameter 可以通过各种数值组合去降低 Loss。

Weight Decay 相当于再增加一个偏好:

在完成任务的同时,不要毫无代价地让 Parameter Scale 一路膨胀。

所以 Weight Decay 经常被放在:

Regularization。

正则化

的语境下理解。

但是一定要严谨。

用了 Weight Decay:

不代表一定不会 Overfitting(过拟合)。

也不代表参数越小越好。

Data。

Architecture。

Training Duration。

Learning Rate。

Scale。

Objective。

这些东西都会影响最终结果。

Weight Decay 只是 Training Recipe 中的一环。


十六、AdamW 真正难懂的地方来了:Weight Decay 为什么不能直接塞进 Adam?

以前学习机器学习,经常会看到:

L2 Regularization

和:

Weight Decay

放在一起说。

在普通 SGD 中,它们确实可以出现非常漂亮的等价形式。

假设我们给 Loss 加一个 L2 项:

L′ = L + (λ/2)‖θ‖²

对 Parameter 求导:

∇θL′ = ∇θL + λθ

SGD 更新:

θ ← θ − η(∇L + λθ)

拆开:

θ ← (1 − ηλ)θ − η∇L

非常漂亮。

一部分:

正常 Gradient Update。

另一部分:

Parameter 往 0 收缩。

所以普通 SGD 里,把 L2 Regularization 和 Weight Decay 联系起来理解,问题不大。

可 Adam 不一样。

别忘了 Adam 最大的特点是什么:

它会根据 Gradient 历史做 Adaptive Scaling。

问题就出在这里。


十七、如果把 Weight Decay 塞进 Gradient,会发生一件很奇怪的事

假设我们直接写:

g′ = g + λθ

然后把整个:

g′g'

交给 Adam。

Adam 并不知道:

前面那一部分:

来自真正 Task Loss。

后面:

λθ

是我们人为加进去的 Parameter Shrink。

它只看见:

Gradient。

于是:

λθ

同样会被放进:

First Moment。

Second Moment。

平方。

平滑。

Adaptive Scaling。

这就有一点奇怪了。

我们原本只想:

让 Parameter 每一步独立往 0 收一点。

可现在这股收缩力量也被 Adam 按照 Gradient 的历史尺度重新加工了一遍。

也就是说:

Adaptive Gradient Update

和:

Weight Decay

被耦合在一起了。

这正是 AdamW 要处理的问题。


十八、AdamW 最值钱的地方,其实只有两个字:拆开

AdamW 一个非常核心的思想:

Decoupled Weight Decay。

解耦权重衰减。

翻译成人话:

Gradient Update:

你算你的。

Weight Decay:

我做我的。

别搅在一起。

粗略写成:

θ ← θ − η · m̂ₜ/(√v̂ₜ + ε) − ηλθ

前半部分:

Adam 根据 Gradient History 得到的 Adaptive Update。

后半部分:

独立的 Weight Decay。

Weight Decay 不需要先假装成 Gradient,再跟着 Adam 的 Moment Estimation 一起走一遍。

这就是 AdamW 那个 W 真正重要的地方。

所以以后别人再问:

Adam 和 AdamW 最大区别是什么?

不要只回答:

“AdamW 加了 Weight Decay。”

这个说法太粗。

更准确地说:

AdamW 把 Weight Decay 从 Adam 的自适应 Gradient 更新中解耦了。

这才是重点。


十九、到这里还有一个比 AdamW 更重要的旋钮:Learning Rate

其实 SGD、Momentum、Adam、AdamW 讨论这么久,有一个东西一直没离开:

η

Learning Rate。

你可以有非常准确的 Gradient。

也可以有非常优秀的 Adam Moment Estimate。

但如果 Learning Rate 设置得离谱:

训练照样会崩。

Learning Rate 太小:

每一步方向虽然正确。

但像蚂蚁一样挪。

Training Budget 用完了,

可能还没走到足够好的区域。

Learning Rate 太大:

一步跨出去太远。

好不容易找到一个低 Loss 区域,

直接从这一边跨到另一边。

下一步 Gradient 又把你往回推。

于是:

来回震荡。

再严重一点:

Loss Spike。

NaN。

Training Divergence。

训练直接炸掉。

所以这里有一句特别适合记住:

方向正确,不代表步子可以随便迈。

Gradient 决定哪边低。

Learning Rate 控制你一脚能跨多远。


二十、这时候 Warmup 就一点都不神秘了

很多 Transformer Training Recipe 里会看到:

Warmup。

学习率预热。

例如最终计划使用:

3 × 10⁻⁴

但训练刚开始的时候,并不直接上:

3 × 10⁻⁴

而是从更小的值开始。

慢慢增加。

最后到 Peak Learning Rate(峰值学习率)。

为什么?

不是:

“GPU 需要热身。”

真正原因还是 Optimization Stability:

优化稳定性。

训练刚开始:

Parameter 刚刚进入学习状态。

Adam 的:

mₜ

和:

vₜ

也刚开始积累。

网络内部各种 Representation 还没有形成稳定结构。

这个时候如果上来就:

“全油门!”

很容易前几步就给 Parameter 造成过大的扰动。

所以 Warmup 的思想很简单:

刚起步的时候,先小心走。

这里有一句特别值得留下:

Warmup 不是因为刚开始没有方向,而是因为刚开始还没有足够理由相信这个方向。


二十一、那为什么训练后期 Learning Rate 又会慢慢下降?

前面小心。

中间加速。

后面又减速。

为什么?

因为训练早期:

Parameter 可能离比较好的区域非常远。

这时候:

步子太小反而浪费时间。

所以允许更大的 Learning Rate:

赶路。

训练后期:

Parameter 已经进入一个相对不错的区域。

这时候如果还一脚跨特别远:

很容易在附近来回震荡。

于是 Learning Rate 通常开始下降。

这就是:

Learning Rate Schedule。

学习率调度。

例如:

Linear Decay。

Cosine Decay。

具体曲线以后再细讲。

现在只需要理解背后的直觉:

训练前期解决“去哪”,训练后期解决“怎么停得更准”。

或者更生活化一点:

Warmup 是刚起步别猛踩油门,Decay 是快到终点记得开始刹车。


二十二、如果某一次 Gradient 突然特别离谱怎么办?

这时候又会看到一个常见训练词:

Gradient Clipping。

梯度裁剪。

正常情况下:

Gradient Norm(梯度范数)

可能一直在一个相对稳定的范围。

结果某一个 Batch 突然来了一次特别大的 Gradient。

如果 Optimizer 完全照单全收:

Parameter 可能一下被推得非常远。

所以我们可以规定:

如果 Gradient Norm 超过某个阈值,

就按比例缩小。

注意。

Gradient Clipping 并不是在说:

“这次 Backward 算错了。”

它真正表达的是:

即使数学上得到这个 Gradient,我也不允许单个 Training Step 拥有把整个模型掀翻的权力。

你会发现真实训练已经越来越像一个控制系统。

Gradient:

提出修改意见。

Momentum:

参考长期趋势。

Adam:

参考历史尺度。

Learning Rate:

控制步幅。

Warmup:

控制开局风险。

Gradient Clipping:

防止极端冲击。

Weight Decay:

控制 Parameter Scale。

所以真正的大模型优化绝对不是一句:

“算梯度,然后更新参数。”

它是一整套:

把 noisy Gradient 安全转换成 Parameter Update 的机制。


二十三、学到这里,回头看optimizer.step()就完全不一样了

很多人第一次写 PyTorch:

optimizer.zero_grad() loss.backward() optimizer.step()

点击并拖拽以移动

写几十次以后,就感觉这几行代码天生应该长这样。

现在再看:

意义已经完全不同。

optimizer.zero_grad()

把上一轮 Gradient 清掉。

因为 PyTorch Gradient 默认可以累积。

loss.backward()

做的是 Backpropagation。

计算:

∇θL

注意:

这里还没有真正更新 Parameter。

真正动 Parameter 的是:

optimizer.step()

如果 Optimizer 是 AdamW,它内部会做很多事情。

读取当前 Gradient。

更新:

First Moment。

更新:

Second Moment。

做 Bias Correction。

进行 Adaptive Scaling。

结合当前 Learning Rate。

执行 Decoupled Weight Decay。

最后:

Parameter 真正发生变化。

所以:

loss.backward()

和:

optimizer.step()

完全不是一回事。

前者:

算怎么改。

后者:

真的改。


二十四、还有一个很现实的问题:Adam 的两本账不是免费的

现在假设模型有:

几十亿 Parameter。

Adam 给很多 Parameter 都要维护:

mₜ

以及:

vₜ

Parameter 本身已经占显存。

Gradient 也要占。

现在又多了两份 Optimizer State(优化器状态)。

还没算:

Activation(激活值)。

Backward 中间状态。

Temporary Buffer。

分布式训练通信 Buffer。

所以你以后再看到一句:

“这个模型权重只有 20GB,24GB 显卡应该可以 Full Training 吧?”

应该马上警觉。

推理和训练完全不是同一份显存账。

推理的时候:

主要是在运行 Parameter。

训练的时候:

你不只是在运行模型。

你还要:

保存现场。

保存 Gradient。

保存 Optimizer History。

准备 Backward。

再真正更新 Parameter。

这里可以记一句:

推理是把模型跑起来,训练是把模型跑起来之后,还要把“它为什么得到这个结果”完整追一遍,再保存下一步怎么改的历史。

这就是为什么 Training Memory 往往比单纯权重体积复杂得多。

以后讲:

ZeRO。

FSDP。

Optimizer State Sharding。

你会再次回到今天这里。


二十五、那么 AdamW 到底“优化”了什么?

这个问题很重要。

AdamW 并不知道:

“智能”是什么。

它不知道:

“数学能力”是什么。

不知道:

“写代码更好”是什么意思。

它甚至不知道当前 Output 是:

中文。

英文。

还是 Python。

它真正做的是:

根据当前 Training Objective 产生的 Gradient,调整 Parameter,让这个 Objective 更容易下降。

如果当前 Objective 是:

Next-Token Prediction。

那 AdamW 就在帮助降低:

Next-Token Prediction Loss。

以后到了 SFT:

Objective 变化。

到了 DPO:

Objective 又变化。

到了 RL:

Reward 和优化机制再次变化。

Optimizer 可以还是 AdamW。

但模型正在学习的东西已经不同。

所以这里一定把三层分清:

Objective:

到底希望模型学什么。

Gradient:

当前 Parameter 往哪里变,更可能让 Objective 下降。

Optimizer:

怎样把 Gradient 真正转换成 Parameter Update。

一句话:

Optimizer 决定“怎么学”,Objective 决定“学什么”。

这句话以后到了 Post-Training 仍然非常重要。


二十六、现在把第十七课和第十八课真正接成一条完整训练链

还是那句话:

今天天气真好。

当前 Prefix:

今天天气真

模型 Forward。

经过:

Embedding。

Transformer。

Attention。

MLP。

Residual。

RMSNorm。

LM Head。

最后得到 Vocabulary Logits。

Softmax 以后假设:

“冷”:52.5%

“好”:23.6%

“热”:9.6%

……

Training Target:

好。

于是:

L = −log(0.236)

大约:

1.441.44

Cross Entropy 告诉模型:

正确 Token 获得的 Probability 太低。

Backward 开始。

Gradient 沿着:

Logits

→ LM Head

→ Final Hidden State

→ Transformer Block

→ MLP

→ Attention

→ Q/K/V

→ 前一层 Transformer

→ …

一路向回。

于是各种参与当前有效路径的可训练 Parameter 获得:

∇θL

到这里,是第十七课。

然后第十八课开始。

AdamW 接过这些 Gradient。

对于某一个 Parameter,它会结合:

当前 Gradient。

历史 First Moment。

历史 Second Moment。

Bias Correction。

Learning Rate。

Weight Decay。

计算真正的 Parameter Update。

最终:

θₜ → θₜ₊₁

注意这一刻。

模型才真正改变。

下一次遇到类似 Context:

它已经不是刚才那一台模型。

也许:

P(好)

从:

23.6%

变成:

23.61%。

非常小。

甚至下一个 Batch 来了以后,它可能又变成:

23.59%。

看起来不像“学习”。

可真实 Pretraining 从来不是靠一个 Batch 完成的。

而是:

无数 Sequence。

无数 Token。

无数 Batch。

无数 Gradient。

无数 Parameter Update。

长期拉扯。

慢慢累积。


二十七、这其实是大模型训练最反直觉、也最迷人的地方

我们最后看到的大模型可能会:

写代码。

做数学。

翻译语言。

总结论文。

理解上下文。

甚至完成复杂推理。

可你如果把训练过程一帧一帧扒开,会发现:

根本没有哪一个 Training Step 在做:

“写入数学能力。”

没有:

“安装编程模块。”

也没有:

“保存一条知识。”

每一步看到的只有:

θₜ → θₜ₊₁

一堆浮点数:

稍微变了一点。

然后下一批。

又稍微变一点。

再下一批。

继续变。

所以我特别喜欢这样理解大模型训练:

单独看任何一次 Parameter Update,都笨得惊人;真正不可思议的是,足够多这种微小、机械、局部的修正叠加以后,竟然能长出复杂能力。

所谓 Learning,

并不存在一个神奇瞬间。

更多时候只是:

比上一秒好一点点。

然后把这个“一点点”,重复到不可思议的次数。


二十八、最后,别背 AdamW,把这条“问题链”带走

如果过两天你忘记:

β₁

是多少。

忘记:

β₂

是多少。

甚至忘记 Bias Correction 的完整公式。

都没关系。

真正应该留下的是下面这条推导。

第一步。

Gradient 已经有了。

最自然的想法:

沿反方向走。

于是:

SGD。

第二步。

发现 Mini-Batch Gradient 有 Noise。

当前一步不能完全代表长期方向。

于是:

记住历史趋势。

Momentum 出现。

第三步。

发现不同 Parameter 的 Gradient Scale 相差巨大。

不能只看绝对 Gradient。

于是:

给不同 Parameter 自己维护历史尺度。

Adam 出现。

第四步。

又发现 Weight Decay 如果直接塞进 Adam Gradient,也会被 Adaptive Scaling。

可我们本来只想单独对 Parameter 做收缩。

于是:

把两件事拆开。

AdamW 出现。

再往外:

步子太大怎么办?

Learning Rate。

刚开始训练不稳定怎么办?

Warmup。

后期需要精调怎么办?

Learning Rate Decay。

偶尔 Gradient 突然异常怎么办?

Gradient Clipping。

到这里你会发现:

这些概念根本不是散的。

它们都在回答同一个问题:

一个 noisy、局部、只代表当前 Batch 的 Gradient,到底应该怎样安全地变成真正的 Parameter Update?

这就是 Optimization。


二十九、如果只允许带走三句话

第一句:

Gradient 只是坡度,不是参数更新量。

第二句:

Adam 的核心不是公式复杂,而是同时记住“最近往哪走”和“这里的 Gradient 平时有多大”。

第三句:

AdamW 真正的 W,不是简单“多了 Weight Decay”,而是把 Weight Decay 从 Adam 的自适应 Gradient 更新里解耦出来。

如果这三句话你真的理解了,

以后再看任何训练代码里的:

AdamW。

Learning Rate。

Warmup。

Scheduler。

Weight Decay。

Gradient Clipping。

就不会再觉得是一堆神秘配置。

它们其实都在管理同一件事:

模型这一步,到底该怎么改。


三十、下一课,我们终于要把镜头拉远了

到现在为止,我们一直盯着一件很微观的事情:

一个 Token 错了以后,

Loss 怎么出来。

Gradient 怎么出来。

Parameter 又怎么被 Optimizer 更新。

也就是说:

我们终于把:

Data → Prediction → Loss → Gradient → Optimizer → Parameter Update

这条最底层训练闭环真正走通了。

但接下来,一个更大的问题马上出现:

既然模型就是这样一点点学,

那为什么过去几年整个行业几乎都在疯狂扩大:

Parameters。

Data。

Compute。

100M。

1B。

10B。

100B。

甚至更大的模型规模。

难道:

参数越多,就一定越聪明?

如果模型扩大 10 倍,

数据不变,

会怎么样?

如果数据增加 10 倍,

模型却太小,

又会怎么样?

如果今天突然多给你 10 倍 GPU,

究竟应该:

训练更大的模型,

还是:

让同一个模型看更多 Token?

这些问题最后把现代大模型带向了一个非常重要的概念:

Scaling Law。

缩放定律。

下一课,我们不急着背任何 Scaling 公式。

我们先回答一个更根本的问题:

大模型训练原理(19)|同样都是烧 GPU,为什么有的人把模型做大,有的人却选择让模型多读书?

因为大模型真正的 Scaling,从来不是一句:

“参数越多越强。”

它真正研究的是:

Parameters、Data、Compute 三种资源,到底应该怎样交换,才能把每一份算力变成尽可能多的能力。

这会是我们第一次从:

“一个 Parameter 怎么学”

走向:

“一个 Frontier Model 为什么要被训练成今天这个规模”。

而从这里开始,大模型训练会正式进入另一个世界。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询