FFN 层的秘密身份:Transformer 里的知识仓库

Transformer 中三分之二的参数藏在一个看起来最”无聊”的组件里。它到底在干什么?

一个奇怪的事实

如果你打开任何一个大语言模型的参数统计,你会发现一个令人困惑的数字:大约 67% 的参数都属于 FFN(Feed-Forward Network)层。不是那个引人注目的 Attention 机制,不是精巧的位置编码,而是每一层里那个看起来最朴素的”两层全连接网络”。

这就像发现一栋摩天大楼里,三分之二的面积其实是地下室的仓库。建筑师(Attention)负责决定信息如何流动,但真正储存东西的地方,是那个不起眼的仓库。

为什么需要这么多参数?它们在存什么?如果我们能打开这个”仓库”看一眼,会发现什么?

这些问题在过去几年里催生了一系列令人兴奋的研究。答案比你想象的更有趣:FFN 层本质上是一个巨大的键值记忆系统——每个”神经元”对应一个模式匹配规则,整个 FFN 层构成了模型的”事实数据库”。

从数学开始:FFN 到底长什么样

最简单的版本

让我们先看 FFN 层的数学形式。在原始 Transformer 中,它就是一个两层的前馈网络:

\[\text{FFN}(x) = W_2 \cdot \text{ReLU}(W_1 \cdot x + b_1) + b_2\]

其中 $x$ 是某个位置的隐藏状态(维度 $d_{model}$),$W_1$ 把它从 $d_{model}$ 维扩展到 $d_{ff}$ 维(通常 $d_{ff} = 4 \times d_{model}$),ReLU 做非线性激活,然后 $W_2$ 再把它压回 $d_{model}$ 维。

用人话说:先把信息展开到一个更大的空间,在那个空间里做选择(哪些维度被激活),然后再压缩回来。

这像什么?想象你有一面巨大的开关墙,上面有数千个开关。输入的信息会点亮其中一部分开关(通过 $W_1$ 和 ReLU),然后被点亮的开关各自贡献一个”意见”($W_2$ 的对应列),最后这些意见被加在一起,形成 FFN 的输出。

参数为什么这么多

以 GPT-3 为例:$d_{model} = 12288$,$d_{ff} = 4 \times 12288 = 49152$。

  • $W_1$ 的参数量:$12288 \times 49152 \approx 6$ 亿
  • $W_2$ 的参数量:$49152 \times 12288 \approx 6$ 亿
  • 每一层 FFN:约 12 亿参数

而同一层的 Attention(QKV 投影 + 输出投影)参数量约为 $4 \times d_{model}^2 = 4 \times 12288^2 \approx 6$ 亿。

所以 FFN 的参数量是 Attention 的 两倍。96 层叠起来,FFN 占全模型参数的 2/3。这不是设计失误——这些参数有明确的用途。

核心洞见:FFN 是一个键值记忆库

Geva 的发现(2021)

2021 年,Mor Geva 等人发表了一篇改变我们理解 FFN 方式的论文:“Transformer Feed-Forward Layers Are Key-Value Memories”

他们的核心洞见极为优雅:把 FFN 的公式重新写一下——

\[\text{FFN}(x) = \sum_{i=1}^{d_{ff}} \text{ReLU}(k_i \cdot x) \cdot v_i\]

其中 $k_i$ 是 $W_1$ 的第 $i$ 行(一个”键”向量),$v_i$ 是 $W_2$ 的第 $i$ 列(一个”值”向量)。

翻译成人话:

  1. 每个”神经元” $i$ 先计算输入 $x$ 与自己的”键” $k_i$ 有多匹配(内积)
  2. 如果匹配度 > 0(通过 ReLU),就按匹配程度把自己的”值” $v_i$ 贡献出来
  3. 最终输出是所有被激活神经元的”值”的加权求和

这和数据库查询惊人地相似:输入是查询(query),$W_1$ 的每一行是一个键(key),$W_2$ 的每一列是对应的值(value)。FFN 做的事情就是:用输入去匹配所有的键,然后返回匹配到的值的加权组合。

