Transformer内部结构
整个 NLP 的发展,中间还经历很多很多重要的阶段,例如:
- 神经概率语言模型
- 卷积神经网络模型
- 循环神经网络以及长短期记忆网络
再到目前最为流行的 Transformer 架构。
输入和输出
将 LLM 看作是一个黑盒:输入称之为提示词(Prompt)。
在使用模型的时候,模型并不是一次性生成所有的文本,而是一次生成一个词元。如下图所示:
模型在生成每一个新词元时,都会基于当前的输入序列进行一次前向传播(Forward Propagatio)。
所谓前向传播,是指在神经网络中,从输入层开始,数据依次通过每一层神经元的计算,最终产生输出的过程。
具体步骤:
- 输入嵌入。
- 多个神经网络层处理。
- 输出一个分布,就是所有词元的一个概率。
- 选一个词生成出来。
而新生成的词元会被追加到输入序列的末尾,作为下一步生成的提示词上下文,从而逐步影响整个输出。
在机器学习中,有一个专门的词用来描述这种使用早期预测来进行后续预测的模型,称之为自回归模型。Transformer 模型就是一个自回归模型。
LLM架构
整体来讲分成四大块:
分词器
模型的第一步是将自然语言输入送入分词器(Tokenizer),将其转换为词元 ID(token IDs)。例如:
我今天很开心
分词后:
['我', '今天', '很', '开', '心']
映射为词表中的词元 ID:
[1, 354, 2764, 77, 199]
嵌入层
在分词器将文本转换为词元 ID 之后,这些整数 ID 本身并不能直接用于神经网络计算。此时,需要通过嵌入层将每个 ID 映射为一个向量,形成模型的输入表示。
例如前面得到的词元 ID 列表:
[1, 354, 2764, 77, 199]
通过嵌入层处理后,得到的嵌入向量:
[
[0.12, -0.87, ..., 0.34], # 对应 token 1
[0.02, 0.45, ..., -0.11], # 对应 token 354
...
[0.76, -0.01, ..., 0.08] # 对应 token 199
]
每个词元 ID 都会被映射为一个固定维度的向量(例如 768 维或 4096 维),这些向量是模型可学习的参数,在训练过程中会被不断优化。
Transformer层
Stacked Transformer Blocks,这些 Transformer 块是 LLM 的核心模块,也是模型理解上下文、捕捉语言结构和语义关系的关键所在。
每个 Transformer 块内部包含两个主要子模块:
-
自注意力机制(Self-Attention):让每一个词元可以“看见”它前面的所有词元,从而理解上下文。
“我 今天 很 开心”
↑ ↑ ↑ ↑
每个词元都能关注到前面的词元(因自回归模型只看左边)- 比如模型在预测“开心”时,会去关注“我”、“今天”、“很”这些词,理解语义关系。
- 注意力机制会为不同词元分配不同的权重。
-
前馈网络(Feed-Forward Network):对每个位置上的词元向量单独做非线性变换,提高模型表达能力。
为什么称之为堆叠呢?
因为 Transformer 块并非一层,而是有多层:
Transformer块1 → Transformer块2 → Transformer块3 → Transformer块4 → ...
每一层都会接收上一层的输出,并进一步处理。层数越多,大模型就越能够捕捉高层次、复杂的语言结构,也就是说,对输入的文本理解得越准确。
下表是主流大模型的层数对比:
| 模型名称 | 参数规模 | Transformer 层数 | 备注 |
|---|---|---|---|
| GPT-2 (small) | 117M | 12 | OpenAI |
| GPT-3 | 175B | 96 | OpenAI |
| GPT-4 (推测) | ~200B+ | 96–128(估计) | 可能为 MoE 架构 |
| Claude 2 | ~100B+ | ~80–100(推测) | Anthropic,未公开完整细节 |
| Claude 3 Opus | 未知 | ~128(推测) | 有极强编码能力,多模态支持 |
| PaLM 2 | 340B | 120 | |
| Gemini 1.5 Pro | 推测 >100B | 未知 | 多模态,长上下文(>1M tokens) |
| LLaMA 2 (7B) | 7B | 32 | Meta,小模型中非常高效 |
| LLaMA 2 (70B) | 70B | 80 | Meta |
| Mistral (7B) | 7B | 32 | Dense 模型,训练非常高效 |
| Mixtral (MoE) | 12.9B act. | 32 | 激活 2/8 experts(MoE 架构) |
语言建模头
经过多层 Transformer 块处理后,会得到每一个位置上的一个高维向量表示。这些向量已经融合了上下文语义信息,接下来需要通过语言建模头(Language Modeling Head)将这些向量转换为我们最终关心的输出:预测下一个词元。
在自回归生成中,只用最后一个词元位置上的向量来预测下一个词。
[
[0.12, -0.87, ..., 0.34], ← 代表“我”
[0.45, 0.10, ..., -0.77], ← 代表“今天”
[-0.22, 0.63, ..., 1.02] ← 代表“很”
]
为什么只用最后一个词?
Transformer 是一个上下文感知的结构。当我们输入“我今天很”,并经过多层 Transformer 处理后,虽然只取了最后一个词“很”对应的向量,但这个向量已经不是孤立的“很”了,它已经通过自注意力机制,融合了前面所有词元的信息,即“我”、“今天”、“很”的上下文。
工作流程
假设有一个词表(语料库)大小为 V = 50,000,Transformer 输出的每个向量是 d = 768 维,那么,语言建模头就是一个维度为:
[768 × 50000]
的线性变换矩阵,这个矩阵是语言建模头的核心参数,也是参数量最多的一层之一。这里我们把这个矩阵命名为 W。
接下来下一步是针对 词表 里面的每一个词元(50000)进行打分,大致的计算公式如下:
logits(最终的得分) = z(最后一个词元的向量) · W(线性矩阵)
- z:Transformer 所输出的最后一个词元的嵌入向量,长度为 768。
- W:上面所提到的线性变换矩阵。
经过计算后,会得到一个 50000 维的向量数组。这个 50000 维的向量数组里面的每一个值就是词表中词元的得分。
这个分数仅仅是一个未归一化的分数,所谓未归一化,就是指这些分数可以是任何实数(正的、负的、不限制范围),它们还不是概率,还不能直接表示“可能性”。例如假设我们的词表只有 5 个词,这里就能得到词表中每个词元的分数
| 词元 | logits 值 |
|---|---|
| 开心 | 4.2 |
| 累 | 2.7 |
| 忙 | 1.5 |
| 昨天 | -1.2 |
| 小狗 | -3.5 |
最后一步是经过 softmax 转换,目的是将分数转换为概率分布,计算公式如下:
\text{softmax}(logits_i) = \frac{e^{logits_i}}{\sum_{j=1}^{n} e^{logits_j}}
整个 softmax 接收上一步拿到的 logits,然后做了两件事:
- 先对每个值取指数(确保变成正数)
- 再除以总和(确保总和为 1)
最终,语言建模头工作流程大致如下:
z = Transformer_output[-1] # 取最后一个向量
logits = z · W # [0.1, 0.3, -1.5, 2.6, ...]
probs = softmax(logits) # [0.01, 0.02, 0.00001, 0.85, ...]
完整流程
假设当前输入的是一句未完成的话:
我今天很
目标是让大语言模型预测下一个最可能的词元。
整体流程:
1. 分词器处理
["我", "今天", "很"]
[1, 354, 2764]
2. 嵌入层处理
每个词元 ID 会被映射为高维度向量
“我” → [0.12, -0.87, ..., 0.34]
“今天” → [-0.11, 0.45, ..., 0.90]
“很” → [0.20, 0.14, ..., -0.06]
嵌入向量会形成一个二维数组,维度是 [3, 768]。
3. Transformer块处理
经过多层 Transformer 块处理之后,得到的仍然是一个维度为 [3, 768] 的向量数组.
只取最后一个
z = [0.12, -0.45, ..., 0.33] ← 长度为 768
虽然这个 z 只是 “很” 这个词元所对应的向量,但是融入了前面词元的意思
4. 语言建模头计算 logits
假设语料库里面的词元数量为 50000
logits = z × W → 得到一个 [1 × 50000] 的向量
logits = [0.9, -1.3, 2.1, ..., 5.7] ← 长度为 50000
5. softmax 归一化为概率
{
开心: 0.61,
累: 0.12,
忙: 0.08,
郁闷: 0.04,
美丽: 0.02,
...
}
解码策略
根据概率选择词元的方法被称之为解码策略(decoding strategy)。
贪婪策略
每一步都选择当前概率最大的词元作为下一个输出,不考虑后续潜在可能性。
例如当前上下文是:“我今天很”,模型输出的 softmax 概率如下:
{
开心: 0.61,
累: 0.12,
忙: 0.08,
美丽: 0.04,
...(共 50000 个词)
}
如果使用贪婪策略解码,下一词 = 选择概率最大的词 = “开心”
贪婪策略简单、易实现、速度快,但缺乏多样性,同样的输入每次都会得到同样的输出,容易陷入局部最优。
采样策略
采样策略是在每一步生成时,不总是选概率最大的词,而是根据 softmax 概率分布进行随机抽样,这样每次生成可能都不一样,增强语言多样性。
例如上面的 softmax 输出为:
{
开心: 0.61,
累: 0.12,
忙: 0.08,
美丽: 0.04,
...(共 50000 个词)
}
那么会根据概率随机抽一个:
- 可能是“开心”(61%)。
- 也可能是“累”(12%)。
- 有小概率是“美丽”(4%)。
采样策略的核心思想是:不是总选最有可能的那个词,而是让**可能性高的词更有可能被选中*,但不是唯一结果。
采样策略多样性高、更自然,但不可控,有时会胡说八道。
温度系数
在采样策略中,可以引入一个温度系数(Temperature) 来控制 softmax 概率分布的陡峭程度,影响模型的随机性与确定性。
默认 softmax 的计算方式如下:
probs = softmax(logits) // 将分数转为概率
加入温度 T 后,变为:
probs = softmax(logits / T)
- T 是一个正数(一般取值 0.5 ~ 2)
- logits 除以 T 后,整个分布会变化
| 温度 T | 分布特征 | 解码表现 |
|---|---|---|
| T < 1 | 更尖锐 | 更偏向高概率词 |
| T = 1 | 原始分布 | 标准采样 |
| T > 1 | 更平坦 | 更倾向随机、多样化 |
示例说明
仍以上面的 logits 为例:
{
开心: 4.2,
累: 2.7,
忙: 1.5,
昨天: -1.2,
小狗: -3.5
}
不同温度下的行为:
- T = 1:开心(61%)仍最可能,但其他词有较低概率。
- T = 0.5:开心更具压倒性优势(例如 >80%)。
- T = 2.0:其他词概率显著提升,分布变“平”。
温度越低,越倾向于选择高概率的词,温度越高,越倾向于选择其他词。
- 想生成稳定、一致性强的结果 → 使用低温度(如 T = 0.7)。
- 想生成有创意、更多样的结果 → 使用高温度(如 T = 1.5)。
总结一句话:温度系数是控制生成文本“保守”还是“放飞”的旋钮。
其他解码策略
除了贪婪策略和采样策略,还有一些常用的高级解码方式:
| 策略 | 每一步做什么 | 效果 |
|---|---|---|
| 贪婪解码 | 选概率最大 | 单一、重复、稳定 |
| 采样(随机) | 根据概率随机选一个词 | 多样、有趣但不稳定 |
| Top-k | 只在概率前 k 名中随机选 | 控制随机性 + 保留合理选项 |
| Top-p(nucleus) | 在累计概率 > p 的词中随机选 | 更智能的采样策略 |
| Beam Search | 保留多个候选句分支并评分 | 更接近全局最优但计算更贵 |
Transformer块
整个大语言模型就是由一系列 Transformer 块组成的。每个块处理其输入,然后将处理结果传递给下一块。
在原始的 Transformer 论文中约为 6 块,现在许多 LLM 中已经超过 100 个了。
每个 Transformer 块由以下两首首尾相接的组件构成:
- 自注意力层
- 前馈神经网络层
自注意力层
注意力机制帮助模型在处理特定词元的时候 整合上下文信息。
狗追猫,因为它
为了预测“它”之后的内容,模型需要知道“它”指代的是什么,是“狗”还是“猫” ?
注意力机制会将上下文信息添加到“它”这个词元的表示中。
工作原理
注意力机制会为“它”这个词元计算它与句子中所有其他词元的关联程度。
- 它会算出“它”和“狗”有多相关。
- “它”和“猫”有多相关。
- 甚至“它”和“追”“因为”等词之间的关系。
这些相关性通过一个叫做“注意力权重”的分数来表示,相关性越高,注意力分数越大。
下图是另外一段英文提示词文本
The cat sat on the mat
在自注意力层所生成的权重矩阵图:
- 横轴(Key):表示被关注的词,即“被看的对象”。
- 纵轴(Query):表示当前在处理的词,即“正在看别人的词”。
- 单元格中的值:表示 Query 对应的词对 Key 的关注程度(注意力权重),数值越大,颜色越深。
图中 sat → The 的注意力值是 0.23,意味着在处理 “sat” 这个词时,模型“最关注”的词之一是 “The”;cat → on 的注意力值是 0.21,表示 “cat” 在编码时也部分关注了 “on”。
回到我们上面“狗追猫”的例子,假设注意力机制得出以下权重:
"它" 对每个词的注意力权重:
狗:0.3
猫:0.6
其他词:0.1
模型“认为”——“它”更可能指的是“猫”。
那么模型可能就会生成诸如“它吓倒了狗”的后续内容。
核心:当前词会去关注其它词,并且根据相关性分配权重,从而形成更有语境感知的一个表达。
多头注意力
所谓多头注意力,指的是模型不只使用一个注意力机制去“看”上下文,而是使用多个注意力头(head),每个从不同的角度并行地关注输入中的不同部分。
一个注意力头只关注一套特定的关系(比如“它”和“狗、猫”之间的关系),但现实语言中的语义很复杂:
- 有的头可能专注于语法(主语-动词关系);
- 有的头可能关注指代(“它”指代谁);
- 有的头可能关注情感、时间顺序等……
多头注意力可以让模型从多个“子空间”中提取信息,从而提升理解力和泛化能力。
狗追猫,因为它
假设有三个注意力头,它们分别学习到了不同的关注模式:
- Head 1:指代消解视角 —— “它”主要关注“猫”,注意力权重为:猫 0.6,狗 0.3,其它词 0.1;
- Head 2:句法结构视角 —— “它”关注“追”这个动词,理解句子动作逻辑;在这个头中,“追”的相关性得分最高
- Head 3:逻辑关系视角 —— “它”关注“因为”,模型试图理解因果结构。在这个头中,“因为”的相关性得分最高
这些注意力头会各自生成一份“它”的表示,最后再把这些表示合并起来,形成一个更加丰富、综合的向量。这个向量同时融合了:
- 谁是“它”可能指代的对象,
- “它”参与了什么样的动作,
- “它”在语义上处于怎样的逻辑位置。
- .....
“它”所对应的向量的含义背后的语义就非常丰富了。这也是为什么前面说 LLM 只需要取最后一个词元来预测下一个词。
这就像一个小型“专家团队”,每个注意力头都是一个“专家”,专门从某种语言视角来理解当前词元。最终,它们的意见会被整合,让模型拥有更全面的判断力。
前馈神经网络层
自注意力机制让每个词元在上下文中“看别人”,整合其他词的信息。但仅靠这些信息还不够,Transformer 还需要进一步让每个词自己思考、提炼、变换。这个任务,就交给了前馈神经网络层(Feed Forward Neural Network,简称 FFN)。
前馈神经网络的特别之处在于:它不会“看别人”,只处理自己。
怎么处理?
它是对每一个词元单独做的一次变换处理。你可以理解为:自注意力层结束后,每个词元都从“他人”那里学到了不少内容;接下来轮到它自己好好消化一遍。
如何消化?
其实就是把词元当前的表示向量送入一个小型的神经网络中,通常会包含两层线性变换和一个非线性激活函数,流程如下:
输入 → 线性变换(升维) → 激活函数 → 线性变换(降维) → 输出
再具体一点的话,这一过程可以用公式表示为:
FFN(x)=GELU(xW1+b1)W2+b2
其中 GELU 是一种激活函数,负责加入“非线性思考能力”。
例如:
狗追猫,因为它
在经过自注意力机制之后,“它”这个词已经看向了上下文,并初步融合了来自“猫”“狗”等词的语义信息。
但是,这样的表示只是“初加工品”。模型还需要进一步处理它,让它具备更强的语义表达能力和推理能力。这时,“它”的向量就会被送入前馈网络中:
- 前馈层会先把这个向量升维到一个更高维度(比如从 768 维扩展到 3072 维);
- 接着,经过 GELU 激活函数进行非线性处理;
- 然后再降维回原来的大小,形成一个新的、更复杂的向量表示。
这个新表示就是“它”这个词元的升级版本,里面包含了模型对“它”这个词更深层的理解,可以帮助模型提取出更适合判断行为、情感、逻辑的语义特征。最终形成的向量将送入下一层 Transformer,继续处理。
因此,前馈层也是非常重要的一层,看起来只是“对每个词做了一遍变换”,但它非常关键。如果 Transformer 只有注意力层没有前馈层,那它就像是一个只会模仿别人的人,不会自己总结、推理和表达。如果说自注意力阶段是“看外部世界”,那么前馈网络阶段就是“闭上眼睛思考自己”。