Transformer 全面拆解:从「预测下一个词」到改变世界的技术
写给那些不满足于"注意力机制很强大"这种解释的人。
本文目标:把一个"黑箱",拆成你能 mentally simulate 的系统。
引言:一个看似简单的问题
你有没有想过——ChatGPT 为什么"看起来懂你"?
当你问它"帮我写一封拒绝朋友请求的礼貌邮件",它不仅能写出来,还能感知到"拒绝"和"礼貌"之间的张力,给出一封语气恰当、逻辑自洽的信。这不是简单的模板填充,也不是数据库检索。
它真的理解语言吗?
答案比你想象的既更简单,也更深刻。
Transformer 本质上只做一件事:预测下一个 Token。
没有世界模型,没有常识库,没有专门的语法规则。就是反复地、大规模地、在海量文本上——预测下一个词。
然而就是这个看似朴素的任务,催生出了 GPT-4、Claude、Gemini 这些震动世界的系统。
为什么?
因为"完美预测下一个词",在信息论上,等价于"完全理解语言背后的结构"。而 Transformer 架构,提供了一种前所未有的、可大规模扩展的方式去逼近这个目标。
这篇文章,我们就来把这个"黑箱",一层一层地拆开。
读完之后,你不一定能写出 GPT-4,但你应该能:
- 在脑子里模拟 token 从输入到输出的完整流程
- 理解为什么 Transformer 打败了 RNN
- 知道为什么模型越大越聪明,以及这条路的边界在哪里
- 对"模型到底理解了什么"有自己批判性的判断
不需要记公式,但需要你认真思考。
让我们开始。
第一部分:核心直觉
1. Transformer 的本质:信息如何在序列中流动?
在理解任何细节之前,先建立最重要的直觉:
Transformer 是一台"信息路由机器"。
给定一个 token 序列(比如一句话),Transformer 的核心任务是:让每个 token 能够"看到"并"收集"序列中其他位置的相关信息,然后据此更新自己的表示。
这句话有三个关键词:
- 看到:不是所有 token 都同等重要,需要有选择地关注
- 收集:把分散在序列中的信息汇聚到当前位置
- 更新:根据收集到的信息,修正自己对这个 token 的"理解"
这个过程,在每一层 Transformer Block 里都会发生一次。一个现代 LLM 有 96 层甚至更多,也就是说,每个 token 会经历 96 次这样的"信息更新"。
最终输出的向量,已经不再是孤立的词义,而是包含了整个上下文信息的、高度压缩的语义表示。
2. 从 RNN 到 Attention:为什么旧时代崩塌?
要真正理解 Attention 的价值,必须先理解它在解决什么问题。
RNN/LSTM 的三个致命问题
问题一:长距离依赖(Long-range dependency)
RNN 的工作方式像一个人在读书,每次只看一个词,然后把"记忆"(hidden state)传递给下一个时刻。问题是:当序列很长时,早期的信息经过多次传递,会越来越稀薄。
想象一个极端例子:
“我在法国长大,父母都是巴黎人,从小说法语,后来去了美国读书,毕业后在硅谷工作,现在已经十年没回去了,但我的母语仍然是______”
答案是"法语",但关键信息在序列最开始。RNN 在处理到最后时,早已"忘记"了开头的上下文。LSTM 通过门控机制有所改善,但本质问题没有解决——信息必须通过一个窄瓶颈(hidden state)逐步传递。
问题二:串行计算(Sequential computation)
RNN 必须按顺序处理每个 token:先处理第 1 个,再处理第 2 个,依此类推。这意味着:
- 无法并行化
- 在现代 GPU(擅长大规模并行计算)上效率极低
- 训练长序列时,时间成本线性增长
这是工程上的死穴。
问题三:表达瓶颈(Representation bottleneck)
整个序列的语义,必须被压缩进一个固定大小的 hidden state 向量里。无论句子多长、多复杂,这个向量的维度是固定的。
这就像要你用一张明信片,描述清楚一本书的全部内容。
Attention 如何一刀解决
Self-Attention 的核心思想极其优雅:
与其让信息"穿越时间隧道"逐步传递,不如让每个 token 直接"看到"序列中所有其他 token,按需提取信息。
- 长距离依赖?不存在。任意两个 token 之间的距离,都是 1(直接注意力连接)。
- 串行计算?不存在。所有 token 的 Attention 计算可以完全并行。
- 表达瓶颈?不存在。每个 token 都可以直接访问完整的序列信息,不需要挤过一个固定大小的瓶颈。
三个问题,一个机制,全部解决。
这就是为什么 2017 年那篇论文用了一个如此自信的标题——Attention Is All You Need。
第二部分:一张图看懂 Transformer
3. 一张总图:LLM 在干什么?
让我们把整个流程用最直观的方式串联起来:
输入文本: "The cat sat on the"
↓
[Tokenization]
"The" / "cat" / "sat" / "on" / "the"
↓
[Embedding]
每个 token → 一个高维向量(比如 4096 维)
↓
[Position Encoding]
向量 + 位置信息(第1个词、第2个词...)
↓
[Transformer Block × N]
┌──────────────────────┐
│ Multi-Head Attention │ ← 信息路由(token 之间通信)
│ Add & LayerNorm │
│ Feed-Forward Network │ ← 信息处理(每个 token 独立计算)
│ Add & LayerNorm │
└──────────────────────┘
↓ (重复 N 次,N 可能是 96 或更多)
[最后一层的输出向量]
↓
[Language Model Head]
输出向量 → 词汇表上的概率分布(50000 个词,每个有一个概率)
↓
[采样]
选取下一个 token(比如 "mat")
这就是完整的数据流。没有魔法,只是矩阵乘法和非线性激活函数,在极大规模下重复执行。
4. 为什么现代 LLM 都是 Decoder-only?
原始的 Transformer(2017 年)有两部分:Encoder 和 Decoder,专门用于机器翻译——Encoder 读源语言,Decoder 写目标语言。
但现代 LLM——GPT、Claude、LLaMA——都是 Decoder-only 架构。Encoder 去哪儿了?
Encoder 被"淘汰"的本质原因:
Encoder 的设计是双向的,也就是说,处理某个 token 时,它可以同时看到左边和右边的上下文。这对理解任务(分类、抽取)很好,但对生成任务来说,这在逻辑上是矛盾的——你在生成第 k 个词时,右边的词根本还不存在。
Decoder-only 架构使用因果掩码(Causal Mask),强制每个 token 只能看到自己左边(之前)的内容。这使得它天然适合自回归生成:一个 token 一个 token 地往右生成。
更深层的原因是:研究者发现,Decoder-only 架构 + 足够大的规模 + 足够多的数据,在几乎所有任务上都能超越 Encoder-Decoder 架构。包括原本被认为需要 Encoder 的理解类任务。
这是 Scaling Law 带来的实证结论,不是先验设计。
第三部分:语言是怎么变成向量的?
5. Tokenization:语言不是词,而是压缩编码
大多数人以为 LLM 以"词"为单位处理文本。这是错的。
LLM 处理的是 Token——一种介于字符和单词之间的语言单位。
"unbelievable" 可能被切分成 ["un", "believ", "able"] 三个 token。
"ChatGPT" 可能是一个 token,也可能是两个,取决于训练数据。
中文 "我爱北京天安门" 在某些 tokenizer 里每个字是一个 token。
为什么要这样做?
核心原因是信息压缩。
BPE(Byte Pair Encoding)和 SentencePiece 的算法逻辑是:找出训练语料中出现频率最高的字符组合,将其合并成一个新的 token。反复执行这个过程,直到词表达到目标大小(通常 32000 到 200000 个 token)。
效果是:常见词(“the”、“is”)被编码为单个 token,罕见词被拆成子词片段,极罕见字符退化为字节。
关键认知点:Token ≠ 单词。
这个认知会帮你理解很多 LLM 的"奇怪行为":
- 为什么 LLM 数数字母有时会数错?(因为"strawberry"可能是一个 token,模型没有"看到"里面有几个 r)
- 为什么某些拼写任务对 LLM 困难?(操作 token 不等于操作字符)
- 为什么 token 长度影响模型成本?(按 token 计费,不按词计费)
6. Embedding:语义空间是如何形成的?
Token 经过 Tokenization 变成一个整数 ID(比如 4821)。但整数 ID 本身没有任何语义结构——4821 和 4822 不应该比 4821 和 9000 更"相似"。
Embedding 把这个 ID 映射成一个高维向量(比如 4096 维的浮点数向量)。
这个映射本身就是一个巨大的查找表,在训练过程中不断被优化。
“词向量"其实是统计结构
Embedding 的神奇之处在于:训练结束后,语义相似的词,在向量空间中的距离也相近。
这不是人为设计的,而是从大量文本的共现统计中涌现出来的。
直觉解释:如果"猫"和"狗"总是出现在相似的上下文里(“我养了一只___"、“宠物___"),那么预测任务会倾向于给它们分配相似的向量——因为相似的向量在后续计算中会产生相似的行为,这对减小预测误差是有利的。
为什么相似词会靠近?
因为 Transformer 的目标是最小化预测下一个 token 的误差。在这个目标下,语义相近的词可以"共享"更多的表示结构,这比让它们的向量天各一方更高效。优化压力,自然地将语言的语义结构编码进了几何空间。
7. 位置编码:Transformer 如何"记住顺序”?
这是一个非常微妙但重要的问题。
为什么 Attention 本身是"无序的”?
Self-Attention 机制在计算时,把所有 token 的向量打包成一个矩阵,然后做矩阵运算。在这个过程中,每个 token 对其他 token 的关注度,取决于它们向量之间的相似性——但完全不考虑它们的位置顺序。
换句话说,如果你把输入 token 的顺序打乱,Self-Attention 的计算结果(排列意义上)是一样的。
这意味着:如果不额外加入位置信息,"猫 吃 鱼" 和 "鱼 吃 猫" 对模型来说完全一样——这显然是灾难性的。
解决方案:位置编码(Positional Encoding)
最简单的方式:给每个位置生成一个固定的向量,加到 Embedding 上。模型就能感知到"这是序列里第 3 个 token”。
原始 Transformer 用的是正弦/余弦函数生成的固定位置向量。这有效,但有局限:预设了最大序列长度,外推能力差。
RoPE 为什么成为主流?
RoPE(Rotary Position Embedding,旋转位置编码)是现代 LLM 的主流选择(LLaMA、Mistral、GPT-NeoX 等都用它)。
直觉解释:与其把位置信息"加"到向量上,RoPE 将其旋转向量。具体来说,两个 token 在 Attention 计算中的相对关系,通过它们向量之间的旋转角度来体现。
这样设计的好处:
- 相对位置自然涌现:模型关注的是两个 token 的相对距离,而非绝对位置
- 外推能力强:通过频率调整(YaRN、LongRoPE 等方法),可以将上下文窗口从 4K 扩展到 128K 甚至更长
- 与 Attention 计算无缝结合:不需要修改架构,只需在 Q、K 向量上施加旋转变换
你不需要理解旋转的具体数学,只需记住直觉:RoPE 让模型在做 Attention 时,天然感知到两个 token 之间的相对距离。
第四部分:注意力机制
8. Self-Attention 的直觉版本(不写公式)
先忘掉公式,从最直观的角度理解。
Query / Key / Value = 信息检索系统
想象你在用搜索引擎:
- 你输入一个搜索词(Query)
- 数据库里每条记录有一个索引标签(Key)
- 实际内容是Value
搜索的过程:将你的 Query 和每条记录的 Key 做匹配,相关的 Key 得到高分,最终返回高分记录的 Value 的加权组合。
Self-Attention 做的就是这件事,只不过:
- Query、Key、Value 都来自同一个序列
- 每个 token 同时扮演三个角色:它既是查询者(Query),也是被查询者(Key + Value)
- 每个 token 通过自己的 Query,在序列中查找和自己相关的信息(Key 高度匹配的位置),然后提取那些位置的 Value
类比:
想象一个圆桌会议,每个人都在讲话。你(当前 token)需要决定:此刻,谁说的话和我最相关?你用自己的"问题"(Query)去匹配每个人的"话题标签"(Key),然后重点听那些标签最符合你问题的人说的话(Value)。
这就是 Self-Attention。
9. 从直觉到数学:Attention 到底在算什么?
Attention(Q, K, V) = softmax(QK^T / √dk) · V
看起来复杂,但拆开来非常清晰:
第一步:QK^T(计算相关性分数)
Q 是一个矩阵(每行是一个 token 的 Query 向量),K 也是一个矩阵(每行是一个 token 的 Key 向量)。
QK^T 做的是:让序列中每对 token 之间计算一个点积分数,得到一个 n×n 的分数矩阵。
点积越大 → 两个向量越相似 → 这两个 token 越"相关"。
第二步:除以 √dk(缩放)
为什么要除以一个数?
因为 dk(Key 向量的维度)通常很高(比如 128)。在高维空间里,点积的数值会随维度增大而增大,导致 softmax 的输入数值过大,使得 softmax 的输出变得极度尖锐(几乎把所有注意力集中在一个 token 上)。
除以 √dk 是一个归一化操作,把数值压回一个合理的范围,确保梯度不会消失,训练稳定进行。这是一个非常实用的工程技巧,背后的直觉就是:高维点积需要缩放才能被 softmax 正常处理。
第三步:softmax(转换为概率)
Softmax 把分数矩阵的每一行转换成概率分布——所有值加起来等于 1,且都是正数。
这就是"注意力权重":token i 对 token j 的注意力权重,表示 i 在更新自己时应该从 j 那里提取多少信息。
第四步:乘以 V(加权聚合)
用注意力权重对 Value 矩阵做加权求和,得到每个 token 的新表示。
整个过程:用相似度加权,从序列中提取最相关的信息,融合成当前 token 的新表示。
10. Multi-Head Attention:为什么要"多视角看世界"?
单头 Attention 有一个问题:在同一次计算中,每个 token 只能用一种"注意力模式"去看其他 token。但语言的关系是多维的——语法关系、语义关系、指代关系、位置关系……
Multi-Head Attention 的解法极其优雅:
把 Q、K、V 各自线性投影到 h 个更小的子空间(每个子空间叫一个 “head”),在每个子空间里独立做 Attention,然后把所有 head 的输出拼接起来,再投影回原始维度。
每个 head 学不同模式
大量的可视化研究表明,不同 head 确实专注于不同的语言关系:
- 某些 head 关注直接相邻的 token(局部语法结构)
- 某些 head 追踪代词和其指代对象之间的关系(“他”→“约翰”)
- 某些 head 捕捉动词和其宾语之间的依存关系
- 某些 head 关注对称性结构(括号匹配、列举关系)
没有人告诉模型要学这些,这些模式是在预测任务的压力下自动涌现的。
这是 Transformer 最令人惊叹的特性之一:它在没有语言学监督的情况下,自己发现了语言学规律。
11. Causal Mask:LLM 为什么不会"偷看答案"?
回到前面提到的一个关键问题:LLM 是自回归的——它在生成第 k 个 token 时,右边的 token 还不存在。
但 Transformer 的 Attention 机制在没有限制的情况下,会让每个 token 都能看到序列中所有其他 token(包括右边的)。
这在生成时是不允许的:如果训练时 token k 能看到 token k+1、k+2,它就"作弊"了,学到的不是真正的语言分布,而是一种取巧的映射。
Causal Mask 的解法:
在 Attention 分数矩阵上,把所有"向右看"的位置(上三角)设为负无穷(-∞)。经过 softmax 后,-∞ 变成 0——也就是说,这些位置的注意力权重为 0,完全被忽略。
这样,每个 token 只能从左边(之前生成的内容)获取信息,自然地实现了时间因果性。
训练时和推理时,这个 mask 的逻辑完全一致:模型从来不"看未来"。
第五部分:Transformer Block 内部到底发生了什么?
12. 一个 Block 的完整拆解(最重要小节)
这是理解 Transformer 最关键的部分。让我们把一个 Block 拆成四个步骤:
输入 x
↓
[Multi-Head Self-Attention(x)]
↓ 得到注意力输出 attn
[x + attn] ← 残差连接(Residual Connection)
↓ 得到 x₁
[LayerNorm(x₁)]
↓ 得到 x₂
[Feed-Forward Network(x₂)]
↓ 得到 ffn
[x₂ + ffn] ← 残差连接
↓ 得到 x₃
[LayerNorm(x₃)]
↓
输出(作为下一个 Block 的输入)
每个 Block 的作用:让 token 的表示向量,经过一次"信息交换 + 信息处理"后,变得更丰富、更具上下文感知能力。
96 个 Block 串联下来,最后一层的向量,已经包含了整个上下文的高度抽象语义信息。
13. FFN:为什么 Attention 之后还要 MLP?
这是一个好问题:既然 Attention 已经做了信息聚合,为什么还需要一个 Feed-Forward Network(本质是两层 MLP)?
Attention 是"通信",FFN 是"计算"。
- Attention 的作用:让 token 之间相互交换信息(跨位置的信息路由)
- FFN 的作用:对每个 token 独立地进行非线性变换(位置无关的特征提取)
一个流行的解释来自 Geva 等人 2021 年的研究:FFN 层像是一个巨大的键值存储(key-value memory store)。
直觉上,Attention 层负责确定"现在这个位置应该关注什么类型的信息",而 FFN 层负责"根据这个类型,检索和处理相应的知识"。
这就是为什么 FFN 的中间维度通常是 Attention 维度的 4 倍甚至更多——它需要足够的容量来存储和处理大量的"隐性知识"。
有研究表明,一些具体的事实性知识(比如"巴黎是法国的首都")可以被定位到特定 FFN 层的特定神经元。这说明 FFN 不只是在做特征变换,还在进行某种形式的"知识存储"。
14. LayerNorm + Residual:训练为什么不会崩?
残差连接(Residual Connection)
公式:output = x + f(x)
为什么这个简单的加法操作,对深度网络至关重要?
想象没有残差连接的 96 层网络。梯度在反向传播时,每经过一层都要乘以一个雅可比矩阵。96 次相乘之后,梯度要么变成 0(梯度消失),要么爆炸到无穷大——两种情况都会让训练完全失败。
残差连接提供了一条"梯度高速公路":梯度可以直接通过跳跃连接流回早期层,不需要经过 f(x) 的变换。这让梯度传播变得稳定,使得 100+ 层的网络可以被正常训练。
另一个直觉:残差连接让网络学的是"残差"(需要修正的部分),而不是"全量变换"。如果某一层的变换不必要,它可以学成恒等映射(f(x) → 0),让输入直接通过。这降低了每层的学习难度。
Layer Normalization
LayerNorm 对每个 token 的向量做归一化(减去均值,除以标准差),使得数值保持在合理范围内。
为什么需要归一化?因为随着网络加深,向量的数值分布会漂移,导致后续层的 Attention 计算出现数值不稳定问题。LayerNorm 把分布"拉回"标准化状态,让每一层都能在稳定的数值范围内工作。
现代 LLM(如 LLaMA)通常把 LayerNorm 放在 Attention 和 FFN 之前(Pre-Norm),而不是之后(Post-Norm),这进一步改善了训练稳定性。
第六部分:模型是怎么学会语言的?
15. 训练目标:为什么"预测下一个词"就够了?
这是整个 LLM 领域最深刻的洞见之一,值得认真思考。
信息论视角:
Shannon 的信息论告诉我们,一个信息源的"熵",等于从该信息源完美预测下一个符号所需要的平均比特数。
换句话说:如果你能完美预测下一个词,你就完全理解了这个信息源的统计结构。
语言是一个极其复杂的信息源。为了完美预测下一个词,模型需要学会:
- 语法规则(“is” 后面跟动名词还是原型?)
- 语义关系(“法国的首都"后面最可能是"巴黎”)
- 世界知识(“爱因斯坦发现了___“后面是相对论相关的内容)
- 文体风格(学术论文的下一句和微博的下一句截然不同)
- 逻辑推理(前提铺垫之后,合理的结论是什么?)
所有这些,都被这一个训练目标隐含地涵盖了。这就是为什么"预测下一个词"看似简单,实则是一个极其通用和强大的学习信号。
16. Loss 函数到底在优化什么?
LLM 的训练损失是交叉熵(Cross-Entropy)。
不用记公式,理解直觉:
模型对每个位置输出一个概率分布,表示"下一个 token 是词表中每个词的概率”。如果词表有 50000 个词,那就是一个 50000 维的概率向量。
训练的目标是:让真实 token(ground truth)对应的概率尽可能高,其他 token 的概率尽可能低。
交叉熵的计算方式是:取真实 token 的概率的负对数。如果真实 token 概率很高(接近 1),负对数接近 0(损失小);如果概率很低(接近 0),负对数趋向无穷(损失大)。
整个训练就是在最小化这个损失:让模型在每个位置,对真实下一个 token 的预测概率越来越高。
17. Scaling Law:为什么模型越大越聪明?
2020 年,OpenAI 发表了一篇奠基性论文,揭示了 LLM 的幂律缩放定律(Scaling Laws):
模型在语言建模任务上的性能(用 loss 衡量),与参数量 N、训练数据量 D、计算量 C 之间,存在可预测的幂律关系。
直觉解释:
- 更多参数:更大的 FFN 层 = 更多可以存储的"隐性知识”;更宽的 Attention = 更高维的语义表示空间
- 更多数据:更丰富的语言分布统计 = 更少的泛化误差
- 更多计算:参数被更充分地更新,收敛到更好的局部最优
关键洞见:这三者之间存在最优比例关系(Chinchilla 定律)。粗略来说:参数量翻倍时,训练数据量也应该翻倍,才能充分利用模型容量。早期很多模型(包括 GPT-3)其实是"过大欠训"(参数很多但训练数据相对不足)的。
为什么这改变了世界?
因为这意味着模型性能是可预测的、可工程化的。你不需要靠运气找到好的架构——只要把三个旋钮(参数、数据、计算)按比例调大,性能就会按规律提升。这让 LLM 的研发从"科学探索"变成了"工程建设"。
第七部分:推理时到底发生了什么?
18. 生成过程逐步拆解(token by token)
假设输入是:"The capital of France is"
模型怎么生成下一个词?
步骤一:前向传播
把输入 tokenize,每个 token 经过 Embedding + Position Encoding,然后通过所有 Transformer Block,最终得到最后一个 token("is")的输出向量。
步骤二:Language Model Head
把输出向量乘以词表矩阵(本质上是 Embedding 层的转置),得到词表上的 logits 向量(50000 维)。
步骤三:Softmax
把 logits 转换为概率分布。
步骤四:采样
从概率分布中选取下一个 token(比如 "Paris")。
步骤五:自回归循环
把 "Paris" 拼接到输入序列末尾,重复上述过程,生成下一个 token(比如 ".")。
如此往复,直到生成终止 token 或达到最大长度。
关键点:每次生成一个 token,都需要对整个(到目前为止的)序列做一次完整的前向传播。如果没有优化,这会极其低效。
19. KV Cache:为什么推理可以加速 10x?
上面提到,每次生成新 token 时,需要对整个序列做前向传播。但仔细想想——对于已经处理过的 token,它们的 Key 和 Value 向量(Attention 计算中用到的)其实不会改变!
(因为 Causal Mask,每个已有 token 的 Attention 结果不依赖于未来的 token)
KV Cache 的原理:把每一层 Attention 计算出的 Key 和 Value 向量缓存起来,下次生成新 token 时,只需要:
- 对新 token 计算它的 Q、K、V
- 用新 token 的 Q,与缓存的所有历史 K 做 Attention
- 用 Attention 权重,对缓存的所有历史 V 做加权求和
不需要重新计算历史 token 的 K、V——这些计算量占了推理的绝大部分。
效果:理论上,推理速度从 O(n²) 降到了近似 O(n)(n 是序列长度),实际加速可以达到 10x 甚至更多。
代价:KV Cache 需要存储每一层、每个 token 的 K 和 V 向量,内存占用巨大。对于长上下文(128K token)的大模型,KV Cache 本身就可能占用数十 GB 内存。这是现代 LLM 推理的主要内存瓶颈。
20. 采样策略:模型"性格"的来源
为什么同一个模型,有时输出非常保守,有时输出天马行空?
这取决于采样策略。
Greedy Decoding(贪心解码):
每次选择概率最高的 token。
特点:确定性、可复现,但输出往往单调、重复。极端情况下会陷入循环(“这是最好的,这是最好的,这是最好的……")。
Temperature(温度采样):
在 softmax 之前,把 logits 除以一个"温度"参数 T。
- T < 1(低温):概率分布变得更尖锐,高概率 token 更容易被选中,输出更保守、更可预测
- T > 1(高温):概率分布变得更平坦,低概率 token 也有机会被选中,输出更随机、更多样
- T = 1:原始分布
Temperature 就是调节"模型性格"的旋钮:低温=谨慎,高温=放飞自我。
Top-p(Nucleus Sampling):
不是限制候选数量,而是限制候选集合的累积概率。
具体做法:按概率从高到低排列所有 token,找到使累积概率刚好超过 p(比如 0.9)的最小 token 集合,从这个集合中采样。
好处:动态调整候选集大小——当模型非常确定时(一个词的概率就超过了 0.9),只在极小的候选集里选;当模型不确定时(需要很多词才能累积到 0.9),有更广泛的选择空间。
为什么模型有时"发散”?
高 Temperature + 不当的 top-p 设置 + 某些触发条件,可能让模型进入"高熵状态"——每步都选择了低概率 token,导致上下文越来越偏离,模型试图"圆场"时反而越跑越远。这就是"模型发散"的本质。
第八部分:现代 LLM 的进化方向
21. 长上下文问题:为什么 Transformer 很贵?
Self-Attention 的计算量和内存占用,与序列长度 n 的平方成正比——这就是著名的 O(n²) 问题。
为什么是 n²?
因为 Attention 要计算序列中每对 token 之间的相关性。n 个 token 就有 n² 个 token 对,每个 token 对需要一次向量点积计算。
对于短序列(n=2048),这还可以接受。但当 n=128000(现代长上下文模型的目标),计算量是 (128000)² = 1.6 × 10¹⁰,内存占用是 128K × 128K 的矩阵——在所有层上叠加,这是无法承受的数字。
这就是 Transformer 扩展到超长上下文的核心瓶颈。
22. 各种优化思路
Sparse Attention(Longformer / BigBird)
核心思想:不是让每个 token 关注所有其他 token,而是只关注:局部窗口内的 token + 少量全局 token + 随机采样的 token。
效果:把计算复杂度从 O(n²) 降到 O(n),代价是可能错过一些远距离的重要联系。
Linear Attention
将 Attention 的计算重新组合,利用矩阵运算的结合律,把 O(n²) 降到 O(n)。
技术上是可行的,但现实中 Linear Attention 的表现通常不如标准 Attention——它牺牲了一定的表达能力来换取效率。这是一个活跃的研究领域。
MoE(Mixture of Experts,混合专家)
这是一个完全不同的思路:与其增大模型密度(让所有参数对每个 token 都激活),不如增大模型总参数量,但每次只激活其中一小部分(“专家”)。
比如 GPT-4 据传是 MoE 架构,总参数量约 1.8T,但每次推理只激活约 220B 的参数。
好处:用更少的计算量(FLOPs),获得更大模型的性能。
代价:路由机制复杂,训练稳定性要求高,推理时仍需加载全部参数(内存需求未减少)。
23. 新架构挑战者
Mamba(SSM 系列)
Mamba 基于状态空间模型(State Space Model),用一个"选择性"的循环机制代替 Self-Attention。
核心优势:推理时的计算复杂度是 O(n)(每步只需更新固定大小的状态),内存占用不随序列增长而增长。
对于超长上下文(百万 token 级别),Mamba 理论上有显著优势。
现实挑战:目前,Mamba 在大规模训练和性能上仍落后于同量级的 Transformer,尚未证明能够完全替代。
RWKV
RWKV 尝试结合 RNN 的推理效率和 Transformer 的训练并行性——训练时像 Transformer(并行),推理时像 RNN(线性)。
挑战与 Mamba 类似:在最强性能上,目前仍难以匹敌顶级 Transformer。
结论:Transformer 的地位目前非常稳固。挑战者存在,但尚未证明自己。这个领域在快速演化,未来三年可能会有实质性的架构变化。
第九部分:模型内部到底学了什么?
24. Attention 可视化:模型在"看哪里"?
通过提取各层 Attention 权重矩阵并可视化,研究者发现了很多有趣的模式:
- 浅层:倾向于关注相邻 token(局部依存关系,类似 n-gram)
- 中间层:出现语法相关的模式(动词关注其论元,代词关注指代对象)
- 深层:更抽象的语义关系,以及与任务目标相关的模式
一个经典发现:在处理"The animal didn’t cross the street because it was too tired"时,对应"it"的 Attention head 会将注意力集中在"animal"上,正确解析了指代关系。这种模式在不同模型、不同规模中都能重现,说明 Transformer 确实学到了一些语言学意义上的结构。
但要小心过度解读:Attention 权重并不直接等于"重要性",它是信息路由的权重,不是因果解释。
25. Logit Lens:中间层在说什么?
Logit Lens 是一个优雅的分析工具。
想法:把每一个中间层的输出向量,直接通过 Language Model Head 解码成 token 概率分布,看看"模型在这一层的输出,如果直接生成,会说什么"。
发现:
- 最初几层:输出的 token 几乎是随机的,没有语义
- 中间层:开始出现合理但粗糙的预测(比如正确的语义类别)
- 后面几层:预测越来越精准,最终与实际输出一致
这说明模型是在逐层精化语义表示——不是在某一层突然"顿悟",而是每一层都在对表示做一次小幅度的修正和改进。
这个视角支持了一个重要观点:Transformer 的深度不只是为了"更多计算",而是为了"多轮语义精化"。
26. 模型有没有"理解"?(批判性讨论)
这是 AI 领域最有争议的问题之一。让我们用更精确的方式来讨论它。
支持"有理解"的证据:
- 模型能够完成需要多步推理的任务(数学证明、代码调试)
- 在没有见过的领域组合上能够泛化(将医学知识和法律知识结合应用)
- 语义表示空间具有组合性(King - Man + Woman ≈ Queen 之类的关系)
- Attention 模式对应语言学结构(见上)
反对"真正理解"的证据:
- 分布外脆弱性:对输入做微小的语义无关修改(改变词序、添加无关短语),模型有时会给出完全不同的答案
- 逻辑一致性问题:模型对同一问题的不同表述,有时给出矛盾的答案
- 无世界模型:模型没有独立于语言的感知和行动能力,所有"理解"都是语言内的统计关系
- 幻觉问题:模型会自信地生成错误信息,这表明它并不"知道自己知道什么"
更准确的描述:
LLM 学到的是一种语言的统计结构映射——它能非常精准地模拟"一个博学之人在各种情境下会说什么"。这种模拟在很多情况下和"理解"在功能上等价,但在机制上有本质不同。
用 John Searle 的"中文房间"思想实验来说:LLM 可能是一个极其精密的"中文房间"。但这个"房间"足够大时,“理解"和"完美的功能性模拟"之间的实践区别,也许比我们以为的要小。
这个问题没有确定答案,而且可能无法用现有的哲学框架解答。
第十部分:实践
27. 用 PyTorch 写一个最小 Transformer
只保留核心逻辑,去掉所有工程噪音:
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
class MultiHeadAttention(nn.Module):
def __init__(self, d_model, n_heads):
super().__init__()
assert d_model % n_heads == 0
self.d_k = d_model // n_heads
self.n_heads = n_heads
# Q, K, V 投影矩阵
self.W_q = nn.Linear(d_model, d_model, bias=False)
self.W_k = nn.Linear(d_model, d_model, bias=False)
self.W_v = nn.Linear(d_model, d_model, bias=False)
self.W_o = nn.Linear(d_model, d_model, bias=False)
def forward(self, x, mask=None):
B, T, C = x.shape # batch, seq_len, d_model
# 投影并分成多个头
Q = self.W_q(x).view(B, T, self.n_heads, self.d_k).transpose(1, 2)
K = self.W_k(x).view(B, T, self.n_heads, self.d_k).transpose(1, 2)
V = self.W_v(x).view(B, T, self.n_heads, self.d_k).transpose(1, 2)
# 现在 Q/K/V 的形状: (B, n_heads, T, d_k)
# Attention 计算
scores = Q @ K.transpose(-2, -1) / math.sqrt(self.d_k) # (B, n_heads, T, T)
# Causal mask(只看左边)
if mask is not None:
scores = scores.masked_fill(mask == 0, float('-inf'))
attn = F.softmax(scores, dim=-1)
# 加权聚合
out = attn @ V # (B, n_heads, T, d_k)
out = out.transpose(1, 2).contiguous().view(B, T, C) # 拼接所有头
return self.W_o(out)
class TransformerBlock(nn.Module):
def __init__(self, d_model, n_heads, d_ff):
super().__init__()
self.attn = MultiHeadAttention(d_model, n_heads)
self.ffn = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.GELU(),
nn.Linear(d_ff, d_model)
)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
def forward(self, x, mask=None):
# Pre-Norm + 残差连接
x = x + self.attn(self.norm1(x), mask)
x = x + self.ffn(self.norm2(x))
return x
class MiniGPT(nn.Module):
def __init__(self, vocab_size, d_model=256, n_heads=8, n_layers=6,
d_ff=1024, max_seq_len=512):
super().__init__()
self.embedding = nn.Embedding(vocab_size, d_model)
self.pos_embedding = nn.Embedding(max_seq_len, d_model)
self.blocks = nn.ModuleList([
TransformerBlock(d_model, n_heads, d_ff) for _ in range(n_layers)
])
self.norm = nn.LayerNorm(d_model)
self.lm_head = nn.Linear(d_model, vocab_size, bias=False)
# 构建 Causal Mask
self.register_buffer(
'mask',
torch.tril(torch.ones(max_seq_len, max_seq_len)).view(1, 1, max_seq_len, max_seq_len)
)
def forward(self, idx):
B, T = idx.shape
# Token + 位置 Embedding
x = self.embedding(idx) + self.pos_embedding(torch.arange(T, device=idx.device))
# 通过所有 Transformer Block
mask = self.mask[:, :, :T, :T]
for block in self.blocks:
x = block(x, mask)
x = self.norm(x)
# 输出 logits
return self.lm_head(x) # (B, T, vocab_size)
# 使用示例
model = MiniGPT(vocab_size=50257) # GPT-2 词表大小
x = torch.randint(0, 50257, (2, 128)) # batch=2, seq_len=128
logits = model(x)
print(f"输出形状: {logits.shape}") # torch.Size([2, 128, 50257])
# 计算语言建模 Loss
targets = torch.randint(0, 50257, (2, 128))
loss = F.cross_entropy(logits.view(-1, 50257), targets.view(-1))
print(f"Loss: {loss.item():.4f}")
代码量不到 80 行,但包含了 Transformer 的所有核心组件:Multi-Head Attention、Causal Mask、Feed-Forward、LayerNorm、Residual Connection、自回归语言模型头。
28. 用 Hugging Face 拆一个 GPT
from transformers import GPT2Model, GPT2Tokenizer
import torch
# 加载模型和 tokenizer
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2Model.from_pretrained('gpt2', output_attentions=True, output_hidden_states=True)
model.eval()
# 准备输入
text = "The capital of France is"
inputs = tokenizer(text, return_tensors='pt')
# 前向传播
with torch.no_grad():
outputs = model(**inputs)
# 分析输出结构
hidden_states = outputs.hidden_states # 所有层的隐状态
attentions = outputs.attentions # 所有层的注意力权重
print(f"层数: {len(hidden_states)}") # 13 (embedding + 12 layers)
print(f"每层形状: {hidden_states[0].shape}") # (1, seq_len, 768)
print(f"Attention 头数: {attentions[0].shape[1]}") # 12
# 可视化最后一层的 Attention
import matplotlib.pyplot as plt
import seaborn as sns
tokens = tokenizer.convert_ids_to_tokens(inputs['input_ids'][0])
last_layer_attn = attentions[-1][0].mean(dim=0) # 对所有 head 取平均
plt.figure(figsize=(8, 6))
sns.heatmap(
last_layer_attn.numpy(),
xticklabels=tokens,
yticklabels=tokens,
cmap='Blues'
)
plt.title("Last Layer Attention (Head Average)")
plt.tight_layout()
plt.show()
# 用 Logit Lens 分析中间层
from transformers import GPT2LMHeadModel
lm_model = GPT2LMHeadModel.from_pretrained('gpt2', output_hidden_states=True)
lm_model.eval()
with torch.no_grad():
lm_outputs = lm_model(**inputs)
# 把每个中间层的 hidden state 解码成 token
print("\n=== Logit Lens 分析 ===")
for layer_idx, hidden in enumerate(lm_outputs.hidden_states):
# 直接用 LM head 解码中间层
logits = lm_model.lm_head(lm_model.transformer.ln_f(hidden))
pred_token = tokenizer.decode(logits[0, -1].argmax())
print(f"Layer {layer_idx:2d}: 预测下一词 = '{pred_token}'")
运行这段代码,你会看到:
- Layer 0-2:预测几乎是随机的(比如 “Paris” 可能是 “London” 或 " a”)
- Layer 5-8:开始出现语义上合理的预测(地名、国家相关词)
- Layer 10-12:越来越接近正确答案 “Paris”
这就是"逐层语义精化"的直观证明。
结语:Transformer 为什么改变世界?
29. 它真正的突破是什么?
Transformer 的诞生,表面上是一个更好的 NLP 模型。但它真正的突破,在于两件事:
第一:可扩展性(Scalability)
Transformer 的设计,在工程上极其适合扩展:
- Self-Attention 和 FFN 可以完全并行化,完美匹配 GPU 的计算范式
- 层数、宽度、头数可以独立增加,性能预测性好(Scaling Law)
- 训练目标(预测下一个 token)可以从互联网上无限获取训练数据
这意味着:只要投入更多的计算资源,性能就会可预测地提升。这是一种"工业化"的 AI 研发范式,让大公司的工程能力成为了核心竞争力。
第二:通用表示学习(Universal Representation Learning)
Transformer 在预测下一个 token 的过程中,被迫学习了语言中几乎所有的结构——语法、语义、逻辑、世界知识、推理模式……
这些表示不是针对某个特定任务设计的,而是通用的。同一个预训练模型,通过 fine-tuning(甚至仅仅通过 prompting),可以应用到翻译、摘要、代码生成、数学推理、对话、创作……
这就是"基础模型"(Foundation Model)概念的核心:一个大规模预训练模型,是整个 AI 应用栈的基础设施,而不是一个特定任务的解决方案。
30. 它的局限 & 下一步
诚实地说,Transformer 并非没有根本性的局限。
长上下文的代价
O(n²) 的 Attention 计算,使得超长上下文(百万 token 级别)在计算上极其昂贵。目前的各种优化(Sparse Attention、FlashAttention、RoPE 外推等)只是在工程上缓解,没有从根本上解决问题。当上下文窗口扩展到极限时,模型的"注意力稀释"问题(无法同时关注超长上下文中所有重要信息)也是一个悬而未决的挑战。
推理成本
运行一个顶级 LLM 的边际成本,远超一次搜索引擎查询。当 AI 被嵌入到日常工作流的每一个环节,推理成本将成为一个严肃的经济和能源问题。
真正的推理能力
目前的 LLM 在复杂多步推理上仍不稳定。CoT(Chain of Thought)提示大幅改善了表现,但这更像是让模型"工作步骤可见从而减少错误",而非真正实现了可靠的符号推理。o1/o3 等模型的出现(通过在推理时花更多计算)是一个有趣的方向,但可能也只是更复杂的 token 预测,而非架构上的突破。
是否会被替代?
Mamba、RWKV、线性 Attention 等架构在特定场景下展示了潜力,但到目前为止,没有一个能在相同规模下全面超越 Transformer。更可能的未来是混合架构——将 Transformer 的表达能力与循环模型的推理效率结合起来。
最后的思考
我们开头问了一个问题:ChatGPT 真的理解语言吗?
读到这里,你应该有了自己的判断。
它学到的不是人类意义上的"理解",而是一种深度的统计结构映射——从人类书写的海量文本中,提炼出语言的形式规律、知识模式和推理框架,压缩进数百亿个参数里。
这种压缩,在功能上极其强大,以至于在很多任务上可以模拟出"理解"的效果。但这与人类的认知有根本的不同——人类的理解是具身的、因果的、有意图的;LLM 的理解是统计的、关联的、无意图的。
Transformer 改变世界,不是因为它创造了人工智能,而是因为它创造了一种前所未有的、能够大规模编码和利用人类知识的技术路径。
这条路通向哪里,仍然是一个开放的问题。
但理解这条路是如何走出来的,是我们每个技术人的必修课。