¿Qué es logits, softmax y softmax_cross_entropy_with_logits?

351

Estaba revisando los documentos de la API de tensorflow aquí . En la documentación de tensorflow, usaron una palabra clave llamada logits. ¿Qué es? En muchos métodos en los documentos de API se escribe como

tf.nn.softmax(logits, name=None)

Si lo que está escrito es logitssolo Tensorseso, ¿por qué mantener un nombre diferente logits?

Otra cosa es que hay dos métodos que no pude diferenciar. Ellos eran

tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

Cuáles son las diferencias entre ellos? Los documentos no son claros para mí. Se lo que tf.nn.softmaxhace. Pero no el otro. Un ejemplo será realmente útil.

Shubhashis
fuente

Respuestas:

427

Logits simplemente significa que la función opera en la salida sin escala de capas anteriores y que la escala relativa para comprender las unidades es lineal. Significa, en particular, que la suma de las entradas puede no ser igual a 1, que los valores no son probabilidades (puede tener una entrada de 5).

tf.nn.softmaxproduce solo el resultado de aplicar la función softmax a un tensor de entrada. El softmax "aplasta" las entradas para que sum(input) = 1: sea una forma de normalización. La forma de salida de un softmax es la misma que la entrada: simplemente normaliza los valores. Las salidas de softmax pueden interpretarse como probabilidades.

a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508  0.205666    0.25120102  0.37474789]]

Por el contrario, tf.nn.softmax_cross_entropy_with_logitscalcula la entropía cruzada del resultado después de aplicar la función softmax (pero lo hace todo de una manera matemáticamente más cuidadosa). Es similar al resultado de:

sm = tf.nn.softmax(x)
ce = cross_entropy(sm)

La entropía cruzada es una métrica de resumen: suma a través de los elementos. La salida de tf.nn.softmax_cross_entropy_with_logitsun [2,5]tensor de forma es de forma [2,1](la primera dimensión se trata como el lote).

Si desea hacer una optimización para minimizar la entropía cruzada Y está haciendo softmaxing después de su última capa, debe usarla en tf.nn.softmax_cross_entropy_with_logitslugar de hacerlo usted mismo, porque cubre casos de esquina numéricamente inestables de la manera matemáticamente correcta. De lo contrario, terminarás hackeando agregando pequeños épsilons aquí y allá.

Editado el 07/02/2016: si tiene etiquetas de una sola clase, donde un objeto solo puede pertenecer a una clase, ahora puede considerar usarlo tf.nn.sparse_softmax_cross_entropy_with_logitspara no tener que convertir sus etiquetas en una matriz densa de un solo hot. Esta función se agregó después de la versión 0.6.0.

dga
fuente
1
Acerca de softmax_cross_entropy_with_logits, no sé si lo uso correctamente. El resultado no es tan estable en mi código. El mismo código se ejecuta dos veces, la precisión total cambia de 0.6 a 0.8. cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.nn.softmax(tf.add(tf.matmul(x,W),b)),y) cost=tf.reduce_mean(cross_entropy). Pero cuando uso otra forma, pred=tf.nn.softmax(tf.add(tf.matmul(x,W),b)) cost =tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))el resultado es estable y mejor.
Rida
15
Eres doble softmaxing en tu primera línea. softmax_cross_entropy_with_logits espera logits sin escala, no la salida de tf.nn.softmax. Solo quieres tf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W, b))en tu caso.
dga
77
@dga Creo que tiene un error tipográfico en su código, bdebe estar fuera del soporte,tf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W), b)
jrieke
1
¿Qué significa "que la escala relativa para comprender las unidades es lineal"? parte de tu primera oración significa?
Charlie Parker el
55
Votó a favor, pero su respuesta es ligeramente incorrecta cuando dice que "[l] a forma de salida de un softmax es la misma que la entrada, simplemente normaliza los valores". Softmax no solo "aplasta" los valores para que su suma sea igual a 1. También los redistribuye, y esa es posiblemente la razón principal por la que se usa. Consulte stackoverflow.com/questions/17187507/… , especialmente la respuesta de Piotr Czapla.
Paolo Perrotta
282

Version corta:

Suponga que tiene dos tensores, donde y_hatcontiene puntajes calculados para cada clase (por ejemplo, de y = W * x + b) y y_truecontiene etiquetas verdaderas codificadas en caliente.

y_hat  = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded

Si interpreta los puntajes y_hatcomo probabilidades de registro no normalizadas, entonces son logits .

