在 Pytorch F.nll_loss() 中预期的类型为 torch.LongTensor 的对象,但为参数 #2 'target' 找到了类型 torch.FloatTensor

Posted

技术标签:

【中文标题】在 Pytorch F.nll_loss() 中预期的类型为 torch.LongTensor 的对象,但为参数 #2 \'target\' 找到了类型 torch.FloatTensor【英文标题】:In Pytorch F.nll_loss() Expected object of type torch.LongTensor but found type torch.FloatTensor for argument #2 'target'在 Pytorch F.nll_loss() 中预期的类型为 torch.LongTensor 的对象,但为参数 #2 'target' 找到了类型 torch.FloatTensor 【发布时间】:2018-12-29 03:23:03 【问题描述】:

为什么会出现这个错误。

我正在尝试编写一个自定义损失函数,它最终具有负对数可能性。

根据我的理解,NLL 是在两个概率值之间计算的?

>>> loss = F.nll_loss(sigm, trg_, ignore_index=250, weight=None, size_average=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home//lib/python3.5/site-packages/torch/nn/functional.py", line 1332, in nll_loss
    return torch._C._nn.nll_loss(input, target, weight, size_average, ignore_index, reduce)
RuntimeError: Expected object of type torch.LongTensor but found type torch.FloatTensor for argument #2 'target'

这里的输入如下:

>>> sigm.size()
torch.Size([151414, 80])
>>> sigm
tensor([[ 0.3283,  0.6472,  0.8278,  ...,  0.6756,  0.2168,  0.5659],
        [ 0.6603,  0.5957,  0.8375,  ...,  0.2274,  0.4523,  0.4665],
        [ 0.5262,  0.4223,  0.5009,  ...,  0.5734,  0.3151,  0.2076],
        ...,
        [ 0.4083,  0.2479,  0.5996,  ...,  0.8355,  0.6681,  0.7900],
        [ 0.6373,  0.3771,  0.6568,  ...,  0.4356,  0.8143,  0.4704],
        [ 0.5888,  0.4365,  0.8587,  ...,  0.2233,  0.8264,  0.5411]])

而我的目标张量是:

>>> trg_.size()
torch.Size([151414])
>>> trg_
tensor([-7.4693e-01,  3.5152e+00,  2.9679e-02,  ...,  1.6316e-01,
         3.6594e+00,  1.3366e-01])

如果我将其转换为 long,我会丢失所有数据:

>>> sigm.long()
tensor([[ 0,  0,  0,  ...,  0,  0,  0],
        [ 0,  0,  0,  ...,  0,  0,  0],
        [ 0,  0,  0,  ...,  0,  0,  0],
        ...,
        [ 0,  0,  0,  ...,  0,  0,  0],
        [ 0,  0,  0,  ...,  0,  0,  0],
        [ 0,  0,  0,  ...,  0,  0,  0]])
>>> trg_.long()
tensor([ 0,  3,  0,  ...,  0,  3,  0])

如果我也将目标张量的原始值转换为sigmoid

>>> F.sigmoid(trg_)
tensor([ 0.3215,  0.9711,  0.5074,  ...,  0.5407,  0.9749,  0.5334])
>>> loss = F.nll_loss(sigm, F.sigmoid(trg_), ignore_index=250, weight=None, size_average=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lib/python3.5/site-packages/torch/nn/functional.py", line 1332, in nll_loss
    return torch._C._nn.nll_loss(input, target, weight, size_average, ignore_index, reduce)
RuntimeError: Expected object of type torch.LongTensor but found type torch.FloatTensor for argument #2 'target'

这确实很高兴地计算了损失,但它再次只是相信我在长时间转换中丢失了数据:

>>> loss = F.nll_loss(sigm, F.sigmoid(trg_).long(), ignore_index=250, weight=None, size_average=True)
>>> loss 
tensor(-0.5010)

>>> F.sigmoid(trg_).long()
tensor([ 0,  0,  0,  ...,  0,  0,  0])

【问题讨论】:

【参考方案1】:

“根据我的理解,NLL是在两个概率值之间计算的?”

不,NLL 不是在两个概率值之间计算的。根据pytorch docs (见形状部分),通常用于实现交叉熵损失。当 N 是数据大小并且 C 是类的数量时,它需要输入预期是对数概率并且大小为 (N, C)。目标是一个大小为 (N,) 的长张量,它告诉样本的真实类别。

由于在您的情况下,目标肯定不是真正的类,您可能必须实现自己的损失版本,并且您可能无法使用 NLLLoss。如果你添加更多关于你想要编码的损失的详细信息,我可以帮助/解释更多关于如何做到这一点(如果可能的话,使用 Torch 中的现有函数)。

【讨论】:

【参考方案2】:

我将在此处留下可运行的最少注释代码,以便您查看每个步骤的维度并了解此(或其他)损失是如何工作的:

import torch
import torch.nn as nn

m = nn.LogSoftmax()
loss = nn.NLLLoss()

# input is of size N x C = 3 x 5
# this is FloatTensor containing probability for 
# each item in batch for each class
input = torch.randn(3, 5)

# target is LongTensor for index of true class for each item in batch
# each element in target has to have 0 <= value < C
target = torch.tensor([1, 0, 4])

# output is tensor of 0 dimension, i.e., scaler wrapped in tensor
output = loss(m(input), target)

【讨论】:

【参考方案3】:

在 Tensorflow 2 中运行代码为我解决了这个问题

【讨论】:

以上是关于在 Pytorch F.nll_loss() 中预期的类型为 torch.LongTensor 的对象,但为参数 #2 'target' 找到了类型 torch.FloatTensor的主要内容,如果未能解决你的问题,请参考以下文章

在 SpriteKit 中预加载纹理

在 Android 中预加载网页(使用 WebView?)

为啥我需要在迁移学习中预训练权重

在 reactjs 组件中预加载数据

在 UIPageViewControllers (Swift) 中预加载所有 UIViewControllers

如何在 Django 中预取聚合的@property?