Gradienten für Bias-Terme in der Backpropagation

13

Ich habe versucht, ein neuronales Netzwerk von Grund auf neu zu implementieren, um die Mathematik dahinter zu verstehen. Mein Problem hängt vollständig mit der Rückausbreitung zusammen, wenn wir eine Ableitung in Bezug auf die Verzerrung vornehmen, und ich habe alle Gleichungen abgeleitet, die bei der Rückausbreitung verwendet werden. Jetzt stimmt jede Gleichung mit dem Code für das neuronale Netzwerk überein, mit Ausnahme der Ableitung in Bezug auf Verzerrungen.

z1=x.dot(theta1)+b1

h1=1/(1+np.exp(-z1))
z2=h1.dot(theta2)+b2
h2=1/(1+np.exp(-z2))

dh2=h2-y
#back prop

dz2=dh2*(1-dh2)
H1=np.transpose(h1)
dw2=np.dot(H1,dz2)
db2=np.sum(dz2,axis=0,keepdims=True)

Ich habe online nach dem Code gesucht und möchte wissen, warum wir die Matrix addieren und dann der Skalar db2=np.sum(dz2,axis=0,keepdims=True)von der ursprünglichen Verzerrung subtrahiert wird, warum nicht die Matrix als Ganzes subtrahiert wird. Kann mir jemand helfen, etwas Intuition dahinter zu geben. Wenn ich eine partielle Ableitung des Verlusts in Bezug auf die Vorspannung nehme, gibt es mir nur einen oberen Gradienten, der dz2 ist, weil z2=h1.dot(theta2)+b2h1 und Theta 0 und b2 1 sind. Der obere Term bleibt also übrig.

b2+=-alpha*db2
user34042
quelle

Antworten:

6

Der Bias-Term ist sehr einfach, weshalb Sie ihn oft nicht berechnet sehen. Eigentlich

db2 = dz2

Ihre Aktualisierungsregeln für die Verzerrung eines einzelnen Elements lauten also:

b2 += -alpha * dz2

und

b1 += -alpha * dz1

In Bezug auf die Mathematik, wenn Ihr Verlust ist und Sie für ein gegebenes Neuron das den Bias-Term . . .JJziibi

Jbi=Jzizibi

und

zibi=1

weilzi=(something unaffected by bi)+bi


Es sieht so aus, als ob der von Ihnen kopierte Code das Formular verwendet

db2=np.sum(dz2,axis=0,keepdims=True)

weil das Netzwerk für die Verarbeitung von Beispielen in (Mini-) Stapeln ausgelegt ist und Sie daher Gradienten für mehr als ein Beispiel gleichzeitig berechnen lassen. Die Summe drückt die Ergebnisse auf ein einziges Update. Dies wäre einfacher zu bestätigen, wenn Sie auch den Aktualisierungscode für Gewichte anzeigen würden.

Neil Slater
quelle
Ja, genau das waren meine Gedanken, denn so sieht es mathematisch aus. Aber der Code, den ich gesehen habe, hat die Matrix zusammengefasst und dann zum b1 hinzugefügt.
user34042
theta1=theta1-alpha*dw1 theta2=theta2-alpha*dw2 Ich verstehe es immer noch nicht. Auf diese Weise wird allen verschiedenen Begriffen im 'b'-Vektor derselbe Begriff hinzugefügt, der sonst für jeden einzelnen Begriff unterschiedliche Gewichte gehabt hätte. Dies würde einen signifikanten Unterschied für das neuronale Netzwerk bedeuten, um Minima zu erreichen.
user34042
@ user34042: Etwas scheint mir nicht richtig zu sein - könnten Sie die Quelle verknüpfen, von der Sie diesen Code erhalten haben? Ich frage mich, ob die Quelle es falsch verstanden hat, weil sie Mini-Batch-Code mit einfachem Online-Gradientenabstieg gemischt und abgeglichen hat.
Neil Slater
Ich denke, die Quelle hat es falsch. Der NN arbeitet immer noch mit allen gleichen Bias-Werten, sodass sie es möglicherweise nicht bemerkt haben. Und wie bereits erwähnt, können Sie diesen Code tatsächlich in einem stapelbasierten Szenario verwenden, sodass es sich möglicherweise nur um einen Fehler beim Ausschneiden und Einfügen handelt.
Neil Slater
10

Ich möchte die Bedeutung von erklären, db2=np.sum(dz2,axis=0,keepdims=True)da es mich auch einmal verwirrt hat und nicht beantwortet wurde.

Die Ableitung von L(Verlust) wrt bist die vorgelagerte Ableitung multipliziert mit der lokalen Ableitung :

Lb=LZZb

Wenn wir mehrere Stichproben haben Zund Lbeide Matrizen sind. b ist immer noch ein Vektor.

Die lokale Ableitung ist einfach ein Vektor von Einsen :

Zb=bW×X+b=1

Das heißt, unsere vollständige Ableitung ist eine Matrixmultiplikation, die wie folgt aussieht (z. B. 2 Abtastwerte mit 3 Ausgängen) :

LZ×1=[......][111]

Beachten Sie, dass dies die Summe der Zeilen ist .

Und da db2=np.sum(dz2, axis=0, keepdims=True)kommt es her. Es ist einfach eine Abkürzung für die Matrixmultiplikation der lokalen und der vorgelagerten Ableitungen.

oezguensi
quelle
0

Zunächst müssen Sie Ihre Formel für den Gradienten der Sigmoidfunktion korrigieren.

Die erste Ableitung der Sigmoidfunktion ist: (1−σ(x))σ(x)

Ihre Formel für dz2 lautet: dz2 = (1-h2)*h2 * dh2

Sie müssen die Ausgabe der Sigmoid-Funktion σ(x)nicht für den Gradienten verwenden.

Sie müssen den Gradienten für die Vorspannung summieren, da dieser Gradient von vielen einzelnen Eingaben stammt (Anzahl der Eingaben = Stapelgröße). Daher müssen wir sie akkumulieren, um die Verzerrungen von Schicht 2 zu aktualisieren. Da die Gradienten jedoch zu Schicht 1 kommen, müssen Sie den gesamten Gradienten für die Aktualisierung der Verzerrungen und Gewichte in Schicht 1 summieren, da sie von vielen Knoten von Schicht 2 stammen Dieser Fall unterscheidet sich von der Summe der Verzerrungen in Schicht 2.

Mein Gerät für zwei vollständig verbundene Schichten mit den Aktivierungsfunktionen sind Sigmoidfunktionen:

lr = 1e-3
f = lambda x: 1.0/(1.0 + np.exp(-x))
# pass through layer 1
out_l1 = np.dot(x, W_1) + b_1

out_s1 = f(out_l1)

# pass through layer 2
out_l2 = np.dot(x, W_2) + b_2

out_s2 = f(out_l2)

loss = get_loss(out_s2, y)

# BACKWARD PASS
grad = out_s2 - y

d_h2 = (1 - out_s2) * out_s2 * grad

# Accumulate the gradient come from all examples
d_W2 = out_s1.T.dot(d_h2)
d_b2 = np.sum(d_h2, axis=0, keepdims=True)

# sum of gradient come out from prev node:
grad_1 = np.sum(d_W2.T, axis=0, keepdims=True)
d_h1 = (1 - out_l1) * out_l1 * grad_1

d_W1 = x.T.dot(d_h1)
d_b1 = np.sum(d_h1, axis=0, keepdims=True)

W_1 -= d_W1 * lr
b_1 -= d_b1 * lr

W_2 -= d_W2 * lr
b_2 -= d_b2 * lr
biendltb
quelle