把大模型从“会说话的黑箱”拆成可理解的计算链路:文本如何变成向量,向量如何互相看见,子层如何归一化与加工,位置如何编码,最后如何逐 token 生成答案;QKV、位置编码、Norm 与 FFN 的机制细节已并入本页
已并入:QKV 与多头注意力机制细节(第六节)、位置编码与 RoPE(第七节)、Normalization 与 Residual(第八节)、FFN 与 MoE(第九节)。
| 环节 | 它解决什么问题 | 你应该抓住的直觉 | 常见误解 |
|---|---|---|---|
| Tokenization | 把连续文本变成模型可处理的离散编号 | 模型不是直接读字词,而是读 token 序列;细节见 Tokenizer / 词表 | 把 token 等同于汉字、英文单词或语义单位 |
| Embedding | 把 token id 映射成高维向量 | 向量是模型内部的工作语言 | 以为 embedding 本身已经“理解”完整语义 |
| Position | 让模型知道 token 的顺序 | 同样的词在不同位置,作用可能不同;细节见 位置编码 / RoPE | 以为 Transformer 天生知道顺序 |
| Self-Attention | 让每个位置读取其他位置的信息 | 每个 token 都在问:我现在该看谁 | 以为 attention 就等于人类注意力 |
| Feed Forward | 对每个位置做非线性特征变换 | Attention 负责混合信息,FFN 负责加工信息;细节见 MLP / FFN / SwiGLU | 只记住 Attention,忽略 FFN 的容量作用 |
| Logits / Sampling | 给所有候选 token 打分并采样 | 生成不是一次写完,而是一步一步选下一个 | 以为模型内部先有完整答案再输出 |
| 读法 | 链路顺序 | 关键问题 | 继续下钻 |
|---|---|---|---|
| 训练视角 | 文本样本 → chat template / packing → token id → causal mask → forward → logits → next-token loss → 反向传播 | 模型为什么能从大量文本里学到条件概率、格式、模式和部分世界知识? | 语言建模目标 / Batch / Mask / Packing / 优化器 / Loss |
| 推理视角 | 用户消息 → message serialization → token id → prefill → KV cache → decode loop → logits → softmax / sampling → 新 token | 为什么输入越长首 token 越慢,输出越长总耗时越高? | Chat Template / 推理计算 / KV Cache / 解码 / 采样 |
| 工程视角 | 请求上下文 → token 预算 → 截断 / 压缩 → 模型路由 → 参数配置 → 流式返回 → Trace / Eval | 为什么同一个模型在不同上下文、参数、路由和后处理下表现差别很大? | 上下文组装 / 模型路由 / 一次请求的一生 |
底层理解不要把概念散着背。最稳的顺序是:消息先变成 token 序列,token 查表变成向量,位置机制注入顺序,Transformer block 反复混合和加工信息,最后输出 logits;训练时 logits 接 loss,推理时 logits 接采样。大多数 AI 工程问题,最后都能回到这条链路上的某个位置。
Token 是模型的输入颗粒度。你在 Prompt 里写的是人类文本,模型实际处理的是一串 token id。上下文窗口、成本、分块、缓存和生成速度,最终都会回到 token 数量。
| 概念 | 作用 | 可以怎么理解 | 边界 |
|---|---|---|---|
| Input Embedding | 把 token id 查表成向量 | 每个 token 有一组可训练坐标 | 单个 token 向量不等于完整语义 |
| Position Encoding | 给 token 注入顺序信息 | 让模型区分“猫追狗”和“狗追猫” | RoPE / position ids / 长上下文外推 |
| Hidden State | 每层 Transformer 后的位置表示 | 同一个 token 随上下文逐层改变含义 | 不能把它当成固定词典解释 |
| Output Projection | 把最终向量投回词表分数 | 问所有 token:谁最可能是下一个 | 高分不代表事实正确,只代表模型条件概率高 |
模型内部的 token embedding 是训练模型的一部分;RAG 常说的 embedding 通常是把句子、段落或文档编码成检索向量。二者都叫 embedding,但一个服务于模型计算,一个服务于语义检索。
Q 像“我现在想找什么信息”,K 像“我这里有什么特征可被匹配”,V 像“如果你看我,我能提供什么内容”。Attention 先用 Q 和 K 计算相关性,再按权重混合 V;更细的多头、mask、GQA/MQA 和 KV Cache 关系见 QKV / 注意力头机制。
Attention(Q,K,V) = softmax(QK^T / sqrt(d_k)) * V
Decoder-only 大模型生成时,只允许当前位置看见过去 token,不能偷看未来 token。这就是为什么它可以被训练成“预测下一个 token”的机器。
| 模块 | 职责 | 为什么需要 |
|---|---|---|
| LayerNorm / RMSNorm | 稳定每层输入分布 | 深层网络训练更稳定,梯度更可控;细节见 Norm / Residual |
| Attention | 跨位置混合上下文信息 | 让每个 token 的表示受其他 token 影响 |
| Residual Connection | 把原输入绕过子层加回来 | 避免深层网络丢失原信息,帮助梯度传播;细节见 残差流 |
| Feed Forward Network | 对每个位置做非线性变换 | 提供模型容量,完成特征加工和组合;细节见 MLP / FFN / SwiGLU |
| Stacking | 多层重复同类结构 | 低层偏局部模式,高层逐步形成更抽象表示 |
Encoder-only: 适合理解和分类,例如 BERT 路线。
Decoder-only: 适合自回归生成,是多数通用 LLM 的主流路线。
Encoder-Decoder: 适合输入到输出的转换任务,例如早期机器翻译和部分序列到序列模型。
这一节从 Attention 子层视角补 Q、K、V 的机制细节、多头注意力、注意力边界与可解释性,与第四节(信息路由直觉)互补。
| 步骤 | 做什么 | 抓住的直觉 | 常见失败 |
|---|---|---|---|
| 输入 hidden state | 每个 token 位置都有一个当前层表示 | Attention 处理的是上下文化向量,不是原始文字 | 把注意力图误读成词典关系 |
| Q / K / V 投影 | 用三组权重把同一 hidden state 投成 Query、Key、Value | Q 负责找,K 负责被匹配,V 负责被读取 | 把 Q/K/V 当成三份不同文本 |
| QK 打分 | 用点积计算当前位置和历史位置的匹配强度 | 分数越高,越可能从那个位置读取信息 | 忽略缩放、位置编码和 mask 的影响 |
| Mask + Softmax | 屏蔽不可见位置,再把分数转成权重 | 模型只能看允许看的 token | mask 错导致偷看未来、看见 padding 或漏看上下文 |
| 混合 V | 按权重加权求和 Value 向量 | Attention 的输出是从可见位置搬来的信息混合 | 以为 attention 只是在“标重点” |
| 输出投影 | 把多头结果拼接并投影回模型维度 | 多个信息通道汇总后写回残差流 | 忽略 output projection 和后续层的再加工 |
Q/K 决定“看哪里”,V 决定“拿什么”,mask 决定“能不能看”,softmax 决定“看多少”。
| 对象 | 来自哪里 | 它负责什么 | 可以怎么想 |
|---|---|---|---|
| Query | 当前位置 hidden state 乘以 Wq | 表达当前位置正在寻找什么信息 | 问题、检索意图、当前槽位需求 |
| Key | 各位置 hidden state 乘以 Wk | 表达每个历史位置有什么可被匹配的特征 | 索引、标签、可匹配线索 |
| Value | 各位置 hidden state 乘以 Wv | 表达命中该位置后可以读取的内容 | 实际搬运的信息包 |
| QK^T | Query 与所有 Key 做点积 | 生成 attention score | 当前位置对每个可见位置的匹配强度 |
| softmax(score) | 归一化后的权重 | 决定各位置 Value 混合比例 | 一个可学习的信息路由分布 |
Q/K 维度越大,点积分数的尺度越容易变大。除以 sqrt(d_k) 是为了让 softmax 不至于过早变得极端,帮助训练稳定。
RoPE 通常作用在 Q/K 上,让两个位置的 attention score 自然携带相对距离信息。位置机制不只是输入前贴标签,而是进入了“谁看谁”的匹配过程。
| Mask 类型 | 限制什么 | 典型场景 | 错误症状 |
|---|---|---|---|
| Causal mask | 当前位置不能看未来 token | decoder-only LLM 训练和生成 | 训练泄漏、评测虚高、生成行为异常 |
| Padding mask | 不让模型看 padding 位置 | batch 推理、不同长度样本混合 | batch 后输出和单条输出不一致 |
| Attention mask | 控制哪些 token 可见 | prefix、特殊模板、分段输入 | 模型漏看系统指令或看见不该看的片段 |
| Sliding window mask | 只允许看局部窗口 | 长上下文降成本 | 远距离依赖丢失、跨段推理变弱 |
| Block / sparse mask | 按块或稀疏规则可见 | 长序列、结构化文档、特殊架构 | 局部正常,长距离证据不稳定 |
很多看起来像“模型玄学变笨”的问题,其实是 mask、padding side、position ids 或 KV Cache offset 错了。先排输入可见性,再谈模型能力。
| 机制 | 直觉 | 收益 | 边界 |
|---|---|---|---|
| Multi-Head Attention | 多个独立 head 并行读上下文 | 能同时捕捉不同关系 | 显存和计算更重 |
| Multi-Query Attention | 多个 Q head 共享一组 K/V | 显著降低 KV Cache 占用 | 可能牺牲部分表达灵活性,需要任务评测 |
| Grouped-Query Attention | 多个 Q head 分组共享 K/V | 在质量和推理成本之间折中 | 不同模型实现细节不同 |
| Head pruning | 裁掉低贡献 head | 压缩模型或解释结构 | 贡献依赖任务和层,不能只看注意力强弱 |
| 观察对象 | 能告诉你什么 | 不能直接证明什么 | 继续深入 |
|---|---|---|---|
| Attention pattern | 某个 head 在某层偏向看哪些位置 | 不能直接证明输出因果由它决定 | 可解释性 / 模型内部表征 |
| Induction-like pattern | 模型可能在复制、续写、模板匹配中利用历史模式 | 不能说明模型真的“理解规则” | Prompt / 上下文工程 |
| Attention ablation | 去掉或替换某些头后输出是否变化 | 单次样本不能代表全局功能 | 模型评测 |
| Activation patching | 某个中间状态是否参与特定行为 | 不能替代真实生产评测和安全审计 | 模型内部机制 |
Attention 可视化适合找线索,不适合直接当审计证据。要证明某个 head 真有作用,需要干预实验、消融、跨样本稳定性和外部行为评测。
| 主题 | Attention 层发生什么 | 工程后果 | 回读页面 |
|---|---|---|---|
| Prefill | 一次性为整个输入序列计算 Q/K/V 和 attention | 输入越长,首 token 等待越明显 | 推理计算 / KV Cache |
| Decode | 每个新 token 只新增当前 Q,并读取历史 K/V | 输出越长,总耗时越长 | 解码 / 采样 |
| KV Cache | 缓存每层每个历史 token 的 K/V | 省重复计算,但消耗显存 | 推理计算 / KV Cache |
| RoPE / position ids | Q/K 携带位置旋转或位置关系 | 位置错位会导致长上下文质量异常 | 位置编码 / RoPE |
| GQA / MQA | 减少 K/V head 数量 | 降低 KV Cache 和带宽压力 | 模型服务 / 网关 |
| FlashAttention | 优化 attention 中间结果和显存读写 | 提升长上下文 prefill 效率 | AI Infra / GPU |
| 症状 | 优先怀疑 | 检查动作 |
|---|---|---|
| 单条输入正常,batch 后异常 | padding mask、position ids、left/right padding | 对比 batch 与 single 的 token、mask、position ids |
| 长上下文越长越漏证据 | attention 稀释、位置偏差、Top-K 片段过多 | 做位置扰动、needle retrieval、chunk 排序对照 |
| 续写重复或突然跑偏 | KV Cache offset、cache position、stop sequence | 检查 past length、cache reuse 边界和 position continuity |
| 量化后代码或长文本能力掉 | Q/K/V 或 attention 输出精度敏感 | 按任务切片比较 logits、attention 稳定性和最终评测 |
| 可解释图看起来合理但答案仍错 | Attention pattern 只是线索,后续层和 MLP 改写了表示 | 做消融、activation patching 和外部行为评测 |
| 证据节点 | 必须记录的字段 | 用来排查什么 |
|---|---|---|
| 输入边界 | token_ids_hash、attention_mask_hash、position_ids_hash、padding_side | batch 后异常、padding 错位、位置错位和不可见 token 泄漏 |
| Q / K / V 投影 | layer_id、head_id、qkv_dtype、quantization_config、shape_summary | 量化、张量并行或模型转换是否破坏了注意力计算 |
| 注意力模式 | attention_pattern_summary、top_attended_positions、mask_violations、entropy | 长上下文漏证据、格式 token 过强、注意力过度集中或过度稀释 |
| KV Cache 连续性 | cache_position、past_length、kv_block_id、reuse_boundary、eviction_count | 续写重复、跨请求污染、cache offset 错误和长任务恢复失败 |
| 行为连接 | trace_id、needle_test_id、ablation_result、downstream_metric | 观察到的 attention 变化是否真的解释了输出行为,而不是漂亮图像 |
这一节回答 Transformer 为什么需要位置、RoPE 的最小直觉、长上下文外推的边界,以及 position_ids 为什么是部署雷区。
| 问题 | 没有位置会怎样 | 位置机制解决什么 | 工程上会影响什么 |
|---|---|---|---|
| 顺序 | “猫追狗”和“狗追猫”的 token 集合接近,但含义完全不同 | 让模型知道 token 在序列中的先后关系 | 语法、代码、表格、步骤、引用顺序 |
| 距离 | 模型难以区分相邻依赖和远距离依赖 | 让 attention 感知两个位置相隔多远 | 长文档指代、跨段引用、代码作用域 |
| 因果生成 | Decode 时新 token 不知道自己是第几个位置 | position ids 和 causal mask 共同约束生成路径 | KV Cache 复用、流式生成、continue generation |
| 外推 | 训练只见过 4K,推理硬拉到 32K 会失真 | 通过缩放、插值、微调或窗口策略缓解位置分布漂移 | 长上下文质量、成本、延迟和开源模型兼容 |
Transformer 的 attention 本身更像“内容匹配”,位置编码给它补上“顺序和距离”。没有位置,模型很难知道同样一组 token 应该按什么时间线和结构理解。
| 机制 | 核心直觉 | 优点 | 边界 |
|---|---|---|---|
| Learned absolute position | 每个位置有一个可训练向量,和 token embedding 相加 | 简单直接,早期模型常见 | 训练窗口之外的位置没有学过,外推能力弱 |
| Sinusoidal position | 用不同频率的正弦余弦函数表示位置 | 不需要学习位置表,有一定外推直觉 | 长距离表现仍取决于训练分布和模型使用方式 |
| Relative position bias | attention 里加入相对距离偏置 | 直接表达两个 token 相隔多远 | 实现和缓存策略更复杂,窗口外仍需设计 |
| RoPE | 在 Q/K 向量上按位置做旋转,让内积天然携带相对位置信息 | 适合 decoder-only LLM,和 KV Cache 配合广泛 | 长上下文外推需要缩放、插值或训练配合 |
| ALiBi | 给 attention score 加随距离增长的线性惩罚 | 偏向近邻,外推实现较简洁 | 表达能力和不同任务适配需要实测 |
RoPE 不只是给 token embedding 加一个位置向量,而是在 attention 的 Q/K 空间里注入位置旋转。这样两个位置之间的相对距离会影响 attention score,很适合自回归生成和 KV Cache 场景。
| 对象 | RoPE 里发生什么 | 常见排查 |
|---|---|---|
| Q / K | 按 position id 旋转,attention score 因位置关系而变化 | 检查 RoPE 实现、base、scaling、position ids |
| V | 通常不直接旋转,作为被加权混合的内容值 | 不要把 Q/K/V 的角色混在一起 |
| position ids | 决定当前位置使用哪一组旋转角度 | 续写、padding、batch、KV Cache 时最容易错 |
| attention mask | 决定哪些位置可见,和 position ids 共同塑造生成行为 | padding side、causal mask、prefix cache 要对齐 |
| 做法 | 直觉 | 能解决什么 | 风险 |
|---|---|---|---|
| 直接改配置 | 把允许长度从 4K 改到 32K | 通常只能让程序跑起来 | 模型没有学过这些位置,质量可能明显退化 |
| Position interpolation | 把长序列位置压缩映射回训练过的范围 | 减少外推到陌生相位的程度 | 短距离分辨率可能下降,细节依赖缩放策略 |
| NTK / dynamic scaling | 调整 RoPE 频率或 base,让长距离映射更平滑 | 让 RoPE 在更长窗口下更可用 | 不同模型和任务收益差异大,需要回归评测 |
| Long-context fine-tuning | 用长序列数据继续训练或微调 | 让模型真正见过长距离模式 | 数据、算力、评测和灾难性遗忘都要治理 |
| Sliding / chunked attention | 只看局部窗口或分块聚合 | 控制计算和 KV Cache 压力 | 远距离依赖可能丢失,需要摘要或检索配合 |
“支持 128K 上下文”不等于“128K 内任何位置的信息都同样可用”。长上下文质量要看 needle retrieval、跨段推理、引用忠实、位置偏差、成本和尾延迟,而不是只看最大窗口数字。
| 场景 | 位置相关风险 | 典型症状 | 检查项 |
|---|---|---|---|
| Batch 推理 | 不同长度样本 padding 后 position ids 错位 | 同一输入单条跑正常,batch 后输出异常 | padding side、attention mask、position ids 生成逻辑 |
| 继续生成 | 新 token 的位置必须接在历史 KV 后面 | 续写重复、跑偏、格式突然坏掉 | past length、cache position、position offset |
| Prefix cache | 共享前缀缓存时,后续请求位置偏移要一致 | 缓存命中后质量反而变差 | prefix token 数、cache reuse 边界、position continuity |
| RAG 长文档 | 关键证据放在很靠后位置,可能受位置偏差影响 | 模型漏看中间段或偏向开头 / 结尾 | chunk 排序、引用位置、重排和摘要压缩 |
| 开源模型部署 | RoPE base、scaling、max position 与权重训练不匹配 | 短文本正常,长文本质量崩 | config、model card、推理框架默认 scaling |
Tokenizer 错了,模型读错 token;position ids 错了,模型读错顺序和距离。尤其在 padding、KV Cache、prefix cache、分块推理和长上下文扩展里,位置错位会表现成很玄学的质量退化。
如果长上下文只在“找一句话”评测里表现好,不代表它能稳定完成长文档推理、代码仓库理解、法律合同审阅或多文档对比。越接近真实任务,越要测跨段组合和位置扰动。
长上下文质量问题经常看起来像“模型没理解”,实际可能是 RoPE scaling、position ids、cache position 或证据放置位置不一致。
| 证据节点 | 必须记录字段 | 用来排查什么 |
|---|---|---|
| rope_config | rope_base、rope_scaling_type、scaling_factor、max_position_embeddings、trained_context_length | 部署配置是否偏离权重训练和模型卡声明 |
| position_runtime | position_ids_strategy、cache_position、padding_side、prefix_cache_boundary | batch、续写、prefix cache 下的位置是否连续 |
| evidence_position | context_length_bucket、evidence_offset_bucket、chunk_order、needle_eval_id | 证据放在开头、中间、结尾时质量是否稳定 |
| long_context_gate | eval_artifact_id、p95_latency、kv_cache_mode、release_gate_id | 拉长窗口后的质量、成本和延迟是否都过关 |
| 相邻主题 | 关系 | 本页补上的视角 | 继续深入 |
|---|---|---|---|
| Transformer | 位置机制是 Transformer 能理解顺序和距离的底层部件 | 解释 position encoding 如何进入 attention | Token / Attention / Transformer、QKV / 注意力头 |
| 推理计算 / KV Cache | 长上下文和 KV Cache 都依赖正确的位置连续性 | 解释 position ids、cache position 和长上下文为什么会影响推理稳定性 | 推理计算 / KV Cache |
| 长上下文 / 记忆 | 模型能看多长,不等于系统该记什么 | 区分模型内部位置外推和应用层状态治理 | 长上下文 / 记忆工程 |
| RAG | 检索片段放在 prompt 的不同位置,会影响模型读取和引用 | 解释 chunk 排序、证据位置和长文档偏差 | RAG / 知识检索 |
| 开源部署 | 模型配置里的 RoPE scaling 和 max position 必须和权重、推理框架一致 | 解释为什么“能加载”不等于“长上下文能用” | 开源部署 |
这一节回答深层模型为什么需要残差和归一化、LayerNorm / RMSNorm 归一化了什么、PreNorm / PostNorm 的取舍,以及训练稳定性和部署里的 Norm 风险。
| 问题 | 没有它会怎样 | Residual / Norm 做了什么 | 工程上看哪里 |
|---|---|---|---|
| 信息被层层改写 | 深层子层可能把早期信息冲掉 | Residual 让原隐藏状态沿主路直接传下去 | 残差尺度、layer 输出范数、表示漂移 |
| 梯度难以回传 | 深层网络容易梯度消失、爆炸或更新不均 | 残差路径给梯度提供更短的回传通道 | gradient norm、per-layer update ratio |
| 激活尺度漂移 | 每层输入分布不断变化,训练不稳定 | LayerNorm / RMSNorm 把输入尺度拉回可控范围 | activation norm、NaN、溢出、loss spike |
| 深度扩展困难 | 层数越多越难训,学习率窗口变窄 | PreNorm、残差缩放和初始化共同扩大稳定区间 | 训练初期 loss 曲线、warmup、学习率上限 |
Residual 保留“原信号和梯度主路”,Normalization 控制“每次进入子层前的尺度”。二者合在一起,才让 Transformer block 能被重复堆到很深。
x_next = x + SubLayer(Norm(x)) 是 PreNorm Transformer 的常见直觉。关键不是记公式,而是抓住:主路保留 x,子层写入一个经过尺度控制的增量。
| 机制 | 归一化对象 | 核心直觉 | 常见位置 |
|---|---|---|---|
| BatchNorm | 跨 batch 维度统计均值 / 方差 | 适合 CNN 等场景,但对变长序列和小 batch 不友好 | LLM 主干里较少用 |
| LayerNorm | 对单个 token 的 hidden dimension 做均值 / 方差归一化 | 每个位置独立校准自己的特征尺度 | Transformer 常见基础配置 |
| RMSNorm | 对 hidden dimension 的均方根尺度做归一化,通常不减均值 | 保留方向,控制长度,计算更省 | 许多现代 decoder-only LLM 常用 |
| Scale 参数 | 归一化后再乘可学习缩放 | 不是把所有特征永远压平,而是给模型可学习的尺度自由度 | LayerNorm / RMSNorm 权重 |
Norm 不是让模型“更懂语义”,而是让每层输入的数值尺度更可控。语义能力来自参数、数据、目标函数和层间计算;Norm 负责让这套计算别太容易失控。
| 结构 | 形式直觉 | 优点 | 代价 / 风险 |
|---|---|---|---|
| PostNorm | x_next = Norm(x + SubLayer(x)) | 早期 Transformer 经典结构,输出每层后被校准 | 深层训练更容易不稳定,对 warmup 和初始化更敏感 |
| PreNorm | x_next = x + SubLayer(Norm(x)) | 梯度路径更直接,深层 LLM 训练更稳 | 残差流尺度会逐层积累,需要配合初始化和缩放 |
| Sandwich Norm | 子层前后都放 norm 或额外校准 | 进一步控制激活范围 | 计算和实现更复杂,收益要靠实测 |
| Final Norm | 输出头前再做一次 norm | 让最终 hidden state 进入 LM head 前更稳定 | 必须和权重格式、推理实现保持一致 |
大模型层数深、序列长、混合精度训练多,稳定性窗口很重要。PreNorm 让梯度能更直接沿残差路径回传,RMSNorm 用更简单的尺度控制降低计算和数值负担。
| 相邻机制 | 和 Norm / Residual 的关系 | 常见问题 | 继续深入 |
|---|---|---|---|
| 学习率 / Warmup | Norm 扩大稳定区间,但不能抵消过猛的更新 | loss spike、NaN、训练初期崩坏 | 优化器 / Loss / 训练稳定性 |
| 初始化 / 残差缩放 | 层数越深,残差增量越需要控制初始规模 | 深层激活范数逐层膨胀或过弱 | 神经网络 / 训练循环 |
| 混合精度 | Norm 的统计和除法对数值范围敏感 | FP16 溢出、下溢、loss scale 抖动 | AI Infra / GPU |
| Attention / MLP | Norm 通常放在子层前,控制进入 attention 和 MLP 的尺度 | 某一类子层输出范数异常大 | Transformer、MLP / FFN |
| Logits / LM Head | 最终 norm 会影响输出分数尺度 | logits 过尖、过平、校准变差 | Logits / Softmax |
| 场景 | 风险 | 症状 | 检查项 |
|---|---|---|---|
| 权重转换 | LayerNorm / RMSNorm 权重名、epsilon 或顺序被转错 | 能加载但输出质量离谱 | config、state dict key、eps、final norm |
| 量化 | norm 附近的尺度变化影响量化误差 | 短文本还行,长文本或复杂任务退化 | per-layer error、校准集、是否跳过敏感层 |
| 推理框架 | 融合 kernel 的 norm 实现和原模型不一致 | 不同后端输出不一致 | RMSNorm kernel、dtype、epsilon、近似误差 |
| LoRA / Adapter | 适配器写入残差流,尺度不当会干扰主模型 | 微调后格式、风格或能力失衡 | adapter scale、rank、目标层、回归评测 |
| 长上下文 | 残差流随长序列和多层堆叠积累噪声 | 越长越跑偏、引用不稳 | position 机制、KV Cache、激活范数和真实任务评测 |
Norm 出错常常不是程序崩溃,而是“能跑但模型变笨”。权重转换、推理框架、量化和 adapter 合并时,Norm / residual 相关差异要用固定输入做输出回归。
这一层的问题经常表现为“能跑但变差”。证据包要把残差流、归一化配置、精度路径和回归样本绑在一起看。
| 证据节点 | 必须记录字段 | 用来排查什么 |
|---|---|---|
| norm_config | norm_type、eps、pre_or_post_norm、final_norm、residual_scale | 权重转换、推理框架和原模型结构是否一致 |
| activation_profile | layer_id、hidden_norm、attention_out_norm、mlp_out_norm、residual_after_norm | 哪一层开始爆炸、塌缩或写入异常 |
| precision_path | dtype、norm_kernel_version、quantization_skip_layers、nan_inf_event_id | 混合精度、融合 kernel、量化是否破坏尺度 |
| regression_sample | fixed_prompt_id、logits_diff、adapter_scale、eval_slice、rollback_target | 微调、adapter 合并或后端切换后质量是否漂移 |
这一节回答 FFN / MLP 在 Transformer Block 里的位置、SwiGLU 等激活形态、为什么 FFN 占很多参数和计算,以及它和 MoE 的关系。
| 模块 | 回答的问题 | 直觉 | 容易忽略什么 |
|---|---|---|---|
| Attention | 当前位置应该读取哪些上下文信息 | 跨 token 信息路由 | 它不是 Transformer 的全部 |
| FFN / MLP | 读到信息后,当前位置内部怎样加工 | 逐位置非线性变换和特征组合 | 大量参数和计算常常在这里 |
| Activation | 为什么多层线性变换不退化成一层线性 | 给模型加入弯曲、门槛和选择性 | 激活函数会影响稳定性、稀疏性和吞吐 |
| Gate | 哪些中间特征应该被放大或抑制 | 用一个分支调制另一个分支 | SwiGLU / GEGLU 改变权重形状和转换逻辑 |
Attention 像“从上下文里取料”,FFN 像“在当前位置做加工”。只懂 Attention,会漏掉现代 LLM 很大一部分参数、计算和能力形成位置。
| 步骤 | 形状直觉 | 做什么 | 工程含义 |
|---|---|---|---|
| Up Projection | hidden_size → intermediate_size | 把每个 token 的表示扩到更宽的中间空间 | 中间维度越大,参数和 GEMM 计算越多 |
| Activation | 逐元素非线性 | 让网络能表达复杂函数,而不是多层线性叠加 | GELU、SiLU、ReLU 等会影响速度和数值特性 |
| Down Projection | intermediate_size → hidden_size | 把加工后的中间特征压回 residual stream 的宽度 | 必须和残差主路形状对齐 |
| Residual Add | x + FFN(x) | 把 FFN 的增量写回隐藏状态 | 尺度过大或量化误差会污染后续层 |
FFN(x) = W_down * activation(W_up * x) 是非门控 FFN 的简化直觉。现代 LLM 常用门控变体,所以权重名会变成 gate_proj、up_proj、down_proj。
| 机制 | 核心直觉 | 常见位置 | 注意点 |
|---|---|---|---|
| ReLU | 负值截断,正值保留 | 早期神经网络常见 | 简单快,但表达和梯度特性不是现代 LLM 主流选择 |
| GELU | 按概率平滑地放过输入 | BERT、GPT 早期路线常见 | 比 ReLU 平滑,计算略复杂 |
| SiLU / Swish | x * sigmoid(x),小值平滑抑制,大值保留 | 门控 FFN 的基础激活之一 | 常出现在 SwiGLU 里 |
| GLU | 一个分支生成内容,一个分支生成门控 | 门控前馈网络 | 权重形状和普通 FFN 不同 |
| SwiGLU | SiLU(gate) * up 后再下投影 | 许多现代 decoder-only LLM 常用 | 能力和效率都好,但转换、量化和 LoRA 目标层要识别 gate/up/down |
门控 FFN 不是简单多一个激活函数,而是让模型学会“哪些中间特征现在该开、哪些该关”。这会影响容量、稀疏性、权重命名和微调目标层选择。
| 成本来源 | 受什么影响 | 优化方向 | 风险 |
|---|---|---|---|
| GEMM 计算 | hidden size、intermediate size、batch、sequence length | 融合 kernel、张量并行、批处理 | 小 batch 可能吃不满 GPU |
| 激活内存 | 训练时需要保存中间激活反传 | gradient checkpointing、重计算 | 吞吐下降,训练时间变长 |
| 权重带宽 | 参数量、量化格式、设备内存带宽 | INT8 / 4bit 量化、权重预取 | 质量退化和后端兼容风险 |
| 门控分支 | gate / up / down 多组投影 | 算子融合、正确识别权重名 | 转换和 LoRA 配置容易漏层 |
| 模型类型 | FFN 怎么变 | 好处 | 工程代价 |
|---|---|---|---|
| Dense Transformer | 每层每个 token 都经过同一组 FFN 权重 | 实现简单、吞吐稳定、部署成熟 | 总参数和激活参数一致,扩容成本高 |
| MoE Transformer | 部分 FFN 被替换成多个专家,token 只路由到少数专家 | 总容量变大,单次激活参数可控 | 路由、负载均衡、跨卡通信和尾延迟复杂 |
| Shared Expert | 共享 FFN + 路由专家混合 | 保留通用能力,同时增加专家容量 | 实现和权重格式更复杂 |
| Fine-tuned Expert | 只调部分专家或 adapter | 可降低微调成本 | 容易造成路由偏移和任务不均衡 |
FFN 本来就是逐 token 的非线性加工层,把它拆成多个专家比较自然。Attention 负责全局信息路由,FFN / Expert 负责局部特征加工,两者分工不同。
| 场景 | 要看什么 | 常见坑 | 继续深入 |
|---|---|---|---|
| 权重转换 | gate_proj、up_proj、down_proj、激活函数配置 | 把 SwiGLU 当普通 FFN 转,能加载但质量坏 | 参数 / 权重 / Checkpoint |
| LoRA / Adapter | target modules 是否包含 gate / up / down | 只调 attention,忽略 FFN 可能限制任务适配 | 微调 / 对齐 |
| 量化 | FFN 大矩阵的量化误差和校准集覆盖 | 看似困惑度变化小,复杂任务退化明显 | 压缩 / 量化 |
| 推理引擎 | 激活函数、门控乘法、down projection 是否融合 | 后端不支持某种激活或 kernel 慢 | 推理计算 |
| 可解释性 | MLP 神经元、特征方向和残差写入 | 把单个神经元过度解释成单一概念 | 模型内部表征 |
FFN 问题常在权重转换、量化、kernel 融合和 adapter 目标层里暴露。证据包要证明 gate / up / down、激活函数和残差写入都对齐。
| 证据节点 | 必须记录字段 | 用来排查什么 |
|---|---|---|
| ffn_config | hidden_size、intermediate_size、activation_fn、gate_proj_shape、up_down_shape | 架构配置和权重张量是否一一匹配 |
| adapter_target | target_modules、rank、adapter_scale、merge_script_hash、eval_slice | LoRA / Adapter 是否正确写入 FFN 路径 |
| kernel_path | activation_kernel、fused_mlp_version、dtype、backend_name、logits_diff | 推理后端和原框架的激活、门控实现是否一致 |
| quant_error | quantization_recipe、calibration_set_id、per_layer_error、rollback_target | FFN 大矩阵量化后是否伤害复杂任务和长尾能力 |
| 参数 / 机制 | 影响 | 适合场景 | 风险 |
|---|---|---|---|
| Temperature | 控制分布尖锐程度 | 低温用于事实、抽取、格式化;高温用于创意 | 温度高更发散,温度低也不保证正确 |
| Top-p / Top-k | 限制候选 token 范围 | 控制随机性,避免极低概率候选 | 限制过强会让输出僵硬 |
| KV Cache | 缓存历史 Key / Value | 长输出和多轮生成加速 | 长上下文显存占用会快速增长 |
| Stop Sequence | 遇到特定片段停止生成 | 结构化输出、工具调用、模板边界 | 配置错误会提前截断或停不下来 |