redes neuronales learning intensivo google funcion curso automático automatico aprendizaje algoritmo activación acelerado neural-network regression backpropagation derivative softmax

neural-network - learning - redes neuronales softmax



¿Cómo implementar el derivado de Softmax independientemente de cualquier función de pérdida? (2)

Debería ser así: (x es la entrada a la capa de softmax y dy es el delta procedente de la pérdida que está por encima)

dx = y * dy s = dx.sum(axis=dx.ndim - 1, keepdims=True) dx -= y * s return dx

Pero la forma en que calcula el error debería ser:

yact = activation.compute(x) ycost = cost.compute(yact) dsoftmax = activation.delta(x, cost.delta(yact, ycost, ytrue))

Explicación: Como la función delta es parte del algoritmo de retropropagación, su responsabilidad es multiplicar el vector dy (en mi código, outgoing en su caso) por el jacobiano de la función de compute(x) evaluada en x . Si averiguas qué aspecto tiene este Jacobian para softmax [1], y luego lo multiplicas desde la izquierda por un vector dy , después de un poco de álgebra descubrirás que obtienes algo que corresponde a mi código Python.

[1] https://stats.stackexchange.com/questions/79454/softmax-layer-in-a-neural-network

Para una biblioteca de redes neuronales implementé algunas funciones de activación y funciones de pérdida y sus derivadas. Se pueden combinar arbitrariamente y la derivada en las capas de salida simplemente se convierte en el producto de la derivada de pérdida y la derivada de activación.

Sin embargo, no pude implementar la derivada de la función de activación de Softmax independientemente de cualquier función de pérdida. Debido a la normalización, es decir, el denominador en la ecuación, el cambio de una sola activación de entrada cambia todas las activaciones de salida y no solo una.

Aquí está mi implementación de Softmax donde la derivada falla la verificación del gradiente en aproximadamente 1%. ¿Cómo puedo implementar el derivado de Softmax para que se pueda combinar con cualquier función de pérdida?

import numpy as np class Softmax: def compute(self, incoming): exps = np.exp(incoming) return exps / exps.sum() def delta(self, incoming, outgoing): exps = np.exp(incoming) others = exps.sum() - exps return 1 / (2 + exps / others + others / exps) activation = Softmax() cost = SquaredError() outgoing = activation.compute(incoming) delta_output_layer = activation.delta(incoming) * cost.delta(outgoing)


Matemáticamente, la derivada de Softmax (Xi) con respecto a Xj es:

donde el delta rojo es un delta Kronecker.

Si implementa iterativamente:

def softmax_grad(s): # input s is softmax value of the original input x. Its shape is (1,n) # e.i. s = np.array([0.3,0.7]), x = np.array([0,1]) # make the matrix whose size is n^2. jacobian_m = np.diag(s) for i in range(len(jacobian_m)): for j in range(len(jacobian_m)): if i == j: jacobian_m[i][j] = s[i] * (1-s[i]) else: jacobian_m[i][j] = -s[i]*s[j] return jacobian_m

Prueba:

In [95]: x Out[95]: array([1, 2]) In [96]: softmax(x) Out[96]: array([ 0.26894142, 0.73105858]) In [97]: softmax_grad(softmax(x)) Out[97]: array([[ 0.19661193, -0.19661193], [-0.19661193, 0.19661193]])

Si implementa en una versión vectorizada:

soft_max = softmax(x) # reshape softmax to 2d so np.dot gives matrix multiplication def softmax_grad(softmax): s = softmax.reshape(-1,1) return np.diagflat(s) - np.dot(s, s.T) softmax_grad(soft_max) #array([[ 0.19661193, -0.19661193], # [-0.19661193, 0.19661193]])