- jakezhaojb
- github.com
- Fragen von Neueinsteigern zu MQL4 und MQL5, Hilfe und Diskussion über Algorithmen und Codes
- [Archiv!] Jede Anfängerfrage, um das Forum nicht zu überladen. Fachleute, gehen Sie nicht daran vorbei. Könnte nirgendwo ohne dich hingehen - 2.
- [ARCHIV!] Alle Fragen von Anfängern, um das Forum nicht zu überladen. Fachleute, gehen Sie nicht vorbei. Ohne dich kann ich nirgendwo hingehen - 4.
int layers = 6; // Hiddenlayers inkl Outputlayer int times = 1000; // 1000 durchläufe des Trainings int datanum = Arraysize(x_data); // was bisher existent ist: (Y(=Label), aNet(=aktivierter Neuronenwert), W[j][i][l] (=Gewichte), Neuronenarray[l] (=enthällt die anzahl an Neuronen für den jedweiligen Layer l) // Nomenklatur (bei mir in der regel -> j = Sendeneuron, i = empfängerneuron, l = Layer) //... alle neuen Arrays deklarieren Z_delta[][...][...]; // wird größer als nötig deklariert und später resized deltaW[][...][...]; double error=0, sumtemp=0, errtemp=0; double alpha, beta; // Keine ahnung warum der mustercode 2 learningrates hatte // Training while(loop < times) { loop++; error = 0.0; for(m=0; m<datanum ; m++){ // amount of samples // Feedforward { for (int l=0; l<layers;l++) { for(i=0; i<Neuronenarray[l]; i++) { if (l+1==layers): { sumtemp = 0.0; for(j=0; j<Neuronenarray[l-1]; j++) { sumtemp += W[j][i][l] * aNet[j][l]; // uncertain? } aNet[i][l] = sigmoid(sumtemp); } else: { sumtemp = 0.0; for(j=0; j<Neuronenarray[l-1]; j++) { sumtemp += W[j][i][l] * aNet[j][l]; // uncertain? } aNet[i][l] = sigmoid(sumtemp); // sigmoid serves as the activation function } } } // Backpropagation for (int l = layers; layers>0;l--) { for(i=0; i<Neuronenarray[l]; i++) { if (l+1==layers): { errtemp = y[i] - aNet[i][l]; Z_delta[i][l] = -errtemp * (1.0 + aNet[i][l]) * (1.0 - aNet[i][l]); error += errtemp * errtemp; //errorfunktion } else { errtemp = 0.0; for(j=0; j<NeuronenArray[l+1]; j++) //für jedes Outputneuron den outputerror mit gewicht multiplpizieren und dazu summieren { errtemp += Z_delta[j][l+1] * W[i][j][l]; Z_delta[i][l] = errtemp * (1.0 + aNet[i][l]) * (1.0 - aNet[i][l]); // NeuronError * Deactivation } } } } // Stochastic gradient descent for (int l = layers; layers>0;l--) { for(i=0; i<Neuronenarray[l]; i++) { if(l== Outputlayer) for(j=0; j<Neuronenarray[l-1]; j++){ // für jedes seiner Inputneuronen deltaW[j][i][l] = alpha * deltaW[j][i][l] + beta * Z_delta[i][l] * aNet[j]; // das deltaWeight berechnen W[j][i][l] -= deltaW[j][i][l]; else deltaW[j][i][l] = alpha * deltaW[j][i][l] + beta * Z_delta[i][l] * aNet[j]; W[j][i][l] -= deltaW[j][i][l]; } } } } } // Global error error = error / 2; if(loop%1000==0){ result = "Global Error = "; sprintf(buffer, "%f", error); result += buffer; result += "\r\n"; } if(error < errlimit) break; printf("The %d th training, error: %f\n", loop, error); }
Ich bitte auf Antworten die kurz thematisieren wo im netzwerk etwas falsch läuft
https://github.com/davidalbertonogueira/MLP
Lesen ...verstehen...konvertieren nach MQL5.
- davidalbertonogueira
- github.com
einfach mal stichpunktartig, was mir so auffällt:
- zu "layers=6": kann man im finetuning machen wenn das Netzwerk funktioniert, doch für erste Tests würde ich die Zahl der Layers runtersetzen mit nur 1-2 hidden layers; die Ergebnisse werden ohnehin selten merklich besser durch viele Layers, doch Du hast eine größere Wahrscheinlichkeit von NaN-Errrors
- Initialisierung der Gewichte nicht vergessen (i.d.R. Zufallszahl zwischen 0 und 1, siehe der Beispielcode);
- der Beispielcode mit fix(!) nur 1 hidden layer ist für den Verallgemeinerungsfall nicht sonderlich gut geeignet (meine Meinung), da sich dadurch dass das hidden layer zu sowohl input als auch output eine direkte Verbindung hat, ein paar Besonderheiten ergeben
- was der Kerl da mit alpha und beta macht, verstehe ich auch nicht; verschiedene learning rates sind allerdings durchaus üblich; das Problem zu großer learning rates (sofern sie noch unter der exploding-gradient-Schwelle liegen) ist, dass zwar schnell ein Minimum erreicht wird, jedoch bei späteren Iterationen die Genauigkeit sinkt; der globale Error wird also zu einem leicht höheren Wert konvergieren; was man also gut machen kann ist eine Funktion für eine dynamische learning rate: am Anfang etwas höher; das ist zwar nicht das, was der da mit alpha und beta macht, doch Du kannst z.B. ein alpha definieren und ein dynamisch kleiner werdendes "addon" abhängig von der Zahl der bereits erfolgten Iterationen draufschlagen
- was ist bei Dir Z_delta?
- warum die while-Schleife statt for (int loop=0;loop<times;loop++)? macht letztlich ja das Gleiche und kannst Du so lassen, ist halt nur eine ungewöhnliche Angewohnheit; while-Schleifen sollte man nur einsetzen wo unbedingt nötig wg. infinite-loop-Gefahr; ist in diesem Beispiel zwar nicht vorhanden, doch wenn Du es Dir so angewöhnst, werden des Öfteren Fehler kommen, wo Du nicht verstehst, weshalb sich das Programm aufhängt
- zur Nomenklatur: wenn Du irgendwo im Internet über neuronale Netze liest, wirst Du feststellen, dass zu 99% die Buchstaben, die näher am Anfang des Alphabets stehen, für Layer weiter "links", also näher im Input-Layer, verwendet werden. In allgemeinen Artikeln zum Thema backpropagation, chain rule und delta rule (siehe z.B. Wikipedia) ist meist j ein Neuron im aktuellen Bezugslayer und i steht dann weiter links bzw. k weiter rechts. Die Buchstaben können auch anders gewählt sein, doch die Richtung ist zu 99% so. Wenn Du also i und j verdrehst, bringt Dich das unnötig durcheinander, wenn Du nach allgemeinen Informationen suchst (kann man so machen, der Code wird funktionieren, trotzdem eine unnötige Irritation)
- mit l+1==layers meinst Du wahrscheinlich l==layers-1? das soll das letzte hidden layer vor dem output layer sein, oder? warum unterscheidest Du da? was ist anders als bei den anderen hidden layers? [edit: in der backpropagation macht die Unterscheidung Sinn, s.u., im Forward-feed ist das unnötig]
- forward-feed: für ein Neuron j ERST [Summe aller (Neuronen i * weight_ij)] = Net_in[j] bilden und DANACH erst die Aktivierungsfunktion auf das Ergebnis anwenden; während der Summation hat die Aktivierungsfunktion dort noch nichts zu suchen (= Dein "uncertain")
- backpropagation: der Beispielcode hat da ein paar Probleme, die für den Verallgemeinerungsfall so nicht funktionieren werden; daher hier einfache Zusammenfassung, wie es definitiv funktioniert (vielleicht haben ja auch andere was davon, die ebenfalls mit dem Thema experimentieren, daher mache ich mir hier die Arbeit, denn ich wäre damals froh über praktische Infos gewesen); ganz wichtig ist hier die Reihenfolge! ERST alle errors/hidden errors berechnenen und erst DANACH der Update der Gewichte, denn die Gewichte müssen unbedingt noch im Ursprungszustand bleiben, welcher zu dem jeweiligen globalen Fehler geführt hat, solange bis alle hidden errrors ermittelt sind; in der Praxis:
- globaler Error: global_error=0; for (int j=0;j<outputs;j++){global_error+=0.5*pow(label[i]-OUT[j],2);} // das ist nichts anderes als die berühmte "squared error" Funktion, welche wir minimieren wollen; der Faktor 0.5 vorweg dient nur der einfacheren Ableitung, denn f'(x^2)=2x und f'(0.5x^2) ist dann schlicht und einfach x
- OUT_err[j]=OUT[j]-label[j]
- hidden error Hidden_err[l][j]: for (int j=1;i<neurons(j);j++) { Hidden_err[l][j]=0; for (int k=0;k<neurons[k];k++){Hidden_err[l][j]+=OUT_err[k]*Weight[l][j][k]; }} // l ist hier das Layer, für das gerade der hidden error berechnet wird
- Wiederholung des letzten Schritts für alle hidden layers (also "l")
- DANACH der Update der Gewichte mittels delta rule: delta_w= -(learnrate) * g(Net_in[i]) * g'(Net_in[j]) * Hidden_err[l][j];
- "g" steht hier für die Aktivierungsfunktion
- g(Net_in[i]) kennen wir bereits aus dem forward-feed: es ist ja nichts anderes als die Aktivierungsfunktion angewandt auf die Summe der gewichteten Eingänge am Neuron i; dies wiederum ist ja exakt das Output des Neurons i bzw. das was Du bei Dir aNet nennst
- g'(Net_in[j]) ist die ABLEITUNG der Aktivierungsfunktion angewandt auf die Summe der gewichteten Eingänge am Neuron j; letzteren Wert kennen wir ebenfalls noch aus dem forward-feed
- für das Update der Gewichte zwischen letztem Hidden Layer und dem Output layer haben wir natürlich keinen "hidden error", sondern nur den Error des Output layers selbst; hier kann man in der delta rule also den OUT_err[j] anstelle von Hn_err[j] einsetzen
- Zeit für das Update der Gewichte: Weight(n)[i][j]+=delta_w
einfach mal stichpunktartig, was mir so auffällt:
- zu "layers=6": kann man im finetuning machen wenn das Netzwerk funktioniert, doch für erste Tests würde ich die Zahl der Layers runtersetzen mit nur 1-2 hidden layers; die Ergebnisse werden ohnehin selten merklich besser durch viele Layers, doch Du hast eine größere Wahrscheinlichkeit von NaN-Errrors
- Initialisierung der Gewichte nicht vergessen (i.d.R. Zufallszahl zwischen 0 und 1, siehe der Beispielcode);
- der Beispielcode mit fix(!) nur 1 hidden layer ist für den Verallgemeinerungsfall nicht sonderlich gut geeignet (meine Meinung), da sich dadurch dass das hidden layer zu sowohl input als auch output eine direkte Verbindung hat, ein paar Besonderheiten ergeben
- was der Kerl da mit alpha und beta macht, verstehe ich auch nicht; verschiedene learning rates sind allerdings durchaus üblich; das Problem zu großer learning rates (sofern sie noch unter der exploding-gradient-Schwelle liegen) ist, dass zwar schnell ein Minimum erreicht wird, jedoch bei späteren Iterationen die Genauigkeit sinkt; der globale Error wird also zu einem leicht höheren Wert konvergieren; was man also gut machen kann ist eine Funktion für eine dynamische learning rate: am Anfang etwas höher; das ist zwar nicht das, was der da mit alpha und beta macht, doch Du kannst z.B. ein alpha definieren und ein dynamisch kleiner werdendes "addon" abhängig von der Zahl der bereits erfolgten Iterationen draufschlagen
- was ist bei Dir Z_delta?
- warum die while-Schleife statt for (int loop=0;loop<times;loop++)? macht letztlich ja das Gleiche und kannst Du so lassen, ist halt nur eine ungewöhnliche Angewohnheit; while-Schleifen sollte man nur einsetzen wo unbedingt nötig wg. infinite-loop-Gefahr; ist in diesem Beispiel zwar nicht vorhanden, doch wenn Du es Dir so angewöhnst, werden des Öfteren Fehler kommen, wo Du nicht verstehst, weshalb sich das Programm aufhängt
- zur Nomenklatur: wenn Du irgendwo im Internet über neuronale Netze liest, wirst Du feststellen, dass zu 99% die Buchstaben, die näher am Anfang des Alphabets stehen, für Layer weiter "links", also näher im Input-Layer, verwendet werden. In allgemeinen Artikeln zum Thema backpropagation, chain rule und delta rule (siehe z.B. Wikipedia) ist meist j ein Neuron im aktuellen Bezugslayer und i steht dann weiter links bzw. k weiter rechts. Die Buchstaben können auch anders gewählt sein, doch die Richtung ist zu 99% so. Wenn Du also i und j verdrehst, bringt Dich das unnötig durcheinander, wenn Du nach allgemeinen Informationen suchst (kann man so machen, der Code wird funktionieren, trotzdem eine unnötige Irritation)
- mit l+1==layers meinst Du wahrscheinlich l==layers-1? das soll das letzte hidden layer vor dem output layer sein, oder? warum unterscheidest Du da? was ist anders als bei den anderen hidden layers? [edit: in der backpropagation macht die Unterscheidung Sinn, s.u., im Forward-feed ist das unnötig]
- forward-feed: für ein Neuron j ERST [Summe aller (Neuronen i * weight_ij)] = Net_in[j] bilden und DANACH erst die Aktivierungsfunktion auf das Ergebnis anwenden; während der Summation hat die Aktivierungsfunktion dort noch nichts zu suchen (= Dein "uncertain")
- backpropagation: der Beispielcode hat da ein paar Probleme, die für den Verallgemeinerungsfall so nicht funktionieren werden; daher hier einfache Zusammenfassung, wie es definitiv funktioniert (vielleicht haben ja auch andere was davon, die ebenfalls mit dem Thema experimentieren, daher mache ich mir hier die Arbeit, denn ich wäre damals froh über praktische Infos gewesen); ganz wichtig ist hier die Reihenfolge! ERST alle errors/hidden errors berechnenen und erst DANACH der Update der Gewichte, denn die Gewichte müssen unbedingt noch im Ursprungszustand bleiben, welcher zu dem jeweiligen globalen Fehler geführt hat, solange bis alle hidden errrors ermittelt sind; in der Praxis:
- globaler Error: global_error=0; for (int j=0;j<outputs;j++){global_error+=0.5*pow(label[i]-OUT[j],2);} // das ist nichts anderes als die berühmte "squared error" Funktion, welche wir minimieren wollen; der Faktor 0.5 vorweg dient nur der einfacheren Ableitung, denn f'(x^2)=2x und f'(0.5x^2) ist dann schlicht und einfach x
- OUT_err[j]=OUT[j]-label[j]
- hidden error Hidden_err[l][j]: for (int j=1;i<neurons(j);j++) { Hidden_err[l][j]=0; for (int k=0;k<neurons[k];k++){Hidden_err[l][j]+=OUT_err[k]*Weight[l][j][k]; }} // l ist hier das Layer, für das gerade der hidden error berechnet wird
- Wiederholung des letzten Schritts für alle hidden layers (also "l")
- DANACH der Update der Gewichte mittels delta rule: delta_w= -(learnrate) * g(Net_in[i]) * g'(Net_in[j]) * Hidden_err[l][j];
- "g" steht hier für die Aktivierungsfunktion
- g(Net_in[i]) kennen wir bereits aus dem forward-feed: es ist ja nichts anderes als die Aktivierungsfunktion angewandt auf die Summe der gewichteten Eingänge am Neuron i; dies wiederum ist ja exakt das Output des Neurons i bzw. das was Du bei Dir aNet nennst
- g'(Net_in[j]) ist die ABLEITUNG der Aktivierungsfunktion angewandt auf die Summe der gewichteten Eingänge am Neuron j; letzteren Wert kennen wir ebenfalls noch aus dem forward-feed
- für das Update der Gewichte zwischen letztem Hidden Layer und dem Output layer haben wir natürlich keinen "hidden error", sondern nur den Error des Output layers selbst; hier kann man in der delta rule also den OUT_err[j] anstelle von Hn_err[j] einsetzen
- Zeit für das Update der Gewichte: Weight(n)[i][j]+=delta_w
- Initialisierung der Gewichte wirklich nur zwischen 0 & 1 oder auch evtl negative oder größere Werte? (z.B. bei nur tanh?)
- Z_ delta habe ich einfach aus der Nomenklatur von Anrew Ng übernommen & dürfte mit dem Error eines einzelnen Neurons übereinstimmen, da es sich aus Zielwert- Output ergibt.
- bei "uncertein war ich mir unsicher ob ich das richtige Neuron mit aNet[j][l] erwischt hatte (lag aber an der vertauschung von i & j -> bei rückvertauschung wäre Sendeneuron i wäre richtig ) aktivierungsfunktion wird ja erst darunter angewendet.
Ja, Du hast Recht mit den Gewichten, die können ruhig auch negativ initialisiert werden; Zufallswerte zwischen -1 und +1 wären auch ok. Einen großen Unterschied wird es allerdings nicht machen, denn die Gewichte können auch von alleine nach den ersten Iterationen (also dann, wenn der Fehler noch besonders groß ist) schnell negativ werden, falls größere negative Delta_w vorliegen. Es gibt bei "1" auch keine strenge Grenze, die Werte sollten nur in einem ähnlichen Bereich verteilt sein und in einer ähnlichen Größenordnung wie die Bias-Initialisierung. Die Details macht das Netzwerk dann von alleine.
Wundere Dich übrigens nicht, wenn Du leicht unterschiedliche Formeln findest; das liegt meist daran, was als Cost Function gewählt wurde. Die Squared-Error-Methode ist mathematisch sicherlich am einfachsten weil sie sich so leicht ableiten lässt.
Ich kann nur sagen, dass es so wie ich es mache jedenfalls funktioniert, wie ich z.B. anhand des genannten Binärzahlen-Decoders beweisen/prüfen konnte; da habe ich dann einfach 16 Inputs gewählt und mit 1 oder 0 gefüttert um eine zufällige Binärzahl zwischen 0 und 2^15 zu simulieren und als Label die zugehörige Dezimalzahl ("normalisiert" per Division durch 2^15 genommen). Schon nach wenigen Sekunden war das Netz trainiert genug um (nach Denormalisierung) die korrekte zugehörige Dezimalzahl selbst auszurechnen / auszuspucken. So ein simples System ist sehr nützlich um zu experimentieren, was versch. Aktivierungsfunktionen, learning rates und Netzwerkarchitekturen (Layerzahl, Neuronen pro Layer) für Auswirkungen haben. Mit Börsendaten kann man solche Tests nicht machen weil man nicht weiß, wie "korrekt" das Label ist bzw. welche Rolle Zufall spielt.
einfach mal stichpunktartig, was mir so auffällt:
- zu "layers=6": kann man im finetuning machen wenn das Netzwerk funktioniert, doch für erste Tests würde ich die Zahl der Layers runtersetzen mit nur 1-2 hidden layers; die Ergebnisse werden ohnehin selten merklich besser durch viele Layers, doch Du hast eine größere Wahrscheinlichkeit von NaN-Errrors
- Initialisierung der Gewichte nicht vergessen (i.d.R. Zufallszahl zwischen 0 und 1, siehe der Beispielcode);
- der Beispielcode mit fix(!) nur 1 hidden layer ist für den Verallgemeinerungsfall nicht sonderlich gut geeignet (meine Meinung), da sich dadurch dass das hidden layer zu sowohl input als auch output eine direkte Verbindung hat, ein paar Besonderheiten ergeben
- was der Kerl da mit alpha und beta macht, verstehe ich auch nicht; verschiedene learning rates sind allerdings durchaus üblich; das Problem zu großer learning rates (sofern sie noch unter der exploding-gradient-Schwelle liegen) ist, dass zwar schnell ein Minimum erreicht wird, jedoch bei späteren Iterationen die Genauigkeit sinkt; der globale Error wird also zu einem leicht höheren Wert konvergieren; was man also gut machen kann ist eine Funktion für eine dynamische learning rate: am Anfang etwas höher; das ist zwar nicht das, was der da mit alpha und beta macht, doch Du kannst z.B. ein alpha definieren und ein dynamisch kleiner werdendes "addon" abhängig von der Zahl der bereits erfolgten Iterationen draufschlagen
- was ist bei Dir Z_delta?
- warum die while-Schleife statt for (int loop=0;loop<times;loop++)? macht letztlich ja das Gleiche und kannst Du so lassen, ist halt nur eine ungewöhnliche Angewohnheit; while-Schleifen sollte man nur einsetzen wo unbedingt nötig wg. infinite-loop-Gefahr; ist in diesem Beispiel zwar nicht vorhanden, doch wenn Du es Dir so angewöhnst, werden des Öfteren Fehler kommen, wo Du nicht verstehst, weshalb sich das Programm aufhängt
- zur Nomenklatur: wenn Du irgendwo im Internet über neuronale Netze liest, wirst Du feststellen, dass zu 99% die Buchstaben, die näher am Anfang des Alphabets stehen, für Layer weiter "links", also näher im Input-Layer, verwendet werden. In allgemeinen Artikeln zum Thema backpropagation, chain rule und delta rule (siehe z.B. Wikipedia) ist meist j ein Neuron im aktuellen Bezugslayer und i steht dann weiter links bzw. k weiter rechts. Die Buchstaben können auch anders gewählt sein, doch die Richtung ist zu 99% so. Wenn Du also i und j verdrehst, bringt Dich das unnötig durcheinander, wenn Du nach allgemeinen Informationen suchst (kann man so machen, der Code wird funktionieren, trotzdem eine unnötige Irritation)
- mit l+1==layers meinst Du wahrscheinlich l==layers-1? das soll das letzte hidden layer vor dem output layer sein, oder? warum unterscheidest Du da? was ist anders als bei den anderen hidden layers? [edit: in der backpropagation macht die Unterscheidung Sinn, s.u., im Forward-feed ist das unnötig]
- forward-feed: für ein Neuron j ERST [Summe aller (Neuronen i * weight_ij)] = Net_in[j] bilden und DANACH erst die Aktivierungsfunktion auf das Ergebnis anwenden; während der Summation hat die Aktivierungsfunktion dort noch nichts zu suchen (= Dein "uncertain")
- backpropagation: der Beispielcode hat da ein paar Probleme, die für den Verallgemeinerungsfall so nicht funktionieren werden; daher hier einfache Zusammenfassung, wie es definitiv funktioniert (vielleicht haben ja auch andere was davon, die ebenfalls mit dem Thema experimentieren, daher mache ich mir hier die Arbeit, denn ich wäre damals froh über praktische Infos gewesen); ganz wichtig ist hier die Reihenfolge! ERST alle errors/hidden errors berechnenen und erst DANACH der Update der Gewichte, denn die Gewichte müssen unbedingt noch im Ursprungszustand bleiben, welcher zu dem jeweiligen globalen Fehler geführt hat, solange bis alle hidden errrors ermittelt sind; in der Praxis:
- globaler Error: global_error=0; for (int j=0;j<outputs;j++){global_error+=0.5*pow(label[i]-OUT[j],2);} // das ist nichts anderes als die berühmte "squared error" Funktion, welche wir minimieren wollen; der Faktor 0.5 vorweg dient nur der einfacheren Ableitung, denn f'(x^2)=2x und f'(0.5x^2) ist dann schlicht und einfach x
- OUT_err[j]=OUT[j]-label[j]
- hidden error Hidden_err[l][j]: for (int j=1;i<neurons(j);j++) { Hidden_err[l][j]=0; for (int k=0;k<neurons[k];k++){Hidden_err[l][j]+=OUT_err[k]*Weight[l][j][k]; }} // l ist hier das Layer, für das gerade der hidden error berechnet wird
- Wiederholung des letzten Schritts für alle hidden layers (also "l")
- DANACH der Update der Gewichte mittels delta rule: delta_w= -(learnrate) * g(Net_in[i]) * g'(Net_in[j]) * Hidden_err[l][j];
- "g" steht hier für die Aktivierungsfunktion
- g(Net_in[i]) kennen wir bereits aus dem forward-feed: es ist ja nichts anderes als die Aktivierungsfunktion angewandt auf die Summe der gewichteten Eingänge am Neuron i; dies wiederum ist ja exakt das Output des Neurons i bzw. das was Du bei Dir aNet nennst
- g'(Net_in[j]) ist die ABLEITUNG der Aktivierungsfunktion angewandt auf die Summe der gewichteten Eingänge am Neuron j; letzteren Wert kennen wir ebenfalls noch aus dem forward-feed
- für das Update der Gewichte zwischen letztem Hidden Layer und dem Output layer haben wir natürlich keinen "hidden error", sondern nur den Error des Output layers selbst; hier kann man in der delta rule also den OUT_err[j] anstelle von Hn_err[j] einsetzen
- Zeit für das Update der Gewichte: Weight(n)[i][j]+=delta_w
Habe die Reihenfolge dann mal in code zusammengefasst:
for (t==;t<times;t++) { for (d=datanum; d>0;d--) { globaler Error: global_error=0; for (int j=0;j<Neuronenarray[layers];j++) { global_error +=0.5 * pow(label[d]-aNet[j][outputlayer] , 2); } //wann (vor oder nach dem GewichtUpdate) berechnen wir den global error ? //XXX1 // Im feedforward wird einfach eine Net Matrix deklariert (ohne aktivierungsfunktion also nicht aNet) (zur vereinfachung) double E[][...][...]; // deklarierung einer ErrorMatrix die genauso groß ist wie Net oder aNet, mit ausßahme des ersten Layers bei aNet(==die X_Inputs des Netzes) E[][...][0] bleibt dann einfach immer null (& existiert nur zur vereinfachung der iteration) for (l=layers; l>1;l--) //l>1 weil über alle hiddenlayers iteriert wird, nicht aber über l==0, wobei es sich (in Net[][][]) um den InputLayer handelt { OUT_err[j][l] = OUT[j][l]-label[j] if (l==layers-1) // Befüllung der Erromatrix { E[j][l]=OUT_err[j][l]; } //hidden error Hidden_err[l][j] & Befüllung der Errormatrix for (int j=1;i<neurons(j);j++) // ich gehe davon aus das das i in "i<neurons(j)" ein simpler tippfehler war und normal auch j wäre, stimmts? //XXX2 { Hidden_err[l][j]=0; // l ist hier das Layer, für das gerade der hidden error berechnet wird for (int k=0;k<neurons[k];k++) { //XXX3 Hidden_err[l][j] += OUT_err[k]*Weight[l][j][k]; // Ist Weight [l][j][k] das gewicht, das die Neuronen aus dem Layer davor mit dem Jetzigen verbindet (ja oder nein)? // ich schätze nein, da k alphabetisch nach j kommt, was ist dann "neurons[k]"? // habe die samplenummern (z.B Y[i]) zu d umgeschrieben, weil es mit "datanum" einfacher zu merken ist, //demnach wären dann doch i die Sendeneuronen (statt j) aus dem layer davor, j eigentlich die empfängerneuronen im jetzigen layer (statt k) // und k bräuchten wir nicht oder? und statt Out_err, dann einfach E[j][l+1] } } } //Wiederholung des letzten Schritts für alle hidden layers (also "l") //DANACH das Update der Gewichte mittels delta rule: for (welcher layer zuerst, Fängt man von hinten an oder von vorne?) //XXX4 EDIT: Nets sind ja bereits berechnet worden, sofern ich //XXX3 richtig deute, könnte man die beiden layer loops { // zusammelegen, sofern pro layer iteration immernur das weight des darauffolgenden layers [l+1] geupdatet wird. // da diese ja eigentlich nicht mehr angetastet wird. macht das sinn? for (j=0; Neuronenarray[l];j++) //Empfängerneuron j { for(i=0; Neuronenarray[l-1]) //Sendeneuron i { if (l==layers-1) { //delta_w[i][j][l-1] = -(learnrate) * g(Net_in[i][l-1]) * g'(Net_in[j][l]) * Hidden_err[j][l]; delta_w[i][j][l-1]= -(learnrate) * aNet[i][l-1] * g'(Net[j][l]) * Output_err[j][l]; // aNet= Net ohne aktivierungsfunktion } else { //delta_w= -(learnrate) * g(Net_in[i]) * g'(Net_in[j]) * Hidden_err[l][j]; delta_w[i][j][l-1]= -(learnrate) * aNet[i][l-1] * g'(Net[j][l]) * Hidden_err[j][l]; // mit E Matrix wäre es für alle layer: // delta_w[i][j][l-1]= -(learnrate) * aNet[i][l-1] * g'(Net[j][l]) * E[j][l]; } Weight(n)[i][j][l-1] += delta_w[i][j][l-1]; } } } } }
habe die wenigen vier stellen die noch nicht ganz klar waren mit "//XXX" gekennzeichnet, weil ich sofern diese richtig gelöst sind, sehen könnte ob man die beiden for loops über die layer nicht noch zusammenfassen könnte (Nets sind ja bereits berechnet worden)
desweiteren könnte ich anschließend schauen wie ich die softmax funktion darein intergrieren kann ( wäre ja dann das gleiche oder? (funktioniert backpropagation mit der ableitung einer softamx funktion oder muss man mit dem Net statt dem aNet wert der Outputneuronen arbeiten? würde dann einfach die jeweiligen Outputneuronenergebnisse an die stellen des labelvektors anpassen z.B. [0,0,1,0] sodass sich die ersten 2 Outputneuronen und das letze dem nullwert nähern müssen und der dritte in diesem Beispiel erhöhrt werden müsse))
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.