获得像Keras一样在火炬中的交叉熵损失

问题描述 投票:0回答:1

我正在努力将分类模型从keras移植到pytorch。特别是交叉熵损失似乎返回完全不同的数字。

import numpy as np
import torch as t
import torch.nn as nn
import tensorflow.keras.backend as K

y_true = np.array([[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]])
y_pred = np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1, 0.41, 0.31, 0.21, 0.11]])

print("Keras", K.categorical_crossentropy(K.constant(y_true), K.constant(y_pred)))
print("PyTorch", nn.CrossEntropyLoss()(t.tensor(y_pred).argsort(dim=-1).float(), t.tensor(y_true).argmax(dim=-1)))```

打印:

Keras tf.Tensor([2.3369865],shape =(1,),dtype = float32)

PyTorch张量(1.4587)

因为我有一个自定义损失函数,交叉熵是其中的一部分,所以如果数字不同,我将需要获得相似的结果。

python tensorflow keras pytorch
1个回答
0
投票

问题在于它们具有不同的实现。

如pytorch docs所说,nn.CrossEntropyLossnn.LogSoftmax()nn.NLLLoss()合并为一个类。但是,tensorflow docs指定默认情况下,除非您将keras.backend.categorical_crossentropy设置为True,否则默认情况下from_logits不应用Softmax。因此,除非事先使用softmax,否则不应该使用keras.backend.categorical_crossentropy。除非您使用from_logits=True

如果您不想预先应用softmax,则应使用:

import numpy as np
import torch as t
import torch.nn as nn
import tensorflow.keras.backend as K

y_true = np.array([[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]])
y_pred = np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1, 0.41, 0.31, 0.21, 0.11]])


print("Keras", K.categorical_crossentropy(K.constant(y_true), K.constant(y_pred), from_logits=True))
# output: Keras tf.Tensor([2.408051], shape=(1,), dtype=float32)
print("PyTorch", nn.CrossEntropyLoss()(t.tensor(y_pred).float(), t.tensor(y_true).argmax(dim=-1)))
# output: PyTorch tensor(2.4081)

否则,您可以在计算categorical_crossentropy之前手动应用Softmax

import numpy as np
import torch as t
import torch.nn as nn
import tensorflow.keras.backend as K

y_true = np.array([[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]])
y_pred = np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1, 0.41, 0.31, 0.21, 0.11]])


print("Keras", K.categorical_crossentropy(K.constant(y_true), K.softmax(K.constant(y_pred))))
# output: Keras tf.Tensor([2.408051], shape=(1,), dtype=float32)
print("PyTorch", nn.CrossEntropyLoss()(t.tensor(y_pred).float(), t.tensor(y_true).argmax(dim=-1)))
# output: PyTorch tensor(2.4081)

因此,您不应像在示例中那样将keras.backend.categorical_crossentropyfrom_logits=False一起使用。

tf.keras.backend.categorical_crossentropy

target:与输出形状相同的张量。

output:由softmax产生的张量(除非from_logits为True,在这种情况下,预期输出为logits)。

from_logits:布尔值,是输出是softmax的结果还是logits的张量。

© www.soinside.com 2019 - 2024. All rights reserved.