我们已经知道,大模型里有很多参数,训练时会调整它们,平常聊天时通常不会。
但这还没回答一个最直观的问题:
一堆固定的数字,怎么就能变成一句新话?
"经过注意力、FFN,最后预测下一个 token"这句话没有错,但跳过了最关键的部分:数据到底怎样使用这些权重?
这篇只沿着一个例子往下走,不展开训练、蒸馏和量化。
假设输入是"我喜欢",为了讲解,约定分成两个 token:
- A = "我",已经输入。
- B = "喜欢",已经输入。
- C = "猫",假设下一步选中了它。
- D = "。",假设再下一步选中了它。
这里的切分、编号、向量和分数都是教学示意,不是真实模型的测量结果。"我喜欢"也完全可能接出其他内容。
本文讨论常见的、从左到右生成文本的 decoder-only Transformer;层内顺序采用常见的 Pre-Norm 形式,不代表所有模型都完全相同。
一、先分清:词表、代码和权重不是一回事
运行一个模型,通常需要几类东西配合:
| 组成 | 负责什么 |
|---|---|
| 分词器与词表 | 把文字片段转换成 token ID,也能把 ID 序列还原成文字 |
| 结构配置 | 说明有多少层、每层多宽、多少注意力头等 |
| 执行代码 | 规定怎样查表、乘矩阵、计算注意力,以及按什么顺序执行 |
| 参数权重 | 训练得到的数字,包括词嵌入、各层 Attention、FFN、归一化参数和 LM Head 等 |
这些不一定打包在同一个文件里。比如,权重在下载的模型文件中,执行代码可能由推理框架提供。配置用于构建结构,加载器再把权重装进去。模型加载文档

图里最需要区分的是两张"表":
- 词表:记录 ID 和文字片段的对应关系。
- Embedding 权重表:记录每个 ID 对应的一串数字,也就是向量。
例如,"喜欢"可能被示意为 ID 102;查 Embedding 表后,得到 [0.2, -0.7, ...]。
102 只是编号,不表示"喜欢的程度是 102"。后续神经网络主要处理的是查出来的向量,不是直接拿这个编号做语义运算。分词器说明、Embedding 说明
二、权重怎么参与计算?不是去答案表里查一句话
向量可以先理解成"一串数字",权重矩阵可以先理解成"一张数字表"。
最常见的运算是:拿向量里的多个数字,分别乘上表里的权重,再加起来,得到一个新数字。换一组权重,就能得到另一个新数字。
举一个独立的微型算例:
text
输入的两个数字: 2、-1
使用的两个权重: 0.5、0.2
算出一个新数字: 2 × 0.5 + (-1) × 0.2 = 0.8
矩阵乘法,就是把很多这样的计算组织起来,一次算出一串新数字。部分计算还会加上叫作"偏置"的参数。线性层说明
所以,并不是"一个维度只配一个权重,乘完就结束"。一个输出维度,通常会组合多个输入维度的信息。
普通推理时,表里的权重不变,但输入向量不同,算出的结果就会不同。
这也是为什么同一个模型,既能续写"我喜欢",也能回答别的问题:它重复使用同一套计算规则和权重,处理不同的数据。
至于某个数字是不是"猫的特征"、某个维度是不是"情绪",通常没有这样人工指定、一一对应的标签,不能按一张中文属性表理解。
三、只拆一层:Attention 和 FFN 分别算什么?
现在,"我"和"喜欢"都已经变成了向量。
假设我们停在某一层,盯住 B,也就是"喜欢"这个位置。这一层要做的是:更新 B 的向量。此时还没有选出 C"猫"。

