Implementering av Backpropagation
Allmän metod
Vid framåtriktad spridning 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 spridning 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. 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:
- Själva aktiveringsfunktionen — implementerad med metoden
__call__(), så att den kan tillämpas direkt i klassenLayermedself.activation(z); - Dess derivata — implementerad med metoden
derivative(), vilket möjliggör effektiv beräkning under bakåtriktad spridning viaself.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 zi är ett element i vektorn av preaktiveringar 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 aktiveringsfunktionerna tillämpas operationen på hela vektorn z, 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 z innehåller tre element, beräknas derivatan som:
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 vikterna och biaserna uppdateras eftersom de inte längre behövs för vidare beräkningar:
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 spridning 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 spridning 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. 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:
- Själva aktiveringsfunktionen — implementerad med metoden
__call__(), så att den kan tillämpas direkt i klassenLayermedself.activation(z); - Dess derivata — implementerad med metoden
derivative(), vilket möjliggör effektiv beräkning under bakåtriktad spridning viaself.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 zi är ett element i vektorn av preaktiveringar 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 aktiveringsfunktionerna tillämpas operationen på hela vektorn z, 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 z innehåller tre element, beräknas derivatan som:
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 vikterna och biaserna uppdateras eftersom de inte längre behövs för vidare beräkningar:
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!