verbesserungsvorschläge für endlich fertig gestellte klasse
- 
					
					
					
					
 danke ich werde deine ratschläge bis morgen umsetzen und dann die klasse/n posten. 
 nur eins noch, ich weiß mit der ausgabefunktion nicht so recht viel anzufangen
 wie müsste das hier richtig aussehen : :void matrix<T>::print_at(std::ostream& ausgabe); { //if(spalten_matr < 1) for(unsigned int i = 0; i < zeilen_matr; i++) (std::cout.ausgabe<<("Position ")).ausgabe<<(i); (std::cout.ausgabe<<(": ").ausgabe<<(matrix_eindim[i]); (std::cout.ausgabe<<(std::endl) ); /* else { for(unsigned int i = 0; i < zeilen_matr; i++) { cout<<endl; for(unsigned int j = 0; j < spalten_matr; j++) cout<< "Position " << i << ": " << matrix_zweidim[i][j]; } } */ return ausgabe; }
 
- 
					
					
					
					
 strings schrieb: print_at(ostream& out); warum kein operator<<? ach, den hab ich doch glatt vergessen. ostream& operator<<(ostream& out,Matrix const& m){ return m.printAt(out); }und weil ich irgendwo sowas wie template<typename T> ostream& operator<<(ostream& out,T const& t){ return t.printAt(out); }stehen habe, reicht's bei mir immer, nur eine printAt anzubieten, wenn ich eine klasse ausgebbar machen mag. 
 
- 
					
					
					
					
 warum denn dann 2 methoden für die ausgabe?? 
 
- 
					
					
					
					
 strings schrieb: warum denn dann 2 methoden für die ausgabe?? die printAt()-Methode brauchst du wenn du ein objekt polymorph ausgeben willst, virtual funktioniert leider bei normalen Funktionsaufrufen nicht. der template-wrapper ist ne gute idee  
 
- 
					
					
					
					
 Volkard du hast ja echt VIEL Zeit  Und bitte_bitte_bitte verwende doch Englisch im Code wirkt viel professioneller und ist mit der Zeit besser und auch von allen in der gesamten Welt besser zu lesen. Und bitte_bitte_bitte verwende doch Englisch im Code wirkt viel professioneller und ist mit der Zeit besser und auch von allen in der gesamten Welt besser zu lesen.
 
- 
					
					
					
					
 T *matrix_eindim; T **matrix_zweidim;Und warum machst du in einer Matrixklasse ein und zweidimensionale Matrizen. Normalerweise hast du eine Klasse Matrix2d Matrix3d Matrix4d... Was ist auch bitte eine 1dimensionale Matrix? kannst ja gleich nen float nehmen? 
 
- 
					
					
					
					
 dali schrieb: Was ist auch bitte eine 1dimensionale Matrix? kannst ja gleich nen float nehmen? nee. ein float ist 0d. 
 
- 
					
					
					
					
 [quote="dali"]Volkard du hast ja echt VIEL Zeit ;)[quote] 
 ich habe VIEL zu wenig zeit.Und bitte_bitte_bitte verwende doch Englisch im Code das mache ich manchmal. mit welchem code haste im moment ein problem? wirkt viel professioneller ich lege nicht extrem viel wert darauf, durch irgendwas professioneller zu wirken, als ich bin. besonders im code nicht. den mache ich so gut und so lesbar unter nichtvernachlässigung von ein wenig erweiterbarkeit und performance, wie ich kann. im allgemeinen mache ich projektübergreifend wiederverwendbares auf englisch und domain-spezifisches auf deutsch. das ergibt auch eine schöne und augenfällige schichtentrenung. einfach köstlich. und ist mit der Zeit besser und auch von allen in der gesamten Welt besser zu lesen. da ich eh keine kommentare mache, ist das problem schon fast aus der welt. *g* 
 
- 
					
					
					
					
 Das mit dem Englisch war eigentlich auf exigoner bezogen. Ist sicher Geschmackssache was man verwendet aber Englisch und Deutsch mixen find ich nicht gut... Und Code ohne Kommentare naja... Mir hat man immer Punkte bei den Übungen abgezogen  
 
- 
					
					
					
					
 So noch ein bisschen (?) Matrixdesign. Was willst Du eigentlich mit der Matrix machen? Ich kenne Matrizen in erster Linie aus der diskreten Mathematik oder Numerik. Für einen Datentyp Matrix (der in dem o.g. Kontext eingesetzt werden soll) bietet sich an: 1.) Betreibe zuerst Matrixdesign Das Wichtigste. Überlege Dir zuerst ganz genau, was die Matrix können soll und "make the common case fast". 2.) Implementiere nur den Datentyp Matrix. Es gibt keine "eindimensionale" oder "zweidimensionale" Matrix, in dem Sinne wie es hier verwendet wird. Eine Matrix besteht immer (!) aus Zeilen und Spalten. 
 Und deswegen gibt es nur "zweidimensionale" Matrizen.
 Bsp:
 [1 0] ist eine (1x2)-Matrix
 [1 0; ist eine (2x2)-Matrix
 [0 1]
 [1] ist eine (1x1)-MatrixDie Dimension einer Matrix ist übrigens die Anzahl der linear unabhängigen Zeilen bzw. Spalten. 3.) Repräsentiere den Inhalt der Matrix als doppelt verkettete Liste. Das mag vielleicht auf den ersten Blick wie Speicherverschwendung aussehen, ist aber tatsächlich, was übliche Matrixoperationen angeht, wesentlich effizienter. Du kannst Dir ja als Übung überlegen, warum. Hier nur ein paar Hinweise: 
 - Hinzufügen von Zeilen/Spalten wird einfacher
 - Löschen von Zeilen/Spalten wird einfacher
 - Tauschen von Zeilen/Spalten wird einfacher
 - Transponieren wird einfacher
 - Matrix-Matrix Multiplikation wird einfacher
 - Gaussalgorithmus wird einfacher
 - Konsistenes Prüfen auf NULL-Zeiger4.) Wähle eine einfach Schnittstelle Neben Kontruktor/Destruktor muss die Matrix eigentlich nur +, -, * (und /) sowie Zeilen/Spalten Manipulationen beherrschen. Weitere Elementfunktionen würde ich nur aufnehmen wenn Du sie wirklich häufig brauchst, ansonsten auslagern. 5.) Programmiere einfach und effizient Auch sehr wichtig. Ständiges Hin- und Herkopieren von irgendwelchen Werten ist ziemlich laaaaaaaangsam (stattdessen ein paar Zeiger verbiegen). Ebenso ständiges new und delete (lieber Puffer und Speicherpools verwenden). Überprüfe immer wieder, ob es nicht auch einfacher geht. So genug Lehrmeisterei. Das hat vielleicht sogar ein bisschen zu weit geführt, sollte Dir aber auch zeigen, dass selbst so etwas einfach Erscheinendes wie eine Matrix verdammt schwer zu implementieren ist. Aber es reicht ja schon, wenn Du einfach ein paar Ideen bekommen hast, wie Du Deine Matrixklasse verbessern 
 kannst.Wenn jemand Spass daran hat und ein wenig Langeweile, kann sie/er ja mal versuchen eine effiziente Matrixklasse zu implementieren, die die üblichen Operationen darauf unterstützt und dann zum Beispiel an Bitmaps austesten. 
 Schonmal versucht, alle Eigenvektoren einer Bitmap zu bestimmen? Oder gar zu invertieren?Gruss turing 
 
- 
					
					
					
					
 die ganzen ratschläge lassen sich ja gut umsetzen, aber ich verstehe die ausgabefunktion einfach nicht. 
 packe ich das in meine klassestd::ostream& operator<<(std::ostream& out, matrix const& m) return m.printAt(out);beomme ich fehler 
 
