neuronales Netz
-
Die Zahl der Schichten, sowie die Zahl der Neuronen pro Schicht sind variabel (vector). Sogar jedes einzelne Neuron kann in einem bestimmten Rahmen verschieden viele Inputs haben. (hat aber immer noch nur einen Output
)
Hmm ... was ist denn ein Sigma-Pi-Neuron?
-
Insgesamt geht der Code über 4 dateien: (2 Header- sowie 2 Implementierungsdateien)
neuron.h:
#include<iostream.h> #include<vector.h> #include<stdlib.h> #include<time.h> class synapse; class neuron // Einfaches Neuron innerhalb der Schichten des neuroalen Netzes { public: neuron(); neuron(int nof_inputs); neuron(bool willk); // willkuerliche Initalisierung der Reizschwellen virtual ~neuron(); virtual int operator() (); // Funktionsweise void SetReizschwelle(int rs); int GetReizschwelle(); vector<synapse> inputs; int output; protected: int Reizschwelle; }; class synapse { public: neuron * val; // Verbindung zum unteren Neuron float strengh; // Synaptische Staerke der Verbindung }; template<class S> class inpsynapse; template<class T> class primarneuron : public neuron // Neuron aus der ersten Schicht (N0) { /// aufgrund offenkundiger Aehnlichkeiten zu einem public: // gewoehnlichen Neuron von neuron a bgeleitet primarneuron(); primarneuron(int nof_inputs); ~primarneuron(); int operator() (); vector<inpsynapse<T> > primarinputs; }; template<class S> class inpsynapse { public: S * dot; float strengh; };
neuron.cpp (Implementierungsdatei für die Methoden der obrigen Klassen)
#include"neuron.h" int zufall(const int min, const int max) { int delta; delta = max - min; if(delta <= 0) return min; return (rand() % delta) + min; srand( (unsigned)time( NULL ) ); } neuron::neuron(): Reizschwelle(2), output(0) { } neuron::neuron(bool willk) { if (willk) Reizschwelle=zufall(1,6); else Reizschwelle=2; output=0; } neuron::neuron(int nof_inputs): Reizschwelle(2), output(0) { inputs.resize(nof_inputs); } neuron::~neuron() { } int neuron::operator() () { int str_inputs=0, str_input; output=0; // ! for (int i=0; i<inputs.size(); ++i) { str_input=inputs.at(i).val->output * inputs.at(i).strengh; str_inputs+=str_input; } if (str_inputs > Reizschwelle) output=1; return output; } template<class T> primarneuron<T>::primarneuron(): neuron::Reizschwelle(2), neuron::output(0) { } template<class T> primarneuron<T>::primarneuron(int nof_inputs): neuron::Reizschwelle(2), neuron::output(0) { primarinputs.resize(nof_inputs); } template<class T> primarneuron<T>::~primarneuron() { } template<class T> int primarneuron<T>::operator() () { int str_inputs=0, str_input; output=0; // ! for (int i=0; i<inputs.size(); ++i) { str_input=primarinputs.at(i)->int(dot) * primarinputs.at(i).strengh; str_inputs+=str_input; } if (str_inputs > Reizschwelle) output=1; }
Dann noch der Code für die Klasse, die das Netz als solches repräsentiert
#include"neuron.h" class N_netz { public: N_netz(int levels, int neuronen); // Seitenlaenge der quadratischen Input-Matrix=10, Anzahl der Schichten ~N_netz(); long react(); // Ausloesung jedes Neurons private: int nof_neuronen; // zahl der Neuronen float (*Input)[10]; primarneuron<float> (*schicht1)[10]; vector<vector<neuron> >* schichten; };
Und ihre Methoden ...
#include"nnetz.h" int zufall(const int min, const int max) { int delta; delta = max - min; if(delta <= 0) return min; return (rand() % delta) + min; srand( (unsigned)time( NULL ) ); } N_netz::N_netz(int levels, int neuronen) { nof_neuronen=neuronen; // ------------------------ Aufbau der Topologie des Netzes: -------------------- Input=new float[10][10]; // Input definieren schicht1=new primarneuron<float>[10][10]; // Erste Schicht Neuronen erstellen // Erstellen synaptischer Verbindungen der Erstneuronen zu den Datenpunkten des Input inpsynapse<float> * tsyp; // Aktuelle Synapse auto int sy; // Aktuelle Zahl an Synapsen for (int i=0; i<10; i++) { for (int j=0; j<10; j++)// Fuer jedes Primaerneuron: { sy=zufall(2,10); // Synapsenzahl festlegen for (int k=0; k<=sy; k++) // Fuer jede neue Synapse: { tsyp=new inpsynapse<float>; // Neue Synapse tsyp->strengh=zufall(0,5)/3; // Synaptische Staerke festlegen tsyp->dot=&Input[zufall(0,9)][zufall(0,9)]; // Punkt aus Input nehmen schicht1[i][j].primarinputs.push_back(tsyp); // Synapse dem Neuron zufuehren } } } schichten=new vector<vector<neuron>(neuronen)>(levels); // Neue Neuronen erstellen // Erstellen synaptischer Verbindungen der anderen Neuronen zur jeweils unteren Schicht for (int n=0; n<schichten.size(); n++) { synapse * tsyn; // Aktuelle Synapse auto int sy; // Aktuelle Zahl an Synapsen if (n>0) { for (int i=0; i<schichten.at(n).size(); i++)// Fuer jedes Primaerneuron: { sy=zufall(2,10); // Synapsenzahl festlegen for (int k=0; k<=sy; k++) // Fuer jede neue Synapse: { tsyn=new synapse; // Neue Synapse tsyp->strengh=zufall(0,5)/3; // Synaptische Staerke festlegen tsyp->val=&schichten.at(n).at(zufall(0,schichten.at(n).size())); // Punkt aus vorheriger Schicht nehmen schichten.at(n).at(i).push_back(&tsyn); // Synapse dem Neuron zufuehren } } } else { for (int j=0; j<schichten.at(n).size(); j++)// Fuer jedes Primaerneuron: { sy=zufall(2,10); // Synapsenzahl festlegen for (int k=0; k<=sy; k++) // Fuer jede neue Synapse: { tsyn=new synapse; // Neue Synapse tsyp->strengh=zufall(0,5)/3; // Synaptische Staerke festlegen tsyp->val=&schicht1[zufall(0,9)][zufall(0,9)]: // Punkt aus erster Schicht nehmen schichten.at(n).at(j).push_back(&tsyn); // Synapse dem Neuron zufuehren } } } } tsyp=0; tsyn=0; } N_netz::~N_netz() { delete schichten; delete [] schicht1; delete [] Input; } long N_netz::react() { long rt=0; // Netz traversieren: // Erste Neuronen abfragen: for (int i=0; i<10; i++) { for (int j=0; j<10; j++) { schicht1[i][j](); } } // Die weiteren Neuronen abfragen: for (int i=0; i<schichten.size(); i++) { for (int j=0; j<schichten.at(i).size(); j++) { schichten.at(i).at(j)(); } } // Outputs der letzten Schicht summieren for (int k=0; k<schichten.at(schichten.size()).size(); k++) { rt+=schichten.at(schichten.size()).output; } return rt*rt; // Ergebnis quadrieren und zurueckgeben }
Könnte sein das der Code ein paar Schnitzer enthält. Ich bin ihn mal in der Schule (irgendwann vor den Ferien) durchgegeangen und hab mehrere gefunden. Allerdings hab ich die Blätter auf denen er ausgedruckt war, verlegt ...
-
_mein_ neurales netz besteht aus nur einer ebene
ich hab einen eingangsvector und den gewünschten ausgangsvector, daraus generiere ich die matrix. wenn ich nun die matrix * den eingangsvector rechne, bekomme ich den ausgangsvector.
man kann nun mehrere matrizen aufeinander addieren und "verrauschste" eingangsvectoren anlegen, die matrix wird mit hilfe ihrer gewichtungen das best mögliche ergäbniss liefern.
das ist alles was man zum lehren eines einfachen netzes bauen muss,
das ist ein neuronales Netz und man braucht dafür keine genialen klassen mit den unmöglichsten verknüpfungen. auch bei mehreren ebenen generiert man sich nur matritzen die anhand eines eingangsvectors, den ausgangsvector erstellt werden.
die verbindungen zwischen den ebenen erhällt man, indem man zu jedem eingang einen vector generiert, der mit dem ausgangsvector der vorherigen ebene multipliziert wird (dotprodukt) um den eingangspegel zu erhalten.
an sich ist das die einfachste methode die man schon lange benutzt, da braucht man keine klassen im code zu verknüpfen, man kann sich eine textdatei erstellen in der alles definiert ist. es ist quasi nur ein riesiges array von ein- und ausgängen.
wenn unbedingt erwünscht ist kann ich, wenn ich zuhause bin, ein kleines beispiel aus irgend nem buch abtippen
neuronale netze sind nur mathematisch konstrukte die auch mathematisch modeliert werden, dein code schaut zwar schön aus wenn man ihn als tutorial für für klassenstrukturierung nutzen wollen würde, aber sowas ist eher ungebräuchlich.
falls du mehrere ebenen lehren möchtest, dann solltest du nach "Reinforcement Learning" googlen, aber es ist echt schwer, falls du sofort damit anfangen möchtest, ich hab mit einiger "vor-erfahrung" fast 6 monate gebraucht bis ich zwei simple einheiten(schiffe) dazu gebracht hatte gegeneinander zu kämpfen und nicht sich im kreis zu drehen, voneinander wegzulaufen oder sich zu rammen.
das hier klingt irgendwie, wie: ich hab ein fortbewegungsmittel gebaut, weiß jemand womit ich es betreiben muss? es besteht aus eisen und kohlefasern.
übrigens strotzt dein code vor magischen werten, z.B.
Input=new float[10][10]; // Input definieren schicht1=new primarneuron<float>[10][10]; // Erste Schicht Neuronen erstellen
rapso->greets();
-
rapso schrieb:
ergäbniss
OMG
noch falscher gehts net, ne?
-
eek schrieb:
rapso schrieb:
ergäbniss
OMG
noch falscher gehts net, ne?ärgehbniss, aber das wollte ich euch doch net zumuten :), aber wenn du lieber auf das extremerere propagierst, dann kann ich das sicherlich bewerkstelligen
rapso->greets();
-
rapso schrieb:
das ist ein neuronales Netz und man braucht dafür keine genialen klassen mit den unmöglichsten verknüpfungen. auch bei mehreren ebenen generiert man sich nur matritzen die anhand eines eingangsvectors, den ausgangsvector erstellt werden.
die verbindungen zwischen den ebenen erhällt man, indem man zu jedem eingang einen vector generiert, der mit dem ausgangsvector der vorherigen ebene multipliziert wird (dotprodukt) um den eingangspegel zu erhalten.
an sich ist das die einfachste methode die man schon lange benutzt, da braucht man keine klassen im code zu verknüpfen, man kann sich eine textdatei erstellen in der alles definiert ist. es ist quasi nur ein riesiges array von ein- und ausgängen.
Naja, damit entgehen Dir aber viele Möglichkeiten...
Mit dieser Methode kann man nur Feed-Forward-Netze darstellen und nur lineare Neuronen benutzen. Auch kann man damit nicht jede beliebige Aktivierungsfunktion für den Ausgang des Neurons benutzen.
Und es klingt bei Dir so, wie wenn ein NN mit mehreren Ebenen irgendwie besonders wäre. Ein Feed-Forward-Netz wird üblicherweise immer mindestens 3 Schichten aufweisen, weil ein 2-schichtiges Netz nicht alle Funktionsklassen lernen kann.
Mir gefällt sein Ansatz auch nicht, weil er den Schichtaufbau nicht berücksichtigt und die verschiedenen Systemfunktionen und Neuron-Typen nicht abbildet, bzw. diese auch nicht austauschbar sind.
Aber die Realisierung über Vektoren und Matrizen deckt nur einen unglaublich kleinen Teil der NNs ab. Ein NN, das sich über Vektoren und Matrizen darstellen läßt ist ja nur ein lineares Gleichungssystem, bzw. eine lineare Interpolation einer Funktion. Die ganzen Möglichkeiten nicht-linearer Darstellungen mit Hilfe von NNs entgehen einem.
-
Vielleicht übersiehst du auch nur die Möglichkeiten die man hat, man muss sich nicht auf Feed-Forward-Netze beschrenken. Wenn man im ganzen Netz jeden Eingang und Ausgang eindeutig identifizieren kann, dann werden die Vektoren recht gross die man als Gewichtung benutzen muss, aber damit kann man jeden Eingang mit jedem Ausgang verknüpfen, wenn wir (Menschen) einen Lernalgorithmuss kennen würden, dann wäre es sogar relativ leicht zu realisieren, dass das Netz neue "Verknüpfungen" erstellt, wäre ja nur ein Eintrag im Vector.
Man muss natürlich immer in einen Temp-Vektor die Ergebnisse schreiben und dann zurückkopieren, aber mit diesem System ist jede Verkettung möglich.
Was die Gewichtung anbetrifft spricht eigentlich nichts dagegen diese als Operanten für eine Gewichtungsfunktion zu missbrauchen
Was für mich Neuronale-Netze ausmacht ist, dass man dafür wenig programmieren muss, weil sie aus "primitiv"-Bauteilen bestehen und durch ihre Organisation die "Genialität" entwickeln, deswegen sollte man, meiner kleinen Meinung nach, ein Programm haben, dass man mittels "Config" zu jeder verknüpfung bringen kann. Schlussendlich ist das ganze "Ding" nur Mathematik und kein Algorithmus den man _jedesmal_ neu zu implementieren braucht.
Das verbinden von Klassen und sontigem (mittels Code) ist nicht das, was ein Neuronales-Netz ausmacht, es ist nur die Mathematik... wenn man sich ein _gutes_ Buch darüber besorgt, dann sieht man kaum eine grafische Darstellung von Netzen, sondern nur Formel-Modelle.
bsp.: http://documents.wolfram.com/applications/neuralnetworks/NeuralNetworkTheory/2.7.0.html
rapso->greets();
ps. ich wünschte ich wüste wie man neue Verknüpfungen "lehren" könnte *seufz*
-
hmm ... hab ich mir schon fast gedacht, das mein Code Müll ist, naja ich hab ja keine Erfahrung im Programmieren neuronaler Netze, der Code da oben ist mein erstes. raspo, könntest du hier mal'n Beispielcode von einem deiner Netze posten? (inklusive der dazugehörigen Funktionen)
Noch eine Frage zur Begriffsklärung: Was meint ihr mit 'Gewichtung' ?
-
rapso schrieb:
Vielleicht übersiehst du auch nur die Möglichkeiten die man hat, man muss sich nicht auf Feed-Forward-Netze beschrenken. Wenn man im ganzen Netz jeden Eingang und Ausgang eindeutig identifizieren kann, dann werden die Vektoren recht gross die man als Gewichtung benutzen muss, aber damit kann man jeden Eingang mit jedem Ausgang verknüpfen, wenn wir (Menschen) einen Lernalgorithmuss kennen würden, dann wäre es sogar relativ leicht zu realisieren, dass das Netz neue "Verknüpfungen" erstellt, wäre ja nur ein Eintrag im Vector.
Ich sehe nicht den Vorteil einer riesigen Matrix - es gibt da zwei Varianten:
a) ich nehme ein normales 3-schichtiges Netz, aber verbinde alle Neuronen miteinander und setze gewisse Gewichte auf 0, um die Verbindungen zu trennen und die Schichten zu behalten. Dann erhalte ich eine schwach besetzte Matrix, deren Operationen alle nicht effizient ausgeführt werden.
b) ich verbinde alle Neuronen aller Schichten miteinander und lasse beliebige Verknüpfungen zu - das ist nicht unbedingt hilfreich, da es die Zerlegungssätze für die Interpolation mit Hilfe von NN gibt, die mir aussagen wie komplex ein 3-schichtiges Netz für eine gewisse Interpolationsgenauigkeit sein muß. Wenn ich das Netz nun aber dichter Webe als notwendig ist um zu interpolieren, besitzt mein Netz unnötige redundante Verknüpfungen, die keine neuen Informationen hinzu nehmen.
Und wie gesagt, es ist nicht mehr jeder Neuronentyp verwendbar, mein Netz ist dann eben "nur" noch ein lineares Gleichungssystem.
rapso schrieb:
ps. ich wünschte ich wüste wie man neue Verknüpfungen "lehren" könnte *seufz*
Kannst Du doch - Du verbindest alle Neuronen miteinander und trainierst das NN mit einem Algorithmus, der die Gewichte ändert. Ein Gewicht = 0 bedeutet keine Verbindung - und != 0 bedeutet eine Verbindung. Oder hast Du die Hinzunahme neuer Neuronen damit gemeint?
@cortext85: Begriff "Gewichtung" siehe http://www.fbe.hs-bremen.de/user/risse1/RST/SS98/Neural_N/neuronet.htm#_Toc422573785
-
der vorteil ist, dass du für jedes netz das du haben möchtest nur eine configdatei erstellen mußt, inder du die verbindungen als matrix angibst. es gibt viele leute die die nötige mathematik kennen aber nichtmal prolog können um sich ihre ideen einzucoden, deswegen sind programme, die mathematische eingaben zum konfigurieren brauchen wohl beliebt
das wäre ein vorteil, ein andere wäre, dass man klar darstellt dass es sich bei dem ganzen um mathematik handelt und keine pointer-arithmetik und algorithmen-wirrwarr.wie gesagt, man kann verschiedene aktivierungsfunktionen nutzen wenn man nicht einfach nur ein DotProduct rechnet, sondern vorher die funktion auf den wert anwendet. dann wäre es nicht mehr linear.
"Kannst Du doch - Du verbindest alle Neuronen miteinander und trainierst das NN mit einem Algorithmus, der die Gewichte ändert. Ein Gewicht = 0 bedeutet keine Verbindung - und != 0 bedeutet eine Verbindung. Oder hast Du die Hinzunahme neuer Neuronen damit gemeint? ", Marc++us.
ich meinte keine neuronenzunahme, sondern der aufbau von verbindungen bzw deren kappung. alle mir bekannten trainingsmethoden bauen auf einer vorgegebenen struktur auf, die durch training verbindungen verstärkt oder abdämpft. wenn ich einfach alles mit allem verbinden würde, würde das trotzdem nicht wirklich was schlaues sein müssen.... das ergebnis wäre meiner ansicht nacht sogar total "match", nicht zu gebrauchen.
In einem gehirn bauen sich ja neue verbindungen auf, dabei scheint es auch nicht wirklich ebenen zu geben, die neuronen stellen verbindungen zu anderen her wenn sie lernen.... ich wüste wirklich nicht wie ich überhaupt mathematisch entscheiden sollte welche verdindung aufgebaut wird.
solange es eine oder zwei ebenen sind, ist das ja kein problem, bei 3 ebenen wird es aufwendiger, da man aber die struktur kennt, kann man die bewertungen noch errechnen. aber bei belibigen verknüpfungen?und Cortex85, du hast nicht müll produziert, aber neuronale netze baut man nicht einfach so, eigentlich hat man eine problemstellung und versucht dafür dann das passende netz zu bauen. du hast erstmal die lösung gemacht und möchtest nun ein problem das du damit angehen möchtest und auch noch den weg dazu (die trainingsmethode).
such dir im netz sachen zum z.B. sinusberechnen,wurzelberechnung oder xor mittels neuronaler netze oder so und code dafür dann dein netz das die aufgaben lernt
rapso->greets()
-
kann mir jemand n gutes buch dazu empfehln? (sowas wie "neuronale netze für dummies" ;))
bin bald 2 wochen in italien und hab noch keine lektüre...
-
@raspo: Stimmt, so ungefähr kam es mir auch vor. ich hatte vor, mein Netz auf das Erkennen bestimmter Zahlenmuster in Matrizen zu trainieren, mir fehlte nur die Trainingsfunktion. Das war bloß 'n Lückenfüller-Problem, das stimmt. ich denke, ich werde irgendwann (vielleicht in den nächsten Tagen) mal danach googlen, was du mir gesagt hattest
-
meian schrieb:
kann mir jemand n gutes buch dazu empfehln? (sowas wie "neuronale netze für dummies" ;))
bin bald 2 wochen in italien und hab noch keine lektüre...
-
http://www.gamedev.net/reference/programming/features/vehiclenn/
die haben heute wohl einen article uber das thema diese threads veröffntlich und am ende referenzbuecher angefuert.
rapso->greets();
-
Als Buch kann ich nur http://www.amazon.de/exec/obidos/ASIN/3486243500/jone-21 empfehlen. Es ist sehr gut zu lesen, vermittelt aber auch den entsprechenden mathematischen hintergrund. ich hatte mir das buch damals in der 10. klasse zugelegt, damals konnte ich zwar mit partiellen differentialgleichungen noch wenig anfangen, aber es war einem trotzdem möglich alles prinzipiell zu verstehen, selbst ohne große mathekenntnisse. aber wenn die natuerlich vorhanden sind ... umso besser
ich hab ne dokumentation von einem meiner projekte mit ins abi einbringen koennen : http://johannes.lampel.net/bll137.html
da findet man auch nochmal ne kurze herleitung von dem lernverfahren backpropagation.
-
guck doch sonst auch einfach mal in einer uni bibliothek in deiner nähe vorbei