在 Transformer 中使用后续掩码会导致 NaN 输出

数据挖掘 深度学习 神经网络 nlp 火炬 变压器
2022-02-13 12:15:39

我正在尝试实现一个类似于论文的自回归变压器模型,attention is all you need据我了解,为了完全复制架构,我需要给变压器解码器 3 个掩码。

  1. 目标后续掩码:这是为了因果关系。

  2. 目标填充索引:仅查看非填充索引。

  3. 编码器填充索引:仅查看来自编码器的非填充输入。

片段在这里:

y = self.decoder(y, x,
                         tgt_mask=tgt_causal_mask,
                         tgt_key_padding_mask=tgt_padding_mask,
                         memory_key_padding_mask=src_padding_mask)

像这样生成掩码:

def generate_no_peek_mask(self, sz):
    mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)
    mask = mask.float().masked_fill(mask == 0, float("-inf")).masked_fill(mask == 1, float(0.0))
    mask = mask.to(self.device)
    return mask

def generate_padding_mask(self, seq, pad_idx):
    return (seq != pad_idx).to(self.device)

问题是使用这些掩码会因为 NaN 值而导致 Softmax 函数出现问题。没有这些掩码,模型不会生成任何 NaN 值。我试过玩弄各种输入长度,看看当我确保我的输入适度大时会发生什么,但它仍然不起作用。唯一有效的方法是不给解码器提供掩码。

1个回答

我发现了问题所在。它不是来自随后的面具。是坏事造成的key_padding_maskPyTorch 期望 存在key_padding_masktrue任何有填充标记且false没有填充标记的地方。我以完全相反的方式生成填充蒙版。所以正确的面具将是:

def generate_padding_mask(self, seq, pad_idx):
    return (seq == pad_idx).to(self.device)