LLM底层秘密—Transformer原理解析
语言模型的发展经历了从 BERT、GPT 到今天的多模态大模型的快速演进。传统 Transformer 在处理长文本、关键信息检索以及对抗幻觉等任务时,常常因过度关注无关上下文而陷入困境,导致模型表现受限。为解决这些问题,研究人员提出了多种改进方案,如 DIFF Transformer、Energy-Based Transformer 等新型架构。Transformer、MoE 灵活搭配成为主流,

语言模型的发展经历了从 BERT、GPT 到今天的多模态大模型的快速演进。传统 Transformer 在处理长文本、关键信息检索以及对抗幻觉等任务时,常常因过度关注无关上下文而陷入困境,导致模型表现受限。为解决这些问题,研究人员提出了多种改进方案,如 DIFF Transformer、Energy-Based Transformer 等新型架构。
Transformer、MoE 灵活搭配成为主流,也逐渐有加入等新兴架构做混合架构的尝试,据不完全统计,超过一半新发布模型采用混合架构。这种架构创新也许可以打破 “提升性能必增成本” 的困境,为 LLM 的高效部署提供了新的可能性。
Transformer架构的核心是Encoder-Decoder结构,编码器负责将输入序列转换为上下文表示,解码器则基于编码器的输出和已生成的输出序列生成下一个输出。
当前主流的LLM架构是只有解码器的模型(Decoder-only Transformer),包含自主力(Self-Attention)和多头注意力(Multi-Head Attention)的注意力层、前馈神经网络(FFN),注意力层+FFN等模块组成其中一层,多层堆叠,构成一个Decoder-only Transformer模型,层数通常根据任务复杂度而定,层数越多,模型越深,模型效果越好。但是,模型太深,计算量太大,导致训练困难,所以需要一个取舍,层数通常是经验和实战的选择。
Token数据流示例
举例把"Transformer is powerful."翻译成"Transformer很强大。“时,翻译到"Transformer很"时,解码器已经生成了序列,此时解码器需要根据已生成序列和上下文向量,预测下一个中文词,即"强”,已知的Tokens "Transformer很"输入时,数据流是经过每一层的。
生成Q向量:此时,解码器已经生成了“Transformer 很”。这个已生成的部分序列经过解码器内部的掩码自注意力层处理后,会生成一个代表当前状态(即准备生成下一个词)的查询向量 Q_decoder。
提供K、V向量:编码器已经为英文句子“Transformer is powerful.”生成了一个完整的输出矩阵。这个矩阵中的每一行都是一个K-V对,分别代表了“Transformer”、“is”、“powerful”和“.”的键和值信息。
计算注意力权重:模型会计算 Q_decoder 与所有英文词的K向量的点积,得到一个注意力分数向量。经过Softmax归一化后,这个分数向量就变成了权重向量。我们期望在这个权重向量中,对应“powerful”的权重会非常高。
加权求和:最后,模型用这个权重向量对所有英文词的V向量进行加权求和,得到一个上下文向量。这个向量主要包含了来自“powerful”的信息,并被传递给解码器的下一层,用于最终预测出下一个中文词“强”。
通过这个过程,模型成功地将源语言中的“powerful”与目标语言中的“强”对齐了起来,实现了精准的翻译。
分词(token)
这一部分的实现基本原理在此前的文章中已经介绍过,可参阅LLM学习笔记:最好的学习方法是带着问题去寻找答案》。 举个例子,比如“Transformer is powerful.”,分词后得到“Transformer”、“is”、“powerful”、“.”,其中“.”是句子结束符,表示句子结束,不参与预测
还想补充的是,我个人的一种理解方式,可以认为分词就是为了得到一本字典的索引(目录),在transformer预测下一个词时,根据当前用户的输入以及已有的预测输出,去匹配字典中的词,找到最匹配的词,然后输出。
这是一种很直观的理解方式,省略了很多细节,比如词嵌入的实现方式,词嵌入的维度,词嵌入的优化方式等,但是这种理解方式,可以让我们对分词有一个直观的认识。 当然,如果只是完全随机在字典里去找下一个词,我们的模型就会表现得很诡异,LLM说出来的话也完全没有意义。所以我们通过设计模型架构,通过嵌入、词位置、神经网络权重调整、注意力机制等手段,在训练中让随机变得逐渐有规律可循。 就好比斑马,在出生前,通过DNA表达在娘胎里构建了基础的大脑结构,刚出生几十分钟后就可以跟随母亲在草原上奔跑,而不是让肌肉随机抽搐。
在分词之后,下一步是为所有可能出现的词元构建一个词汇表(Vocabulary)。词汇表是一个从词元到唯一整数ID的映射。例如,我们可以为英文和中文分别构建词汇表:
英文词汇表示例:
中文词汇表示例:
嵌入(embedding)
把我们的示例词嵌入向量 (维度=4):
字典的类比
分词是得到了一本字典的目录,我们想要知道下一个词是什么,就需要去字典里找与上下文最相关的那个词。但如果只有字典目录,也就是只有字,没有词的释义,很难匹配出最相关的词,于是只能随机表达,让肌肉无规律抽搐。所以我们需要给每个词一个 “释义”,这个释义就是词嵌入,也就是把词(token)转换为数学表示映射到高维空间中,这样就可以通过计算两个词的距离,来计算两个词的相关性。就好比我们给字典里的每个词都通过N多个字(一个一维的长序列)把这个字的含义解释清楚,编一个页码;类似的LLM中的词嵌入就是通过高维空间来表示一个词(token),这样就可以通过计算两个词的向量距离(点积),来计算两个token的相关性。
中文字典的索引和字的解析如下图:
字典的类比
分词是得到了一本字典的目录,我们想要知道下一个词是什么,就需要去字典里找与上下文最相关的那个词。但如果只有字典目录,也就是只有字,没有词的释义,很难匹配出最相关的词,于是只能随机表达,让肌肉无规律抽搐。所以我们需要给每个词一个 “释义”,这个释义就是词嵌入,也就是把词(token)转换为数学表示映射到高维空间中,这样就可以通过计算两个词的距离,来计算两个词的相关性。就好比我们给字典里的每个词都通过N多个字(一个一维的长序列)把这个字的含义解释清楚,编一个页码;类似的LLM中的词嵌入就是通过高维空间来表示一个词(token),这样就可以通过计算两个词的向量距离(点积),来计算两个token的相关性。
中文字典的索引和字的解析如下图:
包括大语言模型在内的深度神经网络模型,没法直接处理我们平时看到的原始文本。为什么呢?因为文本数据是 “离散” 的 —— 简单说就是一个字、一个词都是单独的个体,不像数字那样能直接算,所以没办法直接用它做神经网络训练时需要的数学运算。这时候就需要一个办法:把单词变成一种 “连续值向量” 的格式,这样才能让模型用起来。
词嵌入的过程
包括大语言模型在内的深度神经网络模型,没法直接处理我们平时看到的原始文本。为什么呢?因为文本数据是 “离散” 的 —— 简单说就是一个字、一个词都是单独的个体,不像数字那样能直接算,所以没办法直接用它做神经网络训练时需要的数学运算。这时候就需要一个办法:把单词变成一种 “连续值向量” 的格式,这样才能让模型用起来。

