大模型训练原理(14)|Attention 已经把信息找回来了,Transformer 为什么还要塞一个巨大的 MLP?
上一课,我们终于把 Multi-Head Attention(多头注意力)这件事拆明白了。
一个 Token 不再只能用一套 Attention Distribution(注意力分布)去理解上下文。
不同 Head(注意力头)可以拥有不同的 Q、K、V Projection(投影),在不同 Representation Subspace(表示子空间)里形成不同的信息路由。
有人负责看近处。
有人可能捕捉长距离关系。
有人关注结构。
也可能有一些 Head 学到我们根本无法用人类语言准确命名的 Pattern(模式)。
最后:
多个 Head 的结果拼接起来,再经过 (W_O) 融合,得到一个新的 Token Representation(Token 表示)。
于是上一课我们得到了一句话:
Attention 的本质,是 Contextual Information Routing——上下文信息路由。
但第十三课最后,我故意没有让这个故事结束。
因为一个更奇怪的问题马上就出现了:
信息都已经找回来了,然后呢?
Attention 可以告诉当前 Token:
“你应该去看谁。”
也可以告诉它:
“从谁那里拿多少信息。”
但它有没有真正回答另一个问题:
这些信息拿回来以后,你自己到底要怎么加工?
没有。
这就是第十四课真正要填上的那块拼图。上一课原文也正好停在“Attention 主要解决 Token Mixing,而当前 Token 内部的 Feature 如何继续加工”这个问题上。
所以今天,我们不从 FFN 公式开始。
先从一个非常现实的问题开始。
一、开完会,不代表问题已经解决了
假设你是公司负责人。
今天出了一个严重的问题。
你把几个部门的人全叫过来开会。
技术负责人告诉你:
服务器快扛不住了。
财务负责人告诉你:
预算只剩 200 万。
销售负责人告诉你:
最大客户要求下个月必须上线。
法务负责人告诉你:
合同里还有几个风险条款没有解决。
现在你已经获得了大量信息。
但问题解决了吗?
当然没有。
你现在只是完成了:
Information Gathering
信息收集。
接下来真正困难的是:
服务器到底扩不扩?
预算应该优先投在哪里?
客户的上线时间能不能答应?
技术风险、商业风险、法律风险应该怎么权衡?
这些事情已经不是:
“再去找谁问一句”。
而是:
把已经拿到的信息重新组合、筛选、判断,最后形成一个新的结论。
这其实就是 Attention 和 MLP 最直观的区别。
Attention 更像:
把相关的人叫进会议室。
MLP 更像:
会议结束以后,真正坐下来消化这些信息。
所以今天第一句话,我希望你先记住:
找到信息,不等于处理信息。
再进一步:
Attention 主要解决“信息从哪里来”,MLP 主要解决“信息来了以后怎么变”。
只要这句话真正理解,后面 FFN、GELU、SwiGLU 就已经成功一半了。
二、Attention 真正擅长的,其实一直都是 Token 和 Token 之间的关系
继续看上一课的例子:
小明把苹果递给小红,因为她饿了。
现在模型正在处理:
“她”。
经过 Multi-Head Attention 以后,“她”可能已经拿回了很多上下文信息。
某个 Head:
重点关注“小红”。
另一个 Head:
可能捕捉“苹果”和“饿”之间的语义联系。
还有一个 Head:
可能更关注“因为”前后的逻辑关系。
所以现在的“她”,已经和最开始进入模型的时候完全不同。
最开始:
它只是一个 Token Representation。
经过 Attention:
它变成了:
Contextualized Representation
上下文化表示。
换句话说:
原来的“她”只是:
“我是‘她’这个 Token。”
现在的“她”已经知道:
“前面出现过小红。”
“这里有苹果。”
“这是一个因果句。”
“我和前文某些实体存在关系。”
问题来了。
这些 Feature(特征)现在已经进来了。
那它们接下来应该怎么组合?
哪些应该增强?
哪些应该削弱?
某几个 Feature 同时出现的时候,能不能产生一种新的内部表示?
这件事,Attention 本身并没有完整解决。
因为 Attention 最强的地方,是:
Routing
信息路由。
它特别擅长回答:
我应该从哪里拿信息?
而 Transformer 还需要另外一种能力:
Transformation
表示变换。
也就是:
我拿到这些信息以后,要把自己变成什么?
所以可以再记一句:
Attention 解决的是“找谁”,MLP 解决的是“找到以后怎么办”。
三、如果你开始看 Tensor Shape,这两个模块的分工会突然变得特别清楚
假设我们现在有:
N=3
也就是:
3 个 Token。
每个 Token 的 Hidden Size(隐藏维度)是:
dmodel=8
那么输入:
X∈ℝ3×8
翻译成人话:
3 个 Token。
每个 Token 有 8 个 Feature。
你可以想象成:
| Token | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 |
|---|---|---|---|---|---|---|---|---|
| Token 1 | · | · | · | · | · | · | · | · |
| Token 2 | · | · | · | · | · | · | · | · |
| Token 3 | · | · | · | · | · | · | · | · |
现在其实存在两个完全不同的问题。
第一个:
Token 1 应该从 Token 2、Token 3 拿什么?
这就是 Attention 更关心的问题。
所以 Attention 可以粗略理解成:
Token Mixing
Token 之间的信息混合。
它主要解决:
不同 Position(位置)之间怎么交换信息。
但还有另一个问题。
假设 Token 1 已经把其他 Token 的信息拿回来了。
它现在内部有 8 个 Feature。
那这 8 个 Feature:
应该怎样重新组合?
哪些组合是重要的?
能不能从现有 Feature 中构造新的 Feature?
哪些 Feature 当前应该发挥更大的作用?
这就是 MLP 更关心的问题。
所以它经常可以粗略理解成:
Feature Transformation
或者:
Channel Mixing
特征维度上的变换。
于是你可以先建立一个非常好用的坐标系:
Attention:主要在 Token 之间交流。
MLP:主要在一个 Token 内部加工 Feature。
如果非要再形象一点:
Attention 让 Token 去开会,MLP 让 Token 开完会以后回工位干活。
四、MLP 有个非常反直觉的地方:每个 Token 其实是“各算各的”
这件事第一次知道的时候很容易困惑。
假设经过 Attention 后:
[ x1, x2, x3 ]T
其中:
x1,x2,x3∈ℝ8
现在进入 FFN。
第一个 Token:
y1=FFN(x1)
第二个:
y2=FFN(x2)
第三个:
y3=FFN(x3)
这里 FFN 不会重新计算:
Token 1 应该看 Token 2 多少。
也不会重新建立:
Token 2 和 Token 3 的 Attention Weight。
在 FFN 这一阶段:
每一个 Token 都独立经过同一套网络。
所以经典 Transformer 里它有一个名字:
Position-wise Feed-Forward Network
逐位置前馈网络。
这里的 Position-wise 特别重要。
意思不是:
每个位置有一套不同的 FFN。
而是:
所有位置共享同一套 FFN 参数,但每个位置独立计算。
看到这里你很可能马上产生一个问题:
等等。
既然每个 Token 自己算自己的:
那 MLP 不就没有上下文了吗?
这就是这节课非常容易卡住的地方。
答案是:
MLP 的确不会在这一阶段主动重新访问其他 Token。
但是别忘了:
它拿到的 (x_i) 是什么?
不是原始 Embedding。
而是:
Attention 处理后的 Contextualized Representation。
换句话说:
其他 Token 的信息,Attention 已经提前搬进来了。
所以 MLP 不需要再跑出去找别人。
它只需要处理:
现在已经摆在自己桌面上的信息。
这句话非常值得留下:
MLP 不需要重新寻找上下文,因为 Attention 已经把上下文送到它桌上了。
五、现在终于来看 FFN,它其实简单到有点出乎意料
经典 FFN 可以写成:
FFN(x)=W2φ(W1x+b1)+b2
第一次看可能还是觉得有点抽象。
我们直接用数字。
假设:
dmodel=8
也就是说:
一个 Token 当前是 8 维。
首先经过:
W1
假设:
W1∈ℝ8×32
于是:
8→32
原来的 8 维 Representation:
变成 32 维。
这一步可以理解为:
Up Projection
升维投影。
接着:
经过一个 Activation Function(激活函数)。
比如:
GELU。
然后:
再通过第二个矩阵:
W2∈ℝ32×8
于是:
32→8
又回来了。
这一步:
Down Projection
降维投影。
所以经典 FFN 的结构其实就是:
8 → 32 → 8
抽象以后:
dmodel → dff → dmodel
没有想象中复杂。
真正值得问的其实不是:
“公式是什么?”
而是:
为什么模型非要先把 8 维撑到 32 维,然后又压回来?
六、FFN 为什么要先变宽?因为模型需要一个更大的“临时加工车间”
假设:
dmodel=4096
每个 Token 在 Transformer 主干里都是:
4096 维。
现在我们希望模型对当前 Token 的 Feature 做更加复杂的加工。
最直接的一种办法就是:
暂时把它送进一个更宽的空间。
比如:
4096→16384
注意:
这并不是把一句话变长。
也不是增加 Token。
它扩大的是:
当前 Token 内部进行 Feature Computation 的空间。
可以想象成:
主干只有一个 4096 平方米的通道。
真正加工的时候:
临时把 Token 送进一个 16384 平方米的车间。
里面可以形成更多 Intermediate Feature(中间特征)。
加工完成以后:
再压回:
16384→4096
为什么一定要压回来?
因为下一层 Transformer 仍然希望接收统一的:
dmodel
否则:
第一层 4096。
第二层 16384。
第三层 65536。
一路膨胀下去,模型根本没法维持稳定的主干结构。
所以 FFN 实际上像:
主干宽度保持不变,但允许每一层临时进入一个更大的计算空间。
这比单纯记:
“FFN 会升维”
有用得多。
因为你终于知道:
它为什么升。
七、但真正关键的还不是“变宽”,而是中间那个看起来不起眼的激活函数
现在我们做一个思想实验。
假设 FFN 只有:
xW1
然后:
(xW1)W2
中间什么都不加。
于是:
xW1W2
由于两个矩阵可以重新组合:
W=W1W2
所以最后:
xW1W2=xW
发现问题了吗?
你表面上:
8 → 32 → 8。
折腾了一大圈。
但最终:
它依然只是一个 Linear Transformation(线性变换)。
也就是说:
如果中间没有非线性,两层 Linear 本质上仍然可以压缩成一层 Linear。
那整个巨大中间层的表达能力就会受到非常大的限制。
所以必须加入:
Non-linearity
非线性。
于是:
FFN(x)=W2φ(W1x)
里面看起来最不起眼的:
φ
反而成为关键。
这一节真正应该留下的一句话是:
Linear Layer 负责重新组合 Feature,Activation Function 负责让这种组合真正拥有复杂性。
再狠一点:
没有非线性,你堆再多 Linear Layer,本质上仍然只是在做一个更大的 Linear Layer。
八、GELU 不要再背成“Transformer 用的激活函数”
经典 Transformer 中很常见:
GELU
Gaussian Error Linear Unit
高斯误差线性单元。
这里不用背完整公式。
你真正应该知道的是:
为什么神经网络需要这种东西。
最容易理解的是先看 ReLU:
ReLU(x)=max(0,x)
如果输入小于 0:
直接变成 0。
如果大于 0:
保留。
非常像一个硬开关:
开。
或者关。
而 GELU 更平滑。
它不会简单地说:
负数全部判死刑。
而是根据输入大小:
平滑地改变这个 Feature 的输出。
所以从直觉上:
可以把 GELU 看成一种比较柔和的非线性 Feature Transformation。
注意:
GELU 本身不是后来 SwiGLU 那种显式 Gate(门控)结构。
但它已经带出了一个很重要的思想:
不是所有 Feature,在所有输入下,都应该产生同样的影响。
而继续沿着这个方向走:
现代 LLM 就越来越喜欢显式加入:
Gating
门控。
这就到了 SwiGLU。
九、为什么现在的大模型源码里经常出现 gate_proj、up_proj、down_proj?
如果你以后打开一个现代 LLM 的 MLP 源码:
经常会看到三个名字:
gate_proj
up_proj
down_proj
第一次看很容易懵。
刚才不是说:
升维一次。
降维一次。
两个矩阵吗?
怎么突然三个了?
因为现代 LLM 里常见的结构已经不只是最简单的:
Linear → GELU → Linear。
而是类似:
SwiGLU
Swish-Gated Linear Unit
可以理解为:
基于 SiLU/Swish 的门控线性单元。
别急着背名字。
我们直接拆。
输入:
x
先走一条路:
u=xWup
这条可以理解成:
Content Path
内容路径。
它负责产生一批候选 Feature。
也就是:
“我能加工出什么?”
与此同时:
输入再走另外一条路:
g=xWgate
然后经过:
SiLU(g)
这条是:
Gate Path
门控路径。
它更像在学习:
“刚才那些 Feature,这次应该放行多少?”
接下来:
h=SiLU(g)⊙ u
其中:
⊙
表示逐元素相乘。
最后:
y=hWdown
重新压回 Hidden Size。
所以整个 SwiGLU 可以粗略理解为:
SwiGLU(x)= [ SiLU(xWgate) ⊙ (xWup) ]Wdown
公式看着复杂。
翻译成人话只有一句:
一条路负责生产 Feature,另一条路负责控制这些 Feature 当前应该发挥多少作用。
瞬间就简单了。
十、SwiGLU 真正强的地方,不是“多了一个矩阵”,而是多了“选择”
假设 Up Projection 生成:
[u1,u2,u3,u4]
与此同时 Gate 产生一组控制信号。
于是当前输入下:
Feature 1:
可以被强烈保留。
Feature 2:
可以被明显压制。
Feature 3:
只通过一部分。
Feature 4:
可能几乎不起作用。
换一个 Token:
门控结果又可以完全不同。
这意味着:
同一个 MLP:
面对不同输入时,并不需要让所有内部 Feature 以同样方式发挥作用。
所以普通 FFN 更像在问:
“我能构造什么 Feature?”
门控 MLP 又多问了一层:
“这些 Feature 里面,这一次到底该让谁发挥作用?”
这就是一个非常重要的思想升级:
Conditional Computation
条件计算。
当然,现在还只是:
Feature 级别的门控。
但如果继续想一步:
假设我不是决定:
哪几个 Feature 应该打开。
而是决定:
100 个不同的 FFN 里面,这个 Token 到底应该送给哪几个?
你是不是已经开始闻到:
MoE
Mixture of Experts
混合专家模型
的味道了?
所以很多知识一旦按照因果顺序学:
根本不需要死记。
它是自己长出来的。
十一、现在你终于可以真正看懂 intermediate_size
打开很多模型的 Config:
经常会看到:
hidden_size
以及:
intermediate_size
比如假设:
hidden_size = 4096
intermediate_size = 16384
以前看到:
可能只觉得是两个配置参数。
现在再看:
hidden_size = 4096
代表:
Transformer 主干中一个 Token 的 Representation Width(表示宽度)。
而:
intermediate_size = 16384
代表:
这个 Token 进入 MLP 之后,内部临时扩展到多宽的 Feature Space。
于是:
Expansion Ratio = dffdmodel
这里:
163844096=4
也就是:
4× Expansion
四倍扩展。
但是这里千万不要从一个坑跳进另一个坑:
“懂了,大模型 FFN 都是 4 倍。”
不是。
4× 是经典 Transformer 中非常常见的设计。
但是现代 SwiGLU 等 Gated MLP(门控 MLP)经常会重新选择 Intermediate Size。
不同模型也会根据:
参数预算。
FLOPs。
Tensor Parallelism(张量并行)。
Kernel Efficiency(计算内核效率)。
训练效果。
硬件结构。
重新设计。
所以:
Expansion Ratio 从来不是“越大越聪明”的能力旋钮。
它真正代表的是:
Capacity vs Compute
表示容量和计算成本之间的架构权衡。
以后你看到一些奇怪的:
intermediate_size = 11008
或者其他并不整齐的数字,
先不要问:
“为什么不是 16384?”
更好的问题是:
这个模型到底在平衡什么参数预算和计算预算?
这已经是看模型 Config 时非常重要的思维升级。
十二、为什么说 MLP 根本不是配角?直接算一次参数你就明白了
假设:
dmodel=4096
先看经典 MHA。
Q:
4096×4096
K:
4096×4096
V:
4096×4096
Output Projection:
4096×4096
忽略 Bias(偏置),总共大约:
4×40962
也就是:
约 6710 万参数。
已经不少了。
现在再看经典 4× FFN。
假设:
dff=16384
第一层:
4096×16384
第二层:
16384×4096
所以总参数大约:
2×4096×16384
约:
1.34 亿。
也就是说:
在这个经典配置里:
FFN 的参数量,大概是 Attention 的两倍。
这时候你再看 Transformer:
就不会觉得 MLP 是:
“Attention 后面顺手接的一个小模块”。
根本不是。
它是整个模型容量非常重要的承载者。
当然,现代 GQA、MLA、SwiGLU、MoE 会改变具体比例。
所以不要把刚才的 2 倍硬套到所有模型。
这里真正应该记住的是:
Attention 是 Transformer 最出名的模块,不等于它一定拥有最多参数。
明星模块和参数大户:
完全是两个概念。
十三、这时候我们终于可以非常清楚地说:Attention 和 MLP 到底分别负责什么
Attention 更擅长:
Communication
通信。
当前 Token 应该和谁交流?
哪些位置值得读取?
从那里拿多少信息?
所以它非常强调:
Token-to-Token Interaction。
而 MLP 更擅长:
Computation / Transformation
计算与表示变换。
已经拿到的信息:
应该怎样重新组合?
怎样形成新的高阶 Feature?
哪些 Feature 应该增强?
哪些应该抑制?
当前 Token 最终应该形成怎样的新 Representation?
于是:
Attention 更像信息网络。
MLP 更像加工车间。
但这里一定注意。
这只是帮助理解的类比。
千万不要继续简化成:
“Attention 不负责计算。”
或者:
“MLP 才是模型真正思考的地方。”
这都过头了。
更加严谨的表述应该是:
Attention 主要提供内容相关的跨 Token 信息路由;MLP 主要提供逐 Token 的高容量非线性特征变换。
以后真正看论文:
建议记这一版。
十四、所以 Transformer 为什么不能一直堆 Attention?
现在回到文章最开始的问题。
既然 Attention 那么厉害:
为什么不:
Attention
↓
Attention
↓
Attention
↓
Attention
一路堆到底?
因为 Attention 最大的优势:
是动态改变 Token 之间的信息流。
但如果拿回来的 Representation:
缺乏足够强的逐 Token Non-linear Transformation(非线性变换),
模型内部 Feature 的加工能力仍然会受到限制。
所以一个 Transformer Block 才会形成这种非常有意思的交替:
Attention
↓
MLP
↓
Attention
↓
MLP
↓
Attention
↓
MLP
如果把术语暂时都拿掉:
它其实一直在重复:
Communication
交流。
↓
Computation
加工。
↓
Communication
再交流。
↓
Computation
再加工。
这让我觉得 Transformer Block 最值得记住的一句话其实不是公式。
而是:
先把信息找回来,再把信息消化掉;带着新的表示,再进入下一轮信息交换。
Attention 和 MLP:
不是竞争关系。
是分工。
十五、现在让一个 Token 真正走完整个 Transformer Block
到这里,我们终于可以把前面四课真正串起来。
一个 Token 进入 Attention。
首先计算:
Q。
K。
V。
然后:
不同 Head 使用自己的 Representation Subspace。
↓
计算:
QKT
↓
Scaling(缩放)。
↓
Causal Mask(因果掩码)。
↓
Softmax。
↓
得到 Attention Weight。
↓
乘 V。
↓
拿回上下文信息。
↓
多个 Head 拼接。
↓
经过:
WO
重新融合。
于是:
当前 Token 得到:
Contextualized Representation
上下文化表示。
接下来:
进入 MLP。
如果是现代 SwiGLU 风格:
当前 Representation
↓
up_proj
产生候选 Feature。
同时:
gate_proj
产生门控信号。
↓
SiLU。
↓
两条路径逐元素相乘。
↓
得到经过选择和加工的 Intermediate Feature。
↓
down_proj
↓
回到原来的 Hidden Size。
于是:
产生这一层新的 Token Representation。
整个故事其实可以压成:
Context Retrieval
上下文读取
↓
Feature Transformation
特征变换
也就是说:
Attention 把上下文搬进 Token,MLP 再把这些上下文加工成新的 Token 表示。
如果这一句你能真正讲明白:
这一课已经懂了八成。
十六、再从 Shape 看一次,你会理解为什么现代 LLM 出现了两条完全不同的优化路线
还是:
X∈ℝN× d
Attention 会形成类似:
N× N
的 Attention Matrix。
为什么?
因为每个 Token 都需要和其他位置发生关系。
所以 Full Attention 经典复杂度会出现:
O(N2)
当 Context 从:
4K
变成:
32K
128K
甚至 1M,
Attention 就会越来越贵。
于是后面大家开始研究:
MQA。
GQA。
MLA。
Sparse Attention。
Linear Attention。
Delta Attention。
这些技术,本质上都在重新思考:
历史信息到底应该怎样被访问。
而 MLP 面临的是另外一个问题。
它没有构造:
N× N
的 Token Relation Matrix。
每个 Token 只是执行:
d → dff → d
但是:
如果 (d_{ff}) 越来越巨大呢?
每个 Token:
都必须跑一次巨大的 Dense MLP。
于是问题变成:
我要怎样扩大模型的 Feature Capacity,却不让每个 Token 的计算成本一起爆炸?
是不是发现:
Attention 和 MLP:
分别把 Transformer 推向了两类完全不同的架构创新。
Attention 侧解决:
Memory / Routing Efficiency
信息访问效率。
MLP 侧解决:
Capacity / Computation Efficiency
容量和计算效率。
理解这个以后:
后面那些所谓“现代大模型新架构”,就不会再像一堆毫无关系的缩写。
它们都是从具体瓶颈长出来的。
十七、Dense FFN 最大的矛盾,终于暴露出来了
现在假设:
MLP 越大:
模型 Feature Capacity 越强。
那我们直接疯狂增加:
dff
不就好了?
比如:
4096→16384
觉得不够。
那就:
4096→65536
还不够?
4096→262144
参数容量当然越来越大。
但有一个问题一直没有消失:
Dense。
Dense 的意思就是:
几乎每一个 Token,都要运行这整个 FFN。
你的 FFN 有 1 亿参数:
Token A 跑。
Token B 跑。
Token C 还是跑。
现在扩大到 10 亿:
所有 Token 继续跑。
扩大到 100 亿:
还是如此。
于是 Dense Model 出现一个非常现实的矛盾:
想扩大 Capacity,就得让每个 Token 一起承担更多 Compute。
这叫:
Capacity–Compute Coupling
容量和计算被绑定在一起。
那能不能解耦?
比如:
模型一共拥有:
100 个很大的 FFN。
但当前这个 Token:
只需要其中 2 个。
下一个 Token:
可能去另外几个。
于是:
模型总参数可以非常巨大。
但真正处理一个 Token 时:
只激活其中一小部分。
你现在甚至已经不需要我说名字了。
这就是后面的:
MoE
Mixture of Experts
混合专家模型。
所以 MoE 最好的学习方式,从来不是:
“MoE 有 Router 和 Expert。”
而应该从今天这条矛盾推出来:
Dense FFN
↓
想扩大容量
↓
增加参数
↓
所有 Token 都执行
↓
Compute 一起暴涨
↓
那能不能只运行一部分参数?
↓
Sparse Computation
稀疏计算
↓
MoE
你会发现:
MoE 不是因为研究人员突然觉得“专家”这个词听起来很高级。
它是 Dense FFN 的 Capacity–Compute 矛盾被逼到一定程度以后,非常自然的一条答案。
这就是后面学习 MoE 最重要的地基。课程设计里,第十四课本身也被明确放在 MoE 之前,作为 FFN、GELU、SwiGLU 和 Expansion Ratio 的直接前置。
十八、这一课有几个特别容易被讲歪的地方,我想一次说清楚
第一个误区:
“Attention 负责理解,MLP 只是补充计算。”
不对。
它们是两类不同的变换。
Attention 更侧重跨 Token 路由。
MLP 更侧重逐 Token Feature Transformation。
第二个误区:
“MLP 每个 Token 单独计算,所以没有上下文。”
也不对。
MLP 当前这一阶段不主动读取其他 Token。
但它的输入早已经过 Attention。
上下文已经进入当前 Representation。
第三个误区:
“FFN 就是把维度放大,再缩小。”
这只描述了 Shape。
没描述能力来源。
真正关键的是:
中间加入 Non-linearity。
否则:
两层 Linear 依旧可以合并成一层 Linear。
第四个误区:
“intermediate_size 越大,模型肯定越强。”
不能这么说。
更大意味着更多 Capacity。
也通常意味着更多:
Parameters。
FLOPs。
Memory。
通信和硬件成本。
它是架构 Trade-off。
第五个误区:
“SwiGLU 就是多了一层 Linear。”
也不是。
真正重要的是:
它增加了一个输入相关的 Gate。
模型不仅学习:
“我要生成什么 Feature?”
还学习:
“这一次哪些 Feature 应该发挥作用?”
还有最后一个很常见的说法:
“知识全都存在 MLP 里。”
这也过度简化。
模型的能力是:
Embedding。
Attention Projection。
MLP。
Residual Stream。
多层组合。
训练数据和优化。
共同形成的。
MLP 的确承担了大量参数和非线性表示能力。
但不要把整个 Transformer 的知识机制简化成:
“FFN 就是数据库。”
这会让后面的理解越来越歪。
十九、这一课如果公式全忘了,我希望你至少能留下这几句话
第一句:
找到信息,不等于处理信息。
第二句:
Attention 决定信息从哪里来,MLP 决定信息来了以后怎么变。
第三句:
Attention 让 Token 去开会,MLP 让 Token 开完会以后真正消化会议内容。
第四句:
FFN 扩大的不是 Context Length,而是一个 Token 内部进行 Feature Computation 的临时空间。
第五句:
没有 Non-linearity,两层 Linear 再宽,本质上仍然可以塌缩成一个 Linear Transformation。
第六句:
SwiGLU 真正增加的不是一个矩阵,而是“内容”和“门控”两条路径:一条负责产生 Feature,一条负责决定这些 Feature 这次该发挥多少作用。
第七句:
Attention 是 Transformer 最出名的模块,不代表它就是参数最多的模块。
第八句:
Dense FFN 真正的问题不是参数不能继续做大,而是参数一旦做大,所有 Token 都要一起买单。
最后一句,也是我认为这一课真正应该刻进脑子里的:
Attention 解决“我应该知道什么”,MLP 解决“知道这些以后,我应该形成什么新的表示”。
如果这句话懂了:
以后再看 Transformer 架构图:
Attention 后面那个 MLP,
就再也不会是一个可以随便扫过去的小方块。
二十、别急着进入下一课,先检查自己到底懂没懂
现在不要往前翻。
直接试着回答。
为什么 Attention 已经读取了整个 Context:
还需要 MLP?
为什么 MLP 明明逐 Token 独立计算:
仍然可以加工 Contextual Information?
为什么 FFN 经常设计成:
dmodel → dff → dmodel
?
为什么要先升维:
再降回来?
为什么两层 Linear 中间:
必须加入 Non-linearity?
如果直接:
xW1W2
会发生什么?
hidden_size
和:
intermediate_size
到底分别是什么?
Expansion Ratio:
实际在权衡什么?
为什么现代 LLM 会出现:
gate_proj
up_proj
down_proj
?
SwiGLU 的两条路径:
到底分别在干什么?
为什么 Attention 可以粗略理解为:
Token Mixing,
而 MLP 可以粗略理解为:
Feature Transformation?
最后一个问题最重要:
假如 Dense FFN 越做越大:
为什么:
Model Capacity
和:
Per-token Compute
会越来越紧地绑在一起?
如果这个矛盾你已经能够自己讲出来:
那你学到的就不再只是:
FFN。
GELU。
SwiGLU。
几个名词。
而是已经可以自己推出:
为什么现代大模型下一步会开始研究:
Sparse Computation。
这才是我希望这门课真正训练出来的能力。
不是背架构。
而是看到一个技术以后,能够反过来问:
它到底是为了解决前一个方案的什么矛盾?
下一课:Transformer 一层层把 Representation 改下去,为什么几十层之后没有把自己“改坏”?
到今天为止:
一个 Transformer Block 的两大核心计算终于都齐了。
Attention:
负责跨 Token 信息交换。
MLP:
负责逐 Token Feature Transformation。
看起来已经完整了。
但一个新的问题马上出现。
模型不是只有一层。
可能是:
32 层。
64 层。
80 层。
甚至更深。
每一层都在:
Attention。
MLP。
然后重新修改一次 Representation。
那第一层的信息:
到了第八十层还剩多少?
如果每一层都把输入彻底变一次:
模型不会越算越乱吗?
训练的时候:
Gradient 又怎么从最后一层,一路稳定地传回第一层?
为什么 Transformer 里一定会出现一句看起来简单得有点过分的:
xl+1=xl+F(xl)
为什么一个小小的:
Residual Connection
残差连接
会成为深层 Transformer 能够训练起来的关键?
而现代大模型为什么又大量使用:
RMSNorm
均方根归一化
而不是简单把 LayerNorm 原封不动搬下去?
下一课,我们继续不背定义。
先从一个更根本的问题开始:
大模型训练原理(15)|Transformer 堆到几十层为什么还没有“失忆”?Residual 和 RMSNorm 到底在保护什么?
更多推荐

所有评论(0)