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.
import numpy as np
# your solution:
def your_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()
# desertnaut solution (copied from his answer):
def desertnaut_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(axis=0) # only difference
# my (correct) solution:
def softmax(z):
assert len(z.shape) == 2
s = np.max(z, axis=1)
s = s[:, np.newaxis] # necessary step to do broadcasting
e_x = np.exp(z - s)
div = np.sum(e_x, axis=1)
div = div[:, np.newaxis] # dito
return e_x / div
Nehmen wir als Beispiel Wüstennaut:
x1 = np.array([[1, 2, 3, 6]]) # notice that we put the data into 2 dimensions(!)
Dies ist die Ausgabe:
your_softmax(x1)
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037047]])
desertnaut_softmax(x1)
array([[ 1., 1., 1., 1.]])
softmax(x1)
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037047]])
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.
x2 = np.array([[1, 2, 3, 6], # sample 1
[2, 4, 5, 6], # sample 2
[1, 2, 3, 6]]) # sample 1 again(!)
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!
your_softmax(x2)
array([[ 0.00183535, 0.00498899, 0.01356148, 0.27238963],
[ 0.00498899, 0.03686393, 0.10020655, 0.27238963],
[ 0.00183535, 0.00498899, 0.01356148, 0.27238963]])
desertnaut_softmax(x2)
array([[ 0.21194156, 0.10650698, 0.10650698, 0.33333333],
[ 0.57611688, 0.78698604, 0.78698604, 0.33333333],
[ 0.21194156, 0.10650698, 0.10650698, 0.33333333]])
softmax(x2)
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037047],
[ 0.01203764, 0.08894682, 0.24178252, 0.65723302],
[ 0.00626879, 0.01704033, 0.04632042, 0.93037047]])
Ich hoffe, Sie können sehen, dass dies nur bei meiner Lösung der Fall ist.
softmax(x1) == softmax(x2)[0]
array([[ True, True, True, True]], dtype=bool)
softmax(x1) == softmax(x2)[2]
array([[ True, True, True, True]], dtype=bool)
Darüber hinaus sind hier die Ergebnisse der TensorFlows-Softmax-Implementierung aufgeführt:
import tensorflow as tf
import numpy as np
batch = np.asarray([[1,2,3,6],[2,4,5,6],[1,2,3,6]])
x = tf.placeholder(tf.float32, shape=[None, 4])
y = tf.nn.softmax(x)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(y, feed_dict={x: batch})
Und das Ergebnis:
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037045],
[ 0.01203764, 0.08894681, 0.24178252, 0.657233 ],
[ 0.00626879, 0.01704033, 0.04632042, 0.93037045]], dtype=float32)