@anirudhbv_ce: 推断系列第1天:Transformer架构(Attention is All You Need)Transformer通过完全并行化序列处理杀死了RNN,使得序列…

X AI KOLs Timeline 新闻

摘要

本文是30天推断系列的一部分,解释了Transformer架构及其核心组件如自注意力和多头注意力,以及它在现代人工智能中的重要性。

1/30 推断系列第1天 Transformer架构(Attention is All You Need) Transformer通过使序列处理100%可并行化,从而淘汰了RNN。当今每一个基础模型都得益于这种架构。但虽然最初的2017年论文提出了编码器-解码器对,但现代生成式AI的爆发几乎完全由仅扩展解码器部分所驱动。 整个架构可分为以下核心部分: 自注意力(QKV):查询(我在寻找什么)、键(我有什么)和值(实际内容)。它计算每个token应该对其他每个token给予多少关注。 多头注意力:并行运行多个QKV投影,以同时捕获不同的上下文关系。 位置编码:因为模型一次性处理所有内容(不同于RNN),我们必须通过数学方法注入序列顺序。 硬件现实:这种架构用大规模并行矩阵乘法取代了顺序处理——非常适合GPU。但由于注意力机制的计算复杂度是二次的,内存带宽很快成为最终瓶颈(我们稍后会详细讨论!) (附上我分解架构的原始笔记!) 强烈推荐阅读: • 由@viplismism撰写的一篇关于注意力机制底层工作原理的技术好文:https://viplismism.github.io/2026/02/22/attention… • 3Blue1Brown的神经网络播放列表,提供视觉直觉:https://youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi… • @NVIDIAAIDev关于Transformer模型的博客:https://blogs.nvidia.com/blog/what-is-a-transformer-model/… 明天:我们将探讨使Transformer在推断中更高效的最新注意力机制! #MachineLearning #Transformers #GPU #30DaysOfInference
查看原文
查看缓存全文

缓存时间: 2026/08/27 05:32

1/30 推理系列之三十天

Transformer 架构(注意力就是一切)

Transformer 通过将序列处理完全并行化,从而取代了 RNN。当今每一个基础模型都得益于这一架构。虽然 2017 年的原始论文提出了编码器-解码器对,但现代生成式 AI 的爆发几乎完全依赖于仅扩展解码器部分。

整个架构可分为以下核心部分:

  • 自注意力(QKV): 查询(我在找什么)、键(我有什么)以及值(实际内容)。它计算每个词元应对其他每个词元的关注程度。
  • 多头注意力: 并行运行多个 QKV 投影,以同时捕捉不同的上下文关系。
  • 位置编码: 由于模型一次性处理所有信息(不同于 RNN),我们必须通过数学方式注入序列顺序信息。
  • 硬件现实: 该架构以大规模并行矩阵乘法取代了顺序处理——非常适合 GPU。但由于注意力机制的计算复杂度呈平方级增长,内存带宽很快成为终极瓶颈(稍后详述!)。

(附上了我的原始笔记,对架构进行了分解!)

推荐阅读:

  • @viplismism 撰写的关于注意力底层工作原理的优秀技术文章:https://viplismism.github.io/2026/02/22/attention…
  • 3Blue1Brown 的《神经网络》播放列表,提供直观的视觉理解:https://youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi…
  • @NVIDIAAIDev 关于 Transformer 模型的博客文章: https://blogs.nvidia.com/blog/what-is-a-transformer-model/…

明日预告: 我们将探讨使 Transformer 在推理方面更高效的最新注意力机制!

#MachineLearning #Transformers #GPU #30DaysOfInference


注意力就是一切,朋友们

来源:https://viplismism.github.io/2026/02/22/attention 31 分钟阅读 • 6230 词 • 37k 字符

注意力就是一切,朋友们!!

注意啦! 这是一篇长文——大约 6200 词和 37k 字符。冲杯咖啡(或两杯),找个安静的地方,全神贯注地阅读(双关语)吧,建议在笔记本电脑或大屏幕上阅读!

