Implementação do Backpropagation
Abordagem Geral
Na propagação direta, cada camada l recebe as saídas da camada anterior, al−1, como entradas e calcula suas próprias saídas. Portanto, o método forward() da classe Layer recebe o vetor de saídas anteriores como seu único parâmetro, enquanto o restante das informações necessárias é armazenado dentro da classe.
Na propagação reversa, cada camada l precisa apenas de dal para calcular os respectivos gradientes e retornar dal−1, então o método backward() recebe o vetor dal como parâmetro. O restante das informações necessárias já está armazenado na classe Layer.
Derivadas das Funções de Ativação
Como as derivadas das funções de ativação são necessárias para a propagação reversa, funções de ativação como ReLU e sigmoide devem ser implementadas como classes em vez de funções isoladas. Essa estrutura permite definir claramente ambos os componentes:
- A própria função de ativação — implementada usando o método
__call__(), para que possa ser aplicada diretamente na classeLayercomself.activation(z); - Sua derivada — implementada usando o método
derivative(), permitindo o cálculo eficiente durante a propagação reversa viaself.activation.derivative(z).
Representar funções de ativação como objetos facilita o repasse para diferentes camadas e a aplicação dinâmica durante a propagação direta e reversa.
ReLu
A derivada da função de ativação ReLU é a seguinte, onde zi é um elemento do vetor de pré-ativações 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)
Sigmoid
A derivada da função de ativação sigmoid é a seguinte:
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 as funções de ativação, a operação é aplicada a todo o vetor z, assim como à sua derivada. O NumPy realiza automaticamente o cálculo elemento a elemento, ou seja, cada elemento do vetor é processado de forma independente.
Por exemplo, se o vetor z contém três elementos, a derivada é calculada como:
f′(z)=f′z1z2z3=f′(z1)f′(z2)f′(z3)O método backward()
O método backward() é responsável por calcular os gradientes utilizando as fórmulas abaixo:
a^{l-1} e zl são armazenados como os atributos inputs e outputs na classe Layer, respectivamente. A função de ativação f é armazenada como o atributo activation.
Após todos os gradientes necessários serem calculados, os pesos e biases podem ser atualizados, pois não são mais necessários para cálculos posteriores:
Wlbl=Wl−α⋅dWl=bl−α⋅dblPortanto, learning_rate (α) é outro parâmetro deste 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
O operador * realiza a multiplicação elemento a elemento, enquanto a função np.dot() executa o produto escalar no NumPy. O atributo .T transpõe um array.
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo
Can you explain how the backward() method uses the stored attributes in the Layer class?
What is the purpose of the derivative() method in the activation function classes?
Could you provide an example of how forward and backward propagation work together in a simple neural network?
Awesome!
Completion rate improved to 4
Implementação do Backpropagation
Deslize para mostrar o menu
Abordagem Geral
Na propagação direta, cada camada l recebe as saídas da camada anterior, al−1, como entradas e calcula suas próprias saídas. Portanto, o método forward() da classe Layer recebe o vetor de saídas anteriores como seu único parâmetro, enquanto o restante das informações necessárias é armazenado dentro da classe.
Na propagação reversa, cada camada l precisa apenas de dal para calcular os respectivos gradientes e retornar dal−1, então o método backward() recebe o vetor dal como parâmetro. O restante das informações necessárias já está armazenado na classe Layer.
Derivadas das Funções de Ativação
Como as derivadas das funções de ativação são necessárias para a propagação reversa, funções de ativação como ReLU e sigmoide devem ser implementadas como classes em vez de funções isoladas. Essa estrutura permite definir claramente ambos os componentes:
- A própria função de ativação — implementada usando o método
__call__(), para que possa ser aplicada diretamente na classeLayercomself.activation(z); - Sua derivada — implementada usando o método
derivative(), permitindo o cálculo eficiente durante a propagação reversa viaself.activation.derivative(z).
Representar funções de ativação como objetos facilita o repasse para diferentes camadas e a aplicação dinâmica durante a propagação direta e reversa.
ReLu
A derivada da função de ativação ReLU é a seguinte, onde zi é um elemento do vetor de pré-ativações 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)
Sigmoid
A derivada da função de ativação sigmoid é a seguinte:
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 as funções de ativação, a operação é aplicada a todo o vetor z, assim como à sua derivada. O NumPy realiza automaticamente o cálculo elemento a elemento, ou seja, cada elemento do vetor é processado de forma independente.
Por exemplo, se o vetor z contém três elementos, a derivada é calculada como:
f′(z)=f′z1z2z3=f′(z1)f′(z2)f′(z3)O método backward()
O método backward() é responsável por calcular os gradientes utilizando as fórmulas abaixo:
a^{l-1} e zl são armazenados como os atributos inputs e outputs na classe Layer, respectivamente. A função de ativação f é armazenada como o atributo activation.
Após todos os gradientes necessários serem calculados, os pesos e biases podem ser atualizados, pois não são mais necessários para cálculos posteriores:
Wlbl=Wl−α⋅dWl=bl−α⋅dblPortanto, learning_rate (α) é outro parâmetro deste 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
O operador * realiza a multiplicação elemento a elemento, enquanto a função np.dot() executa o produto escalar no NumPy. O atributo .T transpõe um array.
Obrigado pelo seu feedback!