Transformer?Attention?——Are All You Need!
Hi,大家好,我是半亩花海。本文主要较为深入地讲述 transformer 模型及 attention 机制等相关深度学习的知识,主要介绍模型结构、原理等。Transformer 属于是当下比较流行和创新的深度学习的基础模型架构,主要应用于自然语言处理(NLP)、计算机视觉(CV)领域,在处理序列数据时表现出色,因此本文的标题也引用了 Attention经典论文 里面的标题“Attention Is All You Need”,生动活泼。另外,行文难免有不足之处,欢迎大家广泛交流!
目录
一、总体结构图
1. 模型简介
2. 模型总体架构图
二、输入部分
1. 输入层结构
2. 文本嵌入层 / 词嵌入层
3. 位置编码器
4. 结合词嵌入和位置编码
三、编码器
1. 编码器结构
2. 注意力机制(Attention)
3. 前馈网络(Feed-forward Network)
4. 残差连接和层归一化(Residual Connections & Layer Normalization)
四、解码器
1. 解码器结构
2. 掩码张量(Masking Tensor)
3. 带掩码的多头自注意力机制(Masked Self-Attention)
4. 编码器-解码器注意力机制(Encoder-Decoder Attention)
5. 前馈网络(Feed-forward Network)
6. 残差连接和层归一化(Residual Connections & Layer Normalization)
五、输出部分
参考文章
一、总体结构图
1. 模型简介
Transformer 是一种用于自然语言处理(NLP)和其他序列到序列(sequence-to-sequence,seq2seq)任务的深度学习模型架构,比如应用于机器翻译、文本生成、序列任务、语言模型、迁移学习等。Transformer 相比于其他深度学习架构,其关键的创新点在于引入了自注意力机制(Self-Attention),这使得其在处理序列数据时表现出色。
2. 模型总体架构图
在《Attention Is All You Need》经典论文中,给出的 Transformer 结构图如下所示。
图 1 模型总体架构图
具体解释如下图所示,主要简述了编码器(Encoder)、前馈全连接子层 / 前馈网络(Feed-forward Network)、残差连接(Residual Connections)、规范化层 / 层归一化(Layer Normalization)、编码-解码注意力机制(Decoder-Encoder Attention)、解码器(Decoder)。
图 2 模型总体架构图(含各部分解释)
图 3 模型总体架构图(含注意力机制相关解释)
由上图可知,Transformer 本质上是一个 Encoder-Decoder (编码器-解码器)架构,其总体架构大体可分为以下四个部分:
- 输入部分——Inputs、Outputs(shifted right)
- 编码器部分——Encoder
- 解码器部分——Decoder
- 输出部分——Output Probabilities
在接下来的架构分析中,我们将假设使用 Transformer 模型架构处理从⼀种语言文本到另⼀种语言文本的翻译工作。因此,很多命名方式遵循 NLP 中的规则。
二、输入部分
输入部分是Transformer模型中处理数据的第一步。假设我们要输入的句子是 "我喜欢吃苹果"。
1. 输入层结构
输入层主要包含以下两部分:
- Inputs:源文本嵌入层/词嵌入层(Input Embedding)及其位置编码(Positional Encoding)
- Outputs(shifted right):目标文本嵌入层(Output Embedding)及其位置编码(Positional Encoding)
图 4 输入层结构图
2. 文本嵌入层 / 词嵌入层
(1)文本嵌入 / 词嵌入的定义
我们将每个词转化为一个向量,这个过程就是词嵌入或者文本嵌入。
注意:文本嵌入层即 Embedding 层,Embedding 层产生的张量称为词嵌入张量,Embedding 层的最后一维将称作词向量等。
(2)文本嵌入 / 词嵌入的作用
每个词的向量是一个固定维度的表示,通常通过预训练的词向量模型(如Word2Vec、GloVe)获得,或者通过模型学习获得(如BERT)。无论是源文本嵌入还是目标文本嵌入,都是为了将文本的数字表示转变为向量表示,希望在这样的高维空间捕捉词汇间的关系。
3. 位置编码器
(1)位置编码器的定义
由于 Transformer 本身没有卷积和循环结构,即没有序列处理的顺序机制,为了引入位置信息(给每个位置生成一个唯一的向量,帮助模型理解每个词的相对位置),加入位置编码(Positional Encoding, PE),每个位置编码通常是基于正弦和余弦函数的形式,生成独特的向量表示,维度与嵌入相同,如下所示。
(2)位置编码器的作用
因为在 Transformer 的编码器结构中,并没有针对词汇位置信息的处理,因此需要在 Embedding 层后加入位置编码器,将(词汇位置不同可能会产生不同语义的)信息加入到词嵌入张量中,以弥补位置信息的缺失。
例如,在句子 "我喜欢吃苹果" 中,位置编码帮助模型知道 "我" 在最前面,而 "苹果" 是最后一个词。
4. 结合词嵌入和位置编码
词嵌入向量和位置编码向量逐元素相加,得到每个词的最终输入表示。这样,每个词不仅有了语义信息,还带有位置信息。
三、编码器
1. 编码器结构
编码器部分:
- 由 N 个编码器层堆叠而成
- 每个编码器层由两个子层连接结构组成
- 第一个子层包含一个多头注意力机制(Multi-Head Attention)和一个层归一化(Layer Normalization)以及一个残差连接(Residual Connections)
- 第二个子层包含一个前馈网络(Feed-forward Network)和一个层归一化(Layer Normalization)以及一个残差连接(Residual Connections)
图 5 输入层结构图
2. 注意力机制(Attention)
(1)什么是注意力
我们观察事物时,之所以能够快速判断一种事物(当然允许判断是错误的),是因为我们大脑能够很快把注意力放在事物最具有辨识度的部分从而作出判断,而并非是从头到尾的观察一遍事物后,才能有判断结果。正是基于这样的理论,就产生了注意力机制。
(2)自注意力机制(Self-Attention)
在每一层编码器中,首先通过自注意力机制来计算每个词与其他词的相关性或相似性,并据此调整每个位置的表示。具体来说,每个词都会生成一个指定输入的查询向量(Query)、键向量(Key)、值向量(Value),通过公式得到注意力的计算结果,代表 Query 在 Key 和 Value 作用下的表示,目的是计算出每个词在当前上下文中应该关注的其他词。
- 输入表示:假设输入是一个矩阵 ,其中是序列的长度,是每个位置的表示维度。
- 线性变换:输入矩阵 被映射到三个不同的向量:Query、Key、Value,并通过学习的权重矩阵 实现。【这里, 是查询矩阵, 是键矩阵, 是值矩阵。】
- 计算注意力权重:计算查询向量(Q)与键向量(K)的点积来衡量各个位置之间的相关性,得到注意力分数,并通过 Softmax 归一化得到注意力权重,最后与值向量(V)进行加权求和。
其中, 是键向量的维度,通常是 的一部分, 是缩放因子,用于防止点积值过大、造成梯度消失。
(3)多头注意力机制(Multi-Head Attention)
为使模型能够多角度捕捉不同的语义关系,增强表达能力,提升训练效率(并行计算),Transformer 使用了多头注意力机制。每个注意力头独立计算注意力分数,并将它们的结果拼接起来,再通过一个线性变换得到最终的输出。
这里,每个注意力头 是第 个头的注意力输出; 是拼接每个头的输出结果; 是一个权重矩阵,用于线性变换。
3. 前馈网络(Feed-forward Network)
在自注意力层之后,每个编码器层还包含一个前馈网络。它通常包括两个全连接层和一个激活函数(如 ReLU),用于对注意力层输出的信息进行进一步的处理,比如处理复杂的非线性变换。
这里, 是权重矩阵, 是偏置,ReLU 是激活函数,用于增加非线性。
4. 残差连接和层归一化(Residual Connections & Layer Normalization)
为了防止梯度消失和加速训练,每一层的输出都与输入进行残差连接,并进行层归一化,使得模型可以更有效地学习。
其中, 表示经过自注意力或前馈网络的处理。
四、解码器
1. 解码器结构
解码器与编码器的结构基本一致,只不过多了一个编码-解码注意力机制层,具体结构如下:
- 由 N 个解码器层堆叠⽽成
- 每个解码器层由三个⼦层连接结构组成
- 第一个子层包含一个带掩码的多头注意力机制(Masked Multi-Head Attention)和一个层归一化(Layer Normalization)以及一个残差连接(Residual Connections)
- 第二个子层包含一个编码-解码多头注意力机制(Multi-Head Attention)和一个层归一化(Layer Normalization)以及一个残差连接(Residual Connections)
- 第三个子层包含一个前馈网络和一个层归一化(Layer Normalization)以及一个残差连接(Residual Connections)
图 6 输入层结构图
2. 掩码张量(Masking Tensor)
(1)什么是掩码张量
掩代表遮掩,码代表张量中的数值,掩码实际上是一个二进制张量,它的尺寸不定,mask 一般只有 1 和 0 的元素,它与注意力得分矩阵相乘,决定了哪些位置的注意力得分会被屏蔽。比如,自定义掩码张量为 0 的填充位置代表注意力得分被屏蔽,1 代表位置有效。
在 Transformer 中,掩码张量主要用于限制哪些位置的信息能够被模型关注或计算。掩码通过遮盖不需要关注的部分,确保模型只关注有意义的信息,避免计算过程中引入无效的干扰。
(2)掩码张量与注意力得分矩阵相乘
在计算注意力时,掩码张量会与注意力得分矩阵相乘,那么值为 1 则有效,值为 0 的位置则注意力得分设为负无穷,使得经过 Softmax 后这些位置的得分为 0,从而不被注意力机制考虑。
(3)如何判断无效位置?
1)通过填充标记(padding token):填充部分通常会有一个特定的标记(如 <PAD>)。在训练和推理过程中,模型会识别这些标记,并为这些位置创建掩码张量。在掩码张量中,填充位置对应的值会设置为0,有效位置对应的值会设置为1。
举个例子:在处理变长序列时,通常需要将序列填充到相同的长度。而填充部分是不包含有效信息的,因此需要被屏蔽掉。
例如,假设你有以下两个句子,经过填充后如下:
- 句子1:["我", "喜欢", "苹果"]
- 句子2:["苹果", "<PAD>", "<PAD>"]
假设有效位置掩码为 1,填充位置或 <PAD>(即无效位置)的掩码为 0,那么模型会根据 <PAD> 来生成掩码张量如下:
- 句子1的掩码: [1,1,1](因为它没有填充)
- 句子2的掩码: [1,0,0](因为第二和第三个位置是填充部分)
这些掩码张量与注意力得分矩阵相乘时,会屏蔽掉填充部分即 0,确保模型只关注有效的信息。
2)通过长度信息:在某些情况下,输入的序列的真实长度是已知的。假设你知道某个输入句子的有效长度是 4(即 "我 喜欢 吃 苹果"),那么其他超过该长度的部分就是无效的。这样就可以根据序列的真实长度来创建掩码张量、标记无效位置,而无需通过填充。
3. 带掩码的多头自注意力机制(Masked Self-Attention)
与编码器不同的是,解码器中的自注意力层包含掩码机制(Mask),这是为了确保在生成第 个词时,解码器只能使用第 个词及之前的词的信息,而无法看到未来的词(第 个词及之后,因为防止信息泄露)。这通过应用未来掩码(Look-Ahead Mask)来实现。
假设解码器的输入是 ,查询、键、值的计算公式如下:
则注意力得分为:
其中:
- 是查询(Query),表示当前解码器的输入(上一时刻的输出)。
- 是键(Key),表示当前时刻的解码器输入。
- 是值(Value),也是当前时刻的解码器输入。
- 是掩码矩阵(Mask),屏蔽未来位置,通过将未来位置的注意力值设为负无穷大,确保模型不会泄漏未来的信息。
4. 编码器-解码器注意力机制(Encoder-Decoder Attention)
接下来,解码器需要从编码器中提取信息,以生成当前输出序列。编码器-解码器注意力层的作用就是让解码器关注编码器输出的不同部分。这样,解码器可以基于输入的上下文信息来生成正确的输出。
原理:解码器的自注意力机制会根据键(K)和值(V)这些键值对(来自编码器的输出),结合当前解码器的查询 Q(来自解码器上一步的输出——带掩码的...),获取来自编码器的上下文信息。
计算注意力:
这种机制帮助解码器在生成每个词时,参考编码器的输出,确保生成的每个词与输入的上下文一致。
5. 前馈网络(Feed-forward Network)
详见编码器对应部分。
6. 残差连接和层归一化(Residual Connections & Layer Normalization)
详见编码器对应部分。
五、输出部分
输出层主要包含以下两部分:
- Linear:线性层,作用是转换维度,即通过对上一步的线性变化得到指定维度的输出
- Softmax:激活函数层,作用是使最后一维的向量中的数字缩放到 0-1 的概率值域内,并满足他们的和为 1
图 7 输出层结构图
具体来说,解码器的最后输出通过线性变换后,送入 Softmax 函数,生成一个概率分布,用于预测下一个词(得到最终的词预测结果)。
- :解码器的最后隐藏状态。
- 和 :是线性变换的权重和偏置。
参考文章
[1] Transformer——逐步详解架构和完整代码搭建_transformer搭建-CSDN博客
[2] 【超详细】【原理篇&实战篇】一文读懂Transformer-CSDN博客
[3] Transformer 模型详解_transformer模型-CSDN博客