Die Macht der Cluster

Letztens einen Artikel vom Spiegel gelesen, über Mieten von einem Cluster. Mich hat schon immer mal der Gedanke umgetrieben, dass meine Trainingsalgorithmen von NNSpace einfach viel zu langsam auf einem einzelnen Computer laufen. Es gibt ja auch viele andere Sachen, die man eigentlich gerne auf die Computer im ganzen Haus verteilen würde, zugegeben das geht nicht mit Allem aber ich denke das was Amazon hier zum Beispiel anbietet ist schon eine Richtung, die in Zukunft auch genutzt werden wird. So weit denk ich aber noch gar nicht, mir gehts vielmehr um das Prinzip. Es wäre doch mal interessant zu Testen ob man fähig ist so eine Clusterstruktur aufzubauen, jetzt mal ohne Amazon und 1000 Prozessoren, sondern einfach nur mit 2 oder 3 Computern im eigenen Haus. Letztendlich ist dann der Schritt (falls man das Aufteilen der Arbeit in 1000 Teile vorher schon erledigt hat) nicht mehr so groß zum Rechenzentrum. Es geht ja vielmehr um die Fähigkeit der Anwendung überhaupt auf irgend so einem System zu laufen.

  1. Ich glaube wir haben dabei erst mal zwei Typen von Teilnehmern, ich nenne sie jetzt mal Distributor(davon gibts einen) und Calculator(davon kann es unendlich viele geben). Das heißt jetzt nicht unbedingt, dass nicht auch mehrere solcher Typen auf derselben Maschine laufen können, aber wir brauchen irgendwie eine Instanz(Distributor), die Befehle vom Benutzer annimmt und die dann auf die Arbeitspferde(Calculator) verteilt.
  2. Dann ist noch ein Format nötig über das sich Distributor und Calculator unterhalten. Dabei denk ich jetzt nicht an irgendein Protokoll oder oder Ähnliches, das ist Implementierung und gehört nicht zur Architektur, sondern vielmehr die Art der Ergebnisse und Aufträge. Man muss dann eben immer beachten, dass die Übertragung eine kurze Weile dauert, und deshalb die Daten nicht zu oft gesendet werden dürfen und nicht zu groß sein dürfen.

Dabei ist selbstverständlich das Hauptproblem das Aufteilen der Arbeit, denn die Calculators sollten schon eine Weile zu Rechnen haben, bevor sie das Ergebnis zurückschicken, damit sich die ganze Sache lohnt.

Einen Anwendungsfall sehe ich hier zum Beispiel wenn man viele parallele Ausführungen von einem Netz durchführen möchte, mit dem Lernen sieht es hier schon etwas komplizierter aus, weil sich ja die Gewichte ständig ändern und deshalb immer hin und hergeschickt werden müssten. Letztendlich werde ich wohl zuerst über eine generelle Infrastruktur zum Zusammenschließen eines solchen Rechenclusters nachdenken müssen, die mein Netze-Programm dann benutzen kann. Aber diese Funktionen werden natürlich noch nicht mit der CTP 2 kommen, aber wenn sowas funktioniert, dann wäre das sicherlich ein Release für sich wert.

Neue Webpage für AI

Vielleicht hat der eine oder andere schon gemerkt, dass auf der Hauptseite jetzt noch ein neuer Link auf eine Seite zu nnspace steht(anstatt der neuron net builder Sache). In Zukunft werden jetzt alle relevanten Informationen, Downloads und Dokumentationen zu NNSpace und der NNS(Meiner „Verfassung“) dort auftauchen. Ich nenne meine Dokumentation zu NNSpace jetzt Automation Guidance(NNAG). Hier mal noch ein Link

Einheit auf der ganzen Linie – Was Deutschland mit AI gemeinsam hat

Heute ist der Tag der deutschen Einheit! Aufgrund der geschichtsträchtigen Ereignisse vor 20 Jahren hab ich mir auch einmal Gedanken über Einheit gemacht. Dabei hab ich meine Netze zwar nicht gleich schwarz – rot – gold gestrichen, aber es geht(war ja klar) um NNSpace:

