machine-learning tensorflow classification cross-entropy sigmoid

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

  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)

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.