大模型时代,你还不懂Transformer?(图解Transformer,一文搞懂)
Transformer模型是由Vaswani等人在2017年发表的论文 《Attention is All You Need》 中提出的。该模型的核心创新在于自注意力机制(Self-Attention),它通过对全局上下文依赖关系进行并行计算,有效解决了传统RNN和CNN在处理长序列时存在的效率与长程依赖问题。自注意力机制能够让模型动态地关注输入序列中的不同位置,同时结合多头注意力(Multi-H
1、Transformer前世今生
Transformer模型是由Vaswani等人在2017年发表的论文 《Attention is All You Need》 中提出的。该模型的核心创新在于自注意力机制(Self-Attention),它通过对全局上下文依赖关系进行并行计算,有效解决了传统RNN和CNN在处理长序列时存在的效率与长程依赖问题。自注意力机制能够让模型动态地关注输入序列中的不同位置,同时结合多头注意力(Multi-Head Attention)来增强语义捕捉能力,还通过位置编码(Positional Encoding)将序列顺序信息引入模型。
Transformer架构凭借自注意力机制和并行化处理方式,为大语言模型奠定了基础。其编码器 - 解码器结构催生了两大发展方向,分别是用于理解任务的BERT和用于生成任务的GPT。并且,通过诸如T5、RoBERTa等模型优化以及跨模态扩展(如ViT),Transformer持续推动着NLP与AI领域的发展。

- 机器翻译的突破:Transformer最初应用于神经机器翻译(NMT),如Google的翻译系统。其编码器-解码器结构显著提升了翻译质量,成为行业新标准。编码器负责提取源语言特征,解码器则生成目标语言序列,实现了高效并行化处理。
- 双向上下文理解:2018年,Google基于Transformer编码器开发了BERT(Bidirectional Encoder Representations from Transformers)。BERT通过掩码语言建模(MLM)和下一句预测(NSP)任务进行预训练,实现双向上下文理解,广泛应用于问答、分类等自然语言理解任务。例如,BERT在GLUE和SQuAD等基准测试中刷新了性能纪录。
- 自回归文本生成:OpenAI的GPT系列(如GPT-1至GPT-3)基于Transformer解码器,采用自回归训练方式逐词生成文本。GPT模型通过大规模预训练学习语言模式,并在微调后适配多种任务(如文本生成、对话系统)。尤其是GPT-3(1750亿参数)展示了强大的少样本和零样本学习能力,推动了生成式AI的发展。
2、黑盒子解释
我们先把模型看作一个黑盒子。在机器翻译应用中,它会接受一种语言的句子,然后输出另一种语言的翻译。

打开黑盒子我们可以看到一个编码组件、一个解码组件以及它们之间的连接。

编码组件是一堆编码器
(论文中将六个编码器堆叠在一起——“六”这个数字并没有什么神奇之处,当然可以尝试其他排列方式)。
解码组件是一堆相同数量的解码器。

所有编码器的结构完全相同(但它们不共享权重)。每个编码器又分为两个子层:

编码器的输入首先会经过一个自注意力层——该层帮助编码器在编码特定单词时查看输入句子中的其他单词。我们将在本文的后面更深入地探讨自注意力机制。
自注意力层的输出被馈送到前馈神经网络。完全相同的前馈网络独立地应用于每个位置。
解码器具有这两个层,但它们之间是一个注意层(Encoder和Decoder交互部分的注意力机制),可帮助解码器关注输入句子的相关部分(类似于 seq2seq 模型 中的注意力机制)。

这也就是Transformer的整体结构
3、将张量可视化
现在我们已经了解了模型的主要组成部分,让我们开始看看各种向量/张量以及它们如何在这些组成部分之间流动以将训练模型的输入转换为输出。
与一般的 NLP 应用程序一样,我们首先使用**嵌入算法[7]**将每个输入词转换为向量。

每个单词都嵌入到一个大小为 512 的向量中。我们将用这些简单的盒子来表示这些向量。
嵌入仅发生在最底层的编码器中。所有编码器的共同抽象是,它们接收一个大小为 512 的向量列表——在底层编码器中,这将是词嵌入,但在其他编码器中,它将是正下方编码器的输出。这个列表的大小是我们可以设置的超参数——基本上,它是我们训练数据集中最长句子的长度。
将单词嵌入到我们的输入序列中后,每个单词都会流经编码器的两层中的每一层。

这里我们开始看到 Transformer 的一个关键特性:每个位置上的单词在编码器中都会流经其自身的路径。在自注意力层中,这些路径之间存在依赖关系。然而,前馈层没有这些依赖关系,因此各个路径可以在流经前馈层时并行执行。
接下来,我们将示例切换为更短的句子,并查看编码器的每个子层中发生的情况。
4、编码器端
正如我们已经提到的,编码器接收一个向量列表作为输入。它通过将这些向量传递到“自注意力”层来处理该列表,然后传递到前馈神经网络,最后将输出向上发送到下一个编码器。

每个位置上的单词都会经过一个自注意力过程。然后,它们会分别经过一个前馈神经网络——完全相同的网络,每个向量都会分别流经它。
自注意力机制
别被我随口说出“自注意力”这个词给骗了,好像它是个大家都应该熟悉的概念。我个人在读到《注意力就是你所需要的一切》这篇论文之前从未接触过这个概念。让我们来提炼一下它的工作原理。
假设以下句子是我们要翻译的输入句子:
”The animal didn't cross the street because it was too tired”
这句话里的“它”指的是什么?它指的是街道还是动物?对人类来说,这是一个简单的问题,但对算法来说却并非如此简单。
当模型处理“it”这个词时,自注意力机制让模型将“it”与“animal”联系起来。
当模型处理每个单词(输入序列中的每个位置)时,自我注意力机制允许它查看输入序列中的其他位置,以寻找有助于更好地编码该单词的线索。
如果你熟悉 RNN,不妨想象一下,保持隐藏状态如何让 RNN 将其之前处理过的单词/向量的表示与当前正在处理的单词/向量结合起来。自注意力机制是 Transformer 用来将对其他相关单词的“理解”融入当前正在处理的单词/向量的方法。

当我们在编码器5(堆栈中的顶部编码器)中对单词“it”进行编码时,注意力机制的一部分集中在“The Animal”上,并将其部分表示融入到“it”的编码中。
请务必查看 Tensor2Tensor 笔记本,您可以在其中加载 Transformer 模型,并使用此交互式可视化进行检查。

自注意力机制详解
我们先来看看如何使用向量来计算自我注意力,然后再看看它是如何实际实现的——使用矩阵。
计算自注意力机制的第一步是从编码器的每个输入向量(在本例中是每个单词的嵌入向量)创建三个向量。因此,对于每个单词,我们创建一个查询向量、一个键向量和一个值向量。这些向量是通过将嵌入向量乘以我们在训练过程中训练的三个矩阵而创建的。 请注意,这些新向量的维度小于嵌入向量。它们的维度为 64,而嵌入向量和编码器的输入/输出向量的维度为 512。它们不必更小,这是一种架构选择,目的是使多头注意力的计算(大部分)保持恒定。

将 x1 乘以 WQ 权重矩阵,得到 q1 ,即与该词相关的“查询”向量。最终,我们为输入句子中的每个单词创建了“查询”、“键”和“值”的投影。
什么是“查询Q”、“键K”和“值V”向量?
它们是用于计算和思考注意力机制的抽象概念。一旦你继续阅读下文关于注意力机制的计算方法,你就能大致了解这些向量各自所扮演的角色。
计算自注意力机制的第二步是计算分数。假设我们正在计算本例中第一个单词“Thinking”的自注意力机制。我们需要根据这个单词对输入句子中的每个单词进行评分。分数决定了在特定位置对单词进行编码时,对输入句子其他部分的关注程度。 得分是通过对查询向量Q与我们要评分的相应单词的键向量K进行点积计算得出的。因此,如果我们处理位置 1 的单词的自注意力机制,第一个得分将是 q1 和 k1 的点积。第二个得分将是 q1 和 k2 的点积。

第三步和第四步是将得分除以 8(论文中使用的关键向量维度的平方根 - 64。这会导致梯度更稳定。这里可能还有其他可能的值,但这是默认值),然后将结果传递给 softmax 运算。Softmax 会对得分进行归一化,使它们全部为正数,并且总和为 1。

这个 softmax 分数决定了每个单词在这个位置的表达程度。显然,这个位置的单词将具有最高的 softmax 分数,但有时关注与当前单词相关的另一个单词也很有用。
第五步是将每个值向量K乘以 softmax 分数(为求和做准备)。这里的直觉是保留我们想要关注的单词的值,并屏蔽掉不相关的单词(例如,通过乘以 0.001 这样的小数)。
第六步 ,对加权值向量求和。这将产生该位置(第一个单词)的自注意力层输出。

自注意力计算到此结束。得到的向量可以发送到前馈神经网络。然而,在实际实现中,为了加快处理速度,这个计算是以矩阵形式进行的。既然我们已经了解了词级计算的直观原理,现在让我们来看一下。
自注意力机制的矩阵计算
第一步是计算查询、键和值矩阵。我们将嵌入打包到矩阵 X 中,并将其乘以我们训练过的权重矩阵 ( WQ 、 WK 、 WV )。

X 矩阵中的每一行都对应输入句子中的一个单词。我们再次看到了嵌入向量(512,图中为 4 个框)和 q/k/v 向量(64,图中为 3 个框)大小的差异。
最后 ,由于我们处理的是矩阵,我们可以将第二步到第六步浓缩为一个公式来计算自注意力层的输出。

矩阵形式的自注意力计算
Multi-Head 多头机制
论文进一步完善了自注意力层,增加了一种名为“多头”注意力的机制。这从两个方面提升了注意力层的性能:
1、它扩展了模型关注不同位置的能力。没错,在上面的例子中,z1 包含了其他所有编码的一点点,但它可能主要由实际的单词本身决定。如果我们要翻译像“这只动物因为太累了而没有过马路”这样的句子,那么知道“它”指的是哪个词会很有用。
2、它为注意力层提供了多个“表征子空间”。正如我们接下来将看到的,多头注意力机制不仅拥有一组查询/键/值权重矩阵,而是拥有多组(Transformer 使用八个注意力头,因此每个编码器/解码器最终都有八组权重矩阵)。每组权重矩阵都经过随机初始化。训练结束后,每组权重矩阵都会用于将输入嵌入(或来自底层编码器/解码器的向量)投影到不同的表征子空间。

在多头注意力机制下,我们为每个头维护单独的 Q/K/V 权重矩阵,从而得到不同的 Q/K/V 矩阵。与之前一样,我们将 X 乘以 WQ/WK/WV 矩阵,得到 Q/K/V 矩阵。
如果我们进行上面概述的相同的自注意力计算,只需使用不同的权重矩阵进行 8 次不同的计算,我们最终会得到 8 个不同的 Z 矩阵

这给我们带来了一些挑战。前馈层并不期望八个矩阵——它期望一个矩阵(每个单词一个向量)。所以我们需要一种方法将这八个矩阵压缩成一个矩阵。
我们怎么做呢?我们将矩阵连接起来,然后将它们乘以一个额外的权重矩阵 WO。

这就是多头自注意力的全部内容。
这里面有很多矩阵。试着把它们都放在一个视图里,这样我们就能在一个地方看到它们了。

既然我们已经触及了注意力头,让我们重新回顾一下之前的例子,看看当我们在例句中对单词“it”进行编码时,不同的注意力头关注的焦点在哪里:

当我们对“it”这个词进行编码时,一个注意力头主要关注“animal”,而另一个注意力头则关注“tired”——从某种意义上说,模型对“it”这个词的表示融合了“animal”和“tired”的一些表示。
然而,如果我们把所有的注意力头都添加到图片中,事情就会变得更加难以解释:

使用位置编码表示序列的顺序
到目前为止,我们所描述的模型缺少一种解释输入序列中单词顺序的方法。
为什么呢?根据自注意力机制原理的介绍我们知道,自注意力机制在实际运算过程中不过就是几个矩阵来回相乘进行线性变换而已。因此,这就导致即使是打乱各个词的顺序,那么最终计算得到的结果本质上却没有发生任何变换,换句话说仅仅只使用自注意力机制会丢失文本原有的序列信息。
为了解决这个问题,Transformer 为每个输入嵌入添加了一个向量。这些向量遵循模型学习到的特定模式,这有助于模型确定每个单词的位置,或者序列中不同单词之间的距离。这里的直觉是,将这些值添加到嵌入中,可以在嵌入向量投影到 Q/K/V 向量以及进行点积注意计算时,提供它们之间有意义的距离。

为了让模型了解单词的顺序,我们添加了位置编码向量——其值遵循特定的模式。
如果我们假设嵌入的维数为 4,则实际的位置编码将如下所示:

位置编码的真实示例
这种模式看起来是什么样的?
在下图中,每一行对应一个向量的位置编码。因此,第一行是我们要添加到输入序列第一个单词的嵌入中的向量。每一行包含 512 个值,每个值介于 1 到 -1 之间。我们用颜色对它们进行了编码,以便清晰可见。

这是一个真实的位置编码示例,包含 20 个单词(行),嵌入大小为 512(列)。您可以看到它从中心分成两半。这是因为左半部分的值由一个函数(使用正弦函数)生成,右半部分的值由另一个函数(使用余弦函数)生成。然后,它们被连接起来,形成每个位置编码向量。
位置编码的公式在论文(3.5 节)中进行了描述。您可以在get_timing_signal_1d 中看到生成位置编码的代码。这并非唯一可行的位置编码方法。然而,它的优势在于能够扩展到未知长度的序列(例如,如果我们的训练模型被要求翻译一个比训练集中任何一个句子都长的句子)。 上面显示的位置编码来自 Transformer 的 Tensor2Tensor 实现。论文中展示的方法略有不同,它不是直接连接,而是将两个信号交织在一起。下图展示了它的样子。 这是生成它的代码。

残差
在继续之前,我们需要提及编码器架构中的一个细节,即每个编码器中的每个子层(自注意力,ffnn)周围都有一个残差连接,然后是**层归一化[11]**步骤。

如果我们要可视化与自注意力相关的向量和层规范操作,它将看起来像这样:

这也适用于解码器的子层。如果我们设想一个由两个堆叠的编码器和解码器组成的 Transformer,它看起来应该是这样的:

5、解码器端
现在我们已经了解了编码器方面的大部分概念,也基本了解了解码器各个组件的工作原理。接下来,我们来看看它们是如何协同工作的。
编码器首先处理输入序列。然后,顶部编码器的输出被转换为一组注意向量 K 和 V。每个解码器将在其“编码器-解码器注意”层(Encoder-Decoder Attention)中使用它们,这有助于解码器将注意力集中在输入序列中的适当位置:

编码阶段完成后,我们开始解码阶段。解码阶段的每一步都会从输出序列中输出一个元素(在本例中是英语翻译句子)。
以下步骤重复该过程,直到出现一个特殊符号,表示 Transformer 解码器已完成输出。每一步的输出都会在下一个时间步中馈送到底部解码器,解码器会像编码器一样将其解码结果冒泡。并且,就像我们对编码器输入所做的那样,我们在这些解码器输入中嵌入并添加位置编码,以指示每个单词的位置。

解码器中的自注意力层的操作方式与编码器中的自注意力层略有不同:
在解码器中,自注意力层仅允许关注输出序列中较早的位置。这是通过在自注意力计算中的 softmax 步骤之前屏蔽未来位置(将其设置为 -inf )来实现的。(Masked Multi-Head Attention) “编码器-解码器注意”层的工作原理与多头自注意类似,不同之处在于它从其下方的层创建查询矩阵Q,并从编码器堆栈的输出中获取键K和值V矩阵。
6、最后的线性层和 Softmax 层
解码器堆栈输出一个浮点向量。我们如何将其转换成一个单词呢?这是最后的线性层的任务,该层之后是 Softmax 层。
线性层是一个简单的完全连接的神经网络,它将解码器堆栈产生的向量投影到一个更大的向量中,称为 logits 向量。
假设我们的模型知道 10,000 个独特的英语单词(也就是我们模型的“输出词汇”),这些单词是从训练数据集中学习到的。这将使 logits 向量的宽度达到 10,000 个单元格——每个单元格对应一个独特单词的得分。这就是我们对线性层之后的模型输出的解释。
然后,softmax 层将这些分数转换为概率(所有分数均为正,加起来等于 1.0)。选择概率最高的单元格,并生成与其关联的单词作为此时间步的输出。

该图从底部开始,产生的向量作为解码器堆栈的输出。然后将其转换为输出字。
7、训练
在训练过程中,未经训练的模型会经历完全相同的前向传递。但由于我们是在有标签的训练数据集上进行训练,因此我们可以将其输出与实际的正确输出进行比较。
为了形象化这一点,我们假设输出词汇只包含六个单词(“a”、“am”、“i”、“thanks”、“student”和“”(“句子结尾”的缩写))。

我们的模型的输出词汇是在我们开始训练之前的预处理阶段创建的。
一旦我们定义了输出词汇表,我们就可以使用相同宽度的向量来表示词汇表中的每个单词。这也称为独热编码。例如,我们可以使用以下向量表示单词“am”:

示例:输出词汇的独热编码
回顾之后,让我们讨论一下模型的损失函数——我们在训练阶段优化的指标,以得到一个经过训练且希望非常准确的模型。
损失函数
假设我们正在训练模型。假设这是训练阶段的第一步,我们正在用一个简单的例子来训练它——将“merci”翻译成“thanks”。
这意味着,我们希望输出是一个表示“谢谢”的概率分布。但由于该模型尚未训练,因此目前不太可能实现。

由于模型的参数(权重)都是随机初始化的,因此(未训练的)模型会为每个单元/单词生成一个任意值的概率分布。我们可以将其与实际输出进行比较,然后使用反向传播调整所有模型的权重,使输出更接近期望输出。
如何比较两个概率分布?我们只需将一个概率分布减去另一个概率分布即可。更多详细信息,请参阅**交叉熵[12]**和 Kullback-Leibler 散度 [13]。
但请注意,这是一个过于简化的例子。更实际的例子是,我们会使用一个长度超过一个单词的句子。例如,输入:“je suis étudiant”,预期输出:“i am a student”。这实际上意味着,我们希望模型能够连续输出概率分布,其中:
- 每个概率分布都由一个宽度为 vocab_size 的向量表示(在我们的例子中是 6,但更现实的数字是 30,000 或 50,000)
- 第一个概率分布在与单词“i”相关的单元格中具有最高概率
- 第二个概率分布在与单词“am”相关的单元格中具有最高概率
- 依此类推,直到第五个输出分布指示“ ”符号,该符号也具有来自 10,000 个元素词汇表的一个与之关联的单元格。

我们将在一个示例句子的训练示例中针对目标概率分布来训练我们的模型。
在足够大的数据集上对模型进行足够时间的训练后,我们希望产生的概率分布如下所示:

希望经过训练后,模型能够输出我们期望的正确翻译。当然,这并不能真正表明这个短语是否属于训练数据集(参见:交叉验证 )。请注意,即使不太可能是该时间步的输出,每个位置都会获得一点概率——这是 softmax 的一个非常有用的属性,有助于训练过程。
现在,由于模型每次只产生一个输出,我们可以假设模型会从概率分布中选择概率最高的单词,并丢弃其余单词。这是一种实现方法(称为贪婪解码)。
另一种方法是保留前两个单词(例如“I”和“a”),然后在下一步中运行模型两次:第一次假设第一个输出位置是单词“I”,另一次假设第一个输出位置是单词“a”,然后保留在位置 1 和位置 2 中误差较小的版本。我们对位置 2 和位置 3 重复此操作……等等。这种方法称为“集束搜索”,在我们的示例中,beam_size 为 2(意味着始终在内存中保留两个部分假设(未完成的翻译),top_beams 也为 2(意味着我们将返回两个翻译)。这两个都是可以进行实验的超参数。

那么,如何系统的去学习大模型LLM?
作为一名从业五年的资深大模型算法工程师,我经常会收到一些评论和私信,我是小白,学习大模型该从哪里入手呢?我自学没有方向怎么办?这个地方我不会啊。如果你也有类似的经历,一定要继续看下去!这些问题啊,也不是三言两语啊就能讲明白的。
所以我综合了大模型的所有知识点,给大家带来一套全网最全最细的大模型零基础教程。在做这套教程之前呢,我就曾放空大脑,以一个大模型小白的角度去重新解析它,采用基础知识和实战项目相结合的教学方式,历时3个月,终于完成了这样的课程,让你真正体会到什么是每一秒都在疯狂输出知识点。
由于篇幅有限,⚡️ 朋友们如果有需要全套 《2025全新制作的大模型全套资料》,扫码获取~
👉大模型学习指南+路线汇总👈
我们这套大模型资料呢,会从基础篇、进阶篇和项目实战篇等三大方面来讲解。

👉①.基础篇👈
基础篇里面包括了Python快速入门、AI开发环境搭建及提示词工程,带你学习大模型核心原理、prompt使用技巧、Transformer架构和预训练、SFT、RLHF等一些基础概念,用最易懂的方式带你入门大模型。
👉②.进阶篇👈
接下来是进阶篇,你将掌握RAG、Agent、Langchain、大模型微调和私有化部署,学习如何构建外挂知识库并和自己的企业相结合,学习如何使用langchain框架提高开发效率和代码质量、学习如何选择合适的基座模型并进行数据集的收集预处理以及具体的模型微调等等。
👉③.实战篇👈
实战篇会手把手带着大家练习企业级的落地项目(已脱敏),比如RAG医疗问答系统、Agent智能电商客服系统、数字人项目实战、教育行业智能助教等等,从而帮助大家更好的应对大模型时代的挑战。
👉④.福利篇👈
最后呢,会给大家一个小福利,课程视频中的所有素材,有搭建AI开发环境资料包,还有学习计划表,几十上百G素材、电子书和课件等等,只要你能想到的素材,我这里几乎都有。我已经全部上传到CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
相信我,这套大模型系统教程将会是全网最齐全 最易懂的小白专用课!!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)