Eigentlich ist es ja eine Schande. Jedes halbwegs fortschrittliche Land hat heutzutage eine Verfassung. Es existieren für viele Streitfälle(z.B. in der Justiz, o.ä.) genau festgeschriebene Gesetzmäßigkeiten, an die sich alle(oder auch nur manche) halten. Aber wenn ich jetzt den Browser aufmach und neural networks bei google reinhack, dann find ich gleich auf Anhieb mehrere verschiedene Möglichkeiten, wie man sich sowas vorstellt. Ich mein damit nicht, dass etwa bezweifelt wird, dass da Neuronen sind und dass die Gewichte zwischen sich haben und Aktivierungsfunktionen, aber dann hörts auch schon wieder auf. Fragen über Fragen: Müssen die Eingänge immer addiert, und die Gewichte immer mit den Ausgaben multipliziert werden? Was genau ist eine Schicht, gibt es sowas überhaupt, wenn ja wozu? Wann gehören Neuronen zu einer Schicht, wann zu einer anderen? Wie kann man ein neuronales Netz generell(ohne Wissen über den konkreten Anwendungsfall) mit einer spezielleren Struktur, als nur das Neuron als ultimativen Baustein darstellen? Also hab ich mich hingesetzt und eine Verfassung für neuronale Netze geschrieben. Ich werd jetzt NNSpace direkt nach der ausrichten, und meine ganze Infrastruktur aus ihrer Grundlage heraus aufbauen, und sie von jetzt ab immer als Beweis und Erklärung nutzen, weil ich finde, dass so eine einheitliche Definition von unbedingter Wichtigkeit ist. Wer sich meine Einfälle dazu mal ansehen möchte kann das Dokument in Kürze hier runterladen. Es soll NNSpace und der ganzen AI eine Ordnung geben, und bestehende Modelle besser erklären helfen. Dabei hab ich natürlich versucht alle Seiten zufrieden zu stellen, und eine zugleich spezielle, aber auch allgemeingültige Ordnung zu bringen. Wer diese Spezifikation(so mein Ziel) erfüllt(oder durch kleine Umbauten erfüllen kann), der kann und sollte sein Modell sofort in NNSpace dynamisch einbinden. Es handelt sich hierbei also um eine Art Eignungstest(wo wir wieder bei der Integration und Wulff und der deutschen Einheit wären). Sieht man mal wozu mich der gute Kohl noch alles bringt…

EDIT: Download hier

The principle of neural networks – Eine einfache Sicht auf neuronale Netze

