Softmax Numercialmente estable

¿Existe una manera numéricamente estable de calcular la función softmax a continuación? Estoy obteniendo valores que se convierten en Nans en el código de neural network.

np.exp(x)/np.sum(np.exp(y)) 

El softmax exp ( x ) / sum (exp ( x )) es en realidad numéricamente bien educado. Solo tiene términos positivos, por lo que no debemos preocuparnos por la pérdida de importancia, y el denominador es al menos tan grande como el numerador, por lo que se garantiza que el resultado estará entre 0 y 1.

El único accidente que podría ocurrir es un exceso o un flujo insuficiente en las exponenciales. El desbordamiento de un solo o subdesbordamiento de todos los elementos de x hará que la salida sea más o menos inútil.

Pero es fácil protegerse contra eso utilizando la identidad softmax ( x ) = softmax ( x + c) que se cumple para cualquier escalar c: restar max ( x ) de x deja un vector que solo tiene entradas no positivas, descartando desbordamiento y al menos un elemento que es cero descarta un denominador que desaparece (el desbordamiento en algunas pero no todas las entradas es inofensivo).

Nota: teóricamente, los accidentes catastróficos en la sum son posibles, pero necesitaría un número ridículo de términos y ser ridículamente desafortunado. Además, numpy utiliza la sum por pares, que es bastante robusta.

La función Softmax es propensa a dos problemas: desbordamiento y subdesbordamiento

Desbordamiento : Ocurre cuando números muy grandes se aproximan como infinity

Subdesbordamiento : se produce cuando los números muy pequeños (cerca de cero en la recta numérica) se aproximan (es decir, se redondean a) como zero

Para combatir estos problemas cuando se realiza el cálculo de softmax, un truco común es cambiar el vector de entrada restando el elemento máximo de todos los elementos . Para el vector de entrada x , defina z tal que:

 z = x-max(x) 

Y luego tome el softmax del nuevo vector z (estable)


Ejemplo:

 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.]) 

Para más detalles, vea el capítulo Computación numérica en el libro de aprendizaje profundo .

Gracias a la explicación de Paul Panzer , pero me pregunto por qué necesitamos restar max (x). Por lo tanto, encontré información más detallada y espero que sea útil para las personas que tienen la misma pregunta que yo. Consulte la sección “¿Qué pasa con esa resta máxima?”, En el artículo del siguiente enlace.

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

No hay nada de malo en calcular la función softmax como en su caso. El problema parece provenir de la explosión de gradiente o este tipo de problemas con sus métodos de entrenamiento. Concéntrese en esos asuntos ya sea con ” valores de recorte ” o con ” elegir la distribución inicial correcta de pesos “.