tensorflow 如何理解Transformer中的屏蔽多头注意

zxlwwiss  于 2023-08-06  发布在  其他
关注(0)|答案(3)|浏览(113)

我目前正在学习Transformer的代码,但我不能理解解码器的掩码多头。论文说是为了防止你看到生成词,但我不明白,如果生成词之后的词还没有生成,怎么能看到呢?
我试着读Transformer的代码(链接:https://github.com/Kyubyong/transformer)。代码实现掩码如下所示。它用下三角矩阵来遮罩,我不明白为什么。

padding_num = -2 ** 32 + 1
diag_vals = tf.ones_like(inputs[0, :, :])  # (T_q, T_k)
tril = tf.linalg.LinearOperatorLowerTriangular(diag_vals).to_dense()  # (T_q, T_k)
masks = tf.tile(tf.expand_dims(tril, 0), [tf.shape(inputs)[0], 1, 1])  # (N, T_q, T_k)
paddings = tf.ones_like(masks) * padding_num
outputs = tf.where(tf.equal(masks, 0), paddings, inputs)

字符串

wwodge7n

wwodge7n1#

解码器是一个自回归器,不能看到未来的话

  1. Transformer中的编码器是一个自回归器;
    1.这意味着它将根据前一个令牌预测下一个令牌;
    1.所以输入x不能看到未来的单词;
    1.我们使用掩蔽的多头注意力来做到这一点。
avwztpqn

avwztpqn2#

假设我们正在训练的课文是“一二三四五”
这是自我监督训练,我们只是要训练模型来预测序列中的下一个单词。而不是编码器-解码器模型,我们将使用GPT风格的Transformer(有时称为“仅解码器”,因为它是“因果关系”,有时称为“仅编码器”,因为没有交叉注意)。
如果我们正在进行生成式预训练,我们将使用以下内容来训练这个模型:input_tokens = [one, two, three, four]output_tokens [ two, three, four, five ]我们移动令牌,使得模型总是预测下一个令牌。
现在,对于输出“二”,我们只想考虑输入“一”。当学习生成输出“三”时,我们只想考虑输入“一”和“二”。
现在,在预训练之后,我们将输入模型“玛丽had a little”,我们期望得到输出“had a little lamb”。输出被移动一个标记。
在输出中对整个句子进行训练可能看起来很浪费。你可能会问自己,为什么不训练模型来预测下一个令牌呢?为什么预测输入中的单词,需要这个因果掩码?参数是共享的当模型通过关注“一”来学习“二”时,它正在改变模型参数,这些参数有助于在关注“四”时生成“五”。更长的序列长度最终相当于更大的批量大小,因此这种看似冗余的训练方式实际上非常有效。

3mpgtkmj

3mpgtkmj3#

我阅读了Transformer paper之后也有同样的问题。我在互联网上没有找到完整和详细的答案,所以我将尝试解释我对掩蔽多头注意力的理解。
简短的回答是-我们需要掩蔽来使训练并行。并行化是好的,因为它允许模型更快地训练。
这里有一个例子来解释这个想法。比如说,我们训练把“我爱你”翻译成德语。编码器以并行模式工作-它可以在恒定数量的步骤(即,“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, 1321
  • 预测22
  • 并行操作#C。输入:11, 12, 1321, 22
  • 尝试预测23

该算法可以并行执行,而且不会积累误差。并且该算法使用注意力(即,查看所有先前的输入)因此具有关于在进行预测时要考虑的上下文的更多信息。
这就是我们需要面具的地方。训练算法知道整个预期输出(21, 22, 23)。它为每个并行操作隐藏(掩蔽)该已知输出序列的一部分。

  • 当它执行#A -时,它隐藏(屏蔽)整个输出。
  • 当它执行#B -时,它隐藏第二和第三输出。
  • 当它执行#C -时,它隐藏了第三个输出。

掩码本身的实现如下(来自original paper):
我们通过屏蔽(设置为−∞)softmax输入中与非法连接相对应的所有值,在缩放的点积注意力内实现这一点
注意:在推理(非训练)期间,解码器以顺序(非并行)模式工作,因为它最初不知道输出序列。但它与RNN方法不同,因为Transformer推理仍然使用自注意力并查看所有以前的输出(但不仅仅是前一个)。
注2:我在一些材料中看到,掩蔽可以在非翻译应用中以不同的方式使用。例如,对于语言建模,掩蔽可以用于从输入句子中隐藏一些单词,并且模型将尝试在训练期间使用其他未掩蔽的单词(即,未掩蔽的单词)来预测它们。学习理解上下文)。

相关问题