- 
					
					
					
					
 Turing schrieb: 3.) Repräsentiere den Inhalt der Matrix als doppelt verkettete Liste. Das mag vielleicht auf den ersten Blick wie Speicherverschwendung aussehen, ist aber tatsächlich, was übliche Matrixoperationen angeht, wesentlich effizienter. Du kannst Dir ja als Übung überlegen, warum. Hier nur ein paar Hinweise: 
 [...]
 - Matrix-Matrix Multiplikation wird einfacher
 - Gaussalgorithmus wird einfacherBegründung? Was dagegen spricht: 
 - Speicherverbrauch wird bei dichtbesetzten Matrizen viel höher
 - Index-Zugriffe werden langsamerNene, verkettet bitte nur bei großen dünnbesetzten Matrizen. Im Idealfall hat man mehrere Matrixklassen in der Schublade aus denen man je nach Anwendungsfall wählen kann: 
 - Eine dynamische wenn die Dimensionen erst zur Laufzeit bekannt sind.
 - Eine generische, wenn die Dimensionen zur Compilezeit feststehen.
 - Mehrere für dünnbesetzte Matrizen die verkettet, mit einer Hashtable oder ganz anders implementiert sind, je nach Aufbau der Matrix.
 - ...
 
- 
					
					
					
					
 ich werd erstmal keine verketteten listen benutzen um ne basisklasse zu schreiben, vielleicht später zum ausprobieren, aber niccht jetzt. 
 
- 
					
					
					
					
 so was haltet ihr davon?, abgesehen von der ausgabe  #ifndef MATRIX_KLASSE #define MATRIX_KLASSE #include <iostream> #include <cstdlib> template <class T> class matrix { private: T **matrix_zweidim; unsigned int zeilen_array; unsigned int spalten_array; unsigned int index_z; unsigned int index_s; public: matrix(unsigned int z, unsigned int s); //zwei dimemsionen ~matrix(); T *get_matrix(); void ausgabe_array(); void push_pos(T *feld, unsigned int zeilen_array, unsigned int spalten_array, int pos_z, int pos_s); //für zweidim matrix }; //############################################################################## template <class T> inline matrix<T>::matrix(unsigned int zeilen, unsigned int spalten) : index_z(0), index_s(0), zeilen_array(zeilen), spalten_array(spalten) { matrix_zweidim = new T*[zeilen]; for(int i=0; i < zeilen; i++) matrix_zweidim[i] = new T[spalten]; } template <class T> matrix<T>::~matrix() { for(int i=0; i < zeilen_array; i++) delete [] matrix_zweidim[i]; delete [] matrix_zweidim; } template <class T> T *matrix<T>::get_matrix() { return matrix_zweidim; } template <class T> void matrix<T>::push_pos(T *feld, unsigned int feld_zeilen, unsigned int feld_spalten, int position_zeile, int position_spalte) { for(unsigned int i = position_zeile, j = 0; i < (feld_zeilen + position_zeile); i++, j++) for(unsigned int k = position_zeile, l = 0; k < (feld_spalten + position_spalte); k++, l++) matrix_zweidim[i][k] = feld[j][l]; if( (feld_zeilen + position_zeile) > index_z) index_z = (feld_zeilen + position_zeile); if( (feld_spalten + position_spalte) > index_s) index_s = (feld_spalten + position_spalte); } #endif#ifndef ARRAY_KLASSE #define ARRAY_KLASSE #include <iostream> #include <cstdlib> template <class T> class array { private: T *array_eindim; unsigned int zeilen_array; unsigned int index_z; //damit verwechlungen ausgeschlossen sind public: array(unsigned int z); //eine dimension ~array(); T *get_array(); void ausgabe_array(); //std::ostream& operator<<(std::ostream& out, matrix const& m) return m.printAt(out); void push_back(T *feld, unsigned int zeilen_array); //schiebt hinten rein(matrix) void push_pos(T *feld, unsigned int zeilen_array, int pos_z); //für eindim array }; //############################################################################## template <class T> inline array<T>::array(unsigned int zeilen) : index_z(0), zeilen_array(zeilen) { array_eindim = new T[zeilen]; } template <class T> array<T>::~array() { delete [] array_eindim; } template <class T> T *array<T>::get_array() { return array_eindim; } template <class T> void array<T>::ausgabe_array() { for(unsigned int i = 0; i < zeilen_array; i++) std::cout<< "Position " << i << ": " << array_eindim[i] << std::endl; } template <class T> void array<T>::push_back(T *feld, unsigned int feld_zeilen) { for(unsigned int i = 0; i < feld_zeilen; ++i && ++index_z) array_eindim[index_z] = feld[i]; } template <class T> void array<T>::push_pos(T *feld, unsigned int feld_zeilen, int position_zeile) { for(unsigned int i = position_zeile, j = 0; i < (feld_zeilen + position_zeile); i++, j++) array_eindim[i] = feld[j]; if( (feld_zeilen + position_zeile) > index_z) index_z = (feld_zeilen + position_zeile); } #endifich wollts noch machen das man beim erstellen der matrix/arrays die größe beim objekt NICHT angeben brauchsondern angefangen bei einer zeile automatisch erhöht. wie kann ich das machen? kann man da einfach immer wieder "new []" aufrufen? oder muss ich da ein neuen array tmp[] erstellen? 
 
