Transformers 亮相以来彻底改变了深度学习模型。
今天,我们来揭示 Transformers 背后的核心概念:注意力机制、编码器-解码器架构、多头注意力等等。 通过 Python 代码片段,让你深入了解其原理。
一、理解注意力机制
注意力机制是神经网络中一个迷人的概念,特别是在涉及到像 NLP 这样的任务时。它就像给模型一个聚光灯,让它能够集中注意力在输入序列的某些部分,同时忽略其他部分,就像我们人类在理解句子时关注特定的单词或短语一样。
现在,让我们深入了解一种特定类型的注意力机制,称为自注意力,也称为内部注意力。想象一下,当你阅读一句话时,你的大脑会自动突出显示重要的单词或短语来理解意思。这就是神经网络中自注意力的基本原理。它使序列中的每个单词都能“关注”其他单词,包括自己在内,以更好地理解上下文。
二、自注意力是如何工作的?
以下是自注意力在一个简单示例中的工作原理:
考虑一句话:“The cat sat on the mat.”
嵌入
首先,模型将输入序列中的每个单词嵌入到一个高维向量表示中。这个嵌入过程允许模型捕捉单词之间的语义相似性。
查询、键和值向量
接下来,模型为序列中的每个单词计算三个向量:查询向量、键向量和值向量。在训练过程中,模型学习这些向量,每个向量都有不同的作用。查询向量表示单词的查询,即模型在序列中寻找的内容。键向量表示单词的键,即序列中其他单词应该注意的内容。值向量表示单词的值,即单词对输出所贡献的信息。
注意力分数
一旦模型计算了每个单词的查询、键和值向量,它就会为序列中的每一对单词计算注意力分数。这通常通过取查询向量和键向量的点积来实现,以评估单词之间的相似性。
SoftMax 归一化
然后,使用 softmax 函数对注意力分数进行归一化,以获得注意力权重。这些权重表示每个单词应该关注序列中其他单词的程度。注意力权重较高的单词被认为对正在执行的任务更为关键。
加权求和
最后,使用注意力权重计算值向量的加权和。这产生了每个序列中单词的自注意力机制输出,捕获了来自其他单词的上下文信息。
下面是一个计算注意力分数的简单解释:
# 安装 PyTorch !pip install torch==2.2.1+cu121
# 导入库 import torch import torch.nn.functional as F
# 示例输入序列 input_sequence = torch.tensor([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]])
# 生成 Key、Query 和 Value 矩阵的随机权重 random_weights_key = torch.randn(input_sequence.size(-1), input_sequence.size(-1)) random_weights_query = torch.randn(input_sequence.size(-1), input_sequence.size(-1)) random_weights_value = torch.randn(input_sequence.size(-1), input_sequence.size(-1))
# 计算 Key、Query 和 Value 矩阵 key = torch.matmul(input_sequence, random_weights_key) query = torch.matmul(input_sequence, random_weights_query) value = torch.matmul(input_sequence, random_weights_value)
# 计算注意力分数 attention_scores = torch.matmul(query, key.T) / torch.sqrt(torch.tensor(query.size(-1), dtype=torch.float32))
# 使用 softmax 函数获得注意力权重 attention_weights = F.softmax(attention_scores, dim=-1)
# 计算 Value 向量的加权和 output = torch.matmul(attention_weights, value) print("自注意力机制后的输出:") print(output)
三、Transformer 模型的基础
在我们深入探讨Transformer模型的复杂工作原理之前,让我们花点时间欣赏其开创性的架构。正如我们之前讨论的,Transformer模型通过引入围绕自注意力机制的新颖方法,重塑了自然语言处理(NLP)的格局。在接下来的章节中,我们将揭开Transformer模型的核心组件,阐明其编码器-解码器架构、位置编码、多头注意力和前馈网络。
编码器-解码器架构
在Transformer的核心是其编码器-解码器架构——两个关键组件之间的共生关系,分别负责处理输入序列和生成输出序列。编码器和解码器中的每一层都包含相同的子层,包括自注意力机制和前馈网络。这种架构不仅有助于全面理解输入序列,而且能够生成上下文丰富的输出序列。
位置编码
尽管Transformer模型具有强大的功能,但它缺乏对元素顺序的内在理解——这是位置编码所解决的一个缺点。通过将输入嵌入与位置信息结合起来,位置编码使模型能够区分序列中元素的相对位置。这种细致的理解对于捕捉语言的时间动态和促进准确理解至关重要。
多头注意力
Transformer模型的一个显著特征是它能够同时关注输入序列的不同部分——这是多头注意力实现的。通过将查询、键和值向量分成多个头,并进行独立的自注意力计算,模型获得了对输入序列的细致透视,丰富了其表示,带有多样化的上下文信息。
前馈网络
与人类大脑能够并行处理信息的能力类似,Transformer模型中的每一层都包含一个前馈网络——一种能够捕捉序列中元素之间复杂关系的多功能组件。通过使用线性变换和非线性激活函数,前馈网络使模型能够在语言的复杂语义景观中航行,促进文本的稳健理解和生成。
四、Transformer 组件的详细说明
要实现,首先运行位置编码、多头注意力机制和前馈网络的代码,然后是编码器、解码器和Transformer架构。
#import libraries import math import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F
1、位置编码
在Transformer模型中,位置编码是一个关键组件,它将关于标记位置的信息注入到输入嵌入中。
与循环神经网络(RNNs)或卷积神经网络(CNNs)不同,由于其置换不变性,Transformers 缺乏对标记位置的内在知识。位置编码通过为模型提供位置信息来解决这一限制,使其能够按照正确的顺序处理序列。
位置编码的概念
通常在将输入嵌入传入Transformer模型之前,会将位置编码添加到嵌入中。它由一组具有不同频率和相位的正弦函数组成,允许模型根据它们在序列中的位置区分标记。
位置编码的公式如下
假设您有一个长度为L的输入序列,并且需要在该序列中找到第k个对象的位置。位置编码由不同频率的正弦和余弦函数给出:
其中:
-
k:输入序列中对象的位置,0≤k<L/2
-
d:输出嵌入空间的维度
-
P(k,j):位置函数,用于将输入序列中的位置k映射到位置矩阵的索引(k,j)
-
n:用户定义的标量,由《Attention Is All You Need》的作者设置为10,000。
-
i:用于将列索引映射到0≤i<d/2的值,单个i值同时映射到正弦和余弦函数。
不同的位置编码方案
在Transformer中使用了各种位置编码方案,每种方案都有其优点和缺点: