【ML】transform 之 decoder 及其实现细节
- 1. decoder
- 2. encoder 和decoder 之间是如何处理和传递讯息的?self-attention
- 3. 查询(Query)、键(Key)、值(Value)是三个核心概念及其具体含义和计算方式
1. decoder
在 Transformer 架构中,解码器(Decoder)是负责生成输出序列的部分,例如在机器翻译任务中生成目标语言的句子。解码器由多个相同的层组成,每层都包含几个关键组件,以下是解码器的实现细节:
-
自注意力层(Self-Attention Layer):
- 解码器的第一个自注意力层只接收之前生成的输出作为输入,而不是整个输入序列。这确保了解码器在生成每个输出时刻时,只能看到它之前的状态,而不是未来的输出,这是遵循序列生成中的因果关系。
-
遮蔽(Masking):
- 在自注意力层中使用遮蔽技术,确保在计算注意力权重时,仅考虑当前步骤之前的输出,忽略之后的输出。这通常通过在 softmax 操作之前添加一个上三角矩阵的掩码来实现。
-
编码器-解码器注意力层(Encoder-Decoder Attention Layer):
- 紧接着自注意力层的是编码器-解码器注意力层,它允许解码器层关注编码器的输出。这个层通常使用标准的自注意力机制,但只针对编码器的输出序列。
-
前馈网络(Feed-Forward Neural Network):
- 每个自注意力和编码器-解码器注意力层后面都有一个前馈网络,通常包含两个线性变换和一个非线性激活函数(如 ReLU)。
-
残差连接(Residual Connection):
- 每个子层(自注意力层、编码器-解码器注意力层和前馈网络)的输出都通过残差连接与子层的输入相加。这有助于缓解深层网络训练中的梯度消失问题。
-
层归一化(Layer Normalization):
- 在每个子层的输入和输出上应用层归一化,以稳定训练过程并加速收敛。
-
可学习的参数:
- 解码器的每个层都包含可学习的参数,如自注意力层和前馈网络的权重,以及层归一化和残差连接的缩放和平移参数。
-
输出层:
- 解码器的最后一层通常会有一个线性层,将隐藏状态映射到输出词汇表的大小,然后通过 softmax 函数进行归一化,以预测下一个词的概率分布。
-
训练过程:
- 解码器通过最大化给定正确输出序列的似然性来训练,通常使用交叉熵损失函数。
-
并行处理:
- 由于自注意力机制的特性,解码器的所有层都可以并行处理,这与循环神经网络(RNN)的序列处理方式形成对比。
-
条件生成:
- 在生成任务中,解码器可以条件于编码器的输出以及之前生成的输出序列,以生成下一个词。
Transformer 解码器的设计允许它捕捉长距离依赖关系,并在生成序列时保持高效的并行计算能力。这些特性使得 Transformer 成为许多序列到序列任务的强大模型。
对比 decoder 和 encoder 的差异 : 只有下图中红色方框的一点差异,在多头主注意力机制的基础上增加 mask 操作,那么这个操作有什么影响呢?
采用masked self-attention 之后a 和b 之间的依赖关系改编成为,b1 的输出只依赖于 a1,而b2的输出依赖与 a1 a2 ,如图所示依次类推,而原来的 self-attention b 则是有赖于所有的 a
更具体的如下图:
2. encoder 和decoder 之间是如何处理和传递讯息的?self-attention
在 Transformer 架构中,编码器(Encoder)和解码器(Decoder)之间的信息传递是通过一种特殊的自注意力机制实现的,称为交叉注意力(Cross-Attention)或编码器-解码器注意力(Encoder-Decoder Attention)。以下是交叉注意力的实现原理及其细节:
-
编码器输出:
- 编码器处理输入序列(如源语言文本)并生成一系列连续的表示,这些表示捕获了输入数据的上下文信息。
-
查询(Query)、键(Key)、值(Value):
- 在交叉注意力中,解码器的当前状态作为查询,而编码器的输出作为键和值。
- 查询用于与编码器的键进行比较,以确定注意力权重。
-
计算注意力得分:
- 通过计算解码器中每个查询与编码器中每个键的兼容性来确定注意力得分。通常使用点积来计算兼容性:
score = Q ⋅ K T d k \text{score} = \frac{Q \cdot K^T}{\sqrt{d_k}} score=dkQ⋅KT - 其中 ( Q ) 是查询矩阵,( K ) 是键矩阵,( d_k ) 是键向量的维度,分母中的平方根是缩放因子。
- 通过计算解码器中每个查询与编码器中每个键的兼容性来确定注意力得分。通常使用点积来计算兼容性:
-
应用 softmax 函数:
- 使用 softmax 函数对每个查询的注意力得分进行归一化,得到编码器中每个值的注意力权重:
weights=softmax(score)
- 使用 softmax 函数对每个查询的注意力得分进行归一化,得到编码器中每个值的注意力权重:
-
加权值向量:
- 使用归一化的注意力权重对编码器的值向量进行加权求和,得到最终的交叉注意力输出:
context = ∑ i weights i ⋅ V i \text{context} = \sum_{i} \text{weights}_i \cdot V_i context=i∑weightsi⋅Vi - 其中 ( V_i ) 是编码器中与键 ( K_i ) 相关联的值。
- 使用归一化的注意力权重对编码器的值向量进行加权求和,得到最终的交叉注意力输出:
-
多头注意力:
- 交叉注意力可以扩展为多头注意力,其中查询、键和值被分割成多个头,每个头独立计算注意力输出,然后将这些输出拼接起来,并通过一个线性层进行整合。
-
残差连接和层归一化:
- 交叉注意力的输出通常会通过一个残差连接,即将注意力输出与其输入相加,以帮助梯度流动。
- 然后,输出会通过层归一化来进一步稳定训练过程。
-
遮蔽(Masking):
- 在解码器的自注意力层中使用遮蔽,以防止解码器在未来的步骤中获取信息。在交叉注意力中,遮蔽确保解码器只能看到编码器的输出,而不能访问未来的解码器状态。
-
并行处理:
- 交叉注意力允许并行处理解码器的所有步骤,因为每个步骤的输出仅依赖于当前步骤的输入和编码器的输出。
-
实现细节:
- 实现交叉注意力时,可以使用现有的自注意力函数,只需将解码器的状态作为查询,将编码器的输出作为键和值。
- 在多头注意力中,查询、键和值会被分割成多个头,每个头独立计算注意力,然后使用线性层将结果合并。
交叉注意力是 Transformer 解码器的核心部分,它允许解码器在生成每个输出步骤时,有效地利用编码器捕获的输入序列的上下文信息。这种机制使得 Transformer 能够有效地处理序列到序列的任务,如机器翻译、文本摘要等。
decoder 与 encoder 的连接部分 cross attention 两个输入来自与 encoder 一个输入来自于 decoder ,具体的形式如下 2图所示
3. 查询(Query)、键(Key)、值(Value)是三个核心概念及其具体含义和计算方式
在 Transformer 架构中使用的自注意力机制以及交叉注意力机制中,查询(Query)、键(Key)、值(Value)是三个核心概念,它们是从输入数据中派生出来的,用于计算注意力权重和聚合信息。以下是它们的具体含义和计算方式:
-
查询(Query):
- 查询是用于表示解码器中当前步骤的状态,或编码器中当前步骤的状态(在自注意力中)。它们是输入数据通过可学习的线性变换得到的向量。
-
键(Key):
- 键是编码器中输入数据的另一种表示,用于与查询进行比较以确定注意力得分。键同样通过可学习的线性变换从输入数据计算得到。
-
值(Value):
- 值是编码器中与每个键相关联的实际数据,它们包含了编码器处理的输入信息。值也是通过可学习的线性变换从输入数据计算得到的。
计算过程如下:
-
给定输入序列 ( X ),首先将其分别通过三个不同的可学习线性变换 ( W^Q ),( W^K ),和 ( W^V ) 来得到查询 ( Q ),键 ( K ),和值 ( V ):
Q = X W Q , K = X W K , V = X W V Q = XW^Q, \quad K = XW^K, \quad V = XW^V Q=XWQ,K=XWK,V=XWV
其中,( W^Q ),( W^K ),和 ( W^V ) 是模型参数。 -
然后计算查询和键之间的点积来得到初步的注意力得分:
score = Q ⋅ K T \text{score} = Q \cdot K^T score=Q⋅KT -
为了使得注意力得分不会因为维度的大小而受到影响,通常会对得分进行缩放,即除以键向量维度 ( d_k ) 的平方根:
score = Q ⋅ K T d k \text{score} = \frac{Q \cdot K^T}{\sqrt{d_k}} score=dkQ⋅KT -
使用 softmax 函数对缩放后的注意力得分进行归一化处理,得到注意力权重:
weights = softmax ( score ) \text{weights} = \text{softmax}(\text{score}) weights=softmax(score) -
最后,注意力权重用于加权和聚合值 ( V ),得到加权的输出,这通常在自注意力或交叉注意力中完成:
output = ∑ i weights i ⋅ V i \text{output} = \sum_{i} \text{weights}_i \cdot V_i output=i∑weightsi⋅Vi
含义上,查询、键、值机制允许模型在处理序列数据时动态地聚焦于当前步骤最相关的信息。在解码器中,查询来自之前步骤的输出,而键和值来自编码器的输出,这样解码器就可以在生成每个词时考虑编码器中的所有信息,但更加关注与当前词最相关的部分。这种机制使得 Transformer 能够有效地处理长距离依赖问题,并提高了模型的灵活性和表现力。