Implementering af Backpropagation
Generel tilgang
Ved fremadpropagering tager hvert lag l outputtet fra det forrige lag, al−1, som input og beregner sit eget output. Derfor tager forward()
-metoden i Layer
-klassen vektoren af forrige output som sin eneste parameter, mens resten af den nødvendige information er gemt i klassen.
Ved tilbagepropagering behøver hvert lag l kun dal for at beregne de respektive gradienter og returnere dal−1, så backward()
-metoden tager dal-vektoren som sin parameter. Resten af den nødvendige information er allerede gemt i Layer
-klassen.
Afledte af aktiveringsfunktioner
Da afledte af aktiveringsfunktioner er nødvendige for tilbagepropagering, bør aktiveringsfunktioner som ReLU og sigmoid struktureres som klasser i stedet for selvstændige funktioner. Dette gør det muligt at definere både:
- Selve aktiveringsfunktionen (implementeret via
__call__()
-metoden), så den kan anvendes direkte iLayer
-klassen ved brug afself.activation(z)
; - Dens afledte (implementeret via
derivative()
-metoden), hvilket muliggør effektiv tilbagepropagering og bruges iLayer
-klassen somself.activation.derivative(z)
.
Ved at strukturere aktiveringsfunktioner som objekter kan de nemt videregives til Layer
-klassen og bruges dynamisk.
ReLu
Den afledte af ReLU-aktiveringsfunktionen er som følger, hvor zi er et element i vektoren af pre-aktiveringer z:
f′(zi)={1,zi>00,zi≤0class ReLU:
def __call__(self, z):
return np.maximum(0, z)
def derivative(self, z):
return (z > 0).astype(float)
Sigmoid
Afledte af sigmoid aktiveringsfunktion er som følger:
f′(zi)=f(zi)⋅(1−f(zi))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 disse aktiveringsfunktioner anvendes de på hele vektoren z, og det samme gælder for deres afledte. NumPy anvender internt operationen på hvert element i vektoren. For eksempel, hvis vektoren z indeholder 3 elementer, er udledningen som følger:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)Metoden backward()
Metoden backward()
er ansvarlig for beregning af gradienterne ved hjælp af formlerne nedenfor:
a^{l-1} og zl gemmes som henholdsvis attributterne inputs
og outputs
i klassen Layer
. Aktiveringsfunktionen f gemmes som attributten activation
.
Når alle nødvendige gradienter er beregnet, kan vægte og biaser opdateres, da de ikke længere er nødvendige for yderligere beregning:
Wlbl=Wl−α⋅dWl=bl−α⋅dblDerfor er learning_rate
(α) en anden parameter for denne metode.
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
Operatoren *
udfører elementvis multiplikation, mens funktionen np.dot()
udfører dot-produkt i NumPy. Attributten .T
transponerer et array.
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat
Awesome!
Completion rate improved to 4
Implementering af Backpropagation
Stryg for at vise menuen
Generel tilgang
Ved fremadpropagering tager hvert lag l outputtet fra det forrige lag, al−1, som input og beregner sit eget output. Derfor tager forward()
-metoden i Layer
-klassen vektoren af forrige output som sin eneste parameter, mens resten af den nødvendige information er gemt i klassen.
Ved tilbagepropagering behøver hvert lag l kun dal for at beregne de respektive gradienter og returnere dal−1, så backward()
-metoden tager dal-vektoren som sin parameter. Resten af den nødvendige information er allerede gemt i Layer
-klassen.
Afledte af aktiveringsfunktioner
Da afledte af aktiveringsfunktioner er nødvendige for tilbagepropagering, bør aktiveringsfunktioner som ReLU og sigmoid struktureres som klasser i stedet for selvstændige funktioner. Dette gør det muligt at definere både:
- Selve aktiveringsfunktionen (implementeret via
__call__()
-metoden), så den kan anvendes direkte iLayer
-klassen ved brug afself.activation(z)
; - Dens afledte (implementeret via
derivative()
-metoden), hvilket muliggør effektiv tilbagepropagering og bruges iLayer
-klassen somself.activation.derivative(z)
.
Ved at strukturere aktiveringsfunktioner som objekter kan de nemt videregives til Layer
-klassen og bruges dynamisk.
ReLu
Den afledte af ReLU-aktiveringsfunktionen er som følger, hvor zi er et element i vektoren af pre-aktiveringer z:
f′(zi)={1,zi>00,zi≤0class ReLU:
def __call__(self, z):
return np.maximum(0, z)
def derivative(self, z):
return (z > 0).astype(float)
Sigmoid
Afledte af sigmoid aktiveringsfunktion er som følger:
f′(zi)=f(zi)⋅(1−f(zi))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 disse aktiveringsfunktioner anvendes de på hele vektoren z, og det samme gælder for deres afledte. NumPy anvender internt operationen på hvert element i vektoren. For eksempel, hvis vektoren z indeholder 3 elementer, er udledningen som følger:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)Metoden backward()
Metoden backward()
er ansvarlig for beregning af gradienterne ved hjælp af formlerne nedenfor:
a^{l-1} og zl gemmes som henholdsvis attributterne inputs
og outputs
i klassen Layer
. Aktiveringsfunktionen f gemmes som attributten activation
.
Når alle nødvendige gradienter er beregnet, kan vægte og biaser opdateres, da de ikke længere er nødvendige for yderligere beregning:
Wlbl=Wl−α⋅dWl=bl−α⋅dblDerfor er learning_rate
(α) en anden parameter for denne metode.
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
Operatoren *
udfører elementvis multiplikation, mens funktionen np.dot()
udfører dot-produkt i NumPy. Attributten .T
transponerer et array.
Tak for dine kommentarer!