TensorFlow中如何选择交叉熵损失?
Posted
技术标签:
【中文标题】TensorFlow中如何选择交叉熵损失?【英文标题】:How to choose cross-entropy loss in TensorFlow? 【发布时间】:2018-04-12 14:12:17 【问题描述】:分类问题,例如逻辑回归或多项式 逻辑回归,优化交叉熵损失。 通常,交叉熵层在 softmax 层之后, 这会产生概率分布。
在张量流中,至少有十几种不同的交叉熵损失函数:
tf.losses.softmax_cross_entropy
tf.losses.sparse_softmax_cross_entropy
tf.losses.sigmoid_cross_entropy
tf.contrib.losses.softmax_cross_entropy
tf.contrib.losses.sigmoid_cross_entropy
tf.nn.softmax_cross_entropy_with_logits
tf.nn.sigmoid_cross_entropy_with_logits
...
哪一个只适用于二分类问题,哪一个适用于多类问题?什么时候应该使用sigmoid
而不是softmax
? sparse
函数与其他函数有何不同,为什么只有 softmax
?
相关(更面向数学)讨论:What are the differences between all these cross-entropy losses in Keras and TensorFlow?。
【问题讨论】:
我们还有tf.losses.log_loss
,实际上它仅用于二进制交叉熵。还有github.com/tensorflow/tensorflow/issues/2462
【参考方案1】:
虽然接受的答案包含的信息比所要求的要多得多,但我觉得分享一些通用的拇指规则将使答案更加紧凑和直观:
只有一个真正的损失函数。这是交叉熵 (CE)。对于二元分类的特殊情况,这种损失称为二元CE(注意公式不会改变),对于非二元或多类情况同样称为categorical CE (CCE)。稀疏函数是分类 CE 的一种特殊情况,其中预期值不是单热编码而是整数 我们有 softmax 公式,它是 多类 场景的激活。对于 二进制 场景,相同的公式被赋予一个特殊的名称 - sigmoid 激活 因为在处理对数函数时有时会出现数值不稳定(对于极值),TF 建议将激活层和损失层合并为一个函数。这个组合函数在数值上更稳定。 TF 提供了这些组合函数,它们以 _with_logits 为后缀有了这个,现在让我们处理一些情况。假设有一个简单的二元分类问题 - 图像中是否存在猫?激活函数和损失函数的选择是什么?这将是一个 sigmoid 激活和一个(二进制)CE。因此可以使用 sigmoid_cross_entropy 或更优选 sigmoid_cross_entropy_with_logits。后者结合了激活函数和损失函数,并且应该是数值稳定的。
多类分类怎么样。假设我们想知道图像中是否存在猫、狗或驴。激活函数和损失函数的选择是什么?这将是一个 softmax 激活和一个(分类)CE。因此可以使用 softmax_cross_entropy 或更优选 softmax_cross_entropy_with_logits。我们假设期望值是 one-hot 编码的(100 或 010 或 001)。如果(出于某种奇怪的原因),情况并非如此,并且预期值为整数(1 或 2 或 3),您可以使用上述函数的“稀疏”对应项。
可能还有第三种情况。我们可以有一个多标签分类。所以在同一张图片中可能会有一只狗和一只猫。我们如何处理这个?这里的技巧是将这种情况视为多个二元分类问题 - 基本上是猫或没有猫/狗或没有狗和驴或没有驴。找出 3 个(二元分类)中的每一个的损失,然后将它们相加。所以基本上这归结为使用 sigmoid_cross_entropy_with_logits 损失。
这回答了您提出的 3 个具体问题。上面共享的功能就是所需要的。您可以忽略已弃用且不应使用的 tf.contrib 系列。
【讨论】:
【参考方案2】:初步事实
在功能意义上,sigmoid is a partial case of the softmax function,当类的数量等于 2 时。它们都执行相同的操作:将 logits(见下文)转换为概率。
在简单的二元分类中,两者没有太大区别, 然而,在多项分类的情况下,sigmoid 允许处理 具有非排他性标签(又名 多标签),而 softmax 处理 具有独家课程(见下文)。
在计算概率之前,logit(也称为分数)是raw unscaled value associated with a class。就神经网络架构而言,这意味着 logit 是密集(全连接)层的输出。
Tensorflow 命名有点奇怪:下面的所有函数都接受 logits,而不是概率,并自行应用转换(这更有效)。
Sigmoid 函数族
tf.nn.sigmoid_cross_entropy_with_logits
tf.nn.weighted_cross_entropy_with_logits
tf.losses.sigmoid_cross_entropy
tf.contrib.losses.sigmoid_cross_entropy
(已弃用)
如前所述,sigmoid
损失函数用于二元分类。
但是张量流函数更通用,可以做
多标签分类,当类是独立的。
换句话说,tf.nn.sigmoid_cross_entropy_with_logits
解决了N
一次二进制分类。
标签必须是一次性编码的,或者可以包含软类概率。
tf.losses.sigmoid_cross_entropy
还允许设置批量权重,
即让一些例子比其他例子更重要。
tf.nn.weighted_cross_entropy_with_logits
允许设置类权重
(记住,分类是二元的),即使正错误大于
负面错误。这在训练数据不平衡时很有用。
Softmax 函数族
tf.nn.softmax_cross_entropy_with_logits
(在 1.5 中已弃用)
tf.nn.softmax_cross_entropy_with_logits_v2
tf.losses.softmax_cross_entropy
tf.contrib.losses.softmax_cross_entropy
(已弃用)
这些损失函数应该用于多项互斥分类,
即从N
类中选择一个。也适用于N = 2
。
标签必须是 one-hot 编码或可以包含软类概率: 一个特定的例子可以以 50% 的概率属于 A 类和 B 类 有 50% 的概率。请注意,严格来说,这并不意味着 它属于这两类,但可以这样解释概率。
就像在sigmoid
家庭中一样,tf.losses.softmax_cross_entropy
允许
设置批量权重,即让一些示例比其他示例更重要。
据我所知,从 tensorflow 1.3 开始,没有内置的方法来设置 类权重。
[UPD] 在 tensorflow 1.5 中,v2
版本 was introduced 和原始的 softmax_cross_entropy_with_logits
损失已被弃用。它们之间的唯一区别是,在较新的版本中,反向传播会同时发生在 logits 和标签中(here's a discussion 为什么这可能有用)。
稀疏函数族
tf.nn.sparse_softmax_cross_entropy_with_logits
tf.losses.sparse_softmax_cross_entropy
tf.contrib.losses.sparse_softmax_cross_entropy
(已弃用)
和上面普通的softmax
一样,这些损失函数应该用于
多项互斥分类,即从N
类中选择一个。
区别在于标签编码:类被指定为整数(类索引),
不是单热向量。显然,这不允许软类,但它
当有数千或数百万个类时,可以节省一些内存。
但是,请注意 logits
参数仍然必须包含每个类的 logits,
因此它至少消耗[batch_size, classes]
内存。
和上面一样,tf.losses
版本有一个weights
参数,它允许
设置批量权重。
采样的 softmax 函数族
tf.nn.sampled_softmax_loss
tf.contrib.nn.rank_sampled_softmax_loss
tf.nn.nce_loss
这些函数为处理大量类提供了另一种选择。 他们不是计算和比较精确的概率分布,而是计算 随机样本的损失估计。
参数weights
和biases
指定一个单独的全连接层
用于计算所选样本的 logits。
像上面一样,labels
不是 one-hot 编码,而是具有 [batch_size, num_true]
的形状。
抽样函数仅适用于训练。在测试的时候,建议
使用标准的softmax
损失(稀疏或单热)来获得实际分布。
另一个替代损失是tf.nn.nce_loss
,它执行噪声对比估计(如果您有兴趣,请参阅very detailed discussion)。我已将此函数包含在 softmax 系列中,因为 NCE 保证在极限内逼近 softmax。
【讨论】:
我可以要求澄清一下关于 sigmoid 交叉熵 (sigCE) 的问题吗?如果它同时解决N
二元分类任务,则为N = prod(output.shape)
,例如shape = [batch, examples, channels]; N = (batch * examples * channels)
?如果tf.losses
期望“logits”(网络的输出),我是否还应该返回概率以方便使用?你能看看***.com/questions/53612973/…【参考方案3】:
但是,对于 1.5 版,必须使用 softmax_cross_entropy_with_logits_v2
,而将其参数与 argument key=...
一起使用,例如
softmax_cross_entropy_with_logits_v2(_sentinel=None, labels=y,
logits=my_prediction, dim=-1, name=None)
【讨论】:
以上是关于TensorFlow中如何选择交叉熵损失?的主要内容,如果未能解决你的问题,请参考以下文章
Keras 和 TensorFlow 中所有这些交叉熵损失之间有啥区别?
实现二元交叉熵损失给出了与 Tensorflow 不同的答案
交叉熵函数(Cross Entropy)与均方误差损失函数(MSE)对比?为什么选择交叉熵函数?
如何使用 sparse_softmax_cross_entropy_with_logits 在张量流中实现加权交叉熵损失
具有对数损失的 TensorFlow 单 sigmoid 输出与具有稀疏 softmax 交叉熵损失的两个线性输出,用于二进制分类