Basis Script zum anpassen

Dieses Forum beschäftigt sich mit allen Fragen, Kommentaren und Anregungen zu MemBrain Skripten. Auch der Austausch von Skripten zwischen MemBrain Benutzern soll hiermit gefördert werden.
Wenn Sie ein interessantes Skript haben, das Sie anderen MemBrain Benutzern zur Verfügung stellen wollen, dann Erstellen Sie dafür jeweils bitte ein neues Thema in diesem Forum. Der Titel des Themas sollte es anderen Benutzern erlauben möglichst schnell zu erfassen, wozu Ihr Skript dient.
User avatar
Admin
Site Admin
Posts: 438
Joined: Sun 16. Nov 2008, 18:21

Re: Basis Script zum anpassen

Post by Admin »

Hallo Seppy,

vielen Dank für das Skript, das schaue ich mir gerne einmal an, vielleicht kann ich ja hier und da noch was tunen.
Seppy wrote:Fragen:
Wo füge ich den Sleep(100) am besten ein (Anfang oder Ende der Schleife)?
Da muss ich mir erst das Skript anschauen...
Seppy wrote:Wie werden Befehle wie z.B. "bool SleepExec(uint maxTimeMs)" verwendet ?
Der SleepExec() sieht ja so aus:
SleepExec();

Wie ist das mit "bool SleepExec(uint maxTimeMs)" ?
SleepExec(6000);
SleepExec("6000");
bool SleepExec(6000);
bool SleepExec("6000");
Bei 'SleepExec' handelt es sich um eine sogenannte 'überladene' Funktion. Das bedeutet nichts anderes, als dass es mehrere Versionen dieser Funktion gibt, die alle gleich heißen (nämlich 'SleepExec'), sich aber bzgl. der übergebenen und zurückgegebenen Parameter unterscheiden.
Bei 'SleepExec' gibt es die folgenden Varianten ('Überladungen'):

Code: Select all

void SleepExec()
Diese Funktion bekommt keine Parameter übergeben und gibt auch nichts zurück. Sie wartet auf das Beenden von Teach oder Think, egal wie lange das dauert. Das Skript steckt also in der Funktion fest, solange Teach oder Think aktiv ist, und wenn es Tage oder Wochen dauern sollte.
('void' kannst Du als 'nichts' übersetzen. In der Ursprache 'C' musste man dementsprechend das 'void' auch anstatt der leeren Klammern scheiben (also 'void SleepExec(void)' ). Das spart man sich inzwischen und in AngelScript ist es gar nicht mehr gültig, soweit ich weiß, eine leere Parameterliste wird also immer mit leeren Klammern angegeben.)

Code: Select all

bool SleepExec(uint maxTimeMs)
Diese Überladung ('Variante') bekommt einen Parameter vom Typ 'uint' übergeben, der angibt, wie lange die Funktion maximal auf das Beenden des Think bzw. Teach warten soll, bevor sie auf jeden Fall zurückkehrt. Den Parameter-Namen 'maxTimeMs' kannst Du ignorieren, er ist nicht wichtig und Du musst ihn auch nicht in Deinem Code verwenden. Er ist nur von mir so gewählt worden, dass er möglichst gut ausdrückt, was die Funktion mit diesem Parameter macht. Der Rückgabewert vom Typ 'bool' (also entweder der Wert 'true' oder der Wert 'false') gibt an, warum die Funktion zurückgekehrt ist: 'true' bedeutet, dass Teach oder Think geendet hat, 'false' bedeutet, dass die Funktion zurückgekehrt ist, weil der angegebene Timeout-Wert (Parameter 'maxTimeMs') abgelaufen ist, ohne das Teach oder Think geendet hat.

Dementsprechend:

Code: Select all

SleepExec();
Ruft die Funktionsüberladung 'void SleepExec()' auf, kehrt also erst zurück, wenn Teach oder Think beendet ist.

Code: Select all

SleepExec(6000);
Ruft die Überladung 'bool SleepExec(uint maxTimeMs)' auf, wobei für 'maxTimeMs' der Wert 6000 übergeben wird. Die Funktion kehrt also zurück, wenn entweder Think oder Sleep endet, spätestens aber nach 6000 ms. Der Rückgabewert wird hier ignoriert.

Im folgenden Beispiel wird ebenfalls die Überladung 'bool SleepExec(uint maxTimeMs)' aufgerufen, hier wird der Rückgabewert aber verwendet, um eine Fallunterscheidung durchzuführen:

Code: Select all

if (SleepExec(5000))
{
   MessageBox("Think oder Teach wurde beendet!");
}
else
{
  MessageBox("5 s gewartet, aber Think oder Teach noch nicht beendet!");
}
gleichwertig ist der folgende Code, dabei sieht man die Rückgabevariable nur deutlicher:

