"tf.sparse_softmax_cross_entropy_with_logits和tf.softmax_cross_entropy_with_logits的区别是什么?"

126
我最近发现了tf.nn.sparse_softmax_cross_entropy_with_logits,但是与tf.nn.softmax_cross_entropy_with_logits相比有什么区别我无法弄清楚。
使用sparse_softmax_cross_entropy_with_logits时,唯一的区别是训练向量y必须进行独热编码吗?
阅读API时,我无法找到与softmax_cross_entropy_with_logits相比的任何其他差异。那为什么我们需要额外的功能呢?
如果提供了独热编码的训练数据/向量,softmax_cross_entropy_with_logits难道不应该产生与sparse_softmax_cross_entropy_with_logits相同的结果吗?

2
我对比较它们的性能很感兴趣,如果两者都可以使用(例如,具有独占图像标签);我期望稀疏版本在至少内存方面更有效率。 - Yibo Yang
2
请参阅此问题,其中讨论了TensorFlow中的所有交叉熵函数(结果发现有很多种)。 - Maxim
3个回答

187

具有两个不同的功能是一种方便,因为它们产生相同的结果。

区别很简单:

  • 对于sparse_softmax_cross_entropy_with_logits,标签必须具有形状[batch_size]和dtype int32或int64。每个标签都是范围内的int [0,num_classes-1]
  • 对于softmax_cross_entropy_with_logits,标签必须具有形状[batch_size,num_classes]和dtype float32或float64。

softmax_cross_entropy_with_logits中使用的标签是sparse_softmax_cross_entropy_with_logits中使用的标签的one-hot版本

另一个微小的差异是,在sparse_softmax_cross_entropy_with_logits中,您可以将-1作为标签给出,以使此标签的损失为 0


18
-1是否正确?根据文档描述:"labels中的每个条目必须是[0,num_classes)范围内的索引。当在CPU上运行此操作时,其他值将引发异常,并在GPU上为相应的损失和梯度行返回NaN。" - Reddspark
3
[0, num_classes) = [0, num_classes-1]这句话的意思是,区间[0,num_classes)等同于区间[0,num_classes-1]。 - Karthik C
1
这个语句正确吗?“softmax_cross_entropy_with_logits中使用的标签是sparse_softmax_cross_entropy_with_logits中使用的标签的one hot版本。”它反了吗?稀疏损失函数不是0的整数吗,所以稀疏的那个是one-hot版本? - brianlen

28

我想补充一下已接受的答案,你也可以在TF文档中找到以下两点。

第一:

tf.nn.softmax_cross_entropy_with_logits

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

第二:

tf.nn.sparse_softmax_cross_entropy_with_logits

注意:对于此操作,考虑给定标签的概率是互斥的。也就是说,不允许软分类,并且标签向量必须为每个logits(每个minibatch条目)的真实类提供单个特定索引。


4
如果类别不是互斥的,我们应该使用什么?我的意思是,如果我们要组合多个分类标签呢? - Hayro
我也读过这个。这意味着我们将类概率应用于交叉熵,而不是将其作为onehot向量。 - Shamane Siriwardhana
@Hayro - 你的意思是你无法进行独热编码吗?我认为你需要考虑使用不同的模型。这个链接提到了“构建4个二元逻辑回归分类器可能更合适”,以确保你能够正确地分离类别。 - ashley

22

两个函数计算的结果相同,sparse_softmax_cross_entropy_with_logits 直接对稀疏标签进行交叉熵计算,而不是将它们转换为one-hot编码

您可以通过运行以下程序来验证此内容:

import tensorflow as tf
from random import randint

dims = 8
pos  = randint(0, dims - 1)

logits = tf.random_uniform([dims], maxval=3, dtype=tf.float32)
labels = tf.one_hot(pos, dims)

res1 = tf.nn.softmax_cross_entropy_with_logits(       logits=logits, labels=labels)
res2 = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=tf.constant(pos))

with tf.Session() as sess:
    a, b = sess.run([res1, res2])
    print a, b
    print a == b

这里我创建了一个随机的长度为dimslogits向量,并生成了一个独热编码标签(其中pos元素为1,其他元素为0)。

之后我计算softmax和稀疏softmax,并比较它们的输出。请尝试多次重新运行以确保始终产生相同的输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接