[python] Quelle est la différence entre softmax et softmax_cross_entropy_with_logits?


1 Answers

Version courte:

Supposons que vous ayez deux tenseurs, où y_hat contient des scores calculés pour chaque classe (par exemple, à partir de y = W * x + b) et y_true contient des véritables labels codés à chaud.

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

Si vous interprétez les scores dans y_hat comme des probabilités logarithmiques non normalisées, alors ils sont des logits .

De plus, la perte totale d'entropie croisée calculée de cette manière:

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

est essentiellement équivalent à la perte totale d'entropie calculée avec la fonction softmax_cross_entropy_with_logits() :

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

Version longue:

Dans la couche de sortie de votre réseau de neurones, vous allez probablement calculer un tableau contenant les scores de classe pour chacune de vos instances d'apprentissage, par exemple à partir d'un calcul y_hat = W*x + b . Pour servir d'exemple, ci-dessous j'ai créé un y_hat sous la forme d'un tableau 2 x 3, où les lignes correspondent aux instances d'apprentissage et les colonnes correspondent aux classes. Donc, ici, il y a 2 instances d'entraînement et 3 classes.

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]])

Notez que les valeurs ne sont pas normalisées (les lignes ne totalisent pas 1). Afin de les normaliser, nous pouvons appliquer la fonction softmax, qui interprète l'entrée comme des probabilités logarithmiques non normalisées (alias logits ) et produit des probabilités linéaires normalisées.

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]])

Il est important de bien comprendre ce que dit la sortie softmax. Ci-dessous, j'ai montré une table qui représente plus clairement la sortie ci-dessus. On peut voir que, par exemple, la probabilité que l'instance d'entraînement 1 soit «Classe 2» est de 0,619. Les probabilités de classe pour chaque instance d'entraînement sont normalisées, de sorte que la somme de chaque ligne est 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

Alors maintenant nous avons des probabilités de classe pour chaque instance d'entraînement, où nous pouvons prendre l'argmax () de chaque rangée pour générer une classification finale. D'en haut, nous pouvons générer que l'instance de formation 1 appartient à "Classe 2" et l'instance de formation 2 appartient à "Classe 1".

Ces classifications sont-elles correctes? Nous devons mesurer par rapport aux véritables étiquettes de l'ensemble de formation. Vous aurez besoin d'un tableau y_true codé à chaud, où les lignes sont à nouveau des instances d'entraînement et les colonnes sont des classes. Ci-dessous j'ai créé un exemple de y_true une seule y_true où le vrai label pour l'instance d'entraînement 1 est "Classe 2" et le vrai label pour l'instance d'apprentissage 2 est "Classe 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 distribution de probabilité dans y_hat_softmax proche de la distribution de probabilité dans y_true ? Nous pouvons utiliser la perte d'entropie croisée pour mesurer l'erreur.

Nous pouvons calculer la perte d'entropie croisée selon le rang et voir les résultats. Ci-dessous, nous pouvons voir que l'instance d'entraînement 1 a une perte de 0,479, alors que l'instance d'entraînement 2 a une perte plus élevée de 1,200. Ce résultat est logique car dans notre exemple ci-dessus, y_hat_softmax montré que la probabilité la plus élevée de l'instance d'apprentissage 1 était pour "Classe 2", qui correspond à l'instance d'apprentissage 1 dans y_true ; cependant, la prédiction pour l'instance d'apprentissage 2 a montré une probabilité plus élevée pour la «Classe 1», qui ne correspond pas à la vraie classe «Classe 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])

Ce que nous voulons vraiment, c'est la perte totale sur toutes les instances d'entraînement. Nous pouvons donc calculer:

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

Utilisation de softmax_cross_entropy_with_logits ()

Nous pouvons calculer la perte totale d'entropie croisée en utilisant la fonction tf.nn.softmax_cross_entropy_with_logits() , comme indiqué ci-dessous.

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

Notez que total_loss_1 et total_loss_2 produisent des résultats essentiellement équivalents avec quelques petites différences dans les chiffres finaux. Cependant, vous pouvez aussi bien utiliser la deuxième approche: elle prend une ligne de code de moins et accumule moins d'erreur numérique parce que la softmax est faite pour vous à l'intérieur de softmax_cross_entropy_with_logits() .

Question

Je parcourais les docs de l'API tensorflow here . Dans la documentation tensorflow, ils ont utilisé un mot-clé appelé logits . Qu'Est-ce que c'est? Dans beaucoup de méthodes dans les documents de l'API, il est écrit comme

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

Si ce qui est écrit est ces logits sont seulement des Tensors , pourquoi garder un nom différent comme des logits ?

Une autre chose est qu'il y a deux méthodes que je ne pouvais pas différencier. Ils étaient

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

Quelles sont les différences entre eux? Les documents ne sont pas clairs pour moi. Je sais ce tf.nn.softmax fait tf.nn.softmax . Mais pas l'autre. Un exemple sera vraiment utile.




Les réponses ci-dessus ont assez de description pour la question posée.

Ajoutant à cela, Tensorflow a optimisé l'opération d'application de la fonction d'activation puis le calcul du coût en utilisant sa propre activation suivie par des fonctions de coût. Par conséquent, il est tf.nn.softmax_cross_entropy() d'utiliser: tf.nn.softmax_cross_entropy() sur tf.nn.softmax(); tf.nn.cross_entropy() tf.nn.softmax(); tf.nn.cross_entropy()

Vous pouvez trouver une différence importante entre eux dans un modèle intensif en ressources.






Related