Code: Select all

bool execStopped;

execStopped = SleepExec(5000);

if (execStopped )
{
   MessageBox("Think oder Teach wurde beendet!");
}
else
{
  MessageBox("5 s gewartet, aber Think oder Teach noch nicht beendet!");
}
Viele Funktionen von MemBrain sind mit mehreren Varianten überladen. Z.B. die 'SelectInput(...)' Funktion, hier gibt es mehrere Varianten, je nachdem, wie viele Input-Neuronen und welche man selektieren möchte. Auch im Sktipt selbst kann man Funktionsüberladungen programmieren. Ein Beispiel hierfür ist die Methode 'Start' der Klasse 'SecondsTimer', die ich jüngst mit einer weiteren Variante überladen habe. Es gibt hier die beiden Überladungen:

Code: Select all

void Start(uint seconds)
bzw.
void Start()
Je nachdem, ob Du beim Aufruf von 'Start' etwas übergibst oder nicht, sucht sich der Skriptcompiler die richtige Überladung heraus. Den Code für die beiden Varianten kannst Du Dir in der Datei 'SecondsTimer.as' anschauen, wenn Du magst. Ist nichts kompliziertes dran, die Funktion wird einfach noch einmal definiert, mit anderer Parameterliste und anderem Inhalt.

Klärt das Deine Fragen win wenig? Ich weiß, Programierung ist am Anfang etwas mühsam und verwirred, wenn ich mir Deine letzten Skripte aber so anschaue, machst Du beachtlich schnell Fortschritte! Vor allem sehe ich, dass Du schon den wichtigsten Aspekt überhaupt erfasst hast: 'Teile und herrsche!'. Immer alles schön in Unterfunktionen oder sogar neue Skriptdateien auslagern, dann wächst einem ein Programm auch nicht über den Kopf, nur so bleibt die Komplexität beherrschbar! ;)

Viele Grüße,
Thomas
Thomas Jetter
User avatar
Seppy
Posts: 47
Joined: Fri 5. Dec 2008, 04:48
Location: 90537 Feucht

Re: Basis Script zum anpassen

Post by Seppy »

Hallo Leude, Thomas,

das hat meine Fragen natürlich wie immer (vollständig beantwortet).

Naja, mehrere Script-Dateien möchte ich, wenn möglich vermeiden, (Deine mal ausgeschlossen, NetEditor.as, Position.as und SecondsTimer.as).
Ich möchte auch in der main() Funktion wenn möglich nur verzweigungen/aufrufe zu anderen Funktionen haben.
(Dient der Übersichtlichkeit).

ich hab das Script, mit Thomas Hilfe (nochmal ein DICKES DANKESCHÖN) komplett überarbeitet.

Verbesserungen:
Das Lesson handling wurde verbessert.
Die Schleife/Abfrage in der Funktion "Train_Net()" wurde optimiert.
Der "Pattern Error Viewer" wird alle 2 Sekunden in der Höhe angepasst (Fit Y-Scale).

Man kann das Script jetzt auch mehrfach ablaufen lassen:
Damit ist der Bereich in der Funktion main() gemeint, der in der "while" Schleife steht.
Es wird also so oft das gleiche Netz "Net.mbn" resettet, trainiert, abgespeichert und die "Tink" Lesson durchlaufen / Outputs erzeugt.
(Die Outputs sind dann alle in der Datei "Output.csv").

Man kann jetzt auswählen bei welchem "Teacher Abbruch Kriterium (Zeit, Lesson Repetitions, Net Error) ein thinking / Output gemacht wird.
Man kann jetzt z.B. die Trainingszeit auf 2 Minuten begrenzen; Ein "thinking" und "Output" wird aber nur ausgeführt, wenn der unter "EXIT_LEARNING_NET_ERROR" eingetragene "Net Error" erreicht wird.

Ich warte auf weitere Verbesserungen, Vorschläge (Neue Funktionen/Erweiterungen) und auch Fehlermeldungen sind herzlich willkommen.
(Im Forum, als PN oder per E-Mail unter josef.rauch@web.de).

Da ich z.Z. KEINE FEHLER erkennen kann, stell ich's mal in's Forum.

PS: Thomas, ich arbeite gerade an der Komplexität, komplexer als Aktienkurse geht's aber nimmer..... :D

Gruß Seppy
Wer arbeitet macht Fehler, wer wenig arbeitet macht wenig Fehler, wer nicht arbeitet macht keine Fehler, wer keine Fehler macht wird befördert.
User avatar
Admin
Site Admin
Posts: 438
Joined: Sun 16. Nov 2008, 18:21

Re: Basis Script zum anpassen

Post by Admin »

Hallo Seppy,

