轻松理解 Transformers(2):Attention部分

编者按:随着人工智能技术的不断发展,Transformers 模型架构已成为自然语言处理领域的重要基石。然而,许多人对其内部工作机制仍然感到困惑。本文通过浅显易懂的语言和生活中的例子,帮助读者逐步理解 Transformers 中最核心的 Attention 机制。

本文是Transformers系列的第二篇。作者的核心观点是:Attention 机制是 Transformers 模型区分关键信息的关键所在。本文通过直观的类比和数学公式,让读者对 Attention 的计算过程有更深入的理解。文章详细介绍了Attention 机制如何辨别不同单词的重要性;Query、Key、Value 矩阵及其在 Attention 计算过程中的作用;Masking 如何屏蔽无关内容;Dropout、Skip Connection 等机制如何提升模型稳定性;Add & Norm 层的工作原理,以及归一化对模型学习的重要性。

虽然 Transformers 中各个组件之间相互关联,难以一口气理解全貌,但本文通过耐心讲解 Attention 这一核心机制,确实让读者对整体架构有了更扎实的把握。我们衷心希望这类通俗易懂的文章能帮助更多读者了解 Transformers 技术的运行原理。

以下是译文,enjoy!

作者 | Chen Margalit

编译 | 岳扬

本文经原作者授权,由Baihai IDP编译。如需转载译文,请联系获取授权。

原文链接:towardsdatascience.com/transformer...

🚢🚢🚢欢迎小伙伴们加入AI技术软件及技术交流群,追踪前沿热点,共探技术难题~

Transformers 对人工智能领域,乃至对整个世界都产生了深远的影响。这种模型架构由多个组件构成,但正如提出该架构那篇论文的题目------Attention is All You Need,显然注意力机制(Attention)具有特别重要的意义。本系列的第二部分将主要关注注意力(Attention)及其相关功能,这些功能确保了 Transformer 各组件的良好配合。

图片来自 Vaswani, A. 等人的论文[1]

01 注意力机制(Attention)

在 Transformers 中, attention 指的是一种机制,它能让模型在处理过程中专注于输入(input)的相关部分。可以将其想象成一把手电筒,照亮句子的特定部分,并根据语境(context)判断其在句子中的重要程度。 我认为举几个例子比直接将定义摆出来更有效,通过提供具体的例子,可以激发大脑的思考和理解能力,使大脑有机会自己去理解概念,而不仅仅依赖于定义。

当看到句子"The man took the chair and disappeared"时,我们自然而然地会对句子的不同部分赋予不同程度的重要性(即注意力(attention))。但令我惊讶的是,如果我们去掉一些特定的词,句子的意思基本保持不变:"man took chair disappeared"。虽然这个版本的英语句子有些不通顺,但与原句相比,我们仍然可以理解这句话要表达信息的本质。有趣的是,三个单词("The"、"the "和 "and")占据了句子中词数的43%,但对句子的整体意思没有太大影响。在柏林生活期间,我的德语说得非常棒,每一个接触过我的柏林人可能都这么认为(要么学好德语,要么快乐,这是我必须做出的决定),但对于机器学习模型来说,这一点就不那么明显了。

过去,像循环神经网络(RNNs)等早期架构面临着一个重大挑战:它们难以"记住"输入序列(长度通常超过20个单词)中较远位置的单词。众所周知,这些模型主要依靠数学运算来处理数据。不幸的是,这些早期模型架构中使用的数学运算不够高效,无法将单词表征传递到序列的较远位置。

这种长程依赖(long-term dependency)的限制阻碍了循环神经网络(RNN)长时间保持上下文信息的能力,从而影响了语言翻译或情感分析等任务,因为在这些任务中,理解整个输入序列至关重要。然而,Transformer 通过其注意力机制和自注意力机制更有效地解决了这个问题。 它们可以高效地捕捉输入中的长距离依赖关系,使模型能够保留语境和关联信息,即使是序列中更早出现的单词也不例外。因此,Transformer 已成为克服以往架构限制的开创性解决方案,并明显提高了各种自然语言处理任务的性能。

要创造出像我们今天所遇到的高级聊天机器人这样的优秀产品,就必须让模型具备区分高价值和低价值单词的能力,并在输入的中长距离保留上下文信息。Transformer架构为应对这些挑战而引入的机制被称为注意力机制。

02 点积 Dot Product

