Hallo Leute,
Folgendes:
Ich wollte ein Programm schreiben, dass selber lernt ein handschriftliches "X" von einem handschriftlichen "O" zu unterscheiden. Grundidee hierbei war soetwas wie Neuronale Netze zu verwenden. Ich hab also meine Eingänge (4096 Stück (64x64 Pixel) als boolean (schwarz oder weiß)) und dann ein in Ebenen gegliedertes Netz, was letzlich in einem Ausgangs-Neuron mündet.
Jedes Neuron hat dabei einen Eingang für Signale von jedem Neuron aus der Vorgängerebene. Jedes dieser Signale ist an einen Multiplikator gekoppelt, der dem Signal mehr oder weniger Gewicht geben kann. Dann werden also die ganzen Multiplikatoren zusammenaddiert (true => +multi, false => -multi) und wenn ein Grenzwert überschritten wurde, dann sendet das Neuron true weiter, sonst false. Am Ende spuckt also das Ausgangsneuron true (für X) oder false (für O) aus.
Jetzt starte ich mit sagen wir 100 zufällig generierten Netzen. Anschließend teste ich ihre Fähigkeit die Bilder zu unterscheiden. Der Fitnesswert ergibt sich einfach als Summe der gelösten Bilder (und die Nachkommastellen aus der Anzahl der Neuronen, aber der Betrag ist momentan unerheblich). Habe ich alle Fitnesswerte bestimmt, möchte ich die nächste Generation erzeugen. Dafür nehm ich mir je zwei Netze (zufällig, aber keines zwei mal) und übernehme für das neue Netz die Struktur des besseren. Anschließend ergibt sich aus dem Quotient aus der Fitness des schwächeren durch die Fitness des stärkeren eine Wahrscheinlichkeit für eine Mutation (die Struktur bleibt aus Einfachheitsgründen starr, nur die Zahlenwerte wie Multiplikatoren und Grenzwerte mutieren) die dann aus dem Gewichteten Mittel besteht - mit der Fitness zum Quadrat als Gewicht. Zusätzlich kann noch mit einer gaaanz kleinen Wahrscheinlichkeit, zufällig ein Wert mutieren.
Treibe ich das Spiel jetzt mit sagen wir 500 Generationen passiert folgendes:
- Die Anfangsgeneration ist recht symmetrisch um 50% Erfolg verteilt mit einem Spitzenreiter um die 80% i.d.R..
- Mit zunehmender Generations-nummer dünnt die Verteilug aus (was ja denkbar ist, weil immer die bessere Struktur übernomme wird und somit keine so große Vielseitigkeit existiert! Allerdings sind die auftretenden Peaks zufällig und chaotisch.
- Je mehr die Peak ausdünnen, desto schneller testet das Programm die Generationen durch, obwohl ich etwas derartiges nicht implementiert habe! Im Extremen heißt das, sobald nur noch ein Peak da ist, braucht er nur noch 1 Sekunde pro Generation (je nach Anfangseinstellungen) während er für die ersten noch gut 30 Sekunden gebraucht hat.
- Existiert nur noch ein Peak (alle Netze lösen gleich viele Aufgaben), so gibt es zwei deutlich zu erkennende Schwerpunkte um die jede Generation scheinbar zufällig streut (25% ud 70%) (also immer wechselnd, da ja jede Generation nur noch einen Peak aufweist).
Folgende Fragen stell ich mir deshalb:
- Wie muss ich die Netze mutieren lassen, damit ich halbwegs konvergentes Verhalten gegen einen Wert von über 50% habe (vorzugsweise über 90% ^^)?
- Ist Java tatsächlich so genial zu erkennen, dass irgendwann nur noch eine Struktur vorliegt, sodass mein Programm deshalb auf einmal so schnell arbeitet, oder muss ein Programm-Fehler vorliegen?
- Wenn alle Netze die gleiche Struktur haben und deshalb alle Fragen gleich beantworten, wie kann es dann sein, dass wenn ich einzelne mutiere, trotzdem alle Netze immer noch die gleiche Anzahl an Fragen beantworten, die aber deutlich von der vorigen Generation abweicht!
Vielen Dank für Tipps und Hinweise
P.S.: Ich verwende momentan 20 X und 20 O Bilder.