- 
					
					
					
					
 Es ehrt Dich, dass Du BLAS kennst und mich darauf hinweist. Aber mein Vorschlag mit den verketteteten Listen hatte nicht den Anspruch damit zu konkurrieren. Und sicherlich ist die Lösung mit den doppelt verketteten Listen auch nicht die beste und schnellste. 
 Was aber zum Beispiel den Aufwand oder den Schwierigkeitsgrad angeht ist es meiner Meinung ein guter Kompromiss zwischen Einfachheit und Effizienz für übliche Matrixoperationen. Das kommt aber auch wieder darauf an, ob ich gerne mit Zeigern oder Indices rechne. Was einfach ist und was nicht, hängt wahrscheinlich auch sehr vom eigenem Geschmack ab.Und viel höher ist der Speicherverbrauch auch nicht. So etwa das Dreifache... 
 Und der Gewinn? Naja, wie schon gesagt, es wird einiges einfacher.
 Okay, bei einer (1000x1000)-Matrix mit 32 Bit Einträgen wären das statt 4 MB eben 12 MB, noch erträglich finde ich. Aber spätestens bei (1000x1000)-Matrizen sollte dann auch die Grenze dessen liegen, was man "mal eben" von Hand programmieren will.Viel Spass noch beim Weiterdiskutieren. Gruss turing 
 
- 
					
					
					
					
 ich wollte meine arrays für ein neuronales netz benutzen, ich habe noch nie verkettete listen benutzt, wären die für solche arten der anwendung effizient? 
 
- 
					
					
					
					
 dali schrieb: Und Code ohne Kommentare naja... Mir hat man immer Punkte bei den Übungen abgezogen  Ja, aber das liegt einfach daran, dass Tutoren notorisch nicht programmieren können. Die allermeisten Kommentare die ich in Codes lese (ob nun an der Uni, im Netz oder in sonstigen Projekten), sind vollkommen sinnfrei. Wenn man ordentlichen Code schreibt, reduziert sich der zu kommentierende Teil auf ein Minimum. In meinem Fall wäre das fast ausschließlich das Kommentieren von Funktionen und Klassen im Dokumentationsstil (JavaDoc, XML, ...). 
 
- 
					
					
					
					
 stimmt, die meisten kommentare sind sinnlos und helfen nur denjenigen der das prog geschrieben hat. 
 
- 
					
					
					
					
 @exigoner: 
 Mit neuronalen Netzen kenne ich mich leider überhaupt nicht aus. Werden die nicht auch in der Mustererkennung eingesetzt? Schreib doch einfach auf, was Du mit der Matrix konkret machen willst.Zu Kommentaren: 
 Ich finde Kommentare schon sehr wichtig, aber auch hier gilt eindeutig die Devise, dass weniger auch mehr sein kann.
 
