Ich habe die Tensorflow-API-Dokumente durchgesehen hier . In der Tensorflow-Dokumentation wurde ein Schlüsselwort namens logits
verwendet. Was ist es? Bei vielen Methoden in den API-Dokumenten ist es so geschrieben
tf.nn.softmax(logits, name=None)
Wenn geschrieben steht, dass diese logits
nur Tensors
sind, warum einen anderen Namen wie logits
behalten?
Eine andere Sache ist, dass es zwei Methoden gibt, die ich nicht unterscheiden konnte. Sie sind
tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)
Was sind die Unterschiede zwischen ihnen? Die Dokumente sind mir nicht klar. Ich weiß, was tf.nn.softmax
macht. Aber nicht die andere. Ein Beispiel wird sehr hilfreich sein.
Logs bedeuten einfach, dass die Funktion mit der nicht skalierten Ausgabe früherer Layer arbeitet und dass der relative Maßstab zum Verständnis der Einheiten linear ist. Dies bedeutet insbesondere, dass die Summe der Eingaben möglicherweise nicht gleich 1 ist und dass die Werte keine Wahrscheinlichkeiten sind (möglicherweise haben Sie eine Eingabe von 5).
_tf.nn.softmax
_ erzeugt nur das Ergebnis der Anwendung der Softmax-Funktion auf einen Eingangstensor. Der Softmax "quetscht" die Eingaben, so dass sum(input) = 1
: eine Art der Normalisierung. Die Ausgabeform eines Softmax entspricht der Eingabe: Sie normalisiert lediglich die Werte. Die Ausgaben von softmax können als Wahrscheinlichkeiten interpretiert werden.
_a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508 0.205666 0.25120102 0.37474789]]
_
Im Gegensatz dazu berechnet _tf.nn.softmax_cross_entropy_with_logits
_ die Querentropie des Ergebnisses nach Anwendung der Softmax-Funktion (aber dies alles zusammen auf mathematisch sorgfältigere Weise). Es ist ähnlich wie das Ergebnis von:
_sm = tf.nn.softmax(x)
ce = cross_entropy(sm)
_
Die Kreuzentropie ist eine zusammenfassende Metrik: Sie summiert sich über die Elemente. Die Ausgabe von _tf.nn.softmax_cross_entropy_with_logits
_ auf einem Formtensor _[2,5]
_ hat die Form _[2,1]
_ (die erste Dimension wird als Stapel behandelt).
Wenn Sie eine Optimierung durchführen möchten, um die Kreuzentropie UND zu minimieren, die Sie nach Ihrer letzten Ebene softmaxen, sollten Sie stattdessen _tf.nn.softmax_cross_entropy_with_logits
_ verwenden es selbst zu tun, weil es numerisch instabile Eckfälle auf mathematisch richtige Weise abdeckt. Andernfalls hacken Sie es, indem Sie hier und da kleine Epsilons hinzufügen.
Bearbeitet am 07.02.2016: Wenn Sie Beschriftungen für eine einzelne Klasse haben, bei denen ein Objekt nur zu einer Klasse gehören kann, sollten Sie jetzt _tf.nn.sparse_softmax_cross_entropy_with_logits
_, damit Sie Ihre Etiketten nicht in ein dichtes One-Hot-Array konvertieren müssen. Diese Funktion wurde nach Release 0.6.0 hinzugefügt.
Kurzfassung:
Angenommen, Sie haben zwei Tensoren, wobei y_hat
berechnete Punkte für jede Klasse enthält (z. B. aus y = W * x + b) und y_true
one-hot-codierte echte Bezeichnungen enthält.
y_hat = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded
Wenn Sie die Scores in y_hat
als nicht normalisierte Log-Wahrscheinlichkeiten interpretieren, handelt es sich um Logs .
Zusätzlich wird der gesamte Kreuzentropieverlust auf diese Weise berechnet:
y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))
entspricht im Wesentlichen dem mit der Funktion softmax_cross_entropy_with_logits()
berechneten Gesamt-Entropieverlust:
total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
Lange Version:
In der Ausgabeebene Ihres neuronalen Netzwerks werden Sie wahrscheinlich ein Array berechnen, das die Klassenwerte für jede Ihrer Trainingsinstanzen enthält, z. B. aus einer Berechnung y_hat = W*x + b
. Als Beispiel habe ich unten ein y_hat
als 2 x 3-Array erstellt, wobei die Zeilen den Trainingsinstanzen und die Spalten den Klassen entsprechen. Hier gibt es also 2 Trainingsinstanzen und 3 Klassen.
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]])
Beachten Sie, dass die Werte nicht normalisiert sind (d. H. Die Zeilen addieren sich nicht zu 1). Um sie zu normalisieren, können wir die Softmax-Funktion anwenden, die die Eingabe als nicht normalisierte Log-Wahrscheinlichkeiten (aka logits ) interpretiert und normalisierte lineare Wahrscheinlichkeiten ausgibt.
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 ist wichtig zu verstehen, was der Softmax-Ausgang sagt. Unten habe ich eine Tabelle gezeigt, die die Ausgabe oben deutlicher darstellt. Es ist ersichtlich, dass zum Beispiel die Wahrscheinlichkeit, dass die Trainingsinstanz 1 "Klasse 2" ist, 0,619 beträgt. Die Klassenwahrscheinlichkeiten für jede Trainingsinstanz sind normalisiert, sodass die Summe jeder Zeile 1,0 beträgt.
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
Jetzt haben wir Klassenwahrscheinlichkeiten für jede Trainingsinstanz, in der wir das argmax () jeder Zeile verwenden können, um eine endgültige Klassifizierung zu erstellen. Von oben können wir erzeugen, dass die Trainingsinstanz 1 zu "Klasse 2" und die Trainingsinstanz 2 zu "Klasse 1" gehört.
Sind diese Klassifikationen korrekt? Wir müssen uns an den richtigen Etiketten aus dem Trainingsset messen. Sie benötigen ein One-Hot-codiertes y_true
-Array, in dem die Zeilen wiederum Trainingsinstanzen und die Spalten Klassen sind. Unten habe ich ein Beispiel y_true
One-Hot-Array erstellt, in dem die wahre Bezeichnung für Trainingsinstanz 1 "Klasse 2" und die wahre Bezeichnung für Trainingsinstanz 2 "Klasse 3" lautet.
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.]])
Liegt die Wahrscheinlichkeitsverteilung in y_hat_softmax
in der Nähe der Wahrscheinlichkeitsverteilung in y_true
? Wir können Kreuzentropieverlust verwenden, um den Fehler zu messen.
Wir können den Cross-Entropy-Verlust zeilenweise berechnen und die Ergebnisse anzeigen. Unten sehen wir, dass Trainingsinstanz 1 einen Verlust von 0,479 hat, während Trainingsinstanz 2 einen höheren Verlust von 1.200 hat. Dieses Ergebnis ist sinnvoll, da in unserem obigen Beispiel y_hat_softmax
zeigte, dass die höchste Wahrscheinlichkeit für Trainingsinstanz 1 für "Klasse 2" lag, was mit Trainingsinstanz 1 in y_true
übereinstimmt. Die Vorhersage für die Trainingsinstanz 2 zeigte jedoch die höchste Wahrscheinlichkeit für "Klasse 1", die nicht mit der wahren Klasse "Klasse 3" übereinstimmt.
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])
Was wir wirklich wollen, ist der Gesamtverlust über alle Trainingsinstanzen. So können wir berechnen:
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
Verwenden von softmax_cross_entropy_with_logits ()
Wir können stattdessen den gesamten Kreuzentropieverlust mit der Funktion tf.nn.softmax_cross_entropy_with_logits()
berechnen, wie unten gezeigt.
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
Beachten Sie, dass total_loss_1
und total_loss_2
im Wesentlichen äquivalente Ergebnisse mit einigen kleinen Unterschieden in den letzten Ziffern liefern. Sie können jedoch auch den zweiten Ansatz verwenden: Er benötigt eine Codezeile weniger und akkumuliert weniger numerische Fehler, da der Softmax innerhalb von softmax_cross_entropy_with_logits()
für Sie durchgeführt wird.
tf.nn.softmax
berechnet die Vorwärtsausbreitung durch eine Softmax-Schicht. Sie verwenden es während Auswertung des Modells, wenn Sie die Wahrscheinlichkeiten berechnen, die das Modell ausgibt.
tf.nn.softmax_cross_entropy_with_logits
berechnet die Kosten für eine Softmax-Schicht. Es wird nur während Training verwendet.
Die Logs sind die nicht normalisierten Log-Wahrscheinlichkeiten , die das Modell ausgeben (die Werte, die ausgegeben wurden, bevor die Softmax-Normalisierung auf sie angewendet wurde).
Die obigen Antworten enthalten eine ausreichende Beschreibung für die gestellte Frage.
Zusätzlich hat Tensorflow die Anwendung der Aktivierungsfunktion optimiert und anschließend die Kosten mithilfe der eigenen Aktivierung und anschließend der Kostenfunktionen berechnet. Daher ist es eine gute Praxis, Folgendes zu verwenden: tf.nn.softmax_cross_entropy()
über tf.nn.softmax(); tf.nn.cross_entropy()
In einem ressourcenintensiven Modell können Sie einen deutlichen Unterschied zwischen ihnen feststellen.
Was immer an softmax
geht, ist logit, das wiederholt J. Hinton die ganze Zeit in Coursera-Videos.