初步事实
在功能意义上,sigmoid 是 softmax 函数的部分情况,当类的数量等于 2 时。它们都执行相同的操作:将 logits(见下文)转换为概率。
在简单的二元分类中,两者之间没有太大区别,但是在多项分类的情况下,sigmoid 允许处理非排他性标签(又名多标签),而 softmax 处理排他类(见下文)。
在计算概率之前,logit(也称为分数)是与 class 关联的原始未缩放值。就神经网络架构而言,这意味着 logit 是密集(全连接)层的输出。
Tensorflow 的命名有点奇怪:下面的所有函数都接受 logits,而不是 probabilities,并自己应用转换(这更有效)。
Sigmoid 函数族
如前所述,sigmoid
损失函数用于二元分类。但是当类是独立的时,张量流函数更通用并且允许进行多标签分类。换句话说,一次tf.nn.sigmoid_cross_entropy_with_logits
解决N
二进制分类。
标签必须是一次性编码的,或者可以包含软类概率。
tf.losses.sigmoid_cross_entropy
此外允许设置批量权重,即使某些示例比其他示例更重要。
tf.nn.weighted_cross_entropy_with_logits
允许设置类权重
(记住,分类是二元的),即使正错误大于负错误。这在训练数据不平衡时很有用。
Softmax 函数族
这些损失函数应该用于多项互斥分类,即从N
类中挑选一个。时也适用N = 2
。
标签必须是 one-hot 编码或可以包含软类概率:特定示例可以以 50% 的概率属于 A 类,以 50% 的概率属于 B 类。请注意,严格来说,这并不意味着它属于两个类,但可以这样解释概率。
就像在sigmoid
家庭中一样,tf.losses.softmax_cross_entropy
允许设置批量权重,即使某些示例比其他示例更重要。据我所知,从 tensorflow 1.3 开始,没有内置的方法来设置类 weights。
[UPD]在 tensorflow 1.5 中,引入v2
了版本并且不推荐使用原始损失。它们之间的唯一区别是,在较新的版本中,反向传播同时发生在 logits 和标签中(这里讨论了为什么这可能有用)。softmax_cross_entropy_with_logits
稀疏函数族
像softmax
上面普通的一样,这些损失函数应该用于多项互斥分类,即从N
类中挑选一个。区别在于标签编码:类被指定为整数(类索引),而不是 one-hot 向量。显然,这不允许软类,但是当有数千或数百万个类时,它可以节省一些内存。但是,请注意,logits
参数仍然必须包含每个类的 logits,因此它至少会消耗[batch_size, classes]
内存。
像上面一样,tf.losses
版本有一个weights
参数允许设置批量权重。
采样的 softmax 函数族
这些函数为处理大量类提供了另一种选择。他们不是计算和比较精确的概率分布,而是从随机样本中计算损失估计。
参数weights
并biases
指定一个单独的全连接层,用于计算所选样本的 logits。
像上面一样,labels
不是 one-hot 编码,而是具有形状[batch_size, num_true]
.
采样函数仅适用于训练。在测试时,建议使用标准softmax
损失(稀疏或单热)来获得实际分布。
另一种替代损失是tf.nn.nce_loss
,它执行噪声对比估计(如果您有兴趣,请参阅这个非常详细的讨论)。我已将此函数包含在 softmax 系列中,因为 NCE 保证在限制范围内逼近 softmax。