从零到GPT:Transformer如何引领大模型时代
FBI Warning:本文会尽量的把整个
Transformer
机制讲的浅显易懂,而你不要懂特别深入的线形代数和人工智能的知识,在看完这篇文章以后,也能融会贯通,深刻领悟其设计思想。如果你觉得有帮助,记得收藏和分享身边有需要的同学。
关注我,后续会持续更新AI相关最新最热文章。下一篇文章预告:《Prompt engineering》
今天的文章是 AI 相关文章的第二篇,也是非常重要的一篇。我们主要讲解大名鼎鼎的 Transformer
机制。Transformer
是现代大模型的基础架构,深入理解 Transformer
机制,可以让我们更好地理解大模型的运作原理。
对于从未接触过AI领域的小白选手,可以先看第一篇 入门基础人工智能理论
俗话说"外行看热闹,内行看门道"。作为计算机专业出身,但又没有系统学习过人工智能的程序员来说,我们只需要理解核心轮廓即可。因此,本文将用最简单、最通俗易懂的语言来介绍 Transformer
。只要你具备基础的线性代数知识,就能够轻松理解 Transformer
设计的核心原理。
当理解了Transformer
的原理以后,我将再进一步介绍目前的GPT的原理,让你轻松掌握大模型的底层原理。
线性代数基础
在正式开始之前,让我简单聊聊对线性代数的理解。整体来说,线性代数并不难。
人类大脑有专门的区域处理图像,有专门的区域处理语言,但却没有专门的区域来处理数学逻辑。根据我的观察,那些数学和物理很厉害的人都会用大脑的图像区域来代偿性地处理数学和物理逻辑。简单来说就是:数形结合。对于线性代数来说,用图像思维处理更是异常契合。
你可以把向量空间想象为一个坐标系,然后把向量想象成从坐标系原点指向特定点的箭头。
对线性代数的各种运算,就是对空间里箭头的各种拉伸、旋转、压缩变换。
所谓相似度,不就是两个向量点之间的距离吗?
而矩阵,就可以想象为 Excel
中的二维表格,代表着两个向量各个维度之间的关系。
通过这样的形象化理解,线性代数就会变得异常好学。
现在我们开始进入 Transformer
的学习之旅吧。
Transformer 的原理
Transformer
最初被开发来解决序列转换或神经机器翻译问题,旨在处理序列到序列的转换任务。
基于 Encoder-Decoder
架构的 Transformer
主要依赖 RNN
来提取序列信息。
如果我们将用于语言翻译的 Transformer
视为一个简单的黑盒,它会接受一种语言的句子作为输入,并输出相应的翻译结果。
这个黑盒由两个主要部分组成:
Encoder
(编码器):接收输入并输出矩阵表示Decoder
(解码器):接收编码表示并输出翻译结果
然而,编码器和解码器实际上都是由多层堆叠而成的。所有编码器都从最后一个编码器获取输入,所有解码器都从前一个解码器获取输入。
Encoder 的原理
Embedding 过程
在自然语言处理(NLP
)中,文本由离散符号(单词、词元、子词等)组成,而神经网络只能处理数字化的连续向量,并且需要在连续空间里进行计算(加法、乘法、点积、矩阵乘法等)。
在 Transformer
模型中,嵌入(Embedding
)过程是将离散的输入数据(如单词)转换为连续的向量表示,从而使得这些数据可以被深度学习模型处理。
-
预训练嵌入(如
Word2Vec
、GloVe
): 使用在大规模语料库上预训练的词向量。这些方法已经让词具有了一定的语义特性,可以直接用来初始化嵌入层。 -
随机初始化嵌入: 随机初始化嵌入矩阵,并在训练过程中通过误差反向传播更新这些向量。
BERT
和GPT
这样的模型采用的就是这种方法。
经过 Embedding
过程之后,我们就得到了每个单词的向量表示,我们称这些向量表示为 token
。
需要注意的是,一个 token
并不是与单个字符一一对应,而是与完整的词进行映射。比如"蛇"对应一个 token
,"蛇精"对应一个 token
,"杯弓蛇影"也可能对应一个 token
。
有了 token
向量之后,大模型就可以通过一系列操作对这些 token
进行加法、乘法、点积、矩阵乘法等运算。
位置编码
通过 Embedding
计算出来的 token
本身并不携带位置信息。在 Transformer
模型中,位置编码是一个关键机制,用于帮助模型理解序列中各个位置的相对或绝对关系。由于 Transformer
不像 RNN
那样隐含时间顺序,所以必须显式引入"位置信息"。
位置编码与具体词汇无关,只与位置序号相关。同一个位置在任何句子中的编码都相同。
以句子"how are you"为例,how
的位置序列号为 1,are
的位置序列号为 2,you
的位置序列号为 3。位置编码与具体词汇无关,只与位置序号相关。同一个位置在任何句子中编码相同。也就是说,当不同的句子都进行位置平移后,其单词的相关关系保持不变。
可以理解为"how are you"这个句子中的每个词都有编号,现在我们需要在保证它们相对关系不变的情况下,给每个词临时添加上位置信息。
这种组合保持了每个单词的顺序和各自的位置信息。如果需要在另一句子中使用这些位置信息,只需将对应的单词和位置组合在一起,并保证位置序列号保持不变。在另一句子中,它们的拼接仍然能保持与原始句子的相对位置关系。
最常见的位置编码方式是通过正弦和余弦函数进行计算。在论文《Attention is All You Need
》中,位置编码被定义为:
偶数维度采用 sin
函数,奇数维度采用 cos
函数。正弦和余弦是周期函数,只要给出新的位置 pos
,就能计算对应编码,模型可以处理训练中没见过的更长序列而不用学习额外参数。
同时,因为正弦余弦满足和差公式,如果模型知道 PE(pos)
,就能计算 PE(pos+k)
(位置偏移),天然地支持相对位置关系学习。
多头自注意力机制
单头注意力
我们先来介绍单头注意力机制。
注意力机制的目的是为了在一个序列内部计算每个位置的词的 token
对其它位置 token
的"关注程度"。
比如有一个句子:
“猫坐在垫子上”
在处理词"猫"的表示时,我们希望它能根据整个句子中其它单词的信息来调整自己的向量表示,比如"猫"和"垫子"可能更相关。自注意力的作用就是计算每个词对其它所有词的注意力权重。
对于输入的多个词对应的多个 token
,我们按 token
在句子里的顺序排列成二维矩阵 X。
然后通过下面的公式计算出 Q、K、V:
Q、K、V 是同一个输入向量在三个不同功能空间的投影:
- Q:
Query
代表我想找什么信息? - K:
Key
代表我能提供什么信息?K 和 Q 互相配合,一问一答。 - V:
Value
代表我真正的信息内容?
WQ、WK、W^V 是模型级别的可训练参数,它们不依赖于每次具体的输入序列,而是属于模型结构中的固定权重矩阵(像卷积核、全连接层权重那样),会在训练中不断更新,但一旦训练好,就固定在模型中,对所有输入通用。
注意力计算公式:
Softmax
是一个把任意实数向量转换成概率分布的函数:它的输出是正数,所有元素加起来等于 1,符合概率分布。Softmax
把每一行分数变成一个概率分布,表示"该 token
对所有 token
的关注比例"。匹配度越高的分数 → Softmax
概率越高 → 给 V 加权的权重越大。
最终得到一个自注意力得分矩阵 Y,这个矩阵代表了一个句子中各个词语的互相关联强度。
多头注意力机制
上面单头注意力机制中得到的 Q、K、V 都是通过单一的线性变换 WQ、WK、W^V 计算得到的。而这种单一映射只能学到一种关注模式。
比如:
“我爱吃苹果”
单头可能着重关注语法关系,比如"吃"关联"苹果",但可能忽略词性、语义中的其他维度。
而多头注意力就是并行地做多组独立的单头注意力计算,每一组用不同的 WQ、WK、W^V,然后把结果拼在一起。
之前提到的单头注意力公式为:
那么我们每一个头都可以单独计算出一个 Yi。
计算出多头的 Y 结果,其中 W^0 是模型里的一个初始化值,最终值将由模型训练获得。
好比我们有 h 个专家(head),每个专家写了一个 4 页的报告。Concat
函数就等于把专家们的报告横向摊开,变成一个合订本,变成 4h 页的报告合集。之后的 W^O 就是"编辑部",参考全书内容,再重写浓缩回 4 页的总报告。
上面的 Y1、Y2 都是矩阵,我们可以举一个例子来说明 Concat
函数。
那么 Y1 和 Y2 经过 concat
处理后的结果 Y3 为:
在某一个时刻,W^0 的值可以为:
Y3 再和 W^0 相乘,矩阵的维度会变回 2×2 的维度:
残差连接与层归一化
在 Transformer Encoder
中,经过多头注意力(Multi-Head Attention
)之后,紧接着是残差连接(Residual Connection
)+ 层归一化(Layer Normalization
)。
所谓的残差连接,就是把经过位置编码的原始矩阵 X 直接与多头计算得到的注意力矩阵 Y 相加。
编码器层中的每个子层后面都跟着一个归一化步骤:把多头注意力的输出结果(经过 WO 映射后的结果)和这个多头注意力层的输入值 X 逐元素相加,然后送去 Norm
。
为什么要加输入?
- 防止网络层数增多后梯度消失(残差思想)
- 保留输入信息,让模型不用每一层都完全重造特征
- 就算这一层注意力学得不好,还有输入这条"捷径"保底
归一化 Norm 层
LayerNorm
会对每个 token
的特征向量做归一化(均值=0,方差=1),再乘以可训练的缩放参数 γ 并加上偏移 β。
LayerNorm
就是"给每个 token
的全部特征做一遍标准化,然后用可训练的方式调回适合模型的尺度"。
前馈神经网络
接下来是前馈全连接网络,简称 FFN
。
如果网络的每一层都是线性变换(矩阵乘法 + 加偏置),那么无论有多少层,最终都等价于一个线性变换。而线性变换的表达能力非常有限,不能拟合非线性关系。所以,我们要在每个线性层后加非线性函数,让网络有能力表达复杂的模式。以下是常见的非线性操作:
-
升维线性变换:输入首先经过一个线性变换,将输入映射到一个高维空间。这个线性变换通常由一个权重矩阵和一个偏置向量实现(有些大模型架构也会把
bias
省略掉)。 -
非线性激活函数:经过升维线性变换后,输入会通过一个激活函数,增加模型的非线性表达能力。常用的激活函数包括
ReLU
、Sigmoid
、Tanh
等,顺便说一下,当前主流大模型常用的是SwiGLU
。 -
降维线性变换:经过激活函数后,再进行一次线性变换,利用降维矩阵将高维空间的特征映射回原始空间,得到
FFN
层的输出。
其中 W1、b1、W2、b2 都需要训练。
ReLU
、Sigmoid
、Tanh
都是激活函数(Activation Function
),它们的作用是给神经网络引入非线性能力,让模型可以拟合复杂的函数关系。
最终 Encoder
输出是一组向量,每个向量都代表具有丰富上下文理解的输入序列。然后这个输出被用作 Transformer
模型中 Decoder
的输入。
Encoder 总结
你可能会想:Transformer
里,从 embedding
→ attention
→ FFN
这一通处理之后,信息怎么还没丢失,还能在解码器中恢复出原来的含义?
原因如下:
-
残差连接让原信息直接"穿越"到后面,不会被下一层完全覆盖。所以就算 SubLayer 对信息做了复杂变换,那条残差通路保证了"原信息不丢失"。
-
多头注意力和
FFN
底层大部分是线性运算 + 激活。 -
训练目标强制"记住必要信息"
Transformer
是端到端训练,目标(loss)会逼它在中间层保留足够的信息来完成任务:
- 机器翻译任务 → 必须保留语义
- 语言建模任务 → 必须保留前文上下文
- 问答任务 → 必须保留关键事实
如果中间步骤真的把必要信息丢光,损失就会飙升 → 反向传播会调整权重让它别再乱丢。
Encoder 中需要训练的参数汇总
模块 | 功能 | 需要训练的参数 | 典型空间占比 |
---|---|---|---|
Token Embedding(输入层) | 将单词映射到模型的空间,把单词变成向量。 | 词表矩阵 W_embed 大小:V × d_model | 如果 V 大,这里占用最大 |
Positional Encoding | 提供位置信息 | 可学习时:矩阵大小 max_len × d_model ;固定正弦则无参数 | 占比极小 |
Multi-Head Self-Attention | 建模序列内的各个 token 之间的关系 | 对每个头学习 Q、K、V 投影矩阵 + 多头输出矩阵: 多个Wq,多个Wk,多个Wv,1个W_o。 | 中等,占比 10% 左右 |
Feed-Forward Network (FFN) | 对每个位置分别做非线性变换,提升表达力 | W₁,b₁,W₂,b₂ | 在 encoder 层中是最大户(单层) |
Layer Normalization × 2 | 稳定训练,归一化激活值 | 每个 LN 有 γ、β | 可忽略 |
理论上,一个 Encoder
层就能让 Transformer
工作(具备输入—输出信息流动的完整功能),因为一个 Encoder
层已经包含:
- Self-Attention(建模全局依赖关系)
- FFN(非线性特征变换)
- 残差+规范化(稳定训练)
实践上:
NLP
实验中 1~2 层的Encoder
就可以在简单任务(文本分类、小型翻译)上获得可用效果- 但性能会受到限制(无法捕捉深层语义)
- 工业常用:6、12、24 层是最常见的配置
即使是 GPT
、BERT
这种大模型,也不会无限增加 Encoder
层,因为现实中有 4 个硬障碍:
限制因素 | 描述 | 后果 |
---|---|---|
边际收益递减 | 从 6 层 → 12 层 → 24 层提升显著;但比如从 48 层 → 96 层,效果提升趋近于 0 | 白白增加计算成本 |
梯度消失/爆炸 | Transformer 虽有残差连接,但非常深时梯度传递仍易受干扰,训练收敛困难 | Loss 不下降,模型难收敛 |
过拟合风险 | 层数多 → 参数量大,如果训练数据不足,就学到无意义模式 | 在验证集/测试集上性能下降 |
计算/显存成本 | 层数翻倍 → 计算量 & 显存需求近似翻倍(O(N²) Attention还会额外放大) | 成本线性甚至超线性增加 |
了解完整个 Encoder
,我们再看 Decoder
就会快很多。
解码器 Decoder
解码器的作用集中在生成文本序列上。与编码器类似,解码器配备了类似的子层集合。它拥有两个多头注意力层、一个逐点前馈层,并在每个子层后合并了残差连接和层归一化。
Embedding 过程
在解码器的起始阶段,过程与编码器相同。在这里,输入首先通过 Embedding
,计算得到每个词对应的向量值。
位置编码
在 Embedding
之后,同样像编码器一样,输入通过位置编码层。给词嵌入添加对应的位置信息,然后把数据送入多头注意力机制层,用来计算词之间的相关性得分。
掩码自注意力机制
在编码器的自注意力机制中,输出的结果是 token
之间的关系。而 Masked Self-Attention
就是在 Self-Attention
的相似度计算中,人为遮掉(mask)未来的 token
。
从技术上来讲,我们只需要把自注意力的得分矩阵对角线右边部分全部设置为 -∞(负无穷大)。
Decoder
部分,我们是一步一步预测下一个token
。- 如果当前位置能看到未来
token
,模型训练时就会"作弊"——直接用答案(未来的词)进行预测,导致推理时(未来词不可见)性能崩溃。 - Mask 确保:在第 t 步,模型只能用已经生成或输入的
token
信息,不能窥探未来。
假设我们要生成 “I love AI”:
- 训练到生成 “love” 这步时,普通
Self-Attention
若不加掩码,可以直接看到"AI",于是它作弊学答案。 - 改成
Masked Self-Attention
后,模型只能用"I"去猜下一步是"love",训练和推理一致,保证泛化。
编码器-解码器多头注意力或交叉注意力
在解码器的第二个多头注意力层中,我们可以看到 Encoder
和 Decoder
组件之间的数据开始进行结合。在这里,Encoder
的输出既充当 Q 又充当 K,而 Decoder
的第一个多头注意力层的输出充当 V。
这种设置有效地将编码器的输入与解码器的输入对齐,使解码器能够识别并强调编码器输入中最相关的部分。
线性分类器和 Softmax
线性分类器和 Softmax
用于生成输出概率。
经过 Decoder
的一系列运算,我们来到 Transformer Decoder
最后一段,也就是从隐空间向量 → 最终单词概率 → 选词。
最后 Decoder
会接一个线性映射 Linear 层,将向量映射为单词的概率。
这个过程相当于是一个反向的 embedding
过程。假如某个词的向量是 [0.8,0.1,0.2],那么 linear
层会有一个单词和维度的关系:
单词名 | 坐标1 | 坐标2 | 坐标3 |
---|---|---|---|
I | 0.9 | 0.0 | 0.1 |
am | 0.1 | 0.8 | 0.1 |
student | 0.2 | 0.1 | 0.7 |
计算方法:
对"I":0.8×0.9 + 0.1×0 + 0.2×0.1 = 0.74
对"am":0.8×0.1 + 0.1×0.8 + 0.2×0.1 = 0.18
对"student":0.8×0.2 + 0.1×0.1 + 0.2×0.7 = 0.33
结果得分:
I: 0.74
am: 0.33
student: 0.18
当然,这个时候算出的结果仍然是矩阵表示的方式,而 softmax
的方法可以把矩阵表示改成概率。
所以模型将最终选择 I 作为输出结果。
需要注意的是,我这里给的例子只有3个单词,但实际上,linear
层会将向量和所有的单词计算得分。在现实场景中,单词的个数可能有几十万个。每一个词的向量都需要和每一个单词计算相似度,最终返回一个最可能的单词。
而这个 Linear
层的单词和向量的映射关系也是需要通过训练获得的。
到这里我们再看这个图,是不是就清晰明了了。
训练模式与推理模式
众所周知,模型需要训练,训练好的模型才能用来工作。在明白了整个 transformer
模型之后,让我们分别看一下模型是如何训练和推理的。
在训练过程中,需要在 input 端和 output 端分别输入"问题"和"答案"。两边都输入完整的句子。比如想让该模型的目标是做中文到英文的翻译工作,那么你的训练集应该是中文和英文的一一对应关系。比如"我是学生",那么答案应该是 “i am student”。
在输入端,不会直接把"i am student" 输入到模型,还需要对文本插入一个开始符号 <BOF>
和结束符号 <EOF>
,变成 “<BOF>
i am student.<EOF>
”。
在 Masked Multi-head attention
下,会将每一个 token
后面的信息抹去。
<BOF>
i am student.<EOF>
中:
<BOF>
看不到后面的任何信息
i 只能看到前面的 <BOF>
,需要模型来预测当前的 i
am 只能看到前面的 <BOF>
I,需要模型来预测当前的 am
student 只能看到前面的 <BOF>
I am,需要模型来预测当前的 student
若预测的内容和实际答案偏差太大(表现为 output probability 和正确答案的偏差值大),那么这个时候就会通过反向传播来调整模型中的各个参数,直到最后的效果达到目标。
推理模式
当训练完成后,模型就达到了预期效果,就可以进入推理模式来工作了。
在推理模式下,在 input 端输入一句话,然后在 output 端输入一个开始符号 <BOF>
,然后在 output probability 端输出一个最接近答案的结果,再拼接到 output 端继续生成,直到生成 <EOF>
。然后把 output 端里获得的句子去掉开始符和结束符就可以得到我们的答案了。
比如我们在 input 端输入一个句子"我是学生",我们来看一下整个推理过程。
step1
Input端输入:我是学生。
Output端 输入:<BOF>
代表推理开始
output probability 会输出一个概率分布,最终选择I作为我们的输出。
Token候选 | 概率 |
---|---|
I | 0.82 |
You | 0.07 |
He | 0.04 |
step2
Input端输入:我是学生。
Output端 输入:<BOF>
I
output probability 输出 am
Token候选 | 概率 |
---|---|
am | 0.88 |
is | 0.05 |
are | 0.03 |
step3
Input端输入:我是学生。
Output端 输入:<BOF>
I am
output probability 输出 student
Token候选 | 概率 |
---|---|
student | 0.95 |
teacher | 0.04 |
step4
Input端输入:我是学生。
Output端 输入:<BOF>
I am student
output probability 输出 <EOF>
Token候选 | 概率 |
---|---|
<EOF> | 0.97 |
. | 0.02 |
step 5
- 去掉
<BOF>
和<EOF>
,获得最终的译文:I am student
Transformer 的重要意义
Transformer
架构的出现标志着人工智能领域的一个重大转折点。自2017年《Attention is All You Need
》论文发表以来,Transformer
不仅彻底改变了自然语言处理领域,更是推动了整个 AI 行业的发展进程。
Transformer
的核心创新在于完全摒弃了传统的循环神经网络(RNN
)和卷积神经网络(CNN
),仅依靠自注意力机制来处理序列数据。带来了从任务特定模型到通用基础模型的范式转变。传统的机器学习方法需要为每个特定任务设计专门的架构,而基于 Transformer
的大型预训练模型可以通过微调适应各种下游任务,实现了"一个模型,多种用途"的理想。
BERT
:双向编码器表示,在理解类任务中表现卓越GPT
系列:生成式预训练模型,在文本生成方面展现出惊人能力T5
:将所有NLP
任务统一为文本到文本的转换
Transformer
最初就是为机器翻译任务设计的,现在已经成为该领域的标准架构。Google Translate
等主流翻译服务都采用了基于Transformer
的模型。
GPT 的工作原理
这里再简单的介绍以下GPT的工作原理。
GPT
(Generative Pre-trained Transformer)是基于 Transformer
架构的仅解码器(Decoder-only)模型,专门设计用于文本生成任务。与完整的 Transformer
不同,GPT
只使用解码器部分,这一设计选择使其特别适合生成式任务。
GPT
的核心理念是"下一个词预测"——给定前面的文本,预测下一个最可能出现的词。这种自回归的生成方式天然地适合解码器架构:
-
单向注意力:解码器使用掩码自注意力,确保模型在预测当前位置的词时,只能看到之前的词,不能"偷看"未来的信息。
-
统一的预训练目标:通过简单的语言建模任务,模型能够学习到丰富的语言知识和世界知识。
-
架构简化:去掉编码器部分简化了架构,使模型更容易扩展和优化。
GPT 的核心组件 (Decoder-only)
GPT本质上是一个(Decoder-only) 模型。
1. 词嵌入层(Token Embedding)
将输入的文本 token
转换为高维向量表示。GPT
使用学习到的嵌入矩阵,将每个 token
映射到 d_model
维的向量空间。
2. 位置编码(Positional Encoding)
由于 Transformer
本身没有位置信息,GPT
使用可学习的位置嵌入来编码每个 token
在序列中的位置。
3. 多头自注意力机制
这是 GPT
的核心组件,但与标准 Transformer
不同的是,GPT
使用掩码自注意力(Masked Self-Attention):
掩码矩阵示例(4个token的序列):
[1, 0, 0, 0]
[1, 1, 0, 0]
[1, 1, 1, 0]
[1, 1, 1, 1]
这确保了第 i 个位置的 token
只能注意到位置 1 到 i 的 token
,而不能看到位置 i+1 之后的 token
。
4. 前馈神经网络(FFN)
每个 Transformer
层都包含一个位置无关的前馈网络,通常采用两层线性变换加上激活函数:
FFN(x) = max(0, xW₁ + b₁)W₂ + b₂
GPT
作为 Transformer
架构在生成式任务上的成功应用,展现了人工智能技术的巨大潜力。