Inhalte zur Vorlesungswoche #8, Informatik 1 im Wintersemester 2024/25
(EN google-translate)
(PL google-translate)
Themen
|
1 Rekapitulation der letzten Übung mit einem einfachen Neuronalen Netz
siehe hier unten: 04_WS2024_25/02_INF_day_by_day/07_INF_Fr_22_11_2024
2 Einführung zu Optimierungsverfahren
|
Was sind Heuristiken? -- 50_Simulationstechnik/06_Optimierung/02_Heuristiken
Wie arbeitet ein Gradientenverfahren bei der Optimierung? -- 50_Simulationstechnik/06_Optimierung/01_Gradientenverfahren
Was sind genetische Algorithmen und wann kommen sie zum Einsatz? -- 50_Simulationstechnik/07_Genalgorithmus
Was ist das Backpropagation-Verfahren? -- 67_Echtzeitsysteme/08_NeuronaleNetze/02_Backpropagation
3 Implementierung eines modifizierten Gradientenverfahrens
Mit Hilfe eines modifizierten Gradientenverfahrens lassen sich bei einfachen Netzen in einem überwachten Lernprozess bessere Ergebnisse erzielen, als mit blossem Testen einer Folge von Zufallswerten.
Das nachfolgende Netz wurde mittels eines modifizierten Gradientenverfahrens als UND-Gatter belernt:
#include <iostream>
#include <math.h>
using namespace std;
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
double netz(double in0, double in1)
{
//ineffizient, aber komfortabel, die Arrays jedesmal in der
//Funktion neu zu erzeugen:
double w[] = {7.605,-15.22,514.936,-312.267,-806.885,403.354};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,0.0};
double D=0.1;
in[0] = in0;
in[1] = in1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
return out[2];
}
int main(void)
{
cout<<"Test einer NN, das wie ein logisches UND-Gatter reagiert:"<<endl;
cout<<"0 | 0 liefert "<<netz(0.0,0.0)<<endl;
cout<<"0 | 1 liefert "<<netz(0.0,1.0)<<endl;
cout<<"1 | 0 liefert "<<netz(1.0,0.0)<<endl;
cout<<"1 | 1 liefert "<<netz(1.0,1.0)<<endl;
return 0;
}
Code 0-1: Mittels modifiziertem Gradientenverfahren als UND-Gatter belerntes Neuronales Netz.
Test einer NN, das wie ein logisches UND-Gatter reagiert: 0 | 0 liefert 1.72757e-09 0 | 1 liefert 5.26648e-07 1 | 0 liefert 4.33762e-07 1 | 1 liefert 1
Code 0-2: Ausgabe des obigen Programms.
Ausgangspunkt ist ein kleines Neuronales Netz:
Bild 0-1: Neuronales Netz.
Nun soll ein Lernverfahren implementiert werden, damit das Netz lernt, eine bestimmte Aufgabe zu erledingen, hier ist das die Funktionalität eines UND-Gatters:
Bild 0-2: Prinzip des überwachten Lernens.
Nachfolgendes Belern-Programm wird im Unterricht Schritt für Schritt entwickelt:
#include <iostream>
#include <math.h>
#include<cstdlib>
#include<ctime>
#define N 6
using namespace std;
double zufall()
{
return (double)(rand()%10000)*0.02-100.0; // Wertebereich: +/-99.99
}
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
double w[] = {1.0,1.0,1.0,1.0,1.0,1.0};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,1.0};
double netz1(double in0, double in1)
{
in[0]=in0;
in[1]=in1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
out[0] = sigmoid(0.1,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(0.1,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(0.1,out[0]*w[4]+out[1]*w[5]);
return out[2];
}
double fehler()
{
double f0 = netz1(0.0,0.0);
double f1 = netz1(0.0,1.0);
double f2 = netz1(1.0,0.0);
double f3 = 1.0 - netz1(1.0,1.0);
return sqrt(f0*f0+f1*f1+f2*f2+f3*f3);
}
int main(void)
{
srand(static_cast<unsigned int>(time(0)));
for(int i=0;i<N;i++)
w[i]=zufall();
double err = fehler();
for(int D=0;D<10000000;D++)
{
int inx = rand()%N;
double wmerk=w[inx];
//Modifiziertes Gradientenverfahren:
if(rand()%2==0)
w[inx]+=0.001;
else
w[inx]-=0.001;
//Alternativ, Zufallsgewichte testen:
//w[inx]=zufall();
double errneu = fehler();
if(errneu>err)
{
w[inx]=wmerk;
}
else
{
if(errneu<err)
cout<<"err="<<err<<endl;
err=errneu;
}
}
//Bestes Array mit den Gewichten ausgeben,
//um das fertige trainierte Netz in einem anderen Programm
//nutzen zu können:
for(int i=0;i<N;i++)
cout<<w[i]<<",";
cout<<endl;
return 0;
}
Code 0-3: Netz und Lernverfahren: Modifiziertes Gradientenverfahren.
Im Untericht entstanden:
Fehler des Netzes berechnen, das sich wie ein UND-Gatter verhalten soll.
#include <iostream>
#include <math.h>
using namespace std;
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
int main(void)
{
double otest[] = {0.0,0.0,0.0,0.0};
double w[] = {-51.82,99.98,-16.26,6.34,45.94,-100.0};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,1.0};
double D=0.1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
in[0]=0.0;
in[1]=0.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[0] = out[2];
in[0]=1.0;
in[1]=0.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[1] = out[2];
in[0]=0.0;
in[1]=1.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[2] = out[2];
in[0]=1.0;
in[1]=1.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[3] = out[2];
// Quadratischer Fehler: Wurzel aus { Summe (soll-ist)^2..}
double err = sqrt( (0.0-otest[0])*(0.0-otest[0]) +
(0.0-otest[0])*(0.0-otest[0]) +
(0.0-otest[0])*(0.0-otest[0]) +
(1.0-otest[0])*(1.0-otest[0])
);
cout<<"Fehler dieses Netzes: "<<err<<endl;
return 0;
}#include <iostream>
#include <math.h>
using namespace std;
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
int main(void)
{
double otest[] = {0.0,0.0,0.0,0.0};
double w[] = {-51.82,99.98,-16.26,6.34,45.94,-100.0};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,1.0};
double D=0.1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
in[0]=0.0;
in[1]=0.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[0] = out[2];
in[0]=1.0;
in[1]=0.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[1] = out[2];
in[0]=0.0;
in[1]=1.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[2] = out[2];
in[0]=1.0;
in[1]=1.0;
out[0] = sigmoid(D,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(D,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(D,out[0]*w[4]+out[1]*w[5]);
otest[3] = out[2];
// Quadratischer Fehler: Wurzel aus { Summe (soll-ist)^2..}
double err = sqrt( (0.0-otest[0])*(0.0-otest[0]) +
(0.0-otest[0])*(0.0-otest[0]) +
(0.0-otest[0])*(0.0-otest[0]) +
(1.0-otest[0])*(1.0-otest[0])
);
cout<<"Fehler dieses Netzes: "<<err<<endl;
return 0;
}
Code 0-4: Fehler des Netzes berechnen, das sich wie ein UND-Gatter verhalten soll.
Umsetzung des Netzes als Funktion, ebenfalls Fehler berechnen.
#include <iostream>
#include <math.h>
using namespace std;
double w[] = {-51.82,99.98,-16.26,6.34,45.94,-100.0};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,1.0};
double D=0.1;
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
double netz1(double in0, double in1)
{
in[0]=in0;
in[1]=in1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
out[0] = sigmoid(0.1,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(0.1,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(0.1,out[0]*w[4]+out[1]*w[5]);
return out[2];
}
int main(void)
{
double otest0 = netz1(0.0,0.0);
double otest1 = netz1(0.0,1.0);
double otest2 = netz1(1.0,0.0);
double otest3 = netz1(1.0,1.0);
double err = sqrt( (0.0-otest0)*(0.0-otest0)+
(0.0-otest1)*(0.0-otest1)+
(0.0-otest2)*(0.0-otest2)+
(1.0-otest3)*(1.0-otest3)
);
cout<<"Fehler dieses Netzes: "<<err<<endl;
return 0;
}
Code 0-5: Umsetzung des Netzes als Funlktion, ebenfalls Fehler berechnen.
3. Schritt: Auch die Fehlerberechnung als Funktion
#include <iostream>
#include <math.h>
using namespace std;
double w[] = {-51.82,99.98,-16.26,6.34,45.94,-100.0};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,1.0};
double D=0.1;
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
double netz1(double in0, double in1)
{
in[0]=in0;
in[1]=in1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
out[0] = sigmoid(0.1,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(0.1,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(0.1,out[0]*w[4]+out[1]*w[5]);
return out[2];
}
double berechneFehler()
{
double otest0 = netz1(0.0,0.0);
double otest1 = netz1(0.0,1.0);
double otest2 = netz1(1.0,0.0);
double otest3 = netz1(1.0,1.0);
double err = sqrt( (0.0-otest0)*(0.0-otest0)+
(0.0-otest1)*(0.0-otest1)+
(0.0-otest2)*(0.0-otest2)+
(1.0-otest3)*(1.0-otest3)
);
return err;
}
int main(void)
{
cout<<"Fehler dieses Netzes: "<<berechneFehler()<<endl;
return 0;
}
Code 0-6: 3. Schritt: Auch die Fehlerberechnung als Funktion
4. Schritt: Implementierung des modifizierten Gradientenverfahrens
#include <iostream>
#include <math.h>
#include<cstdlib>
#include<ctime>
#define N 6
using namespace std;
using namespace std;
double w[] = {-51.82,99.98,-16.26,6.34,45.94,-100.0};
double out[] = {0.0,0.0,0.0};
double in[] = {0.0,1.0};
double D=0.1;
double zufall()
{
return (double)(rand()%10000)*0.02-100.0; // Wertebereich: +/-99.99
}
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
double netz1(double in0, double in1)
{
in[0]=in0;
in[1]=in1;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
out[0] = sigmoid(0.1,in[0]*w[0]+in[1]*w[1]);
out[1] = sigmoid(0.1,in[0]*w[2]+in[1]*w[3]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[2] = sigmoid(0.1,out[0]*w[4]+out[1]*w[5]);
return out[2];
}
double berechneFehler()
{
double otest0 = netz1(0.0,0.0);
double otest1 = netz1(0.0,1.0);
double otest2 = netz1(1.0,0.0);
double otest3 = netz1(1.0,1.0);
double err = sqrt( (0.0-otest0)*(0.0-otest0)+
(0.0-otest1)*(0.0-otest1)+
(0.0-otest2)*(0.0-otest2)+
(1.0-otest3)*(1.0-otest3)
);
return err;
}
int main(void)
{
srand(static_cast<unsigned int>(time(0)));
for(int i=0;i<N;i++)
w[i] = zufall();
cout<<"Fehler dieses Netzes: "<<berechneFehler()<<endl;
double err = berechneFehler();
for(int durchgang=0; durchgang<1000000; durchgang++)
{
//1. zufällig ein Gewicht auswählen, das geändert werden soll:
int index = rand()%N;
double wmerker = w[index];
//2. Gewicht größer oder kleiner werden lassen
if(rand()%2==0)
w[index]+=0.001;
else
w[index]-=0.001;
//3. Prüfen, ob das Netz besser geworden ist.
double err_neu = berechneFehler();
//4. wenn es besser geworden ist, so lassen, sonst Änderung rückgängig machen.
if(err_neu<=err)
{
if(err_neu<err)
cout<<err_neu<<endl;
err = err_neu;
}
else
{
w[index] = wmerker;
}
}
cout<<"Optimierte Gewichte: "<<endl;
for(int i=0;i<N;i++)
cout<<w[i]<<","<<endl;
cout<<"Optimierte Gewichte: "<<endl;
for(int i=0;i<N;i++)
cout<<w[i]<<","<<endl;
cout<<"00=>"<<netz1(0.0,0.0)<<endl;
cout<<"01=>"<<netz1(0.0,1.0)<<endl;
cout<<"10=>"<<netz1(1.0,0.0)<<endl;
cout<<"11=>"<<netz1(1.0,1.0)<<endl;
return 0;
}
Code 0-7: 4. Schritt: Implementierung des modifizierten Gradientenverfahrens
... 0.0757367 0.0757367 0.0757367 0.0757367 0.0757354 0.0757354 0.0757354 0.0757354 0.0757354 0.075734 Optimierte Gewichte: -82.867, 161.897, -15.634, 7.167, 83.118, -171.254, 00=>0.0120472 01=>0.0393765 10=>0.0491103 11=>0.959649
Code 0-8: Beispielausgabe.
***** ÜBUNGSAUFGABEN *****
Aufgabe 1 -- Schnee fällt herab....
#include <iostream> //nötig für cin cout
#include <cstring> // nötig für strcpy()
#include <unistd.h> // nötig für usleep
#define ZEILEN 14
using namespace std;
int main(void)
{
char feld[][22] = {
//..........x..........
//012345678901234567890
"* * * * ",
" ",
"* * * * *",
" * ",
" ",
" * * ",
" ",
" * * *",
"* * * *",
" ",
" * *",
" ",
" ",
" * * "
};
int startzeile=0;
int countdown=10;
while(true)
{
cout<<"\033c"; //Reset Terminal
for(int i=ZEILEN;i>=0;i--)
cout<<feld[(i+startzeile)%ZEILEN]<<endl;
startzeile++; //Reihenfolge wandern lassen
usleep(300000);// 300000 Mikrosekunden "schlafen"
countdown--;
if(countdown<=0)
break;
}
return 0;
}
Code 0-9: schneefall.cpp
|
Musterlösung, Schneeflocken zählen
#include <iostream> //nötig für cin cout
#include <cstring> // nötig für strcpy()
#include <unistd.h> // nötig für usleep
#define ZEILEN 14
using namespace std;
int main(void)
{
char feld[][22] = {
//..........x..........
//012345678901234567890
"* * * * ",
" ",
"* * * * *",
" * ",
" ",
" * * ",
" ",
" * * *",
"* * * *",
" ",
" * *",
" ",
" ",
" * * "
};
int startzeile=0;
int countdown=10;
int flockenanzahl=0;
while(true)
{
cout<<"\033c"; //Reset Terminal
for(int i=ZEILEN;i>=0;i--)
cout<<feld[(i+startzeile)%ZEILEN]<<endl;
for(int i=0;i<21;i++)
{
if(feld[startzeile%ZEILEN][i]=='*')
{
flockenanzahl++;
}
}
startzeile++; //Reihenfolge wandern lassen
usleep(300000);// 300000 Mikrosekunden "schlafen"
countdown--;
if(countdown<=0)
break;
}
cout<<"Anzahl der Flocken, die am Boden angekommen sind: "<<flockenanzahl<<endl;
return 0;
}
Code 0-10: Musterlösung, Schneeflocken zählen.
Aufgabe 2 -- Schneeflocken fangen
|
#include <iostream> //nötig für cin cout
#include <cstring> // nötig für strcpy()
#include <unistd.h> // nötig für usleep
#define ZEILEN 14
using namespace std;
int main(void)
{
char feld[][22] = {
//..........x..........
//012345678901234567890
"* * * * ",
" ",
"* * * * *",
" * ",
" ",
" * * ",
" ",
" * * *",
"* * * *",
" ",
" * *",
" ",
" ",
" * * "
};
int startzeile=0;
int countdown=10;
int position=10;
int score=0;
int wechsel[] = {0,0,0,-1,-1,-1,1,1,0,0};
while(true)
{
cout<<"c"; //Reset Terminal
for(int i=ZEILEN;i>=0;i--)
cout<<feld[(i+startzeile)%ZEILEN]<<endl;
for(int i=0;i<position;i++)
cout<<" ";
cout<<"F"<<endl;
if(feld[startzeile%ZEILEN][position]=='*')
score++;
position = position + wechsel[countdown-1];
startzeile++; //Reihenfolge wandern lassen
usleep(300000);// 300000 Mikrosekunden "schlafen"
countdown--;
cout<<"SCORE:"<<score<<" COUNTDOWN:"<<countdown<<endl;
if(countdown<=0)
break;
}
return 0;
}
Code 0-11: schneefall2.cpp
Aufgabe 3 -- Regelbasiertes Handeln
Implementieren Sie die nachfolgenden Verhaltensregeln für den Frosch in der Programmvariante weiter unten und überprüfen Sie, welche Punktezahl Sie einmal mit und ohne Ihre Regeln erreichen:
|
#include <iostream> //nötig für cin cout
#include <cstring> // nötig für strcpy()
#include <unistd.h> // nötig für usleep
#define ZEILEN 14
using namespace std;
int main(void)
{
char feld[][22] = {
//..........x..........
//012345678901234567890
"* * * * ",
" ",
"* * * * *",
" * ",
" ",
" * * ",
" ",
" * * *",
"* * * *",
" ",
" * *",
" ",
" ",
" * * "
};
int startzeile=0;
int countdown=300;
int position=10;
int score=0;
while(true)
{
cout<<"\033c"; //Reset Terminal
for(int i=ZEILEN;i>=0;i--)
cout<<feld[(i+startzeile)%ZEILEN]<<endl;
for(int i=0;i<position;i++)
cout<<" ";
cout<<"F"<<endl;
if(feld[startzeile%ZEILEN][position]=='*')
score++;
//Implementieren Sie in diesem Bereich Ihre Verhaltensregeln des Frosches:
// ...
//ENDE Implementieren Sie in diesem Bereich Ihre Verhaltensregeln des Frosches:
startzeile++; //Reihenfolge wandern lassen
usleep(30000);// 300000 Mikrosekunden "schlafen"
countdown--;
cout<<"SCORE:"<<score<<" COUNTDOWN:"<<countdown<<endl;
if(countdown<=0)
break;
}
return 0;
}
Code 0-12: schneefall3.cpp
Hinweise:
Struktur if / else if / else:
if(...)
{
}
else if(...)
{
}
else if(...)
{
}
...
else
{
}
Inhalt des Arrays zwei Zeilen direkt über dem Frosch:
char inhalt = feld[(startzeile+1)%ZEILEN][position];
Code 0-13: Hinweise zu Aufgabe 3.
Musterlösung zu Aufgabe 3:
//Implementieren Sie in diesem Bereich Ihre Verhaltensregeln des Frosches:
if(feld[(startzeile+1)%ZEILEN][position]=='*')
position = position;
else if(feld[(startzeile+1)%ZEILEN][position+1]=='*')
position = position+1;
else if(feld[(startzeile+1)%ZEILEN][position-1]=='*')
position = position-1;
else
{
if(position>10)
position = position-1;
else if (position<10)
position = position+1;
else
position = position;
}
//ENDE Implementieren Sie in diesem Bereich Ihre Verhaltensregeln des Frosches:
Code 0-14: Musterlösung zu Aufgabe 3 (Nur das, was ergänzt wurde).
Aufgabe 4 -- Neuronales Netz
|
|
#include <iostream> // nötig für cin cout
#include <cstring> // nötig für strcpy()
#include <unistd.h> // nötig für usleep()
#include <math.h> // nötig für sqrt()
#include <ctime> // nötig für Initialisierung der Pseudozufallsfolge
#define ZEILEN 14
#define N 16
using namespace std;
double w[16]; // 3*4+4 = 16
double out[] = {0.0,0.0,0.0,0.0,0.0};
double in[] = {0.0,0.0,0.0};
double D=0.1;
double zufall()
{
return (double)(rand()%10000)*0.02-100.0; // Wertebereich: +/-99.99
}
double sigmoid(double d, double u)
{
double x = 1.0/(1.0+exp(-d*u));
return x;
}
double netz2(double in0, double in1, double in2)
{
in[0]=in0;
in[1]=in1;
in[2]=in2;
//Berechnung der Ausgänge der Eingangsneuronenschicht:
out[0] = sigmoid(0.1,in[0]*w[0]+in[1]*w[1]+in[2]*w[2]);
out[1] = sigmoid(0.1,in[0]*w[3]+in[1]*w[4]+in[2]*w[5]);
out[2] = sigmoid(0.1,in[0]*w[6]+in[1]*w[7]+in[2]*w[8]);
out[3] = sigmoid(0.1,in[0]*w[9]+in[1]*w[10]+in[2]*w[11]);
//Berechnung der Ausgänge der Ausgangsneuronenschicht:
out[4] = sigmoid(0.1,out[0]*w[12]+out[1]*w[13]+out[2]*w[14]+out[3]*w[15]);
return out[2];
}
int main(void)
{
srand(static_cast<unsigned int>(time(0)));
//srand(2); //Immer die gleichen "Zufallsgewichte"
for(int i=0;i<N;i++)
w[i] = zufall();
int BESTSCORE = 0;
for(int DURCHLAUF=0;DURCHLAUF<10000;DURCHLAUF++)
{
char feld[][22] = {
//..........x..........
//012345678901234567890
"* * * * ",
" ",
"* * * * *",
" * ",
" ",
" * * ",
" ",
" * * *",
"* * * *",
" ",
" * *",
" ",
" ",
" * * "
};
int startzeile=0;
int countdown=300;
int position=10;
int score=0;
//Optimierungsprozess Teil 1:
int index = rand()%N;
double wmerker = w[index];
//2. Gewicht größer oder kleiner werden lassen
w[index]=zufall();
//ENDE Optimierungsprozess Teil 1.
while(true)
{
/*
cout<<"\033c"; //Reset Terminal
for(int i=ZEILEN;i>=0;i--)
cout<<feld[(i+startzeile)%ZEILEN]<<endl;
for(int i=0;i<position;i++)
cout<<" ";
cout<<"F"<<endl;
*/
if(feld[startzeile%ZEILEN][position]=='*')
score++;
double input[] = {0.0,0.0,0.0};
if(feld[(startzeile+1)%ZEILEN][position]=='*')
input[1]=1.0;
if(position>0 && feld[(startzeile+1)%ZEILEN][position-1]=='*')
input[0]=1.0;
if(position<20 && feld[(startzeile+1)%ZEILEN][position+1]=='*')
input[2]=1.0;
double output = netz2(input[0],input[1],input[2]);
if(output<0.25 && position>0)
position--;
else if(output>0.75 && position<20)
position++;
if(position>=21)
position=0;
startzeile++; //Reihenfolge wandern lassen
// usleep(30000);// 300000 Mikrosekunden "schlafen"
countdown--;
// cout<<"SCORE:"<<score<<" COUNTDOWN:"<<countdown<<endl;
if(countdown<=0)
break;
}
//cout<<"DURCHLAUF:"<<DURCHLAUF<<" SCORE:"<<score<<endl;
//Optimierungsprozess Teil 2:
//3. Prüfen, ob das Netz besser geworden ist.
if(score>=BESTSCORE)
{
if(score>BESTSCORE)
cout<<"DURCHLAUF:"<<DURCHLAUF<<" SCORE:"<<score<<endl;
BESTSCORE=score;
}
else
{
w[index] = wmerker;
}
//ENDE Optimierungsprozess Teil 2
}//for DURCHLAUF
return 0;
}
Code 0-15: schneefall4.cpp
Aufgabe 5
|