Aus der Deep-Learning-Klasse der Udacity ist der Softmax von y_i einfach das Exponential geteilt durch die Summe der Exponentiale des gesamten Y-Vektors:
Wo S(y_i)
ist die Softmax-Funktion von y_i
und e
ist die Exponentialfunktion und j
ist die Nr. von Spalten im Eingabevektor Y.
Ich habe folgendes versucht:
import numpy as np
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
scores = [3.0, 1.0, 0.2]
print(softmax(scores))
was zurückgibt:
[ 0.8360188 0.11314284 0.05083836]
Die vorgeschlagene Lösung war jedoch:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
return np.exp(x) / np.sum(np.exp(x), axis=0)
Dies erzeugt die gleiche Ausgabe wie die erste Implementierung , obwohl die erste Implementierung explizit die Differenz jeder Spalte und das Maximum verwendet und dann durch die Summe dividiert.
Kann jemand mathematisch zeigen warum? Ist einer richtig und der andere falsch?
Ist die Implementierung in Bezug auf Code und Zeitkomplexität ähnlich? Welches ist effizienter?
-inf to +inf
bis-inf to 0
. Ich glaube, ich habe überlegt. hahahaaaaxis = 0
die vorgeschlagene Antwort von Udacity?Antworten:
Sie sind beide korrekt, aber Ihre wird unter dem Gesichtspunkt der numerischen Stabilität bevorzugt.
Sie beginnen mit
Indem wir die Tatsache verwenden, dass a ^ (b - c) = (a ^ b) / (a ^ c) ist, haben wir
Welches ist, was die andere Antwort sagt. Sie könnten max (x) durch eine beliebige Variable ersetzen und es würde sich aufheben.
quelle
(Nun ... viel Verwirrung hier, sowohl in der Frage als auch in den Antworten ...)
Zunächst sind die beiden Lösungen (dh Ihre und die vorgeschlagene) nicht gleichwertig. sie passieren nur für den speziellen Fall von 1-D - Score - Arrays äquivalent. Sie hätten es entdeckt, wenn Sie auch das 2-D-Score-Array im Beispiel des Udacity-Quiz ausprobiert hätten.
In Bezug auf die Ergebnisse ist der einzige tatsächliche Unterschied zwischen den beiden Lösungen das
axis=0
Argument. Um zu sehen, dass dies der Fall ist, versuchen wir Ihre Lösung (your_softmax
) und eine, bei der der einzige Unterschied dasaxis
Argument ist:Wie gesagt, für ein 1-D-Score-Array sind die Ergebnisse tatsächlich identisch:
Hier sind jedoch die Ergebnisse für das 2-D-Score-Array, die im Udacity-Quiz als Testbeispiel angegeben wurden:
Die Ergebnisse sind unterschiedlich - das zweite ist tatsächlich identisch mit dem im Udacity-Quiz erwarteten, bei dem alle Spalten tatsächlich 1 ergeben, was beim ersten (falschen) Ergebnis nicht der Fall ist.
Die ganze Aufregung galt also tatsächlich einem Implementierungsdetail - dem
axis
Argument. Laut der numpy.sum-Dokumentation :während wir hier zeilenweise summieren wollen, daher
axis=0
. Bei einem 1-D-Array sind die Summe der (einzigen) Zeile und die Summe aller Elemente identisch, daher sind Ihre identischen Ergebnisse in diesem Fall ...Die
axis
Frage beiseite, Ihre Implementierung (dh Ihre Wahl , um den max ersten zu subtrahieren) ist eigentlich besser als die vorgeschlagene Lösung! Tatsächlich ist dies die empfohlene Methode zur Implementierung der Softmax-Funktion - siehe hier zur Begründung (numerische Stabilität, auf die auch einige andere Antworten hier hinweisen).quelle
axis
Argumenten zumax
und behoben werdensum
. Die erste Implementierung ist jedoch immer noch besser, da Sie bei der Einnahme leicht überlaufen könnenexp
exp
? Was wurde hier mehr geändert, als einaxis
Argument hinzuzufügen ?Dies ist also wirklich ein Kommentar zu Desertnauts Antwort, aber ich kann ihn aufgrund meines Rufs noch nicht kommentieren. Wie er betonte, ist Ihre Version nur dann korrekt, wenn Ihre Eingabe aus einem einzelnen Beispiel besteht. Wenn Ihre Eingabe aus mehreren Samples besteht, ist dies falsch. Die Lösung von desertnaut ist jedoch auch falsch. Das Problem ist, dass er einmal eine eindimensionale Eingabe und dann eine zweidimensionale Eingabe macht. Lass mich dir das zeigen.
Nehmen wir als Beispiel Wüstennaut:
Dies ist die Ausgabe:
Sie können sehen, dass die Desernauts-Version in dieser Situation fehlschlagen würde. (Es wäre nicht so, wenn die Eingabe nur eindimensional wäre wie np.array ([1, 2, 3, 6]).
Verwenden wir jetzt 3 Samples, da dies der Grund ist, warum wir eine zweidimensionale Eingabe verwenden. Das folgende x2 ist nicht dasselbe wie das aus dem Beispiel eines Desernauts.
Diese Eingabe besteht aus einer Charge mit 3 Proben. Aber Probe eins und drei sind im Wesentlichen gleich. Wir erwarten jetzt 3 Reihen von Softmax-Aktivierungen, wobei die erste mit der dritten und auch mit unserer Aktivierung von x1 identisch sein sollte!
Ich hoffe, Sie können sehen, dass dies nur bei meiner Lösung der Fall ist.
Darüber hinaus sind hier die Ergebnisse der TensorFlows-Softmax-Implementierung aufgeführt:
Und das Ergebnis:
quelle
s = s[:, np.newaxis]
,s = s.reshape(z.shape[0],1)
sollte auch Arbeit.Ich würde sagen, dass beide zwar mathematisch korrekt und implementierungsmäßig korrekt sind, der erste jedoch besser ist. Bei der Berechnung von Softmax können die Zwischenwerte sehr groß werden. Das Teilen von zwei großen Zahlen kann numerisch instabil sein. Diese Notizen (von Stanford) erwähnen einen Normalisierungstrick, der im Wesentlichen das ist, was Sie tun.
quelle
sklearn bietet auch die Implementierung von Softmax an
quelle
Aus mathematischer Sicht sind beide Seiten gleich.
Und das können Sie leicht beweisen. Lass uns
m=max(x)
. Jetzt gibt Ihre Funktionsoftmax
einen Vektor zurück, dessen i-te Koordinate gleich istBeachten Sie, dass dies
m
für alle funktioniert , da für alle (auch komplexen) Zahlene^m != 0
Unter dem Gesichtspunkt der rechnerischen Komplexität sind sie ebenfalls äquivalent und laufen beide
O(n)
zeitlich, wobein
die Größe eines Vektors ist.Unter dem Gesichtspunkt der numerischen Stabilität wird die erste Lösung bevorzugt, da sie
e^x
sehr schnell wächst und selbst bei ziemlich kleinen Wertenx
überläuft. Durch Subtrahieren des Maximalwerts kann dieser Überlauf beseitigt werden. Um die Dinge, über die ich gesprochen habe, praktisch zu erleben, versuchen Sie,x = np.array([1000, 5])
beide Funktionen zu nutzen. Einer gibt die korrekte Wahrscheinlichkeit zurück, der zweite läuft mitnan
Ihre Lösung funktioniert nur für Vektoren (das Udacity-Quiz möchte, dass Sie sie auch für Matrizen berechnen). Um es zu beheben, müssen Sie verwenden
sum(axis=0)
quelle
BEARBEITEN . Ab Version 1.2.0 enthält scipy als Sonderfunktion softmax:
https://scipy.github.io/devdocs/generated/scipy.special.softmax.html
Ich habe eine Funktion geschrieben, die den Softmax auf eine beliebige Achse anwendet:
Das Subtrahieren des Maximums ist, wie von anderen Benutzern beschrieben, eine gute Praxis. Ich schrieb einen ausführlichen Beitrag über sie hier .
quelle
Hier erfahren Sie, warum sie verwendet wurden
- max
.Von dort:
quelle
Eine präzisere Version ist:
quelle
Um eine alternative Lösung anzubieten, betrachten Sie die Fälle, in denen Ihre Argumente extrem groß sind, so dass
exp(x)
ein Unterlauf (im negativen Fall) oder ein Überlauf (im positiven Fall) auftreten würde. Hier möchten Sie so lange wie möglich im Protokollbereich bleiben und nur am Ende potenzieren, wo Sie darauf vertrauen können, dass sich das Ergebnis gut verhält.quelle
axis=0
als Argument hinzufügenlogsumexp
.Ich brauchte etwas, das mit der Ausgabe einer dichten Schicht von Tensorflow kompatibel ist .
Die Lösung von @desertnaut funktioniert in diesem Fall nicht, da ich Datenstapel habe. Daher habe ich eine andere Lösung gefunden, die in beiden Fällen funktionieren sollte:
Ergebnisse:
Ref: Tensorflow Softmax
quelle
Ich würde dies vorschlagen:
Es funktioniert sowohl für stochastische als auch für die Charge.
Weitere Informationen finden Sie unter: https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d
quelle
Um die numerische Stabilität zu gewährleisten, sollte max (x) subtrahiert werden. Das Folgende ist der Code für die Softmax-Funktion;
def softmax (x):
quelle
Bereits ausführlich in den obigen Antworten beantwortet.
max
wird abgezogen, um einen Überlauf zu vermeiden. Ich füge hier eine weitere Implementierung in Python3 hinzu.quelle
Jeder scheint seine Lösung zu veröffentlichen, also werde ich meine veröffentlichen:
Ich erhalte genau die gleichen Ergebnisse wie die von sklearn importierten:
quelle
quelle
Lassen Sie mich anhand aller Antworten und CS231n-Notizen Folgendes zusammenfassen:
Verwendung:
Ausgabe:
quelle
Ich möchte das Problem etwas besser verstehen. Hier ist es richtig, das Maximum des Arrays zu subtrahieren. Wenn Sie den Code jedoch in einem anderen Beitrag ausführen, werden Sie feststellen, dass er Ihnen keine richtige Antwort gibt, wenn das Array 2D- oder höhere Dimensionen aufweist.
Hier gebe ich Ihnen einige Vorschläge:
Folgen Sie dem Ergebnis, um die richtige Antwort zu erhalten, indem Sie eine Vektorisierung durchführen. Da es sich um die Hausaufgaben des Colleges handelt, kann ich den genauen Code hier nicht veröffentlichen, aber ich würde gerne weitere Vorschläge machen, wenn Sie nicht verstehen.
quelle
Der Zweck der Softmax-Funktion besteht darin, das Verhältnis der Vektoren beizubehalten, anstatt die Endpunkte mit einem Sigmoid zu quetschen, wenn die Werte gesättigt sind (dh zu +/- 1 (tanh) oder von 0 zu 1 (logistisch) tendieren). Dies liegt daran, dass mehr Informationen über die Änderungsrate an den Endpunkten erhalten bleiben und daher besser auf neuronale Netze mit 1-aus-N-Ausgangskodierung anwendbar sind (dh wenn wir die Endpunkte zerquetschen, ist es schwieriger, die 1 zu unterscheiden -of-N Ausgabeklasse, weil wir nicht sagen können, welche die "größte" oder "kleinste" ist, weil sie gequetscht wurden.); Außerdem wird die Gesamtausgangssumme auf 1 gesetzt, und der eindeutige Gewinner wird näher an 1 sein, während andere Zahlen, die nahe beieinander liegen, 1 / p ergeben, wobei p die Anzahl der Ausgangsneuronen mit ähnlichen Werten ist.
Der Zweck des Subtrahierens des Maximalwerts vom Vektor besteht darin, dass Sie beim Ausführen von Exponenten möglicherweise einen sehr hohen Wert erhalten, der den Gleitkommawert auf den Maximalwert begrenzt, der zu einem Gleichstand führt, was in diesem Beispiel nicht der Fall ist. Dies wird zu einem GROSSEN Problem, wenn Sie den Maximalwert subtrahieren, um eine negative Zahl zu erhalten. Dann haben Sie einen negativen Exponenten, der die Werte schnell verkleinert und das Verhältnis ändert. Dies ist in der Frage des Posters der Fall und hat die falsche Antwort ergeben.
Die Antwort von Udacity ist schrecklich ineffizient. Das erste, was wir tun müssen, ist, e ^ y_j für alle Vektorkomponenten zu berechnen, DIESE WERTE ZU BEHALTEN, sie dann zusammenzufassen und zu teilen. Wo Udacity durcheinander ist, berechnen sie e ^ y_j ZWEIMAL !!! Hier ist die richtige Antwort:
quelle
Ziel war es, mit Numpy und Tensorflow ähnliche Ergebnisse zu erzielen. Die einzige Änderung gegenüber der ursprünglichen Antwort ist der
axis
Parameter für dienp.sum
API.Erster Ansatz :
axis=0
- Dies liefert jedoch nicht die beabsichtigten Ergebnisse, wenn die Abmessungen N sind.Modifizierter Ansatz :
axis=len(e_x.shape)-1
- Summieren Sie immer die letzte Dimension. Dies liefert ähnliche Ergebnisse wie die Softmax-Funktion von Tensorflow.quelle
Hier ist eine verallgemeinerte Lösung unter Verwendung von Numpy und Vergleich auf Korrektheit mit Tensorflow und Scipy:
Datenaufbereitung:
Ausgabe:
Softmax mit Tensorflow:
Ausgabe:
Softmax mit scipy:
Ausgabe:
Softmax mit numpy ( https://nolanbconaway.github.io/blog/2017/softmax-numpy ):
Ausgabe:
quelle
Die Softmax-Funktion ist eine Aktivierungsfunktion, die Zahlen in Wahrscheinlichkeiten umwandelt, die sich zu eins summieren. Die Softmax-Funktion gibt einen Vektor aus, der die Wahrscheinlichkeitsverteilungen einer Ergebnisliste darstellt. Es ist auch ein Kernelement, das bei Klassifizierungsaufgaben für tiefes Lernen verwendet wird.
Die Softmax-Funktion wird verwendet, wenn wir mehrere Klassen haben.
Es ist nützlich, um herauszufinden, welche Klasse die max. Wahrscheinlichkeit.
Die Softmax-Funktion wird idealerweise in der Ausgabeschicht verwendet, wo wir tatsächlich versuchen, die Wahrscheinlichkeiten zu erreichen, um die Klasse jeder Eingabe zu definieren.
Es reicht von 0 bis 1.
Die Softmax-Funktion wandelt Logits [2.0, 1.0, 0.1] in Wahrscheinlichkeiten [0.7, 0.2, 0.1] um, und die Wahrscheinlichkeiten summieren sich zu 1. Logits sind die Rohwerte, die von der letzten Schicht eines neuronalen Netzwerks ausgegeben werden. Bevor die Aktivierung erfolgt. Um die Softmax-Funktion zu verstehen, müssen wir uns die Ausgabe der (n-1) -ten Schicht ansehen.
Die Softmax-Funktion ist in der Tat eine Arg-Max-Funktion. Dies bedeutet, dass nicht der größte Wert von der Eingabe zurückgegeben wird, sondern die Position der größten Werte.
Beispielsweise:
Vor softmax
Nach Softmax
Code:
quelle