Расчет кросс-энтропии в TensorFlow

Мне сложно вычислить кросс-энтропию в тензорном потоке. В частности, я использую функцию:

tf.nn.softmax_cross_entropy_with_logits()

Используя, казалось бы, простой код, я могу заставить его вернуть только ноль.

import tensorflow as tf
import numpy as np

sess = tf.InteractiveSession()

a = tf.placeholder(tf.float32, shape =[None, 1])
b = tf.placeholder(tf.float32, shape = [None, 1])
sess.run(tf.global_variables_initializer())
c = tf.nn.softmax_cross_entropy_with_logits(
    logits=b, labels=a
).eval(feed_dict={b:np.array([[0.45]]), a:np.array([[0.2]])})
print c

возвращается

0

Я понимаю кросс-энтропию следующим образом:

H(p,q) = p(x)*log(q(x))

Где p (x) - истинная вероятность события x, а q (x) - предсказанная вероятность события x.

Там, если ввести любые два числа для p (x) и q (x), используются такие, что

0<p(x)<1 AND 0<q(x)<1

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


person David Kaftan    schedule 01.03.2017    source источник
comment
Итак, что интересно, я получил идею использования перекрестной энтропии из этого проекта: github .com / carpedm20 / DCGAN-tensorflow / blob / master / model.py они используют его, чтобы определить, получен ли образец из реального распределения. Однако кажется, что бинарная регрессия softmax - это то же самое, что и логистическая регрессия.   -  person David Kaftan    schedule 01.03.2017


Ответы (3)


Как говорится, вы не можете написать softmax_cross_entropy_with_logits без softmax. Softmax [0.45] равен [1], а log(1) равен 0.

Измеряет вероятность ошибки в задачах дискретной классификации, в которых классы являются взаимоисключающими (каждая запись находится ровно в одном классе). Например, каждое изображение CIFAR-10 помечено одной и только одной меткой: изображение может быть собакой или грузовиком, но не обоими сразу.

ПРИМЕЧАНИЕ. Хотя классы являются взаимоисключающими, их вероятности не обязательны. Все, что требуется, - это чтобы каждая строка labels представляла собой допустимое распределение вероятностей. В противном случае расчет градиента будет неправильным.

Если используется исключительный labels (в котором истинен только один и только один класс), см. sparse_softmax_cross_entropy_with_logits.

ПРЕДУПРЕЖДЕНИЕ. Эта операция ожидает немасштабированных логитов, так как для эффективности она выполняет softmax на logits внутренне. Не вызывайте эту операцию с выводом softmax, так как она даст неверные результаты.

logits и labels должны иметь одинаковую форму [batch_size, num_classes] и одинаковый dtype (float16, float32 или float64).

person Don Reba    schedule 01.03.2017
comment
Ага! Так что, похоже, мои проблемы вызваны неправильным пониманием softmax! Спасибо за помощь! - person David Kaftan; 01.03.2017
comment
@DavidKaftan, если это решит вашу проблему, было бы неплохо отметить это как принятый ответ. :) - person Don Reba; 01.03.2017
comment
Спасибо! Я (очевидно) новенький здесь! - person David Kaftan; 02.03.2017

В дополнение к ответу Дона (+1), этот ответ, написанный mrry, может вас заинтересовать, поскольку он дает формулу для расчета перекрестная энтропия в TensorFlow:

Альтернативный способ написать:

xent = tf.nn.softmax_cross_entropy_with_logits(logits, labels)

...было бы:

softmax = tf.nn.softmax(logits)
xent = -tf.reduce_sum(labels * tf.log(softmax), 1)

Однако эта альтернатива была бы (i) менее численно стабильной (поскольку softmax может вычислять гораздо большие значения) и (ii) менее эффективной (поскольку некоторые избыточные вычисления могли бы произойти в обратном распространении). Для реального использования мы рекомендуем использовать tf.nn.softmax_cross_entropy_with_logits().

person Franck Dernoncourt    schedule 01.03.2017
comment
Спасибо за формулу кросс-энтропии (no-softmax) - person alanwsx; 10.04.2017

Вот реализация в Tensorflow 2.0 на случай, если она понадобится кому-то еще (наверное, мне) в будущем.

@tf.function
def cross_entropy(x, y, epsilon = 1e-9):
    return -2 * tf.reduce_mean(y * tf.math.log(x + epsilon), -1) / tf.math.log(2.)

x = tf.constant([
    [1.0,0],
    [0.5,0.5],
    [.75,.25]
    ]
,dtype=tf.float32)

with tf.GradientTape() as tape:
    tape.watch(x)
    y = entropy(x, x)

tf.print(y)
tf.print(tape.gradient(y, x))

Выход

[-0 1 0.811278105]
[[-1.44269502 29.8973541]
 [-0.442695022 -0.442695022]
 [-1.02765751 0.557305]]
person Souradeep Nanda    schedule 08.09.2020