Сигмоид с тензорным потоком и кросс-энтропия против сигмоидального_кросса_энтропия_свит_лог

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

  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)

1 ответ

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

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

Формула, которую вы используете, является правильной и соответствует 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 число, соответствующее вероятности класса А.

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

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

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

так что в любом случае перекрестная энтропия:

   p * -tf.log(q)

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

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

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

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

Другие вопросы по тегам