什么是logits,softmax和softmax_cross_entropy_with_logits?


350

我正在这里浏览tensorflow API文档。在tensorflow文档中,他们使用了名为的关键字logits。它是什么?API文档中的许多方法都将其编写为

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

如果写的是什么是那些logitsTensors,为什么保持一个不同的名称,如logits

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

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

它们之间有什么区别?这些文档对我来说还不清楚。我知道是什么tf.nn.softmax呢。但是没有其他。一个例子将非常有帮助。

Answers:


426

Logits只是意味着函数在较早的图层的未缩放输出上运行,并且理解单位的相对缩放是线性的。特别是,这意味着输入的总和可能不等于1,这意味着值不是概率(输入可能为5)。

tf.nn.softmax仅产生将softmax函数应用于输入张量的结果。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,5]张量的输出是一定形状的[2,1](将第一维视为批处理)。

如果要进行优化以最小化交叉熵,并且要在最后一层之后进行软最大化,则应使用tf.nn.softmax_cross_entropy_with_logits而不是自己进行处理,因为它以数学上正确的方式涵盖了数值不稳定的拐角情况。否则,您最终会在这里和那里添加少量epsilon,从而对其进行破解。

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


1
关于so​​ftmax_cross_entropy_with_logits,我不知道我是否正确使用它。结果在我的代码中不稳定。相同的代码运行两次,总精度从0.6更改为0.8。cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.nn.softmax(tf.add(tf.matmul(x,W),b)),y) cost=tf.reduce_mean(cross_entropy)。但是当我使用另一种方法时,pred=tf.nn.softmax(tf.add(tf.matmul(x,W),b)) cost =tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))结果是稳定且更好的。
里达(Rida)

15
在第一行中,您正在两次实现软最大化。softmax_cross_entropy_with_logits需要未缩放的logits,而不是tf.nn.softmax的输出。您只需要tf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W, b))您的情况。
dga

7
@dga我认为您的代码中有错别字,b需要放在括号之外,tf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W), b)
jrieke

1
“了解单位的相对比例是线性的”是什么?您第一句话的一部分是什么意思?
查理·帕克

5
赞成-但当您说“ softmax的输出形状与输入的形状相同-只是将值归一化”时,您的答案就略有错误。Softmax不仅会“压缩”值,使它们的总和等于1,还会重新分配它们,这可能是使用它的主要原因。请参阅stackoverflow.com/questions/17187507/…,尤其是Piotr Czapla的答案。
保罗·佩罗塔

282

简洁版本:

假设您有两个张量,其中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函数,该函数将输入解释为归一化的对数概率(aka 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输出在说什么很重要。下面我显示了一个表格,可以更清楚地表示上面的输出。可以看出,例如,训练实例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的真实标签为“ 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?我们可以使用交叉熵损失来测量误差。

交叉熵损失的公式

我们可以逐行计算交叉熵损失并查看结果。在下面我们可以看到训练实例1的损失为0.479,而训练实例2的损失为1.200。该结果之所以有意义,是因为在上面的示例中y_hat_softmax,训练实例1的最高机率是“类别2”,它与中的训练实例1相匹配y_true;但是,针对训练实例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()


我确认以上所有内容。简单的代码:M = tf.random.uniform([100, 10], minval=-1.0, maxval=1.0); labels = tf.one_hot(tf.random.uniform([100], minval=0, maxval=10 , dtype='int32'), 10); tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=M) - tf.reduce_sum(-tf.nn.log_softmax(M)*tf.one_hot(labels, 10), -1)到处都返回接近于零的值
Sami A. Haija,

51

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

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

logits是模型输出的未归一化对数概率(将softmax归一化之前对它们输出的值)。


2
我知道了。为什么不调用函数tf.nn.softmax_cross_entropy_sans_normalization?
auro

8
@auro,因为它在交叉熵计算过程中(内部)对值进行了归一化。的重点tf.nn.softmax_cross_entropy_with_logits是评估模型与金标的偏离程度,而不是提供标准化输出。
erickrf

1
在使用tf.nn.sparse_softmax_cross_entropy_with_logits()的情况下,计算稀疏softmax层的成本,因此,仅在训练期间使用该模型时,才可以对新数据运行模型,是否有可能从中获得概率一。
SerialDev

2
@SerialDev,不可能从中获得概率tf.nn.sparse_softmax_cross_entropy_with_logits。要获得概率,请使用tf.nn.softmax
Nandeesh

4

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

除此之外,Tensorflow还优化了应用激活函数的操作,然后使用其自身的激活以及成本函数来计算成本。因此,它是一个很好的做法,使用:tf.nn.softmax_cross_entropy()tf.nn.softmax(); tf.nn.cross_entropy()

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


1
上面的答案显然没有读过这个问题。.他们都说相同的东西,众所周知,但是并没有回答问题本身
Euler_Salter

@abhish你的意思是,tf.nn.softmax其次是tf.losses.softmax_cross_entropy
ankurrc

4

曾经发生过的softmax就是logit,这就是J. Hinton一直在Coursera视频中重复的内容。


1

Tensorflow 2.0兼容答案:的解释dga,并stackoverflowuser2010有很详细的关于Logits和相关的功能。

所有这些功能Tensorflow 1.x都可以正常使用,但是如果您从1.x (1.14, 1.15, etc)2.x (2.0, 2.1, etc..),则使用这些功能会导致错误。

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

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的更多信息,请参阅此迁移指南


0

我肯定要强调的一件事是logit仅仅是原始输出,通常是最后一层的输出。这也可以是负值。如果我们将其用于“交叉熵”评估,如下所述:

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

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

这是我的理解,如果我错了,请纠正我。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.