Lösung Aufgabe 3b
#include <stdlib.h> #include <math.h> #define MAXSCHRITTE 100000.00 #define ANZAHLNEURONEN 16 #define SIGMOID_K 3 double gewicht[ANZAHLNEURONEN][ANZAHLNEURONEN]; double delta[ANZAHLNEURONEN]; double output[ANZAHLNEURONEN]; double input[ANZAHLNEURONEN]; void * ausgabefunktionen[ANZAHLNEURONEN]; eingabe_function(int i) /* fuer die zellen mit eingabe, kopieren auf die ausgabe */ { output[i] = input[i]; } sigmoid_ausgabefunction(int i) { output[i] = 1.0 / (1.0 + exp(-SIGMOID_K * input[i])) ; } oneloop() { int i,j; double erg; for (i=0;i<ANZAHLNEURONEN;i++) { for (erg=0.0,j=0;j<ANZAHLNEURONEN;j++) erg += gewicht[j][i]*output[j]; input[i] = erg; } /* neue eingaben sind bekannt */ for (i=0;i<ANZAHLNEURONEN;i++) { int (*f)() = ausgabefunktionen[i]; f(i); } } init_random_exor_netz() { // zwei eingaben 0,1 // drei erste ebene 2,3,4 // drei zweite ebene 5,6,7 // eine ausgabe 8 // drei schwellwerte erste ebene 9,10,11 // drei schwellwerte zweite ebene 12,13,14 // ein schwellwert ausgabe 15 int i; srand48(getpid()); // initialisieren der zufallswerte gewicht[0][2]=drand48(); gewicht[0][3]=drand48(); gewicht[0][4]=drand48(); gewicht[1][2]=drand48(); gewicht[1][3]=drand48(); gewicht[1][4]=drand48(); gewicht[2][5]=drand48(); gewicht[2][6]=drand48(); gewicht[2][7]=drand48(); gewicht[3][5]=drand48(); gewicht[3][6]=drand48(); gewicht[3][7]=drand48(); gewicht[4][5]=drand48(); gewicht[4][6]=drand48(); gewicht[4][7]=drand48(); gewicht[5][8]=drand48(); gewicht[6][8]=drand48(); gewicht[7][8]=drand48(); // fuer die schwellwerte gewicht[9][2]=drand48(); gewicht[10][3]=drand48(); gewicht[11][4]=drand48(); gewicht[12][5]=drand48(); gewicht[13][6]=drand48(); gewicht[14][7]=drand48(); gewicht[15][8]=drand48(); for (i=0;i<2;i++) gewicht[i][i]=1.0; // fuer eingabe for (i=9;i<16;i++) gewicht[i][i]=1.0; // fuer schwellwerte for (i=9;i<16;i++) output[i]=1.0; // fuer schwellwerte for (i=0;i<2;i++) ausgabefunktionen[i] = (void *)eingabe_function; // fuer eingabe for (i=9;i<16;i++) ausgabefunktionen[i] = (void *)eingabe_function; // fuer schwellwerte for (i=2;i<9;i++) ausgabefunktionen[i] = (void *)sigmoid_ausgabefunction; // fuer neuronen } printnetz() { int i; printf("i:");for (i=0;i<ANZAHLNEURONEN;i++) printf("%2.2f ",input[i]); printf("\n"); printf("o:");for (i=0;i<ANZAHLNEURONEN;i++) printf("%2.2f ",output[i]); printf("\n"); /* printf("g:"); printf("0-2:%2.2f 0-3:%2.2f 0-4:%2.2f 1-2:%2.2f 1-3:%2.2f", gewicht[0][2], gewicht[0][3], gewicht[0][4], gewicht[1][2], gewicht[1][3] ); printf(" 1-4:%2.2f 2-5:%2.2f 2-6:%2.2f 2-7:%2.2f 3-5:%2.2f", gewicht[1][4], gewicht[2][5], gewicht[2][6], gewicht[2][7], gewicht[3][5]); printf(" 3-6:%2.2f 3-7:%2.2f 4-5:%2.2f 4-6:%2.2f 4-7:%2.2f", gewicht[3][6], gewicht[3][7], gewicht[4][5], gewicht[4][6], gewicht[4][7]); printf(" 5-8:%2.2f 6-8:%2.2f 7-8:%2.2f \n", gewicht[5][8], gewicht[6][8], gewicht[7][8]); printf("sw: %2.2f %2.2f %2.2f %2.2f %2.2f %2.2f %2.2f \n", gewicht[9][2], gewicht[10][3], gewicht[11][4], gewicht[12][5], gewicht[13][6], gewicht[14][7], gewicht[15][8]); */ } back() // gewichte zuletzt ändern { float soll; static int loopcounter =1; float eta; float temp; eta = 1.0 - loopcounter++/MAXSCHRITTE; if (input[0] == input[1]) soll = 0.0; else soll = 1.0; // zuerst die ausgabewerte delta[8] = SIGMOID_K * output[8] * (1.0 - output[8] )*(soll - output[8]); // nun level 1 delta[7] = SIGMOID_K * output[7]*(1.0 - output[7]) * delta[8] * gewicht[7][8]; delta[6] = SIGMOID_K * output[6]*(1.0 - output[6]) * delta[8] * gewicht[6][8]; delta[5] = SIGMOID_K * output[5]*(1.0 - output[5]) * delta[8] * gewicht[5][8]; // level 2 temp = delta[7] * gewicht[2][7] + delta [6] * gewicht[2][6] + delta [5]*gewicht[2][5]; delta[2] = SIGMOID_K * output[2] *(1.0 - output[2]) * temp; temp = delta[7] * gewicht[3][7] + delta [6] * gewicht[3][6] + delta [5]*gewicht[3][5]; delta[3] = SIGMOID_K * output[3]* (1.0 - output[3]) * temp; temp = delta[7] * gewicht[4][7] + delta [6] * gewicht[4][6] + delta [5]*gewicht[4][5]; delta[4] = SIGMOID_K * output[4]* (1.0 - output[4]) * temp; gewicht[5][8] += eta*delta[8]*output[5]; gewicht[6][8] += eta*delta[8]*output[6]; gewicht[7][8] += eta*delta[8]*output[7]; gewicht[15][8] += eta*delta[8]*output[15]; gewicht[2][7] += eta*delta[7]*output[2]; gewicht[3][7] += eta*delta[7]*output[3]; gewicht[4][7] += eta*delta[7]*output[4]; gewicht[14][7] += eta*delta[7]*output[14]; gewicht[2][6] += eta*delta[6]*output[2]; gewicht[3][6] += eta*delta[6]*output[3]; gewicht[4][6] += eta*delta[6]*output[4]; gewicht[13][6] += eta*delta[6]*output[13]; gewicht[2][5] += eta*delta[5]*output[2]; gewicht[3][5] += eta*delta[5]*output[3]; gewicht[4][5] += eta*delta[5]*output[4]; gewicht[12][5] += eta*delta[5]*output[12]; gewicht[0][2] += eta*delta[2]*output[0]; gewicht[1][2] += eta*delta[2]*output[1]; gewicht[9][2] += eta*delta[2]*output[9]; gewicht[0][3] += eta*delta[3]*output[0]; gewicht[1][3] += eta*delta[3]*output[1]; gewicht[10][3] +=eta*delta[3]*output[10]; gewicht[0][4] += eta*delta[4]*output[0]; gewicht[1][4] +=eta*delta[4]*output[1]; gewicht[11][4] += eta*delta[4]*output[11]; } onestep() { double d = drand48()*4.0; if (d < 1.0) { output[0]=0.0; output[1]=0.0; } else if (d < 2.0) { output[0]=1.0; output[1]=0.0; } else if (d < 3.0) { output[0]=1.0; output[1]=1.0; } else { output[0]=0.0; output[1]=1.0; } oneloop(); oneloop(); oneloop(); printf("i0:%f i1:%f o8:%f\n",input[0],input[1],output[8]); back(); } main() { int i=1; init_random_exor_netz(); while(i++ < MAXSCHRITTE) onestep(); }