Además, la pérdida total de entropía cruzada se calculó de esta manera:

y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))

es esencialmente equivalente a la pérdida total de entropía cruzada calculada con la función softmax_cross_entropy_with_logits():

total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))

Versión larga:

En la capa de salida de su red neuronal, probablemente calculará una matriz que contiene los puntajes de clase para cada una de sus instancias de entrenamiento, como a partir de un cálculo y_hat = W*x + b. Para servir de ejemplo, a continuación he creado una y_hatmatriz de 2 x 3, donde las filas corresponden a las instancias de entrenamiento y las columnas corresponden a las clases. Así que aquí hay 2 instancias de entrenamiento y 3 clases.

import tensorflow as tf
import numpy as np

sess = tf.Session()

# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5,  1.5,  0.1],
#        [ 2.2,  1.3,  1.7]])

Tenga en cuenta que los valores no están normalizados (es decir, las filas no suman 1). Para normalizarlos, podemos aplicar la función softmax, que interpreta la entrada como probabilidades de registro no normalizadas (también conocidas como logits ) y genera probabilidades lineales normalizadas.

y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863  ,  0.61939586,  0.15274114],
#        [ 0.49674623,  0.20196195,  0.30129182]])

Es importante comprender completamente lo que dice la salida softmax. A continuación, he mostrado una tabla que representa más claramente el resultado anterior. Se puede ver que, por ejemplo, la probabilidad de que la instancia de entrenamiento 1 sea "Clase 2" es 0.619. Las probabilidades de clase para cada instancia de entrenamiento están normalizadas, por lo que la suma de cada fila es 1.0.

                      Pr(Class 1)  Pr(Class 2)  Pr(Class 3)
                    ,--------------------------------------
Training instance 1 | 0.227863   | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182

Entonces, ahora tenemos probabilidades de clase para cada instancia de entrenamiento, donde podemos tomar el argumento argmax () de cada fila para generar una clasificación final. Desde arriba, podemos generar que la instancia de entrenamiento 1 pertenece a "Clase 2" y la instancia de entrenamiento 2 pertenece a "Clase 1".

¿Son correctas estas clasificaciones? Necesitamos medir contra las verdaderas etiquetas del conjunto de entrenamiento. Necesitará una y_truematriz codificada en caliente , donde nuevamente las filas son instancias de entrenamiento y las columnas son clases. A continuación, he creado un ejemplo de y_trueuna matriz activa donde la etiqueta verdadera para la instancia de entrenamiento 1 es "Clase 2" y la etiqueta verdadera para la instancia de entrenamiento 2 es "Clase 3".

y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0.,  1.,  0.],
#        [ 0.,  0.,  1.]])

¿La distribución de probabilidad es y_hat_softmaxcercana a la distribución de probabilidad en y_true? Podemos usar la pérdida de entropía cruzada para medir el error.

Fórmula para la pérdida de entropía cruzada

Podemos calcular la pérdida de entropía cruzada en base a filas y ver los resultados. A continuación podemos ver que la instancia de entrenamiento 1 tiene una pérdida de 0.479, mientras que la instancia de entrenamiento 2 tiene una pérdida mayor de 1.200. Este resultado tiene sentido porque en nuestro ejemplo anterior, y_hat_softmaxmostró que la mayor probabilidad de la instancia de entrenamiento 1 era para "Clase 2", que coincide con la instancia de entrenamiento 1 en y_true; sin embargo, la predicción para la instancia de entrenamiento 2 mostró una mayor probabilidad de "Clase 1", que no coincide con la verdadera clase "Clase 3".

loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 ,  1.19967598])

Lo que realmente queremos es la pérdida total en todas las instancias de entrenamiento. Entonces podemos calcular:

total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944

Usando softmax_cross_entropy_with_logits ()

En cambio, podemos calcular la pérdida total de entropía cruzada utilizando la tf.nn.softmax_cross_entropy_with_logits()función, como se muestra a continuación.

loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 ,  1.19967598])

total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922

Tenga en cuenta que total_loss_1y total_loss_2producir resultados esencialmente equivalentes con algunas pequeñas diferencias en los dígitos finales. Sin embargo, también podría usar el segundo enfoque: toma una línea de código menos y acumula menos errores numéricos porque el softmax se realiza dentro de usted softmax_cross_entropy_with_logits().