我知道你在想什么——“我直接把这扔给 Claude 拿个摘要就行了。”当然,你可以这样做。但如果你真的想从基本原理上理解注意力机制,没有捷径可走。相信我,你在这里花的 30 分钟会为你节省之后数小时的困惑时间。当然,由你决定!

分两次阅读? 如果你时间紧张,这里有一个自然的断点:阅读到“位置嵌入”部分结束(大约前 10-12 分钟)。这部分涵盖了为什么存在 Transformer 以及相关基础。然后稍作休息,再回来阅读后半部分,深入探讨注意力如何实际计算——Q/K/V 机制、多头注意力以及所有有趣的细节。两部分相互承接,但中间休息一下不会打乱你的阅读流。

开始吧!

我知道网上有很多关于 Transformer 的解释,但在我读了第 18 遍之后(是的,我大二时就读过那篇“注意力”论文),直到最近我才真正完全理解其要义,所以我觉得是时候在这里把它写出来了。

我再次请求你们理解注意力!

简而言之: 这可能是你需要的唯一解释,它将从基本原理上真正让你理解注意力。我希望你对 RNN、LSTMs 以及梯度下降的工作原理有一些基本概念——对,就是那个原始算法。如果没有,建议你快速阅读一下(现在就启动你的 Claude 吧!)。好了,开始…

序列问题或为什么 RNN 有点糟

好吧,让我们回到 2015 年左右?!那时,如果你想处理文本或序列数据,RNN 基本上是你唯一真正的选择。我是说,核心思想其实非常直观。

想象一下,你正在逐词阅读一个很长的段落,并试图记住沿途的所有信息。你从“上周约翰买的、坐在垫子上的那只猫……”这样的句子开始读,等你读到句末时,你可能已经忘了开头是什么,对吧?这基本上就是 RNN(循环神经网络)发生的情况——Transformer 之前的老派文本处理方式。

RNN 会逐词处理句子,维护一个关于迄今为止所见一切的“心理笔记”。听起来合理,对吧?但它们有一个巨大的问题:你在句子中回溯得越远,信息就越会消退。这是因为所谓的梯度消失问题,没错,就是那个老问题。

公平地说,梯度消失不只是 RNN 的问题——它是深度学习中的一个根本问题。即使是简单的卷积网络或堆叠线性层,当网络足够深时也会遭遇这个问题。这正是 ResNet 引入跳跃连接的原因。但 RNN 让它变得更糟,因为其顺序特性意味着梯度必须依次流经可能数百个时间步长,这只会让情况恶化!

梯度消失

基本上在反向传播(更新模型权重)期间,误差信号必须随时间向后传播以更新所有权重。问题在于梯度在每个时间步长都会被乘以一个值,而由于这些值通常是分数,它们会急剧缩小。

为了更清楚地说明,假设你有一个包含 100 个词的序列。现在每回溯一步,你的梯度都会乘以一个非常小的数字,比如 0.9。当你到达开头时,你会得到 0.9^100 ≈ 0.000027——这几乎就是零,伙计!现在如果你想用这个量级来更新权重,那基本上等于没有更新。

这就是为什么 RNN 在处理较长上下文时很吃力。如果 50 步前发生了重要事件,模型几乎无法更新那些早期的权重,因为当梯度信号传回去时已经太微弱了。序列中这些遥远部分之间的连接几乎无法学习。这时,那个老派的东西就登场了,Transformer 诞生了。

到底什么是 Transformer?!

直接说吧,Transformer 基本上是一个进行序列建模的机器学习模型。它的意思是,当你有一个序列,并向模型输入该序列的前 x-1 个单元时,它试图预测第 x 个单元应该是什么。就是这样。这对任何类型的序列数据都适用。你可以向 Transformer 输入文本、音符、蛋白质结构、代码——任何顺序重要且存在模式的东西。

比如音乐和弦,在看到 [C, F, G, Am] 之后,模型可能会预测下一个和弦又是 F,因为这是一个常见的进行。

