阅读完
Transformer论文后,我也有同样的问题。在互联网上找不到完整详细的答案,所以我会尝试解释一下我对遮蔽多头注意力的理解。
简短回答是——我们需要屏蔽来使训练并行化。并行化是好的,因为它可以加快模型的训练速度。
这里有一个说明这个想法的例子。假设我们正在训练将“I love you”翻译成德语。编码器以并行模式工作-它可以在固定步骤数内生成输入序列(“I love you”的向量表示)。(即步骤的数量不取决于输入序列的长度)。
假设编码器生成的数字为
11、12、13
作为输入序列的向量表示。实际上,这些向量会更长,但为了简单起见,我们使用短的向量。同时出于简单起见,我们忽略了服务令牌,比如 - 序列开始、序列结束等。
在训练过程中,我们知道翻译应该是“Ich liebe dich”(我们在训练期间总是知道预期输出)。假设“Ich liebe dich”单词的期望向量表示为
21、22、23
。如果我们以顺序模式进行解码器训练,它会类似于循环神经网络的训练。将执行以下顺序步骤:
- 顺序操作#1。输入:
11、12、13
。
- 尝试预测
21
。
- 预测输出不会完全是
21
,假设它将是
21.1
。
- 顺序操作#2。输入:
11、12、13
,以及前一个输出为
21.1
。
- 尝试预测
22
。
- 预测输出不会完全是
22
,假设它将是
22.3
。
- 顺序操作#3。输入:
11、12、13
,以及前一个输出为
22.3
。
- 尝试预测
23
。
- 预测输出不会完全是
23
,假设它将是
23.5
。
这意味着我们需要进行3个顺序操作(在一般情况下-每个输入一个顺序操作)。此外,每次迭代都会累积误差。另外,由于我们只查看单个先前的输出,因此我们不使用注意力。
由于我们实际上知道预期的输出,所以可以调整该过程并使其并行。无需等待上一步的输出。
- 并行操作#A。输入:
11、12、13
。
- 尝试预测
21
。
并行操作#B。输入:11,12,13
和21
。
并行操作#C。输入:11,12,13
和21,22
。
这个算法可以并行执行,也不会累积误差。该算法使用attention(即查看所有先前的输入),因此在进行预测时需要考虑更多上下文信息。
这就是我们需要掩码的地方。训练算法知道整个期望输出(21,22,23
)。对于每个并行操作,它隐藏(掩码)已知输出序列的一部分。
- 当执行#A时-隐藏(掩码)整个输出。
- 当执行#B时-隐藏第二个和第三个输出。
- 当执行#C时-隐藏第三个输出。
掩码本身的实现如下所示(来自原始论文):
我们通过在softmax的输入中屏蔽(设置为-∞)与非法连接相对应的所有值来在缩放的点积attention内部实现这一点。
注意:在推理阶段(而非训练阶段),解码器以顺序模式运行(而非并行),因为它最初不知道输出序列。但这与RNN方法不同,因为Transformer推理仍然使用自注意力并查看所有先前的输出(而不仅仅是前一个)。
注意2:我在一些材料中看到遮罩可以用于非翻译应用。例如,对于语言建模,遮罩可以用于隐藏输入句子中的某些单词,模型将尝试使用其他未被遮罩的单词(即学习理解上下文)在训练过程中预测它们。