Сигмоид с тензорным потоком и кросс-энтропия против сигмоидального_кросса_энтропия_свит_лог
При попытке получить перекрестную энтропию с помощью функции активации сигмоидальной
loss1 = -tf.reduce_sum(p*tf.log(q), 1)
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 и сигмовидной перекрестной энтропией следующим образом:
- для кросс-энтропии softmax фактически имеет одно распределение вероятностей
- для сигмовидной перекрестной энтропии он фактически имеет несколько независимых бинарных распределений вероятностей, каждое бинарное распределение вероятностей можно рассматривать как распределение вероятностей двух классов
так что в любом случае перекрестная энтропия:
p * -tf.log(q)
для кросс-энтропии softmax это выглядит точно так же, как формула выше ,
но для сигмоида он выглядит немного иначе, поскольку он имеет мультибинарное распределение вероятностей для каждого бинарного распределения вероятностей, это
p * -tf.log(q)+(1-p) * -tf.log(1-q)
p и (1-p) вы можете рассматривать как вероятность двух классов в каждом двоичном распределении вероятностей