15

我想知道 TensorFlow 是否有等效的 PyTorch 损失函数softmax_cross_entropy_with_logits

4

4 回答 4

7

TensorFlow 是否有等效的 PyTorch 损失函数softmax_cross_entropy_with_logits

torch.nn.functional.cross_entropy

这将 logits 作为输入(在log_softmax内部执行)。这里的“logits”只是一些不是概率的值(即不一定在区间内[0,1])。

但是,logits 也是将转换为概率的值。如果您考虑 tensorflow 函数的名称,您将理解它是 pleonasm(因为该with_logits部分假设softmax将被调用)。

在 PyTorch 实现中看起来像这样:

loss = F.cross_entropy(x, target)

这相当于:

lp = F.log_softmax(x, dim=-1)
loss = F.nll_loss(lp, target)

这不是F.binary_cross_entropy_with_logits因为这个函数假设多标签分类:

F.sigmoid + F.binary_cross_entropy = F.binary_cross_entropy_with_logits

也不torch.nn.functional.nll_loss是因为此函数采用对数概率(在 之后log_softmax())而不是对数。

于 2020-09-22T17:09:48.070 回答
1

一个解法

from thexp.calculate.tensor import onehot
from torch.nn import functional as F
import torch

logits = torch.rand([3,10])
ys = torch.tensor([1,2,3])
targets = onehot(ys,10)
assert F.cross_entropy(logits,ys) == -torch.mean(torch.sum(F.log_softmax(logits, dim=1) * targets, dim=1))

一热功能:

def onehot(labels: torch.Tensor, label_num):
    return torch.zeros(labels.shape[0], label_num, device=labels.device).scatter_(1, labels.view(-1, 1), 1)
于 2020-08-30T13:44:00.283 回答
0

按照几个线程中的指针,我最终进行了以下转换。我会在此处发布我的解决方案,以防其他人陷入此线程。它是从这里修改的,并在此上下文中按预期运行。

# pred is the prediction with shape [C, H*W]
# gt is the target with shape [H*W]
# idx is the boolean array on H*W for masking

# Tensorflow version
loss = tf.nn.sparse_softmax_cross_entropy_with_logits( \
          logits=tf.boolean_mask(pred, idx), \
          labels=tf.boolean_mask(gt, idx)))

# Pytorch version       
logp = torch.nn.functional.log_softmax(pred[idx])
logpy = torch.gather(logp, 1, Variable(gt[idx].view(-1,1)))
loss = -(logpy).mean()
于 2019-04-12T01:51:10.157 回答
0

@Blade 这是我想出的解决方案!

import torch
import torch.nn as nn
import torch.nn.functional as F


class masked_softmax_cross_entropy_loss(nn.Module):
    r"""my version of masked tf.nn.softmax_cross_entropy_with_logits"""
    def __init__(self, weight=None):
        super(masked_softmax_cross_entropy_loss, self).__init__()
        self.register_buffer('weight', weight)

    def forward(self, input, target, mask):
        if not target.is_same_size(input):
            raise ValueError("Target size ({}) must be the same as input size ({})".format(target.size(), input.size()))

        input = F.softmax(input)
        loss = -torch.sum(target * torch.log(input), 1)
        loss = torch.unsqueeze(loss, 1)
        mask /= torch.mean(mask)
        mask = torch.unsqueeze(mask, 1)
        loss = torch.mul(loss, mask)
        return torch.mean(loss)

顺便说一句:当时(2017 年 9 月)我需要这个损失函数,因为我试图将 Thomas Kipf 的 GCN(参见https://arxiv.org/abs/1609.02907)代码从 TensorFlow 转换为 PyTorch。然而,我现在注意到 Kipf 自己做了这件事(参见https://github.com/tkipf/pygcn),并且在他的代码中,他简单地使用了内置的 PyTorch 损失函数,负对数似然损失,即

loss_train = F.nll_loss(output[idx_train], labels[idx_train])

希望这可以帮助。

~DV

于 2019-12-05T15:06:07.007 回答