В чем разница между сигмоидом, за которым следует перекрестная энтропия, и sigmoid_cross_entropy_with_logits в TensorFlow?

При попытке получить кросс-энтропию с помощью сигмовидной функции активации существует разница между

  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)

person D.S.H.J    schedule 19.09.2017    source источник


Ответы (2)


Вы путаете кросс-энтропию для двоичных и многоклассовых задач.

Мультиклассовая кросс-энтропия

Формула, которую вы используете, верна и напрямую соответствует tf.nn.softmax_cross_entropy_with_logits:

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

Ожидается, что 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]

Обратите внимание, что q вычисляет tf.nn.softmax, т. Е. Выводит распределение вероятностей. Таким образом, это все еще формула кросс-энтропии для нескольких классов, только для N = 2.

Бинарная кросс-энтропия

На этот раз правильная формула

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

Хотя математически это частный случай мультиклассового случая, значение p и q различается. В простейшем случае каждый p и q - это число, соответствующее вероятности класса A.

Важно: пусть вас не путают общие p * -tf.log(q) часть и сумма. Предыдущий p был горячим вектором, теперь это число, ноль или единица. То же самое для q - это было распределение вероятностей, теперь это число (вероятность).

Если p является вектором, каждый отдельный компонент считается независимой двоичной классификацией. См. этот ответ, в котором описывается разница между softmax и сигмоидными функциями в тензорном потоке. Таким образом, определение p = [0, 0, 0, 1, 0] означает не один горячий вектор, а 5 различных функций, 4 из которых выключены, а 1 включена. Определение q = [0.2, 0.2, 0.2, 0.2, 0.2] означает, что каждая из 5 функций включена с вероятностью 20%.

Это объясняет использование функции sigmoid перед перекрестной энтропией: ее цель - сжать логит до [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 является только частью кросс-энтропии, поэтому он содержит правильное значение только тогда, когда p равно 1:

[[ 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=1 не имеет смысла в этой настройке, хотя это была бы допустимая формула в случае нескольких классов.

person Maxim    schedule 11.11.2017
comment
logit_q может быть любым от -infinity до + infinity. Я думаю, то, как вы делаете логит, чтобы он выглядел как вероятность, немного ошибочен? - person LKS; 20.02.2018
comment
Логит - это логарифмическая вероятность, никогда не говорилось, что это похоже на вероятность. - person Maxim; 20.02.2018
comment
Я не пытаюсь сказать, что это ошибка. Конечно, вы никогда не утверждаете, что это вероятность. Логит может быть любым числом, но выбор значения [0,2,0,8] вводит в заблуждение. Кстати, я думаю, что логит обычно интерпретируется как логарифм, где шансы = p/(1-p), где p интерпретируется как вероятность? - person LKS; 20.02.2018
comment
Я понимаю что ты имеешь ввиду. Этот вариант просто соответствует logit_q из вопроса. Но ты прав, это может быть что угодно. И вы тоже правы, было бы точнее назвать это логарифмическими шансами, но люди также говорят, что логарифмическая вероятность означает то же самое. - person Maxim; 20.02.2018
comment
Я предполагаю, что человек, который задает вопрос, может быть в нескольких местах сбит с толку. Спасибо за Ваш ответ. Это также развеивает мои сомнения по поводу tf.nn.sigmoid_cross_entropy_with_logits. - person LKS; 20.02.2018
comment
Во время обучения для случая с несколькими метками правильно ли использовать в качестве потерь для минимизации суммы по оси = 1 вектора tf.nn.sigmoid_cross_entropy_with_logits? - person guik; 22.02.2018
comment
Да, на самом деле принято сводить его к среднему по всем осям. - person Maxim; 22.02.2018
comment
@maxim, ты можешь попробовать это? stackoverflow .com / questions / 53612973 / - person SumNeuron; 04.12.2018

вы можете понять разницу между softmax и сигмовидной перекрестной энтропией следующим образом:

  1. для кросс-энтропии softmax фактически имеет одно распределение вероятностей
  2. для сигмовидной перекрестной энтропии он фактически имеет несколько независимых бинарных распределений вероятностей, каждое бинарное распределение вероятностей можно рассматривать как распределение вероятностей двух классов

так или иначе перекрестная энтропия:

   p * -tf.log(q)

для кросс-энтропии softmax это выглядит точно так же, как формула выше ,

но для сигмовидной формы она выглядит немного иначе, поскольку она имеет мультибинарное распределение вероятностей для каждого бинарного распределения вероятностей, это

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

p и (1-p) вы можете рассматривать как вероятность двух классов в каждом двоичном распределении вероятностей

person zhao yufei    schedule 21.11.2020