Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lära Implementering av Backpropagation | Neuronnätverk Från Grunden
Introduktion till neurala nätverk

bookImplementering av Backpropagation

Allmän metod

Vid framåtriktad propagiering tar varje lager ll utdata från föregående lager, al1a^{l-1}, som indata och beräknar sina egna utdata. Därför tar metoden forward() i klassen Layer vektorn av föregående utdata som sin enda parameter, medan övrig nödvändig information lagras inom klassen.

Vid bakåtriktad propagiering behöver varje lager ll endast dalda^l för att beräkna respektive gradienter och returnera dal1da^{l-1}, så metoden backward() tar vektorn dalda^l som parameter. Övrig nödvändig information finns redan lagrad i klassen Layer.

Derivator av aktiveringsfunktioner

Eftersom derivator av aktiveringsfunktioner behövs för bakåtriktad propagiering, bör aktiveringsfunktioner som ReLU och sigmoid struktureras som klasser istället för fristående funktioner. Detta gör det möjligt att definiera både:

  1. Själva aktiveringsfunktionen (implementerad via metoden __call__()), vilket möjliggör direkt användning i klassen Layer med self.activation(z);
  2. Dess derivata (implementerad via metoden derivative()), vilket möjliggör effektiv bakåtriktad propagiering och används i klassen Layer som self.activation.derivative(z).

Genom att strukturera aktiveringsfunktioner som objekt kan vi enkelt skicka dem till klassen Layer och använda dem dynamiskt.

ReLu

Derivatan av ReLU-aktiveringsfunktionen är följande, där ziz_i är ett element i vektorn av pre-aktiveringar 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

Derivatan av sigmoid-aktiveringsfunktionen är följande:

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)

För båda dessa aktiveringsfunktioner tillämpas de på hela vektorn zz, och detsamma gäller för deras derivator. NumPy utför operationen på varje element i vektorn. Till exempel, om vektorn zz innehåller 3 element, är deriveringen enligt följande:

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}

Metoden backward()

Metoden backward() ansvarar för beräkning av gradienter med hjälp av formlerna nedan:

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} och zlz^l lagras som attributen inputs respektive outputs i klassen Layer. Aktiveringsfunktionen ff lagras som attributet activation.

När alla nödvändiga gradienter har beräknats kan vikter och bias uppdateras eftersom de inte längre behövs för vidare beräkning:

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}

Därför är learning_rate (α\alpha) en annan parameter för denna metod.

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
Notering

*-operatorn utför elementvis multiplikation, medan funktionen np.dot() utför skalärprodukt i NumPy. Attributet .T transponerar en array.

question mark

Vilket av följande beskriver bäst rollen för metoden backward() i klassen Layer under backpropagation?

Select the correct answer

Var allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 2. Kapitel 8

Fråga AI

expand

Fråga AI

ChatGPT

Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal

Awesome!

Completion rate improved to 4

bookImplementering av Backpropagation

Svep för att visa menyn

Allmän metod

Vid framåtriktad propagiering tar varje lager ll utdata från föregående lager, al1a^{l-1}, som indata och beräknar sina egna utdata. Därför tar metoden forward() i klassen Layer vektorn av föregående utdata som sin enda parameter, medan övrig nödvändig information lagras inom klassen.

Vid bakåtriktad propagiering behöver varje lager ll endast dalda^l för att beräkna respektive gradienter och returnera dal1da^{l-1}, så metoden backward() tar vektorn dalda^l som parameter. Övrig nödvändig information finns redan lagrad i klassen Layer.

Derivator av aktiveringsfunktioner

Eftersom derivator av aktiveringsfunktioner behövs för bakåtriktad propagiering, bör aktiveringsfunktioner som ReLU och sigmoid struktureras som klasser istället för fristående funktioner. Detta gör det möjligt att definiera både:

  1. Själva aktiveringsfunktionen (implementerad via metoden __call__()), vilket möjliggör direkt användning i klassen Layer med self.activation(z);
  2. Dess derivata (implementerad via metoden derivative()), vilket möjliggör effektiv bakåtriktad propagiering och används i klassen Layer som self.activation.derivative(z).

Genom att strukturera aktiveringsfunktioner som objekt kan vi enkelt skicka dem till klassen Layer och använda dem dynamiskt.

ReLu

Derivatan av ReLU-aktiveringsfunktionen är följande, där ziz_i är ett element i vektorn av pre-aktiveringar 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

Derivatan av sigmoid-aktiveringsfunktionen är följande:

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)

För båda dessa aktiveringsfunktioner tillämpas de på hela vektorn zz, och detsamma gäller för deras derivator. NumPy utför operationen på varje element i vektorn. Till exempel, om vektorn zz innehåller 3 element, är deriveringen enligt följande:

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}

Metoden backward()

Metoden backward() ansvarar för beräkning av gradienter med hjälp av formlerna nedan:

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} och zlz^l lagras som attributen inputs respektive outputs i klassen Layer. Aktiveringsfunktionen ff lagras som attributet activation.

När alla nödvändiga gradienter har beräknats kan vikter och bias uppdateras eftersom de inte längre behövs för vidare beräkning:

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}

Därför är learning_rate (α\alpha) en annan parameter för denna metod.

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
Notering

*-operatorn utför elementvis multiplikation, medan funktionen np.dot() utför skalärprodukt i NumPy. Attributet .T transponerar en array.

question mark

Vilket av följande beskriver bäst rollen för metoden backward() i klassen Layer under backpropagation?

Select the correct answer

Var allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 2. Kapitel 8
some-alt