前言
如今,从智能客服到内容创作,从编程辅助到翻译工具,大语言模型(Large Language Model,简称 LLM)正悄然渗透进我们日常生活和工作的方方面面。在这些"智能"背后,其实都是一个庞大而复杂的模型在实时运转------它不仅能理解你输入的每一个字,还能推理语义、捕捉语气,甚至"猜测"你接下来想说什么。
这一切的核心,是 LLM 在面对一段输入文本( prompt)时,能够通过内部机制对其进行理解与推理,并基于上下文的概率分布,一步步生成下一个最有可能的词(token),从而构建出连贯、自然的输出内容。这个过程看似流畅自然,实则背后蕴含着强大的算法架构与计算能力。而支撑这一强大能力的技术底座,正是 Transformer 架构。
Transformer 是一种深度学习模型结构,最早由 Google 和多伦多大学的研究人员在 2017 年发表的论文《Attention Is All You Need》中提出。它彻底改变了传统的循环神经网络(RNN)和长短时记忆网络(LSTM)对序列建模的依赖方式,引入了全新的注意力机制(Attention Mechanism),使得模型能够更高效地处理长距离依赖关系,并显著提升了训练速度和模型性能。从那以后,Transformer 成为了现代大语言模型的核心框架,也奠定了今天AI语言理解能力的基础。
为了更深入地理解 LLM 是如何一步步生成语言的,我们需要了解支撑它的核心架构------Transformer。Transformer 架构就像一条精密的语言处理流水线,由多个功能模块协同组成,各司其职,共同完成从输入文本到输出预测的全过程。
Transformer 框架概览
Transformer架构最早由《Attention is All You Need》提出,它依赖于编码器-解码器(Encoder-Decoder)结构来实现高效的文本处理与生成,对应的模型架构如下所示:

