Implementación de Retropropagación
Enfoque general
En la propagación hacia adelante, cada capa l toma las salidas de la capa anterior, al−1, como entradas y calcula sus propias salidas. Por lo tanto, el método forward()
de la clase Layer
toma el vector de salidas previas como su único parámetro, mientras que el resto de la información necesaria se almacena dentro de la clase.
En la propagación hacia atrás, cada capa l solo necesita dal para calcular los gradientes respectivos y devolver dal−1, por lo que el método backward()
toma el vector dal como parámetro. El resto de la información requerida ya está almacenada en la clase Layer
.
Derivadas de funciones de activación
Dado que las derivadas de las funciones de activación son necesarias para la retropropagación, funciones de activación como ReLU y sigmoide deben estructurarse como clases en lugar de funciones independientes. Esto nos permite definir tanto:
- La propia función de activación (implementada mediante el método
__call__()
), permitiendo que se aplique directamente en la claseLayer
usandoself.activation(z)
; - Su derivada (implementada mediante el método
derivative()
), lo que permite una retropropagación eficiente y se utiliza en la claseLayer
comoself.activation.derivative(z)
.
Al estructurar las funciones de activación como objetos, podemos pasarlas fácilmente a la clase Layer
y usarlas de manera dinámica.
ReLu
La derivada de la función de activación ReLU es la siguiente, donde zi es un elemento del vector de preactivaciones z:
f′(zi)={1,zi>00,zi≤0class ReLU:
def __call__(self, z):
return np.maximum(0, z)
def derivative(self, z):
return (z > 0).astype(float)
Sigmoide
La derivada de la función de activación sigmoide es la siguiente:
f′(zi)=f(zi)⋅(1−f(zi))class Sigmoid:
def __call__(self, x):
return 1 / (1 + np.exp(-z))
def derivative(self, z):
sig = self(z)
return sig * (1 - sig)
Para ambas funciones de activación, se aplican al vector completo z, y lo mismo ocurre con sus derivadas. NumPy aplica internamente la operación a cada elemento del vector. Por ejemplo, si el vector z contiene 3 elementos, la derivación es la siguiente:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)El método backward()
El método backward()
se encarga de calcular los gradientes utilizando las siguientes fórmulas:
a^{l-1} y zl se almacenan como los atributos inputs
y outputs
en la clase Layer
, respectivamente. La función de activación f se almacena como el atributo activation
.
Una vez que se han calculado todos los gradientes necesarios, los pesos y sesgos pueden actualizarse ya que no se requieren para cálculos posteriores:
Wlbl=Wl−α⋅dWl=bl−α⋅dblPor lo tanto, learning_rate
(α) es otro parámetro de este método.
def backward(self, da, learning_rate):
dz = ...
d_weights = ...
d_biases = ...
da_prev = ...
self.weights -= learning_rate * d_weights
self.biases -= learning_rate * d_biases
return da_prev
El operador *
realiza una multiplicación elemento a elemento, mientras que la función np.dot()
realiza el producto punto en NumPy. El atributo .T
transpone un arreglo.
¡Gracias por tus comentarios!
Pregunte a AI
Pregunte a AI
Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla
Can you explain how the backward() method uses the stored attributes in the Layer class?
What is the purpose of the activation function's derivative in backpropagation?
Could you provide an example of how to use these activation function classes in a neural network layer?
Awesome!
Completion rate improved to 4
Implementación de Retropropagación
Desliza para mostrar el menú
Enfoque general
En la propagación hacia adelante, cada capa l toma las salidas de la capa anterior, al−1, como entradas y calcula sus propias salidas. Por lo tanto, el método forward()
de la clase Layer
toma el vector de salidas previas como su único parámetro, mientras que el resto de la información necesaria se almacena dentro de la clase.
En la propagación hacia atrás, cada capa l solo necesita dal para calcular los gradientes respectivos y devolver dal−1, por lo que el método backward()
toma el vector dal como parámetro. El resto de la información requerida ya está almacenada en la clase Layer
.
Derivadas de funciones de activación
Dado que las derivadas de las funciones de activación son necesarias para la retropropagación, funciones de activación como ReLU y sigmoide deben estructurarse como clases en lugar de funciones independientes. Esto nos permite definir tanto:
- La propia función de activación (implementada mediante el método
__call__()
), permitiendo que se aplique directamente en la claseLayer
usandoself.activation(z)
; - Su derivada (implementada mediante el método
derivative()
), lo que permite una retropropagación eficiente y se utiliza en la claseLayer
comoself.activation.derivative(z)
.
Al estructurar las funciones de activación como objetos, podemos pasarlas fácilmente a la clase Layer
y usarlas de manera dinámica.
ReLu
La derivada de la función de activación ReLU es la siguiente, donde zi es un elemento del vector de preactivaciones z:
f′(zi)={1,zi>00,zi≤0class ReLU:
def __call__(self, z):
return np.maximum(0, z)
def derivative(self, z):
return (z > 0).astype(float)
Sigmoide
La derivada de la función de activación sigmoide es la siguiente:
f′(zi)=f(zi)⋅(1−f(zi))class Sigmoid:
def __call__(self, x):
return 1 / (1 + np.exp(-z))
def derivative(self, z):
sig = self(z)
return sig * (1 - sig)
Para ambas funciones de activación, se aplican al vector completo z, y lo mismo ocurre con sus derivadas. NumPy aplica internamente la operación a cada elemento del vector. Por ejemplo, si el vector z contiene 3 elementos, la derivación es la siguiente:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)El método backward()
El método backward()
se encarga de calcular los gradientes utilizando las siguientes fórmulas:
a^{l-1} y zl se almacenan como los atributos inputs
y outputs
en la clase Layer
, respectivamente. La función de activación f se almacena como el atributo activation
.
Una vez que se han calculado todos los gradientes necesarios, los pesos y sesgos pueden actualizarse ya que no se requieren para cálculos posteriores:
Wlbl=Wl−α⋅dWl=bl−α⋅dblPor lo tanto, learning_rate
(α) es otro parámetro de este método.
def backward(self, da, learning_rate):
dz = ...
d_weights = ...
d_biases = ...
da_prev = ...
self.weights -= learning_rate * d_weights
self.biases -= learning_rate * d_biases
return da_prev
El operador *
realiza una multiplicación elemento a elemento, mientras que la función np.dot()
realiza el producto punto en NumPy. El atributo .T
transpone un arreglo.
¡Gracias por tus comentarios!