可以看到举个实际的例子,最小的 GPT-2 模型(它的参数量是 1.17 亿),用的嵌入维度是 768;而 GPT-3 模型(参数量达到 1750 亿),嵌入维度就更高了,有 12288。
所以,按字典的方式理解分词和词嵌入,举例GPT-3的词汇表大小是50257个,词嵌入的维度是12288维,每个词用12288维度去解释,那么GPT-3的全部词汇嵌入矩阵就是5025712288=617558016大小,每个维度占据4字节(32位浮点数 FP32),所以GPT-3的词汇嵌入矩阵大小就是6175580164=2470232064字节,也就是2.34GB。
这里维度占据存储空间取决于模型运行时使用的数值精度(数值数据类型)。在深度学习领域,最常见的数据类型是32位浮点数(FP32)和16位浮点数(FP16/BF16)。
不仅是文本,像视频、音频这些不同类型的数据,也能通过专门的神经网络层,或者借助另一个提前训练好的神经网络模型,转换成这种神经网可用的数据格式,这个过程就叫 “嵌入”。 嵌入的分类:
说到底,嵌入的本质其实很简单: 把那些离散的东西(比如单个单词、一张图片,甚至一整篇文档),对应到一个连续的向量空间里,变成一个个 “点”。 这么做的主要目的,就是把文字、图像这种非数值的数据,转成神经网络能读懂、能处理的格式。
另外,词嵌入中 “维度” 可以从 1 维到几千维不等。一般来说,维度越高,越能捕捉到数据里那些细微的关系 —— 比如单词之间更复杂的关联。就好比我们用N个字来解释一个词(一维的长序列),解释篇幅越长,这个词的含义就会越能被清晰表达,在整本字典中的位置、与其他词之间的关系就能准确定位,但代价是我们要阅读更多的文字,字典会变得非常厚,我们的大脑也需要理解内化更多知识,超出人脑极限;据说汉字有两万多个,但我们日常常用的仅需四千多个就足够日常生活了,我们无法准确记忆字典每个词的释义,但我们认识的字对应的含义内化在我们的大脑的神经网络当中了。理解回LLM,维度越高我们的计算代价就更高,计算起来会更慢,效率会下降,所以还需要做出权衡。
为更清晰直观理解词嵌入,这里举例rojector.tensorflow 上Word2Vec词嵌入模型在200维度的情况对71291个词元的嵌入结果,再降维到3D,并可视化后的情况,可以直观的看到词元之间的空间情况。可以跳转网页上直观感受动画效果。
词嵌入的实现方式有很多种,如Word2Vec、GloVe、FastText、ELMo、BERT、GPT、GPT-2、GPT-3、GPT-4、GPT-5等,其中GPT-3参数量达到1750亿。
词嵌入外,在AI常见应用中,还有句子嵌入、段落嵌入、文档嵌入等,如RAG应用。
我们的世界还有声音、视频等其他格式的信息,它们之间又如何建立关联关系呢?比如一个多模态的LLM,就需要有这样的能力,这就要实现多模态对齐,需要将不同模态的词元嵌入到同一个空间中,才能进行比较。
位置编码(Positional Encoding)
Transformer模型的一个核心特点是其并行计算能力,它不像循环神经网络(RNN)那样按顺序处理序列。然而,这种并行性也带来了一个问题:模型本身无法感知词语在序列中的位置或顺序。为了解决这个问题,Transformer引入了位置编码(Positional Encoding)机制。位置编码是一组与词嵌入维度相同的向量,它被加到每个词的嵌入向量上,从而为模型提供关于词序的信息。这样,模型就能区分“狗咬人”和“人咬狗”这两种完全不同的含义。位置编码的设计需要满足几个条件:它应该为每个位置生成一个唯一的编码,并且能够处理任意长度的序列。
让我们为案例中的句子“Transformer is powerful.”添加位置编码。假设我们的嵌入维度是4,我们可以使用简化的位置编码函数来生成每个位置的编码向量。
在这个例子中,我们为每个位置的词元生成了一个独特的位置编码向量,并将其与词嵌入向量逐元素相加,输入嵌入=词元嵌入矩阵+位置编码矩阵。
位置编码的实现方式有很多种,大致分为两种:
绝对位置编码:直接与序列中的特定位置相关联。
相对位置编码:关注的是词元之间的相对位置或距离,而非它们的绝对位置。 输入嵌入经过归一化后,可以传递到注意力层。
注意力机制
编码器(Encoder)是Transformer模型的核心组件之一,其主要任务是接收经过预处理的输入序列(即融合了位置信息的词嵌入向量),并将其转换为一个富含上下文信息的特征表示。这个特征表示捕捉了输入句子中所有词语之间的复杂关系,包括语法结构和语义依赖。编码器由多个相同的层(layers)堆叠而成,每一层都包含两个主要的子层:一个多头自注意力层(Multi-Head Self-Attention)和一个简单的、位置全连接的前馈神经网络(Feed-Forward Network)。在每个子层周围都使用了残差连接(Residual Connection)和层归一化(Layer Normalization),以帮助模型更稳定地进行训练。通过这一系列操作,编码器能够逐步提炼输入序列的表示,为解码器生成目标序列提供全面的上下文信息。
为什么需要注意力机制?解决的是在预测下一个词时,要理解上下文的关系,才能更好的预测下一个词,让模型表现更好。好比别人给我们丢了一个问题,我脑袋空空,手上只有一本几万个字的字典,我怎样才能更好的回答这个问题呢?我需要先看下问题,然后看下问题中的关键词,再根据关键词去字典中找答案,这样就能更好的回答这个问题了。那如何能找到与问题最关联的下一个词呢?
这就需要使用注意力机制捕捉数据依赖关系,是现代深度学习模型中非常常见的做法。比如,我们想让模型理解 “我” 和 “你” 之间的关系,就可以用注意力机制,让模型 “看” 到 “我” 和 “你” 之间的关联。举个类比就是就像我们拿SQL语句去关系型数据库查询我们想要的数据一样,我们拿查询条件去匹配库表中的值,从而拿到我们想要的数据记录。当然,远没有那么简单,SQL语句是 “静态” 的,而模型是 “动态” 的,随着输出追加到输入后面再作为新的输入,整个上下文的词列表一直在变化,我们就需要重新计算注意力。
注意力机制包括:自注意力机制、多头注意力机制、位置编码、注意力机制的变体等。
自注意力机制
原理
传统的注意力机制关注的是两个不同序列元素之间的关系。在自注意力机制中,“自”指的是该机制通过关联单个输入序列中的不同位置来计算注意力权重的能力。核心思想:让每个词关注句子中的其他词。
它可以评估并学习输入本身各个部分之间的关系和依赖,比如句子中的单词或图片中的像素。如下图中的"doc"就需要计算整个输入序列中各个元素之间的关系,从而计算出每个元素对应的权重
,再以此计算出上下文向量。
在自注意力机制中,我们的目标是为输入序列中的每个元素计算上下文向量
。上下文向量(context vector)可以被理解为一种包含了序列中所有元素信息的嵌入向量。
一个输入序列,记为
,它由个元素组成,分别表示为到
。
嵌入化词元序列之间的注意力权重α= 注意力分数w的归一化
注意力分数
=词元
与其他词元的点积而得;点积值越大则这两个词元相似度越高(即对齐度越高)
注意力分数归一化softmax后得到每一个词元的注意力权重α,即获得总和为1的注意力权重。
位移词元下标i,循环以上步骤,将所有词元的注意力权重都计算出来。

