Je parcourais la documentation de l'API tensorflow ici . Dans la documentation de tensorflow, ils utilisaient 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 que ces logits
ne sont que Tensors
, pourquoi garder un nom différent comme logits
?
Une autre chose est qu'il y a deux méthodes que je ne pourrais 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 docs ne sont pas clairs pour moi. Je sais ce que tf.nn.softmax
fait. Mais pas l'autre. Un exemple sera vraiment utile.
Logits signifie simplement que la fonction opère sur la sortie non mise à l'échelle des couches précédentes et que l'échelle relative permettant de comprendre les unités est linéaire. Cela signifie notamment que la somme des entrées peut ne pas être égale à 1, que les valeurs sont des probabilités et non (vous pourriez avoir une entrée de 5).
tf.nn.softmax
produit uniquement le résultat de l'application de fonction softmax à un tenseur d'entrée. Le softmax "écrase" les entrées pour que sum(input) = 1
: soit un moyen de normalisation. La forme de la sortie d'un softmax est identique à celle de l'entrée: elle normalise simplement les valeurs. Les sorties de softmax peuvent être interprétées comme des probabilités.
a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508 0.205666 0.25120102 0.37474789]]
En revanche, tf.nn.softmax_cross_entropy_with_logits
calcule l'entropie croisée du résultat après l'application de la fonction softmax (mais le fait tous ensemble d'une manière plus mathématiquement plus prudente). C'est semblable au résultat de:
sm = tf.nn.softmax(x)
ce = cross_entropy(sm)
L'entropie croisée est une métrique récapitulative: elle consiste à faire la somme de tous les éléments. La sortie de tf.nn.softmax_cross_entropy_with_logits
sur une forme [2,5]
tenseur est de forme [2,1]
(la première dimension est traitée comme un lot).
Si vous souhaitez effectuer une optimisation afin de minimiser l'entropie croisée ET après la dernière couche, vous devez utiliser tf.nn.softmax_cross_entropy_with_logits
à la place. de le faire vous-même, car il couvre mathématiquement les cas de coin instables numériquement. Sinon, vous finirez par le pirater en ajoutant de petits epsilons ici et là.
Modifié le 17/02/2016: Si vous avez des étiquettes à une seule classe, dans lesquelles un objet ne peut appartenir qu'à une seule classe, vous pouvez maintenant envisager d'utiliser tf.nn.sparse_softmax_cross_entropy_with_logits
afin que vous n'ayez pas à convertir vos étiquettes en un tableau dense à une seule tâche. Cette fonction a été ajoutée après la version 0.6.0.
Version abrégée:
Supposons que vous avez deux tenseurs, où y_hat
contient les scores calculés pour chaque classe (par exemple, de y = W * x + b) et y_true
contient des étiquettes vraies codées à 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 de journal non normalisées, il s'agit alors de logits .
De plus, la perte totale par 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 équivalente à la perte totale d'entropie croisée 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 calculerez probablement un tableau contenant les scores de classe pour chacune de vos instances de formation, par exemple à partir d'un calcul y_hat = W*x + b
. Pour servir d'exemple, j'ai créé ci-dessous un y_hat
sous la forme d'un tableau 2 x 3, où les lignes correspondent aux instances de formation et les colonnes correspondent aux classes. Donc, ici, il y a 2 instances de formation 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 (c'est-à-dire que 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 de journal non normalisées (ou logits ) et génère 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é un tableau qui représente plus clairement la sortie ci-dessus. On peut voir que, par exemple, la probabilité que l'instance de formation 1 soit "Classe 2" est de 0,619. Les probabilités de classe pour chaque instance d'apprentissage étant normalisées, la somme de chaque ligne est égale à 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
Nous avons donc maintenant des probabilités de classe pour chaque instance de formation, où nous pouvons utiliser la méthode argmax () de chaque ligne pour générer une classification finale. De là-haut, nous pouvons générer que l'instance de formation 1 appartient à la "classe 2" et l'instance de formation 2 à la "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ù encore une fois, les lignes sont des instances d'apprentissage et les colonnes sont des classes. J'ai créé ci-dessous un exemple de tableau y_true
one-hot où le véritable libellé de l'instance d'apprentissage 1 est "Classe 2" et le véritable libellé de 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
est-elle proche de la distribution de probabilité dans y_true
? Nous pouvons utiliser perte d'entropie croisée pour mesurer l'erreur.
Nous pouvons calculer la perte d'entropie croisée par rangée et voir les résultats. Nous pouvons voir ci-dessous que l'instance de formation 1 a une perte de 0,479, tandis que l'instance de formation 2 a une perte plus élevée de 1 200. Ce résultat est logique car dans notre exemple ci-dessus, y_hat_softmax
a montré que la probabilité la plus élevée de l'instance de formation 1 était pour "Classe 2", ce qui correspond à l'instance de formation 1 dans y_true
; toutefois, la prédiction pour l'instance de formation 2 indiquait une probabilité plus élevée de "classe 1", ce 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 de formation. 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 plutôt calculer la perte totale d'entropie croisée à l'aide de 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 différences minimes dans les derniers chiffres. Cependant, vous pouvez aussi bien utiliser la seconde approche: elle prend une ligne de code en moins et génère moins d’erreurs numériques car la softmax est faite pour vous dans softmax_cross_entropy_with_logits()
.
tf.nn.softmax
calcule la propagation en avant via une couche softmax. Vous l'utilisez pendant evaluation du modèle lorsque vous calculez les probabilités que le modèle génère.
tf.nn.softmax_cross_entropy_with_logits
calcule le coût d'un calque softmax. Il est utilisé uniquement pendant training.
Les logits sont les probabilités de journal non normalisées générées par le modèle (les valeurs générées avant l'application de la normalisation softmax).
Les réponses ci-dessus ont suffisamment de description pour la question posée.
En plus de cela, Tensorflow a optimisé l'opération consistant à appliquer la fonction d'activation, puis à calculer le coût à l'aide de sa propre activation suivie de fonctions de coût. Par conséquent, il est recommandé d'utiliser: tf.nn.softmax_cross_entropy()
sur tf.nn.softmax(); tf.nn.cross_entropy()
Vous pouvez trouver une différence importante entre eux dans un modèle gourmand en ressources.
Tout ce qui se passe à softmax
est logit, c'est ce que J. Hinton répète tout le temps dans les vidéos de coursera.