什么是logits、softmax和softmax与logits的交叉熵?

2024-05-15 03:55:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我在看tensorflow API文档here。在tensorflow文档中,他们使用了一个名为logits的关键字。它是什么?在API文档中的许多方法中,它的编写方式如下

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

如果写的是那些logits只是Tensors,为什么要保留一个不同的名称,比如logits

另一件事是有两种方法我无法区分。他们是

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

他们之间有什么区别?我不清楚这些文件。我知道tf.nn.softmax做什么。但不是另一个。举个例子会很有帮助的。


Tags: 方法name文档名称noneapiheretf
3条回答

tf.nn.softmax计算通过softmax层的正向传播。当计算模型输出的概率时,可以在模型的求值过程中使用它。

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

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

短版本:

假设有两个张量,其中y_hat包含每个类的计算分数(例如,来自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))

长版本:

在神经网络的输出层中,您可能会计算一个数组,该数组包含每个训练实例的类分数,例如通过计算y_hat = W*x + b。作为一个例子,下面我创建了一个y_hat作为2 x 3数组,其中的行对应于训练实例,而列对应于类。这里有2个训练实例和3个课程。

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函数,该函数将输入解释为非规范化的对数概率(akalogits),并输出规范化的线性概率。

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输出的意思很重要。下面我展示了一个更清楚地表示上面输出的表。可以看出,例如,训练实例1成为“类2”的概率为0.619。每个训练实例的类概率是标准化的,因此每行的总和为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

现在我们有了每个训练实例的类概率,在这里我们可以取每一行的argmax()来生成最终的分类。由此,我们可以生成训练实例1属于“类2”,训练实例2属于“类1”。

这些分类正确吗?我们需要根据训练场的真实标签来衡量。您将需要一个单热编码的y_true数组,其中的行是训练实例,列是类。下面我创建了一个示例y_true一个热数组,其中训练实例1的真正标签是“类2”,训练实例2的真正标签是“类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来测量误差。

Formula for cross-entropy loss

我们可以按行计算交叉熵损失,并看到结果。下面我们可以看到训练实例1的损失为0.479,而训练实例2的损失更高,为1.200。这个结果是有意义的,因为在我们上面的例子中,y_hat_softmax显示训练实例1的最高概率是“类2”,它与y_true中的训练实例1匹配;然而,对训练实例2的预测显示了“类1”的最高概率,它与真正的类“类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()内为您完成的。

Logits简单地说,函数对早期层的未缩放输出进行操作,并且理解这些单位的相对比例是线性的。它特别意味着,输入的和可能不等于1,值是而不是概率(您可能有5个输入)。

tf.nn.softmax只生成对输入张量应用softmax function的结果。softmax“挤压”输入,以便sum(input) = 1:这是一种规范化的方法。softmax的输出形状与输入相同:它只是将值规格化。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]]

相比之下,tf.nn.softmax_cross_entropy_with_logits在应用softmax函数后计算结果的交叉熵(但它以一种更精确的数学方式一起计算)。其结果类似于:

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

交叉熵是一个总结性的度量:它在元素之间求和。形状张量上的tf.nn.softmax_cross_entropy_with_logits的输出是形状[2,1](第一维被视为批处理)。

如果要进行优化以最小化交叉熵在最后一层之后进行的软最大化,应该使用tf.nn.softmax_cross_entropy_with_logits而不是自己进行,因为它以数学上正确的方式覆盖了数值不稳定的角点情况。否则,你最终会在这里和那里添加一些epsilons来破解它。

编辑日期:2016-02-07: 如果只有一个类标签,其中一个对象只能属于一个类,那么现在可以考虑使用tf.nn.sparse_softmax_cross_entropy_with_logits,这样就不必将标签转换为密集的一个热数组。此函数是在0.6.0版之后添加的。

相关问题 更多 >

    热门问题