案例拆解:分析“powerful”如何关联到“Transformer”
让我们回到案例“Transformer is powerful.”,并聚焦于单词“powerful”。在自注意力机制中,当模型处理“powerful”这个词时,它会生成一个查询向量Q_powerful。同时,句子中的每个词(包括“Transformer”、“is”和“.”)都会生成自己的键向量K和值向量V。接下来,Q_powerful会与K_Transformer、K_is、K_dot进行点积运算,计算出“powerful”与句子中其他每个词的相关性得分。由于“powerful”是用来描述“Transformer”的,我们可以预期Q_powerful与K_Transformer的点积结果会是一个较高的值。这个得分经过Softmax函数归一化后,会得到一个较高的注意力权重。同时,Q_powerful与K_is和K_dot的得分会相对较低,对应的注意力权重也较小。最后,模型会用这些权重对所有词的值向量(V_Transformer, V_is, V_dot)进行加权求和。由于V_Transformer的权重最大,其向量表示将对最终的上下文向量贡献最多。因此,“powerful”的最终表示将主要包含“Transformer”的信息,从而建立起“powerful”和“Transformer”之间的强关联。
为什么是Q、K、V?
在注意力机制的上下文中,K“键”、Q“查询”和V“值”这些术语是从信息检索和数据库领域借鉴来的,在这些领域中,类似的概念被用于存储、搜索和检索信息。关系型数据库的查询,我们有查询条件、查询索引、数据记录本身,我们通过查询条件(查询索引)去匹配数据记录(值),从而拿到我们想要的数据记录。而且为了查询效率,我们通常会使用B+树索引,而不是全表扫描。
与之类比的,自注意力机制也是通过查询、键和值来计算注意力权重,从而计算出上下文向量,且缓存了计算结果(K和V),在自回归模型中,可以避免重复计算,提高效率。缓存之前的计算结果(特别是注意力机制中的一些特定向量),就不需要重复计算之前的流,而只需要计算最后一条流。这种优化技术被称为键-值(key-value,KV)缓存,它能显著加快生成过程。
“查询”(query)类似于数据库中的搜索查询。它代表模型当前关注或试图理解的项目(例如,句子中的一个词或 Token)。查询用于探查输入序列的其他部分,以确定应该给予它们多少注意力。
“键”(key)类似于数据库中用于索引和搜索的键。在注意力机制中,输入序列中的每个项目(例如,句子中的每个词)都有一个关联的键。这些键用于与查询匹配。
“值”(value)在这个上下文中类似于数据库中键值对的值。它代表输入项目的实际内容或表示。一旦模型确定哪些键(哪些输入部分)与查询(当前关注项目)最相关,它就检索相应的值。




