Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre Implémentation de la Rétropropagation | Réseau de Neurones à Partir de Zéro
Introduction aux Réseaux de Neurones

bookImplémentation de la Rétropropagation

Approche générale

Lors de la propagation avant, chaque couche ll prend les sorties de la couche précédente, al1a^{l-1}, comme entrées et calcule ses propres sorties. Ainsi, la méthode forward() de la classe Layer prend le vecteur des sorties précédentes comme unique paramètre, tandis que le reste des informations nécessaires est stocké dans la classe.

Lors de la rétropropagation, chaque couche ll a seulement besoin de dalda^l pour calculer les gradients correspondants et retourner dal1da^{l-1}, donc la méthode backward() prend le vecteur dalda^l comme paramètre. Le reste des informations requises est déjà stocké dans la classe Layer.

Dérivées des fonctions d'activation

Puisque les dérivées des fonctions d'activation sont nécessaires pour la rétropropagation, les fonctions d'activation telles que ReLU et sigmoïde doivent être implémentées sous forme de classes plutôt que de fonctions autonomes. Cette structure permet de définir clairement les deux composants :

  1. La fonction d'activation elle-même — implémentée via la méthode __call__(), afin qu'elle puisse être appliquée directement dans la classe Layer avec self.activation(z) ;
  2. Sa dérivée — implémentée via la méthode derivative(), permettant un calcul efficace lors de la rétropropagation via self.activation.derivative(z).

Représenter les fonctions d'activation sous forme d'objets facilite leur passage à différentes couches et leur application dynamique lors de la propagation avant et arrière.

ReLu

La dérivée de la fonction d'activation ReLU est la suivante, où ziz_i est un élément du vecteur des pré-activations zz :