输入 x W₁ 的行 = 键(Keys) k₁: "首都是..." k₂: "发明者..." k₃: "年份..." k₄: ... k_dff ReLU 匹配 → 激活 W₂ 的列 = 值(Values) v₁: → "巴黎" v₂: → "爱迪生" v₃: → "1969" v₄: ... v_dff 输出 Σ 加权值 FFN = 键值记忆查询:输入匹配键 → 返回对应值的加权组合

实验验证:键对应什么模式?

Geva 团队做了一个漂亮的实验:他们取出 $W_1$ 中的每一行(每个”键”),然后去找训练数据中哪些输入最能激活这个键。

结果令人惊叹:大多数键都对应着人类可解释的文本模式。比如:

  • 某个键专门对”某国的首都是”这类上下文响应
  • 某个键专门对年份数字之后的上下文响应
  • 某个键对编程语言关键字后的上下文响应

值对应什么输出?

更有趣的是值向量 $v_i$ 的含义。Geva 在后续工作(2022)中进一步发现:每个值向量在词汇空间中”推广”某个概念

具体来说,如果你把某个值向量 $v_i$ 投影到输出 embedding 空间(通过乘以 unembedding 矩阵),你会发现它对应着一组语义相关的词。例如:

  • 某个值向量强烈推广 “Paris”, “France”, “Eiffel” 这组概念
  • 另一个值向量推广 “1945”, “war”, “victory” 这组概念

翻译成人话: FFN 层的每个神经元就像一条”如果看到 X 模式,就推广 Y 概念”的规则。数万条这样的规则叠加在一起,构成了模型的知识库。

Attention 搬运,FFN 加工:分工合作

一个直觉

如果 Transformer 是一家公司,那么:

  • Attention 是信息的物流系统——它决定”哪个位置的信息应该送到哪个位置”
  • FFN 是每个工位上的专家——它接收送来的信息,从自己的知识库中查询相关内容,然后给出回应

Attention 是跨位置的操作:它让不同 token 之间交流。 FFN 是逐位置的操作:它独立处理每个位置,不看其他 token。

这个分工意味着什么?当模型处理”法国的首都是”这个 prompt 时:

  1. Attention 负责把”法国”这个关键信息传递到”是”后面的预测位置
  2. FFN 在那个位置接收到包含”法国”+”首都”的混合信息,然后从自己的记忆库中检索出”巴黎”

Meng 等人的因果追踪(2022)

Kevin Meng 等人在”Locating and Editing Factual Associations in GPT”中用一种叫因果追踪(Causal Tracing)的方法证实了这种分工。

他们的实验思路很巧妙:

  1. 给模型一个事实性问题:”The Eiffel Tower is located in the city of ___”
  2. 把输入搞乱(加噪声),模型当然答不出来了
  3. 然后逐个恢复模型各个位置、各层的激活值,看恢复哪里能让模型重新答对

结果非常清晰:恢复中间层(约第 15-25 层)的 MLP 输出,在主语 token(”Eiffel Tower”)的位置,就能恢复正确答案。这说明事实知识就存储在这些中间层的 FFN 中。

更进一步,他们发现可以通过对 FFN 权重做一个小小的秩一更新(Rank-One Model Editing, ROME),就能精确地修改单个事实——比如让模型”相信”埃菲尔铁塔在罗马而不是巴黎。这证明了知识确实以一种局部化的方式存储在 FFN 参数中。

因果追踪:知识存储在哪里? 浅层 中层 深层 The Eiffel Tower is in the city of ___ ⭐ 关键! Attn 搬运 = MLP 存储事实(中层 + 主语位置) = Attention 搬运到输出位置

知识神经元:可以精确定位的记忆

从群体到个体

Geva 的工作告诉我们 FFN 整体是记忆库,Meng 的工作告诉我们知识在中间层。但能不能更精确——定位到具体哪几个神经元存储了某个事实?