我们看看这个经典Transformer架构的组成部分:
- Input Embedding:文字的向量化表示
首先,输入的文本被分割成一个个token(如单词或子词),每个token通过Embedding层转换为固定维度的嵌入向量。这个过程是将人类可读的文字信息转化为机器能够理解和处理的数值形式。
- Positional Encoding:赋予序列顺序信息
此外,还需要一种方法来保留输入序列中词语的位置信息。Positional Encoding通过给每个token的嵌入向量添加特定的位置编码,使得模型可以识别出token在序列中的位置关系。
- Encoder:深度语义分析
Encoder由多个相同的层堆叠而成,每层包括两个主要子层:多头自注意力机制(Multi-Head Self-Attention)和前馈神经网络(Feed-Forward Neural Networks)。这些层负责提取输入文本的深层次语义特征,并将其转换为更丰富的表示形式。
- Decoder 层:基于上下文生成文本
与Encoder类似,Decoder也由多个相同的层组成,但每一层额外包含了第二个注意力子层,即Encoder-Decoder Attention,用于关注Encoder的输出。这有助于在生成新token时考虑到整个输入序列的信息。
- Linear 层与 Softmax 层:生成概率分布
Decoder的最后一层输出传递给一个线性变换层(Linear Layer),该层将高维向量映射到词汇表大小的维度上。随后,Softmax函数将这些得分转换为概率分布,从而确定下一个最有可能出现的token。
总的来说,Transformer架构中的各个组件紧密协作,实现了从原始文本输入到最终token预测的全流程。
Transformer的工作过程
我们通过一个具体的心理咨询场景,来看看Transformer架构是如何处理输入文本并生成准确、有逻辑的回应的。
假设在一个在线心理咨询服务中,客户与 AI 助手之间发生了如下对话:
plaintext
用户: 最近我总感觉焦虑,晚上睡不好,白天注意力不集中,想跟你聊聊。
助手: 听起来你最近情绪有些困扰。这种焦虑是从什么时候开始的?有具体压力源吗?
用户: 大概三个月前,工作突然变多,还要带新人。起初还能应付,后来越来越力不从心,连周末都觉得很累。
助手: 你承担的责任可能已超出当前的承受范围。身体和生活习惯有变化吗?
用户: 变化挺大。以前偶尔运动,现在完全没时间也没心情。吃饭也不规律,晚上满脑子都是工作,翻来覆去睡不着。
助手: 这些变化会加重心理负担。焦虑常伴随失眠、疲惫和注意力下降。你有没有尝试缓解的方法?
用户: 试过听音乐放松,但效果不大。我也想倾诉,又怕别人觉得我脆弱,所以大多时候都在自己扛。
助手: 我能理解你对情绪表达的顾虑。其实每个人都会有低落的时候,愿意面对并寻求帮助本身就是一种坚强。你有没有考虑过去看看心理咨询师,或写日记来梳理情绪?
用户: 我确实想过要不要做心理咨询,但还有些犹豫。一方面是担心费用,另一方面也怕被贴标签。你觉得我这种情况,有必要接受专业帮助吗?
现在,AI助手要基于这段对话来回答客户的问题,也就是说,模型要基于这段 prompt 来生成回答。
为此,模型需要从这段 prompt 中准确理解以下几个关键要素:
- 用户当前的主要困扰:包括焦虑情绪、睡眠问题以及注意力难以集中等心理与生理表现;
- 引发困扰的背景原因:如近期工作压力增大、责任加重等外部压力源;
- 用户的生活状态变化:例如作息紊乱、缺乏运动、社交回避等行为调整;
- 用户的深层顾虑:对表达情绪的担忧、害怕被误解为脆弱,以及对寻求专业帮助的犹豫与疑虑;
- 用户最终提出的核心问题:像自己这样的情况,是否有必要接受心理咨询或专业帮助?
为了提供有深度且具针对性的回应,模型需要准确捕捉这些信息之间的联系,然后基于情感理解能力与常识推理能力进行回答。
这一过程依赖于Transformer架构中的多个组件协同工作,尤其是自注意力机制(Self-Attention),它使得模型能够捕捉到句子内部以及不同句子之间的复杂关系,从而实现对上下文的深层次理解。
接下来,我们将详细解析Transformer架构是如何逐步处理这段对话的。
Tokenization:把文本转成 Token
要让大模型理解一段对话或输入文本,第一步是将其转化为模型可以处理的形式------将文字转换为一系列 Token。这个过程被称为 Tokenization(词元化)。
什么是 Token
简单来说,Token 是模型处理语言的基本单位,它可以是一个单词、一个汉字、一个标点符号,也可以是一个常见的词语或短语组合。
以英文为例,一个完整的单词可能会被进一步拆分为多个子词(subword)单位。例如,"playing"可能被拆分为两个 Token:"play" + "ing"。这种基于子词的划分方式,使得模型在有限的词表容量下,依然能够灵活地应对各种词汇变化。
对于中文这类没有明显空格分隔的语言,Tokenization 的过程更像是对单字和常用短语的识别与切分。例如:
- 单个汉字如"焦"、"虑"可能会各自作为一个 Token;
- 常见心理术语或表达如"注意力"、"失眠"等,也可能被模型识别为一个完整的 Token。
- 有些模型还会结合汉字结构信息,引入字形结构建模(如偏旁部首)、拼音辅助等
不同模型在处理中文时会采用不同的策略。以 GPT 系列模型为例,平均来看,一个汉字大约对应 1.5 到 2 个 Token,具体数量取决于上下文以及所使用的 Tokenizer 实现方式。
为什么需要 Tokenization
Tokenization 将文本分割成更小的单元(Tokens),这是模型能够理解并处理文本的前提。Tokenization 的意义在于:
- 简化词汇表示:直接处理完整句子或词语会导致词表庞大且难以管理。通过 Tokenization,可以将复杂词语拆解为更小的部分,减少词表规模。
- 增强模型泛化能力:使用子词(subword)作为 Token 不仅能覆盖已知词汇,还能灵活应对未登录词(OOV)。例如,"unhappiness"可分解为"un"+"happy"+"ness",使模型能够处理未知词汇。
- 提高计算效率:有效的 Tokenization 方法能使文本表示更加紧凑,减少数据量,从而提高计算效率。
- 支持多语言处理:不同的语言有不同的语法结构和书写系统。Tokenization 提供了一种通用方法来处理各种语言的文本,保持词表可控性。
因此,Tokenization 不仅仅是为了简化词汇表示,还在增强模型泛化能力、提高计算效率和支持多语言处理等方面发挥着重要作用。
Tokenizer 工具简介
为了高效地完成 Tokenization 过程,主流的大语言模型通常都会配备专用的 Tokenizer 工具。例如:
- OpenAI 采用的是 tiktoken,这是一种高效且轻量级的 Token 编码器,支持多种模型版本,具有极快的处理速度;
- Hugging Face 提供的 Transformers 库集成了多种常用的 Tokenizer 实现,包括 BPE(Byte Pair Encoding)、WordPiece 和 SentencePiece 等。
这些 Tokenizer 不仅决定了文本如何被切分为 Token,还直接影响模型对语言的理解效率和表达能力。它们的核心目标是:用尽可能少的 Token 表达尽可能丰富的语言信息,从而在保证语言表达能力的同时,控制模型的词表规模和计算开销。
Embedding:Token变成嵌入向量
在将文本转换为 Token 后,为了使模型能够理解并处理这些信息,我们需要进一步将 Token 转换为向量形式------即 嵌入(Embedding)向量。这一过程不仅涉及简单的转换,还包括捕捉每个 Token 的语义特征。
为什么要将 Token 转换为向量
在深入理解 Embedding 之前,我们先来澄清一个基础但非常重要的概念:什么是向量?
张量、向量与矩阵:从基本结构说起
在数学和深度学习中,张量(Tensor) 是描述数据结构的基本单位,它包括了标量、向量、矩阵以及更高维数据的统一表示:
- 标量(Scalar):0维张量,就是一个单独的数字,比如
5
。 - 向量(Vector):1维张量,是一组有序的数字,代表某个空间中的一个点,比如
[0,0,0,...]
- 矩阵(Matrix):2维张量,由多个行和列组成的数字阵列,比如
[[0,0],[0,0]]
- 高维张量:如 3D、4D 张量,用于表示更复杂的数据结构,比如图像或批量的词向量。
在自然语言处理中,我们最常打交道的就是 向量,它是我们理解语言的基本数学工具。
"特征向量"的意义
从机器学习的角度来看,把 Token 转换为向量的过程,本质上就是在提取其特征表示,因此这个向量可以被称为"特征向量"。特征向量的基本构成:
- 数学空间:指的是向量所处的多维环境。例如,在三维空间中,一个点由三个坐标 (x, y, z) 确定;而在 NLP 中,一个词可能被映射到几百甚至几千维的空间中,由相应数量的数值共同定义其位置。
- 向量:它是数学空间中的一个点,由多个数值组成,每个数值代表某个维度上的特征值。这些特征值共同描述了该语言单元的语义或结构特性。
- 特征:是指向量中各个维度所承载的具体含义。在语言模型中,这些特征可能对应词语的语义、语法角色、上下文关系等语言学信息。
在大语言模型(LLM)中,我们将Token 转换为词向量,这背后的核心思想是:用数学方式表达语言的语义和结构信息,它让模型能够以计算的方式理解和处理语言。
Token 是如何转换为向量的?
one-hot 编码
为了将 Token 转换为成向量,最简单的做法是使用 one-hot 编码(One-Hot Encoding)。
- 对于一个包含 N 个唯一 Token 的词汇表,每个 Token 都会被表示为一个长度为 N 的向量。
- 在这个向量中,只有一个位置是 1,其余位置都是 0,这个唯一的 1 表示当前 Token 在词汇表中的位置。
以中文为例,虽然汉字总数接近 10 万个,但日常使用的高频汉字数量并不多,3000 个常用汉字即可覆盖 99% 的书面表达场景。如果我们为这 3000 个汉字建立一个 one-hot 编码表,这样每个汉字都能用一个 3000 维的向量来表示:
- "我" →
[1, 0, 0, ..., 0]
- "你" →
[0, 1, 0, ..., 0]
- "他" →
[0, 0, 1, ..., 0]
这种编码方式简单易实现,很适合较小的词汇表或简单的分类任务,在早期的机器学习模型中被广泛使用。然而,这种方式也存在明显的局限性:
- 高维稀疏问题:每个词被映射为一个非常大的向量,导致映射表庞大且极度稀疏,浪费大量存储空间;
- 缺乏语义关联:单纯的编码无法反映词语之间的语义相似性;
- 无逻辑关系:编码向量之间不能支持类似
king - man + woman ≈ queen
的逻辑运算。
显然,one-hot 编码远远不能满足现代语言模型对语义理解的需求。
Embedding 嵌入向量
现代的大语言模型(LLM)使用的是更高效、更具表达能力的嵌入(Embedding)技术。Embedding 将每个 Token 映射到一个新的数学空间中,使得语义相近的词在该空间中的向量距离也更近,并支持向量之间的数学运算。
嵌入向量应满足以下几个关键要求:
- 可计算相似度:能够通过向量间的距离衡量语义上的相似性;
- 支持数学或逻辑运算:可以在向量之间进行加减等操作,揭示词汇之间的类比或逻辑关系。
例如,转化后的向量要支持king - man + woman ≈ queen
逻辑运算。假设我们经过 Embedding 得到的向量如下(为便于展示,这里使用 8 维简化示例):
css
king -> [5.0, 3.2, 4.1, 2.5, 6.7, 1.8, 0.9, 3.3]
man -> [2.0, 1.5, 3.0, 1.2, 4.0, 0.8, 0.5, 2.1]
woman -> [2.1, 1.6, 3.1, 1.3, 4.2, 0.9, 0.6, 2.2]
那我们可以进行如下计算:
ini
result = king - man + woman = [5.1, 3.3, 4.2, 2.6, 6.9, 1.9, 1.0, 3.4]
然后我们在 Embedding 空间中查找最接近 result
的向量,发现它非常接近于queen
的向量:
ini
queen: [5.2, 3.4, 4.0, 2.7, 6.8, 2.0, 1.1, 3.2]
这就验证了我们的类比关系:king - man + woman ≈ queen
。
Embedding 向量的维度
我们应该把 Token 映射到多少维的数学空间呢?
随着模型架构的演进,Embedding 的向量维度也在不断提升:
- 2017 年的经典 Transformer 模型使用的是 512 维 向量;
- 2020 年的 GPT-3 将维度提升到了 12288 维;
- 到了 2024 年的 Llama 3,甚至达到了 16384 维。
这些高维向量不仅承载了词语本身的含义,还能反映出其与其他词语之间的语义关系。更高的维度意味着更强的表达能力 ------ 它能容纳更多语义信息,使模型在处理复杂语言任务时具备更精细的区分能力和更丰富的上下文理解。
Embedding 向量的数值怎么确定
Embedding 层本质上是一个可训练的神经网络层。它负责将输入的 Token 转换为高维向量表示,这些向量共同组成一个词典(Vocabulary),而这个词典本身也是一个神经网络的一部分。
- 在模型初始化时,每个 Token 对应的向量值是随机生成的,并没有实际语义含义。
- 随后,在训练过程中,模型通过大量文本数据学习词语之间的关系,并不断调整这些向量的数值,使得语义相近的词语在向量空间中的距离更近,而语义无关的词语则彼此远离。
通过大规模语料训练,Embedding 模型能够自动学习词语之间的语义联系。例如,在百科词条中,"king"一词通常由其他描述性词语构成定义,模型可以通过统计学习捕捉这些词语之间的共现规律,从而构建出具有丰富语义信息的向量空间。
因此,Embedding 不仅仅是一个从 Token 到向量的简单映射过程,更是赋予语言模型深层理解能力的关键一步。
Positional Encoding :在向量中加入位置信息
在将 Token 转换为 Embedding 向量之后,我们还需要解决一个关键问题:模型如何理解词语的顺序?
为什么需要位置信息?
首先,大语言模型在处理文本时,与人类的阅读方式存在本质区别:
-
人类阅读是按顺序进行的,通常从左到右、从上到下逐字理解;
-
模型则可以根据架构选择不同的处理方式:
- 传统的 RNN(循环神经网络)采用顺序处理机制,逐字处理文字序列,虽然贴合自然语言的线性结构,但效率较低,且难以实现并行计算;
- 而 Transformer 架构通过并行处理大幅提升运算效率,但这要求每个词必须显式携带其在句子中的位置信息。
此外,语言的语义不仅依赖于词语本身,也高度依赖它们的排列顺序。例如"猫追狗"和"狗追猫",这两句话由完全相同的词语构成,但由于词语顺序不同,表达的含义截然相反。
因此,在 Transformer 这样的并行架构中,必须为每个 Token 的 Embedding 向量添加相应的位置编码(Positional Encoding),以帮助模型准确理解词语之间的顺序和句法结构。
如何实现位置编码?
我们为段落中的每一个位置生成一个对应的 Positional Encoding 向量,然后将其与原始的 Embedding 向量相加,形成最终的输入向量。
用数学公式表示为: <math xmlns="http://www.w3.org/1998/Math/MathML"> X i = E i + P i \mathbf{X}_i = \mathbf{E}_i + \mathbf{P}_i </math>Xi=Ei+Pi
其中:
- <math xmlns="http://www.w3.org/1998/Math/MathML"> X i \mathbf{X}_i </math>Xi 是第 $$$$个 Token 的最终输入向量;
- <math xmlns="http://www.w3.org/1998/Math/MathML"> E i \mathbf{E}_i </math>Ei 是该 Token 经过 Embedding 层映射得到的语义向量;
- <math xmlns="http://www.w3.org/1998/Math/MathML"> P i \mathbf{P}_i </math>Pi 是该 Token 对应的位置编码向量。
这种向量加法操作在维度上是可对齐的,即 Embedding 向量与 Position 编码向量要具有相同的维度,从而保证逐元素相加的有效性。
这样,每个输入向量既包含了词语本身的含义,也包含了它在整个句子中的位置信息。
Positional Encoding 向量是怎么得到的?
那么,Positional Encoding 向量 <math xmlns="http://www.w3.org/1998/Math/MathML"> P i \mathbf{P}_i </math>Pi 要怎么定义呢?
固定公式生成
在《Attention Is All You Need》论文中,作者提出了一种基于正弦和余弦函数的位置编码方式。该方法通过固定的数学公式直接为每个位置生成唯一的 Positional Encoding 向量。具体公式如下:
对于位置 <math xmlns="http://www.w3.org/1998/Math/MathML"> pos \text{pos} </math>pos 和维度 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i(从 0 到 <math xmlns="http://www.w3.org/1998/Math/MathML"> d model − 1 d_{\text{model}} - 1 </math>dmodel−1),定义
<math xmlns="http://www.w3.org/1998/Math/MathML"> P E ( pos , 2 i ) = sin ( pos 1000 0 2 i d model ) PE(\text{pos}, 2i) = \sin\left(\frac{\text{pos}}{10000^{\frac{2i}{d_{\text{model}}}}}\right) </math>PE(pos,2i)=sin(10000dmodel2ipos), <math xmlns="http://www.w3.org/1998/Math/MathML"> P E ( pos , 2 i + 1 ) = cos ( pos 1000 0 2 i d model ) PE(\text{pos}, 2i+1) = \cos\left(\frac{\text{pos}}{10000^{\frac{2i}{d_{\text{model}}}}}\right) </math>PE(pos,2i+1)=cos(10000dmodel2ipos)
其中:
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> pos \text{pos} </math>pos 是当前 Token 在序列中的位置;
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> d model d_{\text{model}} </math>dmodel 是 Embedding 向量的维度;
-
偶数维度使用正弦函数,奇数维度使用余弦函数。
这种方式的优点在于:
- 位置信息具有周期性变化特性,有助于模型识别相对位置;
- 适用于任意长度的输入序列,即使训练时未见过的长序列也能自动生成对应的位置编码;
- 无需额外训练参数,节省模型复杂度和训练成本。
另一方面,这种固定编码方式也存在局限性:
- 缺乏对绝对位置的明确建模能力,难以区分位置顺序完全相反的序列;
- 固定编码无法根据任务或上下文进行动态调整,表达能力受限;
- 对于复杂结构(如长距离依赖、句法结构),提供的位置信息可能不够精细。
因此,固定公式法适合通用性强的长文本处理场景;而现代 LLM 逐渐转向另一种更加灵活的方式:可学习的位置编码,以弥补固定位置编码的局限性,并提升模型对位置信息的建模能力。
可学习的位置编码(Learnable Positional Encoding)
可学习的位置编码 将 Positional Encoding 设为可训练的嵌入层(embedding layer),这种方法让模型根据任务数据自动学习最适合的位置表示。
具体来说,模型会维护一个大小为 <math xmlns="http://www.w3.org/1998/Math/MathML"> L max × d model L_{\text{max}} \times d_{\text{model}} </math>Lmax×dmodel 的位置编码表(其中 <math xmlns="http://www.w3.org/1998/Math/MathML"> L max L_{\text{max}} </math>Lmax 是最大序列长度),每个位置都对应一个可训练的向量。在训练过程中,这些向量会随着模型优化不断调整,以更好地适应当前任务的需求。
这样做的好处是:
- 更灵活地捕捉特定任务中的位置模式;
- 对某些任务可能带来更好的性能表现;
- 能结合绝对位置与相对位置建模。
但缺点是:
- 需要额外的参数,增加模型复杂度;
- 通常只能处理不超过 <math xmlns="http://www.w3.org/1998/Math/MathML"> L max L_{\text{max}} </math>Lmax 的输入长度。
目前主流的大语言模型(如 GPT 系列、BERT、T5 以及 Llama 系列)普遍采用可学习的位置编码。这种方式允许模型根据训练数据自动优化位置表示,更加灵活地适应不同任务和上下文结构。相比固定公式生成的方式,可学习 Positional Encoding 能更好地捕捉特定任务中的位置模式,从而提升模型在实际应用中的表现。
Encoder & Decoder:深度理解语义
回到我们的心理咨询例子:在完成了 Tokenization、Embedding 和 Position Encoding 这些预处理步骤之后,原始文本已经被转化为一组包含语义信息和位置信息的向量序列。假设这段对话共有 500 多个字,经过模型处理后,最终生成了约 1000个12288维的输入向量。
然而,一段自然语言文本往往承载着丰富的情感、背景和上下文线索,其中每一个细节都可能影响对整体问题的理解。因此,仅仅将每个词或短语表示为一个独立的向量是远远不够的。模型还需要具备从上下文中提取关键信息,并将其有效整合进目标语义中的能力。
那么,模型是如何从这些输入向量中提炼出有用的信息,从而更好地把握用户问题的核心含义呢?这就需要依靠 Encoder + Decoder 的信息聚合机制。
在大语言模型中,编码器(Encoder) 负责理解输入文本,而 解码器(Decoder) 则负责生成回答,它们共同构成了一个"理解 + 生成"的智能映射系统,是整个架构的核心组件。
语义理解:信息聚合
信息聚合(Information Aggregation)是指:在理解某个核心词语时,模型会从整个上下文中筛选出与之相关的语义信息,并将其融合到该词的向量表示中,从而增强其语义表达能力。
具体来说,在当前的心理咨询对话中:
- 原始的"心理咨询"这个词,转化后得到的只是一个 12288 维的向量,仅包含它本身的 Token 信息和位置信息;
- 以它为中心主题词,模型可以从整段对话中识别出与其相关的内容,比如"焦虑"、"失眠"、"犹豫"、"专业帮助"等关键词;
- 然后,模型会对这些相关词的向量进行加权汇总,并融合进"心理咨询"的向量中;
- 最终得到的"心理咨询"向量不仅代表了它本身的意义,还包含了上下文中与之密切相关的语义信息。
这种动态的信息聚合过程,使得模型能够更准确地理解用户的真实意图和情感需求,特别是在面对复杂的问题时,展现出更强的语义理解和共情能力。
那么,模型是如何识别出与当前词语相关的内容呢?
在信息聚合的过程中,模型主要通过两个维度来判断哪些信息是与当前词相关的:
- 语义相关性(Semantic Relevance)
模型通过计算不同 Token 的 Embedding 向量之间的相似度(例如使用余弦相似度)来衡量它们之间的语义关联程度。向量之间的距离越近,说明它们在语义上越接近,因此该信息对理解当前词就越有帮助。
比如在心理咨询对话中,当模型关注"心理咨询"这个词时,它会自动识别出与之语义相近的词汇,如"焦虑"、"失眠"、"帮助"、"情绪"等。这些词汇在语义空间中距离较近,因此会被模型视为与"心理咨询"高度相关的信息。
- 位置邻近性(Positional Proximity)
除了语义相似性,Token 的位置关系也是模型判断相关性的重要依据。通常来说,位置相近的 Token 更可能构成一个完整的语义单元。
由于我们在 Embedding 向量中加入了 Positional Encoding,模型就能识别出哪些词在原文中是相邻或接近的。这种位置信息使得模型在进行信息聚合时,能更好地捕捉局部语义结构。这也正是 Positional Encoding 的一个重要作用:帮助模型在理解语言时,不仅关注"说了什么",还能理解"在哪说的"和"怎么连起来说的"。
下面分别看看 编码器 和 解码器 的工作流程。

