Backpropagation fehler finden

ZuseZ3

Lt. Commander
Registriert
Jan. 2014
Beiträge
1.659
Ich habe mal aus Neugier angefangen ein Neuronales Netz komplett von Hand zu implementieren, statt immer nur auf die bekannten Bibliotheken zurückzugreifen. Wie sich gezeigt hat war das notwendig, ich bin nämlich gerade zu unfähig den Fehler bei meinem Backprop Ansatz zu verstehen. Letzten Endes lernt mein Netz nach ca 60 Trainingsbeispielen jeder Klasse konstant die gleiche Wahrscheinlichkeit zuzuordnen, unabhängig vom Input. :freak::D
Gewichtsänderung sind danach durchschnittlich in der Größe 10-e32...

Netzaufbau:
Input layer (Fully connected) : 32x32-> 40
Hidden layer (Fully connected): 40->10
Softmax layer: 10 -> 10

Jedes Layer ist als eigene Instanz implementiert und hat eine inference Methode die das Bild bzw. entstehendes Array annimmt.
Dabei speichert es den input x, den aufsummierten input net( net_j = b_j + Sum w_ij * x_i ), sowie den output.
Der output o_j ist (1/(1+exp(-net_j)) für die FC layer und (exp(net_j) / exp(sum net) für das softmax Layer.

Zusätzlich besitzt jedes Layer eine train Methode, welche in umgekehrter Reihenfolge aufgerufen wird.
Das Softmax layer nimmt beim training einen one-hot Vektor entgegen, gibt selbst nen feedback Vector ans FC Layer zurück, welches daraus die gewichte+biase anpasst und einen eigenen feedback vector ans input Layer zurück reicht.

Dabei ist mein Problem, dass die Verarbeitung im Hidden Layer fehlerhaft ist.
Mein Softmax Layer gibt, auch nach den 60 Trainingsbeispielen, konstant einen sinnvollen Feedback Vector zurück (9*x, 1*y, one-hot)
Mein Hidden Layer gibt nach den 60 Trainingsbeispielen sehr langsam fallend 40*0,02x als Feedback Vector an das input Layer, welches natürlich nix lernt. (0,02 * 0,001 * abc => 0).
Gleichzeitig steigt der output von meinem Hidden Layer richtung 1 (0,97x)

Daher nun zu meiner Implementierung. Reminder, ich nutze im letzten Layer softmax und CEerror
softmax.train(targetVector):
Result = float(10)
for i = 1..10:
Result = output - targetVector
return Result


hidden.train(backpropVec):
Result = float(40)
//calculate feedback for prev Layer
for i = 1...40
for j = 1...10
Result += backpropVec[j] * w[j] * (output[j] * (1-output[j]))
// update weights
for i = 1...40
for j = 1...10
w[j] += input * backpropVec[j] * learningRate;
// update biase
for j = 1...10
bias[j] += 1 * backpropVec[j] * learningRate;



Hier noch mein input Layer, auch wenn ich erstmal nen fehler im hidden Layer vermute:

input.train(backpropVec):
// update bias
for i = 1...32*32
for j = 1...40
weights[j] += input * feedback[j]* learningRate
// update bias
for j = 1..40
bias[j] += 1* backpropVec[j] * learningRate;

Ein paar Gedanken:
1) Die unterscheidung ob Gewichte addiert oder subtrahiert werden erfolgt ja nach der Berechnung im letzten layer, bei mir sollte es + sein.
2) Abgesehen von der Mathematischen Herleitung müsste das Bias ja 1 * backpropVec[j] * learningRate sein, da es quasi an einem daueraktiven Neuron hängt.

3) Mir ist bekannt, dass ich nicht alle (Richtungs) ableitungen explizit berechnet habe,allerdings kürzt sich da ja eh sehr viel raus. Daher erschien es mir einfacher dies soweit sinvoll zusammenzufassen.
4) Alle gewichte werden random im bereich [0,0.1] und alle biase mit 0.5 initialisiert.
5) lerning Rate wurde mit verschiedenen Werten getestet, meist 0.001

Wenn mir jemand einen Hinweis geben könnte, wäre ich sehr verbunden.
 
Zuletzt bearbeitet:
Hab ich auch schon mal mit "nur" NumPy gemacht vor Jahren.

ZuseZ3 schrieb:
1) Die unterscheidung ob Gewichte addiert oder subtrahiert werden erfolgt ja nach der Berechnung im letzten layer, bei mir sollte es + sein.
Das verstehe ich nicht ganz. Man nimmt doch einfach nur die Ableitung der Kostenfunktion und im Layer davor aktualisiert man die Parameter mit
W = W - α * dW b = b - α * db

Hast du mal mit einem Minimalbeispiel und "Zettel/Stift" einfach durchgerechnet? Ist doch mehr oder weniger trivial dann den Fehler zu finden.
 
  • Gefällt mir
Reaktionen: ZuseZ3
Theoretisch sollte es trivial sein, praktisch habe ich jetzt nur für dieses Problem schon 10h+ investiert -.-
Ein Fehler war ein Bias in dem softmax layer, welches ich vergessen hatte und nicht geupdated wurde.
Ich habe ihn entfernt, nun läuft das Netz nicht mehr so hart auf einen festen output zu.

Ich bekomme aber immer noch kein vernünftigen output, dh. mal zur Sicherheit die konkrete Rechnung:

Sei w[j] die Verbindung von input i zu neuron j.
Der output jedes Fully Connected Layers mit n Neuronen ist:

o[ j ] = 1 / (1 + exp ( - net[ j ])) wobei net[ j ] = b [ j ] + SUM(w[ i ][ j ] * x[ i ])

Der output meines Softmax layers lautet:
o[ j ] = exp( x[ j ]) / (sum_i exp( x[I]))

Nach dem durchlaufen gibt das softmax Layer folgenden Vektor zurück:
return[ j ] = o[ j ] - t[ j ]

Wenn wir jetzt mal nur das Layer direkt vor dem Softmax layer betrachten:
b[ j ] = b[ j ] - return [ j ] * 1 * learnrate
w[ j ] = w[ j ] - return [ j ] * input [ i ] * learnrate

Ich habe auch einiges anderes rumprobiert, aber bin noch zu keinem Ergebnis gekommen.
Liege ich zumindest bis hier richtig @abcddcba ?
[/I]
 
Hast Du zufaellig Deinen Code auf GitHub oder Aehnlichem, dass man sich ihn Mal anschauen koennte um den Fehler zu finden?
 
Habe dir ne PN geschickt, danke schonmal.
 
Update, hab es selbst gelöst bekommen.
Mein Fehler war in erster Linie, dass ich schon öfter die implementierung von Softmax als einzelnem Layer gesehen hatte. Damit dachte ich, dass ich es auch ohne vorgeschaltetes Fully Connected laufen würde.
Praktisch hatte ich dadurch aber softmax(sigmoid(net_j)), was natürlich nicht das selbe war wie eine verkettung von softmax(net_j) mit sigmoid(net_j). Da ich mich aber bei den Ableitungen zu sehr an den theoriebeispielen orientiert habe, ging das natürlich schief.

Was die für mich besten Seiten waren um zu verstehen, wie ich das ganze gut implementieren kann waren diese beiden: diese (sehr simpel gehalten) und diese hier (mit schöner herleitung und sogar einer trainingsiteration zum abgleichen der eigenen Ergebnisse).
 
Zuletzt bearbeitet:
Zurück
Oben