用直白语言讲透 Transformer

自 2017 年提出以来,Transformer 已成为机器学习领域的重要技术架构,极大革新了主流机器翻译与自动补全服务的能力。

近年来,随着 OpenAI 的 ChatGPT、GPT‑4 以及 Meta 的 Llama 和深度求索的deepseek等大语言模型相继出现,Transformer 的受欢迎程度进一步提升。这些广受关注的模型均以 Transformer 架构为基础。借助 Transformer 的能力,这类模型在自然语言理解与生成方面取得了显著突破,并走向大众。

尽管已有不少优质资料详细解析 Transformer 的工作原理,但我发现自己虽然能从数学上理解其机制,却难以直观地解释它的工作过程。在多次交流、与行业人员讨论并进行相关技术分享后,我发现很多人都存在同样的问题。

在这篇技术文章中,我将不依赖代码与数学公式,从高层视角解释 Transformer 的工作原理。我的目标是避免使用晦涩的专业术语,也不与早期架构进行对比。虽然 Transformer 本身较为复杂,我会尽可能保持内容简洁易懂,希望能帮助大家更直观地理解它的功能与实现方式。

什么是 Transformer?

Transformer 是一类神经网络架构,非常适合处理以序列为输入的任务。这类序列中最常见的例子就是句子,可以看作一组有序的单词。

这类模型的目标是为序列中的每个元素生成一个数值表示,其中包含该元素及其上下文的关键信息。生成的数值表示可输入到后续网络中,用于执行生成、分类等多种任务。

通过构建这种高信息量的表示,模型能让下游网络更好地理解输入序列内部的模式与关系,从而提升输出的连贯性与上下文相关性。

Transformer 的核心优势在于:

  • 能够有效处理序列中的长距离依赖

  • 计算效率高,支持并行处理序列

这使其在机器翻译、情感分析、文本生成等任务中尤为适用。

Transformer 的输入是什么?

要将输入传入 Transformer,我们必须先将其转换为令牌序列(token sequence),即用一组整数来表示输入内容。

由于 Transformer 最初应用于自然语言处理(NLP)领域,我们先以此场景为例。将句子转换为令牌序列的最简单方法,是定义一个作为查找表的词典,把单词映射为整数。我们可以预留一个特定数值,用来表示词典中未包含的单词,从而保证每个单词都能被赋予一个整数值。

在实际应用中,这种文本编码方式较为简单粗糙。例如 catcats 虽然是同一种动物的单复数形式,却会被当作完全不同的令牌处理。为解决这一问题,研究者提出了 ** 字节对编码(Byte-Pair Encoding)** 等多种分词策略,先将单词拆分为更小的单元,再建立索引。此外,通常还会加入特殊令牌来表示句子开头、结尾等信息,为模型提供更多上下文。

我们通过下面的例子来更好地理解分词过程:

"Hello there, isn't the weather nice today in Drosval?"

其中 Drosval 是 GPT‑4 根据提示词生成的虚构地名:"你能创造一个听起来属于 David Gemmell 的 Drenai 世界的虚构地名吗?"。特意选用这个词,是因为它不应该出现在任何现有模型的词典中

使用 Hugging Face Transformers 库中的 bert-base-uncased 分词器,这句话会被转换为如下令牌序列:

表示每个单词的整数会因具体的模型训练与分词策略而不同。对其进行解码后,我们可以看到每个令牌对应的单词:

有趣的是,我们可以看到结果与原始输入并不完全一致。模型添加了特殊令牌,缩写被拆分为多个令牌,虚构地名也被表示为若干个片段(chunk)。由于使用了不区分大小写的模型,所有大小写信息也都丢失了。

不过,尽管我们以句子作为示例,Transformer 并不局限于文本输入;该架构在视觉任务上也表现出色。为了将图像转换为序列,ViT 的作者将图像切分为互不重叠的 16×16 像素块,并将其拼接成长向量后输入模型。如果在推荐系统中使用 Transformer,一种可行的方式是将用户最近浏览的 n 个物品的 ID 作为输入序列传入网络。只要能为特定领域生成有意义的输入令牌表示,就可以将其送入 Transformer 网络。

令牌嵌入

在得到表示输入的整数序列后,我们将其转换为嵌入(embedding) 。嵌入是一种便于机器学习算法处理的信息表示方式:它将信息表示为一组数值,以压缩形式捕获被编码令牌的语义。初始时,嵌入被初始化为随机数值序列,在训练过程中逐渐学习到有意义的表示。但这类嵌入存在一个固有缺陷:不考虑令牌出现的上下文。这主要体现在两个方面。

根据任务不同,在对令牌进行嵌入时,我们通常还需要保留令牌的顺序信息 ,这在自然语言处理等领域尤为重要,否则模型会退化为词袋模型。为解决这一问题,我们会对嵌入加入位置编码(positional encoding)。尽管位置编码的实现方式有多种,但其核心思想是:使用另一组嵌入表示每个令牌在输入序列中的位置,并与令牌嵌入相加融合。

另一个问题是,令牌的含义会根据其周围的令牌而发生变化。请看下面两个句子:

It's dark, who turned off the light?

Wow, this parcel is really light!

在这里,单词 light 出现在两种不同的语境中,含义完全不同!但根据分词策略的不同,它很可能会被映射成同一个令牌,得到相同的嵌入向量。在 Transformer 中,这一问题是通过 ** 注意力机制(attention mechanism)** 来解决的。

从概念上理解:什么是注意力?

Transformer 架构中最重要的机制或许就是注意力机制。它让网络能够判断输入序列中哪些部分对当前任务最为重要。对于序列中的每个令牌,注意力机制都会找出:在当前语境下,哪些其他令牌对理解它是关键的。

在讲解注意力在 Transformer 中的具体实现之前,我们先从简单的角度理解它在概念上要达成什么目标,以便建立直观认识。

一种理解方式是:注意力是一种将每个令牌的嵌入替换为包含上下文信息的嵌入 的方法,而不是不管语境如何都使用完全相同的嵌入。如果我们知道哪些令牌与当前令牌相关,就可以通过对这些相关嵌入做加权平均 (更一般地说是线性组合)来捕捉上下文信息。

我们用之前见过的其中一个句子,举一个简单的例子来看看这一过程。在应用注意力机制之前,序列中的嵌入向量不包含相邻词的上下文信息。因此,我们可以将单词 light 的嵌入向量表示为如下的线性组合。

在这里我们可以看到,权重只是**单位矩阵**。 在应用注意力机制后,我们希望学习到一个权重矩阵,使得我们可以用类似下面的方式来表示 **light** 对应的嵌入。

这一次,我们会为与当前令牌最相关的序列部分分配更大的权重,从而保证新的嵌入向量能够捕捉到最重要的上下文信息。

包含当前上下文信息的嵌入有时被称为上下文嵌入(contextualised embeddings),这也是我们最终想要得到的结果。

现在我们已经从宏观上理解了注意力机制的目标,接下来将在本节中讲解它的具体实现方式。

注意力是如何计算的?

注意力机制有多种类型,主要区别在于计算线性组合权重的方式。这里我们介绍原论文中提出的缩放点积注意力(scaled dot-product attention),这也是最常用的方法。本节中假设所有嵌入都已加入位置编码。

回顾一下,我们的目标是通过原始嵌入的线性组合得到上下文嵌入。我们先从简单情况出发,假设所有必要信息都可以被学习到的嵌入向量表示,我们只需要计算权重。

为了计算权重,必须先确定哪些令牌之间是相关的。为此,我们需要定义两个嵌入之间的相似度 。表示这种相似度的一种方法是使用点积:我们希望学习到的嵌入能让分数越高表示两个单词越相关。

由于我们需要为每个令牌计算它与序列中其他所有令牌的相关性,因此可以将这一过程推广为矩阵乘法,从而得到权重矩阵,这类矩阵通常被称为注意力分数。 为了使所有权重之和为 1,我们还会应用 SoftMax 函数。 然而,矩阵乘法可能会产生极大的数值,导致 SoftMax 函数在面对较大的注意力分数时输出极小的梯度,进而在训练过程中引发梯度消失问题。 为解决这一问题,会在应用 SoftMax 之前,将注意力分数乘以一个缩放因子。

现在,我们可以将注意力分数与原始嵌入矩阵相乘,从而得到上下文嵌入矩阵,这等价于对嵌入向量进行线性组合。

尽管模型有可能学到足够复杂的嵌入,来生成注意力分数与后续的上下文嵌入,但我们需要将大量信息压缩到通常维度较小的嵌入空间中。 因此,为了让模型的学习任务稍微简单一些,我们引入更多可学习参数。不再直接使用嵌入矩阵,而是将其经过三个独立的线性层(矩阵乘法)处理;这能让模型更好地"关注"嵌入中的不同部分。如下图所示:

从图中可以看到,这些线性投影被标记为 Q、K 和 V。在原论文中,这三个投影分别被命名为 Query(查询)、Key(键)和 Value(值),据说是受到信息检索领域的启发。就我个人而言,我从未觉得这个类比有助于理解,因此通常不会过多关注它。我在这里沿用这套术语,只是为了与文献保持一致,并明确表明这三个线性层是相互独立的。 现在我们已经理解了这一过程的工作原理,可以将注意力计算看作一个拥有三个输入的独立模块,这三个输入会分别被送入 Q、K 和 V。

当我们将同一个嵌入矩阵 同时输入到 Q、K 和 V 时,这种结构称为自注意力(self-attention)

什么是多头注意力?

在实际应用中,我们通常会并行使用多个自注意力模块 ,使 Transformer 能够同时关注输入序列的不同部分 ------ 这就是多头注意力(multi-head attention)

多头注意力的思想非常简单:将多个独立的自注意力模块的输出拼接(concatenate)在一起,然后输入到一个线性层中。该线性层让模型学习如何融合来自每个注意力头的上下文信息。

在实际应用中,每个自注意力模块使用的隐藏维度通常设置为原始嵌入维度除以注意力头数,以保持嵌入矩阵的形状不变。

Transformer 还由哪些部分组成?

尽管提出 Transformer 的那篇论文标题为《Attention is all you need》(如今已广为人知),但这个说法容易让人产生误解 ------Transformer 并非只由注意力机制构成,它还包含其他组件。

一个 Transformer 模块还包含以下部分:

前馈神经网络(FFN) 一种两层神经网络,会独立作用于批次和序列中的每个令牌嵌入。前馈网络模块的作用是为 Transformer 引入额外的可学习参数,用于保证上下文嵌入具有区分度且分布合理。原始论文使用了 GeLU 激活函数,但前馈网络的具体结构会随架构不同而变化。

**层归一化(Layer Normalisation)**用于提升深度神经网络(包括 Transformer)的训练稳定性。它对每个序列的激活值进行归一化,避免训练过程中激活值过大或过小,从而防止出现梯度消失、梯度爆炸等与梯度相关的问题。这种稳定性对训练极深的 Transformer 模型至关重要。

**跳跃连接(Skip connections)**与 ResNet 架构类似,Transformer 使用残差连接来缓解梯度消失问题,提升训练稳定性。

尽管 Transformer 整体架构自提出以来变化不大,但层归一化模块的位置 会根据具体实现有所不同。原始架构(现在称为 post-layer norm)如下所示:

如下图所示,在近年的主流架构中,最常见的布局是前置层归一化(pre-layer norm),它将归一化模块放在跳跃连接内、自注意力模块与前馈网络模块之前。

Transformer 的不同类型有哪些?

尽管如今已经出现了许多不同的 Transformer 架构,但大多数可以归为三大类。

编码器架构(Encoder Architectures)

编码器模型的目标是生成上下文嵌入 ,可用于分类、命名实体识别等下游任务。因为其注意力机制能够对整个输入序列进行关注,这也是本文到目前为止所讲解的架构类型。最流行的纯编码器 Transformer 系列是 BERT 及其各种变体。

将数据经过一个或多个 Transformer 模块后,我们会得到一个复杂的上下文嵌入矩阵,它为序列中的每个令牌都生成一个嵌入。然而,在分类这类下游任务中,我们只需要输出一个预测结果。传统做法是取第一个令牌,并将其传入一个分类头(classification head);分类头通常包含 Dropout 层和线性层。这些层的输出可以再经过 SoftMax 函数,转换为类别概率。下图展示了其大致结构。

解码器架构(Decoder Architectures)

解码器架构与编码器架构几乎完全相同 ,核心区别在于:解码器架构使用了掩码自注意力层(或称因果自注意力层) 。这使得注意力机制只能关注输入序列中当前位置及之前的元素 ,意味着生成的上下文嵌入仅会考虑上文信息。主流的纯解码器模型包括 GPT 系列。