schickes Skript, gefällt mir sehr gut! Das ist eine Klasse Basis für alle, die über das erste Probieren und manuelle Experimentieren mit MemBrain hinaus arbeiten wollen. Schön flexibel und gut kommentiert auch!

Eine weitere Anregung wäre, das Output-File gleich automatisch öffnen zu lassen, z.B. mit Excel oder welcher Anwendung auch immer, die mit csv-Dateien verknüpft ist:

Code: Select all

// Soll das erzeugte Output-File zum Ende des Skripts geöffnet werden?
const bool OPEN_OUTPUT_FILE = true;


if (OPEN_OUTPUT_FILE)
  {
    if (!ShellExecute("open", OUTPUT_LESSON_FILE_NAME, ""))
    {
        Error("Kann Output-Datei nicht öffnen!");
    }
  }


Viele Grüße und ein ganz dickes Dankeschön für das Skript!
Thomas Jetter
User avatar
Seppy
Posts: 47
Joined: Fri 5. Dec 2008, 04:48
Location: 90537 Feucht

Re: Basis Script zum anpassen

Post by Seppy »

Hallo Thomas,

danke für die schöne Idee, ist jetzt drin.
Ich hab auch noch folgendes in main() eingebaut:

if (CLOSE_MEMBRAIN_ON_EXIT) // Ist "CLOSE_MEMBRAIN_ON_EXIT" = true, dann hier weiter.
{
ExitMemBrain(); // MemBrain wird beendet.
}

Wenn man sich jetzt noch ein Icon auf den Desktop legt, mit z.B. dieser Befehlszeile:

"C:\Program Files\MemBrain\MemBrain.exe" /S "C:\Users\Josef Rauch\Documents\MemBrain\Dax_Woche\Base.as"

Kann man das ganze mit 1-2 Mausklicks (Je nach Windows Einstellung) ablaufen lassen und erhält am Ende nur die geöffnete "Output.csv".

Dann hab ich noch "TRAIN" durch "LEARN" ersetzt, wegen Verwechslungsgefahr von "TRAIN" und "THINK".
(Mir ist es nämlich auch schon passiert, daß ich meine Trainingsdaten versehentlich in "Think.csv" abgespeichert habe).

Gruß Seppy
Wer arbeitet macht Fehler, wer wenig arbeitet macht wenig Fehler, wer nicht arbeitet macht keine Fehler, wer keine Fehler macht wird befördert.
User avatar
Admin
Site Admin
Posts: 438
Joined: Sun 16. Nov 2008, 18:21

Re: Basis Script zum anpassen

Post by Admin »

Hallo Seppy,

ich habe auf Basis Deines schicken Basis-Skripts für 'Michael' hier im Forum
viewtopic.php?f=5&t=49&p=262#p262
ein Skript mit einer kleinen, nützlichen Erweiterung erstellt: Wenn die neue Konstante AUTO_CREATE_NORMALIZE_LESSON auf 'true' gesetzt ist, dann wird die 'Normalize'-Lesson nicht aus einer Datei geladen, sondern vom Skript automatisch aus 'Learn'- 'Validate'- und 'Think'- Lesson zusammengesetzt.

Dazu habe ich Deine Funktion 'Init_Lessons()' etwas 'kleingeklopft', zwei weitere Funktionen 'OpenLessonFile' und 'CreateNormalizeLesson' sowie ein bisschen Code in die Funktion 'Init_First' eingefügt und ein String-Array für die Lesson-Namen eingeführt (LESSON_NAMES).

Vielleicht hast Du ja Lust, das in Dein 'Basis'-Skript zu übernehmen? Du müsstest nur aus Michaels Skript die geänderten und neuen Funktionen sowie die Deklarationen für die boolsche Konstante und das String-Array in Dein Skript kopieren. Außer diesen Dingen habe ich nichts geändert und die Änderungen habe ich auf Basis Deines Originalskripts gemacht (vor ein paar Stunden heruntergeladen).

Vielen herzlichen Dank an dieser Stelle nochmal für das 'Basis-Skript'! Es wird immer leistungsfähiger und flexibler und vereinfacht die Arbeit mit MemBain immens!

Viele Grüße,
Thomas
Thomas Jetter
User avatar
Seppy
Posts: 47
Joined: Fri 5. Dec 2008, 04:48
Location: 90537 Feucht

Re: Basis Script zum anpassen

Post by Seppy »

Hallo Thomas,
das kommt natürlich ins Script rein, ich schaus mir gleich mal an, aber vorm Wochenende wird das nichts.
danke Dir, tolle Idee.
Gruß Seppy
Wer arbeitet macht Fehler, wer wenig arbeitet macht wenig Fehler, wer nicht arbeitet macht keine Fehler, wer keine Fehler macht wird befördert.
Post Reply