Donc, c'est vraiment un commentaire à la réponse de desertnaut mais je ne peux pas encore le commenter en raison de ma réputation. Comme il l'a souligné, votre version n'est correcte que si votre entrée consiste en un seul échantillon. Si votre entrée se compose de plusieurs échantillons, c'est faux. Cependant, la solution de desertnaut est également fausse. Le problème est qu'une fois qu'il prend une entrée unidimensionnelle, puis il prend une entrée bidimensionnelle. Permettez-moi de vous le montrer.
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
Prenons l'exemple des déserteurs:
x1 = np.array([[1, 2, 3, 6]]) # notice that we put the data into 2 dimensions(!)
Voici la sortie:
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]])
Vous pouvez voir que la version desernauts échouerait dans cette situation. (Ce ne serait pas le cas si l'entrée n'était qu'une dimension comme np.array ([1, 2, 3, 6]).
Permet maintenant d'utiliser 3 échantillons car c'est la raison pour laquelle nous utilisons une entrée bidimensionnelle. Le x2 suivant n'est pas le même que celui de l'exemple desernauts.
x2 = np.array([[1, 2, 3, 6], # sample 1
[2, 4, 5, 6], # sample 2
[1, 2, 3, 6]]) # sample 1 again(!)
Cette entrée consiste en un lot de 3 échantillons. Mais les échantillons un et trois sont essentiellement les mêmes. Nous attendons maintenant 3 rangées d'activations softmax où la première devrait être la même que la troisième et aussi la même que notre activation de x1!
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]])
J'espère que vous pouvez voir que ce n'est que le cas avec ma solution.
softmax(x1) == softmax(x2)[0]
array([[ True, True, True, True]], dtype=bool)
softmax(x1) == softmax(x2)[2]
array([[ True, True, True, True]], dtype=bool)
En outre, voici les résultats de la mise en œuvre de softmax TensorFlows:
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})
Et le résultat:
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)