如何使用具有多维序列到序列的 PyTorch Transformer?

Posted

技术标签:

【中文标题】如何使用具有多维序列到序列的 PyTorch Transformer?【英文标题】:How to use the PyTorch Transformer with multi-dimensional sequence-to-seqence? 【发布时间】:2021-02-28 18:13:47 【问题描述】:

我正在尝试使用 Transformer 模型去seq2seq。我的输入和输出是相同的形状(torch.Size([499, 128]),其中 499 是序列长度,128 是特征数。

我的输入看起来像:

我的输出如下所示:

我的训练循环是:

    for batch in tqdm(dataset):
        optimizer.zero_grad()
        x, y = batch

        x = x.to(DEVICE)
        y = y.to(DEVICE)

        pred = model(x, torch.zeros(x.size()).to(DEVICE))

        loss = loss_fn(pred, y)
        loss.backward()
        optimizer.step()

我的模型是:

import math
from typing import final
import torch
import torch.nn as nn

class Reconstructor(nn.Module):
    def __init__(self, input_dim, output_dim, dim_embedding, num_layers=4, nhead=8, dim_feedforward=2048, dropout=0.5):
        super(Reconstructor, self).__init__()

        self.model_type = 'Transformer'
        self.src_mask = None
        self.pos_encoder = PositionalEncoding(d_model=dim_embedding, dropout=dropout)
        self.transformer = nn.Transformer(d_model=dim_embedding, nhead=nhead, dim_feedforward=dim_feedforward, num_encoder_layers=num_layers, num_decoder_layers=num_layers)
        self.decoder = nn.Linear(dim_embedding, output_dim)
        self.decoder_act_fn = nn.PReLU()

        self.init_weights()

    def init_weights(self):
        initrange = 0.1
        nn.init.zeros_(self.decoder.weight)
        nn.init.uniform_(self.decoder.weight, -initrange, initrange)

    def forward(self, src, tgt):

        pe_src = self.pos_encoder(src.permute(1, 0, 2))  # (seq, batch, features)
        transformer_output = self.transformer_encoder(pe_src)
        decoder_output = self.decoder(transformer_output.permute(1, 0, 2)).squeeze(2)
        decoder_output = self.decoder_act_fn(decoder_output)
        return decoder_output

我的输出形状为torch.Size([32, 499, 128]),其中32 是批处理,499 是我的序列长度,128 是特征数。但是输出具有相同的值:

tensor([[[0.0014, 0.0016, 0.0017,  ..., 0.0018, 0.0021, 0.0017],
         [0.0014, 0.0016, 0.0017,  ..., 0.0018, 0.0021, 0.0017],
         [0.0014, 0.0016, 0.0017,  ..., 0.0018, 0.0021, 0.0017],
         ...,
         [0.0014, 0.0016, 0.0017,  ..., 0.0018, 0.0021, 0.0017],
         [0.0014, 0.0016, 0.0017,  ..., 0.0018, 0.0021, 0.0017],
         [0.0014, 0.0016, 0.0017,  ..., 0.0018, 0.0021, 0.0017]]],
       grad_fn=<PreluBackward>)

我做错了什么?非常感谢您的帮助。

【问题讨论】:

在您的前向传递中,self.transformer_encoder() 未定义。你的意思是transformer_output = self.transformer()(显然没用过)? 【参考方案1】:

有几点需要检查。由于您对不同的输入具有相同的输出,我怀疑某些层会将其所有输入归零。所以检查 PositionalEncoding 和 Transformer 的 Encoder 块的输出,以确保它们不是恒定的。但在此之前,请确保您的输入不同(例如,尝试注入噪声)。

此外,从我在图片中看到的内容来看,您的输入和输出是语音信号,并以 22.05kHz 采样(我猜),所以它应该有大约 10k 个特征,但您声称您只有 128 个。这是另一个检查的地方。现在,数字 499 代表某个时间片。确保切片在合理范围内(20-50 毫秒,通常为 30)。如果是这种情况,那么 30 毫秒乘以 500 是 15 秒,这在您的示例中要多得多。最后,您在输入中掩盖了三分之一秒的语音,我相信这太多了。

我认为检查 Wav2vec 和 Wav2vec 2.0 论文会很有用,它们成功地解决了使用 Transformer Encoder 在语音识别领域进行自我监督训练的问题。

【讨论】:

以上是关于如何使用具有多维序列到序列的 PyTorch Transformer?的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch-19 使用 nn.Transformer 和 TorchText 进行序列到序列的建模

如何使用 pytorch 构建多维自动编码器

将多维表单数据序列化为 JSON 对象数组以使用 application/json

如何将多维数组添加到序列化的 POST 数据中?

使用pytorch的序列到序列模型

如何序列化谷物上的多维数组,C++ 序列化库