【问题标题】:Example CrossEntropyLoss for 3D semantic segmentation in pytorchpytorch 中 3D 语义分割的示例 CrossEntropyLoss
【发布时间】:2017-12-08 13:48:55
【问题描述】:

我有一个网络在 5D 输入张量上执行 3D 卷积。我的网络的输出大小(1、12、60、36、60)对应于(BatchSize、NumClasses、x-dim、y-dim、z-dim)。我需要计算体素交叉熵损失。但是我不断收到错误。

当尝试使用 torch.nn.CrossEntropyLoss() 计算交叉熵损失时,我不断收到以下错误消息:

RuntimeError: multi-target not supported at .../src/THCUNN/generic/ClassNLLCriterion.cu:16

这是我的代码摘录:

import torch
import torch.nn as nn
from torch.autograd import Variable
criterion = torch.nn.CrossEntropyLoss()
images = Variable(torch.randn(1, 12, 60, 36, 60)).cuda()
labels = Variable(torch.zeros(1, 12, 60, 36, 60).random_(2)).long().cuda()
loss = criterion(images.view(1,-1), labels.view(1,-1))

当我为标签创建一个单热张量时也会发生同样的情况:

nclasses = 12
labels = (np.random.randint(0,12,(1,60,36,60))) # Random labels with values between [0..11]
labels = (np.arange(nclasses) == labels[..., None] - 1).astype(int) # Converts labels to one_hot_tensor
a = np.transpose(labels,(0,4,3,2,1)) #  Reorder dimensions to match shape of "images" ([1, 12, 60, 36, 60])
b = Variable(torch.from_numpy(a)).cuda()
loss = criterion(images.view(1,-1), b.view(1,-1))

知道我做错了什么吗? 有人可以提供一个在 5D 输出张量上计算交叉熵的示例吗?

【问题讨论】:

    标签: pytorch


    【解决方案1】:

    刚刚检查了一些用于 2D 语义分割的实现 (fcn),并尝试使其适应 3D 语义分割。不保证这是正确的,我必须仔细检查......

     import torch
     import torch.nn.functional as F
     def cross_entropy3d(input, target, weight=None, size_average=True):
        # input: (n, c, h, w, z), target: (n, h, w, z)
        n, c, h, w , z = input.size()
        # log_p: (n, c, h, w, z)
        log_p = F.log_softmax(input, dim=1)
        # log_p: (n*h*w*z, c)
        log_p = log_p.permute(0, 4, 3, 2, 1).contiguous().view(-1, c) # make class dimension last dimension
        log_p = log_p[target.view(n, h, w, z, 1).repeat(1, 1, 1, 1, c) >= 0] # this looks wrong -> Should rather be a one-hot vector
        log_p = log_p.view(-1, c)
        # target: (n*h*w*z,)
        mask = target >= 0
        target = target[mask]
        loss = F.nll_loss(log_p, target.view(-1), weight=weight, size_average=False)
        if size_average:
            loss /= mask.data.sum()
        return loss
    images = Variable(torch.randn(5, 3, 16, 16, 16))
    labels = Variable(torch.LongTensor(5, 16, 16, 16).random_(3))
    cross_entropy3d(images, labels, weight=None, size_average=True)
    

    【讨论】:

    • 你解决了吗?我正在寻找方法,因为我使用的是 3D Unet
    【解决方案2】:

    docs 解释了这种行为(底线,看起来它实际上是在计算 sparse 交叉熵损失,因此不需要输出所有维度的目标,而只需要需要一个)...他们特别声明:

    Input: (N,C), where C = number of classes
    Target: (N), where each value is 0 <= targets[i] <= C-1
    Output: scalar. If reduce is False, then (N) instead.
    

    我不确定您的用例,但您可能想改用KL DivergenceBinary Cross Entropy Loss。两者都是在相同大小的输入和目标上定义的。

    【讨论】:

      猜你喜欢
      • 2020-05-03
      • 2018-11-26
      • 2021-07-30
      • 1970-01-01
      • 2018-06-23
      • 2019-11-15
      • 2020-10-20
      • 2021-02-19
      • 2020-11-17
      相关资源
      最近更新 更多