这通常通过使用二进制下三角矩阵对注意力分数进行掩码,并将未掩码的元素替换为负无穷来实现;在经过后续的 SoftMax 运算后,这些位置的注意力分数会被置为 0。我们可以更新之前的自注意力示意图来体现这一点,如下所示。

由于解码器架构只能关注当前位置及之前的内容 ,因此通常被用于自回归任务,例如序列生成。不过,与编码器相比,在使用上下文嵌入进行序列生成时,还需要考虑一些额外因素。下图展示了一个示例。

我们可以注意到,虽然解码器会为输入序列中的每个令牌生成上下文嵌入,但在生成序列时,我们通常会将最后一个令牌对应的嵌入作为后续层的输入。

此外,在对 logits 应用 SoftMax 函数后,如果不做任何过滤,得到的将是模型词表中所有令牌的概率分布------ 这个规模可能非常大!我们通常希望通过各种过滤策略减少候选数量,最常见的方法包括:

  • 温度系数调节(Temperature Adjustment) 温度是一个在 SoftMax 内部使用的参数,用于控制生成文本的随机性。它通过调整输出单词的概率分布,决定模型输出的创造性或集中程度。温度越高,分布越平坦,输出越多样。

  • **Top-P 采样(Top-P Sampling)**该方法根据给定的概率阈值筛选下一个令牌的候选集,并只在这些候选上重新归一化概率分布。

  • Top-K 采样(Top-K Sampling) 该方法将候选限制为概率(或 logit)最高的 K 个令牌(具体取决于实现)。

在调整或缩小下一个令牌的候选概率分布后,我们可以从中采样 得到预测结果 ------ 这本质上就是从多项分布中抽样。预测出的令牌会被拼接到输入序列中,再重新送入模型,直到生成指定数量的令牌,或模型输出结束令牌(stop token)------ 一种表示序列终止的特殊令牌。


编码器--解码器(Encoder-decoder)架构

Transformer 最初被提出时是用于机器翻译的架构,通过编码器 + 解码器 共同完成任务:先用编码器生成中间表示,再用解码器将其转换为目标输出格式。虽然编码器--解码器架构如今不那么常见,但如 T5 这类模型证明了:问答、摘要、分类等任务都可以被建模为序列到序列问题,并用这种方式解决。

编码器--解码器架构的核心区别 在于:解码器使用编码器--解码器注意力(encoder-decoder attention) 。在注意力计算中,它使用编码器的输出作为 K 和 V ,使用解码器模块的输入作为 Q。这与自注意力中所有输入都使用同一个嵌入矩阵的情况不同。除此之外,整体生成过程与纯解码器架构非常相似。

我们可以通过下图直观理解编码器--解码器架构。为简化图示,我使用了原论文中的后置层归一化(post-layer norm)版本,即层归一化位于注意力模块之后。

结论

希望本文能帮助你直观理解 Transformer 的工作原理,以相对易懂的方式拆解其中的细节,并为揭开现代 Transformer 架构的神秘面纱提供一个良好的起点!

相关推荐
我材不敲代码2 小时前
计算机视觉基础——opencv的基础操作
人工智能·opencv·计算机视觉
VALENIAN瓦伦尼安教学设备2 小时前
便携式蒸汽阀门漏气检测仪作用
人工智能·嵌入式硬件·算法
成都它思科技有限公司2 小时前
语音识别错误率是多少,我们认为错误率是多少?
人工智能·语音识别
Cx330❀2 小时前
Linux ELF格式与可执行程序加载全解析:从磁盘文件到运行进程
linux·运维·服务器·人工智能·科技
杜子不疼.2 小时前
2026年AI Agent实战:从玩具到生产力的落地手册(附源码)
人工智能
科技快报2 小时前
华为发布AI数据平台,重塑数据基座,加速企业AI应用落地
大数据·人工智能·华为
智塑未来2 小时前
哪些GEO服务商有自研AI监测工具?2026年AI品牌监测平台深度对比
人工智能
不懒不懒2 小时前
【零基础入门 PyTorch:实现食物图片分类任务】
人工智能·pytorch·python
PengShuaiD52 小时前
【AI编码】用ChatGPT基于Whisper+ffmpeg实现一个根据视频字幕执行自动化裁剪本地小工具
人工智能·chatgpt·ffmpeg·whisper