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. Resterande nödvändig information finns redan lagrad i klassen Layer.
Derivator av aktiveringsfunktioner
Eftersom derivator av aktiveringsfunktioner krävs för bakåtriktad propagiering bör aktiveringsfunktioner som ReLU och sigmoid implementeras som klasser istället för fristående funktioner. Denna struktur gör det möjligt att tydligt definiera 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 propagiering 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 propagiering.
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 sigmoidaktiveringsfunktionen ä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)backward()-metoden
Metoden backward() ansvarar för beräkning av gradienterna 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
Can you explain how the backward() method uses the stored attributes in the Layer class?
What is the purpose of the derivative() method in the activation function classes?
Could you provide an example of how forward and backward propagation work together in a simple neural network?
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. Resterande nödvändig information finns redan lagrad i klassen Layer.
Derivator av aktiveringsfunktioner
Eftersom derivator av aktiveringsfunktioner krävs för bakåtriktad propagiering bör aktiveringsfunktioner som ReLU och sigmoid implementeras som klasser istället för fristående funktioner. Denna struktur gör det möjligt att tydligt definiera 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 propagiering 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 propagiering.
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 sigmoidaktiveringsfunktionen ä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)backward()-metoden
Metoden backward() ansvarar för beräkning av gradienterna 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!