什么是逻辑? softmax 和 softmax_cross_entropy_with_logits 有什么区别?

What are logits? What is the difference between softmax and softmax_cross_entropy_with_logits?

tensorflow API docs 中,他们使用了一个名为 logits 的关键字。它是什么?很多方法都是这样写的:

tf.nn.softmax(logits, name=None)

如果 logits 只是一个通用的 Tensor 输入,为什么它被命名为 logits


其次,下面两种方法有什么区别?

tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

我知道 tf.nn.softmax 的作用,但不知道另一个。一个例子会很有帮助。

softmax+logits 只是意味着该函数对较早层的未缩放输出进行操作,并且理解单位的相对比例是线性的。特别是,这意味着输入的总和可能不等于 1,即值是 而不是 的概率(您的输入可能为 5)。在内部,它首先将 softmax 应用于未缩放的输出,然后计算这些值与标签定义的“应该”值的交叉熵。

tf.nn.softmax 产生将 softmax function 应用于输入张量的结果。 softmax“挤压”输入使得 sum(input) = 1,它通过将输入解释为对数概率 (logits) 然后将它们转换回 0 到 1 之间的原始概率来进行映射。 softmax与输入相同:

a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508  0.205666    0.25120102  0.37474789]]

请参阅 this answer 了解为什么 softmax 在 DNN 中被广泛使用的更多信息。

tf.nn.softmax_cross_entropy_with_logits 在应用 softmax 函数后将 softmax 步骤与交叉熵损失的计算相结合,但它以一种更数学上谨慎的方式将它们结合在一起。它类似于以下结果:

sm = tf.nn.softmax(x)
ce = cross_entropy(sm)

交叉熵是一个汇总指标:它对所有元素求和。 tf.nn.softmax_cross_entropy_with_logits 在形状 [2,5] 张量上的输出是形状 [2,1](第一个维度被视为批处理)。

如果你想做优化以最小化交叉熵 AND 你在最后一层之后进行 softmaxing,你应该使用 tf.nn.softmax_cross_entropy_with_logits 而不是自己做,因为它以数学上正确的方式涵盖了数值上不稳定的极端情况。否则,您最终会通过在各处添加小 epsilon 来破解它。

2016-02-07 编辑: 如果您有单个 class 标签,其中一个对象只能属于一个 class,您现在可以考虑使用 tf.nn.sparse_softmax_cross_entropy_with_logits,这样您就不必将标签转换为密集单热阵列。此功能是0.6.0版本后添加的

tf.nn.softmax 计算通过 softmax 层的前向传播。当您计算模型输出的概率时,您可以在模型的 评估 期间使用它。

tf.nn.softmax_cross_entropy_with_logits 计算 softmax 层的成本。它仅在 训练 期间使用。

logits 是 未规范化的对数概率 输出模型(应用 softmax 规范化之前输出的值)。

短版:

假设您有两个张量,其中 y_hat 包含每个 class 的计算得分(例如,来自 y = W*x +b)并且 y_true 包含单热编码的真实标签。

y_hat  = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded

如果您将 y_hat 中的分数解释为非标准化对数概率,则它们是 logits.

此外,以这种方式计算的总交叉熵损失:

y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))

本质上等同于用函数softmax_cross_entropy_with_logits():

计算的总交叉熵损失
total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))

长版:

在神经网络的输出层,您可能会计算一个数组,其中包含每个训练实例的 class 分数,例如来自计算 y_hat = W*x + b 的分数。作为示例,下面我创建了一个 y_hat 作为 2 x 3 数组,其中行对应于训练实例,列对应于 classes。所以这里有 2 个训练实例和 3 个 classes.

import tensorflow as tf
import numpy as np

sess = tf.Session()

# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5,  1.5,  0.1],
#        [ 2.2,  1.3,  1.7]])

请注意,这些值未标准化(即行加起来不等于 1)。为了对它们进行归一化,我们可以应用 softmax 函数,它将输入解释为非归一化的对数概率(又名 logits)并输出归一化的线性概率。

y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863  ,  0.61939586,  0.15274114],
#        [ 0.49674623,  0.20196195,  0.30129182]])

充分理解 softmax 输出的含义很重要。下面我显示了一个 table 更清楚地表示上面的输出。可以看出,例如训练实例1为"Class 2"的概率为0.619。每个训练实例的 class 概率被归一化,因此每行的总和为 1.0。

                      Pr(Class 1)  Pr(Class 2)  Pr(Class 3)
                    ,--------------------------------------
Training instance 1 | 0.227863   | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182

所以现在我们有每个训练实例的 class 概率,我们可以在其中使用每行的 argmax() 来生成最终的 class 化。从上面,我们可以生成训练实例 1 属于 "Class 2",训练实例 2 属于 "Class 1"。

