理解Transformer解码器
Transformer Decoder 究极解释
-
- 1.3 理解解码器
-
- 1.3.1 带掩码的多头注意力层
- 1.3.2 多头注意力层
- 1.3.3 前馈网络层
- 1.3.4 叠加和归一组件
- 1.3.5 线性层和softmax层
- 1.3.6 解码器总览
- 1.4 整合编码器和解码器
1.3 理解解码器
假设我们想把英语句子I am good(原句)翻译成法语句子Je vais bien(目标句)。首先,将原句I am good送入编码器,使编码器学习原句,并计算特征值。在前文中,我们学习了编码器是如何计算原句的特征值的。然后,我们把从编码器求得的特征值送入解码器。解码器将特征值作为输入,并生成目标句Je vais bien,如图1-35所示。
图1-35 Transformer的编码器和解码器
在编码器部分,我们了解到可以 N N N叠加个编码器。同理,解码器也可以有 N N N个叠加在一起。为简化说明,我们设定 N = 2 N=2 N=2。如图1-36所示,一个解码器的输出会被作为输入传入下一个解码器。我们还可以看到,编码器将原句的特征值(编码器的输出)作为输入传给所有解码器,而非只给第一个解码器。因此,一个解码器(第一个除外)将有两个输入:一个是来自前一个解码器的输出,另一个是编码器输出的特征值。
图1-36 编码器和解码器
接下来,我们学习解码器究竟是如何生成目标句的。当时 t=1(t 表示时间步),解码器的输入是<sos>,这表示句子的开始。解码器收到<sos>作为输入,生成目标句中的第一个词,即Je,如图1-37所示。
图1-37 解码器在时的预测结果
当时,解码器使用当前的输入和在上一步(t-1)生成的单词,预测句子中的下一个单词。在本例中,解码器将<sos>和Je(来自上一步)作为输入,并试图生成目标句中的下一个单词,如图1-38所示。
图1-38 解码器在时的预测结果
同理,你可以推断出解码器在 t=3 时的预测结果。此时,解码器将<sos>、Je和vais(来自上一步)作为输入,并试图生成句子中的下一个单词,如图1-39所示。
图1-39 解码器在时的预测结果
在每一步中,解码器都将上一步新生成的单词与输入的词结合起来,并预测下一个单词。因此,在最后一步(t=4),解码器将<sos>、Je、vais和bien作为输入,并试图生成句子中的下一个单词,如图1-40所示。
图1-40 解码器在时的预测结果
从图1-40中可以看到,一旦生成表示句子结束的<eos>
标记,就意味着解码器已经完成了对目标句的生成工作。
在编码器部分,我们将输入转换为嵌入矩阵,并将位置编码添加到其中,然后将其作为输入送入编码器。同理,我们也不是将输入直接送入解码器,而是将其转换为嵌入矩阵,为其添加位置编码,然后再送入解码器。
如图1-41所示,假设在时间步t=2,我们将输入转换为嵌入(我们称之为嵌入值输出,因为这里计算的是解码器在以前的步骤中生成的词的嵌入),将位置编码加入其中,然后将其送入解码器。
图1-41 带有位置编码的编码器和解码器
接下来,让我们深入了解解码器的工作原理。一个解码器模块及其所有的组件如图1-42所示。
图1-42 解码器模块
从图1-42中可以看到,解码器内部有3个子层。
-
带掩码的多头注意力层
-
多头注意力层
-
前馈网络层
与编码器模块相似,解码器模块也有多头注意力层和前馈网络层,但多了带掩码的多头注意力层。现在,我们对解码器有了基本的认识。接下来,让我们先详细了解解码器的每个组成部分,然后从整体上了解它的工作原理。
1.3.1 带掩码的多头注意力层
以英法翻译任务为例,假设训练数据集样本如图1-43所示。
图1-43 训练数据集样本
图1-43所示的数据集由两部分组成:原句和目标句。在前面,我们学习了解码器在测试期间是如何在每个步骤中逐字预测目标句的。
在训练期间,由于有正确的目标句,解码器可以直接将整个目标句稍作修改作为输入。解码器将输入的<sos>作为第一个标记,并在每一步将下一个预测词与输入结合起来,以预测目标句,直到遇到<eos>标记为止。因此,我们只需将<sos>标记添加到目标句的开头,再将整体作为输入发送给解码器。
比如要把英语句子I am good转换成法语句子Je vais bien。我们只需在目标句的开头加上<sos>标记,并将<sos>Je vais bien作为输入发送给解码器。解码器将预测输出为Je vais bien<eos>,如图1-44所示。
图1-44 Transformer的编码器和解码器
为什么我们需要输入整个目标句,让解码器预测位移后的目标句呢?下面来解答。
首先,我们不是将输入直接送入解码器,而是将其转换为嵌入矩阵(输出嵌入矩阵)并添加位置编码,然后再送入解码器。假设添加输出嵌入矩阵和位置编码后得到图1-45所示的矩阵。
图1-45 嵌入矩阵
然后,将矩阵送入解码器。解码器中的第一层是带掩码的多头注意力层。这与编码器中的多头注意力层的工作原理相似,但有一点不同。
为了运行自注意力机制,我们需要创建三个新矩阵,即查询矩阵Q、键矩阵K 和值矩阵V。由于使用多头注意力层,因此我们创建了 h 个查询矩阵、键矩阵和值矩阵。对于注意力头 i i 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而得。
下面,让我们看看带掩码的多头注意力层是如何工作的。假设传给解码器的输入句是<sos>
Je vais bien。我们知道,自注意力机制将一个单词与句子中的所有单词联系起来,从而提取每个词的更多信息。但这里有一个小问题。在测试期间,解码器只将上一步生成的词作为输入。
比如,在测试期间,当 t=2 时,解码器的输入中只有[<sos>
, Je],并没有任何其他词。因此,我们也需要以同样的方式来训练模型。模型的注意力机制应该只与该词之前的单词有关,而不是其后的单词。要做到这一点,我们可以掩盖后边所有还没有被模型预测的词。
比如,我们想预测与<sos>
相邻的单词。在这种情况下,模型应该只看到<sos>
,所以我们应该掩盖<sos>
后边的所有词。再比如,我们想预测Je后边的词。在这种情况下,模型应该只看到Je之前的词,所以我们应该掩盖Je后边的所有词。其他行同理,如图1-46所示。
图1-46 掩码
像这样的掩码有助于自注意力机制只注意模型在测试期间可以使用的词。但我们究竟如何才能实现掩码呢?我们学习过对于一个注意力头 i 的注意力矩阵 Z_i
的计算方法,公式如下。
Z i = s o f t m a x ( Q i ⋅ K i T d k ) ⋅ V i Z_i = softmax(\frac{Q_i \cdot K_{i}^{T}} {\sqrt{d_k} } ) \cdot {V_i} Zi=softmax(dkQi⋅KiT)⋅Vi
计算注意力矩阵的第1步是计算查询矩阵与键矩阵的点积。图1-47显示了点积结果。需要注意的是,这里使用的数值是随机的,只是为了方便理解。
图1-47 查询矩阵与键矩阵的点积
第2步是将 Q i ⋅ K i T {Q_i \cdot K_{i}^{T}} Qi⋅KiT矩阵除以键向量维度的平方根 d k \sqrt{d_k} dk