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 med Python

bookImplementering av Backpropagation

Allmän metod

Vid framåtriktad spridning 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 spridning 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. Resterande nödvändig information finns redan lagrad i klassen Layer.

Derivator av aktiveringsfunktioner

Eftersom derivator av aktiveringsfunktioner krävs för bakåtriktad spridning, bör aktiveringsfunktioner som ReLU och sigmoid implementeras som klasser istället för fristående funktioner. Denna struktur möjliggör tydlig definition av båda komponenterna:

  1. Själva aktiveringsfunktionen — implementerad med metoden __call__(), så att den kan tillämpas direkt i klassen Layer med self.activation(z);
  2. Dess derivata — implementerad med metoden derivative(), vilket möjliggör effektiv beräkning under bakåtriktad spridning via self.activation.derivative(z).

Att representera aktiveringsfunktioner som objekt gör det enkelt att överföra dem till olika lager och tillämpa dem dynamiskt under både framåt- och bakåtriktad spridning.

ReLu

Derivatan av ReLU-aktiveringsfunktionen är följande, där ziz_i är ett element i vektorn av preaktiveringar 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 aktiveringsfunktionerna tillämpas operationen på hela vektorn zz, samt på dess derivata. NumPy utför automatiskt beräkningen elementvis, vilket innebär att varje element i vektorn behandlas oberoende.

Till exempel, om vektorn zz innehåller tre element, beräknas derivatan som:

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}

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 vikterna och biaserna uppdateras eftersom de inte längre behövs för vidare beräkningar:

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
Notera

*-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

bookImplementering av Backpropagation

Svep för att visa menyn

Allmän metod

Vid framåtriktad spridning 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 spridning 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. Resterande nödvändig information finns redan lagrad i klassen Layer.

Derivator av aktiveringsfunktioner

Eftersom derivator av aktiveringsfunktioner krävs för bakåtriktad spridning, bör aktiveringsfunktioner som ReLU och sigmoid implementeras som klasser istället för fristående funktioner. Denna struktur möjliggör tydlig definition av båda komponenterna:

  1. Själva aktiveringsfunktionen — implementerad med metoden __call__(), så att den kan tillämpas direkt i klassen Layer med self.activation(z);
  2. Dess derivata — implementerad med metoden derivative(), vilket möjliggör effektiv beräkning under bakåtriktad spridning via self.activation.derivative(z).

Att representera aktiveringsfunktioner som objekt gör det enkelt att överföra dem till olika lager och tillämpa dem dynamiskt under både framåt- och bakåtriktad spridning.

ReLu

Derivatan av ReLU-aktiveringsfunktionen är följande, där ziz_i är ett element i vektorn av preaktiveringar 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 aktiveringsfunktionerna tillämpas operationen på hela vektorn zz, samt på dess derivata. NumPy utför automatiskt beräkningen elementvis, vilket innebär att varje element i vektorn behandlas oberoende.

Till exempel, om vektorn zz innehåller tre element, beräknas derivatan som:

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}

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 vikterna och biaserna uppdateras eftersom de inte längre behövs för vidare beräkningar:

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
Notera

*-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