神经网络模型如何在理论上辨别不同单词的重要性呢?在分析句子时,我们的目标是找出相互之间关系更紧密的词语。 由于这些单词已经被表示为向量(由数字组成),因此我们需要一种测量数字之间相似性的方法。测量向量之间相似性的数学术语是"点积"(Dot Product)。它涉及将两个向量的元素相乘,并产生一个标量值(例如2、16、-4.43),该值能够表示这两个向量的相似性。机器学习建立在各种数学运算的基础上,其中点积尤为重要。因此,我将花时间详细解释这一概念。

个人感觉和直观理解 Intuition

假设我们将下面这5个单词转换为嵌入表征:"florida", "california", "texas", "politics"和"truth"。由于嵌入(embeddings)只是由数字组成的数组,我们可以将其绘制在图表上。但是,由于它们的维度(用于表示单词的数字数量)很高,可以轻松达到 100 到 1000,因此我们无法将它们原封不动地绘制出来。我们无法在2维的计算机/手机屏幕上绘制一个100维的向量。此外,人脑很难理解超过3维的东西。4维向量是什么样子的?我不知道。

为了解决这个问题,我们采用了主成分分析(PrincipalComponentAnalysis,PCA[2])这一降维技术。通过应用PCA,我们可以将嵌入投影到二维空间(x、y坐标)。维度的减少有助于我们在图表上更直观地展现数据。虽然降维后会丢失一些信息,但希望这些降维后的向量仍然能够保持足够的相似性,从而使我们能够深入了解和理解词语之间的关系。

这些数据基于 GloVe 嵌入[3]。

ini 复制代码
florida = [-2.40062016, 0.00478901]
california = [-2.54245794, -0.37579669]
texas = [-2.24764634, -0.12963368]
politics = [3.02004564, 2.88826688]
truth = [4.17067881, -2.38762552]

也许你会发现这些数字有一些规律可循,但为了方便起见,现在来绘制这些数字。

图中有5个二维向量

在这张图片中,我们能够看到五个二维向量(用x,y坐标表示),分别代表五个不同的单词。正如我们所见,该图示表明了有些单词与其他单词的关联度更高。

数学 math

通过一个简单的方程,我们可以将向量的数学表示与这张图片对应起来。如果您对数学不是特别感兴趣,并且记得《Attention is All You Need》的论文作者将 Transformer 架构描述为"简单的网络架构",有时候机器学习领域的概念和技术可能会让人感到复杂或难以理解,这可能是真的,但在本文中不会是这样,本文所讨论的内容都是相对简单的。我来解释一下:

点积计算公式

符号 ||a|| 表示向量 "a" 的大小,它表示从原点(点 0,0)到向量顶端的距离。计算向量大小的公式如下:

向量大小计算公式

计算结果会是一个数字,如 4 或 12.4。

Theta(θ)指的是向量之间的角度(可以看一下上方的图片)。角度的余弦值,表示为cos(θ),是将余弦函数应用于该角度值的简单结果。

代码 Code

斯坦福大学的研究人员使用 GloVe 算法[3]为这些单词生成嵌入,这些我们在前文讨论过。虽然他们有创建这些嵌入的自有技术,但其基本概念与我们在本系列前一部分中谈到的相同。举个例子,选取 4 个单词,将它们的维度降为 2,然后将它们的向量直接绘制成 x 坐标和 y 坐标。

为了使这个过程顺利运行,下载GloVe[3]是必要的先决条件。

*下面是部分代码,第一个框中的代码,灵感来自于我之前见过的一些代码,但我似乎已经找不到源代码了。

python 复制代码
import pandas as pd

path_to_glove_embds = 'glove.6B.100d.txt'

glove = pd.read_csv(path_to_glove_embds, sep=" ", header=None, index_col=0)
glove_embedding = {key: val.values for key, val in glove.T.items()}
python 复制代码
words = ['florida', 'california', 'texas', 'politics', 'truth']
word_embeddings = [glove_embedding[word] for word in words]

print(word_embeddings[0]).shape # 100 numbers to represent each word.
---------------------
output:
(100,)
python 复制代码
pca = PCA(n_components=2) # reduce dimensionality from 100 to 2.
word_embeddings_pca = pca.fit_transform(word_embeddings)
python 复制代码
for i in range(5):
 print(word_embeddings_pca[i])

---------------------
output:
[-2.40062016 0.00478901] # florida
[-2.54245794 -0.37579669] # california
[-2.24764634 -0.12963368] # texas
[3.02004564 2.88826688] # politics
[ 4.17067881 -2.38762552] # truth

