首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >src_mask与src_key_padding_mask的区别

src_mask与src_key_padding_mask的区别
EN

Stack Overflow用户
提问于 2020-06-03 18:18:40
回答 3查看 4.9K关注 0票数 10

我在理解transformers时遇到了困难。每件事都在一点一点地变得清晰,但有一件事让我头疼,那就是src_mask和src_key_padding_mask之间的区别是什么,它在编码层和解码器层都是作为向前函数的参数传递的。

https://pytorch.org/docs/master/_modules/torch/nn/modules/transformer.html#Transformer

EN

回答 3

Stack Overflow用户

发布于 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 sizeD=E is the feature number):

  1. src_mask [Tx, Tx] = [S, S] -源序列的附加掩码(可选)。这是在执行atten_src + src_mask时应用的。我不确定是否有示例输入-请参阅tgt_mask获取示例,但典型的用法是添加-inf,以便在需要时可以以这种方式屏蔽src_attention。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。

  1. tgt_mask [Ty, Ty] = [T, T] - tgt序列的附加掩码(可选)。这是在执行atten_tgt + tgt_mask时应用的。一个例子是使用对角线来避免解码器作弊。因此,tgt被右移,第一个令牌是嵌入SOS/BOS的序列令牌的开始,因此第一个条目是零,而其余的条目。请参阅附录中的具体示例。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。

  1. memory_mask [Ty, Tx] = [T, S]-编码器输出的附加掩码(可选)。这是在执行atten_memory + memory_mask时应用的。不确定是否使用示例,但与前面一样,添加-inf会将一些注意力权重设置为零。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。

  1. src_key_padding_mask [B, Tx] = [N, S] -每批src密钥的ByteTensor掩码(可选)。由于您的src通常具有不同长度的序列,因此通常会删除附加在末尾的填充向量。为此,您可以指定批处理中每个示例的每个序列的长度。具体示例见附录。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。

  1. tgt_key_padding_mask [B, Ty] = [N, t] -每批tgt密钥的ByteTensor掩码(可选)。与上一次相同。具体示例见附录。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。

  1. memory_key_padding_mask [B, Tx] = [N, S] -每批内存密钥的ByteTensor掩码(可选)。与上一次相同。具体示例见附录。如果提供了ByteTensor,则不允许非零位置参加,而零位置将保持不变。如果提供了BoolTensor,则不允许具有True的职位参加,而False值将保持不变。如果提供了FloatTensor,则会将其添加到注意力权重。

附录

pytorch教程(https://pytorch.org/tutorials/beginner/translation_transformer.html)中的示例:

1个src_mask示例

代码语言:javascript
复制
    src_mask = torch.zeros((src_seq_len, src_seq_len), device=DEVICE).type(torch.bool)

返回大小为[Tx, Tx]的布尔值的张量

代码语言:javascript
复制
tensor([[False, False, False,  ..., False, False, False],
         ...,
        [False, False, False,  ..., False, False, False]])

2 tgt_mask示例

代码语言:javascript
复制
    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))

生成右移输出的对角线,该对角线是解码器的输入.

代码语言:javascript
复制
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有它自己的序列,因此它有自己的填充。示例:

代码语言:javascript
复制
    src_padding_mask = (src == PAD_IDX).transpose(0, 1)
    tgt_padding_mask = (tgt == PAD_IDX).transpose(0, 1)
    memory_padding_mask = src_padding_mask

输出:

代码语言:javascript
复制
tensor([[False, False, False,  ...,  True,  True,  True],
        ...,
        [False, False, False,  ...,  True,  True,  True]])

请注意,False表示那里没有填充标记(所以是的,在转换器转发传递中使用该值),而True表示存在填充标记(因此屏蔽了它,以便转换器转发不受影响)。

答案在某种程度上是分散的,但我发现只有这三个参考文献是有用的(单独的层文档/东西并不是很有用,老实说):

https://pytorch.org/tutorials/beginner/translation_transformer.html

  • 长教程
票数 11
EN

Stack Overflow用户

发布于 2020-06-04 00:26:02

我必须说PyTorch实现有点混乱,因为它包含了太多的掩码参数。但我可以阐明您所指的两个掩码参数。在MultiheadAttention机制中同时使用src_masksrc_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_maskkey_padding_mask,解码器的MultiheadAttention使用解码器的MultiheadAttention机制

研究一下MultiheadAttention的实现可能会对您有所帮助。

正如您从herehere中看到的,首先使用src_mask来阻止特定职位的出席,然后使用key_padding_mask来阻止出席到pad令牌。

备注。答案根据@michael-jungo的评论进行了更新。

票数 5
EN

Stack Overflow用户

发布于 2021-05-26 16:03:29

举个小例子,考虑我想要建立一个连续的推荐器,即给定用户在't‘之前购买的商品,预测't+1’的下一个商品。

代码语言:javascript
复制
u1 - [i1, i2, i7]
u2 - [i2, i5]
u3 - [i6, i7, i1, i2]

对于这个任务,我可以使用一个转换器,通过在左边填充0来使序列长度相等。

代码语言:javascript
复制
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将如下所示

代码语言:javascript
复制
[[True, False, False, False],
 [True, True , False, False],
 [True, True , True , False]
 [True, True , True , True ]]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62170439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档