Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

eisenmad

Treue Seele

  • »eisenmad« ist der Autor dieses Themas

Beiträge: 84

Wohnort: Heute hier, morgen dort

Beruf: Denker

  • Private Nachricht senden

1

29.09.2015, 17:51

Analyse Objektorientierung - Neuronales Netz

Hallo

Ich will versuchen objektorientiertes Programmieren zu lernen. Dazu habe ich jetzt viel in meinem neuen Lehrbuch gelesen und die Beispielprogramme darin nachprogrammiert. Das hat funktioniert, aber da hatte ich halt auch fertigen Code.... Trotz des vielen Arbeiten mit dem Lehrbuch fühle ich mich noch sehr, sehr schwach im objektorientierten Denken. Meine Denkweise ist total seriell. :-(

Der Autor schreibt, dass man als erstes eine Analyse durchführen muss um die am Programm beteiligten Objekte und damit ihre Klassen zu identifizieren, und um danach eine Beschreibung ihres Verhaltens zueinander zu finden. Dies möchte ich jetzt an einem Beispiel selbst versuchen.

Ich konnte beim C++ lernen ein funktionierendes neuronales Netz zum speichern und (verrauschten) wiedererkennen von Informationen programmieren (ein sog. Autoassociator). Dies jedoch im Spaghetti-Code. Mein Ziel wird sein mein Programm nochmal neu zu schreiben und zwar objektorientiert. Mein Programm ist hier als Anhang hochgeladen. Ich erkläre nun was es macht. Bitte compiliert es und seht die Ausgabe an.

Hopfield-Netzwerk.cpp

Zuerst definiere ich mir aus einer Gleichverteilung zwei zufällige, binäre Muster §x_i \in \{0,1 \}^{\mathrm{N}} §, mit der Dimension §\mathrm{N}§. Diese Dimension entspricht auch der Anzahl der Neuronen. Danach konstruiere ich die sog. §( \mathrm{N} \times \mathrm{N} )§-Adjazenzmatrix §W_{ij}§ (welche die Struktur des neuronales Netzes wieder spiegelt):

§ W_{ij} = \sum\limits_{k=1}^{2} x_i^k x_j^k §

Die Diagonalelemente sind nicht zu Null gesetzt. Ich erlaube im Netz also Selbstkopplungen der Neuronen. In dieser Matrix sind die zwei Muster gespeichert. Nun existieren §2^{\mathrm{N}}§ mögliche Testvektoren, die man dem Netz präsentieren kann. Das bedeutet ich schnappe mir einen beliebigen Testvektor, gebe diesen dem Netz als Eingabe und gucke was heraus kommt. Sollte der Testvektor eine der gespeicherten Informationen sein, muss diese auch als Ausgabe erscheinen. Der Null Vektor geht immer in den Nullvektor über.

Das Netz hat dann eine Information gefunden, wenn es von Lern- zu Lernschritt keine Veränderung mehr findet. Das geschieht durch eine sog. "synchrone Update-Regel" der Form:

§ x_i(n) = f \left( \sum\limits_{j=1}^{N} W_{ij} x_j(n-1) \right) §

Die Ausgabe ist also der Vektor, der sich von Iteration zu Iteration unter dieser Lernregel nicht ändert. Man nennt diese Vektoren Attraktoren oder auch Fixpunkte des Netzes. Die Funktion §f§ ist die sog. Transferfunktion und wird bei mir durch eine Stufenfunktion realisiert:

§f(t) = \begin{cases} 1 \text{ falls } t \geq \Theta \\ 0 \text{ falls } t< \Theta \end{cases}§ und §\Theta§ ist der Threasholdwert.

Das ist so zu verstehen, dass in der biologischen Motivation Signale durch Dendriten einlaufen, vom Zellkörper aufsummiert werden und wenn ein bestimmter Schwellenwert/Threshold erreicht ist, das Neuron über sog. Axon signale wieder feuert.

Das war per se ein Hopfield Netz. Mein Programm geht an der Stelle aber noch weiter. Ich wähle mir nicht nur ein beliebiges Testmuster und berechne was das Netz damit macht, sondern ich präsentiere dem Netz alle möglichen §2^{ \mathrm{N}}§ Vektoren die existieren und lasse für jeden einzelnen ausgeben in welchen stabilen Zustand es läuft und und lasse mir auch ausgeben welche gelernten Bilder alle wiedererkannt wurden. Das ist die Verallgemeinerung von obiger Beschreibung in einer großen Schleife über alle möglichen Konfigurationen.

Nun ist die Frage wie ich dieses Vorgehen und mein Programm objektorientiert aufbauen würde.

Naiv würde ich sagen, dass alle obigen Eigeschaften Zwei Objekte beschreiben.

1. Objekt: Neuronen
2. Objekt: Netzwerk

Die Konstruktion der Adjazenzmatrix sollte in Netzwerk enthalten sein. Die Lernregel in Neuronen. Hier bin ich mir aber schon nicht mehr sicher, ob die Transferfunktion separat in Netzwerk gehört oder mit zu Neuronen.

Alles sehr schwammig und ich weiss nicht wie man korrekt analysiert, wie man mein Programm objektorientiert schreibt.

Wäre toll wenn mir da jemand mit Rat besteht mein Programm neu zu schreiben. Wie würdet ihr Vorschlagen das Problem zu analysieren?

Danke und Grüße

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »eisenmad« (29.09.2015, 18:09)


TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

2

29.09.2015, 18:05

Um Klassen aus deinem Programm zu finden kann man folgenden Ansatz verfolgen: Beschreibe dein Programm in einem zusammenhängenden fließtext mit deren Beziehungen zueinander, sowie im groben die Funktion der einzelnen. Dabei wirst du im nachhinein Subjektive finden, die klar Klassen repräsentieren. Danach kannst du aus den Verben Beziehungen und erste Methoden ableiten. Wichtig ist, dass du beim schreiben des Textes eher an funktionales denkst und nicht technische Details. Daraus ergibt sich ein fachliches Modell aus Klassen, was man dann recht gut in ein technisches Modell verfeinern kann.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

30.09.2015, 00:10

Du kannst auch einfach mal anfangen dein Programm so einzuteilen wie du es für richtig hältst. Am Anfang werden sicherlich viele Dinge zu wenigen Klassen zusammen gefasst aber mit der Zeit wirst du immer besser wissen wie du deinen Code sinnvoll zu einzelnen Klassen zusammen fassen kannst. Am Anfang versuchen viele auch möglichst viel Code in wenige Funktionen zu stopfen und mit der Zeit lernt man eben immer mehr wie man einzelne Funktionen weiter aufsplitten kann. Das selbe ist es mit Klassen an sich erst mal auch.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

30.09.2015, 06:37

Wasserfall ist ebenfalls sehr unproduktiv, sobald es über eine Hand voll Klassen/Komponenten hinaus geht. Das wird zwar hübsch mit UML im Studium gelehrt, ist in der Praxis aber oft reichlich nutzlos, speziell wenn man Methoden und Properties mit einbezieht. So detailliert kann man nur bei wenigen Klassen wirklich planen und alles darüber hinaus wird meist noch sehr heftig geändert, weil man eben doch wesentlich mehr braucht oder gewisse Dinge anders gemacht werden müssen. Wenn man aber eh so viel ändern muss, kann man sich den Aufwand auch schenken und direkt nach der Identifikation der wichtigsten Komponenten / Klassen aufhören.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

30.09.2015, 06:43

Ich würde raten, sich weniger den Kopf zu zerbrechen und stattdessen einfach mal auszuprobieren, welche Aufteilung dir sinnvoll erscheint. Du wirst dann schon rausfinden, was du hättest besser machen sollen und dann machst du es einfach so. Ich hatte auch so eine (wenn auch kurze) Phase, wo ich ein neues Design erstmal in UML ausprobiert hab. Was ich daraus gelernt hab ist, dass UML und Noun Phrase Methode und was es sonst an Kram noch alles in irgendwelchen abgehobenen Büchern zu finden gibt völlig nutzlos ist. Softwaredesign funktioniert am Ende durch Erfahrung und Intuition und nicht weil man erstmal alles bis ins Letzte zerdacht und hübsche Bildchen gemalt hat. Die richtigen Probleme sieht man immer erst, sobald man Code schreibt. Ich fang in meinen Projekten einfach an, Header zu schreiben und arbeite mich von dort aus vor. Design muss leben, was bedeutet, dass es sich ständig verändern kann. Software, in der das Refactoring aufgehört hat, ist tot. Und ganz wichtig zu verstehen: OOP ist nicht die Antwort auf alles... ;)

Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von »dot« (30.09.2015, 07:15)


xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

6

01.10.2015, 03:27

Naja intuitiv ist schön und gut vor allem für Anfänger aber arbeitet mal in einem Team von 10 LEuten an einer Engine und plant dann einfach mal nichts sondern mach mal einfach deine header und schreib lustig drauf los.
Software planung ist das A und O. Für kleine Popelprogramme kan man schon einfach mal drauf losschrieben aber ncith für ernste Software mit vielen Anforderungen

Aber was weiß ich schon bestimmt ist es sehr easy eifnach mal einen 1 Million Zeilen Code zu schreiben indem man eifnach mal drauf los schreibt udn sich schon mal die Header anlegt
:whistling: Natürlich werden die anderen schon mit meiner Denkweise zurecht kommen, wer braucht denn schon Bildchen....der Code ist doch da.

Jain. Natuerlich brauchen groessere Softwareprojekte eine gehoerige Portion an Planung. Jedoch selten auf dem Level von Klassen und welche Funktionen diese denn haben sollen. Auf dem Level aendert sich Software staendig, und oft sind die Anforderungen ganz zu Beginn des Projekts auch nicht voellig ersichtlich.

Was dann umso wichtiger wird ist ein ordentliches Testing Konzept damit ohne grosses Risiko Refactorings machen kann. Genau das wuerde ich eisenmad hier auch empfehlen. Statt dir zu viele Gedanken ueber das detaillierte Design zu machen, wuerde ich wie dot und BlueCobold schon gesagt haben einfach drauf los legen und mir dann eher Gedanken machen wie sich das ganze ordentlich testen laesst.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

