PyTorch等效于tf.nn.softmax_cross_entropy_with_logits和tf.nn.sigmoid_cross_entropy_with_logits的交叉熵函数

tcbh2hod  于 2022-11-09  发布在  Git
关注(0)|答案(2)|浏览(224)

我找到了here的帖子。在这里,我们试图在PyTorch中找到tf.nn.softmax_cross_entropy_with_logits的等价物。答案对我来说仍然很困惑。
下面是Tensorflow 2代码

import tensorflow as tf
import numpy as np

# here we assume 2 batch size with 5 classes

preds = np.array([[.4, 0, 0, 0.6, 0], [.8, 0, 0, 0.2, 0]])
labels = np.array([[0, 0, 0, 1.0, 0], [1.0, 0, 0, 0, 0]])

tf_preds = tf.convert_to_tensor(preds, dtype=tf.float32)
tf_labels = tf.convert_to_tensor(labels, dtype=tf.float32)

loss = tf.nn.softmax_cross_entropy_with_logits(logits=tf_preds, labels=tf_labels)

它给予loss作为

<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1.2427604, 1.0636061], dtype=float32)>

下面是PyTorch代码

import torch
import numpy as np

preds = np.array([[.4, 0, 0, 0.6, 0], [.8, 0, 0, 0.2, 0]])
labels = np.array([[0, 0, 0, 1.0, 0], [1.0, 0, 0, 0, 0]])

torch_preds = torch.tensor(preds).float()
torch_labels = torch.tensor(labels).float()

loss = torch.nn.functional.cross_entropy(torch_preds, torch_labels)

但是,它会引发:
运行时错误:预期1D目标Tensor,不支持多目标
看来这个问题还是没有解决,如何在PyTorch中实现tf.nn.softmax_cross_entropy_with_logits
那么tf.nn.sigmoid_cross_entropy_with_logits呢?

mzsu5hc0

mzsu5hc01#

-第一个月第一个月

  • 编辑:* 这实际上并不等同于F.cross_entropy。后者只能处理单类分类设置。而不是更一般的多类分类情况,即标签可以由多个类组成。实际上,F.cross_entropy将唯一的类ID作为目标(每个示例),而不是tf.nn.softmax_cross_entropy_with_logits可以期望接收的类的概率分布
>>> logits = torch.tensor([[4.0, 2.0, 1.0], [0.0, 5.0, 1.0]])
>>> labels = torch.tensor([[1.0, 0.0, 0.0], [0.0, 0.8, 0.2]])

为了得到所需的结果,对你的logits应用log-softmax,然后取负对数似然:

>>> -torch.sum(F.log_softmax(logits, dim=1) * labels, dim=1)
tensor([0.1698, 0.8247])

-tf.nn.sigmoid_cross_entropy_with_logits(第四个数字)

对于这个,您可以应用F.binary_cross_entropy_with_logits

>>> F.binary_cross_entropy_with_logits(logits, labels, reduction='none')
tensor([[0.0181, 2.1269, 1.3133],
        [0.6931, 1.0067, 1.1133]])

这相当于先应用S形,然后应用负对数似然,将每个类视为二元分类任务:

>>> labels*-torch.log(torch.sigmoid(logits)) + (1-labels)*-torch.log(1-torch.sigmoid(logits))
tensor([[0.0181, 2.1269, 1.3133],
        [0.6931, 1.0067, 1.1133]])
  • 已将torch.nn.functional导入为F *。
yptwkmov

yptwkmov2#

nn.CrossEntropyLoss的输出与tf.nn.softmax_cross_entropy_with_logits相同

>>> import torch

>>> loss_fct = torch.nn.CrossEntropyLoss(reduction='none')

>>> preds = np.array([[.4, 0, 0, 0.6, 0], [.8, 0, 0, 0.2, 0]])
>>> labels = np.array([[0, 0, 0, 1.0, 0], [1.0, 0, 0, 0, 0]])

>>> preds = torch.from_numpy(preds)
>>> labels = torch.from_numpy(labels)

>>> loss_fct(preds, labels)
tensor([1.2428, 1.0636], dtype=torch.float64)

reduction参数默认为mean。我将其设置为none以匹配您的输出。
nn.BCEWithLogitsLoss的输出与tf.nn.sigmoid_cross_entropy_with_logits相同

>>> tf.nn.sigmoid_cross_entropy_with_logits(logits=tf_preds, labels=tf_labels)
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
array([[0.91301525, 0.6931472 , 0.6931472 , 0.43748793, 0.6931472 ],
       [0.37110066, 0.6931472 , 0.6931472 , 0.79813886, 0.6931472 ]],
      dtype=float32)>

>>> loss_fct = torch.nn.BCEWithLogitsLoss(reduction='none')
>>> loss_fct(preds, labels, )
tensor([[0.9130, 0.6931, 0.6931, 0.4375, 0.6931],
        [0.3711, 0.6931, 0.6931, 0.7981, 0.6931]], dtype=torch.float64)

相关问题