f(zi)={1,zi>00,zi0f'(z_i) = \begin{cases} 1, z_i > 0\\ 0, z_i \le 0 \end{cases}
class ReLU:
    def __call__(self, z):
        return np.maximum(0, z)

    def derivative(self, z):
        return (z > 0).astype(float)

Sigmoïde

La dérivée de la fonction d'activation sigmoïde est la suivante :

f(zi)=f(zi)(1f(zi))f'(z_i) = f(z_i) \cdot (1 - f(z_i))
class Sigmoid:
    def __call__(self, x):
        return 1 / (1 + np.exp(-z))

    def derivative(self, z):
        sig = self(z)
        return sig * (1 - sig)

Pour les deux fonctions d'activation, l'opération est appliquée à l'ensemble du vecteur zz, ainsi qu'à sa dérivée. NumPy effectue automatiquement le calcul élément par élément, ce qui signifie que chaque élément du vecteur est traité indépendamment.

Par exemple, si le vecteur zz contient trois éléments, la dérivée est calculée comme suit :

f(z)=f([z1z2z3])=[f(z1)f(z2)f(z3)]f'(z) = f'\left( \begin{bmatrix} z_1\\ z_2\\ z_3 \end{bmatrix} \right) = \begin{bmatrix} f'(z_1)\\ f'(z_2)\\ f'(z_3) \end{bmatrix}

La méthode backward()

La méthode backward() est responsable du calcul des gradients en utilisant les formules ci-dessous :

dzl=dalfl(zl)dWl=dzl(al1)Tdbl=dzldal1=(Wl)Tdzl\begin{aligned} dz^l &= da^l \odot f'^l(z^l)\\ dW^l &= dz^l \cdot (a^{l-1})^T\\ db^l &= dz^l\\ da^{l-1} &= (W^l)^T \cdot dz^l \end{aligned}

a^{l-1} et zlz^l sont stockés respectivement comme attributs inputs et outputs dans la classe Layer. La fonction d'activation ff est stockée comme attribut activation.

Une fois tous les gradients nécessaires calculés, les poids et biais peuvent être mis à jour car ils ne sont plus requis pour les calculs ultérieurs :

Wl=WlαdWlbl=blαdbl\begin{aligned} W^l &= W^l - \alpha \cdot dW^l\\ b^l &= b^l - \alpha \cdot db^l \end{aligned}

Ainsi, learning_rate (α\alpha) est un autre paramètre de cette méthode.

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
Note
Remarque

L’opérateur * effectue une multiplication élément par élément, tandis que la fonction np.dot() réalise un produit scalaire dans NumPy. L’attribut .T transpose un tableau.

question mark

Laquelle des propositions suivantes décrit le mieux le rôle de la méthode backward() dans la classe Layer lors de la rétropropagation ?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 2. Chapitre 8

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

Suggested prompts:

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

bookImplémentation de la Rétropropagation

Glissez pour afficher le menu

Approche générale

Lors de la propagation avant, chaque couche ll prend les sorties de la couche précédente, al1a^{l-1}, comme entrées et calcule ses propres sorties. Ainsi, la méthode forward() de la classe Layer prend le vecteur des sorties précédentes comme unique paramètre, tandis que le reste des informations nécessaires est stocké dans la classe.

Lors de la rétropropagation, chaque couche ll a seulement besoin de dalda^l pour calculer les gradients correspondants et retourner dal1da^{l-1}, donc la méthode backward() prend le vecteur dalda^l comme paramètre. Le reste des informations requises est déjà stocké dans la classe Layer.

Dérivées des fonctions d'activation

Puisque les dérivées des fonctions d'activation sont nécessaires pour la rétropropagation, les fonctions d'activation telles que ReLU et sigmoïde doivent être implémentées sous forme de classes plutôt que de fonctions autonomes. Cette structure permet de définir clairement les deux composants :

  1. La fonction d'activation elle-même — implémentée via la méthode __call__(), afin qu'elle puisse être appliquée directement dans la classe Layer avec self.activation(z) ;
  2. Sa dérivée — implémentée via la méthode derivative(), permettant un calcul efficace lors de la rétropropagation via self.activation.derivative(z).

Représenter les fonctions d'activation sous forme d'objets facilite leur passage à différentes couches et leur application dynamique lors de la propagation avant et arrière.

ReLu

La dérivée de la fonction d'activation ReLU est la suivante, où ziz_i est un élément du vecteur des pré-activations zz :

f(zi)={1,zi>00,zi0f'(z_i) = \begin{cases} 1, z_i > 0\\ 0, z_i \le 0 \end{cases}
class ReLU:
    def __call__(self, z):
        return np.maximum(0, z)

    def derivative(self, z):
        return (z > 0).astype(float)

Sigmoïde

La dérivée de la fonction d'activation sigmoïde est la suivante :

f(zi)=f(zi)(1f(zi))f'(z_i) = f(z_i) \cdot (1 - f(z_i))
class Sigmoid:
    def __call__(self, x):
        return 1 / (1 + np.exp(-z))

    def derivative(self, z):
        sig = self(z)
        return sig * (1 - sig)

Pour les deux fonctions d'activation, l'opération est appliquée à l'ensemble du vecteur zz, ainsi qu'à sa dérivée. NumPy effectue automatiquement le calcul élément par élément, ce qui signifie que chaque élément du vecteur est traité indépendamment.

Par exemple, si le vecteur zz contient trois éléments, la dérivée est calculée comme suit :

f(z)=f([z1z2z3])=[f(z1)f(z2)f(z3)]f'(z) = f'\left( \begin{bmatrix} z_1\\ z_2\\ z_3 \end{bmatrix} \right) = \begin{bmatrix} f'(z_1)\\ f'(z_2)\\ f'(z_3) \end{bmatrix}

La méthode backward()

La méthode backward() est responsable du calcul des gradients en utilisant les formules ci-dessous :

dzl=dalfl(zl)dWl=dzl(al1)Tdbl=dzldal1=(Wl)Tdzl\begin{aligned} dz^l &= da^l \odot f'^l(z^l)\\ dW^l &= dz^l \cdot (a^{l-1})^T\\ db^l &= dz^l\\ da^{l-1} &= (W^l)^T \cdot dz^l \end{aligned}

a^{l-1} et zlz^l sont stockés respectivement comme attributs inputs et outputs dans la classe Layer. La fonction d'activation ff est stockée comme attribut activation.

Une fois tous les gradients nécessaires calculés, les poids et biais peuvent être mis à jour car ils ne sont plus requis pour les calculs ultérieurs :

Wl=WlαdWlbl=blαdbl\begin{aligned} W^l &= W^l - \alpha \cdot dW^l\\ b^l &= b^l - \alpha \cdot db^l \end{aligned}

Ainsi, learning_rate (α\alpha) est un autre paramètre de cette méthode.

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
Note
Remarque

L’opérateur * effectue une multiplication élément par élément, tandis que la fonction np.dot() réalise un produit scalaire dans NumPy. L’attribut .T transpose un tableau.

question mark

Laquelle des propositions suivantes décrit le mieux le rôle de la méthode backward() dans la classe Layer lors de la rétropropagation ?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 2. Chapitre 8
some-alt