¿Cuál es la diferencia entre sparse_softmax_cross_entropy_with_logits y softmax_cross_entropy_with_logits?

111

Recientemente me encontré con tf.nn.sparse_softmax_cross_entropy_with_logits y no puedo entender cuál es la diferencia en comparación con tf.nn.softmax_cross_entropy_with_logits .

¿Es la única diferencia que los vectores de entrenamiento ytienen que codificarse en un solo uso cuando se usan sparse_softmax_cross_entropy_with_logits?

Al leer la API, no pude encontrar ninguna otra diferencia en comparación con softmax_cross_entropy_with_logits. Pero entonces, ¿por qué necesitamos la función adicional?

¿No debería softmax_cross_entropy_with_logitsproducir los mismos resultados que sparse_softmax_cross_entropy_with_logitssi se suministra con datos / vectores de entrenamiento codificados en un solo uso?

daniel451
fuente
1
Me interesa ver una comparación de su rendimiento si se pueden usar ambos (por ejemplo, con etiquetas de imagen exclusivas); Espero que la versión dispersa sea más eficiente, al menos en cuanto a memoria.
Yibo Yang
1
Consulte también esta pregunta , que analiza todas las funciones de entropía cruzada en tensorflow (resulta que hay muchas).
Maxim

Respuestas:

175

Tener dos funciones diferentes es conveniente , ya que producen el mismo resultado.

La diferencia es simple:

  • Para sparse_softmax_cross_entropy_with_logits, las etiquetas deben tener la forma [batch_size] y el dtype int32 o int64. Cada etiqueta es un int en rango [0, num_classes-1].
  • Para softmax_cross_entropy_with_logits, las etiquetas deben tener la forma [batch_size, num_classes] y dtype float32 o float64.

Las etiquetas utilizadas en softmax_cross_entropy_with_logitsson la única versión activa de las etiquetas utilizadas en sparse_softmax_cross_entropy_with_logits.

Otra pequeña diferencia es que con sparse_softmax_cross_entropy_with_logits, puede dar -1 como etiqueta para tener pérdida 0en esta etiqueta.

Olivier Moindrot
fuente
15
¿Es correcto el -1? Como dice la documentación: "Cada entrada en las etiquetas debe ser un índice en [0, num_classes). Otros valores generarán una excepción cuando esta operación se ejecute en la CPU y devolverán NaN para las filas de pérdida y gradiente correspondientes en la GPU".
user1761806
1
[0, num_classes) = [0, num_classes-1]
Karthik C
24

Solo me gustaría agregar 2 cosas a la respuesta aceptada que también puede encontrar en la documentación de TF.

Primero:

tf.nn.softmax_cross_entropy_with_logits

NOTA: Si bien las clases son mutuamente excluyentes, sus probabilidades no necesitan serlo. Todo lo que se requiere es que cada fila de etiquetas sea una distribución de probabilidad válida. Si no es así, el cálculo del gradiente será incorrecto.

Segundo:

tf.nn.sparse_softmax_cross_entropy_with_logits

NOTA: Para esta operación, la probabilidad de una etiqueta determinada se considera exclusiva. Es decir, las clases blandas no están permitidas y el vector de etiquetas debe proporcionar un único índice específico para la clase verdadera para cada fila de logits (cada entrada de minibatch).

Arrastrar0
fuente
4
¿Qué deberíamos usar si las clases no son mutuamente excluyentes? Quiero decir, ¿si estamos combinando varias etiquetas categóricas?
Hayro
También leí esto. Entonces significa que aplicamos la probabilidad de clase en la entropía cruzada en lugar de tomarla como un vector onehot.
Shamane Siriwardhana
@Hayro - ¿Quieres decir que no puedes hacer una codificación en caliente? Creo que tendrías que mirar un modelo diferente. Esto mencionó algo como "sería más apropiado construir 4 clasificadores de regresión logística binaria" Para asegurarse primero de poder separar las clases.
Ashley
21

Ambas funciones calculan los mismos resultados y sparse_softmax_cross_entropy_with_logits calcula la entropía cruzada directamente en las etiquetas dispersas en lugar de convertirlas con codificación one-hot .

Puede verificar esto ejecutando el siguiente programa:

import tensorflow as tf
from random import randint

dims = 8
pos  = randint(0, dims - 1)

logits = tf.random_uniform([dims], maxval=3, dtype=tf.float32)
labels = tf.one_hot(pos, dims)

res1 = tf.nn.softmax_cross_entropy_with_logits(       logits=logits, labels=labels)
res2 = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=tf.constant(pos))

with tf.Session() as sess:
    a, b = sess.run([res1, res2])
    print a, b
    print a == b

Aquí creo un logitsvector aleatorio de longitud dimsy genero etiquetas codificadas one-hot (donde el elemento en poses 1 y otros son 0).

Después de eso, calculo softmax y sparse softmax y comparo su salida. Intente volver a ejecutarlo varias veces para asegurarse de que siempre produzca el mismo resultado

Salvador Dalí
fuente