machine learning - Tensorflow sigmoide y entropía cruzada vs sigmoid_cross_entropy_with_logits
machine-learning classification (1)
Cuando se trata de obtener entropía cruzada con la función de activación sigmoidea, hay una diferencia entre
-
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)
Pero son iguales cuando con la función de activación softmax.
El siguiente es el código de muestra:
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)
Estás confundiendo la entropía cruzada para problemas binarios y multiclase .
Entropía cruzada multiclase
La fórmula que utiliza es correcta y corresponde directamente a
tf.nn.softmax_cross_entropy_with_logits
:
-tf.reduce_sum(p * tf.log(q), axis=1)
se espera que
q
sean distribuciones de probabilidad sobre N clases.
En particular, N puede ser 2, como en el siguiente ejemplo:
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]
Tenga en cuenta que
q
calcula
tf.nn.softmax
, es decir, genera una distribución de probabilidad.
Entonces todavía es una fórmula de entropía cruzada de clases múltiples, solo para N = 2.
Entropía cruzada binaria
Esta vez la fórmula correcta es
p * -tf.log(q) + (1 - p) * -tf.log(1 - q)
Aunque matemáticamente es un caso parcial del caso de múltiples clases, el
significado
de
p
y
q
es diferente.
En el caso más simple, cada
p
y
q
es un número, correspondiente a una probabilidad de la clase A.
Importante
: No se confunda con la parte común
p * -tf.log(q)
y la suma.
La
p
anterior era un vector de un solo hot, ahora es un número, cero o uno.
Lo mismo para
q
: era una distribución de probabilidad, ahora es un número (probabilidad).
Si
p
es un vector, cada componente individual se considera una
clasificación binaria independiente
.
Vea
esta respuesta
que describe la diferencia entre las funciones softmax y sigmoide en el tensorflow.
Entonces, la definición
p = [0, 0, 0, 1, 0]
no significa un vector único, sino 5 características diferentes, 4 de las cuales están apagadas y 1 está encendida.
La definición
q = [0.2, 0.2, 0.2, 0.2, 0.2]
significa que cada una de las 5 características está activada con un 20% de probabilidad.
Esto explica el uso de la función
sigmoid
antes de la entropía cruzada: su objetivo es aplastar el logit al intervalo
[0, 1]
.
La fórmula anterior aún es válida para múltiples características independientes, y eso es exactamente lo que calcula
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))
Debería ver que los últimos tres tensores son iguales, mientras que el
prob1
es solo una parte de la entropía cruzada, por lo que contiene el valor correcto solo cuando
p
es
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]]
Ahora debe quedar claro que tomar una suma de
-p * tf.log(q)
largo del
axis=1
no tiene sentido en esta configuración, aunque sería una fórmula válida en el caso de varias clases.