11

在使用 TensorFlow 一段时间后,我阅读了一些 Keras 教程并实现了一些示例。keras.losses.binary_crossentropy我找到了几个用作损失函数的卷积自动编码器教程。

我认为binary_crossentropy应该是多类损失函数,并且很可能会使用二进制标签,但实际上 Keras(TF Python 后端)调用,它实际上是用于具有多个互斥的独立类的分类任务。tf.nn.sigmoid_cross_entropy_with_logits

另一方面,我的期望categorical_crossentropy是用于多类分类,其中目标类相互依赖,但不一定是单热编码的。

但是,Keras 文档指出:

(...)当使用 categorical_crossentropy 损失时,您的目标应该是分类格式(例如,如果您有 10 个类,则每个样本的目标应该是一个 10 维向量,该向量是全零期望索引处为 1对应于样本的类别)。

如果我没记错的话,这只是 one-hot 编码分类任务的特例,但潜在的交叉熵损失也适用于概率分布(“多类”,依赖标签)?

此外,Keras 使用tf.nn.softmax_cross_entropy_with_logits(TF python backend) 来实现,它本身声明

注意:虽然这些类是互斥的,但它们的概率不必是. 所需要的只是每一行标签都是一个有效的概率分布。如果不是,则梯度的计算将不正确。

如果我错了,请纠正我,但在我看来,Keras 文档 - 至少 - 不是很“详细”?!

那么,Keras 命名损失函数背后的想法是什么?文档是否正确?如果二进制交叉熵真的依赖于二进制标签,它不应该适用于自动编码器,对吧?!同样,分类交叉熵:如果文档正确,则仅适用于单热编码标签?!

4

3 回答 3

8

通过定义每个损失适用的区域,您是正确的:

  • binary_crossentropy(并且tf.nn.sigmoid_cross_entropy_with_logits在引擎盖下)用于二进制多标签分类(标签是独立的)。
  • categorical_crossentropy(并且tf.nn.softmax_cross_entropy_with_logits在引擎盖下)用于多类分类(类是专有的)。

另请参阅此问题中的详细分析。

我不确定您的意思是什么教程,因此无法评论binary_crossentropy自动编码器的选择是好是坏。

至于命名,绝对正确合理。或者你认为sigmoidsoftmax名字听起来更好?

因此,您问题中唯一的困惑是categorical_crossentropy文档。请注意,所陈述的一切都是正确的:损失支持 one-hot 表示。在 tensorflow 后端的情况下,这个函数确实适用于标签的任何概率分布(除了一个热向量),它可以包含在文档中,但这对我来说并不重要。此外,需要检查其他后端,theano 和 CNTK 是否支持软类。请记住,keras 试图成为最流行的用例的极简主义和目标,所以我可以理解这里的逻辑。

于 2017-12-19T14:50:54.170 回答
1

不确定这是否回答了您的问题,但对于 softmax 损失,输出层需要是概率分布(即总和为 1),而对于二元交叉熵损失则不需要。就那么简单。(二进制并不意味着只有 2 个输出类,它只是意味着每个输出都是二进制的。)

于 2017-12-18T22:18:01.470 回答
0

文档没有提到BinaryCrossentropy可用于多标签分类,这可能会造成混淆。但它也可以用于二元分类器(当我们只有 2 个专有类,如猫和狗时) - 请参阅经典示例。但在这种情况下,我们必须设置n_classes=1

tf.keras.layers.Dense(units=1)

BinaryCrossentropytf.keras.losses.binary_crossentropy不同的行为。

让我们看一下文档中的示例,以证明它实际上是用于多标签分类的。

y_true = tf.convert_to_tensor([[0, 1], [0, 0]])
y_pred = tf.convert_to_tensor([[0.6, 0.4], [0.4, 0.6]])

bce = tf.keras.losses.BinaryCrossentropy()
loss1 = bce(y_true=y_true, y_pred=y_pred)
# <tf.Tensor: shape=(), dtype=float32, numpy=0.81492424>

loss2 = tf.keras.losses.binary_crossentropy(y_true, y_pred)
# <tf.Tensor: shape=(2,), dtype=float32, numpy=array([0.9162905 , 0.71355796], dtype=float32)>

np.mean(loss2.numpy())
# 0.81492424

scce = tf.keras.losses.SparseCategoricalCrossentropy()
y_true = tf.convert_to_tensor([0, 0])
scce(y_true, y_pred)
# <tf.Tensor: shape=(), dtype=float32, numpy=0.71355814>
y_true = tf.convert_to_tensor([1, 0])
scce(y_true, y_pred)
# <tf.Tensor: shape=(), dtype=float32, numpy=0.9162907>
于 2020-06-24T14:17:04.703 回答