首页 文章

什么是logits,softmax和softmax_cross_entropy_with_logits?

提问于
浏览
259

我正在浏览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 的作用 . 但不是另一个 . 一个例子将非常有用 .

4 回答

  • 355

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

    tf.nn.softmax 仅产生将softmax function应用于输入张量的结果 . softmax "squishes"输入使 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)
    

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

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

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

  • 36

    Short version:

    假设您有两个张量,其中 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))
    

    Long version:

    在神经网络的输出层,您可能会计算一个数组,其中包含每个训练实例的类分数,例如来自计算 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函数,该函数将输入解释为非标准化的对数概率(又名 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 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来测量错误 .

    Formula for cross-entropy loss

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

    Using 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() 内为你完成的 .

  • 225

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

    tf.nn.softmax_cross_entropy_with_logits 计算softmax图层的成本 . 它仅在 training 期间使用 .

    logits是输出模型的非标准化日志概率(在softmax标准化应用于它们之前输出的值) .

  • 1

    以上答案对问题提出了足够的描述 .

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

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

相关问题