web-dev-qa-db-fra.com

Softmax numériquement stable

Existe-t-il un moyen numériquement stable de calculer la fonction softmax ci-dessous? Je reçois des valeurs qui deviennent Nans dans le code de réseau Neural.

np.exp(x)/np.sum(np.exp(y))
6
Abhishek Bhatia

Le softmax exp ( x )/sum (exp ( x )) est en fait numériquement correct. Il ne contient que des termes positifs, nous n’avons donc pas à nous soucier de la perte de signification, et le dénominateur est au moins aussi grand que le numérateur. Le résultat est donc garanti entre 0 et 1.

Le seul accident susceptible de se produire est un excès ou un sous-écoulement dans les exponentielles. Le débordement d’un seul élément ou le sous-écoulement de tous les éléments de x rendra la sortie plus ou moins inutile.

Mais il est facile de se prémunir contre cela en utilisant l’identité softmax ( x ) = softmax ( x + c) qui vaut pour tout scalaire c: Soustraire max ( x ) de x laisse un vecteur qui n'a que des entrées non positives, excluant le débordement et au moins un élément nul excluant un dénominateur en voie de disparition (le débordement de certaines entrées est inoffensif).

Remarque: théoriquement, des accidents catastrophiques sont possibles dans la somme, mais vous auriez besoin d’un nombre ridicule de termes et être ridiculement malchanceux. De plus, numpy utilise une sommation par paire, ce qui est plutôt robuste.

23
Paul Panzer

La fonction Softmax est sujette à deux problèmes: overflow et underflow

Overflow : Cela se produit lorsque de très grands nombres sont approximés comme infinity

Dépassement négatif : Il survient lorsque de très petits nombres (proches de zéro dans la droite numérique) sont approximés (arrondis à) en tant que zero

Pour résoudre ces problèmes lors du calcul softmax, une astuce courante consiste à décaler le vecteur d’entrée de en soustrayant l’élément maximum qui le compose de tous les éléments}. Pour le vecteur d'entrée x, définissez z tel que:

z = x-max(x)

Et ensuite, prenez la softmax du nouveau vecteur (stable) z


Exemple:

In [266]: def stable_softmax(x):
     ...:     z = x - max(x)
     ...:     numerator = np.exp(z)
     ...:     denominator = np.sum(numerator)
     ...:     softmax = numerator/denominator
     ...:     return softmax
     ...: 

In [267]: vec = np.array([1, 2, 3, 4, 5])

In [268]: stable_softmax(vec)
Out[268]: array([ 0.01165623,  0.03168492,  0.08612854,  0.23412166,  0.63640865])

In [269]: vec = np.array([12345, 67890, 99999999])

In [270]: stable_softmax(vec)
Out[270]: array([ 0.,  0.,  1.])

Pour plus de détails, voir le chapitreCalcul numériqueinapprentissage en profondeurbook.

2
kmario23

Il n'y a rien de mal à calculer la fonction softmax comme c'est le cas dans votre cas. Le problème semble provenir de gradient explosant ou de ce type de problèmes avec vos méthodes d’entraînement. Concentrez-vous sur les problèmes suivants: " Valeurs de découpage " ou " Choix de la bonne répartition initiale des poids ".

1

Merci Paul Panzer explication, mais je me demande pourquoi nous devons soustraire max (x). C’est pourquoi j’ai trouvé des informations plus détaillées et j’espère que cela sera utile aux personnes qui ont la même question que moi.

https://nolanbconaway.github.io/blog/2017/softmax-numpy

1
Alumi Lu