现在我们拥有了这5个单词的真实表征,下一步是进行点积计算。

计算向量大小:

python 复制代码
import numpy as np

florida_vector = [-2.40062016,  0.00478901]
florida_vector_magnitude = np.linalg.norm(florida_vector)

print(florida_vector_magnitude)
---------------------
output:
2.4006249368060817 # The magnitude of the vector "florida" is 2.4.

计算两个相似向量之间的点积:

python 复制代码
import numpy as np

florida_vector = [-2.40062016,  0.00478901]
texas_vector = [-2.24764634 -0.12963368]

print(np.dot(florida_vector, texas_vector))

---------------------
output:
5.395124299364358

计算两个不同向量之间的点积:

python 复制代码
import numpy as np

florida_vector = [-2.40062016, 0.00478901]
truth_vector = [4.17067881, -2.38762552]

print(np.dot(florida_vector, truth_vector))

---------------------
output:
-10.023649994662344

从点积计算中可以明显看出,它似乎捕捉并反映了不同概念之间的相似性。

03 缩放点积注意力 Scaled Dot-Product attention

个人感觉和直观理解 Intuition

既然我们已经基本掌握了点积的计算方法,那么就可以开始深入研究注意力机制(attention)了,特别是自注意力机制(self-attention mechanism)。使用自注意力机制使模型能够确定每个单词的重要性,而不管它与其他单词的"物理"距离是多少。这使得模型能够根据每个单词的上下文相关性(contextual relevance)做出比较明智的决策,从而更好地理解单词。

为了实现这一宏伟目标,我们创建了由可学习参数(learnable parameters)组成的3个矩阵,称为查询矩阵(Query)、键矩阵(Key)和值矩阵(Value)(Q、K、V)。查询矩阵(query matrix)可以看作是一个包含用户查询或询问的矩阵(例如,当您询问ChatGPT:"上帝今天下午5点有空吗?(god is available today at 5 p.m.?)"时,这就是查询矩阵)。键矩阵(key matrix)包含序列中的所有其他单词。通过计算这些矩阵之间的点积,我们可以得到每个单词与我们当前正在研究的单词之间的相关程度(例如,翻译或回答用户的询问)。

值矩阵(value matrix)为序列中的每个单词都提供了一种"干净"的表示("clean" representation)。其他两个矩阵都是以类似的方式形成的,为什么我只说值矩阵"干净(clean)"?因为值矩阵保持在其原始形式,我们不会在与另一个矩阵相乘后使用它,也不会用某个值对它进行归一化处理。这种区别使得值矩阵与众不同,确保它保留了原始的嵌入,无需额外的计算或变换。

这三个矩阵的大小都是word_embedding (512)。不过,它们都被分成了"heads"。在论文中,作者使用了8个"heads"(译者注:heads指的是将注意力机制分解为多个子机制的一种方法。模型可以同时关注输入的不同方面,并从中获取更丰富的信息。这种分解可以增加模型的表达能力和性能。),因此每个矩阵的大小为 sequence_length 乘以64。你可能会问,为什么同样的操作要对 1/8 的数据执行 8 次,而不是对所有数据执行一次。这种方法的理论基础是,通过使用8组不同的权重(如前所述,这些权重是可学习的)进行相同的操作8次,我们可以利用数据中固有的多样性。每个"heads"可以专注于输入中的一个特定方面,总的来说,这可以带来更好的性能。

*在大多数实施方案中,我们实际上并没有将主矩阵分成8份。通过索引,可以实现分割,从而为每个部分实现并行处理。然而,这些只是实现细节。不过,这些只是实现细节。从理论上讲,我们可以用 8 个矩阵完成几乎相同的操作。

我们将查询矩阵Q和键矩阵K进行点积运算,然后将结果除以维度的平方根进行归一化。然后将归一化后的结果通过Softmax函数[4]进行处理,然后将结果与值矩阵V相乘。之所以要对结果进行归一化处理,是因为查询矩阵Q和键矩阵K是以某种随机方式生成的矩阵。它们的维度可能完全不相关(独立),而独立矩阵之间的乘法可能会产生非常大的数值,这可能会对学习效果产生不利影响,我将在本系列的后续部分中解释。

