Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Takaisinkytkennän Toteutus | Neuroverkon Rakentaminen Alusta Alkaen
Johdatus neuroverkkoihin

bookTakaisinkytkennän Toteutus

Yleinen lähestymistapa

Eteenpäin suuntautuvassa laskennassa jokainen kerros ll ottaa edellisen kerroksen tuottamat arvot, al1a^{l-1}, syötteenä ja laskee omat lähtöarvonsa. Tämän vuoksi forward()-luokan Layer-metodi ottaa edellisen kerroksen lähtövektorin ainoana parametrinaan, kun taas muu tarvittava tieto säilytetään luokan sisällä.

Takaisinlevityksessä jokainen kerros ll tarvitsee vain dalda^l laskeakseen vastaavat gradientit ja palauttaakseen dal1da^{l-1}, joten backward()-metodi ottaa dalda^l-vektorin parametrinaan. Loput tarvittavat tiedot ovat jo tallennettuina Layer-luokkaan.

Aktivointifunktioiden derivaatat

Koska aktivointifunktioiden derivaattoja tarvitaan takaisinlevityksessä, aktivointifunktiot kuten ReLU ja sigmoid tulisi toteuttaa luokkina erillisten funktioiden sijaan. Tämä mahdollistaa sekä:

  1. Varsinaisen aktivointifunktion (toteutettu __call__()-metodilla), jolloin sitä voidaan käyttää suoraan Layer-luokassa muodossa self.activation(z);
  2. Sen derivaatan (toteutettu derivative()-metodilla), mikä mahdollistaa tehokkaan takaisinlevityksen ja käytetään Layer-luokassa muodossa self.activation.derivative(z).

Rakentamalla aktivointifunktiot olioiksi ne voidaan helposti välittää Layer-luokalle ja käyttää dynaamisesti.

ReLU

ReLU-aktivointifunktion derivaatta on seuraava, missä ziz_i on esiaaktivaatioiden vektorin zz alkio:

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

Sigmoid-aktivointifunktion derivaatta on seuraava:

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)

Molempia näitä aktivointifunktioita sovelletaan koko vektoriin zz, samoin niiden derivaattoja. NumPy suorittaa operaation automaattisesti jokaiselle vektorin alkiolle. Esimerkiksi, jos vektori zz sisältää 3 alkiota, derivointi tapahtuu seuraavasti:

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}

backward()-metodi

backward()-metodi vastaa gradienttien laskemisesta alla olevien kaavojen mukaisesti:

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} ja zlz^l tallennetaan inputs- ja outputs-attribuutteihin Layer-luokassa. Aktivointifunktio ff tallennetaan activation-attribuuttiin.

Kun kaikki tarvittavat gradientit on laskettu, painot ja biasit voidaan päivittää, koska niitä ei enää tarvita jatkolaskentaan:

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}

Täten learning_rate (α\alpha) on toinen tämän metodin parametri.

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
Huomio

Operaattori * suorittaa alkiokohtaisen kertolaskun, kun taas funktio np.dot() suorittaa pistetulon NumPyssa. Attribuutti .T transponoi taulukon.

question mark

Mikä seuraavista kuvaa parhaiten backward()-metodin roolia Layer-luokassa takaisinkytkennän aikana?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 8

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

Suggested prompts:

Can you explain how the backward() method uses the stored attributes in the Layer class?

What is the purpose of the activation function's derivative in backpropagation?

Could you provide an example of how to use these activation function classes in a neural network layer?

Awesome!

Completion rate improved to 4

bookTakaisinkytkennän Toteutus

Pyyhkäise näyttääksesi valikon

Yleinen lähestymistapa

Eteenpäin suuntautuvassa laskennassa jokainen kerros ll ottaa edellisen kerroksen tuottamat arvot, al1a^{l-1}, syötteenä ja laskee omat lähtöarvonsa. Tämän vuoksi forward()-luokan Layer-metodi ottaa edellisen kerroksen lähtövektorin ainoana parametrinaan, kun taas muu tarvittava tieto säilytetään luokan sisällä.

Takaisinlevityksessä jokainen kerros ll tarvitsee vain dalda^l laskeakseen vastaavat gradientit ja palauttaakseen dal1da^{l-1}, joten backward()-metodi ottaa dalda^l-vektorin parametrinaan. Loput tarvittavat tiedot ovat jo tallennettuina Layer-luokkaan.

Aktivointifunktioiden derivaatat

Koska aktivointifunktioiden derivaattoja tarvitaan takaisinlevityksessä, aktivointifunktiot kuten ReLU ja sigmoid tulisi toteuttaa luokkina erillisten funktioiden sijaan. Tämä mahdollistaa sekä:

  1. Varsinaisen aktivointifunktion (toteutettu __call__()-metodilla), jolloin sitä voidaan käyttää suoraan Layer-luokassa muodossa self.activation(z);
  2. Sen derivaatan (toteutettu derivative()-metodilla), mikä mahdollistaa tehokkaan takaisinlevityksen ja käytetään Layer-luokassa muodossa self.activation.derivative(z).

Rakentamalla aktivointifunktiot olioiksi ne voidaan helposti välittää Layer-luokalle ja käyttää dynaamisesti.

ReLU

ReLU-aktivointifunktion derivaatta on seuraava, missä ziz_i on esiaaktivaatioiden vektorin zz alkio:

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

Sigmoid-aktivointifunktion derivaatta on seuraava:

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)

Molempia näitä aktivointifunktioita sovelletaan koko vektoriin zz, samoin niiden derivaattoja. NumPy suorittaa operaation automaattisesti jokaiselle vektorin alkiolle. Esimerkiksi, jos vektori zz sisältää 3 alkiota, derivointi tapahtuu seuraavasti:

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}

backward()-metodi

backward()-metodi vastaa gradienttien laskemisesta alla olevien kaavojen mukaisesti:

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} ja zlz^l tallennetaan inputs- ja outputs-attribuutteihin Layer-luokassa. Aktivointifunktio ff tallennetaan activation-attribuuttiin.

Kun kaikki tarvittavat gradientit on laskettu, painot ja biasit voidaan päivittää, koska niitä ei enää tarvita jatkolaskentaan:

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}

Täten learning_rate (α\alpha) on toinen tämän metodin parametri.

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
Huomio

Operaattori * suorittaa alkiokohtaisen kertolaskun, kun taas funktio np.dot() suorittaa pistetulon NumPyssa. Attribuutti .T transponoi taulukon.

question mark

Mikä seuraavista kuvaa parhaiten backward()-metodin roolia Layer-luokassa takaisinkytkennän aikana?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 8
some-alt