Tensorflow sigmoid和cross entropy vs sigmoid_cross_entropy_with_logits

D.S*_*H.J 45 classification machine-learning tensorflow cross-entropy sigmoid

当试图用sigmoid激活函数得到交叉熵时,两者之间存在差异

  1. loss1 = -tf.reduce_sum(p*tf.log(q), 1)
  2. loss2 = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=p, logits=logit_q),1)

但是当使用softmax激活功能时,它们是相同的.

以下是示例代码:

import tensorflow as tf

sess2 = tf.InteractiveSession()
p = tf.placeholder(tf.float32, shape=[None, 5])
logit_q = tf.placeholder(tf.float32, shape=[None, 5])
q = tf.nn.sigmoid(logit_q)
sess.run(tf.global_variables_initializer())

feed_dict = {p: [[0, 0, 0, 1, 0], [1,0,0,0,0]], logit_q: [[0.2, 0.2, 0.2, 0.2, 0.2], [0.3, 0.3, 0.2, 0.1, 0.1]]}
loss1 = -tf.reduce_sum(p*tf.log(q),1).eval(feed_dict)
loss2 = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=p, logits=logit_q),1).eval(feed_dict)

print(p.eval(feed_dict), "\n", q.eval(feed_dict))
print("\n",loss1, "\n", loss2)
Run Code Online (Sandbox Code Playgroud)

Max*_*xim 71

对于二元多类问题,你会混淆交叉熵.

多类交叉熵

您使用的公式是正确的,它直接对应于tf.nn.softmax_cross_entropy_with_logits:

-tf.reduce_sum(p * tf.log(q), axis=1)
Run Code Online (Sandbox Code Playgroud)

p并且q预计是N类的概率分布.特别是,N可以是2,如下例所示:

p = tf.placeholder(tf.float32, shape=[None, 2])
logit_q = tf.placeholder(tf.float32, shape=[None, 2])
q = tf.nn.softmax(logit_q)

feed_dict = {
  p: [[0, 1],
      [1, 0],
      [1, 0]],
  logit_q: [[0.2, 0.8],
            [0.7, 0.3],
            [0.5, 0.5]]
}

prob1 = -tf.reduce_sum(p * tf.log(q), axis=1)
prob2 = tf.nn.softmax_cross_entropy_with_logits(labels=p, logits=logit_q)
print(prob1.eval(feed_dict))  # [ 0.43748799  0.51301527  0.69314718]
print(prob2.eval(feed_dict))  # [ 0.43748799  0.51301527  0.69314718]
Run Code Online (Sandbox Code Playgroud)

注意,这q是计算tf.nn.softmax,即输出概率分布.所以它仍然是多类交叉熵公式,仅适用于N = 2.

二进制交叉熵

这次是正确的公式

p * -tf.log(q) + (1 - p) * -tf.log(1 - q)
Run Code Online (Sandbox Code Playgroud)

虽然数学上它是多类案件的部分情况下,意义pq是不同的.在最简单的情况下,每个pq是一个数,对应于类A的概率

重要提示:不要对共同p * -tf.log(q)部分和总和感到困惑.以前p是一个单热矢量,现在它是一个数字,零或一个.同样的q- 它是一个概率分布,现在是一个数字(概率).

如果p是向量,则每个单独的组件被视为独立的二进制分类.请参阅此答案,其中概述了tensorflow中softmax和sigmoid函数之间的区别.因此,定义p = [0, 0, 0, 1, 0]并不意味着单热矢量,而是5个不同的特征,其中4个是关闭的,1个是打开的.该定义q = [0.2, 0.2, 0.2, 0.2, 0.2]意味着5个特征中的每一个都具有20%的概率.

这解释了sigmoid在交叉熵之前使用函数:它的目标是将logit压缩到[0, 1]间隔.

上面的公式仍然适用于多个独立的功能,这正是tf.nn.sigmoid_cross_entropy_with_logits计算:

p = tf.placeholder(tf.float32, shape=[None, 5])
logit_q = tf.placeholder(tf.float32, shape=[None, 5])
q = tf.nn.sigmoid(logit_q)

feed_dict = {
  p: [[0, 0, 0, 1, 0],
      [1, 0, 0, 0, 0]],
  logit_q: [[0.2, 0.2, 0.2, 0.2, 0.2],
            [0.3, 0.3, 0.2, 0.1, 0.1]]
}

prob1 = -p * tf.log(q)
prob2 = p * -tf.log(q) + (1 - p) * -tf.log(1 - q)
prob3 = p * -tf.log(tf.sigmoid(logit_q)) + (1-p) * -tf.log(1-tf.sigmoid(logit_q))
prob4 = tf.nn.sigmoid_cross_entropy_with_logits(labels=p, logits=logit_q)
print(prob1.eval(feed_dict))
print(prob2.eval(feed_dict))
print(prob3.eval(feed_dict))
print(prob4.eval(feed_dict))
Run Code Online (Sandbox Code Playgroud)

您应该看到的是,过去三年张量是相等的,而prob1仅仅是交叉熵的一部分,所以它仅包含正确的值时p1:

[[ 0.          0.          0.          0.59813893  0.        ]
 [ 0.55435514  0.          0.          0.          0.        ]]
[[ 0.79813886  0.79813886  0.79813886  0.59813887  0.79813886]
 [ 0.5543552   0.85435522  0.79813886  0.74439669  0.74439669]]
[[ 0.7981388   0.7981388   0.7981388   0.59813893  0.7981388 ]
 [ 0.55435514  0.85435534  0.7981388   0.74439663  0.74439663]]
[[ 0.7981388   0.7981388   0.7981388   0.59813893  0.7981388 ]
 [ 0.55435514  0.85435534  0.7981388   0.74439663  0.74439663]]
Run Code Online (Sandbox Code Playgroud)

现在应该很清楚,服用的总和-p * tf.log(q)沿着axis=1没有意义在此设置,虽然它会在多类情况下的有效配方.

  • logit_q可以是从-infinity到+ infinity的任何东西.我猜你使logit看起来像概率的方式有点误导? (12认同)
  • 我并不是要说有一个错误。当然,您永远不会说这是一个可能性。Logit可以是任何数字,但仅选择它们为[0.2,0.8]会使它产生误导。顺便说一句,我认为对数通常被解释为对数奇数,其中赔率=`p /(1-p)`,其中`p`被解释为概率? (2认同)