ich glaube, man muss zunächst einmal die KI bzw. NN "freaks" in zwei kategorien aufteilen. 1) anwender und 2) entwickler. Zu einem entwickler eigne ich mich nicht. Bin also "nur" anwender...
Das ist ok, ich benutze - wie milionen andere - ein pkw, ohne im detail zu wissen wie jede einzelner part da funktioniert. Vereinfacht ausgedrückt reicht es zu wissen, wenn ich die kupplung trete, kann ich schalten, ohne dass es knirscht. So möchte ich auch KI bzw. NN nutzen, ich stelle mir das folgendermassen vor:
Den code, den Moppi (danke!) hier gepostet habe, habe ich erstmal etwas aufgeräumt (sorry!) indem ich alles, was in der loop war in eine funktion "calculation()" quasi ausgelagert habe, um die loop übersichtlich zu halten. Ob man diese funktion noch einmal sinnvollerweise in mehr einzelteile, die man sich - nur bei bedarf - anschauen kann, aufteilen sollte, lasse ich erstmal dahingestellt, der code funktioniert zunächst einmal so wie ich ihn aufgeteilt habe.
Andeutungsweise habe ich in der loop mit // erstmal deaktiviert die funktion "input_NN()" eingefügt, der inhalt findet sich auch weiter unten im code. Ich möchte nämlich auch und gerade als "nur" user die möglichkeit haben, die parameter für mein NN vorab einzugeben um die einzelnen parameter auch nebeneinander stellen zu können um sie zu vergleichen. Wie ein vergleich zwischen dem ersten- und rückwärts- gang. Diesen "input code" habe ich (weil die datentypenumwandlung nicht funktioniert hat) nur für die "int" dAtentypen freigeschaltet:Code:/****************************************************************** ArduinoANN - An artificial neural network for the Arduino All basic settings can be controlled via the Network Configuration section. See robotics.hobbizine.com/arduinoann.html for details. ******************************************************************/ #include <math.h> /****************************************************************** Network Configuration - customized per network ******************************************************************/ const float LearningRate = 0.3; const float Momentum = 0.9; const float InitialWeightMax = 0.5; const float Success = 0.0004; const int InputNodes = 2; const int HiddenNodes = 2; const int OutputNodes = 2; const int PatternCount = 4; //zu trainierende Muster const byte Input[PatternCount][InputNodes] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }; //}; const byte Target[PatternCount][OutputNodes] = { { 1, 1 }, { 0, 1 }, { 1, 0 }, { 1, 0 } }; /****************************************************************** End Network Configuration ******************************************************************/ int i, j, p, q, r; int ReportEvery1000; int RandomizedIndex[PatternCount]; long TrainingCycle; float Rando; float Error; float Accum; float Hidden[HiddenNodes]; float Output[OutputNodes]; float HiddenWeights[InputNodes + 1][HiddenNodes]; float OutputWeights[HiddenNodes + 1][OutputNodes]; float HiddenDelta[HiddenNodes]; float OutputDelta[OutputNodes]; float ChangeHiddenWeights[InputNodes + 1][HiddenNodes]; float ChangeOutputWeights[HiddenNodes + 1][OutputNodes]; void setup() { Serial.begin(9600); randomSeed(analogRead(3)); ReportEvery1000 = 1; for ( p = 0 ; p < PatternCount ; p++ ) { RandomizedIndex[p] = p ; } } void loop () { //input_NN(); calculation(); } /****************************************************************** Input ******************************************************************/ int intInput() { char str[10]; int charcount = 0; memset(str, 0, sizeof(str)); // String-Puffer löschen while (!Serial.available()); // Warten bis 1. Zeichen im Eingangspuffer delay(100); // Warten auf weitere Zeichen im Eigangspuffer while (Serial.available() && charcount < 9) { str[charcount] = Serial.read(); // Zeichen aus Eingangspuffer lesen charcount++; } return atoi(str); // String in Integer-Rückgabewert wandeln } void input_NN (void) { /* Serial.print("Geben Sie > LearningRate < (standard = 0.3)ein: "); LearningRate = intInput(); Serial.println(LearningRate); Serial.print("Geben Sie > Momentum < (standard = 0.9)ein: "); Momentum = intInput(); Serial.println(Momentum); Serial.print("Geben Sie > InitialWeightMax < (standard = 0.5)ein: "); InitialWeightMax = intInput(); Serial.println(InitialWeightMax); Serial.print("Geben Sie > Success < (standard = 0.0004)ein: "); Success = intInput(); Serial.println(Success); Serial.print("Geben Sie > InputNodes < (standard = 2)ein: "); InputNodes = intInput(); Serial.println(InputNodes); Serial.print("Geben Sie > HiddenNodes < (standard = 2)ein: "); HiddenNodes = intInput(); Serial.println(HiddenNodes); Serial.print("Geben Sie > OutputNodes < (standard = 2)ein: "); OutputNodes = intInput(); Serial.println(OutputNodes); Serial.print("Geben Sie > PatternCount < (standard = 4)ein: "); PatternCount = intInput(); Serial.println(PatternCount); */ /* Serial.print("Das Ergebnis Wert1 * Wert2 ist = "); long wert3 = (long)wert1 * wert2; Serial.println(wert3); */ Serial.println(); } void calculation() { /****************************************************************** Initialize HiddenWeights and ChangeHiddenWeights ******************************************************************/ for ( i = 0 ; i < HiddenNodes ; i++ ) { for ( j = 0 ; j <= InputNodes ; j++ ) { ChangeHiddenWeights[j][i] = 0.0 ; Rando = float(random(100)) / 100; HiddenWeights[j][i] = 2.0 * ( Rando - 0.5 ) * InitialWeightMax ; } } /****************************************************************** Initialize OutputWeights and ChangeOutputWeights ******************************************************************/ for ( i = 0 ; i < OutputNodes ; i ++ ) { for ( j = 0 ; j <= HiddenNodes ; j++ ) { ChangeOutputWeights[j][i] = 0.0 ; Rando = float(random(100)) / 100; OutputWeights[j][i] = 2.0 * ( Rando - 0.5 ) * InitialWeightMax ; } } Serial.println("Initial/Untrained Outputs: "); toTerminal(); /****************************************************************** Begin training ******************************************************************/ for ( TrainingCycle = 1 ; TrainingCycle < 2147483647 ; TrainingCycle++) { yield(); /****************************************************************** Randomize order of training patterns ******************************************************************/ for ( p = 0 ; p < PatternCount ; p++) { q = random(PatternCount); r = RandomizedIndex[p] ; RandomizedIndex[p] = RandomizedIndex[q] ; RandomizedIndex[q] = r ; } Error = 0.0 ; /****************************************************************** Cycle through each training pattern in the randomized order ******************************************************************/ for ( q = 0 ; q < PatternCount ; q++ ) { p = RandomizedIndex[q]; /****************************************************************** Compute hidden layer activations ******************************************************************/ for ( i = 0 ; i < HiddenNodes ; i++ ) { Accum = HiddenWeights[InputNodes][i] ; for ( j = 0 ; j < InputNodes ; j++ ) { Accum += Input[p][j] * HiddenWeights[j][i] ; } Hidden[i] = 1.0 / (1.0 + exp(-Accum)) ; } /****************************************************************** Compute output layer activations and calculate errors ******************************************************************/ for ( i = 0 ; i < OutputNodes ; i++ ) { Accum = OutputWeights[HiddenNodes][i] ; for ( j = 0 ; j < HiddenNodes ; j++ ) { Accum += Hidden[j] * OutputWeights[j][i] ; } Output[i] = 1.0 / (1.0 + exp(-Accum)) ; OutputDelta[i] = (Target[p][i] - Output[i]) * Output[i] * (1.0 - Output[i]) ; Error += 0.5 * (Target[p][i] - Output[i]) * (Target[p][i] - Output[i]) ; } /****************************************************************** Backpropagate errors to hidden layer ******************************************************************/ for ( i = 0 ; i < HiddenNodes ; i++ ) { Accum = 0.0 ; for ( j = 0 ; j < OutputNodes ; j++ ) { Accum += OutputWeights[i][j] * OutputDelta[j] ; } HiddenDelta[i] = Accum * Hidden[i] * (1.0 - Hidden[i]) ; } /****************************************************************** Update Inner-->Hidden Weights ******************************************************************/ for ( i = 0 ; i < HiddenNodes ; i++ ) { ChangeHiddenWeights[InputNodes][i] = LearningRate * HiddenDelta[i] + Momentum * ChangeHiddenWeights[InputNodes][i] ; HiddenWeights[InputNodes][i] += ChangeHiddenWeights[InputNodes][i] ; for ( j = 0 ; j < InputNodes ; j++ ) { ChangeHiddenWeights[j][i] = LearningRate * Input[p][j] * HiddenDelta[i] + Momentum * ChangeHiddenWeights[j][i]; HiddenWeights[j][i] += ChangeHiddenWeights[j][i] ; } } /****************************************************************** Update Hidden-->Output Weights ******************************************************************/ for ( i = 0 ; i < OutputNodes ; i ++ ) { ChangeOutputWeights[HiddenNodes][i] = LearningRate * OutputDelta[i] + Momentum * ChangeOutputWeights[HiddenNodes][i] ; OutputWeights[HiddenNodes][i] += ChangeOutputWeights[HiddenNodes][i] ; for ( j = 0 ; j < HiddenNodes ; j++ ) { ChangeOutputWeights[j][i] = LearningRate * Hidden[j] * OutputDelta[i] + Momentum * ChangeOutputWeights[j][i] ; OutputWeights[j][i] += ChangeOutputWeights[j][i] ; } } } /****************************************************************** Every 1000 cycles send data to terminal for display ******************************************************************/ ReportEvery1000 = ReportEvery1000 - 1; if (ReportEvery1000 == 0) { Serial.println(); Serial.println(); Serial.print ("TrainingCycle: "); Serial.print (TrainingCycle); Serial.print (" Error = "); Serial.println (Error, 5); toTerminal(); if (TrainingCycle == 1) { ReportEvery1000 = 999; } else { ReportEvery1000 = 1000; } } /****************************************************************** If error rate is less than pre-determined threshold then end ******************************************************************/ if ( Error < Success ) break ; } Serial.println (); Serial.println(); Serial.print ("TrainingCycle: "); Serial.print (TrainingCycle); Serial.print (" Error = "); Serial.println (Error, 5); toTerminal(); Serial.println (); Serial.println (); Serial.println ("Training Set Solved! "); Serial.println ("--------"); Serial.println (); Serial.println (); ReportEvery1000 = 1; while (1) { yield(); } } void toTerminal() { for ( p = 0 ; p < PatternCount ; p++ ) { Serial.println(); Serial.print (" Training Pattern: "); Serial.println (p); Serial.print (" Input "); for ( i = 0 ; i < InputNodes ; i++ ) { Serial.print (Input[p][i], DEC); Serial.print (" "); } Serial.print (" Target "); for ( i = 0 ; i < OutputNodes ; i++ ) { Serial.print (Target[p][i], DEC); Serial.print (" "); } /****************************************************************** Compute hidden layer activations ******************************************************************/ for ( i = 0 ; i < HiddenNodes ; i++ ) { Accum = HiddenWeights[InputNodes][i] ; for ( j = 0 ; j < InputNodes ; j++ ) { Accum += Input[p][j] * HiddenWeights[j][i] ; } Hidden[i] = 1.0 / (1.0 + exp(-Accum)) ; } /****************************************************************** Compute output layer activations and calculate errors ******************************************************************/ for ( i = 0 ; i < OutputNodes ; i++ ) { Accum = OutputWeights[HiddenNodes][i] ; for ( j = 0 ; j < HiddenNodes ; j++ ) { Accum += Hidden[j] * OutputWeights[j][i] ; } Output[i] = 1.0 / (1.0 + exp(-Accum)) ; } Serial.print (" Output "); for ( i = 0 ; i < OutputNodes ; i++ ) { Serial.print (Output[i], 5); Serial.print (" "); } } }
ich weiss es nicht wo es für einen "nur" user sinn macht welche daten und parameter als freie (mit einer empfehlung versehen vielleicht) eingabe zu schalten und welche nicht. So eine möglichkeit wäre eine super hilfe für das verständnis der KI und NN. Auch ohne ein detailiertes wissen um die innereien. Wie beim auto eben...Code:#include <math.h> /****************************************************************** Network Configuration - customized per network ******************************************************************/ float LearningRate = 0.3; int Momentum = 0.9; int InitialWeightMax = 0.5; int Success = 0.0004; int InputNodes; // = 2; int HiddenNodes; // = 2; int OutputNodes; // = 2; int PatternCount; // = 4; //zu trainierende Muster void setup() { Serial.begin(9600); } void loop() { input_NN(); } int intInput() { char str[10]; int charcount = 0; memset(str, 0, sizeof(str)); // String-Puffer löschen while (!Serial.available()); // Warten bis 1. Zeichen im Eingangspuffer delay(100); // Warten auf weitere Zeichen im Eigangspuffer while (Serial.available() && charcount < 9) { str[charcount] = Serial.read(); // Zeichen aus Eingangspuffer lesen charcount++; } return atoi(str); // String in Integer-Rückgabewert wandeln } void input_NN (void) { /* Serial.print("Geben Sie > LearningRate < (standard = 0.3)ein: "); LearningRate = intInput(); Serial.println(LearningRate); Serial.print("Geben Sie > Momentum < (standard = 0.9)ein: "); Momentum = intInput(); Serial.println(Momentum); Serial.print("Geben Sie > InitialWeightMax < (standard = 0.5)ein: "); InitialWeightMax = intInput(); Serial.println(InitialWeightMax); Serial.print("Geben Sie > Success < (standard = 0.0004)ein: "); Success = intInput(); Serial.println(Success); */ Serial.print("Geben Sie > InputNodes < (standard = 2)ein: "); InputNodes = intInput(); Serial.println(InputNodes); Serial.print("Geben Sie > HiddenNodes < (standard = 2)ein: "); HiddenNodes = intInput(); Serial.println(HiddenNodes); Serial.print("Geben Sie > OutputNodes < (standard = 2)ein: "); OutputNodes = intInput(); Serial.println(OutputNodes); Serial.print("Geben Sie > PatternCount < (standard = 4)ein: "); PatternCount = intInput(); Serial.println(PatternCount); Serial.println(); }
Lesezeichen