Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Implementatie van Backpropagation | Neuraal Netwerk Vanaf Nul
Introductie tot Neurale Netwerken

bookImplementatie van Backpropagation

Algemene aanpak

Bij voorwaartse propagatie neemt elke laag ll de uitgangen van de vorige laag, al1a^{l-1}, als invoer en berekent zijn eigen uitgangen. Daarom neemt de forward()-methode van de Layer-klasse de vector van vorige uitgangen als enige parameter, terwijl de overige benodigde informatie binnen de klasse wordt opgeslagen.

Bij achterwaartse propagatie heeft elke laag ll alleen dalda^l nodig om de respectievelijke gradiënten te berekenen en dal1da^{l-1} terug te geven, dus de backward()-methode neemt de dalda^l-vector als parameter. De rest van de benodigde informatie is al opgeslagen in de Layer-klasse.

Afgeleiden van activatiefuncties

Omdat afgeleiden van activatiefuncties nodig zijn voor achterwaartse propagatie, moeten activatiefuncties zoals ReLU en sigmoid worden opgezet als klassen in plaats van losse functies. Dit stelt ons in staat om zowel:

  1. De activatiefunctie zelf (geïmplementeerd via de __call__()-methode), zodat deze direct kan worden toegepast in de Layer-klasse met self.activation(z);
  2. De afgeleide ervan (geïmplementeerd via de derivative()-methode), wat efficiënte achterwaartse propagatie mogelijk maakt en wordt gebruikt in de Layer-klasse als self.activation.derivative(z).

Door activatiefuncties als objecten te structureren, kunnen we ze eenvoudig doorgeven aan de Layer-klasse en dynamisch gebruiken.

ReLu

De afgeleide van de ReLU-activatiefunctie is als volgt, waarbij ziz_i een element is van de vector van pre-activaties 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)

Sigmoid

De afgeleide van de sigmoid activatiefunctie is als volgt:

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)

Voor beide activatiefuncties passen we deze toe op de volledige vector zz, evenals hun afgeleiden. NumPy past de bewerking intern toe op elk element van de vector. Bijvoorbeeld, als de vector zz 3 elementen bevat, is de afleiding als volgt:

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}

De backward()-methode

De backward()-methode is verantwoordelijk voor het berekenen van de gradiënten met behulp van de onderstaande formules:

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} en zlz^l worden respectievelijk opgeslagen als de attributen inputs en outputs in de Layer-klasse. De activatiefunctie ff wordt opgeslagen als het attribuut activation.

Zodra alle benodigde gradiënten zijn berekend, kunnen de gewichten en biases worden bijgewerkt, omdat ze niet langer nodig zijn voor verdere berekeningen:

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}

Daarom is learning_rate (α\alpha) een andere parameter van deze methode.

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
Opmerking

De *-operator voert elementgewijze vermenigvuldiging uit, terwijl de functie np.dot() een dotproduct uitvoert in NumPy. Het attribuut .T transponeert een array.

question mark

Welke van de volgende beschrijvingen geeft het beste de rol van de methode backward() in de klasse Layer weer tijdens backpropagation?

Select the correct answer

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 2. Hoofdstuk 8

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

Awesome!

Completion rate improved to 4

bookImplementatie van Backpropagation

Veeg om het menu te tonen

Algemene aanpak

Bij voorwaartse propagatie neemt elke laag ll de uitgangen van de vorige laag, al1a^{l-1}, als invoer en berekent zijn eigen uitgangen. Daarom neemt de forward()-methode van de Layer-klasse de vector van vorige uitgangen als enige parameter, terwijl de overige benodigde informatie binnen de klasse wordt opgeslagen.

Bij achterwaartse propagatie heeft elke laag ll alleen dalda^l nodig om de respectievelijke gradiënten te berekenen en dal1da^{l-1} terug te geven, dus de backward()-methode neemt de dalda^l-vector als parameter. De rest van de benodigde informatie is al opgeslagen in de Layer-klasse.

Afgeleiden van activatiefuncties

Omdat afgeleiden van activatiefuncties nodig zijn voor achterwaartse propagatie, moeten activatiefuncties zoals ReLU en sigmoid worden opgezet als klassen in plaats van losse functies. Dit stelt ons in staat om zowel:

  1. De activatiefunctie zelf (geïmplementeerd via de __call__()-methode), zodat deze direct kan worden toegepast in de Layer-klasse met self.activation(z);
  2. De afgeleide ervan (geïmplementeerd via de derivative()-methode), wat efficiënte achterwaartse propagatie mogelijk maakt en wordt gebruikt in de Layer-klasse als self.activation.derivative(z).

Door activatiefuncties als objecten te structureren, kunnen we ze eenvoudig doorgeven aan de Layer-klasse en dynamisch gebruiken.

ReLu

De afgeleide van de ReLU-activatiefunctie is als volgt, waarbij ziz_i een element is van de vector van pre-activaties 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)

Sigmoid

De afgeleide van de sigmoid activatiefunctie is als volgt:

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)

Voor beide activatiefuncties passen we deze toe op de volledige vector zz, evenals hun afgeleiden. NumPy past de bewerking intern toe op elk element van de vector. Bijvoorbeeld, als de vector zz 3 elementen bevat, is de afleiding als volgt:

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}

De backward()-methode

De backward()-methode is verantwoordelijk voor het berekenen van de gradiënten met behulp van de onderstaande formules:

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} en zlz^l worden respectievelijk opgeslagen als de attributen inputs en outputs in de Layer-klasse. De activatiefunctie ff wordt opgeslagen als het attribuut activation.

Zodra alle benodigde gradiënten zijn berekend, kunnen de gewichten en biases worden bijgewerkt, omdat ze niet langer nodig zijn voor verdere berekeningen:

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}

Daarom is learning_rate (α\alpha) een andere parameter van deze methode.

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
Opmerking

De *-operator voert elementgewijze vermenigvuldiging uit, terwijl de functie np.dot() een dotproduct uitvoert in NumPy. Het attribuut .T transponeert een array.

question mark

Welke van de volgende beschrijvingen geeft het beste de rol van de methode backward() in de klasse Layer weer tijdens backpropagation?

Select the correct answer

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 2. Hoofdstuk 8
some-alt