Jump to content






Photo
* * * * * 1 votes

Neuronales Netz: Die Implementierung Teil2

Posted by Mythos , 18. August 2012 · 969 views

nn ki
Es hat (leider) etwas länger gedauert als erwartet, aber jetzt steht mal die erste Version.

Ausgeführt wie gesagt als eine Library. Folgende Probleme (und Lösungen) sind während der Implementierung aufgetreten:

Transferfunktionen
Ich kann leider nicht beliebige Transferfunktionen zulassen, Grund ist genaugenommen nur die "Beschränktheit" von MQL. Mit OO könnte man eine Abstrakte "Transferfunction" Klasse machen und dem NN pro neuron ein solches Objekt übergeben. Aber is halt nicht. Also gibt es derzeit 3 mögliche Funktionen: Linear, sigmoid und heavy side.
Welches Neuron welche Funktion verwendet wird bei der Initialisierung durch ein Array von IDs festgelegt (Linear hat ID 0, Sigmoid 1, HeavySide 2). Damit keine verwechslungen aufkommen, hab ich die Definition dieser IDs über Prekompilerkonstanten in ein eigenes mqh gelöst.
Je nachdem welche TransferId das Neuron hat, verhält sich nun also die Funktion zur Berechnung des Neuron-Outputs entsprechend anders.

MT und die Arrays
In MQL gibt es ja bekanntlich Arrays, und man kann mit ArrayResize auch zur Laufzeit beliebig die Größe des Arrays ändern. Das gilt in der Form aber leider nur für eindimensionale Arrays.
Für ein NN benötigt man aber auch 2 und 3 dimensionale Arrays. Und da ich nicht ein konkretes NN mit fixer Anzahl an Layern und Neuronen bauen will, muss auch die Größe der verschiedenen Dimensionen dynamisch sein.

Also musste ein workaround her. Sieht im konkreten Fall so aus, das ich alles eindimensionale Arrays habe und die mehrdimensionalität mit der Indizierung "simuliere".
realesArray[0] entspricht theoretischesArray[0][0][0]
realesArray[1] entspricht theoretischesArray[0][0][1]
Schwierig wirds jetzt zusätzlich weil die Dimensionen nicht nur variabel in der Größe sind, sondern natürlich komplett unterschiedlich sind. Nehmen wir als Beispiel das "zweidimensionale" Array welches die Transferfunction-Id pro neuron speichert.
Theoretisch ist das Array so aufgebaut:
transferId[layer][neuron]
gibt es jetzt 5 Neuronen am Eingangslayer, 3 am layer1 und 2 am Layer2, dann ist
transferId[0][1]= realesArray[1]
transferId[1][1]= realesArray[5+1];
transferId[1][2]= realesArray[5+2];
transferId[2][0]= realesArray[5+3+0];
Ich muss mir hier also merken wieviele Neuronen es bis zum LayerX gibt, um dann für LayerX den richtigen Offset im Array zu wissen.
Diese Info hab ich wiederum in ein Array gespeichert (simple, eindimensional ;)  das für jeden Layer genau diesen Offset speichert.

Noch eine Ebene komplizierter wirds dann bei den Gewichten, die eigentlich 3-dimensional sind. Hier arbeite ich wieder mit solchen gespeicherten Offsets. wobei ich mir speichere wieviele Gewichtswerte es bis zu LayerX gibt (wieder in einem Array) und dann im LayerX einfach nach dem fixen 2D prinzip gehe. Hier funktioniert es, da innerhalb eines Layers alle 2. Dimensionen gleiche Länge haben, da ja jeder Konten auf dem Layer gleichviele Outputknoten hat (Anzahl Knoten vom nächsten Layer).

Biases
Jedes Neuron in einem NN hat ja einerseits die inputs, aber zusätzlich noch einen Schwellwert oder Bias der zur gewichteten Summe dazugezählt wird. Ich habs einfach so implementiert das es ein weiteres Array gibt das sämtliche Biases beinhaltet, analog zum Array mit den Ids der Transferfunktionen.

Speichern und Laden
Die nächste Herausforderung war die Speicherung eines NN (also die Anzahl der Layer, Neuronen pro Layer, TransferId und Bias pro Neuron sowie alle Gewichte zwischen den Neuronen). Da ich die Gewichte grundsätzlich auch händisch/extern anaylisieren will, hab ich mich für csv entschieden, obwohl binär natürlich schneller und effizienter wäre.
MQL hat ja an sich recht nette Filezugriffsmöglichkeiten, aber der Schreibbefehl für csv nimmt zwar eine beliebig lange liste an werten, aber macht immer eine newline. wenn man also zur compilezeit noch nicht weiß wieviele werte das werden und über eine Schleife schreiben will, kann man nur entweder die gesamte line selber als string bauen oder jeden wert in eine eigene Zeile schreiben. Ich hab mich für zweiteres entschieden. Dadurch is das file zwar recht lang, aber mei, die Anzahl der Zeichen ist gleich ;)

Weitere Herausforderungen gabs dann noch beim Einbau des Lernalgorithmus, aber dazu mehr nachdem ich den in einem anderen Eintrag erklärt hab ;)

  • 3



September 2022

M T W T F S S
   1234
567891011
12131415161718
19202122232425
26 27 282930  

Recent Comments

Recent Entries

1 user(s) viewing

0 members, 1 guests, 0 anonymous users

Categories

Latest Visitors

  • Photo
    eurix
    14. Apr 2017 - 21:50 Uhr
  • Photo
    chimbonda
    03. Jul 2016 - 11:49 Uhr
  • Photo
    tompaul
    21. May 2016 - 16:37 Uhr
  • Photo
    fatlemming
    24. Jan 2016 - 17:41 Uhr
  • Photo
    compulsorytrading
    11. Dec 2014 - 09:33 Uhr