Implementierung der Backpropagation
Allgemeiner Ansatz
Bei der Vorwärtspropagation nimmt jede Schicht l die Ausgaben der vorherigen Schicht, al−1, als Eingaben und berechnet ihre eigenen Ausgaben. Daher nimmt die Methode forward()
der Klasse Layer
den Vektor der vorherigen Ausgaben als einzigen Parameter, während die restlichen benötigten Informationen innerhalb der Klasse gespeichert werden.
Bei der Rückwärtspropagation benötigt jede Schicht l nur dal, um die jeweiligen Gradienten zu berechnen und dal−1 zurückzugeben. Die Methode backward()
nimmt daher den Vektor dal als Parameter. Die übrigen erforderlichen Informationen sind bereits in der Klasse Layer
gespeichert.
Ableitungen von Aktivierungsfunktionen
Da für die Rückwärtspropagation Ableitungen von Aktivierungsfunktionen benötigt werden, sollten Aktivierungsfunktionen wie ReLU und Sigmoid als Klassen und nicht als eigenständige Funktionen strukturiert werden. Dadurch können wir sowohl:
- Die Aktivierungsfunktion selbst (implementiert über die Methode
__call__()
), sodass sie direkt in der KlasseLayer
mitself.activation(z)
angewendet werden kann; - Ihre Ableitung (implementiert über die Methode
derivative()
), was eine effiziente Rückwärtspropagation ermöglicht und in der KlasseLayer
alsself.activation.derivative(z)
verwendet wird.
Durch die Strukturierung von Aktivierungsfunktionen als Objekte können wir sie einfach an die Klasse Layer
übergeben und dynamisch verwenden.
ReLU
Die Ableitung der ReLU-Aktivierungsfunktion ist wie folgt, wobei zi ein Element des Vektors der Voraktivierungen z ist:
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
Die Ableitung der Sigmoid-Aktivierungsfunktion ist wie folgt:
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 beide dieser Aktivierungsfunktionen wenden wir sie auf den gesamten Vektor z an, ebenso wie deren Ableitungen. NumPy führt die Operation intern für jedes Element des Vektors aus. Wenn zum Beispiel der Vektor z 3 Elemente enthält, ergibt sich die Ableitung wie folgt:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)Die backward()-Methode
Die Methode backward()
ist zuständig für die Berechnung der Gradienten anhand der folgenden Formeln:
a^{l-1} und zl werden in der Klasse inputs
als die Attribute outputs
bzw. Layer
gespeichert. Die Aktivierungsfunktion f wird als Attribut activation
gespeichert.
Sobald alle erforderlichen Gradienten berechnet wurden, können Gewichte und Biases aktualisiert werden, da sie für weitere Berechnungen nicht mehr benötigt werden:
Wlbl=Wl−α⋅dWl=bl−α⋅dblDaher ist learning_rate
(α) ein weiterer Parameter dieser Methode.
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
Der Operator *
führt eine elementweise Multiplikation durch, während die Funktion np.dot()
das Skalarprodukt in NumPy berechnet. Das Attribut .T
transponiert ein Array.
Danke für Ihr Feedback!
Fragen Sie AI
Fragen Sie AI
Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen
Awesome!
Completion rate improved to 4
Implementierung der Backpropagation
Swipe um das Menü anzuzeigen
Allgemeiner Ansatz
Bei der Vorwärtspropagation nimmt jede Schicht l die Ausgaben der vorherigen Schicht, al−1, als Eingaben und berechnet ihre eigenen Ausgaben. Daher nimmt die Methode forward()
der Klasse Layer
den Vektor der vorherigen Ausgaben als einzigen Parameter, während die restlichen benötigten Informationen innerhalb der Klasse gespeichert werden.
Bei der Rückwärtspropagation benötigt jede Schicht l nur dal, um die jeweiligen Gradienten zu berechnen und dal−1 zurückzugeben. Die Methode backward()
nimmt daher den Vektor dal als Parameter. Die übrigen erforderlichen Informationen sind bereits in der Klasse Layer
gespeichert.
Ableitungen von Aktivierungsfunktionen
Da für die Rückwärtspropagation Ableitungen von Aktivierungsfunktionen benötigt werden, sollten Aktivierungsfunktionen wie ReLU und Sigmoid als Klassen und nicht als eigenständige Funktionen strukturiert werden. Dadurch können wir sowohl:
- Die Aktivierungsfunktion selbst (implementiert über die Methode
__call__()
), sodass sie direkt in der KlasseLayer
mitself.activation(z)
angewendet werden kann; - Ihre Ableitung (implementiert über die Methode
derivative()
), was eine effiziente Rückwärtspropagation ermöglicht und in der KlasseLayer
alsself.activation.derivative(z)
verwendet wird.
Durch die Strukturierung von Aktivierungsfunktionen als Objekte können wir sie einfach an die Klasse Layer
übergeben und dynamisch verwenden.
ReLU
Die Ableitung der ReLU-Aktivierungsfunktion ist wie folgt, wobei zi ein Element des Vektors der Voraktivierungen z ist:
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
Die Ableitung der Sigmoid-Aktivierungsfunktion ist wie folgt:
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 beide dieser Aktivierungsfunktionen wenden wir sie auf den gesamten Vektor z an, ebenso wie deren Ableitungen. NumPy führt die Operation intern für jedes Element des Vektors aus. Wenn zum Beispiel der Vektor z 3 Elemente enthält, ergibt sich die Ableitung wie folgt:
f′(z)=f′(z1z2z3)=f′(z1)f′(z2)f′(z3)Die backward()-Methode
Die Methode backward()
ist zuständig für die Berechnung der Gradienten anhand der folgenden Formeln:
a^{l-1} und zl werden in der Klasse inputs
als die Attribute outputs
bzw. Layer
gespeichert. Die Aktivierungsfunktion f wird als Attribut activation
gespeichert.
Sobald alle erforderlichen Gradienten berechnet wurden, können Gewichte und Biases aktualisiert werden, da sie für weitere Berechnungen nicht mehr benötigt werden:
Wlbl=Wl−α⋅dWl=bl−α⋅dblDaher ist learning_rate
(α) ein weiterer Parameter dieser Methode.
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
Der Operator *
führt eine elementweise Multiplikation durch, während die Funktion np.dot()
das Skalarprodukt in NumPy berechnet. Das Attribut .T
transponiert ein Array.
Danke für Ihr Feedback!