2021 年,Dai 等人在 “Knowledge Neurons in Pretrained Transformers” 中给出了肯定答案。他们的方法是:

  1. 给模型一个事实性补全任务(如”北京是___的首都”→ “中国”)
  2. 逐个关闭 FFN 层的各个神经元
  3. 观察哪些神经元被关闭后,正确答案的概率显著下降

那些对正确答案至关重要的神经元,就是存储这个事实的”知识神经元”。

惊人的发现是:每个事实通常只由少数几十个神经元编码,它们分布在模型的中间层。这意味着知识存储是稀疏的——数万个神经元中,只有极小一部分参与任何一个具体事实的检索。

这解释了为什么 FFN 需要那么大

如果每个事实只占用几十个神经元的”容量”,那要存储人类知识中数以百万计的事实,你就需要一个非常大的内部维度。这就是为什么 $d_{ff} = 4 \times d_{model}$(甚至更大):它需要足够多的”记忆槽位”来存储所有训练数据中的模式和事实。

这也解释了一个经验观察:增大 FFN 的内部维度比增大 Attention 的维度更能提升模型的事实性知识。你在给模型的”仓库”扩容。

现代进化:门控 FFN(SwiGLU)

标准 FFN 的局限

原始 Transformer 用 ReLU 作为 FFN 的激活函数。ReLU 很简单:正数保留,负数变零。但它有一个问题——大量神经元会”死掉”(永远输出 0),浪费了宝贵的参数空间。

而且,ReLU 的”开/关”特性太生硬了。一个神经元要么完全激活要么完全沉默,没有中间状态。这限制了记忆库的表达能力。

门控机制:让神经元学会”犹豫”

2020 年,Noam Shazeer 提出了 GLU(Gated Linear Unit)变体用于 Transformer,其中最成功的是 SwiGLU

\[\text{SwiGLU}(x) = (\text{Swish}(xW_{gate}) \odot xW_{up}) W_{down}\]

这里有三个权重矩阵而不是两个!关键变化是引入了一个门控(gate)机制:

  • $xW_{up}$:正常的信息投影(”我要说什么”)
  • $xW_{gate}$:决定哪些信息该通过(”我该不该说”)
  • 两者逐元素相乘:只有门控同意的信息才能通过

用人话说:标准 FFN 里每个神经元只有一个”投票权”,而 SwiGLU 给了每个神经元一个额外的”否决权”。这种设计让信息流动更加精细可控。

为什么这比单纯的 ReLU 好?

回到”键值记忆”的视角:

  • ReLU FFN:每个记忆条目只有”激活/不激活”两种状态
  • SwiGLU FFN:每个记忆条目可以”部分激活”,而且激活的强度由一个独立的门控信号控制

这就像数据库从布尔索引升级到了加权索引——查询结果更加精确和细腻。

在实践中,SwiGLU 带来了显著的性能提升。LLaMA、PaLM、Mistral 等几乎所有现代大模型都采用了 SwiGLU 或类似的门控 FFN 设计。为了保持总参数量不变(因为多了一个门控矩阵),通常把内部维度从 $4d$ 缩小到 $\frac{8}{3}d$。

超位置与多义性:一个神经元不只存一件事

记忆库的容量困境

如果每个神经元真的只对应一个干净的模式,那 FFN 的容量就被严格限制了:$d_{ff}$ 个神经元最多存 $d_{ff}$ 条规则。但实际上模型需要存储的模式远比神经元数量多。

这就引出了超位置(superposition)的概念:模型把更多的特征”塞”进有限的维度中,代价是特征之间会有轻微干扰。这就像在一个书架上用密码编码的方式存了比格子数更多的书——只要你知道怎么解码,大部分时候都能正确取出想要的书。

多义性(Polysemanticity)

超位置在神经元层面的表现就是多义性:单个神经元同时对多种看似无关的模式响应。

Anthropic 在对 MLP 神经元的分析中发现,许多神经元同时被完全不相关的输入激活。比如一个神经元可能同时对”亚洲国家名”和”学术论文标题格式”有反应——这不是因为这两件事有什么关系,而是模型在有限的空间里做了一种”压缩存储”。

