Neuronales Netz bringt nur Mist
-
also ich hab mir ne Klasse für nen neuronales Netz gebastelt - eigentlich sollte sie funktionieren.. (habs mal gaaanz unsauber in der .h)
#include <stdio.h> #include <stdlib.h> #include <string.h> #undef RAND_MAX #define RAND_MAX 255 class cNN { private : char *Matrix , *NeuronOut , *NeuronIn , Act ; int cntNeurons , cntInputs , cntOutputs ; int Flag; public : cNN (int cntN, int cntI, int cntO, int Fl); ~cNN (); int Flags (int Flag); int load (char *File); int save (char *File); int init (void); int get (char *In, char *Out); int learn (char *In, char *Out); }; cNN::cNN (int cntN, int cntI, int cntO, int Fl) { /* Daten übernehmen, Speicher allokieren */ cntNeurons = cntN; cntInputs = cntI; cntOutputs = cntO; Flags (Fl); Act = 50; Matrix = new char [cntN * cntN]; NeuronOut = new char [cntN]; NeuronIn = new char [cntN]; } cNN::~cNN () { delete[] Matrix; delete[] NeuronOut; delete[] NeuronIn; } int cNN::Flags (int Fl) { if (Fl == 0) { return Flag; } else { Flag = Fl; } } int cNN::load (char *File) { FILE *F; delete[] Matrix; F = fopen(File, "rb"); if (F == NULL) { return -1; } fread(&cntNeurons, sizeof(int), 1, F); fread(&cntInputs , sizeof(int), 1, F); fread(&cntOutputs, sizeof(int), 1, F); Matrix = new char [cntNeurons * cntNeurons]; fread(Matrix , sizeof(char), cntNeurons * cntNeurons, F); fclose(F); return 0; } int cNN::save (char *File) { FILE *F; F = fopen(File, "wb"); if (F == NULL) { return -1; } fwrite(&cntNeurons, sizeof(int), 1, F); fwrite(&cntInputs , sizeof(int), 1, F); fwrite(&cntOutputs, sizeof(int), 1, F); fwrite(Matrix , sizeof(char), cntNeurons * cntNeurons, F); fclose(F); return 0; } int cNN::init (void) { int i; for (i = 0; i < (cntNeurons * cntNeurons); i++) { Matrix[i] = (char) rand(); } } int cNN::get (char *In, char *Out) { int i, a, c; char *ptOut = &NeuronOut[cntNeurons-cntOutputs]; memcpy (NeuronOut, In, sizeof(char) * cntNeurons); memcpy (NeuronIn, NeuronOut, sizeof(char) * cntNeurons); for (i = cntInputs; i < cntNeurons; i++) { c = 0; for (a = 0; a < cntNeurons; a++) { /* Ausgang berechnen */ c += Matrix[i * cntNeurons + a] * NeuronOut[a]; } if (c > 50) { NeuronOut[i] = c - 50; } else { NeuronOut[i] = 0; } } memcpy (NeuronOut, ptOut, sizeof(char) * cntOutputs); return 0; } int cNN::learn (char *In, char *Out) { int i , d = cntNeurons - cntOutputs , pren ; char myOut[cntNeurons]; get(In, myOut); /* lernen und so ... * * vergleichen von myOut mit Out und * * entsprechendes Abändern der * * Eingangswerte */ for (i = d; i < cntNeurons; i++) { for (pren = 0; pren < cntNeurons; pren++) { Matrix[i * cntNeurons + pren] += (myOut[i] - Out[i])/5; myOut[pren] = Out[pren] * Matrix[i * cntNeurons + pren]; } } }
Leider produziert mein Testprogramm nur Mist - ergo hab ich da irgendwo nen Programmierfehler drin nur find ich ihn nicht.
#include <stdlib.h> #include <stdio.h> #include "cnn.h" int main (int argc, char **argv) { int i; char a[2] ,c[1]; cNN *myKNN = new cNN(5,2,1,0); myKNN->init(); myKNN->save("c:\\test.knn"); #define MAX_RAND 10; for (i = 0; i < 130; i++) { a[0] = char(rand()); a[1] = char(rand()); c[0] = a[0] + a[1]; printf ("a :%i, b :%i, c:%i\n", a[0], a[1], c[0] ); myKNN->learn(a, c); } myKNN->save("c:\\test.knn"); printf("A eingeben:"); scanf ("%d", &a[0]); printf("B eingeben:"); scanf ("%d", &a[1]); myKNN->get(a, c); printf ("Ergebnis : %i\n", c[0]); delete myKNN; system("PAUSE"); }
Ich hoffe, ihr seht mehr als ich
p.s.: Den Stil bitte erst nach der Fehlerfindung bemängeln..
-
ich glaub kaum, dass sich jemand diesen unübersichtlichen code ohne genauen hinweis, wo der fehler stecken könnte anschaut. (ich jedenfalls nicht)
-
Also ich denke, dass die Fehlerkorrektur Mist ist..
int cNN::learn (char *In, char *Out) { int i , d = cntNeurons - cntOutputs , pren ; char myOut[cntNeurons]; get(In, myOut); /* lernen und so ... * * vergleichen von myOut mit Out und * * entsprechendes Abändern der * * Eingangswerte */ printf ("ist : %i ___ soll : %i\n", myOut[0], Out[0]); for (i = d; i < cntNeurons; i++) { for (pren = 0; pren < cntNeurons; pren++) { Matrix[i * cntNeurons + pren] += (myOut[i] - Out[i])/5; myOut[pren] = Out[pren] * Matrix[i * cntNeurons + pren]; } } }
So nebenbei : was ist unübersichtlich am Code? (von den fehlenden Kommentaren mal abgesehn)
-
Ische schrieb:
So nebenbei : was ist unübersichtlich am Code? (von den fehlenden Kommentaren mal abgesehn)
deine tabweite ist manchmal 4, manchmal 2.
du machst bei auflistungen das komma in die neue zeile und dahinter das statement (das muss genau andersrum, bei einem aufsatz machst du das komma doch auch nicht in eine neue zeile..).
zwischen funktionsnamen und der offenen klammer sind leerstellen, dadurch wirds nur unübersichtlich. genauso wenn du ganz viele leerstellen lässt und dann erst ein komma setzt damit das komma auf gleicher höhe mit dem dadrüber ist. (das gleiche bei gleichheitszeichen).es scheint einfach ein bisschen übertrieben formatiert und dadurch unübersichtlich zu sein.
ob da nen logischer fehler in der methode "learn" ist kann ich dir nicht sagen, du solltest evtl erst erklären was die funktion genau leisten soll.
-
nächster punkt: ohne das hier irgendjemand weis, was das neuronale netz überhaupt tun soll, wird man hier eh nichts finden...
-
@borg: das meiste, was du bemängelst, ist Stilfrage. Sicher nicht dein Stil (und auch nicht meiner), aber konsistent genug um "abgesegnet" zu werden.
@ische: an dem Komma vorn wird jeder aufstoßen. gewöhn' dir das am besten wieder ab
Ansonsten hast du auf dem "untersten level" (formatierung) schon 'ne gute ordnung drin. Immer schön konsistent und für eins entscheiden, dann wird das schon.
Auf der nächsten ebene - Bezeichner bezeichner bezeichner - sieht es ganz traurig aus.
cNN::cNN (int cntN, int cntI, int cntO, int Fl)
Würde da ruchmed hrach al akhbar stehen, wäre es auch nicht verständlicher.
Aussagekräftige namen. z.B.
cNeuralNet::cNeuralNet(int neuronsTotal, int neuronsIn, int neuronsOut, int fragMich)
Der Mehraufwand beim tippen lohnt sich auf alle Fälle, wen irgendwann mal jemand deinen Code lesen muß. ("Jemand anderes" magst Du in einem halben Jahr sein...)
Der nächste Schritt wären "VErtragskommentare": was repräsentiert die Klasse cNN, was tut der Konstruktor, welche Bedeutung haben einzelne parameter, welche Werte sind gültig usw.
Und dann... in-code-Kommentare, die deine "Absicht" darlegen (wozu sind die nächsten 12 Zeilen gut?)
Zu deiner eigentlichen Frage: Ic hweiß über Neuronale Netze soviel wie über Ärzte (daß sie defekte menschen reparieren), und "main macht Mist" ist nun wirklich kein Ansatz. Welche Zweige / Abschnitte kansnt du verifizieren, daß sie's nicht sind? was ist "Mist"? usw...
-
gewöhn dir mal an variablen dann einzuführen, wenn du sie brauchst.
beispiel: for(int pren=0... und nicht irgendwo am beginn.
-
und solche komischen namen wie pren solltest du auch vermeiden!
-
peterchen schrieb:
@borg: das meiste, was du bemängelst, ist Stilfrage. Sicher nicht dein Stil (und auch nicht meiner), aber konsistent genug um "abgesegnet" zu werden.
naja er hat gefragt was unübersichtlich ist
. aber du hast recht, die variablennamen sind natürlich auch unübersichtlich
-
ja, und bis auf das "Komma vorn" kannst DU dich an all das gewöhnen
ist ein kleines bißchen ernst gemeint: Coding Style sollte in erster Linie konsistent sein, dann dem Projekt angepaßt, und erst zum Schluß persönlichen Vorzügen (das ist natürlich alle Wurst, wenn man für sich allein codet...)
@Ische:
Kannst du das Problem ein wenig eingrenzen? z.B. Stellen finden, an denen irgendwelche Werte falsch sind, und dann zurückverfolgen wieso?
-
Matrix = new char [cntN * cntN]; NeuronOut = new char [cntN]; NeuronIn = new char [cntN];
Der Code ist schon sinnfrei, alle Größen mit cntN zu initialisieren. Obwohl später im Code immer unterschiedliche Größen angegeben werden.
Ich gehe davon aus das der OP ein einstufiges KNN bauen möchte, andernfalls sollte der Code komplett überdacht werden.
Die "KNN" Matrix ist nicht cntN * cntN sondern eine "n x m" oder "m x n" Matrix wobei n die Anzahl der Eingangsneuronen und m die Anzahl der Ausgangsneuronen ist. Meist wird noch eine zusätzliche Spalte, Zeile eingefügt je nach dem wie man das Layout gewählt hat, diese stellt dann einen sog. Bias Wert dar.
Der Lernalgorithmus so wie er da steht sollte überarbeitet werden. Am Ende lässt sich das bei so einem einfachen Netz, auf Vektor - Matrix Multiplikation reduzieren.
bye
tt
-
ookay also das cnt ist einfach ne Abkürzung für Counter - wurde hier nicht neulich von irgendwem sowas vorgeschlagen ??
Wie auch immer.. die Einrückungen mach ich nicht mit dem Tabulator. Ich arbeite teilweise mit Programmen, die mit Tabs nicht klar kommen. Ich werd versuchen, mich daran zu halten.
Also das Trainingsnetz ist so gedacht, dass es mehrstufig arbeiten kann.
Was ich mir eigentlich dabei dachte war das hier
Ich habe jetzt einfach mal probiert, 2 Zahlen miteinander zu addieren. ( 3 und 4 )
Das hab ich 100 mal gelernt, brachte aber nix.Das vom Netz errechnete Ergebnis ist grundsätzlich falsch. Meine get - funkion sieht jetzt so aus :
int cNN::get (char *In, char *Out) { int i, a, c; char *ptOut = &NeuronOut[cntNeurons-cntOutputs]; memcpy (NeuronOut, In, sizeof(char) * cntNeurons); memcpy (NeuronIn, NeuronOut, sizeof(char) * cntNeurons); for (i = cntInputs; i < cntNeurons; i++) { c = 0; for (a = 0; a < cntNeurons; a++) { /* Ausgang berechnen */ c += Matrix[i * cntNeurons + a] * NeuronOut[a]; } NeuronOut[i] = c; } memcpy (Out, ptOut, sizeof(char) * cntOutputs); return 0; }