Meine Gedanken schweifen im Moment in die Richtung Abstraktion für neuronale Netze. Irgendwie hab ich den Eindruck, dass mein altes feed-forward Programm nicht mehr ganz aktuell ist, wenn ich auf die deep belief networks schaue. Es ist ja so, dass man(mit einigem Aufwand) so ein deep belief network bauen kann. Sonst gäbe es sie ja nicht. Aber das ist immer mit sehr viel Tipperei verbunden, und nicht jeder, der diese Netze gerne mal austesten würde beherrscht eine Programmiersprache und kennt sich mit den mathematischen Hintergründen aus. Wie Komplex diese Dinger sind merkt man spätestens wenn man mal versucht eins selbst zu programmieren(wie ich es jetzt in C# geschafft hab). ich könnte jetzt meinen Quellcode posten, und vielleicht würde ihn sogar der eine oder andere verstehen, aber irgendwie gefällt mir der Ansatz nicht für jedes dieser Netzte ein neues Programm zu schreiben(was dann auch noch so riesig ist!). Deshalb ja auch schon meine klein Anwendung für feed-forward. Also muss auch für die deep belief networks ein Tool her(meiner Meinung nach). Allerdings findet man im Internet dazu überhaupt nichts, und zumindest die meisten Tools haben die Dinger nicht in ihrer Feature-liste. Die Antwort in den Support Foren ist dann meistens: Haben wir nicht, kriegen wir auch nicht. Und auch bei den Tutorials steht überall: „Man schreibe den Code für …“. Also gibt es noch nicht wirklich ein Tool, was deep lerning Algorithmen bereitstellt. Ok, aber warum nicht? ist es denn wirklich so schwierig? Ich denke ja, und nein. Zunächst: ja, natürlich, komplizierter als Backprop allemal, und wenn  man dann noch wie Hinton Backprop und deep lerning kombinieren will, wirds erst recht kompliziert, wenn nicht sogar unmöglich für die meisten(zum Beispiel mein Programm). Also, warum dann nein? Weil ich der Meinung bin, dass man für so etwas zunächst mal seine Perspektive verändern muss:

Was ist ein neuronales Netz, woraus besteht es?

Alle neuronalen Netze sind doch im Prinzip sehr ähnlich in gewissen Dingen. Da fallen mir eigentlich 3 ein, nämlich: Sie alle haben Gewichte, Schichten, und Abhängigkeiten. Abhängigkeiten heißt: Unit a hängt von Unit b mit dem Gewicht g ab. Schichten deshalb, weil ich einfach zu faul bin über 700 Units einzeln aufzulisten. Wenn das nötig ist befindet sich eben in jeder Schicht nur eine Unit, aber der Benutzer soll  nicht(wie das bei manchen Tools der fall ist) mit einem riesigen Bild von Kreisen die über Striche verbunden sind verärgert werden, weil er da sowieso nicht durchsieht, sondern er soll eine schöne überschaubare Liste haben, die soweit wie möglich zusammengefasst ist. Deshalb: Schichten, und keine Units, das ist der erste wichtige Punkt. Abhängigkeiten definieren dann eben nicht Abhängigkeiten zwischen Units, sondern zwischen Schichten, und Gewichte sind Eigenschaften der Abhängigkeiten. Warum also die Gewichte noch von den Abhängigkeiten trennen, eigentlich gibt es doch(normalerweise) auch nur einfach Gewichte, und nicht noch was drüber. Mein Gedanke war da der folgende: Zum Lernen brauch ich Gewichte, und wirklich nur Gewichte. Ich hab einen Algorithmus, und der verändert Gewichte nach einem bestimmten Schema(natürlich anhand von Lerndaten, die aber nicht Bestandteil des Netzes sind). Das heißt ich trenne die Lernlogik von der Ausführungslogik, was es mir ermöglicht mehrere Gewichte mit unterschiedlichen Algorithmen zu trainieren, und auf eine noch ganz andere selbst definierte Weise auszuführen.

Also haben wir jetzt eine ganz neue Definition von einem neuronalen Netz, die sich viel leichter implementieren lässt. Wie das Programm aussieht, und wie es im konkreten funktioniert, darüber später mehr. Wichtig für mich ist das Folgende: Finden wir eine Definition für alle neuronalen Netze, die so einfach ist, dass sie 1. der Benutzer versteht und anwenden kann, ohne sich über Algorithmen Gedanken machen zu müssen, und die aber auch so genau ist, dass 2. ein Algorithmus genau weiß, was er zu tun hat, und die 3. so dynamisch ist, dass sie auf alle erdenklichen Variationen von implementierten Algorithmen angewandt werden kann, weil: der Algorithmus ändert sich ja nicht, sondern nur die Struktur, wie das Netz ausgeführt wird, oder besser gesagt wie die Gewichte ausgeführt werden.

Demzufolge liegt mir besonders die Trennung von Gewichten und allen anderen Bestandteilen am Herzen, weil die es ermöglicht den Algorithmus immer so zu lassen wie er ist.

Hier schon mal ein erster Screenshot von der Anwendung im Design-Modus:

Ein einfaches feed forward Netz ohne hidden Schicht:

Viele Layer im deep belief network

In einem der letzten Posts war bereits  eine ganz einfache Restricted Boltzmann Machine das Thema, jetzt soll es darum gehen, wie mehrere Layer aussehen, und wie das Lernen implementiert wird.

1. Wie funktioniert eine RBM?

Wir müssen uns bei dem Umstieg von einem feed-forward Netz zur RBM zunächst mit einigen grundsätzlichen Dingen vertraut machen. Ein feed-forward Netz hat Eingabe- und Ausgabeunits, und beliebig viele versteckte zwischengeschaltete Schichten. Von der Optik her sieht die RBM ganz ähnlich aus, mit dem Unterschied, dass es prinzipiell nur 2 Schichten gibt, wobei die Units allerdings nicht nur in eine Richtung, sondern in beide Richtungen miteinander verkettet sind:

Eine RBM verwendet ausschließlich binäre Aktivierungsfunktionen, wobei beachtet werden muss, dass das ganze mit Wahrscheinlichkeiten rechnet, dazu aber später mehr. Das Netz berechnet sich aber jetzt nicht mehr so einfach wie feed forward(logisch), sondern die erste Schicht dient sowohl als Eingabe-, als auch als Ausgabeschicht, wobei wenn sich diese ändert, sich wieder die nachgeschaltete Schicht ändert, die wieder die erste Schicht beeinflusst u.s.w. Ein bestimmter Zustand des Netzes bezeichnet eine sogenannte Energie des Zustandes. Je geringer diese Energie umso wahrscheinlicher, dass das Netz in der Stellung verharrt, oder je größer die Energie umso größer die nachfolgende Änderung, ähnlich wie beim Hopfield – Netz. Die Energie berechnet sich aus den bestimmten Zuständen der Units und den Gewichten nach der Formel:

v = ist der Zustand aller input(visible) Units, also erste Schicht(normalerweise Vektor oder im Programm eine Liste),
h = der Zustand aller hidden Units(zweite Schicht),
w = Gewichtsmatrix
b = die bias Parameter der Units(könnte auch als eigenständige Bias Unit entwickelt werden, dann entspricht dieser Wert den Bias – Gewichten auf die Unit)

Es gibt also nicht mehr input und target Werte, sondern einfach nur noch input Werte, was die ganze Sache vereinfacht, das Netz lernt sich selbst ein. Der Lernvorgang bezeichnet also eigentlich das Vermindern der Energie für einen bestimmten Zustand, damit die Wahrscheinlichkeit höher ist, dass dieser am Ende herauskommt. Zu der Verknüpfung der gelernten Daten mit anderen Werten als den inputs kommen wir später mal. Jetzt ist unser Ziel erst mal die exakte Reproduktion gelernter Daten(d.h. ich lerne einen Zustand ein, und wenn der dann wieder kommt ändert sich das Netz nicht, d.h. der Zustand hat eine zu geringe Energie für eine Änderung)

Das tatsächliche Lernverfahren ist relativ einfach:

  • Als erstes werden neben den input und hidden Schichten noch zwei weitere Schichten erstellt, die wir nur zum Lernen brauchen. Wir erstellen also ein Netz was das Netz trainiert. Die neuen Schichten entsprechen den ersten Schichten, und auch die Gewichte sind immer dieselben. Dieses Kopieren hat den einzigen Grund, dass die Werte zwar reproduziert werden sollen, aber der Eingangsvektor unverändert bleiben soll, weil der dann später noch gebraucht wird. Man kann sich das auch so vorstellen, dass das Netz nur einmal ausgeführt wird, also die input Werte genau einmal auf die hidden, dann wieder auf die inputs, und dann noch mal auf die hidden propagiert werden, und zwischendurch alle Werte und Zwischenstellungen gemerkt werden. Sieht dann so aus:
  • Dann werden die Gewichte zufällig initialisiert(oder eben bereits vorhandene Gewichte von anderen Lernvogängen sind schon da), wobei alle drei Gewichtsmatrizen exakt gleich sind. Man schaue sich zur Verdeutlichung noch mal  das Bild weiter oben an. Man sieht, dass die Gewichte nach oben und unten übereinstimmen, und da der letzte sowieso  nur eine Kopie vom ersten ist sind die natürlich auch gleich.
  • Jetzt kommt das eigentliche Lernen(simpel): Der Eingabevektor wird auf die ganz linke untere Schicht draufgegeben, dann werden alle anderen Schichten berechnet. Wenn in den beiden linken Schichten zwei Units gleichzeitig aktiv(eine oben, eine unten) sind wird deren Gewicht um eine Lernrate erhöht, wenn dasselbe in der rechten der Fall ist wird das Gewicht um die Rate vermindert.

Fertig mit Lernen!

2. Wie funktioniert ein deep belief network?

Was ist der Unterschied zwischen einer RBM und einem deep belief network? Ganz einfach ein deep belief network ist eine Stapelung von RMB´s, das heißt ich nehme einfach die hidden Schicht von meiner RBM als input für die nächste RBM, die dann oben darüber gebaut wird. Dann nehm ich deren hidden wieder als input für die nächste, und so weiter… Das macht das Ganze wesentlich effizienter, weil wir viel mehr Regelmäßigkeiten/Features oder Muster oder wie man es auch immer nennen will erkennen können, weilwir in den Mustern wieder nach Mustern suchen. Klingt vielleicht kompliziert, ist es aber nicht. Am Lernen ändert sich überhaupt nichts. Es wird einfach erst die unterste RBM eingelernt, dann wird mit deren hidden die nächste trainiert, und die nächste und nächste…

Wäre natürlich langweilig wenn das alles über deep belief networks wäre, man kann die noch tunen, da kommt dann wieder mal die Backprop, aber das schreib ich jetzt nicht mehr hier rein. Also: Auch wenn Deutschland(leider) jetzt nicht ins WM Finale kommt: Das war erst der Anfang(und nicht das Ende, wie bei der WM)

Restricted Boltzmann Machine – einfacher Test

Die neue Generation der neuronalen Netzwerke ist angebrochen!
Ich hab mal versucht meine Infrastruktur auf die neuronalen Netze von hier anzuwenden. Natürlich erst mal mit dem ganz einfachen Beispiel am Anfang probiert. Meine Anwendung sieht jetzt so aus:

Dazu hab ich mir noch ein kleines Control geschrieben, was die Pixeleingabe ermöglicht. Man kann also jetzt ein Muster eingeben:

und dann mit Train trainieren. Ich hab das mal mit ein Paar Einsen ausprobiert, und jetzt kommt eine Eins, die er noch nie gesehen hat:

Ok, zugegeben ich bin nicht besonders gut im Einsen malen, aber er macht die noch schön gerade, und verändert sie dabei fast nicht:

Und dabei hab ich ihn nur mit handgemalten(hässlichen) Daten, und auch nicht mit besonders vielen trainiert. Find ich genial, vor allen Dingen, weil das ja eigentlich noch gar nicht fertig ist, es kommen ja noch sehr viele Schichten dazu(also höhere Genauigkeit). Ich werden demnächst mal meine Anwendung mit diesen Beispielen erweitern. Vorher sind aber erstmal die  nächsten Schichten angesagt.

Neural Nets extendet — Alles vernetzt

Hi,

das erste Stable Release von meiner Anwendung zum Bauen neuronaler Netze ist einsatzbereit! Gleich mit dazu kommt eine Anwendung, die die Zahlen 1 bis 5 als Muster erkennt(Mehr über das Projekt und Download)


Pattern Recognizer
Neural Networks in action


Die Implementierung davon ist mit meiner schönen Infrastruktur ganz einfach


  • Step 1, Netz laden


Das Netz wird aus einer Datei mit der Endung .nnet geladen:

try
{
    using (FileStream fs = new FileStream(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "patrec.nnet"), FileMode.Open, FileAccess.Read))
    {
           this.LayerList = ((SerializationObject)new BinaryFormatter().Deserialize(fs)).LayerList.ToList();
    }
}
catch
{
    MessageBox.Show("Error, net file not found", "Error");
}