这意味着 FFN 的实际容量远大于其神经元数量。但也意味着”一个神经元 = 一条知识”的简单类比需要修正:真正的记忆单元不是单个神经元,而是神经元的组合模式

各层 FFN 做的事不一样

渐进式的信息加工

不是所有 FFN 层都在做同样的事。研究表明,Transformer 的不同深度有着不同的分工:

浅层 FFN(前 1/4): 主要做”去噪”和基础模式检测。这些层的神经元对应较为基础的语法和词汇模式——像是”名词之后通常跟动词”这种统计规律。

中间层 FFN(1/4 到 3/4): 这是事实知识存储的核心区域。因果追踪实验反复确认,修改这些层的 FFN 权重最能影响事实性输出。在这里,模型把”法国”和”首都”的信息组合起来,检索出”巴黎”。

深层 FFN(最后 1/4): 主要做输出准备和最终调整。这些层的值向量与具体的输出 token 更直接对应,它们在做最后的”措辞选择”。

层间残差连接的放大效应

别忘了每个 FFN 的输出会通过残差连接加回到主信息流中。这意味着 FFN 不需要”重写”整个表示——它只需要给出一个增量更新

这非常关键:FFN 的输出实际上是在说”在当前表示的基础上,加上这个修正”。Geva (2022) 的工作表明,这些修正在词汇空间中可以被解释为”推广某些概念,抑制另一些概念”。

每一层 FFN 都给出自己的”投票”,这些投票逐层累积,最终在输出层形成一个清晰的预测。这就像一个由数千名专家组成的委员会,每个人看了信息后给出一个小意见,最终的决策是所有意见的叠加。

实际意义:为什么这些理论很重要

知识编辑

如果我们知道知识存储在哪里,就能精确地修改它。ROME 方法已经证明可以通过修改 FFN 的参数来更新单个事实。这为解决模型”幻觉”和知识过时问题提供了一条路径——不需要重新训练整个模型,只需要”手术式”地修改相关的记忆条目。

模型压缩

知道 FFN 是稀疏激活的(大部分时候只有少数神经元活跃),就能做更聪明的压缩。比如可以裁剪那些几乎从不激活的神经元,或者用更低精度来表示激活频率低的神经元权重。

MoE 的直觉

Mixture of Experts(MoE)模型本质上就是把 FFN 层拆分成多个”专家”子网络,每次输入只激活其中几个。从”FFN 是记忆库”的角度看,MoE 就是把一个大仓库分成多个专题分库,然后用一个路由器快速判断”当前查询应该去哪个分库找答案”。这就是为什么 MoE 能在不增加计算量的前提下大幅增加模型容量——你增加了仓库面积,但每次只需要走访其中一小部分。

总结:重新认识 FFN

让我们回到开头的问题:FFN 层到底在干什么?

它不是一个简单的非线性变换。它是 Transformer 的知识仓库。

  • 它占据了模型 2/3 的参数,因为存储知识需要空间
  • 它的数学形式(两层线性 + 非线性)天然等价于一个键值记忆系统
  • 它以稀疏的方式存储事实:每个事实对应少量”知识神经元”
  • 它与 Attention 形成分工:Attention 搬运信息,FFN 加工和检索
  • 现代门控设计(SwiGLU)让这个记忆系统更加精确可控
  • 不同深度的 FFN 承担不同角色:从基础模式到事实检索到输出准备

下次当你看到一个 70B 参数的大模型时,你可以这样想:其中大约 47B 参数是”记忆”,剩下 23B 参数是”思考”(Attention + 其他组件)。模型越大,不只是”更聪明”,更是”记住了更多东西”。

下一篇预告

FFN 存储了知识,但知识是怎么进去的?训练时梯度下降如何把百科全书式的事实压缩进矩阵权重?下一篇我们会探讨损失函数的景观与优化器——模型”学习”的微观力学。