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 comme ReLU et sigmoïde doivent être structurées comme des classes plutôt que comme des fonctions autonomes. Cela permet de définir à la fois :

  1. La fonction d'activation elle-même (implémentée via la méthode __call__()), permettant son application directe dans la classe Layer avec self.activation(z) ;
  2. Sa dérivée (implémentée via la méthode derivative()), permettant une rétropropagation efficace et utilisée dans la classe Layer comme self.activation.derivative(z).

En structurant les fonctions d'activation comme des objets, il est facile de les passer à la classe Layer et de les utiliser dynamiquement.

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 ces deux fonctions d'activation, l'application se fait sur l'ensemble du vecteur zz, ainsi que pour leurs dérivées. NumPy applique l'opération à chaque élément du vecteur. Par exemple, si le vecteur zz contient 3 éléments, la dérivation est la suivante :

f(z)=f([z1z2z3])=[f(z1)f(z2)f(z3)]f'(z) = f'( \begin{bmatrix} z_1\\ z_2\\ z_3 \end{bmatrix} ) = \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 des 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

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 comme ReLU et sigmoïde doivent être structurées comme des classes plutôt que comme des fonctions autonomes. Cela permet de définir à la fois :

  1. La fonction d'activation elle-même (implémentée via la méthode __call__()), permettant son application directe dans la classe Layer avec self.activation(z) ;
  2. Sa dérivée (implémentée via la méthode derivative()), permettant une rétropropagation efficace et utilisée dans la classe Layer comme self.activation.derivative(z).

En structurant les fonctions d'activation comme des objets, il est facile de les passer à la classe Layer et de les utiliser dynamiquement.

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 ces deux fonctions d'activation, l'application se fait sur l'ensemble du vecteur zz, ainsi que pour leurs dérivées. NumPy applique l'opération à chaque élément du vecteur. Par exemple, si le vecteur zz contient 3 éléments, la dérivation est la suivante :

f(z)=f([z1z2z3])=[f(z1)f(z2)f(z3)]f'(z) = f'( \begin{bmatrix} z_1\\ z_2\\ z_3 \end{bmatrix} ) = \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 des 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