01.10.2015, 05:49

Ich habe nciht selten in der Mitte eines Projektes auf Grund von mangelnder Vorüberlegungen schon mal eine sehr große Umstrukturierung meins Systemes machen müssen und sowas ist dann einfach zum Kotzen wo cih mir dann immer auch an den Kopf fassen muss und mcih fragen muss warum cih das zum teufel nciht doch besser vorher überlegt habe!

Genau so funktioniert Softwareentwicklung. Der Grund, wieso du dir das vorher nicht besser überlegt hattest, ist ganz einfach, dass du vorher das Problem noch nicht gut genug verstanden hattest und auch nicht verstanden haben konntest, um das nun richtig erscheinende Design vorher schon zu sehen. Du musstest erstmal zum Punkt der Erkenntnis coden, und kein UML Diagramm der Welt hätte irgendwas daran geändert...

Nutzlos beduetet für mcih dass jeder der das macht nur zeit verschwendet und am ende kommt ncihts bei raus...

Jap, genau das meinte ich damit... ;)

Zitat von »Jeff Atwood«

UML is great if you don't want to do any work; you just draw pictures of what it would look like if work was actually done. This is not only borderline laziness, it's also a recipe for disaster. You can't architect a real world application on a whiteboard. You must prototype it in code to gather data on the performance and design implications of the choices you are making.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (01.10.2015, 06:07)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

01.10.2015, 06:55

