一句话版本
Transformer 接收一串 token 向量;每层先让 token 互相交换信息,再分别加工每个 token;最后把某个位置的向量变成词表上的概率。
模型只认识编号。单词、汉字或词片段先映射成词表 ID。
Embedding 表把每个 ID 查成 d_model 维向量,并加入位置信息。
注意力决定每个 token 应该从其他位置取回多少信息。
最终向量投影到整个词表,经 softmax 得到下一个 token 的概率。
TRANSFORMER · 从输入到输出
它做的核心工作:让每个 token 查看其他 token,再把有用信息带回自己身上。
01 · 全局地图
下面所有细节都只是这条流水线中的一个局部。先知道数据从哪里来、变成什么、最后去哪里。
Transformer 接收一串 token 向量;每层先让 token 互相交换信息,再分别加工每个 token;最后把某个位置的向量变成词表上的概率。
模型只认识编号。单词、汉字或词片段先映射成词表 ID。
Embedding 表把每个 ID 查成 d_model 维向量,并加入位置信息。
注意力决定每个 token 应该从其他位置取回多少信息。
最终向量投影到整个词表,经 softmax 得到下一个 token 的概率。
02 · 输入表示
计算机不能直接计算“猫”。它需要编号、向量和顺序三样东西。
“Transformer 很强”可能被切成 [“Transform”, “er”, “很”, “强”]。切法由 tokenizer 决定,和模型一起固定。
每个 token 在词表里有唯一整数编号,例如“猫”→ 4387。
用编号查询一行可训练参数,得到含义向量。相似用法会逐渐得到相近表示。
一句话最终变成 n 个 token;批处理中会补齐或截断到一定长度。
纯注意力本身看不出先后顺序,所以必须把位置信息写入向量。
使用固定的正弦、余弦位置编码,不需要学习参数。
为每个位置训练一行 embedding,BERT 等模型使用过这种方案。
许多现代大模型旋转 Q、K 向量,让注意力自然感知相对距离。
03 · 核心机制
对每个 token,都做一次“我现在要找什么、别人提供什么、最后拿回什么”的加权检索。
柱子越高,代表当前 token 从那个位置读取的信息越多。注意力权重相加等于 1。
“猫”主要读取动作“坐在”,也保留自身身份。真实模型的权重由训练自动学出。
每个输入向量分别乘三组参数矩阵,得到 Query、Key、Value。它们来自同一个序列,所以叫 self-attention。
当前 token 发出的检索请求。比如“它”可能在找前文中的指代对象。
每个 token 提供的索引标签。Q 与 K 越匹配,相关分数越高。
匹配后被取走的内容。权重用于加权求和所有 V。
假设有 n 个 token,每个头的维度为 dₖ。矩阵一次算完所有 token 对所有 token 的关系。
训练会把需要匹配的 Q、K 调整到相近方向;方向越一致,点积越大。
维度增大时点积方差也增大。缩放让 softmax 保持可训练的梯度。
04 · 多头注意力
单个注意力头只有一套 Q/K/V 投影。多个头可以在不同子空间同时学习不同关系。
05 · 一个完整 Block
一个 Transformer block 通常由注意力子层和前馈子层组成;每个子层外都有残差连接与归一化。
子层只需要学习“应该补充什么”,原输入沿捷径直接通过。这让深层网络更容易训练。
当前 token 已经拥有的信息。
注意力或 FFN 新学到的修正。
注意力沿“序列方向”混合信息;FFN 沿“特征方向”加工每个 token。所有位置共享同一套 FFN 参数。
d_model 常先扩大到约 4 倍的 d_ff,增加表达容量。
GELU、SiLU 或 SwiGLU 让网络能表示复杂函数。
第二个线性层把维度恢复到 d_model,便于残差相加。
06 · Encoder 与 Decoder
两种结构最关键的差异是注意力可见范围。这个差异决定模型适合“理解”还是“生成”。
每个 token 可查看左右所有位置。适合理解整段输入,BERT 是典型 encoder-only 模型。
每个 token 只能看自己和左侧,避免训练时偷看未来。GPT 是典型 decoder-only 模型。
行表示正在计算的位置,列表示想看的位置。灰色格子是未来,分数会被加上负无穷,softmax 后权重变成 0。
| 我 | 爱 | 机器 | 学习 | |
|---|---|---|---|---|
| 我 | ✓ | × | × | × |
| 爱 | ✓ | ✓ | × | × |
| 机器 | ✓ | ✓ | ✓ | × |
| 学习 | ✓ | ✓ | ✓ | ✓ |
翻译、摘要等任务常使用完整 encoder–decoder。Decoder 除了看已生成内容,还通过 Cross-Attention 读取 encoder 输出。
双向读取源文本,产出每个输入 token 的上下文表示。
因果遮罩,只读取已经生成的目标 token。
Q 来自 decoder;K、V 来自 encoder,让生成内容对齐输入。
07 · 训练与推理
训练时整段目标一次并行计算;推理时必须一个 token 接一个 token 生成。这是速度差异的根源。
输入“我 爱 机器”,目标分别是“爱 机器 学习”。
每个位置输出一个词表长度的原始分数。
正确 token 概率越低,损失越大。
梯度更新 embedding、QKV、FFN 等全部参数。
每次选概率最高者,稳定但容易重复、缺少多样性。
降低会让分布更尖锐,提高会增加随机性。
只在累计概率达到 p 的最小候选集合中采样。
旧 token 在每层产生的 K 和 V 不会因新 token 到来而改变,所以缓存起来。新一步只计算新 token 的 Q、K、V。
避免重复计算旧 token,大幅减少自回归解码的算力。
上下文越长、层数越多,KV Cache 占用的显存越大。
08 · 张量形状
理解 shape 能直接消除大部分 Transformer 代码阅读障碍。下面以 batch=B、长度=n 为例。
| 张量 | 典型形状 | 含义 |
|---|---|---|
| token_ids | B × n | 每个样本的一串词表编号 |
| X | B × n × d_model | embedding 后的输入表示 |
| Q,K,V | B × h × n × dₖ | 拆成 h 个注意力头 |
| scores | B × h × n × n | 每个头内,所有 token 两两相关分数 |
| head_output | B × h × n × dₖ | 每个头汇总 V 后的结果 |
| concat | B × n × d_model | 把所有头重新拼接 |
| FFN hidden | B × n × d_ff | 每个 token 的扩张特征,常约为 4×d_model |
| logits | B × n × vocab_size | 每个位置对整个词表的预测分数 |
09 · 架构家族
它们都使用 Transformer block,主要差别来自可见范围、模块组合和训练目标。
双向看完整输入,擅长提取上下文表示。
因果注意力,只看左侧前缀,连续预测下一个 token。
Encoder 理解输入,Decoder 在 Cross-Attention 帮助下生成输出。
10 · 成本与边界
注意力让任意两个 token 一步建立联系,但也产生随序列长度平方增长的矩阵。
n 翻倍时,n×n 注意力分数约变为 4 倍。长上下文尤其昂贵。
注意力只是模型参数和算力的一部分;宽大的 FFN 往往占多数参数。
训练保存中间激活用于反向传播;推理主要承受模型权重和 KV Cache。
FlashAttention 减少显存读写;GQA/MQA 减少 K/V 头;量化降低权重与缓存占用。
输出由概率驱动,可能幻觉;有限上下文不等于可靠长期记忆;注意力权重也不等于完整因果解释。
11 · 自测
先在脑中回答,再展开答案。每题都对应架构中的一个关键边界。
Q 表示当前 token 想找什么;K 表示每个 token 可匹配的索引;V 是匹配后真正被加权取回的内容。
维度增大时点积绝对值容易变大,让 softmax 过度饱和、梯度变小。缩放可稳定分布和训练。
多头在同一层并行观察不同关系;多层把前一层结果继续加工,逐步形成更复杂表示。
Attention 在 token 之间交换信息;FFN 对每个 token 的特征独立做非线性变换。
训练时整段文本同时进入模型;遮住未来位置可防止当前 token 偷看目标答案,并与自回归推理保持一致。
Q 来自 decoder 当前状态;K、V 来自 encoder 输出。它让生成端有选择地读取输入端。
缓存历史 token 每层的 K、V,因为未来 token 会查询它们。Q 只用于当前 token 发起查询,用完即可。
训练时已知完整真实序列,可用 mask 一次计算所有位置;生成时下一个 token 依赖刚生成的结果,必须逐步进行。