stackoverflowuser2010
fuente
Confirmo todo lo anterior. El código simple: M = tf.random.uniform([100, 10], minval=-1.0, maxval=1.0); labels = tf.one_hot(tf.random.uniform([100], minval=0, maxval=10 , dtype='int32'), 10); tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=M) - tf.reduce_sum(-tf.nn.log_softmax(M)*tf.one_hot(labels, 10), -1)devuelve casi cero en todas partes
Sami A. Haija
51

tf.nn.softmaxcalcula la propagación hacia adelante a través de una capa softmax. Lo usa durante la evaluación del modelo cuando calcula las probabilidades que genera el modelo.

tf.nn.softmax_cross_entropy_with_logitscalcula el costo de una capa softmax. Solo se usa durante el entrenamiento .

Los logits son las probabilidades de registro no normalizadas que salen del modelo (los valores que salen antes de que se les aplique la normalización softmax).

Ian Goodfellow
fuente
2
Lo entiendo. ¿Por qué no llamar a la función tf.nn.softmax_cross_entropy_sans_normalization?
auro
8
@auro porque normaliza los valores (internamente) durante el cálculo de entropía cruzada. El punto tf.nn.softmax_cross_entropy_with_logitses evaluar cuánto se desvía el modelo de las etiquetas doradas, no proporcionar una salida normalizada.
erickrf
1
En el caso de usar tf.nn.sparse_softmax_cross_entropy_with_logits () calcula el costo de una capa de softmax dispersa y, por lo tanto, solo debe usarse durante el entrenamiento, ¿cuál sería la alternativa cuando se ejecuta el modelo con nuevos datos? ¿Es posible obtener probabilidades de esto? uno.
SerialDev
2
@SerialDev, no es posible obtener probabilidades de tf.nn.sparse_softmax_cross_entropy_with_logits. Para obtener probabilidades use tf.nn.softmax.
Nandeesh
4

Las respuestas anteriores tienen suficiente descripción para la pregunta formulada.

Además de eso, Tensorflow ha optimizado la operación de aplicar la función de activación y luego calcular el costo utilizando su propia activación seguida de las funciones de costo. Por lo tanto, es una buena práctica usar: tf.nn.softmax_cross_entropy()overtf.nn.softmax(); tf.nn.cross_entropy()

Puede encontrar una diferencia notable entre ellos en un modelo de uso intensivo de recursos.

Abish
fuente
1
la respuesta anterior claramente no ha leído la pregunta ... Todos dicen las mismas cosas, que son conocidas, pero no responden la pregunta en sí misma
Euler_Salter
@abhish ¿Querías decir, tf.nn.softmaxseguido de tf.losses.softmax_cross_entropy?
ankurrc
4

Lo que pasa softmaxes logit, esto es lo que J. Hinton repite en los videos de curso todo el tiempo.

prosti
fuente
1

2.0 Tensorflow respuesta Compatible : Las explicaciones de dgay stackoverflowuser2010son muy detallados sobre logits y las funciones relacionadas.

Todas esas funciones, cuando se usan Tensorflow 1.x, funcionarán bien, pero si migra su código de 1.x (1.14, 1.15, etc)a 2.x (2.0, 2.1, etc..), el uso de esas funciones dará como resultado un error.

Por lo tanto, especificando las llamadas compatibles 2.0 para todas las funciones, discutimos anteriormente, si migramos desde 1.x to 2.x, para el beneficio de la comunidad.

Funciones en 1.x :

  1. tf.nn.softmax
  2. tf.nn.softmax_cross_entropy_with_logits
  3. tf.nn.sparse_softmax_cross_entropy_with_logits

Funciones respectivas cuando se migra de 1.xa 2.x :

  1. tf.compat.v2.nn.softmax
  2. tf.compat.v2.nn.softmax_cross_entropy_with_logits
  3. tf.compat.v2.nn.sparse_softmax_cross_entropy_with_logits

Para obtener más información sobre la migración de 1.xa 2.x, consulte esta Guía de migración .

Soporte Tensorflow
fuente
0

Una cosa más que definitivamente me gustaría destacar como logit es solo una salida sin formato, generalmente la salida de la última capa. Esto también puede ser un valor negativo. Si lo usamos como para la evaluación de "entropía cruzada" como se menciona a continuación:

-tf.reduce_sum(y_true * tf.log(logits))

entonces no funcionará. Como log de -ve no está definido. Entonces, utilizando la activación de o softmax, se superará este problema.

Este es mi entendimiento, corrígeme si estoy equivocado.

vipin bansal
fuente