编码器(Encoder)
在大语言模型中,编码器(Encoder) 的主要任务是对输入文本进行深度理解,并将原始的语义信息转化为高维度的向量表示。通过一系列复杂的处理步骤,包括多头注意力机制和前馈神经网络,编码器能够捕捉到输入文本中的丰富语义和上下文关联,从而为解码器生成高质量的回答提供坚实的基础。
输入
经过 Embedding 和 Positional Encoding 处理后的向量序列。这些向量包含了原始文本中的语义信息及其在句子中的位置信息。以我们前面的心理咨询对话为例,输入为 1000 个 12288 维的向量。
处理过程
编码器通过多个层级(由参数 Nx 控制)逐步提升对输入信息的理解,每一层都包含两个关键操作:
- 注意力机制(Self-Attention) 模型以每个 Token 为中心,通过计算它与其他 Token 的语义相关性,从上下文中提取最有价值的信息,并进行加权整合。例如在"心理咨询"这个词的处理中,模型会识别出"焦虑"、"失眠"、"犹豫"等与其语义相关的内容,并据此增强"心理咨询"这个 Token 的语义表达。 这一过程让每个词都能"看到"整个上下文,从而获得更全面的理解。
- 前馈神经网络(Feed-Forward Network, FNN) 在完成注意力计算后,每个 Token 的向量会被送入一个结构相同的全连接神经网络中进行非线性变换。这个网络会对每个位置的向量进行独立处理,进一步提炼其语义特征,并提升模型的表达能力。虽然每个位置的处理是独立的,但输入已经融合了上下文信息,因此 FNN 实际上是在对"上下文增强后的语义"进行建模。
这两个步骤会在每一层中依次执行,并通过残差连接(Residual Connection)和归一化(Layer Normalization)来稳定训练过程、提升模型表现。
整个过程会重复多次,具体次数由参数 Nx 控制。在经典的 Transformer 架构中,通常设置为 Nx = 6 层;而在像 GPT-3 这样的大规模模型中,这一数值被提升至 Nx = 96,以便捕捉更加复杂和深层的语言结构与语义关系。
输出
仍然是 1000 个 12288 维的向量,但此时每个向量都已融合了丰富的上下文信息,具有更强的语义表征能力。换句话说,这些向量不仅"知道"自己代表什么词,还能"理解"这个词在整个对话中所处的语境和作用。
解码器(Decoder)
在大语言模型中,回答的生成是一个逐步进行的过程,每一步都依赖于之前已经生成的内容。这种机制被称为 自回归生成(Autoregressive Generation) ------ 模型根据已有信息逐字生成回复,每次生成的新 Token 都会被加入到输入序列中,参与后续的计算,直至完成整个回答。
输入
解码器接收两部分输入:
- 编码器输出的向量:来自编码器的1000个12288维向量,代表了 prompt 中的历史对话上下文和用户提出的问题。这部分信息为模型提供了生成回答所需的背景语义支持。
- 已生成的回答 Token 对应的 Embedding 向量:这部分输入体现了模型的自回归特性。在生成过程中,模型会逐字输出 Token,每一个新生成的 Token 都会被转换为对应的 Embedding 向量,并立即加入到下一轮的输入序列中。这样,模型在生成当前 Token 时,就能参考之前已经生成的内容(例如"建议"),从而确保语义连贯性和逻辑一致性。
处理过程
解码器同样由多个层级组成(层级数量由参数 Nx 控制),每一层包含三个关键步骤:
- 自注意力处理(Self-Attention) 首先,解码器会对已生成的回答 Token 进行自注意力处理。这一步骤让模型能够理解当前回答内部的结构和语义关系。例如,当模型读取到已经输出的 Token 是"建议:"时,它会通过自注意力机制识别出后续内容应当围绕"具体建议内容"展开,从而继续生成具有指导性和连贯性的回应。
- 交叉注意力处理(Cross-Attention) 接着,解码器将这些向量与编码器输出的上下文向量进行交互式融合。通过交叉注意力机制,模型能够结合上下文的整体语义信息,确保生成的回答既连贯又相关。例如,在生成"建议"这个词时,模型会参考之前的上下文,如"焦虑"、"失眠"等关键词,从而生成更为准确和有针对性的回答。
- 前馈神经网络(Feed-Forward Network, FNN) 经过注意力处理后,每个 Token 的向量会被送入一个全连接神经网络中进行非线性变换。这个步骤进一步提炼每个位置的语义特征,提升模型的表达能力。
这些步骤会在每一层中依次执行,并通过残差连接(Residual Connection)和归一化(Layer Normalization)来稳定训练过程、提高模型表现。
输出
解码器的输出是一个逐字生成的过程。
-
在每一轮会生成一个新的12288维向量,不仅包含了当前回答的语义信息,还融合了上下文的整体语义。
-
这个向量随后通过线性层(Linear Layer)和 Softmax 函数处理,预测下一个最有可能出现的 Token(如"建议"),将其加入到已生成的序列中,并参与下一轮自回归计算。
-
整个生成过程将持续进行,直到模型预测出表示回答结束的特殊标记(如
<EOS>
),或达到预设的最大生成长度为止。
Linear & Softmax
在解码器生成最后一个 Token 的隐藏状态(即一个 12288 维的向量)之后,模型会通过两个关键步骤将其转化为实际可输出的 Token:
- Linear 层:生成"下一个字"的权重分布
Linear 层是一个全连接层(也称为投影层),它将解码器输出的高维向量(如 12288 维)映射到一个维度等于词汇表大小的向量上。
这个向量中的每一个数值,代表了模型认为下一个最有可能出现的 Token 对应的"得分"或"权重"。
举例来说,如果词汇表包含 50,000 个词,那么 Linear 层的输出就是一个长度为 50,000 的向量,每个位置对应一个候选词的得分。
- Softmax 层:将权重分布转换为概率分布
Softmax 函数将 Linear 层输出的得分向量归一化为一个概率分布。
每个位置的得分被转换为一个介于 0 和 1 之间的概率值,表示该 Token 成为下一个输出的"可能性"。
最终,模型会选择概率最高的 Token(或根据特定采样策略选取 Token),作为当前步的输出。
通过 Linear 层和 Softmax 层的配合,模型能够从复杂的高维语义空间中,精准地选出最合适的下一个字,从而实现连贯、自然的文本生成。这一过程在每一轮生成中都会重复,直到输出结束标记 <EOS>
或达到最大生成长度。
以上就是 Transformer 的整体工作过程。通过多个模块的协同工作,Transformer 模型能够有效地理解输入文本并生成高质量的输出。
核心模块:Decoder
在整个架构中,解码器扮演着尤为关键的角色。接下来,我们将深入探讨 Transformer 架构中的解码器,详细解析其内部结构和工作机制,帮助你更好地理解这一核心组件的工作原理及其在生成任务中的重要性。
Decoder Only 架构:现代大语言模型的核心设计
为了让大语言模型在理解一段文本的基础上输出下一个字,经典的 Transformer 模型采用了 编码器 + 解码器 的双塔结构。
-
编码器:负责理解输入内容。完成深度语义建模,但它本身不具备输出能力;
-
解码器:负责生成输出内容。基于编码器的理解结果,结合已生成的历史内容,逐步构造出完整、流畅的语言回应。
变体:Encoder Only 和 Decoder Only
随着技术的发展,两种特殊的变体逐渐被广泛应用:
-
Encoder Only :BERT 的双向理解能力
- 只用编码器,不能生成文本,主要用于语义理解和特征提取。
- 以 BERT 为代表的 Encoder Only 模型利用了 Transformer 中的编码器模块,专注于对输入文本进行深度上下文建模。通过双向注意力机制,BERT 能够同时考虑一个词在其前后语境中的意义,从而获得更丰富的语义表示。
- 这种方法在自然语言理解任务(如问答、情感分析、命名实体识别等)中取得了显著成效。但因为缺乏解码器模块,这类模型无法直接生成新文本,只能用于理解或分类任务。
-
Decoder Only :GPT 系列的语言生成核心
- 只使用解码器,目前主流的大语言模型(如 GPT 系列)普遍采用这种架构,专注于文本生成任务。
- GPT 系列(从 2018 年的 GPT-1 开始)采用了 Decoder Only 的架构,专注于语言生成任务。这类模型不再区分"问题"和"答案",而是统一处理整个输入文本,并基于已有内容进行"续写"。
目前主流的大语言模型(LLM),如 GPT、LLaMA、ChatGLM、DeepSeek 等,普遍采用 Decoder Only 的架构。接下来,我们将深入讲解这一架构的工作原理及其核心优势。
Decoder Only 的工作方式
经典 Transformer 架构 | GPT1 的 Decoder-Only 架构 |
---|---|
![]() |
![]() |
在经典的 Encoder-Decoder 架构 中,处理过程分为两个阶段:
-
编码器(Encoder)负责对用户提供的完整提示词(prompt)进行理解,并将其转化为上下文丰富的向量表示,输出给解码器;
-
解码器(Decoder)则有两个输入来源:
- 一部分来自模型已生成的 Token 序列,通过自注意力机制(Self-Attention)理解当前生成内容的内部结构;
- 另一部分来自编码器的输出,通过交叉注意力机制(Cross-Attention)结合上下文信息;
- 这两个输入向量融合处理后生成输出向量,最终预测下一个 Token。
而在 Decoder Only 架构 中,整个模型仅由解码器构成,处理流程更为简洁高效:
- 解码器只有一个输入来源,即用户提供的完整提示词(prompt)。模型的任务是基于这段已有的文本,预测下一个最有可能出现的 Token,实现"文本续写";
- 在每一轮生成新的 Token 后,该 Token 会被立即添加到当前的输入序列中,作为下一轮生成的新输入。这一过程不断循环,直到生成结束标记
<EOS>
或达到预设的最大长度。
这种设计使得 Decoder Only 模型在生成任务中具有更高的灵活性和实用性,也成为当前主流大语言模型(如 GPT 系列)的基础架构。
Prompt-Response 模式
在传统的 Encoder-Decoder 框架 中,模型通常采用明确的分工模式:
- 编码器 负责理解用户输入的问题;
- 解码器 则基于编码器的理解结果,逐步生成对应的答案。
而在 Decoder Only 架构 中,这种界限被打破了。所有对话内容(包括问题与回答)都被统一作为输入提供给模型,不再区分"问题"和"答案"。这种处理方式也更贴近 LLM 的本质:它并不是在"回答问题",而是在根据已有文本,进行"文本续写"。
这种交互方式被称为 Prompt-Response 模式,即通过给定一段提示(Prompt),引导模型生成一个合理的响应(Response)。它构成了当前大多数大语言模型的基础交互形式。
Decoder Only 架构下的解码器
在 Decoder Only 架构 下,解码器内部的模块进行了一些关键调整,以适应其专注于生成任务的需求:
-
省去 Cross-Attention 层:这一层原本用于融合编码器输出的上下文信息,在 Decoder Only 架构中不需要了。
-
带掩码的多头自注意力机制 :为了确保生成过程中的因果关系(即每个位置只能依赖于之前的位置),多头自注意力机制 (Multi-Head Self-Attention) 被替换为 带掩码的多头自注意力机制(Masked Multi-Head Self-Attention)。
- 通过掩码(Masking)限制每个位置的 Token 只能关注其前面的 Token,而不能看到后面的 Token。
- 在每一层 Masked Multi-Head Attention 中,每个 Token 都会根据其前面的 Token 来更新自己的语义表示。经过多个层级的堆叠,位于末尾的 Token 就能逐步积累到前面所有 Token 的信息。
- 最终,只有最后一个 Token 的向量,能够代表整段 prompt 的语义含义,成为后续生成任务的主要依据。
Decoder Only 架构之所以成为当前大语言模型的主流选择,正是因为它很好地适应了"基于上下文进行生成"的需求。通过 Masked 自注意力机制,它能够在保持因果关系的前提下,实现高质量的文本生成和上下文理解。
核心机制:多头自注意力机制(Multi-Head Self Attention)
在 Transformer 架构中,多头自注意力机制(Multi-Head Self-Attention) 是编码器和解码器中最核心的组成部分。它取代了早期以 RNN 为核心的序列建模方式,带来了更高的效率与更强的建模能力。
从 RNN 到 Attention:序列建模的演进
在 Transformer 出现之前,RNN(循环神经网络) 是处理序列数据的主流方法。它的工作方式非常像人类阅读:逐字处理,每一步都依赖前一步的输出。
假设我们有1000个输入向量,RNN 的处理方式:
- 首先,从输入序列的第一个 Token <math xmlns="http://www.w3.org/1998/Math/MathML"> x 0 x_0 </math>x0 计算得到隐藏状态 <math xmlns="http://www.w3.org/1998/Math/MathML"> z 0 z_0 </math>z0,表示第一个 Token 的语义信息;
- 接着,从上一个隐藏状态 <math xmlns="http://www.w3.org/1998/Math/MathML"> z 0 z_0 </math>z0 和当前 Token <math xmlns="http://www.w3.org/1998/Math/MathML"> x 1 x_1 </math>x1 通过非线性变换计算出新的隐藏状态 <math xmlns="http://www.w3.org/1998/Math/MathML"> z 1 z_1 </math>z1,代表前两个 Token 的综合表示;
- 依此类推,每一步都基于上一步的状态 <math xmlns="http://www.w3.org/1998/Math/MathML"> z t − 1 z_{t-1} </math>zt−1和当前Token <math xmlns="http://www.w3.org/1998/Math/MathML"> x t x_t </math>xt计算新的隐藏状态 <math xmlns="http://www.w3.org/1998/Math/MathML"> z t z_t </math>zt ,最终得到的 <math xmlns="http://www.w3.org/1998/Math/MathML"> z 999 z_{999} </math>z999 代表整个输入序列的语义表示。
这种方式使得 RNN 能够在理论上建模任意长度的序列。但它存在几个显著问题:
- 信息遗忘:随着序列变长,早期信息在传递过程中容易被逐步覆盖或丢失,影响模型对长程依赖的建模能力。
- 无法并行计算:每一步都依赖前一步的输出,无法并行计算,导致训练效率低下。
- 长序列建模能力有限:受限于梯度消失或爆炸问题,难以有效捕捉非常长序列中的复杂依赖关系。
为了解决这些问题,Transformer 引入了 注意力机制(Attention) ,开启了序列建模的新时代。
注意力机制(Attention):QKV 的定义与计算
注意力机制的核心公式如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V </math>Attention(Q,K,V)=softmax(dk QKT)V
其中:
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> Q Q </math>Q:查询(Query)矩阵,表示当前关注的内容;
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> K K </math>K:键(Key)矩阵,表示可被关注的内容;
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> V V </math>V:值(Value)矩阵,表示每个内容的实际信息;
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> d k d_k </math>dk:键向量的维度,用于缩放以稳定梯度。
注意力机制的工作原理:
- 给定一个查询 <math xmlns="http://www.w3.org/1998/Math/MathML"> Q Q </math>Q,模型会计算它与所有键 <math xmlns="http://www.w3.org/1998/Math/MathML"> K K </math>K 的相似度;
- 然后基于这些相似度,对值 <math xmlns="http://www.w3.org/1998/Math/MathML"> V V </math>V 进行加权求和,得到最终输出;
这种机制通过计算相似度,让模型能够"聚焦"在最相关的信息上。
简单来说,你可以把注意力机制想象成一个"注意力选择器":
- Q(查询):我此刻想知道什么?
- K(键):这些信息的主题是什么?
- V(值):这些信息的具体内容是什么?
当模型计算出 Q 和 K 的相似度(也就是注意力权重)后,它就用这些权重去"读取"对应的 V,从而获得最相关的信息。
我们可以通过下面的例子更直观地理解它的工作原理:
假设我们有一个心理咨询常见问题与回应的知识库,当用户提出一个情绪困扰问题(Q)时,模型通过注意力机制找到最匹配的历史问题(K),然后找到对应的建议(V),并计算最终的输出。
- Q:我最近总是感觉很焦虑,晚上也睡不好,怎么办?
- K、V:知识库中的问题集合(键 K)及对应建议(值 V)
问题(K) | 建议(V) |
---|---|
最近总是很焦虑,睡不着怎么办? | 可以尝试睡前冥想或深呼吸练习。 |
工作压力大导致失眠怎么办? | 尝试调整作息,避免睡前使用手机。 |
情绪低落时如何自我调节? | 多与朋友沟通,适当运动有助于缓解情绪。 |
焦虑情绪会影响睡眠吗? | 是的,焦虑会加重入睡困难,建议寻求专业帮助。 |
有没有适合缓解焦虑的放松技巧? | 可以尝试渐进式肌肉放松或正念练习。 |
首先,把这些文本都处理成向量。
注意力机制的计算过程:
- 计算相似度 :模型计算查询 Q 与每个键 K 的语义相似度。在这个例子中,相似度系数分别为:
0.48、0.25、0.10、0.40 和 0.30
。 - 加权求和 :根据相似度系数对值 V 进行加权求和。比如,
0.48×"尝试睡前冥想或深呼吸练习。"+0.40×"建议寻求专业帮助。"+...0.48×"尝试睡前冥想或深呼吸练习。"+0.40×"建议寻求专业帮助。"+...
最后,模型综合了几个最相关的问题建议,生成最终输出:"你目前的焦虑和失眠可能是相互影响的。可以尝试睡前冥想或深呼吸等放松练习。如果持续困扰你,建议寻求专业帮助。"
通过这个计算过程可以看到,注意力机制通过计算查询(Q)和键(K)之间的相似度,实现了信息的选择性聚焦,这就是"注意力"的含义,它本质上是一种允许模型对输入序列中不同部分给予不同权重的方法。
自注意力机制(Self Attention):信息聚合的核心
在LLM场景中,当注意力机制的 <math xmlns="http://www.w3.org/1998/Math/MathML"> Q , K , V Q, K, V </math>Q,K,V 都来自输入序列本身时,就构成了 自注意力机制(Self Attention)。它是 Transformer 的核心,用于捕捉序列内部的依赖关系。
自注意力机制中的线性变换设计
在自注意力机制中,输入的 Token 向量并不会直接作为 <math xmlns="http://www.w3.org/1998/Math/MathML"> Q , K , V Q, K, V </math>Q,K,V 使用,而是分别通过三个可学习的线性变换矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> W Q , W K , W V W_Q, W_K, W_V </math>WQ,WK,WV 得到这三个向量。
<math xmlns="http://www.w3.org/1998/Math/MathML"> Q , K , V Q, K, V </math>Q,K,V 向量在自注意力机制中扮演了不同的角色,因此这三个矩阵应该从输入的Token向量中提取对应的特征:
- <math xmlns="http://www.w3.org/1998/Math/MathML"> W Q W_Q </math>WQ:决定当前 Token 作为"查询"时,应该关注哪些其他 Token;
- <math xmlns="http://www.w3.org/1998/Math/MathML"> W K W_K </math>WK:决定当前 Token 作为"键"时,哪些查询会关注它;
- <math xmlns="http://www.w3.org/1998/Math/MathML"> W V W_V </math>WV:决定当前 Token 作为"值"时,它将向关注它的查询传递哪些信息。
这三个矩阵是模型训练过程中可学习的参数,使得模型能够根据任务目标自动优化每个 Token 在注意力机制中的"角色",从而提升整体建模能力。
基于自注意力机制的信息聚合
具体来说,在 LLM 的自注意力机制中,模型会以每个Token向量作为中心,对上下文中的信息进行聚合:
- 每个中心Token对应的向量被用作查询(Q),而序列中所有Token的向量则分别作为键(K)和值(V)。对于每一个Q,模型会计算它与所有K之间的相似度(或称为相关性),从而生成一个注意力权重矩阵,该矩阵反映了当前Token与上下文中其他Token之间的相关程度;
- 随后,这些注意力权重会被用于对值向量(V)进行加权求和,从而生成该Token的新表示。
这种机制使得每个Token不仅能关注自身的语义信息,还能动态地聚焦于与其最相关的其他位置的信息,从而实现对整个输入序列上下文的深入理解。
我们来看一个例子。假设让模型理解一句话:
"小明在公园里跑步,他觉得很放松。"
现在模型正在处理"他"这个 Token向量:
-
模型想知道"他"指的是谁(这就是 Q);
-
然后,模型去上下文(所有K)中寻找"他"可能的指代对象(计算查 Q 与所有键 K 之间的相似度)。在这个例子中,"小明"是最有可能的指代对象;
-
找到了"小明"之后,模型会从"小明"(K)对应的值向量 V 中提取相关信息。例如,"性别为男"、"正在跑步"、"感到放松"等;
-
最终,模型将这些从值向量 V 中提取的信息加权聚合到"他"这个Token向量的表示中,从而更新或丰富了对"他"的理解,使其包含了来自"小明"的语义信息。
自注意力机制的核心优势
自注意力机制的核心优势可以总结为:
- 信息聚合:自注意力机制允许每个Token(例如"他")不仅关注到自身,还能通过查询(Q)、键(K)和值(V)的计算,"看到"整个输入序列的信息,从而捕捉长距离依赖关系。
- 动态建模:自注意力机制能够根据 Token 之间的语义相似度自动调整注意力权重,使模型能灵活聚焦于最相关的上下文信息。例如,模型会发现"他"与"小明"之间的关联性最强(相似度得分较高),这导致了从"小明"的值向量中提取的信息被赋予更高的权重,进而更强烈地影响最终的输出表示。
- 并行处理:在自注意力机制中,所有的 Q,K,V 都是直接从输入序列计算出来的,并且可以在并行完成相似度的计算和值向量的加权求和。这极大地提高了处理速度,并且避免了梯度消失问题。
因此,自注意力机制能够有效地捕捉长距离依赖关系,并克服了传统循环神经网络(RNNs)中存在的梯度消失问题,同时支持更高的并行化处理效率,是现代深度学习模型中处理序列数据的一项关键技术。
多头自注意力机制(Multi-Head Self Attention):多视角建模
尽管这种(单头)自注意力机制已经非常强大,能够捕捉到输入序列中的关键依赖关系,但它使用单一的注意力模式,在建模时只能从一个角度关注上下文中的信息。
为了进一步增强模型的表达能力,Transformer 引入了多头自注意力机制,实现从多个视角对输入进行建模。
"多头"的含义是:使用多组不同的 <math xmlns="http://www.w3.org/1998/Math/MathML"> Q , K , V Q, K, V </math>Q,K,V 投影矩阵( <math xmlns="http://www.w3.org/1998/Math/MathML"> W q , W k , W v W_q, W_k, W_v </math>Wq,Wk,Wv)对输入向量进行处理,每组都是一个独立的"头"(Head),从不同角度提取信息。
- 每个头关注不同的语义关系或位置依赖,例如有的头可能更关注句法结构,有的则更关注语义角色或情感倾向;
- 最终将多个头的结果拼接在一起,并通过一个输出矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> W O W_O </math>WO 进行线性投影整合,生成统一的输出表示;
通过这种多头的处理方式,模型在每一层都能同时学习到多种不同类型的上下文关系,极大地增强了其表达能力和泛化能力。
使用多头机制的好处:
-
充分利用高维空间:高维的输入向量蕴含了极其丰富的语义信息,单头注意力无法充分挖掘其全部潜力;
-
多角度建模:每个头可以学习不同的特征,例如有的关注句法结构,有的关注语义角色,有的关注情感色彩;
-
增强模型鲁棒性:多头机制使得模型在面对歧义或复杂语境时,能够综合多个视角做出更准确的判断。
多头自注意力机制的工作原理
多头自注意力机制的核心思想是通过并行地使用多个注意力头(Attention Head) ,让模型能够从多个不同的表示空间中提取信息,从而捕捉更丰富、更全面的上下文语义。
具体流程如下:
-
输入表示 :假设输入是一个 Token 序列,每个 Token 已经通过 Embedding 层被表示为一个向量,维度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> d model d_{\text{model}} </math>dmodel;
-
线性变换 :每个 Token 向量会分别通过 <math xmlns="http://www.w3.org/1998/Math/MathML"> h h </math>h 组(头)可学习的投影矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> W Q , W K , W V W_Q, W_K, W_V </math>WQ,WK,WV,生成对应的查询( <math xmlns="http://www.w3.org/1998/Math/MathML"> Q Q </math>Q)、键( <math xmlns="http://www.w3.org/1998/Math/MathML"> K K </math>K)和值( <math xmlns="http://www.w3.org/1998/Math/MathML"> V V </math>V)向量。对于每个头 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i:
- <math xmlns="http://www.w3.org/1998/Math/MathML"> Q i = X W Q i , K i = X W K i , V i = X W V i Q_i = X W_{Q_i},\quad K_i = X W_{K_i},\quad V_i = X W_{V_i} </math>Qi=XWQi,Ki=XWKi,Vi=XWVi
-
降维处理 :为了保持计算效率,通常会将每个头的向量维度设置为 <math xmlns="http://www.w3.org/1998/Math/MathML"> d k = d model / h d_k = d_{\text{model}} /h </math>dk=dmodel/h,这样总计算量保持不变;
-
多头并行计算:每个头独立地执行注意力计算:
- <math xmlns="http://www.w3.org/1998/Math/MathML"> Attention ( Q i , K i , V i ) = softmax ( Q i K i T d k ) V i \text{Attention}(Q_i, K_i, V_i) = \text{softmax}\left(\frac{Q_i K_i^T}{\sqrt{d_k}}\right) V_i </math>Attention(Qi,Ki,Vi)=softmax(dk QiKiT)Vi
- 这样,每个头从不同的语义或结构角度理解输入。
-
拼接与融合 :将所有头的输出向量在维度上拼接起来,再通过一个输出矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> W O W_O </math>WO 进行线性变换,得到最终的多头注意力输出:
- <math xmlns="http://www.w3.org/1998/Math/MathML"> MultiHead ( Q , K , V ) = Concat ( head 1 , head 2 , . . . , head h ) W O \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \text{head}_2, ..., \text{head}_h) W_O </math>MultiHead(Q,K,V)=Concat(head1,head2,...,headh)WO
- 其中: <math xmlns="http://www.w3.org/1998/Math/MathML"> head i = Attention ( Q i , K i , V i ) \text{head}_i = \text{Attention}(Q_i, K_i, V_i) </math>headi=Attention(Qi,Ki,Vi)
通过这种方式,模型不仅能够捕捉到不同的语义关系,还能增强对复杂语言结构的建模能力,使得 Transformer 在各种自然语言任务中表现出色。
掩码自注意力机制(Masked Self Attention):保证生成过程的因果性
在 Decoder Only 模型(如 GPT 系列)中,为了保证生成过程的因果性(即不能看到未来 Token),自注意力机制会引入掩码(Masked):
- 每个 Token 只能关注它前面的 Token;
- 不能向后看,确保生成过程是"续写";
这是实现语言模型自回归生成的关键机制。
掩码如何结合到注意力机制中?
具体来说,掩码的作用是修改注意力权重计算公式中的得分矩阵,使得模型不能"看到"未来的信息。
标准的自注意力计算公式为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> Attention ( Q i , K i , V i ) = softmax ( Q i K i T d k ) V i \text{Attention}(Q_i, K_i, V_i) = \text{softmax}\left(\frac{Q_i K_i^T}{\sqrt{d_k}}\right) V_i </math>Attention(Qi,Ki,Vi)=softmax(dk QiKiT)Vi
其中:
-
<math xmlns="http://www.w3.org/1998/Math/MathML"> Q i , K i , V i Q_i, K_i, V_i </math>Qi,Ki,Vi 分别是第 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i 个头的查询、键和值向量。
-
注意力得分矩阵 就是: <math xmlns="http://www.w3.org/1998/Math/MathML"> Scores = Q i K i T d k \text{Scores} = \frac{Q_i K_i^T}{\sqrt{d_k}} </math>Scores=dk QiKiT
为了实现因果性,我们需要在计算注意力得分矩阵时加入一个下三角掩码矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> M M </math>M。对于长度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n 的序列,它的形式如下:
matlab
[[0, -inf, -inf, ..., -inf],
[0, 0, -inf, ..., -inf],
[0, 0, 0, ..., -inf],
...,
[0, 0, 0, ..., 0]]
其中,-inf
表示负无穷大,用于在 Softmax 后将这些位置的权重压缩为 0。
掩码机制的关键就是这个下三角掩码矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> M M </math>M。在计算相似度时,确保前面的 Token 保留正常的相似度得分,而后面的 Token 获得极低的相似度得分(如 -∞),从而在 Softmax 后这些未来的 Token 权重接近零,使得它们不会被当前 Token "看到"。
应用掩码后的得分矩阵为: <math xmlns="http://www.w3.org/1998/Math/MathML"> Scores masked = Scores + M \text{Scores}_{\text{masked}} = \text{Scores} + M </math>Scoresmasked=Scores+M
因此,完整的带掩码注意力公式为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> Attention ( Q i , K i , V i ) = softmax ( Q i K i T + M d k ) V i \text{Attention}(Q_i, K_i, V_i) = \text{softmax}\left( \frac{Q_i K_i^T + M}{\sqrt{d_k}} \right) V_i </math>Attention(Qi,Ki,Vi)=softmax(dk QiKiT+M)Vi
延伸:优化 KV Cache 的注意力机制
在自注意力机制中,每个新生成的 Token 都需与历史 Token 计算注意力权重,导致计算量随序列长度增长而显著上升。为此,实际推理中广泛采用 KV 缓存(Key-Value Cache)机制,即在生成过程中将之前 Token 的 K 和 V 缓存起来,避免重复计算,从而大幅提升解码效率。
- 优势:显著减少计算量,提高推理速度;
- 挑战:随着上下文长度(Context Length)增加,KV 缓存占用显存越来越大,可能超出单张显卡甚至整台服务器的容量。
为了在有限硬件资源下支持更长的上下文,研究者提出了多种优化 KV Cache 的注意力机制:
方法 | 简介 | KV 共享方式 | 缓存大小 | 特点 |
---|---|---|---|---|
MHA(Multi-Head Attention) | 标准注意力机制,每个头独立计算 | 每个头都有独立的 <math xmlns="http://www.w3.org/1998/Math/MathML"> 和 和 </math>和 | 原始大小 | 表达能力强,结构完整,但显存占用高 |
MQA(Multi-Query Attention) | 轻量化方案,减少显存占用 | 所有头共享同一组 <math xmlns="http://www.w3.org/1998/Math/MathML"> 和 和 </math>和 | 减少到 1/h(h 为头数) | 显存占用最低,适合长上下文,但表达能力受限 |
GQA(Grouped-Query Attention) | MHA 与 MQA 的折中方案 | 将头分为 g 组,每组共享一对 <math xmlns="http://www.w3.org/1998/Math/MathML"> 和 和 </math>和 | 减少到 1/g(g 为组数) | 在效率与效果之间取得平衡,适合多卡并行 |
MLA(Multi-head Latent Attention) | GQA 的进一步优化,引入低秩压缩 | 使用低秩矩阵替代分组与重复操作 | 可进一步压缩 | 引入旋转位置编码,兼顾压缩效率与建模能力,是当前前沿方案之一 |
在LLM的实际推理过程中,通常分为两个关键阶段:预填充(Prefill)和生成(Generation),这两个阶段在计算模式和资源需求上具有显著差异。
-
Prefill 阶段(预填充)
- 处理用户输入的所有 Token,并行计算每个 Token 的 <math xmlns="http://www.w3.org/1998/Math/MathML"> Q , K , Q, K, </math>Q,K,,并且 将 <math xmlns="http://www.w3.org/1998/Math/MathML"> K , V K, V </math>K,V 存入 KV 缓存;
- 该阶段计算密集,是计算、显存和带宽的主要瓶颈;
- 为了保证上下文建模的精度,通常在此阶段使用 MHA(Multi-Head Attention) 模式。
-
Generation 阶段(生成)
- 模型逐个 Token 地生成输出,每个新 Token 仅需计算其对应的 Q,而复用 KV 缓存中已有的 K 和 V;
- 此阶段主要受限于显存带宽和缓存访问效率;
- 为了提升推理速度并降低资源消耗,可以采用 MQA(Multi-Query Attention) 或 MLA(Multi-head Latent Attention) 等轻量化注意力机制进行加速。
随着大语言模型对长上下文支持和推理效率的要求不断提高,KV Cache 的优化成为关键。MLA(Multi-head Latent Attention) 作为当前最先进的方案,通过低秩压缩和位置编码优化,进一步提升了效率与建模能力。
Feed Forward Network(FFN):非线性特征提取
在解码器的每一轮处理中,多头自注意力机制(Multi-Head Self-Attention, MHA) 之后,还会经过一个 前馈神经网络(Feed-Forward Network, FFN),用于进一步提炼和筛选特征。
FFN 通常由两个全连接层组成,记作 <math xmlns="http://www.w3.org/1998/Math/MathML"> W 1 W_1 </math>W1 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> W 2 W_2 </math>W2,其典型结构如下:
- 第一层:将输入向量从原始维度(如 12288)映射到一个更高维的空间(如 49152),实现特征的非线性扩展;
- 第二层:再将高维表示压缩回原始维度(如 12288),完成信息的再组合与筛选;
- 两层之间通常引入一个非线性激活函数(如 GELU),以增强模型的表达能力。
引入 FFN 的目的在于:在 MHA 提取的上下文信息基础上,进一步进行局部特征的非线性建模和抽象表示的学习。
虽然 MHA 和 FFN 都用于特征提取,但它们的工作方式有本质区别:
- MHA(多头自注意力):是一种结构化的建模方式。它通过查询(Q)、键(K)、值(V)之间的交互机制,在全局上下文中提取 Token 之间的依赖关系。整个过程具有明确的逻辑流程,是模型"显式"理解上下文的核心机制。
- FFN(前馈网络):则是一种数据驱动的建模方式。它通过大规模参数和非线性变换,从数据中学习复杂的抽象特征,具备更高的灵活性和泛化能力。
简而言之,MHA 是结构化建模,FFN 是数据驱动建模,二者相辅相成,共同构成了 Transformer 的强大表达能力。
小结
Transformer 的核心在于 多头自注意力机制,它让模型能够高效地建模长距离依赖,取代了传统的 RNN。
同时,自注意力机制 和 前馈神经网络 分工明确,一个负责结构化建模,一个负责数据驱动的特征提取,二者结合使得 Transformer 成为了当前大语言模型的基石。
总结:Transformer 的过去、现在与未来
Transformer 自 2017 年提出以来,凭借其并行化能力 和强大的上下文建模机制,彻底改变了自然语言处理领域,成为现代大语言模型的基石。它通过自注意力机制让模型在处理语言时"看到"整个上下文,并通过多头机制、前馈网络、位置编码等模块,构建出高效、灵活的语言理解与生成能力。
Transformer 架构不仅是语言模型的核心,也是模型训练和生成的基础平台。无论是从零开始的预训练,还是针对特定任务的微调,Transformer 提供了一个统一且高效的框架,使得大规模数据集上的训练变得可行。
如今,Transformer 已不仅限于最初的结构。现代模型在原始架构基础上进行了多项增强与优化,包括:
- 更高效的注意力机制:如稀疏注意力、线性注意力、MQA / MLA,提升长文本处理效率;
- 位置编码的改进:从绝对位置编码到相对位置编码(如 RoPE),增强模型对位置信息的建模能力;
- KV 缓存机制与解码优化:显著提升推理速度与资源利用率;
- 模型结构压缩与量化:使大模型更轻量、更易部署;
- 可扩展性增强:如 MoE(Mixture of Experts)结构,让模型在参数规模增长的同时保持高效训练与推理。
可以说,Transformer 不仅是大语言模型的核心架构,更是推动 AI 语言能力持续进化的关键引擎。未来,随着对效率、可解释性与泛化能力的进一步探索,Transformer 及其变体仍将是 AI 领域最核心的技术之一。