from_logits=True 但损失为 0

Posted

技术标签:

【中文标题】from_logits=True 但损失为 0【英文标题】:from_logits=True but loss is 0 【发布时间】:2021-06-30 15:24:25 【问题描述】:

我正在学习 tensorflow,并希望将 tensorflow 实现与数学联系起来。

据我所知,数学交叉熵要求其输入之和为 1。在以下代码中,y_true 是有效输入,而 y_pred 不是数学有效输入:

y_true = [[0, 1]]
y_pred = [[1.0, 20.0]]
print(tf.keras.losses.CategoricalCrossentropy(from_logits=False).call(y_true, y_pred))
print(tf.keras.losses.CategoricalCrossentropy(from_logits=True).call(y_true, y_pred))

给予:

tf.Tensor([0.04879016], shape=(1,), dtype=float32)
tf.Tensor([0.], shape=(1,), dtype=float32)

请找到要点here。

This answer 说:

如果from_logits=False,表示输入是概率

This answer 说:

from_logits=True表示crossEntropy层的输入正常 张量/logits

This answer 说:

"上面代码中raw_predictions的另一个名字是logit

from_logits,我猜,意思是输入是raw_predictions

由于我输入的不是概率,所以我设置了from_logits=True,但我得到的结果是0。

谁能解释一下?

【问题讨论】:

【参考方案1】:

标签 [[0, 1]] 和 logits [[1, 20]] 之间的交叉熵应该是一个非常接近于 0 的值(由于浮点不精确,某些输出可能将其表示为零)。以概率表示,这些 logits 大约为 [[0.000000005, 1]]。请注意这些概率与标签的接近程度。因此交叉熵应该非常低。

正如 OP 在他们的问题中指出的那样,from_logits=True 在未缩放的输出上运行时应该使用。实际上,from_logits=True 用于在输出 before softmax 上进行操作。 Softmax 将未缩放的输出映射到概率。要计算这些概率的交叉熵,应该使用from_logits=False

这是一个例子:

import tensorflow as tf

y_true = tf.convert_to_tensor([[0, 1]], "float32")
y_pred = tf.convert_to_tensor([[1, 20]], "float32")

ce_logits_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
ce_probs_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=False)

print(ce_logits_fn(y_true, y_pred))
# tf.Tensor(0.0, shape=(), dtype=float32)

print(ce_probs_fn(y_true, tf.nn.softmax(y_pred)))
# tf.Tensor(1.1920929e-07, shape=(), dtype=float32)

尝试更紧密地预测。在上面的例子中,正确类的值远高于错误类的值,所以交叉熵会很低。

import tensorflow as tf

y_true = tf.convert_to_tensor([[0, 1]], "float32")
y_pred = tf.convert_to_tensor([[5, 7]], "float32")

ce_logits_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
ce_probs_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=False)

print(ce_logits_fn(y_true, y_pred))
# tf.Tensor(0.12692805, shape=(), dtype=float32)

print(ce_probs_fn(y_true, tf.nn.softmax(y_pred)))
# tf.Tensor(0.126928, shape=(), dtype=float32)

【讨论】:

这说明了很多,谢谢!我发现ce_logits_fn(y_true, tf.nn.softmax(y_pred)) 输出不同的结果。我猜softmax的softmax不是幂等的。如果输入恰好是 [0.1,0.9],我应该设置from_logits=True 吗?我是否应该检查每个输入,如果任何输入看起来不像概率,我假设输入没有通过 softmax? 好吧,我真正关心的是可以一直打开from_logits=True吗?如果我的模型已经有一个 softmax 层,保持from_logits=True 会影响训练吗? 因为你的模型给出了概率,你应该使用from_logits=Falsetf.keras 的较新版本(不确定从何时开始)将隐含 use the logits if they are available。有趣的一点是,概率的 softmax 不会返回相同的值......我很想知道为什么。 如果您在概率上使用from_logits=True,那么您的损失将是错误的,您的模型将无法正确学习。

以上是关于from_logits=True 但损失为 0的主要内容,如果未能解决你的问题,请参考以下文章

以 y_true 依赖于 y_pred 的方式自定义 Keras 的损失函数

如何在张量流的自定义损失中获取张量的形状

在 Tensorflow 2.3.1 中读取损失函数的值

Keras 后端自定义损失函数

如何为 LSTM 实现 Keras 自定义损失函数

带有额外输入数据的 tensorflow 自定义损失函数