或者像“我来自印度,我……”这样的句子,模型预测出“Indian”,其中“Indian”之前的所有词就是那 x-1 个单元,而模型预测出的第 x 个单元就是“Indian”!与 RNN 不同,Transformer 可以轻松地一次查看整个上下文,因此它们不会忘记最开始发生的事情。

现在,如果你不是 ML 背景的人在读这篇文章(伙计,学学 ML 吧,真的!),让我快速解释一下词语实际上是如何输入到这些模型中的。有一个叫做分词的过程,这其实就是“将词语转换为数字”的花哨说法。像“I am from India and I am”这样的句子会被转换成类似 [12, 24, 45, 11, 19, 10, 2] 的形式,每个词都有自己的数字。这些映射没什么特别的——就像为词汇表中的每个词分配 ID 号。

但为什么要这样做?因为计算机擅长处理数字,而不是文本。它们可以对数字进行数学运算,但不能直接对“印度”这个词进行数学运算。所以我们把所有东西转换成数字,进行所有花哨的数学运算,最后再转换回文本。

好了,现在我们有了数字,我们可以继续真正理解 Transformer 是如何工作的了。

注意力,宝宝!

好了,事情从这里开始变得有趣。Transformer 的重大突破基本上是说:去他的顺序处理,如果我们一次性查看所有内容会怎样?

快速插入:什么是编码器和解码器?

在最初的 Transformer 论文中,他们为翻译任务设计了这个编码器-解码器设置。但这到底是什么意思?!好吧,想想两个连接在一起的盒子——每个都有完全不同的任务。编码器盒子接收你的输入句子(比如英语),并一次性处理整个句子,构建出对其含义的丰富理解。就像有人阅读并真正理解你写的东西——完整的上下文、词与词之间的关系,所有的一切。然后它将这种深刻的理解传递给第二个盒子。

编码器实际输出什么?它产生一系列上下文嵌入——每个输入词元一个向量。但这些不是普通的词嵌入。每个向量现在不仅捕捉该词的含义,还捕捉它与句子中每个其他词的关系。所以“the cat sat”中的“cat”嵌入包含了关于“坐着”的信息,而“the cat meowed”中的“cat”则有不同的上下文信息。编码器本质上是一个理解上下文的强大嵌入模型。

现在解码器盒子任务更艰巨,朋友们——它逐词生成输出句子(比如法语),既使用它已经生成的内容,又持续回查编码器的上下文嵌入。这就像有一个翻译,他首先完全理解你的英语句子,然后逐词精心打造完美的法语翻译。

所以编码器 = 一次性理解一切并产生丰富的上下文嵌入,解码器 = 逐部分生成,同时参考这些嵌入。假设你在翻译“the cat sat on the mat”,编码器一次性处理整个英语句子,输出上下文向量,捕捉到有一只猫,它坐着,并且在某块特定的垫子上。然后解码器逐词生成“le chat s’est assis sur le tapis”,关注编码器的嵌入以确保它正确捕捉了一切。

在我们深入探讨编码器与解码器之争之前,要说明的是——它们基本上是一样的。核心构建块是注意力机制,编码器和解码器都使用它。唯一真正的区别是解码器有这种“因果掩码”,每个词只能查看之前的词(因为你从左到右生成文本),这被称为“自回归特性”,而编码器允许你双向查看整个句子。但实际的注意力计算?完全相同。所以与其分开解释它们并重复自己,不如我们直接理解注意力是如何工作的,然后编码器/解码器的区别就显而易见了。我们走起!

核心思想(为什么注意力确实是天才之作)

想象你要把“the cat sat on the mat”翻译成法语。当你要翻译“sat”时,你可能想看看“cat”(谁在坐?)和“mat”(他们坐在哪里?)。你此刻并不真的关心“the”。

这就是注意力。不是强迫网络通过某种压缩的隐藏状态记住所有东西,而是让它回看所有单词,并决定当前哪些词重要。网络学习该关注什么。

让我顿悟的是这个:RNN 就像有人给你讲故事,你试图记住他们说的每一句话。到故事结束时,你已经忘了一半。注意力就像整个故事写在你面前,你可以在任何时刻查看你需要的任何部分。任何时候,你都可以回头再次观察整个上下文,以理解当前时刻。