Aber was weiß ich schon bestimmt ist es sehr easy eifnach mal einen 1 Million Zeilen Code zu schreiben indem man eifnach mal drauf los schreibt udn sich schon mal die Header anlegt
Ich habe den Sarkasmus durchaus verstanden, dennoch will ich dazu sagen, dass das natürlich niemand macht. Es ist durchaus sinnvoll sich Gedanken um die generelle Architektur einer Anwendung zu machen, die Komponenten und ihre Interaktionen zu identifizieren. Aber das ist eben nur sehr grob. Anzufangen konkrete Klassen zu benennen, Methoden festzulegen und Eigenschaften der Klassen hinzuzufügen, führt zu einem Desaster, eben weil eine große Software sich so gar nicht planen lässt. Zudem wird oft sukzessiv gearbeitet, man packt in bestehenden Code also immer weitere Features hinzu. Natürlich ist es hilfreich da vorher einen groben Blick zu haben, was mal kommen könnte, damit man sich nicht fest fährt. Dennoch gibt es da einfache Regeln:
1) Lose Kopplung hilft
2) Gute Kapselung hilft
3) Generell hilft jede "Good Practice" aus dem entsprechenden Paradigma
4) Refactorings sind hin und wieder notwendig und müssen dann entsprechend durchgeführt werden

Wenn man sich daran hält, kommt man sicher besser voran als sich an ein UML-Diagramm mit Klassen, Methoden und Eigenschaften zu halten, was vorn und hinten nicht passt, nicht funktioniert, schlecht entworfen wurde und zu 80% unvollständig ist. Die ersten drei Punkte helfen den vierten zu reduzieren. Ein UML-Diagramm bis in's letzte Detail hingegen maximiert den vierten Punkt und verschwendet Zeit bei der Erstellung von Details, die man zur Zeit der Planung gar nicht abschätzen konnte. Bei Änderungen am Konzept / Design ist das ganze Ding dann auch noch komplett für'n Eimer. Dann lieber mal 2-5h mit ein paar Leuten zusammen eine grobe Architektur abgeklärt als wochenlang so ein unnützes Diagramm erstellt zu haben.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Tobiking

1x Rätselkönig

  • Private Nachricht senden

9

01.10.2015, 08:49

Der Schlüssel bei großen Projekten ist letztendlich die Abstraktion. Wenn man mit mehreren Leuten an einem Projekt arbeitet, kommt man sehr schnell an einen Punkt, wo es niemanden mehr gibt der alles im Detail überblicken kann. Dann zählt nicht mehr groß der Code selber (solange er das tut was er verspricht), sondern nur noch die Schnittstellen. Teile des Code werden so gesehen zur Black Box. Das heißt dann aber auch das der Inhalt dieser Black Box im Gesamtbild gar nicht mehr wichtig ist und Umbauten innerhalb der Black Box den Rest des Systems nicht in Mitleidenschaft ziehen. Unterteilungen von Code in Klassen, Module, Subsysteme etc. schachtelt (wenn gut gemacht) diese Black Boxen ineinander, um den Einfluss von Umstrukturierungen auf mehreren Ebenen einzudämmen. Entsprechend sollte der Fokus auch darin liegen die umgebende Architektur zu planen und den Code so zu schreiben das sich guten Funktionseinheiten bilden (Stichwort lose Kupplung und gute Kapselung was BluCobold schon erwähnt hatte).

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

10

01.10.2015, 23:27

Eine Option (falls diese schon genannt wurde, bitte ich um Verzeihung) ist in bestehende Lösungen mal reinzuschauen. NNs sind ja nicht so speziell, dass es noch nie jemand gemacht hätte und Ideen sammeln ist durchaus erlaubt. Natürlich ist da der Lerneffekt ggf. ein anderer - wenn man direkt einen funktionierenden Ansatz verwendet, versteht man noch lange nicht warum diese Lösung funktioniert.
Übrigens glaube ich sind NNs nicht ideale Beispiel fürs OO Design, weil es dabei oft eher um Performance als um schöne Kapselung geht. Wenn ich mich recht erinnere ist data oriented design da geeigneter.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Werbeanzeige