剖析 BERT 附录:解码器
转载自:https://medium.com/dissecting-bert/dissecting-bert-appendix-the-decoder-3b86f66b0e5f
符号
在开始之前,让我们定义将在整篇文章中使用的符号:
emb_dim:嵌入的尺寸
input_length:输入序列的长度
target_length:目标序列的长度 + 1。+1 是移位的结果。
vocab_size:词汇量中的单词数量(偏离语料库)。
目标输入:我们将互换使用这个术语来描述解码器中的输入字符串(句子集)或序列。
介绍
Transformer是一种基于注意力的自然语言处理 (NLP) 架构,一年前在《 Attention Is All You Need》一文中介绍了这一架构。
在这篇博文中,我们将深入研究解码器;BERT 中未使用的Transformer 架构部分。我们将参考Encoder来解释完整的Transformer架构。
注意:如果您只想了解 BERT 的工作原理,则本博文中描述的Transformer部分不相关。
这篇文章的结构安排如下:
- Transformer旨在解决的问题。
- 信息流。
- 解码器。
问题
Transformer解决的问题是翻译。要将句子翻译成另一种语言,我们希望我们的模型能够:
- 能够捕捉输入句子中单词之间的关系。
- 将输入句子中包含的信息与每一步已翻译的信息结合起来。
想象一下,目标是将一个句子从英语翻译成西班牙语,我们得到以下标记序列:
X = [‘Hello’, ‘,’, ‘how’, ‘are’, ‘you’, ‘?’] (输入序列) Y = [
‘Hola’, ‘,’, ‘como’, ‘estas’, ‘?’](目标序列)
首先,我们希望通过组合序列中每个单词的信息来处理输入序列*X中的信息。*这是在编码器内部完成的。
一旦我们在编码器的输出中获得了这些信息,我们就希望将其与目标序列结合起来。这是在解码器中完成的。
编码器和解码器是Transformer架构的特定部分,如图 1 所示。我们将在第 3-b 级:层中详细研究解码器。
信息流
该架构的数据流如下:
- 该模型将每个标记表示为维度emb_dim的向量。然后,我们得到特定输入序列的维度*(input_length) x (emb_dimb)矩阵。*
- 然后它添加位置信息(位置编码)。*此步骤将返回维度(input_length) x (emb_dim)*的矩阵,就像上一步一样。
- 数据经过 N 个编码器块。之后,我们获得维度为*(input_length) x (emb_dim)*的矩阵。
- 目标序列被屏蔽并通过相当于 1) 和 2) 的解码器发送。输出的尺寸为*(target_length) x (emb_dim)*。
- 4)的结果经过N个解码器块。在每次迭代中,解码器都使用编码器的输出 3)。这在图 2 中用从编码器到解码器的箭头表示。输出的尺寸为*(target_length) x (emb_dim)*。
- 最后,它应用了全连接层和行式 softmax。输出的维度为*(target_length) x (vocab_size)。*
解码器块的输入和输出的维度是相同的。因此,使用一个解码器块的输出作为下一个解码器块的输入是有意义的。
注意:在 Attention Is All You Need 实验中,N 选择为 6。
注意:块不共享权重
输入
请记住,所描述的算法正在处理输入句子和目标句子以训练网络。输入句子将按照编码器架构中的描述进行编码。在本节中,我们讨论给定一个目标句子(例如“Hola,como estás?”),我们如何获得代表解码器块的目标句子的矩阵。
过程完全相同。它也由两个一般步骤组成:
- 代币嵌入
- 位置的编码。
主要区别在于目标句子发生了转移。也就是说,在填充之前,目标序列将如下:
[“Hola”, “, “, “como”, “estás”, “?”]→[“”, “Hola”, “, “, “como”, “estás”, “?”]
向量化目标序列的其余过程将与编码器架构中输入句子所描述的过程完全相同。
解码器
在本节中,我们将介绍解码器中与编码器中介绍的部分不同的部分。
解码器块——训练与测试
在测试期间,我们没有基本事实。在这种情况下,步骤如下:
- 计算输入序列的嵌入表示。
- 使用起始序列标记,例如“”作为第一个目标序列:[]。该模型给出下一个标记作为输出。
- 将最后一个预测的标记添加到目标序列中,并使用它生成新的预测 [‘’, Prediction_1,…,Prediction_n]
- 执行步骤 3,直到预测的标记是代表序列结束的标记,例如 。
在训练期间,我们有基本事实,即我们希望模型为上述过程的每次迭代输出的标记。由于我们提前有了目标,我们将立即为模型提供整个移位目标序列,并要求它预测未移位的目标。
继续我们之前的示例,我们将输入:
[‘’,‘Hola’, ‘,’, ‘como’, ‘estas’, ‘?’]
预期的预测是:
[‘Hola’, ‘,’, ‘como’, ‘estas’, ‘?’, ‘’]
然而,这里有一个问题。如果模型看到预期的标记并用它来预测自己怎么办?例如,它可能会在*'como’右侧看到’estas* '并用它来预测*‘estas’*。这不是我们想要的,因为模型在测试时无法做到这一点。
我们需要修改一些注意力层,以防止模型看到右侧(或向量表示矩阵中的向下)信息,但允许它使用已经预测的单词。
让我们用一个例子来说明这一点。鉴于:
[‘’,‘Hola’, ‘,’, ‘como’, ‘estas’, ‘?’]
我们将其转换为如上所述的矩阵并添加位置编码。这将产生一个矩阵:
就像编码器中一样,解码器块的输出也将是大小为*(target_length) x (emb_dim)*的矩阵。在逐行线性(右侧矩阵乘积形式的线性层)和每行 Softmax 之后,这将产生一个矩阵,其中每行的最大元素指示下一个单词。
这意味着分配给“”的行负责预测“Hola”,分配给“Hola”的行负责预测“,”,依此类推。因此,为了预测“estas”,我们将允许该行直接与绿色区域交互,但不与图 13 中的红色区域交互。
观察到我们在线性层中没有问题,因为它们被定义为按标记/按行以矩阵右乘的形式。
问题出在多头注意力上,并且输入需要被屏蔽。我们将在下一节中详细讨论屏蔽。
在训练时,所有行的预测都很重要。鉴于在预测时我们正在进行迭代过程,我们只关心目标/输出序列中最后一个标记的下一个单词的预测。
蒙面多头注意力
这将与多头注意力机制完全相同,但会为我们的输入添加屏蔽。
唯一需要屏蔽的**多头注意力块是每个解码器块的第一个。**这是因为中间的一层用于组合编码输入和从前一层继承的输出之间的信息。将每个目标标记的表示与任何输入标记的表示组合起来没有问题(因为我们将在测试时拥有所有这些表示)。
修改将在计算后进行: Q i K i T d k \frac{Q_iK_i^T}{\sqrt{d_k}} dkQiKiT
现在,屏蔽步骤只是将矩阵严格上三角部分中的所有条目设置为负无穷大。在我们的例子中:
就是这样!其余过程与编码器的多头注意力中描述的相同。
现在让我们深入研究一下将这些元素设置为负无穷在数学上意味着什么。观察到,如果这些条目是每行的相对注意力度量,它们越大,我们需要对该标记给予更多关注。因此,将这些元素设置为负无穷大主要是说:“对于分配给预测“estás”的行(输入为*“como”的行),忽略“estás”*和“ ?”。我们的 Softmax 输出如下所示:
我们试图忽略的那些代币的相对关注度确实已经归零。
当将该矩阵与V_i相乘时,用于预测下一个单词的唯一元素是其右侧的元素,即模型在测试期间可以访问的元素。
观察到,这次修改后的多头注意力层的输出将是一个维度为*(target_length) x (emb_dim)的矩阵,因为计算它的序列的序列长度为target_length。*
多头注意力——编码器输出和目标
请注意,在这种情况下,我们对该层使用不同的输入。更具体地说,该层将使用编码器的最终输出E(所有编码器块的最终结果)和解码器的前一层输出,而不是像我们在之前的多头注意力层中所做的那样从X导出**Q_i、K_i和V_i D(经过Dropout、Add 和 Norm层后的屏蔽多头注意力)。
让我们首先澄清这些输入的形状及其代表的含义:
- E是编码后的输入序列,是一个维度*(input_length) x (emb_dim)*的矩阵,它通过 6 个编码器块对输入标记之间的关系进行了编码。
- D是经过加法和范数后蒙版多头注意力的输出,是一个维度矩阵*(target_length) x (emb_dim)*。
现在让我们深入研究如何处理这些矩阵。我们将使用与之前相同维度的加权矩阵:
W i K with dimensons d m o d e l x d k W i Q with dimensons d m o d e l x d k W i V with dimensons d m o d e l x d v \begin{aligned}W_i^K&\text{with dimensons }d_{model}\text{x}d_k\\W_i^Q&\text{with dimensons }d_{model}\text{x}d_k\\W_i^V&\text{with dimensons }d_{model}\text{x}d_v\end{aligned} WiKWiQWiVwith dimensons dmodelxdkwith dimensons dmodelxdkwith dimensons dmodelxdv
但这次生成Q_i的投影将使用**D (目标信息)完成,而生成K和V的投影将使用E(输入信息)创建。
D W i Q = Q i w i t h d i m e n s o n s t a r g e t _ l e n g t h x d k E W i K = K i with dimensons i n p u t _ l e n g t h x d k E W i V = V i with dimensons i n p u t _ l e n g t h x d v \begin{gathered} DW_{i}^{Q} =Q_i\mathrm{~with~dimensons~}target\_length\text{ x }d_k \\ EW_{i}^{K} =K_i\text{ with dimensons }input\_length\text{ x }d_k \\ EW_{i}^{V} =V_i\text{ with dimensons }input\_length\text{ x }d_v \end{gathered} DWiQ=Qi with dimensons target_length x dkEWiK=Ki with dimensons input_length x dkEWiV=Vi with dimensons input_length x dv
对于每个头 i=1,…, h。
头连接后使用的矩阵*W_0将具有维度**(d_v*h) x (emb_dim),*就像编码器块中使用的矩阵一样。
除此之外,多头注意力模块与编码器中的模块完全相同。
请注意,在这种情况下,矩阵由以下公式得出:
S o f t m a x ( Q i K i T d k ) Softmax\left(\frac{Q_iK_i^T}{\sqrt{d_k}}\right) Softmax(dkQiKiT)
描述“编码输入标记”和“编码目标标记”之间的相关关系。此外请注意,该矩阵的尺寸为*(target_length)x(input_length)*。
继续我们的例子:
正如我们所看到的,目标中的每个投影行标记都涉及(编码的)输入序列中的所有位置。该矩阵编码输入序列和目标序列之间的关系。
重复我们在编码器的多头注意力中使用的符号,与V_i相乘的结果是:
正如我们所看到的,目标序列中的每个标记在每个头中都表示为编码输入标记的组合。此外,这将发生在多个头上,就像以前一样,这将允许目标序列的每个标记由与输入序列中的标记的多种关系来表示。
就像在编码器块中一样,一旦执行了串联,我们就将其与W_0相乘:
C o n c a t ( V 1 , V 2 , . . . . . . , V h ) W 0 Concat(V_1,V_2,......,V_h)W_0 Concat(V1,V2,......,Vh)W0
线性和 Softmax
这是获得目标序列中每个位置的预测标记之前的最后一步。如果您熟悉语言模型,这与它们的最后一层相同。最后一个解码器块的最后一个 Add & Norm 层的输出是维度为*(target_length)x(emb_dim)的矩阵 X。*
线性层的思想是对 X 的 x 中的每一行进行计算:
x W 1 xW_{1} xW1
其中W_1是维度**(emb_dim) x (vocab_size)的学习权重矩阵。因此,对于特定行,结果将是长度为vocab_size 的向量。
最后,一个软最大应用于该向量,产生描述下一个标记的概率的向量。因此,取最大概率对应的位置会根据模型返回最有可能的下一个单词。
以矩阵形式表示,如下所示: x W 1 xW_{1} xW1
X。*
线性层的思想是对 X 的 x 中的每一行进行计算:
x W 1 xW_{1} xW1
其中W_1是维度**(emb_dim) x (vocab_size)的学习权重矩阵。因此,对于特定行,结果将是长度为vocab_size 的向量。
最后,一个软最大应用于该向量,产生描述下一个标记的概率的向量。因此,取最大概率对应的位置会根据模型返回最有可能的下一个单词。
以矩阵形式表示,如下所示: x W 1 xW_{1} xW1
并在每个结果行中应用 Softmax。