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.
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.
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: