问题是它们有不同的实现。
正如 pytorch docs 所说,nn.CrossEntropyLoss 将 nn.LogSoftmax() 和 nn.NLLLoss() 组合在一个类中。但是,tensorflow docs 指定 keras.backend.categorical_crossentropy 默认不应用 Softmax,除非您将 from_logits 设置为 True。出于这个原因,除非你使用from_logits=True,否则你不应该使用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_crossentropy 和 from_logits=False。
tf.keras.backend.categorical_crossentropy
target:与输出形状相同的张量。
输出:由 softmax 产生的张量(除非 from_logits 为 True,在这种情况下,输出应为 logits)。
from_logits:布尔值,输出是 softmax 的结果,还是 logits 的张量。