Neuronale Netze
lima-city → Forum → Sonstiges → Schule, Uni und Ausbildung
anzahl
array
bit
byte
code
datei
ende
guter stil
machen
matrix
methode
netz
neuron
programmieren
schauen
spalte
speichern
speicherplatz
verbindung
zeile
-
Ich bräuchte eure Hilfe.
Ich muss für mein Projejt einen Simulator für neuronale Netze programmieren. Mit der Materie kenn ich mich aus, aber ich bräuchte etwas hilfe dies in C++ aus zu programmieren.
Meine Idee war es eine Klasse mit einen Neuron zu machen und mit einem dynamischen Array von Pointern die verkettung zwischen den neuronen her zu stellen aber ich bräuchte ein paar tipps wie ich diese informationen in eine datei bringe (die funktionen kenne ich, ich suche eine einfache aber geniale art die verkettungsinformation zu speichern.)
Bitte helft mir -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Interessant. Kannst du mir das Endprodukt dann zukommen lassen?
Ich nehme mal an, du möchtest möglichst kompakt speichern.
Also, eine relativ simple Idee wäre, für jedes Neuron eine Zeile zu nehmen(also gar nicht die Neuron-ID speichern, sondern Zeilennummer=NeuronID)
Und in jeder Zeile schreibst du dann die IDs der verbundenen Neuronen.
Der Nachteil dieser Methode ist, dass das löschen eines Neurons mit einem gewissem Aufwand verbunden ist(IDs von Verbindungen müssen decrementiert werden)
Und ich bezweifle, dass du das viel kompakter speichern könntest. Es sei denn, du weißt, wie deine Neuronen in der Regel verbunden sind (Anzahl,Anzahl der Verbindungen). Aber diese Lösung dürfte noch am besten skalieren.
Wenn du die Neuronen dann mit dynamischer Speicherreservierung anlegst, kannst du dann auch per Pointer gezielt bestimmte Neuronen aufrufen (Die Neuronen liegen dann schließlich wie ein Array hintereinander in einem Speicherblock).
So kannst du dann sowohl über Pointer-Berechnungen auf ein Neuron mit einer bestimmten ID zugreifen, als auch über die neuronalen Verbindungen.
Und die Zeilen liest du dann einfach per getline() aus und castest die Werte nach int. Eventuell geht das auch eleganter mit fscanf(), so dass du nicht explizit casten musst. Aber ich weiß jetzt nicht genau wie.
Ich hoffe, das löst dein Problem.
mfg, bladehunter
Beitrag geändert: 11.12.2007 16:42:44 von bladehunter -
Wenn ejdes Neuron mit jedem Verkettet ist... nunja. Speichere jede NeuronenID und lasse sie speichern.
Dann leist du sie wieder Zeile für Zeile in ein Array und lässt sie per Permutationsalgorythmus druchgehen. Und verkettest bei jedem Durchlauf die nächsten Neuronen. Das dürfte gehen. Ist aber etwas..umständlich gelöst. WOllte nurmal die alternativen darlegen. *zwinker* -
Andere Idee:
Du nimmst zum speichern der IDs ein unsigned char, so dass du Zahlen von 0-255 darstellen kannst.
In der entsprechenden Datei speichers du dann die verbundenen Neurone als Binärzahlen.
So dass 1 Byte=1 Verbindung entspricht.
Und so liest du dann Byte für Byte z.B. mit fgetc() aus, bis du auf die 255 stößt. Die 255 bedeutet dann, dass jetzt die Verbindungen für das nächste Neuron kommen. Und ich schätze mal, mehr als 255 Neuronen werdet ihr nicht simulieren, oder?
Jedenfalls musst du dann einen Zähler/Pointer mitlaufen lassen, der bei jeder 255 erhöht wird, so dass du weißt, welches Neuron du gerade mit Verbindungen ausstattest. -
Die Idee von bladehunter gefällt mir ganz gut ich werd mich mal in mein kämmerchen verziehen und ein bisschen programmieren.
-
Ich habe gerade nochmal über meine 2. Variante nachgedacht.
Auf den meisten Systemen steht die -1 (minus 1) für das Ende einer Datei. Also kann man die -1 nicht nehmen.
Dafür hätte ich folgende Lösungsidee:
-1 im 2er-Komplement ist: 11111111
wenn man jetzt per fgetc() eine -1 liest, muss man natürlich das auslesen der Datei beenden.
Um jetzt bei -1 keinen Hüpfer zu haben, könnte man das folgendermaßen lösen:
//ungetesteter Code!
char verbindung;
while(verbindung=fgetc(datei_handle)!=EOF)
{
char * zeiger=&verbindung;
unsigned char * zeiger2=cast_funktion_oder_so ;
//... *zeiger als Verbindung eintragen
}
Das ganze kann man vllt noch eleganter lösen. Wichtig ist hier erstmal, dass wir ein signed char (über 2er-Komplement kodiert) in ein unsigned char umwandeln (normale Binärschreibweise).
Edit: Es ändern sich also nicht die Bits, sondern nur die Interpretation dieser Bits.
Und weil -1 umgewandelt in einen unsigned char gleich 255 ist, können wir 255 nicht mehr als Listengrenze benutzen, sondern müssen dann 254 als Markierung dafür nutzen, dass jetzt die Verbindungen zum nächsten Neuron kommen.
Beitrag geändert: 12.12.2007 15:29:24 von bladehunter -
Es gibt im Internet ja schon einige Neuronale Netze simulationen (Opensource) warum das Rad neu erfinden?
-
htlstp schrieb:
Es gibt im Internet ja schon einige Neuronale Netze simulationen (Opensource) warum das Rad neu erfinden?
Vielleicht weil es noch ehrliche Menschen gibt die nicht spicken wollen und auch was lernen wollen!
Hätte man das rad nicht oft neu erfuden gäb es heutzutage keine reifen
(der satz gefällt mir!)
Wie ich solche Post hasse, und ich hasse es noch mehr das ich darauf poste, naja egal -
Ich kenne mich nicht mit C aus, aber mit fgetc( ) != EOF zu arbeiten, wenn man eigentlich eine Binärdatei hat ist bestimmt kein guter Stil ;) warum nicht andere Möglichkeiten nutzen um zu schauen ob man das Ende der Datei erreicht hat (feof)?
Wenn man nur 256 Neurone hat, dann würde man selbst wenn man die Verknüpfungen mit einer Adjazenzmatrix speichert weniger als 2 KByte belegen.
Also man speichert ein \"zweidimensionales\" binäres Array der Größe 256 x 256. Wenn in der i-ten Zeile und j-ten Spalte eine 1 steht sind die Neurone i und j miteinander verbunden.
Der Nachteil ist, dass man 256 Schritte braucht um das für ein Neuron auszulesen und dass man einen hohen Speicherverbrauch (2 KB ) hat, dafür ist die Lösung unendlich einfach.
Man kann den Speicherbedarf noch halbieren, wenn man nur die obere Hälfte der Matrix nimmt: Wenn z. B. Neuron 4 und 7 miteinander verbunden sind, steht in der 4. Zeile und 7. Spalte eine 1 genauso wie in der 7. Zeile und 4. Spalte, was überflüssige Information ist.
-
Ich kenne mich nicht mit C aus, aber mit fgetc( ) != EOF zu arbeiten, wenn man eigentlich eine Binärdatei hat ist bestimmt kein guter Stil
Öhm. Warum sollte das kein guter Stil sein? C ist nunmal Lowlevel und EOF ist in der Regel ein Makro für -1, welches wiederum häufig das Symbol für das Ende einer Datei ist. Außerdem kennt Linux nur Binärdateien.
Und -1 ist schließlich ein sinnvoller Wert, wenn du Textdateien hast, die alle ASCII Werte >= 0 haben. Außerdem ist -1 im 2er Komplement 11111111 .
warum nicht andere Möglichkeiten nutzen um zu schauen ob man das Ende der Datei erreicht hat (feof)?
Ich bin mir nicht 100%ig sicher, aber ich wage zu behaupten, dass feof() nix anderes macht, als zu überprüfen ob das aktuelle Zeichen im Stream eine -1 ist. Bei Strings in C muss man schließlich auch aufpassen, dass man nicht die Grenzen (die mit der 0 markiert sind) überschreitet.
Wenn man nur 256 Neurone hat, dann würde man selbst wenn man die Verknüpfungen mit einer Adjazenzmatrix speichert weniger als 2 KByte belegen.
Meine Methode hat einen Speicherverbrauch von O(n²).
Aber dein Speicherverbrauch ist THETA(n²).
Im Worst Case mögen wir beide gleich schlecht sein, aber je weniger komplexer das Netzwerk ist, desto besser wird meine Variante gegenüber deiner.
Also man speichert ein \"zweidimensionales\" binäres Array der Größe 256 x 256. Wenn in der i-ten Zeile und j-ten Spalte eine 1 steht sind die Neurone i und j miteinander verbunden.
Ich halte trotzdem eine Adjazenzliste für günstiger, als eine Adjazenzmatrix. Außerdem sollen die Verbindungen der Neurone untereinander als Objekteigenschaft - und nicht als Matrix- gespeichert werden.
Der Nachteil ist, dass man 256 Schritte braucht um das für ein Neuron auszulesen und dass man einen hohen Speicherverbrauch (2 KB ) hat, dafür ist die Lösung unendlich einfach.
Ich wüsste nicht, was am Auslesen einer Adjazenzliste so schwer sein sollte.
Und wie schon oben erwähnt, hast du durch die Matrix THETA(n²) Speicherverbrauch und Speicherzugriffe, während meine Variante O(n²) Speicherverbrauch hat.
Man kann den Speicherbedarf noch halbieren, wenn man nur die obere Hälfte der Matrix nimmt: Wenn z. B. Neuron 4 und 7 miteinander verbunden sind, steht in der 4. Zeile und 7. Spalte eine 1 genauso wie in der 7. Zeile und 4. Spalte, was überflüssige Information ist.
Neuronale Verbindungen entsprechen einem gerichtetem Graph. Es gibt daher keine gespiegelte Hälfte. -
Öhm. Warum sollte das kein guter Stil sein? C ist nunmal Lowlevel und EOF ist in der Regel ein Makro für -1, welches wiederum häufig das Symbol für das Ende einer Datei ist. Außerdem kennt Linux nur Binärdateien.
Ja aber es heißt doch aber nicht umsonst get char und nicht get byte.
Und -1 ist schließlich ein sinnvoller Wert, wenn du Textdateien hast, die alle ASCII Werte >= 0 haben. Außerdem ist -1 im 2er Komplement 11111111 .Ich bin mir nicht 100%ig sicher, aber ich wage zu behaupten, dass feof() nix anderes macht, als zu überprüfen ob das aktuelle Zeichen im Stream eine -1 ist. Bei Strings in C muss man schließlich auch aufpassen, dass man nicht die Grenzen (die mit der 0 markiert sind) überschreitet.
Wenn das wirklich so ist, wie schaffen es Leute einen Hexeditor in C zu programmieren? Der müsste ja immer abbrechen beim Einlesen der Datei, wenn er zufällig auf ein FF stößt.Meine Methode hat einen Speicherverbrauch von O(n²).
Also mal ein Beispiel, du hast ein Netz wo jedes Neuron mit dem anderen verbunden ist, da braucht deine Lösung acht mal so viel Speicherplatz wie meine, denn ich brauch nur 1 Bit um eine Verbindung zu speichern, du brauchst ein Byte.
Aber dein Speicherverbrauch ist THETA(n²).
Im Worst Case mögen wir beide gleich schlecht sein, aber je weniger komplexer das Netzwerk ist, desto besser wird meine Variante gegenüber deiner.
-
cga schrieb:
Ja aber es heißt doch aber nicht umsonst get char und nicht get byte.
Es gibt aber keinen Datentyp byte in C/C++. Und der Datentyp char ist auf den meisten Architekturen 1 Byte groß. Und ich denke mal, deswegen heißt es auch getc().
Ich bin mir nicht 100%ig sicher, aber ich wage zu behaupten, dass feof() nix anderes macht, als zu überprüfen ob das aktuelle Zeichen im Stream eine -1 ist. Bei Strings in C muss man schließlich auch aufpassen, dass man nicht die Grenzen (die mit der 0 markiert sind) überschreitet.
Wenn das wirklich so ist, wie schaffen es Leute einen Hexeditor in C zu programmieren? Der müsste ja immer abbrechen beim Einlesen der Datei, wenn er zufällig auf ein FF stößt.
Stimmt. Guter Einwand.
Meine Methode hat einen Speicherverbrauch von O(n²).
Also mal ein Beispiel, du hast ein Netz wo jedes Neuron mit dem anderen verbunden ist, da braucht deine Lösung acht mal so viel Speicherplatz wie meine, denn ich brauch nur 1 Bit um eine Verbindung zu speichern, du brauchst ein Byte.
Aber dein Speicherverbrauch ist THETA(n²).
Im Worst Case mögen wir beide gleich schlecht sein, aber je weniger komplexer das Netzwerk ist, desto besser wird meine Variante gegenüber deiner.
OK. Sobald die Summe der Anzahl der Neuronen und der Verbindungen mehr als 1024 sind, verbrauchst du weniger Speicherplatz als ich. Aber um zu schauen, welche neuronalen Verbindungen für ein einzelnes Neuron bestehen, brauchst du konstant 32 Speicherzugriffe. Das ist schon ein bißchen viel. -
ich hab das jetzt ausprobiert mit feof() und es funktioniert!! ich hab mir eine Binärdatei in.bin gebastelt, bei der mitten in der Datei ein FF vorkommt.
Das hier kopiert die Datei NICHT vollständig, sondern bricht vor dem FF ab:
#include <stdio.h> int main() { FILE *fsrc, *fdest; char c; fsrc = fopen(\"c:\\\\in.bin\",\"r+b\"); fdest = fopen(\"c:\\\\out.bin\",\"w+b\"); while((c=fgetc(fsrc))!=EOF) fputc(c,fdest); fclose(fdest); fclose(fsrc); return 0; }
während dieser Code hier die gesamte Datei nach out.bin kopiert:
#include <stdio.h> int main() { FILE *fsrc, *fdest; char c; fsrc = fopen(\"c:\\\\in.bin\",\"r+b\"); fdest = fopen(\"c:\\\\out.bin\",\"w+b\"); while(!feof(fsrc)) fputc(fgetc(fsrc), fdest); fclose(fdest); fclose(fsrc); return 0; }
OK. Sobald die Summe der Anzahl der Neuronen und der Verbindungen mehr als 1024 sind, verbrauchst du weniger Speicherplatz als ich. Aber um zu schauen, welche neuronalen Verbindungen für ein einzelnes Neuron bestehen, brauchst du konstant 32 Speicherzugriffe. Das ist schon ein bißchen viel.
Aber hier gehts ja nur ums Format in dem gespeichert werden soll, man hat ja nur einmal die Speicherzugriffe beim parsen.
Parser sind meistens schwer zu programmieren aber mit der Adjazenzmatrix macht man es sich relativ einfach.
Die Datenstruktur mit der das Programm dann arbeitet muss natürlich eine Adjazenzliste sein, allein schon weil die Algorithmen für eine Adjazenzmatrix schwer zu programmieren sind.
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage