Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Implementering av Backpropagation | Nevralt Nettverk fra Bunnen Av
Introduksjon til nevrale nettverk

bookImplementering av Backpropagation

Generell tilnærming

Ved fremoverpropagering tar hvert lag ll utgangene fra forrige lag, al1a^{l-1}, som input og beregner sine egne utganger. Derfor tar forward()-metoden i Layer-klassen vektoren av forrige utganger som eneste parameter, mens resten av nødvendig informasjon lagres i klassen.

Ved bakoverpropagering trenger hvert lag ll kun dalda^l for å beregne de respektive gradientene og returnere dal1da^{l-1}, så backward()-metoden tar dalda^l-vektoren som parameter. Resten av nødvendig informasjon er allerede lagret i Layer-klassen.

Derivater av aktiveringsfunksjoner

Siden derivater av aktiveringsfunksjoner er nødvendige for bakoverpropagering, bør aktiveringsfunksjoner som ReLU og sigmoid implementeres som klasser i stedet for frittstående funksjoner. Denne strukturen gjør det mulig å definere begge komponentene tydelig:

  1. Selve aktiveringsfunksjonen — implementert med __call__()-metoden, slik at den kan brukes direkte i Layer-klassen med self.activation(z);
  2. Dens derivat — implementert med derivative()-metoden, som gir effektiv beregning under bakoverpropagering via self.activation.derivative(z).

Å representere aktiveringsfunksjoner som objekter gjør det enkelt å sende dem til ulike lag og bruke dem dynamisk under både fremover- og bakoverpropagering.

ReLu

Derivatet av ReLU-aktiveringsfunksjonen er som følger, der ziz_i er et element i vektoren av pre-aktiveringer 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

Derivert av sigmoid aktiveringsfunksjon er som følger:

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)

For begge aktiveringsfunksjonene blir operasjonen brukt på hele vektoren zz, samt på dens derivert. NumPy utfører automatisk beregningen elementvis, noe som betyr at hvert element i vektoren behandles uavhengig.

For eksempel, hvis vektoren zz inneholder tre elementer, beregnes den deriverte slik:

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() er ansvarlig for beregning av gradientene ved hjelp av følgende formler:

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} og zlz^l lagres som henholdsvis inputs og outputs attributter i Layer-klassen. Aktiveringsfunksjonen ff lagres som attributtet activation.

Når alle nødvendige gradienter er beregnet, kan vektene og biasene oppdateres siden de ikke lenger trengs for videre beregning:

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}

Dermed er learning_rate (α\alpha) en annen parameter for denne metoden.

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
Merk

Operatoren * utfører elementvis multiplikasjon, mens funksjonen np.dot() utfører skalarprodukt i NumPy. Attributtet .T transponerer et array.

question mark

Hvilket av følgende beskriver best rollen til backward()-metoden i Layer-klassen under tilbakepropagering?

Select the correct answer

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 2. Kapittel 8

Spør AI

expand

Spør AI

ChatGPT

Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår

Awesome!

Completion rate improved to 4

bookImplementering av Backpropagation

Sveip for å vise menyen

Generell tilnærming

Ved fremoverpropagering tar hvert lag ll utgangene fra forrige lag, al1a^{l-1}, som input og beregner sine egne utganger. Derfor tar forward()-metoden i Layer-klassen vektoren av forrige utganger som eneste parameter, mens resten av nødvendig informasjon lagres i klassen.

Ved bakoverpropagering trenger hvert lag ll kun dalda^l for å beregne de respektive gradientene og returnere dal1da^{l-1}, så backward()-metoden tar dalda^l-vektoren som parameter. Resten av nødvendig informasjon er allerede lagret i Layer-klassen.

Derivater av aktiveringsfunksjoner

Siden derivater av aktiveringsfunksjoner er nødvendige for bakoverpropagering, bør aktiveringsfunksjoner som ReLU og sigmoid implementeres som klasser i stedet for frittstående funksjoner. Denne strukturen gjør det mulig å definere begge komponentene tydelig:

  1. Selve aktiveringsfunksjonen — implementert med __call__()-metoden, slik at den kan brukes direkte i Layer-klassen med self.activation(z);
  2. Dens derivat — implementert med derivative()-metoden, som gir effektiv beregning under bakoverpropagering via self.activation.derivative(z).

Å representere aktiveringsfunksjoner som objekter gjør det enkelt å sende dem til ulike lag og bruke dem dynamisk under både fremover- og bakoverpropagering.

ReLu

Derivatet av ReLU-aktiveringsfunksjonen er som følger, der ziz_i er et element i vektoren av pre-aktiveringer 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

Derivert av sigmoid aktiveringsfunksjon er som følger:

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)

For begge aktiveringsfunksjonene blir operasjonen brukt på hele vektoren zz, samt på dens derivert. NumPy utfører automatisk beregningen elementvis, noe som betyr at hvert element i vektoren behandles uavhengig.

For eksempel, hvis vektoren zz inneholder tre elementer, beregnes den deriverte slik:

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() er ansvarlig for beregning av gradientene ved hjelp av følgende formler:

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} og zlz^l lagres som henholdsvis inputs og outputs attributter i Layer-klassen. Aktiveringsfunksjonen ff lagres som attributtet activation.

Når alle nødvendige gradienter er beregnet, kan vektene og biasene oppdateres siden de ikke lenger trengs for videre beregning:

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}

Dermed er learning_rate (α\alpha) en annen parameter for denne metoden.

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
Merk

Operatoren * utfører elementvis multiplikasjon, mens funksjonen np.dot() utfører skalarprodukt i NumPy. Attributtet .T transponerer et array.

question mark

Hvilket av følgende beskriver best rollen til backward()-metoden i Layer-klassen under tilbakepropagering?

Select the correct answer

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 2. Kapittel 8
some-alt