如果我不想自回归,我该如何使用 PyTorch Transformers 执行 seq2seq 任务?

Sha*_*oon 8 python transformer-model pytorch

我可能弄错了,但 PyTorch Transformers 似乎是自回归的,这就是掩蔽的用途。但是,我已经看到一些实现,人们只使用编码器并将其直接输出到Linear层。

就我而言,我试图将频谱图(行是频率,列是时间步长)转换为另一个相同维度的频谱图。我有一个不可能的时间试图弄清楚如何做到这一点。

对于我的模型,我有:

class TransformerReconstruct(nn.Module):
    def __init__(self, feature_size=250, num_layers=1, dropout=0.1, nhead=10, output_dim=1):
        super(TransformerReconstruct, self).__init__()
        self.model_type = 'Transformer'

        self.src_mask = None
        self.pos_encoder = PositionalEncoding(feature_size)
        self.encoder_layer = nn.TransformerEncoderLayer(d_model=feature_size, nhead=nhead, dropout=dropout)
        self.transformer_encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers)
        self.decoder = nn.Linear(feature_size, output_dim)
        self.init_weights()

    def init_weights(self):
        initrange = 0.1
        self.decoder.bias.data.zero_()
        self.decoder.weight.data.uniform_(-initrange, initrange)

    def forward(self, src):
        if self.src_mask is None or self.src_mask.size(0) != len(src):
            device = src.device
            mask = self._generate_square_subsequent_mask(len(src)).to(device)
            self.src_mask = mask

        src = self.pos_encoder(src)
        output = self.transformer_encoder(src, self.src_mask)
        output = self.decoder(output)
        return output

    def _generate_square_subsequent_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))
        return mask
Run Code Online (Sandbox Code Playgroud)

在训练时,我有:

model = TransformerReconstruct(feature_size=128, nhead=8, output_dim=128, num_layers=6).to(device)
Run Code Online (Sandbox Code Playgroud)

这将返回正确的形状,但似乎没有学习。

我的基本训练循环如下所示:

for i in range(0, len(data_source) - 1, input_window):
  data, target = get_batch(data_source, i, 1)
  output = recreate_model(data)
Run Code Online (Sandbox Code Playgroud)

我正在使用MSELoss并且我正在尝试学习一个非常简单的身份。输入和输出相同的地方,但这不是学习。我可能做错了什么?提前致谢。

Jin*_*ich 2

Huggingface Transformers 中的大多数模型都是 BERT 的某种版本,因此不是自回归的,唯一的例外是仅解码器模型(GPT 和类似模型)和序列到序列模型。

有两种概念上不同类型的掩码:一种是特定于输入批次的输入掩码,目的是允许在单个批次中使用不同长度的序列。当序列被填充到相同的长度时,自注意力应该注意填充位置。self.transformer_encoder这是您在调用转发方法时应该使用的内容。

此外,自回归 Transformer 解码器使用另一种类型的掩码。正是三角掩码阻止了自注意力去关注当前位置右侧的标记(在推理时,当前位置右侧的单词在实际生成之前是未知的)。这就是方法中的内容_generate_square_subsequent_mask,这就是使模型自回归的原因。它是常数,不依赖于输入批次。

总结一下:要拥有一个双向 Transformer,只需去掉三角形掩模即可。如果您的输入序列具有不同的长度,则应该使用特定于批次的掩码,如果没有,则只需传递一个带有 1 的矩阵。