D'après la classe d'apprentissage en profondeur d'Udacity , le softmax de y_i est simplement l'exponentielle divisée par la somme des exponentielles de l'ensemble du vecteur Y:
Où S(y_i)
est la fonction softmax de y_i
et e
est l'exponentielle et j
est le non. de colonnes dans le vecteur d'entrée Y.
J'ai essayé ce qui suit:
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))
qui renvoie:
[ 0.8360188 0.11314284 0.05083836]
Mais la solution suggérée était:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
return np.exp(x) / np.sum(np.exp(x), axis=0)
ce qui produit la même sortie que la première implémentation , même si la première implémentation prend explicitement la différence de chaque colonne et le max puis divise par la somme.
Quelqu'un peut-il montrer mathématiquement pourquoi? L'un est-il correct et l'autre faux?
L'implémentation est-elle similaire en termes de code et de complexité temporelle? Quel est le plus efficace?
-inf to +inf
à-inf to 0
. Je suppose que je pensais trop. hahahaaaaxis = 0
la réponse suggérée par Udacity?Réponses:
Ils sont tous les deux corrects, mais le vôtre est préféré du point de vue de la stabilité numérique.
Vous commencez avec
En utilisant le fait que a ^ (b - c) = (a ^ b) / (a ^ c) nous avons
C'est ce que dit l'autre réponse. Vous pourriez remplacer max (x) par n'importe quelle variable et cela annulerait.
la source
(Eh bien ... beaucoup de confusion ici, à la fois dans la question et dans les réponses ...)
Pour commencer, les deux solutions (c'est-à-dire la vôtre et celle suggérée) ne sont pas équivalentes; ils arrivent être équivalents uniquement pour le cas spécial des tableaux de scores 1-D. Vous l'auriez découvert si vous aviez essayé également le tableau de score 2D dans l'exemple de test d'Udacity.
En termes de résultats, la seule différence réelle entre les deux solutions est l'
axis=0
argument. Pour voir que c'est le cas, essayons votre solution (your_softmax
) et celle où la seule différence est l'axis
argument:Comme je l'ai dit, pour un tableau de scores 1D, les résultats sont en effet identiques:
Néanmoins, voici les résultats du tableau de score 2D donnés dans le quiz Udacity comme exemple de test:
Les résultats sont différents - le second est en effet identique à celui attendu dans le quiz Udacity, où toutes les colonnes totalisent en effet 1, ce qui n'est pas le cas avec le premier (mauvais) résultat.
Donc, tout le tapage était en fait pour un détail de mise en œuvre - l'
axis
argument. Selon la documentation numpy.sum :alors qu'ici nous voulons faire la somme des lignes, donc
axis=0
. Pour un tableau 1-D, la somme de la (seule) ligne et la somme de tous les éléments se trouvent être identiques, d'où vos résultats identiques dans ce cas ...Le
axis
problème mis à part, votre implémentation (c'est-à-dire votre choix de soustraire le maximum en premier) est en fait meilleure que la solution suggérée! En fait, c'est la façon recommandée d'implémenter la fonction softmax - voir ici pour la justification (stabilité numérique, également soulignée par d'autres réponses ici).la source
axis
argument aux deuxmax
etsum
. Cependant, la première implémentation est encore meilleure car vous pouvez facilement déborder lors de la priseexp
exp
? Quoi de plus a été modifié ici que l'ajout d'unaxis
argument?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.
Prenons l'exemple des déserteurs:
Voici la sortie:
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.
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!
J'espère que vous pouvez voir que ce n'est que le cas avec ma solution.
En outre, voici les résultats de la mise en œuvre de softmax TensorFlows:
Et le résultat:
la source
s = s[:, np.newaxis]
,s = s.reshape(z.shape[0],1)
devrait également fonctionner.Je dirais que si les deux sont corrects mathématiquement, en ce qui concerne la mise en œuvre, le premier est meilleur. Lors du calcul de softmax, les valeurs intermédiaires peuvent devenir très grandes. La division de deux grands nombres peut être numériquement instable. Ces notes (de Stanford) mentionnent une astuce de normalisation qui est essentiellement ce que vous faites.
la source
sklearn propose également la mise en œuvre de softmax
la source
D'un point de vue mathématique, les deux côtés sont égaux.
Et vous pouvez facilement le prouver. Allons
m=max(x)
. Maintenant, votre fonctionsoftmax
retourne un vecteur dont la i-ème coordonnée est égale ànotez que cela fonctionne pour tout
m
, car pour tous les nombres (même complexes)e^m != 0
du point de vue de la complexité de calcul, ils sont également équivalents et fonctionnent tous les deux dans
O(n)
temps, oùn
est la taille d'un vecteur.du point de vue de la stabilité numérique , la première solution est préférée, car elle se
e^x
développe très rapidement et même pour de très petites valeurs,x
elle débordera. La soustraction de la valeur maximale permet de se débarrasser de ce débordement. Pour expérimenter pratiquement ce dont je parlais, essayez d'alimenterx = np.array([1000, 5])
vos deux fonctions. L'un retournera une probabilité correcte, le second débordera denan
votre solution ne fonctionne que pour les vecteurs (le quiz Udacity veut que vous le calculiez également pour les matrices). Pour le réparer, vous devez utiliser
sum(axis=0)
la source
MODIFIER . Depuis la version 1.2.0, scipy inclut softmax comme fonction spéciale:
https://scipy.github.io/devdocs/generated/scipy.special.softmax.html
J'ai écrit une fonction appliquant le softmax sur n'importe quel axe:
La soustraction du maximum, comme d'autres utilisateurs l'ont décrit, est une bonne pratique. J'ai écrit un article détaillé à ce sujet ici .
la source
Ici, vous pouvez découvrir pourquoi ils ont utilisé
- max
.De là:
la source
Une version plus concise est:
la source
Pour proposer une solution alternative, considérez les cas où vos arguments sont d'une ampleur extrêmement grande, tels que des
exp(x)
débordements (dans le cas négatif) ou des débordements (dans le cas positif). Ici, vous souhaitez rester dans l'espace journal le plus longtemps possible, en exponentiant uniquement à la fin où vous pouvez avoir confiance que le résultat se comportera bien.la source
axis=0
comme argument àlogsumexp
.J'avais besoin de quelque chose de compatible avec la sortie d'une couche dense de Tensorflow .
La solution de @desertnaut ne fonctionne pas dans ce cas car j'ai des lots de données. Par conséquent, je suis venu avec une autre solution qui devrait fonctionner dans les deux cas:
Résultats:
Réf: Tensorflow softmax
la source
Je suggérerais ceci:
Cela fonctionnera aussi bien pour le stochastique que pour le lot.
Pour plus de détails, voir: https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d
la source
Afin de maintenir la stabilité numérique, max (x) doit être soustrait. Voici le code de la fonction softmax;
def softmax (x):
la source
Déjà répondu en détail dans les réponses ci-dessus.
max
est soustrait pour éviter le débordement. J'ajoute ici une autre implémentation en python3.la source
Tout le monde semble poster sa solution donc je vais poster la mienne:
J'obtiens exactement les mêmes résultats que ceux importés de sklearn:
la source
la source
Sur la base de toutes les réponses et des notes du CS231n , permettez-moi de résumer:
Usage:
Production:
la source
Je voudrais compléter un peu plus la compréhension du problème. Ici, il est correct de soustraire max du tableau. Mais si vous exécutez le code dans l'autre article, vous constaterez qu'il ne vous donne pas la bonne réponse lorsque le tableau est de dimensions 2D ou supérieures.
Ici, je vous donne quelques suggestions:
Suivez le résultat, vous obtiendrez la bonne réponse en faisant de la vectorisation. Puisqu'il est lié aux devoirs du collège, je ne peux pas poster le code exact ici, mais je voudrais donner plus de suggestions si vous ne comprenez pas.
la source
Le but de la fonction softmax est de préserver le rapport des vecteurs par opposition à écraser les points finaux avec un sigmoïde car les valeurs saturent (c'est-à-dire ont tendance à +/- 1 (tanh) ou de 0 à 1 (logistique)). En effet, il conserve plus d'informations sur le taux de changement aux points d'extrémité et est donc plus applicable aux réseaux neuronaux avec codage de sortie 1 sur N (c'est-à-dire que si nous écrasons les points d'extrémité, il serait plus difficile de différencier le 1 -of-N classe de sortie parce que nous ne pouvons pas dire laquelle est la "plus grande" ou "la plus petite" parce qu'elles ont été écrasées.); il fait également la somme totale de sortie à 1, et le gagnant clair sera plus proche de 1 tandis que d'autres nombres qui sont proches les uns des autres seront totalisés à 1 / p, où p est le nombre de neurones de sortie avec des valeurs similaires.
Le but de soustraire la valeur maximale du vecteur est que lorsque vous faites des exposants e ^ y, vous pouvez obtenir une valeur très élevée qui coupe le flotteur à la valeur maximale conduisant à une égalité, ce qui n'est pas le cas dans cet exemple. Cela devient un GRAND problème si vous soustrayez la valeur maximale pour obtenir un nombre négatif, puis vous avez un exposant négatif qui réduit rapidement les valeurs modifiant le rapport, ce qui s'est produit dans la question de l'affiche et a donné la réponse incorrecte.
La réponse fournie par Udacity est HORRIBLEMENT inefficace. La première chose que nous devons faire est de calculer e ^ y_j pour toutes les composantes vectorielles, CONSERVER CES VALEURS, puis les additionner et diviser. Où Udacity a gâché, ils calculent e ^ y_j DEUX FOIS !!! Voici la bonne réponse:
la source
L'objectif était d'obtenir des résultats similaires en utilisant Numpy et Tensorflow. Le seul changement par rapport à la réponse d'origine est le
axis
paramètre pour l'np.sum
api.Approche initiale :
axis=0
- Cela ne donne cependant pas les résultats escomptés lorsque les dimensions sont N.Approche modifiée :
axis=len(e_x.shape)-1
- Somme toujours sur la dernière dimension. Cela donne des résultats similaires à la fonction softmax de tensorflow.la source
Voici une solution généralisée utilisant numpy et la comparaison pour l'exactitude avec tensorflow et scipy:
Préparation des données:
Production:
Softmax utilisant tensorflow:
Production:
Softmax utilisant scipy:
Production:
Softmax utilisant numpy ( https://nolanbconaway.github.io/blog/2017/softmax-numpy ):
Production:
la source
La fonction softmax est une fonction d'activation qui transforme les nombres en probabilités qui se résument à un. La fonction softmax génère un vecteur qui représente les distributions de probabilité d'une liste de résultats. C'est également un élément central utilisé dans les tâches de classification de l'apprentissage en profondeur.
La fonction Softmax est utilisée lorsque nous avons plusieurs classes.
Il est utile pour trouver la classe qui a le max. Probabilité.
La fonction Softmax est idéalement utilisée dans la couche de sortie, où nous essayons en fait d'atteindre les probabilités de définir la classe de chaque entrée.
Il va de 0 à 1.
La fonction Softmax transforme les logits [2.0, 1.0, 0.1] en probabilités [0.7, 0.2, 0.1] et la somme des probabilités à 1. Les logits sont les scores bruts émis par la dernière couche d'un réseau neuronal. Avant l'activation. Pour comprendre la fonction softmax, nous devons regarder la sortie de la (n-1) ème couche.
La fonction softmax est, en fait, une fonction arg max. Cela signifie qu'il ne renvoie pas la plus grande valeur de l'entrée, mais la position des plus grandes valeurs.
Par exemple:
Avant softmax
Après softmax
Code:
la source