然后,我们使用一种名为Softmax[4]的非线性变换(non-linear transformation),使所有数字的范围介于 0 到 1 之间,并且总和为1。结果类似于概率分布(因为有从0到1的多个结果数字相加得到1)。这些数字体现了序列中每个单词与其他单词的相关性。

最后,我们将结果与矩阵V相乘,就得到了自注意力分数(self-attention score)。

*实际上,编码器由N(在论文中,N=6)个相同的层构成,每个层从上一层获取输入并执行相同的操作。最后一层将数据传递给解码器(我们将在本系列的后续部分中讨论)和编码器的上层。

这是自注意力机制的可视化图像。它就像教室里的一群朋友,有些人与某些人的联系更紧密,有些人与任何人的联系都不太紧密。

图片来自 Vaswani, A. 等人的论文[1]

数学 math

查询矩阵Q、键矩阵K和值矩阵V是通过对嵌入矩阵进行线性变换得到的。线性变换在机器学习中非常重要,如果你对成为一名机器学习从业者感兴趣,我建议你进一步探索这个知识点。本文不会进行深入探讨,但我要说的是,线性变换是一种将向量(或矩阵)从一个空间移动到另一个空间的数学操作。听起来似乎比实际要复杂得多。想象一个箭头指向一个方向,然后移动到右边30度的位置。这就是线性变换的示例。线性变换需要满足一些条件才能被认为是线性的,但现在并不重要。关键是它保留了许多原始向量的特性。

自注意力层的整个计算是通过应用以下公式来完成的:

缩放点积注意力------图片来自 Vaswani, A. 等人的论文[1]

计算过程如下所示:

  1. 用Q乘以K的转置(翻转)。

  2. 将结果除以矩阵 K 维度数的平方根。

  3. 然后有了描述每个单词与其他单词相似程度的"注意力矩阵分数(attention matrix scores)"。将每一行进行 Softmax[4](非线性)变换。Softmax[4] 有三个有趣的相关功能:

    a. 缩放所有数字,使其介于 0 和 1 之间。

    b. 使所有数字的和为1。

    c. 突出差距,使得稍微更重要的部分变得更加重要。因此,我们现在可以轻松区分模型对单词x1与x2、x3、x4等之间联系的不同感知程度。

  4. 将计算出来的分数与矩阵V相乘。这是自注意力机制操作的最终结果。

04 Masking

在本系列的前一章中,我已经解释过我们使用虚拟标记来处理句子中出现的特殊情况,如句子中的第一个单词、最后一个单词等。其中一个标记,表示为,表示没有实际数据,但我们需要在整个过程中保持一致的矩阵大小。为了确保模型理解这些是虚拟标记,并且在自注意力的计算过程中对其不予考虑,我们将这些标记表示为负无穷大(例如一个非常大的负数,例如-153513871339)。掩码值被添加到Q乘以K的乘积结果中。然后,Softmax将这些数字转换为0。这使我们能够在注意力机制(attention mechanism)中有效地忽略虚拟标记,同时保持计算的完整性。

05 Dropout

在自注意力层之后,应用了一种被称为 Dropout 的操作。Dropout是机器学习中广泛使用的一种正则化技术。正则化的目的是在训练过程中对模型施加约束,使其难以过度依赖特定的输入细节。这样,模型就能够更加稳健地学习,并提高其泛化能力。具体实现包括随机选择一些激活值(activations)(来自不同层的输出数字),并将它们置零。在同一层的每次传递中,都有不同的激活值将被置零,从而防止模型根据所获数据找到特定的解决方案。从本质上讲,Dropout有助于增强模型处理不同输入内容的能力,并使模型难以针对数据中的特定模式进行调整。

06 Skip Connection

Transformer架构中的另一个重要操作称为Skip Connection。

图片来自 Vaswani, A. 等人的论文[1]

Skip Connection是一种在不经过任何转换的情况下传递输入(input)的方法。举例来说,假设我向我的经理报告,而我的经理又向他的经理报告。即使是出于让报告更有用的纯粹目的,输入内容在经过另一个人(或 ML 层)处理时,也会进行一些修改。在这个类比中,Skip Connection就像是我直接向我的经理的经理汇报。因此,上级经理既通过我的经理(经过处理的数据)接收输入,也直接从我这里(未经处理的数据)接收输入。然后,上级经理可以更好地做出决策。采用Skip Connection是为了解决梯度消失等潜在问题,我将在下一节中解释。

07 Add & Norm 层

