2、MLP的定位:MLP在Encoder和Decoder中的位置,与Attention模块的关系
好,咱们接着聊。上一章我讲了MLP模块的基本结构,说白了就是两个全连接层加个激活函数。但有个问题我一直想强调——MLP在Transformer里到底放在哪儿?它跟Attention是什么关系?
这个问题,我当年刚接触Transformer时也困惑过。看论文里的图,Encoder和Decoder都是一层叠一层的,但每个子层里到底谁先谁后,为什么这么放,很多人其实没深想。今天我就把这块掰开揉碎了讲清楚。
2.1 标准位置:Post-Norm vs Pre-Norm
先看最经典的Transformer结构。原始论文里,每个Encoder层包含两个子层:
- 多头自注意力(Multi-Head Self-Attention)
- 前馈神经网络(FFN,也就是MLP)
每个子层外面都包了一层残差连接 + 层归一化。这个设计,我习惯叫它Post-Norm结构——先做子层计算,再加残差,最后做归一化。
公式表达:
# Post-Norm 结构
x = LayerNorm(x + Attention(x))
x = LayerNorm(x + MLP(x))
Decoder那边稍微复杂一点。它有三个子层:
- 掩码多头自注意力(防止看到未来信息)
- 交叉注意力(拿Decoder的查询去查Encoder的键值对)
- MLP
你看,MLP始终是最后一个子层。这个顺序不是随便定的,我后面会解释原因。
我的经验:Post-Norm在训练深层Transformer时容易不稳定。我曾在训练一个12层的模型时,发现梯度爆炸了——后来换成Pre-Norm(先归一化再做子层计算),问题就解决了。现在很多主流模型(比如GPT系列)都用Pre-Norm。
2.2 MLP与Attention的分工:一个形象的比喻
我个人喜欢用一个比喻来解释两者的关系:
- Attention 像是通信部门——负责让不同位置的token互相交换信息。它解决的是"谁该关注谁"的问题。
- MLP 像是加工部门——每个token拿到别人传来的信息后,自己再独立地做特征变换。它解决的是"这个信息该怎么理解"的问题。
说白了,Attention做的是空间上的混合,MLP做的是特征上的变换。两者缺一不可。
为什么会这样?你想想看,如果只有Attention没有MLP,那每个token只是把别人的特征加权求和一下,自己的表达能力完全没有提升。反过来,如果只有MLP没有Attention,那每个token就变成了"闭门造车",完全不知道上下文里发生了什么。
2.3 为什么MLP要放在Attention后面?
这个问题我当年也问过自己。为什么不是先MLP再Attention?
嗯,这里有个关键点:Attention的输出是上下文信息的聚合。每个token经过Attention后,已经拿到了它需要关注的邻居信息。这时候再经过MLP,就可以对这些聚合后的信息做非线性变换和维度扩展。
我举个例子:
# 假设输入是 "I love this course"
# Attention阶段:每个词都看到了其他词
# "love" 看到了 "I"、"this"、"course"
# MLP阶段:对"love"这个位置,把聚合后的信息做深层加工
# 比如理解"love"在这里是动词,不是名词
我在项目中遇到过一种情况:有人把MLP和Attention的顺序调换了,结果模型收敛速度明显变慢。后来分析发现,先做MLP再做Attention,相当于让MLP在信息不全的情况下做决策——这就像你还没听完问题就开始回答,能答好才怪。
避坑指南:我曾经试过在Decoder的交叉注意力后面再加一个MLP,想着"多一层总比少一层好"。结果模型参数量上去了,效果反而下降了。后来才明白,MLP的位置和数量是经过精心设计的,随意添加反而会破坏信息流。
2.4 实际模型中的变体
虽然原始Transformer把MLP放在Attention后面,但后来的模型做了不少改动。我整理了一个表格:
| 模型 | MLP位置 | 特点 |
|---|---|---|
| 原始Transformer | Attention之后 | Post-Norm,经典结构 |
| GPT系列 | Attention之后 | Pre-Norm,更稳定 |
| BERT | Attention之后 | Post-Norm,但用了更大的MLP |
| MLP-Mixer | 无Attention | 完全用MLP做空间混合 |
| Switch Transformer | Attention之后 | MLP被替换为MoE层 |
你看,虽然变体很多,但MLP放在Attention后面这个基本规律,绝大多数模型都遵守。MLP-Mixer是个例外,它干脆把Attention都去掉了,用两个MLP分别做空间混合和特征变换——这个思路很有意思,但那是另一个故事了。
2.5 一个关键细节:MLP的隐藏维度
说到MLP的位置,就不得不提它的隐藏维度。原始Transformer里,MLP的中间层维度是4倍的模型维度。比如模型维度是512,那MLP中间层就是2048。
为什么是4倍?我个人的理解是:Attention输出的信息需要被"展开"到更高维空间,才能做更丰富的特征交互。就像你写文章,先收集素材(Attention),然后在一个大桌子上铺开整理(MLP的高维空间),最后再浓缩成精华输出。
我的建议:如果你在调参,MLP的隐藏维度可以从2倍到8倍之间尝试。我做过实验,4倍是个不错的起点。太小了表达能力不够,太大了容易过拟合而且显存吃不消。
2.6 总结一下
好,这一章的核心内容我帮你捋一遍:
- MLP在Encoder和Decoder中都是最后一个子层,前面是Attention(或交叉注意力)
- Attention负责信息交换,MLP负责特征变换,两者分工明确
- Post-Norm和Pre-Norm是两种常见的归一化方式,Pre-Norm在深层模型中更稳定
- MLP的隐藏维度通常是模型维度的4倍,这个比例经过实践检验
下一章我会深入MLP的内部结构,讲讲那两个全连接层到底在干什么,以及激活函数为什么选ReLU而不是别的。到时候见。