Transformer Block
Transformer Block
Transformer block 的核心分工是“跨位置通信 + 逐位置变换”。Attention 让一个 token 读取其他可见 token,FFN/MoE 在每个位置独立改变表示;残差把新信息加回旧流,归一化控制数值尺度。把这几件事混成“一个大网络层”,就解释不了缓存、并行和故障定位。
1 | token ids → embedding + position |
一次 block 发生什么
设输入为 x。Pre-LN 结构可抽象成:
1 | x1 = x + Attention(Norm(x)) |
第一条支路把跨位置信息写入序列,第二条支路把每个位置的特征投影到更高维中间空间,再压回 D。因果链是:可见性决定能读取什么 → attention 交换上下文 → FFN 非线性重组局部表示 → residual 保留旧信息并提供梯度通路 → 多层堆叠形成逐步抽象。
组件边界
- Attention:受 Causal Mask 约束的上下文聚合,推理时关联 KV Cache。
- FFN:同一位置上的两层投影与激活;它不直接在 token 之间通信。
- MoE:用 router 选择少量 expert,减少每个 token 激活的计算,但引入负载均衡和通信问题。
- Residual:保留输入并改善深层优化,不是普通意义的防过拟合正则。
- Normalization:控制激活尺度;Pre-LN/Post-LN 的位置不同,不能只交换两行代码。
架构族与取舍
| 架构 | attention 可见性 | 生成方式 | 典型用途 |
|---|---|---|---|
| Encoder-only | 双向 self-attention | 通常输出表示/分类 | 理解、检索编码 |
| Decoder-only | causal self-attention | next-token generation | 生成式 LLM |
| Encoder-decoder | encoder 双向,decoder cross-attention | 条件生成 | 翻译、摘要、seq2seq |
模型名字相同不代表 block 完全相同:norm、激活、位置编码、GQA/MQA、MoE、并行残差和 FFN expansion 都会改变内存与算力路径。
实现检查
先用 Tensor Shape 写出 [B,T,D] 到 Q/K/V 和 FFN 中间维度,再检查 residual 两端是否同形。源仓库教学 model.py 的每个 head 做完整 D→D 投影,不是标准 Dh=D/H 的 MHA,不能直接迁移到生产实现。
它向上连接 Autoregressive Generation,向下依赖 Scaled Dot-Product Attention、FFN kernel 和 normalization,横向连接 encoder-decoder、MoE 与 MHA 变体。
参考资料
Residual 顺序会改变优化路径
Pre-LN 把归一化放在子层之前,通常给深层网络提供更直接的 residual 梯度通路;Post-LN 则把归一化放在残差相加之后,对初始化和学习率更敏感。还有 parallel residual,把 attention 和 FFN 都从同一个 Norm(x) 分支计算再相加,减少串行深度但改变两条支路看到的输入。它们都可以叫“Transformer block”,却不能互换 checkpoint 或只改配置名。
FFN 是逐位置的容量层
attention 负责把信息搬到当前位置,FFN 再用非线性把当前位置的 D 维向量扩展到 Dff,经过激活后压回 D。因此把 FFN 的中间维度加大,增加的是每个 token 的变换容量,而不是让 token 彼此交流。SwiGLU 等门控结构会用一条支路控制另一条支路,参数和激活形状也随之变化。性能排查时要分别量 attention 的读 KV 和 FFN 的 GEMM,不能把所有 block 时间都归咎于 attention。
MoE 把 block 的问题转成路由问题
MoE router 为每个 token 选择少数 expert,让总参数量可以很大而每 token 只激活一部分计算;代价是 token dispatch、expert capacity、负载均衡损失和跨卡通信。一个 expert 过热会造成丢 token 或 padding,算力利用率下降;router loss 很漂亮也不代表真实负载均衡。验证 MoE block 要同时看路由熵、expert token 计数、drop rate、通信时间和任务质量。
定位 block 回归时,把问题拆成 attention、FFN、norm、residual 四个子路径:冻结三者逐个替换或做激活对齐,通常比从最终 logits 猜测更快。