"Add & Norm"层主要执行加法和归一化操作。我先说加法,因为它比较简单。基本上,我们是将自注意力层的输出与原始输入(通过Skip Connection接收)相加。这个加法是逐元素进行的(每个数字与其相同位置的数字相加)。然后对结果进行归一化。

我们之所以进行归一化处理,原因是每个层都要进行大量计算。数字多次相乘可能会导致意想不到的情况。例如,如果我取一个小数,比如0.3,然后将其与另一个小数,比如0.9相乘,得到的结果是0.27,会比起开始时更小。如果我多次这样做,最终可能会得到非常接近于0的结果。这可能会导致深度学习中的一个问题,即梯度消失。

我现在不想说得太深,以免这篇文章读起来费时费力,但我想说的是,如果数字变得非常接近 0,模型将无法学习。现代机器学习的基础是计算梯度,并使用这些梯度(以及其他一些因素)调整权重。如果这些梯度接近于0,模型将很难有效地学习。

相反,当非小数与非小数相乘时,可能会发生相反的现象,即梯度爆炸(exploding gradients) ,会导致值变得过大。因此,由于权重和激活值的巨大变化,模型的学习会面临困难,从而导致训练过程中的不稳定性和发散性。

机器学习模型有点像小孩子,它们需要保护。保护这些模型免受数字过大或过小的影响的一种方法是归一化。

数学 math

层归一化操作虽然看起来很可怕(一如既往),但实际上相对简单。

图片由 Pytorch 提供,摘自此处[5]

在层归一化操作中,我们需要对每个输入执行以下简单步骤:

  • 从输入中减去其均值。
  • 除以方差的平方根并加上一个epsilon(ε)(一个非常小的数字),用于避免除以零。
  • 将得到的得分乘以一个可学习的参数,称为gamma(γ)。
  • 添加另一个可学习的参数,称为beta(β)。
  • 这些步骤可确保均值接近于0,标准差接近于1。归一化过程增强了训练的稳定性、速度和整体性能。

代码 Code

matlab 复制代码
# x being the input.
(x - mean(x)) / sqrt(variance(x) + epsilon) * gamma + beta

08 总结

至此,我们对编码器的主要内部工作原理有了扎实的了解。此外,我们还探索了Skip Connection,这是机器学习中一种纯粹的技术(也是一种重要的技术),可以提高模型的学习能力。

尽管本节内容有点复杂,但让我们已经对整个 Transformer 架构有了实质性的了解。随着我们在本系列中的进一步深入,理解本部分的内容将有助于你理解本系列中其他部分的内容。

请记住,这是一个前沿领域中的最新技术。学起来并不简单。即使您现在仍然没有完全理解所有内容,您也已经取得了很大的进步!

下一部分将介绍机器学习中的另一个基础(且更简单)的概念,即前馈神经网络。

图片来自 Vaswani, A. 等人的论文[1]

END

参考资料

[1]proceedings.neurips.cc/paper_files...

[2]scikit-learn.org/stable/modu...

[3]nlp.stanford.edu/projects/gl...

[4]docs.scipy.org/doc/scipy/r...

[5]pytorch.org/docs/stable...

🚢🚢🚢欢迎小伙伴们加入AI技术软件及技术交流群,追踪前沿热点,共探技术难题~

相关推荐
一尘之中2 分钟前
网 络 安 全
网络·人工智能·学习·安全
学习前端的小z4 分钟前
【AIGC】ChatGPT是如何思考的:探索CoT思维链技术的奥秘
人工智能·chatgpt·aigc
新缸中之脑13 分钟前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
人工智障调包侠14 分钟前
基于深度学习多层感知机进行手机价格预测
人工智能·python·深度学习·机器学习·数据分析
开始King1 小时前
Tensorflow2.0
人工智能·tensorflow
Elastic 中国社区官方博客1 小时前
Elasticsearch 开放推理 API 增加了对 Google AI Studio 的支持
大数据·数据库·人工智能·elasticsearch·搜索引擎
infominer1 小时前
RAGFlow 0.12 版本功能导读
人工智能·开源·aigc·ai-native
涩即是Null1 小时前
如何构建LSTM神经网络模型
人工智能·rnn·深度学习·神经网络·lstm
本本的小橙子1 小时前
第十四周:机器学习
人工智能·机器学习
励志成为美貌才华为一体的女子2 小时前
《大规模语言模型从理论到实践》第一轮学习--第四章分布式训练
人工智能·分布式·语言模型