我在理解transformers时遇到了困难。每件事都在一点一点地变得清晰,但有一件事让我头疼,那就是src_mask和src_key_padding_mask之间的区别是什么,它在编码层和解码器层都是作为向前函数的参数传递的。
https://pytorch.org/docs/master/_modules/torch/nn/modules/transformer.html#Transformer
发布于 2021-07-15 23:36:58
src_mask与src_key_padding_mask的区别
一般情况下,要注意张量_mask和_key_padding_mask的用法的区别。在变换器内部当注意完成时,我们通常得到一个平方的中间张量,其中包括大小[Tx, Tx] (对于编码器的输入),[Ty, Ty] (对于移位的输出-解码器的一个输入)和[Ty, Tx] (对于记忆掩码-编码器/记忆的输出和解码器/移位的输出之间的注意力)。
因此,我们得到了转换器中每个掩码的用法(请注意,pytorch文档中的符号如下所示,其中Tx=S is the source sequence length (例如最大输入批次),Ty=T is the target sequence length (例如最大目标长度),B=N is the batch size,D=E is the feature number):
[Tx, Tx] = [S, S] -源序列的附加掩码(可选)。这是在执行atten_src + src_mask时应用的。我不确定是否有示例输入-请参阅tgt_mask获取示例,但典型的用法是添加-inf,以便在需要时可以以这种方式屏蔽src_attention。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。[Ty, Ty] = [T, T] - tgt序列的附加掩码(可选)。这是在执行atten_tgt + tgt_mask时应用的。一个例子是使用对角线来避免解码器作弊。因此,tgt被右移,第一个令牌是嵌入SOS/BOS的序列令牌的开始,因此第一个条目是零,而其余的条目。请参阅附录中的具体示例。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。[Ty, Tx] = [T, S]-编码器输出的附加掩码(可选)。这是在执行atten_memory + memory_mask时应用的。不确定是否使用示例,但与前面一样,添加-inf会将一些注意力权重设置为零。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。[B, Tx] = [N, S] -每批src密钥的ByteTensor掩码(可选)。由于您的src通常具有不同长度的序列,因此通常会删除附加在末尾的填充向量。为此,您可以指定批处理中每个示例的每个序列的长度。具体示例见附录。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。[B, Ty] = [N, t] -每批tgt密钥的ByteTensor掩码(可选)。与上一次相同。具体示例见附录。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。[B, Tx] = [N, S] -每批内存密钥的ByteTensor掩码(可选)。与上一次相同。具体示例见附录。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。附录
pytorch教程(https://pytorch.org/tutorials/beginner/translation_transformer.html)中的示例:
1个src_mask示例
src_mask = torch.zeros((src_seq_len, src_seq_len), device=DEVICE).type(torch.bool)返回大小为[Tx, Tx]的布尔值的张量
tensor([[False, False, False, ..., False, False, False],
...,
[False, False, False, ..., False, False, False]])2 tgt_mask示例
mask = (torch.triu(torch.ones((sz, sz), device=DEVICE)) == 1)
mask = mask.transpose(0, 1).float()
mask = mask.masked_fill(mask == 0, float('-inf'))
mask = mask.masked_fill(mask == 1, float(0.0))生成右移输出的对角线,该对角线是解码器的输入.
tensor([[0., -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf,
-inf, -inf, -inf],
[0., 0., -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf,
-inf, -inf, -inf],
[0., 0., 0., -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf,
-inf, -inf, -inf],
...,
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., -inf],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0.]])通常,右移的输出在开头有BOS/SOS,本教程只需在前面添加BOS/SOS,然后用tgt_input = tgt[:-1, :]修剪最后一个元素就可以得到右移。
3个_padding
填充只是为了掩蔽末尾的填充。src填充通常与存储器填充相同。tgt有它自己的序列,因此它有自己的填充。示例:
src_padding_mask = (src == PAD_IDX).transpose(0, 1)
tgt_padding_mask = (tgt == PAD_IDX).transpose(0, 1)
memory_padding_mask = src_padding_mask输出:
tensor([[False, False, False, ..., True, True, True],
...,
[False, False, False, ..., True, True, True]])请注意,False表示那里没有填充标记(所以是的,在转换器转发传递中使用该值),而True表示存在填充标记(因此屏蔽了它,以便转换器转发不受影响)。
答案在某种程度上是分散的,但我发现只有这三个参考文献是有用的(单独的层文档/东西并不是很有用,老实说):
https://pytorch.org/tutorials/beginner/translation_transformer.html
发布于 2020-06-04 00:26:02
我必须说PyTorch实现有点混乱,因为它包含了太多的掩码参数。但我可以阐明您所指的两个掩码参数。在MultiheadAttention机制中同时使用src_mask和src_key_padding_mask。根据MultiheadAttention的文档
key_padding_mask -如果提供,注意将忽略键中指定的填充元素。
attn_mask - 2D或3D遮罩,可防止对某些位置的注意。
正如你从论文中了解到的,Attention is all you need,MultiheadAttention在编码器和解码器中都使用了。然而,在解码器中,有两种类型的MultiheadAttention。一种称为Masked MultiheadAttention,另一种称为常规MultiheadAttention。为了适应这两种技术,PyTorch在其MultiheadAttention实现中使用了上述两个参数。
所以,长话短说-
here.指出,编码器的MultiheadAttention使用
attn_mask和key_padding_mask,解码器的MultiheadAttention使用解码器的MultiheadAttention机制研究一下MultiheadAttention的实现可能会对您有所帮助。
正如您从here和here中看到的,首先使用src_mask来阻止特定职位的出席,然后使用key_padding_mask来阻止出席到pad令牌。
备注。答案根据@michael-jungo的评论进行了更新。
发布于 2021-05-26 16:03:29
举个小例子,考虑我想要建立一个连续的推荐器,即给定用户在't‘之前购买的商品,预测't+1’的下一个商品。
u1 - [i1, i2, i7]
u2 - [i2, i5]
u3 - [i6, i7, i1, i2]对于这个任务,我可以使用一个转换器,通过在左边填充0来使序列长度相等。
u1 - [0, i1, i2, i7]
u2 - [0, 0, i2, i5]
u3 - [i6, i7, i1, i2]我将使用key_padding_mask来告诉PyTorch应该忽略0的值。现在,考虑用户u3,在给定[i6]的情况下,我想预测[i7],然后在给定[i6, i7]的情况下,我想预测[i1],即,我想要因果注意力,这样注意力就不会窥视未来的元素。为此,我将使用attn_mask。因此,对于用户u3,attn_mask将如下所示
[[True, False, False, False],
[True, True , False, False],
[True, True , True , False]
[True, True , True , True ]]https://stackoverflow.com/questions/62170439
复制相似问题