本文是「GPT 训练分步学习路径」的一篇番外,不绑定具体代码,只做一件事:把前面几篇里散落的术语,按「框架 / 训练 / 推理」三大类汇总成一张速查表。看完你应该能分清 PyTorch、Transformers、推理引擎各自管什么,也能听懂别人口中的「backward」「自回归解码」「KV Cache」「Trainer」到底在说什么。
目录
- 一句话先说清
- 框架三层关系:引擎、壳、专用引擎
- 训练相关术语
- 推理相关术语
- 注意力家族:字、头、维度、方向
- 架构差异:换零件与三种省法
- 训练 vs 推理:核心差异
- 开源模型的六层框架
- 术语速查总表
- 核心结论速览
1. 一句话先说清
大模型这套技术栈,可以用三句话锚定:
- PyTorch 是计算引擎:负责真正的数学运算(前向、求导、更新参数),训练离不开它。
- Transformers 是套在引擎上的壳:一行
from_pretrained就帮你把模型结构、分词器、生成逻辑都装好了。 - 推理引擎是专门优化过的跑步鞋:只跑推理不训练,所以能砍掉一半负担,跑得更快更省。
剩下的术语,基本都能挂到「训练」或「推理」这两根主线上。
2. 框架三层关系:引擎、壳、专用引擎
很多人容易把 PyTorch、Transformers、vLLM 混为一谈,其实它们是三个不同层级:
| 层级 | 代表 | 干什么 | 类比 |
|---|---|---|---|
| 计算引擎 | PyTorch / TensorFlow / JAX | 做张量运算、自动求导、参数更新 | 汽车的发动机 |
| 模型框架(壳) | HuggingFace Transformers | 封装模型结构 / 分词器 / 训练循环 / 生成逻辑 | 整车(含方向盘) |
| 专用推理引擎 | llama.cpp、vLLM、TensorRT-LLM、ONNX | 只做推理,用自己的算子追求极致速度,可脱离 PyTorch | 专业赛道跑鞋 |
几个关键结论:
- Transformers 是多后端设计,理论上不强制 PyTorch,但现实中 99% 的场景配的都是 PyTorch。
- 训练必须有计算引擎(要算梯度);推理可以不用 PyTorch,换成专用引擎往往更快。
3. 训练相关术语
| 术语 | 英文 | 一句话解释 | 对应本项目 |
|---|---|---|---|
| 前向传播 | forward | 把输入喂进模型,一层层算出预测结果 | model(x) |
| 损失 | loss | 衡量「预测」和「正确答案」差多少的一个数字 | F.cross_entropy |
| 反向传播 | backward | 从 loss 倒推每个参数「该往哪调、调多少」,只有一行却是引擎核心 | loss.backward() |
| 自动微分 | autograd | PyTorch 自动帮你算出所有梯度的机制,backward 背后的魔法 | PyTorch 内置 |
| 更新参数 | optimizer step | 按梯度真正把参数改一点点 | optimizer.step() |
| 清空梯度 | zero_grad | 每个 batch 开始前把上轮梯度清零,避免累加 | optimizer.zero_grad() |
| 梯度累积 | gradient accumulation | 用小显存模拟大 batch:攒几步再更新一次 | config.yml 里配置 |
| 学习率调度 | lr scheduling | 训练过程中动态调整步子大小(如 warmup + 余弦退火) | src/train.py |
| 微调 | fine-tuning | 在别人预训练好的模型上接着训,代价远小于从零训 | Transformers 主场景 |
| LoRA / PEFT | — | 只训练极少量新增参数的高效微调法 | 工业微调栈 |
训练四步口诀:前向算结果 → 比损失 → backward 倒推梯度 → step 更新参数(然后 zero_grad 清零,循环下一轮)。
4. 推理相关术语
| 术语 | 英文 | 一句话解释 | 对应本项目 |
|---|---|---|---|
| 推理 | inference | 用训练好的模型做预测,不再改参数 | src/infer.py |
| 自回归 | autoregressive | 「算一个字 → 加回输入 → 再算下一个字」的整体生成范式 | 生成循环 |
| 解码 | decoding | 从模型输出的概率分布里挑出具体那个字(贪心 / 采样 / top-k / top-p) | 生成循环 |
| KV Cache | — | 缓存前面已经算过的中间结果,新字只算增量,大幅加速 | 推理优化 |
| 连续批处理 | continuous batching | 多个请求动态拼批跑,提高吞吐(vLLM 的招牌) | vLLM |
| PagedAttention | — | vLLM 用「分页」方式管理 KV Cache 显存,省显存 | vLLM |
| 量化推理 | quantized inference | 用 INT8 / INT4 跑推理,省显存提速度(详见量化番外) | 量化引擎 |
| no_grad | torch.no_grad | 推理时告诉 PyTorch「别存梯度」,省显存 | 推理必用 |
推理为什么更简单:它砍掉了 backward 这半壁江山——不用存中间激活、不用算梯度、不用维护优化器状态,所以显存占用小、逻辑更聚焦,也才催生了 llama.cpp、vLLM 这类轻量专用引擎。
5. 注意力家族:字、头、维度、方向
前面 KV Cache 缓存的到底是什么?为什么 MHA / GQA / MQA 天天被提起?搞懂注意力机制,只需要拆清四个维度,别把它们搅在一起就不会晕。
下面全部用本项目的真实配置举例:
n_embd=256、n_head=4、n_kv_head=2(GQA),所以head_dim = 256 / 4 = 64。
5.1 四个维度,先各自站好队
| 维度 | 是什么 | 关键澄清 |
|---|---|---|
| 字(序列) | 一句话里的每个 token | 每个字都完整参与,一个都不丢 |
| 头(切分) | 一个字的向量被切成几段并行算注意力 | 「头」是字内部的切分,不是字与字之间 |
| 维度(宽度) | 每个头的宽度 head_dim | 恒等于 n_embd / n_head = 64,点积必须对齐 |
| 方向(因果) | 谁能看谁 | 当前字只能回头看前面的字(含自己),不能看后 |
5.2 Q / K / V 是每个字的三种身份
最常见的误解是「要预测的字用 Q,前面的字是 K/V」——不对。
真相是:每个字都同时拥有 Q、K、V 三份向量,它们是同一个字算出来的三种「身份」:
- Q(Query):我想找什么
- K(Key):我能被谁匹配到
- V(Value):如果被选中,我贡献什么信息
计算时,当前字用自己的 Q,去和前面所有字(含自己)的 K 做点积算相似度,再按相似度加权求和它们的 V。方向由因果掩码限定:只向左看。
5.3 头 = 一个字内部的切分(不是取舍字!)
另一个高频误解是「GQA 就是两个字取一个」——大错。共享的是头,不是字;字永远全参与。
一个字算注意力的过程是这样的:
1 | 「很」这个字 (256 维) |
注意:不是一个字算了 4 次 QKV,而是先算出一整份,再切成头。head_dim 恒为 64(由 n_head 决定,Q·K 点积要求维度对齐),所谓「K/V 是 128 维」指的是总宽度 = 2 段 × 64,不是每段 128。
5.4 MHA / GQA / MQA:只差 K/V 切几段
三者唯一的区别就是「几个 Q 头共用几份 K/V」,Q 头数和注意力流程完全不变:
| 类型 | Q 头数 | K/V 头数 | K/V 总宽度 | 本项目对应 |
|---|---|---|---|---|
| MHA | 4 | 4 | 256 | 标准多头 |
| GQA | 4 | 2 | 128 | 本项目 n_kv_head=2 |
| MQA | 4 | 1 | 64 | 极致省显存 |
1 | MHA: Q0 Q1 Q2 Q3 GQA: Q0 Q1 Q2 Q3 MQA: Q0 Q1 Q2 Q3 |
K/V 头越少 → KV Cache 越小 → 推理越快越省显存;而 Q 头保持多样,效果几乎不掉。省的是 KV Cache,不是让模型更笨。
5.5 存 128、算前复制回 256
既然 Q 是 4 个头、K/V 只有 2 个头,点积时怎么对齐?靠 _repeat_kv:把存下的 2 份 K/V 广播复制回 4 份,去配 4 个 Q 头。
所以:存的时候 128 维(省 KV Cache),点积前复制回 256 维参与计算。这就是 GQA 又省显存、效果又不掉的原理。
5.6 一句话收尾
- 字:全参与,因果方向只向左看
- 头:字内部切分,MHA/GQA/MQA 只动 K/V 头数
- 维度:head_dim 恒 64,Q=256 / K/V=128
- KV Cache 缓存的:正是每个历史字的 K、V(第 4 节的伏笔在此收束)
6. 架构差异:换零件与三种省法
看过 Llama、Mistral、Mixtral、Qwen 这么多名字,会以为架构五花八门。其实 90% 的差异只是几个”零件”在换,剩下少数是”骨架级”改动。这一节把它们收进一张统一的地图。
6.1 一个模型可拆成 4 个可替换零件
一个 decoder-only 模型,各家的差异几乎全集中在这 4 处:
| 零件 | 作用 | 常见选法(老 → 新) |
|---|---|---|
| 位置编码 | 告诉模型字的先后顺序 | 绝对位置(GPT-2)→ RoPE 旋转(Llama 系,主流)→ ALiBi |
| 注意力 | 字与字之间怎么算关系 | MHA(GPT-2)→ GQA(Llama/Qwen)→ MQA(Falcon)→ 滑动窗口(Mistral) |
| 归一化 | 稳定每层数值 | LayerNorm(GPT-2)→ RMSNorm(Llama 系) |
| 前馈网络(MLP) | 每个字自己做非线性变换 | GELU-MLP(GPT-2)→ SwiGLU(Llama 系) |
主流架构照着对号入座:
| 架构 | 位置编码 | 注意力 | 归一化 | MLP |
|---|---|---|---|---|
| GPT-2 | 绝对位置 | MHA | LayerNorm | GELU |
| Llama | RoPE | GQA | RMSNorm | SwiGLU |
| Mistral | RoPE | GQA + 滑动窗口 | RMSNorm | SwiGLU |
| Qwen2 | RoPE | GQA | RMSNorm | SwiGLU |
| Falcon | RoPE | MQA | LayerNorm | GELU |
可以看到一个明显趋势:GPT-2 的老四件(绝对位置 / MHA / LayerNorm / GELU)几乎被 Llama 的新四件(RoPE / GQA / RMSNorm / SwiGLU)全面取代。
6.2 注意力稀疏:省”计算量”
普通模型用全注意力(稠密):每个字和前面所有字都算一遍关系,开销随长度 N² 平方级增长。序列一长(几千上万字),计算和显存直接爆炸。
注意力稀疏 = 不算全部字对,只保留重要的连接:
1 | 稠密(每个字看全部前文) 稀疏(每个字只看一部分) |
常见图案:滑动窗口(Mistral,只看最近 N 个字)、局部+全局(Longformer/BigBird)、块稀疏等。
代价:跳过的连接万一重要就漏信息;且不规则计算对 GPU 不友好,短文本反而”稠密 + FlashAttention”更划算。所以稀疏是长文本专用,短序列用不上。
6.3 MoE:省”激活的算力”
普通(稠密)模型每层只有 1 个 MLP,所有字都从它过。MoE(专家混合)把每层那 1 个 MLP 换成多个并列的”专家”,再由一个”路由器”给每个字挑几个走。
1 | 稠密模型:每层 1 个 MLP MoE:每层多个专家,路由器挑 top-k |
以 Mixtral 为例:总共 8 个专家,每个字只激活 2 个。于是出现两个数字:
| 说法 | 含义 | Mixtral |
|---|---|---|
| 总专家数 | 一共备了几个专家 | 8 |
| 激活专家数(top-k) | 每个字实际走几个 | 2 |
关键——MoE 的”省”是相对”同等博学的稠密大模型”而言,不是相对小模型:
| 想要 47B 的知识容量 | 做法 | 每个字算多少 |
|---|---|---|
| 稠密大模型 | 1 个超大 MLP 撑到 47B | 每字都算完整 47B → 慢 |
| MoE(Mixtral) | 拆成 8 个各 ~7B,每字走 2 个 | 每字只算 ~13B → 快得多 |
一句话:MoE 不是”更快的小模型”,而是”跑得起的大模型”——用局部激活,避免为了博学而全量计算。 代价是 8 个专家都得加载进显存(省算力不省显存)。
6.4 三种”省法”放在一起看
这几样常被混为一谈,其实各动各的零件:
| 技术 | 省什么 | 动哪个零件 | 适用 |
|---|---|---|---|
| GQA / MQA | KV Cache 显存 | 注意力的头(K/V 头数变少) | 通用 |
| 注意力稀疏 | 计算量 N² | 注意力的字对(少算字对) | 长文本 |
| MoE | 激活的算力 | MLP(换成多专家,挑 top-k) | 想大又想快 |
正好呼应第 5 节的「注意力四维度」:GQA 动头、稀疏动字,而 MoE 跳出注意力、动的是 MLP。
7. 训练 vs 推理:核心差异
| 维度 | 训练 | 推理 |
|---|---|---|
| 目的 | 改参数,让模型变聪明 | 用参数,产出结果 |
| 有没有 backward | 有(核心) | 没有 |
| 显存占用 | 大(存激活+梯度+优化器状态) | 小(只存前向必要的) |
| 典型工具 | PyTorch / Transformers Trainer | 原生 PyTorch 或 vLLM/llama.cpp |
| 加速手段 | 梯度累积、混合精度、多卡 | KV Cache、量化、连续批处理 |
一句话:训练是「双向」的(前向+反向),推理是「单向」的(只前向),这就是推理能更轻的根本原因。
8. 开源模型的六层框架
判断一个模型「开源到什么程度」,可以看这六层是否都放出来:
| 层级 | 内容 | 通常开放度 |
|---|---|---|
| ① 权重 | 训练好的参数文件 | 常开 |
| ② 结构代码 | 模型结构 + 推理代码 | 常开 |
| ③ 微调代码 | 微调 / 推理脚本 | 较常开 |
| ④ 预训练代码 | 从零预训练的完整脚本 | 较少开 |
| ⑤ 训练数据 | 预训练用的原始数据 | 极少开 |
| ⑥ 配置日志 | 训练超参、训练日志 | 视情况 |
大多数「开源模型」开的是 ①②③(能推理、能微调),但 ④⑤ 往往不全——所以能用、能改,却很难一键从零复现。
9. 术语速查总表
| 分类 | 术语 | 一句话 |
|---|---|---|
| 框架 | PyTorch | 计算引擎,管运算和自动求导 |
| 框架 | Transformers | 套在引擎上的壳,一行加载全套 |
| 框架 | vLLM / llama.cpp | 专用推理引擎,可脱离 PyTorch 求极速 |
| 训练 | forward | 前向算预测 |
| 训练 | loss | 预测与答案的差距 |
| 训练 | backward | 倒推梯度,引擎核心 |
| 训练 | autograd | 自动求导机制 |
| 训练 | optimizer.step | 按梯度更新参数 |
| 训练 | fine-tuning | 在预训练模型上接着训 |
| 推理 | inference | 用模型做预测,不改参数 |
| 推理 | autoregressive | 算一个字加回去继续算的范式 |
| 推理 | decoding | 从概率里挑字 |
| 推理 | KV Cache | 缓存历史结果只算增量 |
| 注意力 | Q/K/V | 每个字的三种身份:想找/被找/贡献 |
| 注意力 | 头(head) | 字内部的切分,head_dim 恒 64 |
| 注意力 | MHA/GQA/MQA | 只差 K/V 切几段(4/2/1) |
| 架构 | 4 个零件 | 位置编码/注意力/归一化/MLP 的组合 |
| 架构 | 注意力稀疏 | 少算字对,省 N² 计算,长文本专用 |
| 架构 | MoE / 专家 | 每层多个 MLP,每字只激活 top-k 个 |
10. 核心结论速览
- 三层框架:PyTorch(引擎)→ Transformers(壳)→ 专用推理引擎(跑鞋),层级不同、各司其职。
- 训练四步:前向 → 损失 → backward → step,backward 是训练独有的核心。
- 推理更轻:砍掉 backward,不存梯度、不用优化器状态,所以能用轻量专用引擎。
- 自回归解码:推理时「算一个字、加回去、再算下一个」,靠 KV Cache 加速,全程不改参数。
- 注意力四维度:字(全参与)/ 头(字内部切分)/ 维度(head_dim 恒 64)/ 方向(因果只向左);MHA/GQA/MQA 只差 K/V 切几段。
- 架构差异:90% 是 4 个零件(位置编码/注意力/归一化/MLP)的排列组合;三种省法各动一处——GQA 省 KV Cache(动头)、稀疏省 N² 计算(动字对)、MoE 省激活算力(动 MLP)。
- 开源六层:权重/结构/微调/预训练/数据/日志,多数模型开前三层,难一键复现。