1. Attention:先算"参考谁、参考多少",再混合信息
它不是看到"喜欢"两个字,就按人工规则认定应该关注"我"。它依然在算数字。
可以拆成三步。
第一步:用训练好的权重,把输入向量变成三类向量。
这三类向量叫 Q、K、V。先不用背英文,可以这样记:Q、K 用于计算匹配程度,V 是随后参与混合的信息。
例如,B 的输入向量经过 Q 投影权重,得到 B 的 Q;A、B 的输入向量分别经过 K、V 投影权重,得到各自的 K、V。
投影权重是训练好的;本次得到的 Q、K、V 是运行时数据。换了上下文、层或位置,结果可以不同。
第二步:用 B 的 Q,分别和 A、B 的 K 计算分数。
经过缩放、可见范围限制和 softmax 转换后,得到一组和为 1 的比例。
假设某一层的某一个头,本次算出的比例是:
text
参考 A"我": 30%
参考 B"喜欢":70%
这两个比例只是示意,而且是这次算出来的,不是模型文件里写死的"我占 30%"。
从左到右生成时,B 可以参考自己和前面的 A,不能参考未来的 C。
第三步:按这个比例混合 V。
也就是:取 A 的 V 的 30%,加上 B 的 V 的 70%。多个头会各自计算,再合并,并通过一组输出投影权重。
得到的仍然是一串数字:给 B 位置的更新量,不是一个新词。Attention 原理与多头计算
注意这里有两种容易混淆的"权重":
| 名称 | 来源 | 普通推理时是否固定 |
|---|---|---|
| Q/K/V 等投影权重 | 训练得到的模型参数 | 固定 |
| 注意力权重,也就是上面的参考比例 | 根据本次输入计算 | 随输入和位置变化 |
它们都叫"权重",但不是同一类东西。
2. FFN:不再挑别的 token,而是重新组合当前向量里的数字
Attention 的结果与原向量相加后,B 的表示已经带上了上下文信息。经过归一化,它进入 FFN,也叫前馈网络,代码里常写作 MLP。
为了看清原理,先看一种简单的 FFN:
text
B 的向量 → 第一组权重 → 非线性变换 → 第二组权重 → 更新量
第一组权重把输入的多个数字重新组合,通常会得到一串更长的中间向量。例如,教学模型可以把 4 个数字变成 8 个数字。
中间再加一道非线性变换。最简单的例子是 ReLU:负数变成 0,正数保留。这样,哪些中间值继续发挥作用,就与这次输入有关。
第二组权重再把这些中间值组合回原来的宽度,例如从 8 个数字回到 4 个数字,方便与原向量相加。
这里变多的是一个向量里的数字,不是 token 数从 4 个变成了 8 个。
这也解释了为什么 FFN 不只是"又乘一次矩阵":如果中间没有非线性,连续两次线性变换可以合成一次,表达能力就不同了。原始 Transformer 的逐位置 FFN 使用两次线性变换和 ReLU;同一层的所有位置复用相同参数,不同层使用各自的参数。FFN 原理
实际模型可能采用带门控的 FFN,例如 Llama 实现会让两条计算分支相乘,再投影回来;不一定是上述 ReLU 版本。这里保留的是共同点:使用学到的参数,对每个位置的向量做非线性变换。
FFN 不会直接去读取 A 的向量,但 B 交给它的输入,已经包含 Attention 汇入的上下文。因此,"逐位置处理"不等于"完全不知道前文"。
3. 一层结束了,为什么还没有新 token?
因为 Attention 和 FFN 的输出都是向量。
图中还有两个辅助操作:归一化用于调整向量的数值尺度;残差相加是把模块更新量加回它的输入,保留原来的信息通路。
以图中的 Pre-Norm 顺序为例:
text
先归一化 → Attention → 加回这一段的输入
再归一化 → FFN → 加回这一段的输入
B 的向量更新后,会交给下一层。下一层也做 Attention 和 FFN,但使用的是下一层自己的权重。如此走完 N 层,才进入最终归一化和输出打分。层顺序、FFN 与输出层实现
层数不是生成次数。经过 N 层,是本轮计算的一部分,不是生成了 N 个 token。
四、LM Head:现在才开始给候选 token 打分
处理完输入 A、B 后,我们取最后一个已知位置 B 的最终向量,用它预测后面接什么。
LM Head 不是另外请来的评分模型。它就是当前模型的输出层,有自己的训练参数;有些模型会与 Embedding 共享权重。
它把这串向量与输出权重矩阵相乘,得到与词表大小对应的一串分数:一个候选 token 对应一个分数。这些原始分数叫 logits。
例如,只展示其中三个候选的示意分数:
| 候选 token | 本轮分数 |
|---|---|
| 猫 | 3.2 |
| 茶 | 2.7 |
| 书 | 1.1 |
这个表不是事先存好的答案。事先存好的是计算这些分数的权重;分数由本轮向量算出来。
接下来才轮到生成策略:可以取最高分,也可以把分数转换为概率后采样。采样不保证每次都选最高分,而且这种概率不是"答案客观正确的概率"。
假设这次选中了"猫"的 ID,它才成为新 token C。分词器再把 ID 序列解码成我们看见的文字。
到这里,才算走完了"根据 A、B,生成 C"的过程。
五、生成了"猫",下一轮怎么继续?
最容易绕晕的地方,是把"正在处理的 token"和"即将生成的 token"都叫成"当前 token"。
我们直接把两轮分开。

第一轮,模型处理已知的 A、B。经过各层计算,使用 B 的最终向量,选出 C"猫"。
第二轮,"猫"已经是已知 token。它的 ID 直接作为新输入,查 Embedding、经过各层 Attention 和 FFN,最后用 C 的最终向量预测 D"。"。
注意,不需要先把"猫"显示成文字,再重新分词。生成循环里已经拿到了它的 ID,可以直接续在 token 序列后面。
使用 KV Cache 时,也不用每轮把 A、B 的全部计算重做一遍。第一轮各层算出的 A、B 的 K、V 会被保存;第二轮处理 C 到哪一层,就复用那一层对应的历史 K、V,同时计算 C 自己的 Q、K、V。
因此,第二轮虽然通常只把 C 作为新增输入送进网络,但它的 Attention 仍能通过缓存参考 A、B,不是只看"猫"这一个词。KV Cache 与逐步生成
还有一个时间点值得记住:刚选出 C 时,缓存里还没有 C 自己的 K、V;下一轮真正处理 C 时,才会计算并写入。
KV Cache 是运行中保存的中间数据,不是新训练的权重。两轮使用的模型参数仍然是同一套。
最后,把整件事压成四句话
- 权重是训练好的计算参数,不是一张现成的回答列表。
- Attention 用本轮算出的比例混合可见位置的信息;FFN 对各位置的向量分别做非线性变换。
- 经过所有层后,LM Head 算候选分数,生成策略才选出新 token。
- 新 token 成为下一轮的已知输入;参数通常不变,向量、分数和缓存继续变化。
再回到开头的问题:固定的数字为什么能生成新话?
不是因为权重文件里藏着每一句完整答案,而是因为这套训练得到的计算,能把不同上下文变成不同的候选分数,再一步步选出后面的 token。