Implementering av Backpropagation
Allmän metod
Vid framåtriktad propagiering tar varje lager l utdata från föregående lager, al−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 l endast dal för att beräkna respektive gradienter och returnera dal−1, så metoden backward()
tar vektorn dal 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:
- Själva aktiveringsfunktionen (implementerad via metoden
__call__()
), vilket möjliggör direkt användning i klassenLayer
medself.activation(z)
; - Dess derivata (implementerad via metoden
derivative()
), vilket möjliggör effektiv bakåtriktad propagiering och används i klassenLayer
somself.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 zi är ett element i vektorn av pre-aktiveringar 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
Derivatan av sigmoid-aktiveringsfunktionen är följande:
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)
För båda dessa aktiveringsfunktioner tillämpas de på hela vektorn z, och detsamma gäller för deras derivator. NumPy utför operationen på varje element i vektorn. Till exempel, om vektorn z innehåller 3 element, är deriveringen enligt följande:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)Metoden backward()
Metoden backward()
ansvarar för beräkning av gradienter med hjälp av formlerna nedan:
a^{l-1} och zl lagras som attributen inputs
respektive outputs
i klassen Layer
. Aktiveringsfunktionen f 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:
Wlbl=Wl−α⋅dWl=bl−α⋅dblDärför är learning_rate
(α) 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
*
-operatorn utför elementvis multiplikation, medan funktionen np.dot()
utför skalärprodukt i NumPy. Attributet .T
transponerar en array.
Tack för dina kommentarer!
Fråga AI
Fråga AI
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
Implementering av Backpropagation
Svep för att visa menyn
Allmän metod
Vid framåtriktad propagiering tar varje lager l utdata från föregående lager, al−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 l endast dal för att beräkna respektive gradienter och returnera dal−1, så metoden backward()
tar vektorn dal 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:
- Själva aktiveringsfunktionen (implementerad via metoden
__call__()
), vilket möjliggör direkt användning i klassenLayer
medself.activation(z)
; - Dess derivata (implementerad via metoden
derivative()
), vilket möjliggör effektiv bakåtriktad propagiering och används i klassenLayer
somself.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 zi är ett element i vektorn av pre-aktiveringar 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
Derivatan av sigmoid-aktiveringsfunktionen är följande:
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)
För båda dessa aktiveringsfunktioner tillämpas de på hela vektorn z, och detsamma gäller för deras derivator. NumPy utför operationen på varje element i vektorn. Till exempel, om vektorn z innehåller 3 element, är deriveringen enligt följande:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)Metoden backward()
Metoden backward()
ansvarar för beräkning av gradienter med hjälp av formlerna nedan:
a^{l-1} och zl lagras som attributen inputs
respektive outputs
i klassen Layer
. Aktiveringsfunktionen f 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:
Wlbl=Wl−α⋅dWl=bl−α⋅dblDärför är learning_rate
(α) 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
*
-operatorn utför elementvis multiplikation, medan funktionen np.dot()
utför skalärprodukt i NumPy. Attributet .T
transponerar en array.
Tack för dina kommentarer!