Tensorflow sigmoid和cross entropy vs sigmoid_cross_entropy_with_logits

时间:2017-09-19 03:23:43

标签: machine-learning tensorflow classification 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)
  3. 但是当使用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)
    

2 个答案:

答案 0 :(得分:61)

您对二进制多类问题的交叉熵感到困惑。

多级交叉熵

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

-tf.reduce_sum(p * tf.log(q), axis=1)
预计

pq是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]

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

二进制交叉熵

这次正确的公式是

p * -tf.log(q) + (1 - p) * -tf.log(1 - q)

虽然在数学上它是多类案例的部分案例,但pq含义却不同。在最简单的情况下,每个pq都是一个数字,对应于A类的概率。

重要:不要对常见的p * -tf.log(q)部分和总和感到困惑。上一个p是一个单热矢量,现在它是一个数字,零或一个。同样适用于q - 这是一个概率分布,现在它是一个数字(概率)。

如果p是向量,则每个单独的组件都被视为独立的二进制分类。参见this answer,其中概述了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))

您应该看到最后三个张量相等,而prob1只是交叉熵的一部分,所以只有当p1时才包含正确的值:< / p>

[[ 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]]

现在应该清楚的是,在-p * tf.log(q)axis=1private static List<Team> _teams = new ArrayList<>(); public static void main (String[] args) { final List<User> allUsers = Arrays.asList( new User("Lily",1), new User("Kecia",2), new User("Tanika",3), new User("Julieta",4), new User("Alla",5), new User("Pennie",6), new User("Anna",7), new User("Mohammad",8), new User("John",9) ); Collections.shuffle(allUsers); makeTeams(allUsers); } public static void makeTeams(List<User> users) { if (users.size() > 9) { //here } else { User first = users.get(0); User sec = users.get(1); Team team = new Team(first,sec); first.setTeam(team); sec.setTeam(team); for (User user : users) { if (team.getUsers().contains(user)) continue; team.add(user); user.setTeam(team); } _teams.add(team); } _teams.forEach(System.out::println); } 之间的总和在这个设置中没有意义,尽管它在多类情况下是一个有效的公式

答案 1 :(得分:0)

您可以通过以下方式了解softmax与S型交叉熵之间的差异:

  1. 对于softmax交叉熵,它实际上具有一个概率分布
  2. 对于S形交叉熵,它实际上具有多个独立的二元概率分布,每个二元概率分布都可以视为两类概率分布

所以反熵是:

   p * -tf.log(q)

对于softmax交叉熵,它看起来与上述公式完全相同,

但是对于S形来说,它看起来有点不同,因为它具有多二进制概率分布 对于每个二元概率分布,它是

p * -tf.log(q)+(1-p) * -tf.log(1-q)

p和(1-p)可以视为每个二元概率分布内的两类概率