TransFormer--解码器:带掩码的多头注意力层
TransFormer--解码器:带掩码的多头注意力层
以英法翻译任务为例,假设训练数据集样本如下表所示。
原句 | 目标翻译 |
---|---|
I am good | Je vais bien |
Good morning | Bonjour |
Thank you very much | Merci beaucoup |
上表所示的数据集由两部分组成:原句和目标句。在前面,我们学习了解码器在测试期间是如何在每个步骤中逐字预测目标句的。
在训练期间,由于有正确的目标句,解码器可以直接将整个目标句稍作修改作为输入。解码器将输入的作为第一个标记,并在每一步将下一个预测词与输入结合起来,以预测目标句,直到遇到标记为止。因此,我们只需将标记添加到目标句的开头,再将整体作为输入发送给解码器。
比如要把英语句子I am good转换成法语句子Je vais bien。我们只需在目标句的开头加上标记,并将Je vais bien作为输入发送给解码器。解码器将预测输出为Je vais bien,如下图所示。
为什么我们需要输入整个目标句,让解码器预测位移后的目标句呢?
首先,我们不是将输入直接送入解码器,而是将其转换为嵌入矩阵(输出嵌入矩阵)并添加位置编码,然后再送入解码器。假设添加输出嵌入矩阵和位置编码后得到下图所示的矩阵X。
然后,将矩阵X送入解码器。解码器中的第一层是带掩码的多头注意力层。这与编码器中的多头注意力层的工作原理相似,但有一点不同。
为了运行自注意力机制,我们需要创建三个新矩阵,即查询矩阵Q、键矩阵K和值矩阵V。由于使用多头注意力层,因此我们创建了h个查询矩阵、键矩阵和值矩阵。对于注意力头i的查询矩阵 Q i Q_i Qi、键矩阵 K i K_i Ki和值矩阵 V i V_i Vi,可以通过将X分别乘以权重矩阵 W i Q 、 W i K 、 W i V W_i^Q、W_i^K、W_i^V WiQ、WiK、WiV而得。
下面,让我们看看带掩码的多头注意力层是如何工作的。假设传给解码器的输入句是Je vais bien。我们知道,自注意力机制将一个单词与句子中的所有单词联系起来,从而提取每个词的更多信息。但这里有一个小问题。在测试期间,解码器只将上一步生成的词作为输
入。
比如,在测试期间,当t=2时,解码器的输入中只有[, Je],并没有任何其他词。因此,我们也需要以同样的方式来训练模型。模型的注意力机制应该只与该词之前的单词有关,而不是其后的单词。要做到这一点,我们可以掩盖后边所有还没有被模型预测的词。
比如,我们想预测与相邻的单词。在这种情况下,模型应该只看到,所以我们应该掩盖后边的所有词。再比如,我们想预测Je后边的词。在这种情况下,模型应该只看到Je之前的词,所以我们应该掩盖Je后边的所有词。其他行同理,如下图所示。
像这样的掩码有助于自注意力机制只注意模型在测试期间可以使用的词。但我们究竟如何才能实现掩码呢?我们学习过对于一个注意力头i的注意力矩阵 Z i Z_i Zi的计算方法,公式如下。
Z i = S o f t M a x ( Q i ∗ K i T d k ) ∗ v i Z_i = SoftMax(\frac{Q_i * K_i^T}{\sqrt{d_k}}) * v_i Zi=SoftMax(dkQi∗KiT)∗vi
计算注意力矩阵
第1步是计算查询矩阵与键矩阵的点积。下图显示了点积结果。需要注意的是,这里使用的数值是随机的,只是为了方便理解。
第2步是将矩阵除以键向量维度的平方根。假设下图是结果。
第3步,我们对上图所得的矩阵应用softmax函数,并将分值归一化。但在应用softmax函数之前,我们需要对数值进行掩码转换。以矩阵的第1行为例,为了预测后边的词,模型不应该知道右边的所有词(因为在测试时不会有这些词)。因此,我们可以用掩盖右边的所有词,如下图所示。
接下来,让我们看矩阵的第2行。为了预测Je后边的词,模型不应该知道Je右边的所有词(因为在测试时不会有这些词)。因此,我们可以用 − ∞ -\infty −∞掩盖Je右边的所有词,如下图所示。
同理,我们可以用 − ∞ -\infty −∞掩盖vais右边的所有词,如下图所示。
现在,我们可以将softmax函数应用于前面的矩阵,并将结果与值矩阵 V i V_i Vi相乘,得到最终的注意力矩阵 Z i Z_i Zi。同样,我们可以计算h个注意力矩阵,将它们串联起来,并将结果乘以新的权重矩阵 W 0 W_0 W0,即可得到最终的注意力矩阵M,如下所示。
M = C o n c a t e n a t e ( Z 1 , Z 2 , . . . , Z i , . . . , Z h ) W 0 M = Concatenate(Z_1,Z_2,...,Z_i,...,Z_h)W_0 M=Concatenate(Z1,Z2,...,Zi,...,Zh)W0
最后,我们把注意力矩阵M送到解码器的下一个子层,也就是另一个多头注意力层。