真实面经题目 · 原创解析
Transformer FFN 为什么通常先升维再降维,这对表达能力和计算量有什么影响?
这题考 Transformer MLP/FFN 的基本机制:逐 token 的非线性变换、扩展中间维提升表达能力,再投回 hidden size 以便残差连接和层间堆叠。
真实面经题目 · 原创解析
这题考 Transformer MLP/FFN 的基本机制:逐 token 的非线性变换、扩展中间维提升表达能力,再投回 hidden size 以便残差连接和层间堆叠。
Transformer 里的 FFN 通常是对每个 token 独立做两层 MLP:先从 hidden size d 升到中间维 d_ff,再经过非线性激活,最后降回 d。先升维是为了给每个 token 更宽的特征空间,让模型能组合、筛选和重编码更多非线性特征;如果一直在 d 维里做线性变换,表达能力会受限。降维是因为 Transformer block 的输入输出 hidden size 要保持一致,才能和 residual connection、LayerNorm、下一层 attention 对接。计算量方面,普通 FFN 参数量约为 2*d*d_ff,单层每个 token 的矩阵乘计算也与 2*d*d_ff 成正比;如果 d_ff 是 4d,FFN 往往是 block 里很大的计算和参数来源。像 GLU/SwiGLU 会多一个门控投影,表达更强,但参数和计算也更高。面试里要同时讲表达能力、残差形状约束和计算代价。
Self-attention 负责 token 之间的信息混合,FFN 则对每个位置的 hidden state 独立做非线性变换。它不直接改变序列长度,也不在 token 间通信,而是提升每个 token 表示的特征变换能力。
从 d 升到 d_ff 相当于把 token 表示投到更宽的中间空间。宽层可以学习更多特征通道和组合模式,配合 GELU、ReLU 或 SwiGLU 等非线性后,模型能表达更复杂的函数。
如果只有线性升维和线性降维,中间没有激活,两层线性变换可以合并成一个线性变换,表达能力不会本质增强。激活函数或门控机制让 FFN 能选择性放大、抑制和组合特征。
FFN 输出必须回到 d 维,因为残差连接要把 FFN 输出加回输入 hidden state,后续 LayerNorm、attention 和下一层 block 也都期望相同 hidden size。降维不是丢掉全部信息,而是把宽空间中的有效特征压回模型主干维度。
普通两层 FFN 的参数量约为 d*d_ff + d_ff*d,也就是 2*d*d_ff。对 batch、序列长度分别为 B、L 的输入,矩阵乘的主要计算也与 B*L*2*d*d_ff 成正比;若按乘加分别计数,FLOPs 口径会再乘常数因子。
早期 Transformer 常用 d_ff=4d。现代 LLM 常见 GLU/SwiGLU 变体,会用 up projection、gate projection 和 down projection,通过门控提升表达,但会带来更多参数和计算,所以通常会调整中间维比例来平衡成本。
Self-attention 混合不同 token 的信息,FFN 对每个 token 的表示做非线性特征变换。前者负责上下文交互,后者负责局部表示的加工和重编码。
这是表达能力和计算成本的经验折中。更大的 d_ff 提升容量但增加参数、显存和延迟;更小的 d_ff 成本低但可能限制模型非线性变换能力。
意义很有限。两个线性层串联仍等价于一个线性层,只有加入激活或门控后,宽中间层才能表达非线性组合。
SwiGLU 通常有一个 up projection 和一个 gate projection,二者经过激活与逐元素相乘后再 down projection。门控能提升特征选择能力,但比普通两层 FFN 多一组投影成本。