如果我不尝试自回归,我如何用PyTorch Transformers完成seq2seq任务



我可能错了,但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

在训练时,我有:

model = TransformerReconstruct(feature_size=128, nhead=8, output_dim=128, num_layers=6).to(device)

这会返回正确的形状,但似乎不会学习。

我的基本训练循环看起来像:

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

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

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

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

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

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

如果希望模型停止以自回归方式运行,则需要将令牌"取消隐藏"到当前令牌的右侧,即修改/删除_generate_square_subsequent_mask

如何修改取决于任务。您是否正在尝试恢复"损坏"的输入序列?然后屏蔽令牌的随机子集,并将其视为自动编码器。

如果你只是想近似身份函数,请完全去掉掩码。

最新更新