但是等等——如果我们同时查看所有单词,模型如何知道“cat sat on mat”与“mat sat on cat”不同?词序显然很重要,对吧?

这就是位置嵌入的作用。

位置嵌入:赋予你翅膀

位置嵌入

在其他一切发生之前,我们将每个词转换成向量(词嵌入——标准操作)。但接着我们直接将位置信息添加到这些嵌入中。位置 1 添加一种模式,位置 2 添加另一种,以此类推。可以把它想象成非常基础的东西,告诉模型一个特定词真正位于哪里,这就是位置嵌入的作用。

Transformer 使用这些特定公式来创建位置模式:

PE(pos, 2i) = sin(pos / 10000^(2i/d))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d))

让我分解一下,以免它看起来吓人。pos 是序列中的位置编号(第 1 个词,第 2 个词,等等)。i 是我们正在计算的维度索引(0, 1, 2… 直到 d/2-1),因为每个 i 值通过 sin 产生两个维度值 2i,通过 cos 产生 2i+1。d 是总嵌入大小,原始 Transformer 是 512。如果 d 是 512,那么 i 只需从 0 到 255:

• i=0 给出维度 0 和 1 • i=1 给出维度 2 和 3 • … • i=255 给出维度 510 和 511

让我用 d=512 计算不同位置的实际值。假设我们有一个序列“the cat sat on mat”,现在位置 1 是单词“the”,位置 2 是“cat”:

对于位置 1 (pos=1):

对于维度 i=0:
  PE(1, 0) = sin(1/10000^(0/512)) = sin(1/1) = sin(1) = 0.84
  PE(1, 1) = cos(1/10000^(0/512)) = cos(1/1) = cos(1) = 0.54

对于维度 i=1:
  PE(1, 2) = sin(1/10000^(2/512)) = sin(1/1.0027) = sin(0.997) = 0.84
  PE(1, 3) = cos(1/10000^(2/512)) = cos(1/1.0027) = cos(0.997) = 0.55

对于位置 2 (pos=2):

对于维度 i=0:
  PE(2, 0) = sin(2/10000^(0/512)) = sin(2/1) = sin(2) = 0.91
  PE(2, 1) = cos(2/10000^(0/512)) = cos(2/1) = cos(2) = -0.42

对于维度 i=1:
  PE(2, 2) = sin(2/10000^(2/512)) = sin(2/1.0027) = sin(1.994) = 0.91
  PE(2, 3) = cos(2/10000^(2/512)) = cos(2/1.0027) = cos(1.994) = -0.41

如你所见,每个位置都获得一个完全独特的 512 值的向量。位置 1 的向量以 [0.84, 0.54, 0.84, 0.55…] 开头,而位置 2 的以 [0.91, -0.42, 0.91, -0.41…] 开头。

这里有一件重要的事情——位置 1 的位置嵌入始终完全相同,无论它是“the cat sat on mat”中的第一个词,还是“transformers are awesome”中的第一个词,或是任何其他序列。它只是告诉模型:“嘿,这个词在位置 1,这个词在位置 2”等等。

好了,现在每个词有两个不同的嵌入:

  • 来自嵌入模型的词嵌入(词的含义)
  • 我们刚刚计算的位置嵌入(词的位置)

我们怎么处理它们?超级简单——我们直接把它们加起来!就是这样。

对于每个词,我们取它的词嵌入向量,加上其位置的 position embedding 向量,组合后的向量就成为我们输入到注意力层的数据。

为什么加法在这里有效?嗯,两个嵌入都是向量,向量加法是将两个实体组合成一个新的中间表示的标准数学运算。当你将两个向量相加时,你会创建一个新的方向和大小,它同时携带来自两个来源的信息。从几何角度看——单词“cat”在嵌入空间中指向某个方向(捕捉其含义),而位置 3 指向另一个方向(捕捉位置信息)。将它们相加,你就得到一个编码了两种信息的新向量。

在训练期间,

相似文章