pytorch nllloss 函数目标形状不匹配

Posted

技术标签:

【中文标题】pytorch nllloss 函数目标形状不匹配【英文标题】:pytorch nllloss function target shape mismatch 【发布时间】:2020-05-24 01:00:54 【问题描述】:

我正在使用批量大小为 256 的 pytorch 和 NLLLoss() 作为损失函数来训练 LSTM 模型。 损失函数的数据形状有问题。

前向传递的 softmax 输出的形状为 torch.Size([256, 4, 1181]),其中 256 是批量大小,4 是序列长度,1181 是词汇大小。

目标的形状为torch.Size([256, 4]),其中 256 是批量大小,4 是输出序列长度。

当我早先以 1 的批量大小进行测试时,模型运行良好,但当我添加批量大小时,它就坏了。我读到 NLLLoss() 可以将类目标作为输入,而不是一个热编码目标。

我是不是误会了?还是我没有正确格式化目标的形状?

class LSTM(nn.Module):

    def __init__(self, embed_size=100, hidden_size=100, vocab_size=1181, embedding_matrix=...):
        super(LSTM, self).__init__()
        self.hidden_size = hidden_size
        self.word_embeddings = nn.Embedding(vocab_size, embed_size)
        self.word_embeddings.load_state_dict('weight': torch.Tensor(embedding_matrix))
        self.word_embeddings.weight.requires_grad = False
        self.lstm = nn.LSTM(embed_size, hidden_size)
        self.hidden2out = nn.Linear(hidden_size, vocab_size)


    def forward(self, tokens):
        batch_size, num_steps = tokens.shape
        embeds = self.word_embeddings(tokens)
        lstm_out, _ = self.lstm(embeds.view(batch_size, num_steps, -1))
        out_space = self.hidden2out(lstm_out.view(batch_size, num_steps, -1))
        out_scores = F.log_softmax(out_space, dim=1)
        return out_scores

model = LSTM(self.config.embed_size, self.config.hidden_size, self.config.vocab_size, self.embedding_matrix)
loss_function = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=self.config.lr)

错误:

~/anaconda3/lib/python3.7/site-packages/torch/nn/functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
   1846         if target.size()[1:] != input.size()[2:]:
   1847             raise ValueError('Expected target size , got '.format(
-> 1848                 out_size, target.size()))
   1849         input = input.contiguous().view(n, c, 1, -1)
   1850         target = target.contiguous().view(n, 1, -1)

ValueError: Expected target size (256, 554), got torch.Size([256, 4])

【问题讨论】:

您的使用方式似乎是正确的。最好添加您的确切错误。 @akshayk07 添加。 model = LSTM(self.config.embed_size, self.config.hidden_size, self.config.vocab_size, self.embedding_matrix) -> 在这一行,你可以直接使用合适的尺寸吗?可能是导致问题的原因。 @TYZ 检查文档中的nn.NLLLoss 再次仔细描述形状。如果输入是 (N,C,d),那么目标应该是 (N,d)。在您的情况下,它看起来像输入是 (N,d,C),因此转置输入的暗淡 1 和 2 可能会解决您的问题。 @TYZ 对不起,我指的是损失函数的输入,即网络输出。我只是在评论,如果x 是 (N,d,C) 网络输出,y 是 (N,d) 目标,那么 loss_function(x.reshape(N*d,C), y.reshape(N*d))loss_function(x.transpose(1,2), y) 相同,至少对于 NLLLoss . 【参考方案1】:

损失函数的输入形状是(N, d, C) = (256, 4, 1181),目标形状是(N, d) = (256, 4),但是,根据NLLLoss 上的文档,对于(N, d) 的目标,输入应该是(N, C, d)

假设x 是您的网络输出,y 是目标,那么您可以通过转置x 的不正确维度来计算损失,如下所示:

loss = loss_function(x.transpose(1, 2), y)

另外,由于 NLLLoss 只是对所有响应进行平均,因此您只需将 xy 重塑为 (N*d, C)(N*d) 张量即​​可避免创建数据副本并获得相同的结果:

loss = loss_function(x.reshape(N*d, C), y.reshape(N*d))

【讨论】:

以上是关于pytorch nllloss 函数目标形状不匹配的主要内容,如果未能解决你的问题,请参考以下文章

无法在pytorch python中使用多目标损失函数

在pytorch中连接两个不同形状的火炬张量

Pytorch详解NLLLoss和CrossEntropyLoss

标签平滑Label Smoothing Demo(附pytorch的NLLLoss(),gather())

pytorch CrossEntropyLoss(), Softmax(), logSoftmax, NLLLoss

Pytorch 语义分割损失函数