Dabei wird einfach der Binary Formatter genutzt um die Kontraktklasse SerializationObject, in der alle wichtigen Informationen enthalten sind, zu speichern, und zu laden.


  • Step 2, Execute Vorbereiten


Wenn die Ausführung beendet ist, wollen wir das Ergebnis in Variablen(strings) abspeichern, die an die Oberfläche gebunden sind(PropertyChanged aktualisiert die WPF Obberfläche). Dazu definieren wir für jede Ausgabeunit folgendes:

buildNet.First(el => el.Key.Layer == 2 && el.Key.Index == #).Value.OutputChanged += delegate
{
    this.Result# = buildNet.First(el => el.Key.Layer == 2 && el.Key.Index == #).Value.Output.ToString();
    this.OnPropertyChanged("Result#");
};

(Vorrausgesetzt es handelt sich um ein 3-Schichtiges Netz, da Layer 0 der kleinste Layer ist, ist dann 2 der größte, also der Ausgabelayer)

Das Delegate wird sofort bei Wertänderung aufgerufen, und die Ergebnisse werden weitergeleitet.

# ist durch den jew. Index der Augabeunit zu ersetzen, dann wird bei erfolgter asynchroner Ausführung der Wert der zuvor zu definierenden Variable gesetzt, also: alles ganz easy!


  • Step 3, Execute itself


Dann muss das Netz natürlich ausgeführt werden, wobei alle Eingabewerte durch Benutzereingabe gegeben sind. Es braucht nur noch folgendes für jede Eingabeunit an die Infrastruktur weitergeleitet zu werden:

buildNet.First(el => el.Key.Index == # && el.Key.Layer == 0).Value.Input(Value#);

# ist der Index der Eingabeunit, Value# der Wert, den der Benutzer für die Unit angegeben hat.

Dann wird das ganze asynchron ausgeführt, und die Ergebnisse erscheinen im Fenster.

Thats it!