Neuronales Netz, entwickelt sich wie es will

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

  • Verständnisfragen:
    Was meinst du mit "Struktur"? (Die Anzahl der versteckten Ebenen? Die Anzahl der Neuronen?)
    Was meinst du mit "gleich viele Aufgaben [lösen]"?

    Die Beschreibung deiner Vorgehensweise lässt mich zumindest einem Fehler im Ansatz vermuten. Ohne den Code zu kennen, klingt es für mich so, als ob du die richtige Netzwerkkonfiguration haben möchtest, aber nicht wirklich an der Lösung des Problems interessiert bist. Es wäre mE sinnvoller, die Konvergenzrate fixer Strukturen zu testen und dann die am schnellsten konvergierende Struktur auszuwählen.

  • Verständnisfragen:
    Was meinst du mit "Struktur"? (Die Anzahl der versteckten Ebenen? Die Anzahl der Neuronen?)

    Also mein Vorgehen ist ja so, dass ich zwei Netze vergleiche, das stärkere (mehr gelöste Aufgaben) nehme und dann mit einer gewissen Zufälligkeit, die vom Verhältnis der Stärken abhängt, einzelne Werte mutiere.
    Das heißt, dass irgendwann natürlich alle Netze die gleiche Anzahl Ebenen und Neuronen hat. Das meinte ich mit Struktur. Denn es wundert mich, dass das testen der Netze immer schneller geht, je weniger unterschiedliche Strukturen (anzahl Ebenen und Neuronen) ich habe. Obwohl die Anzahl an Operationen die für jede Generation durchgeführt werden müssen immer gleich ist! (Logisch da: Gleich viele Netze pro Generation, für jedes Netz stumpfer Algorithmus, der das Ausgangssignal ausgibt).


    Verständnisfragen:
    Was meinst du mit "gleich viele Aufgaben [lösen]"?

    Ich habe 40 Bilder: 20 X-Bilder und 20 O-Bilder. Jedes Netzt bekommt diese Bilder gegeben und soll mir sagen ob es ein X oder ein O ist. Heißt also 40 "Aufgaben". Gelöst ist die Aufgabe natürlich, wenn das Bild richtig interpretiert wurde. Die Fitness ergibt sich dann also durch: #(richtig erkannt)/#(gesamt).



    Es wäre mE sinnvoller, die Konvergenzrate fixer Strukturen zu testen und dann die am schnellsten konvergierende Struktur auszuwählen.

    Das Problem ist, dass bei mir nicht mal fixe Strukturen konvergieren. Durch die zufällige Permutation wird das Ergebnis jedesmal wieder beliebig schlecht oder gut (obwohl ich nur gaaaaanz wenig zufällig permutiere).
    Und die Idee war natürlich auch, dass sich die bessere Struktur bei den ersten paar Generationen durchsetzt und ich dann automatisch mit einer halbwegs brauchbaren arbeite. Es setzt sich zwar eine Struktur durch, jedesmal wenn ich das Programm starte (siehe vorigen Post von mir). Das Problem ist nur, dass danach eben nichts mehr konvergiert und sich alles äußerst für mich unerklärlich verhält (siehe vorigen Post).

    Ich gebe zu ohne Code ist hier wohl nur raten möglich, aber ich muss mal gucken ob ich den Code soweit zusammenschneiden kann, dass jemand überhaupt Lust hat da reinzuschauen ^^.

  • Das heißt, dass irgendwann natürlich alle Netze die gleiche Anzahl Ebenen und Neuronen hat. Das meinte ich mit Struktur. Denn es wundert mich, dass das testen der Netze immer schneller geht, je weniger unterschiedliche Strukturen (anzahl Ebenen und Neuronen) ich habe. Obwohl die Anzahl an Operationen die für jede Generation durchgeführt werden müssen immer gleich ist! (Logisch da: Gleich viele Netze pro Generation, für jedes Netz stumpfer Algorithmus, der das Ausgangssignal ausgibt).

    Also das ist leicht erklärt: Wenn du ein Netz mit 4096 Inputneuronen und 2 Output Neuronen hast, dann kommt es natürlich drauf an, wie die Struktur in der Mitte ausschaut, wenn du dich über die Laufzeit wunderst. -> Die Strukturen sollten am Ende alle gleich sein, ja, aber hast du geschaut, wie die Struktur ausschaut (wieviele Ebenen / Neuronen, da versteckt drin sind)? Da ist es sehr gut möglich, dass dein Netz so "intelligent" ist und kleinere Netze bevorzugt (weil die Wahrscheinlichkeit, ob eine Änderung gut oder schlecht ist, ja auch von der Größe abhängen kann).

    Das Problem ist, dass bei mir nicht mal fixe Strukturen konvergieren. Durch die zufällige Permutation wird das Ergebnis jedesmal wieder beliebig schlecht oder gut (obwohl ich nur gaaaaanz wenig zufällig permutiere).


    Naja, wenn du eine fixe Struktur hast und eine Population von 100 Netzen, die bessere Hälfte überleben lässt, die andere Hälfte durch Fortpflanzung jeweils 2 der besseren neu durch mischt, dann noch eine kleine Mutationsrate hast, wo du aber doch das ganze Netz neuinitialisierst (mit Random-Werten). Dann sollte es auch irgendwann auf eine bessere Lösung konvergieren. (Zumindest würde ich mir das erwarten. Mit den gewählten Parametern kann man sich natürlich ewig rumspielen. Dafür braucht man bei solchen genetischen Algorithmen fast nichts wissen.)

    Und die Idee war natürlich auch, dass sich die bessere Struktur bei den ersten paar Generationen durchsetzt und ich dann automatisch mit einer halbwegs brauchbaren arbeite. Es setzt sich zwar eine Struktur durch, jedesmal wenn ich das Programm starte (siehe vorigen Post von mir). Das Problem ist nur, dass danach eben nichts mehr konvergiert und sich alles äußerst für mich unerklärlich verhält (siehe vorigen Post).


    Naja, aber du weißt ja nicht, ob sich die durchgesetzte Struktur überhaupt eignet, das Problem noch zu lösen. Möglicherweise kann es dann auch nicht mehr durch einen Wechsel der Fortpflanzungsstrategie trainiert werden.


  • Naja, wenn du eine fixe Struktur hast und eine Population von 100 Netzen, die bessere Hälfte überleben lässt, die andere Hälfte durch Fortpflanzung jeweils 2 der besseren neu durch mischt, dann noch eine kleine Mutationsrate hast, wo du aber doch das ganze Netz neuinitialisierst (mit Random-Werten). Dann sollte es auch irgendwann auf eine bessere Lösung konvergieren. (Zumindest würde ich mir das erwarten. Mit den gewählten Parametern kann man sich natürlich ewig rumspielen. Dafür braucht man bei solchen genetischen Algorithmen fast nichts wissen.)

    Hmm, ich werde es weiter probieren ^^. Also jetzt erst mal fixe Struktur ok.



    Naja, aber du weißt ja nicht, ob sich die durchgesetzte Struktur überhaupt eignet, das Problem noch zu lösen. Möglicherweise kann es dann auch nicht mehr durch einen Wechsel der Fortpflanzungsstrategie trainiert werden.

    Da hast du recht. Ich gehe wie s.o. vor.


    Danke schonmal

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!