案例讲解:逐步生成翻译
现在,让我们完整地模拟解码器是如何一步步生成“Transformer很强大。”这个翻译结果的。这个过程是自回归的,每一步都依赖于前一步的输出。
第一步:生成“Transformer”
输入:<START> 标记。
过程:解码器接收到<START>标记,并结合编码器提供的关于整个英文句子的上下文信息。通过编码器-解码器注意力机制,模型发现当前最相关的信息是整个句子的主语“Transformer”。
输出:模型预测出第一个词是“Transformer”。
第二步:生成“很”
输入:<START> Transformer。
过程:解码器现在知道已经生成了“Transformer”。它通过掩码自注意力机制处理这个部分序列,并通过编码器-解码器注意力机制关注英文句子。此时,模型需要决定如何翻译系动词“is”。在中文里,“is”在这里被翻译为程度副词“很”,用来修饰后面的形容词。
输出:模型预测出下一个词是“很”。
第三步:生成“强”
输入:<START> Transformer 很。
过程:解码器处理已生成的部分,并通过编码器-解码器注意力机制,将注意力高度集中在英文单词“powerful”上。模型开始翻译“powerful”这个形容词,并首先生成其第一个字“强”。
输出:模型预测出下一个词是“强”。
第四步:生成“大”
输入:<START> Transformer 很 强。
过程:解码器继续处理,并再次关注“powerful”。它意识到“强大”是一个更完整的翻译,因此生成第二个字“大”来完成这个形容词。
输出:模型预测出下一个词是“大”。
第五步:生成句号“。”
输入:<START> Transformer 很 强 大。
过程:解码器注意到英文句子以句点“.”结束,并且根据已生成的完整中文句子,判断翻译已经完成。因此,它会生成一个对应的中文句号“。”。
输出:模型预测出下一个词是“。”。

更多推荐


所有评论(0)