这些 class说明是否正确?我们需要根据训练集中的真实标签进行测量。您将需要一个单热编码的 y_true 数组,其中行再次是训练实例,列是 classes。下面我创建了一个示例 y_true one-hot 数组,其中训练实例 1 的真实标签是 "Class 2",训练实例 2 的真实标签是 "Class 3".

y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0.,  1.,  0.],
#        [ 0.,  0.,  1.]])

y_hat_softmax中的概率分布是否接近y_true中的概率分布?我们可以用cross-entropy loss来衡量误差。

我们可以逐行计算交叉熵损失并查看结果。下面我们可以看到训练实例 1 的损失为 0.479,而训练实例 2 的损失更高,为 1.200。这个结果是有道理的,因为在我们上面的例子中,y_hat_softmax 表明训练实例 1 的最高概率是 "Class 2",这与 y_true 中的训练实例 1 匹配;然而,训练实例 2 的预测显示 "Class 1" 的概率最高,这与真实的 class "Class 3".

不匹配
loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 ,  1.19967598])

我们真正想要的是所有训练实例的总损失。所以我们可以计算:

total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944

使用softmax_cross_entropy_with_logits()

我们可以使用 tf.nn.softmax_cross_entropy_with_logits() 函数来计算总交叉熵损失,如下所示。

loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 ,  1.19967598])

total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922

请注意,total_loss_1total_loss_2 产生的结果基本相同,只是在最后的数字上有一些细微差别。但是,您也可以使用第二种方法:它减少了一行代码并且累积了更少的数值误差,因为 softmax 是在 softmax_cross_entropy_with_logits().

内部为您完成的

以上答案对所提问题有足够的描述。

除此之外,Tensorflow 优化了应用激活函数然后使用其自身的激活计算成本的操作,然后是成本函数。因此,最好使用:tf.nn.softmax_cross_entropy() over tf.nn.softmax(); tf.nn.cross_entropy()

您可以在资源密集型模型中发现它们之间的显着差异。

Tensorflow 2.0 Compatible Answer: dgaWhosebuguser2010的解释很详细,关于Logits和相关函数。

所有这些函数在 Tensorflow 1.x 中使用时都可以正常工作,但是如果您将代码从 1.x (1.14, 1.15, etc)2.x (2.0, 2.1, etc..),使用这些函数会导致错误。

因此,为了社区的利益,如果我们从 1.x to 2.x 迁移,请为我们上面讨论的所有功能指定 2.0 兼容调用。

1.x中的函数:

  1. tf.nn.softmax
  2. tf.nn.softmax_cross_entropy_with_logits
  3. tf.nn.sparse_softmax_cross_entropy_with_logits

从1.x迁移到2.x时的各自功能:

  1. tf.compat.v2.nn.softmax
  2. tf.compat.v2.nn.softmax_cross_entropy_with_logits
  3. tf.compat.v2.nn.sparse_softmax_cross_entropy_with_logits

有关从 1.x 迁移到 2.x 的更多信息,请参阅此 Migration Guide

还有一件事我绝对想强调,因为 logit 只是原始输出,通常是最后一层的输出。这也可以是负值。如果我们按原样使用它进行 "cross entropy" 评估,如下所述:

-tf.reduce_sum(y_true * tf.log(logits))

那就不行了。由于未定义 -ve 的日志。 所以使用 o softmax 激活,将克服这个问题。

这是我的理解,如有错误请指正

学期的数学动机

当我们希望将输出约束在 0 和 1 之间,但我们的模型架构输出不受约束的值时,我们可以添加规范化层来强制执行此操作。

一个常见的选择是 sigmoid 函数。1 在二进制 classification 中,这通常是逻辑函数,在 multi-class 任务多项逻辑函数 (a.k.a softmax).2

如果我们想将新的最后一层的输出解释为 'probabilities',那么(暗示)我们的 sigmoid 的无约束输入必须是 inverse-sigmoid(概率)。在逻辑案例中,这相当于我们概率的 log-odds(即 odds) a.k.a. logit:

的对数

这就是为什么 softmax 的参数在 Tensorflow 中被称为 logits - 因为假设 softmax 是模型中的最后一层,并且输出 p被解释为概率,该层的输入x被解释为logit:

广义术语

在机器学习中,倾向于概括从 maths/stats/computer 科学中借用的术语,因此在 Tensorflow 中 logit(通过类比)被用作许多规范化函数的输入的同义词。


  1. 虽然它具有易于区分和上述概率解释等良好特性,但它有点 arbitrary
  2. softmax 可能更准确地称为 softargmax,因为它是 smooth approximation of the argmax function.