- 
					
					
					
					
 keine sorge, ich kenne mich ddarin auch nicht aus, dann hab ich aber ne klasse für ein netz gefunden und wollt ein eigenes machen, nachdem ich das verstanden habe, was bei sowenig infos im netz recht schwierig ist. aber ich hab ja zeit. nachdem ich die klassen oben um einen standartkonstruktor bereichert habe, und noch ne set-member (für die größe) hinzugefügt habe, wollte ich damit die ein-und-ausgabe daten der neuronen speichern sollen. 
 frag mich nicht wie, aber meine klasse matrix (2d array) soll die gewichte, die später justiert werden speichern.
 die arrays darunter speichern nur aus und eingabe daten.achtung die is von mir ein wenig modifiziert: class simpleNet { private: matrix<float> ihWeights, hoWeights; //ursprünglich float** ihWeights matrix<float> ihWDelta, hoWDelta; array<float> in_inp, in_hid, in_outp; //ursprünglich float* in_inp,... array<float> out_inp, out_hid, out_outp; array<float> errH, errO, prefO, diffO; int amount_inp, amount_hid, amount_outp; float errTol, learnRate, absorp; public: anne(int neur_input, int neur_hidden, int neur_output); anne(int neur_input, int neur_hidden, int neur_output, float **ihW, float **hoW); ~anne(); float *getOutput(); float *getODiff(); void setErrTolerance(float tol); void setLearnRate(float rate); void setAbsorp(float abs); float *run(float *input); bool train(float *input, float *pOutput); void setZero(); };der programmmierer hat diese arrays zum speichern und die 2d-arrays anscheinend noch zum berechnen benutzt: float *simpleNet::run(float *input){ //complete run through the net setZero(); //set needed matrices to zero for(int i=0; i<amountI; i++) //save input-vector inI[i]=input[i]; for(int i=0; i<amountI; i++) //special case here: inI=outI outI[i]=inI[i]; outI[amountI]=1; //shift neuron = 1 for(int i=0; i<amountH; i++) //get input of hidden layer for(int j=0; j<=amountI; j++) inH[i]+=ihWeights[j][i]*outI[j]; for(int i=0; i<amountH; i++) //get output of hidden layer (sigmoide function) outH[i]=1/(1+exp(-inH[i])); outH[amountH]=1; //shift neuron = 1 for(int i=0; i<amountO; i++) //get input of output layer for(int j=0; j<=amountH; j++) inO[i]+=hoWeights[j][i]*outH[j]; for(int i=0; i<amountO; i++) //get output of output layer (sigmoide function) outO[i]=1/(1+exp(-inO[i])); return outO; } bool simpleNet::train(float *input, float *pOutput){ bool converge=true; for(int i=0; i<=amountI; i++) //set delta matrices to 0 (start value) for(int j=0; j<amountH; j++) ihWDelta[i][j]=0; for(int i=0; i<=amountH; i++) for(int j=0; j<amountO; j++) hoWDelta[i][j]=0; run(input); //run forward for(int i=0; i<amountO; i++) //save preferred output prefO[i]=pOutput[i]; for(int i=0; i<amountO; i++){ //compute output difference vector diffO[i]=prefO[i]-outO[i]; if(fabs(diffO[i])>errTol) converge=false;//difference within limit? } for(int i=0; i<amountO; i++) //compute error vector of output layer errO[i]=diffO[i]*outO[i]*(1-outO[i]); for(int i=0; i<=amountH; i++){ //compute error vector of hidden layer for(int j=0; j<amountO; j++) errH[i]+=errO[j]*hoWeights[i][j]; errH[i]*=outH[i]*(1-outH[i]); } for(int i=0; i<=amountI; i++) //update input-hidden weight matrix for(int j=0; j<amountH; j++){ ihWDelta[i][j]=learnRate*errH[j]*outI[i]+ihWDelta[i][j]*absorp; ihWeights[i][j]=ihWeights[i][j]+ihWDelta[i][j]; } for(int i=0; i<=amountH; i++) //update hidden-output weight matrix for(int j=0; j<amountO; j++){ hoWDelta[i][j]=learnRate*errO[j]*outH[i]+hoWDelta[i][j]*absorp; hoWeights[i][j]=hoWeights[i][j]+hoWDelta[i][j]; } return converge; }übrigens ich will wirklich nichts kopieren, ich wollte nur verstehen wie die netze funktionieren. 
 nun weiß ich nicht ob sich listen, da besser machen, zumal ich noch nie welche gemacht oder benutzt habe.