Version corta:
Suponga que tiene dos tensores, donde y_hat
contiene puntajes calculados para cada clase (por ejemplo, de y = W * x + b) y y_true
contiene 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_hat
como 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_hat
matriz 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_true
matriz 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_true
una 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_softmax
cercana a la distribución de probabilidad en y_true
? Podemos usar la pérdida de entropía cruzada para medir el error.
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_softmax
mostró 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_1
y total_loss_2
producir 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()
.
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.