Listing des Programms BACKPRO2.C
/* Programm backpro2.c */
/* 3-Schicht-Netz mit Werbos Backpropagation-Lernregel */
/* --- Spezielle Version fuer Standardbeispiel --- */
/* Burkhard Lenze */
/* 13.02.2009 */
/* header-files */
#include <stdio.h>
#include <math.h>
#include "backpro2.h"
/* globale Variablen */
float x[5][500]; /* Eingabevektorfeld */
float y[5][500]; /* Ausgabevektorfeld */
float theta[30]; /* Schwellwertvektorfeld */
float w[30][30]; /* Matrixfeld der Eingangsgewichte */
float g[30][30]; /* Matrixfeld der Ausgangsgewichte */
float x_test[5]; /* Aktueller Testeingang */
float y_test[5]; /* Aktueller Testausgang */
int n=2; /* Anzahl der Eingabe-Neuronen */
int q; /* Anzahl der verborgenen Neuronen */
int m=1; /* Anzahl der Ausgabe-Neuronen */
int Pxy; /* Anzahl der x-y-Abtastpunkte */
int t; /* Anzahl der Assoziationen (t=Pxy*Pxy) */
int s; /* Anzahl der Trainingszyklen */
int s_max; /* Maximalzahl der Trainingszyklen */
float epsilon; /* Maximaler Ausgabefehler */
float beta; /* Stauchungsparameter */
float lambda; /* Lernrate */
char com; /* Menuparameter */
/* Funktionen */
void lese_x_test(void)
{
int i;
printf("\n");
for (i=1;i<=n;i++)
{
printf("x[%1d] = ? ",i);
scanf("%f",&x_test[i]);
}
}
float f(float x1, float x2)
{
float Z;
Z=1.0;
if (x1+x2>=1.5) {Z=0.0;}
if ((x1<=0.5)&&(x2<=0.25)) {Z=0.0;}
return(Z);
}
void lese_x_y(void)
{
int k,l,ss;
for (l=1;l<=Pxy;l++)
{
for (k=1;k<=Pxy;k++)
{
ss=(l-1)*Pxy+k;
x[1][ss]=(k-1.0)/(Pxy-1.0);
x[2][ss]=(l-1.0)/(Pxy-1.0);
y[1][ss]=f((k-1.0)/(Pxy-1.0),(l-1.0)/(Pxy-1.0));
}
}
}
float T(float A)
{
float Z;
Z=1.0/(1.0+exp(-(beta*A)));
return(Z);
}
float TS(float A)
{
float Z;
Z=(beta*exp(-(beta*A)))/((1.0+exp(-(beta*A)))*(1.0+exp(-(beta*A))));
return(Z);
}
void lernen(void)
{
int i,j,p,st,z;
float A[30],B[30],C[30],y_[10],H,err;
lese_x_y();
s=0;
do
{
s=s+1;
for (st=1;st<=t;st++)
{
for (p=1;p<=q;p++)
{
H=0.0;
for (i=1;i<=n;i++) {H=H+(w[i][p]*x[i][st]);}
A[p]=T(H-theta[p]);
B[p]=TS(H-theta[p]);
}
for (j=1;j<=m;j++)
{
y_[j]=0.0;
for (p=1;p<=q;p++) {y_[j]=y_[j]+g[p][j]*A[p];}
}
for (p=1;p<=q;p++)
{
C[p]=0.0;
for (j=1;j<=m;j++) {C[p]=C[p]+(y[j][st]-y_[j])*g[p][j];}
}
for (j=1;j<=m;j++)
{
for (p=1;p<=q;p++)
{
g[p][j]=g[p][j]+lambda*2.0*(y[j][st]-y_[j])*A[p];
}
}
for (p=1;p<=q;p++)
{
for (i=1;i<=n;i++)
{
w[i][p]=w[i][p]+lambda*2.0*C[p]*B[p]*x[i][st];
}
theta[p]=theta[p]-lambda*2.0*C[p]*B[p];
}
}
err=0.0;
for (st=1;st<=t;st++)
{
for (j=1;j<=m;j++)
{
y_[j]=0.0;
for (p=1;p<=q;p++)
{
H=0.0;
for (i=1;i<=n;i++) {H=H+(w[i][p]*x[i][st]);}
y_[j]=y_[j]+g[p][j]*T(H-theta[p]);
}
err=err+(y[j][st]-y_[j])*(y[j][st]-y_[j]);
}
}
z=1;
if ((s_max/100)>=1) {z=s_max/100;}
if (s%z==0)
{
printf("\nEs wurden bereits %8d Lernzyklen durchlaufen! ",s);
printf("\nDer summierte quadrierte Fehler lautet: %f ",err);
}
if (err<epsilon)
{
printf("\n\nEs wurden genau %8d Lernzyklen durchlaufen! ",s);
printf("\nDer summierte quadrierte Fehler lautet: %f ",err);
printf("\n\nFehler kleiner als %f !!!\n",epsilon);
printf("\n\nAbbruch des Lernalgorithmus !!!\n");
}
if (s==s_max)
{
printf("\n\nEs wurden genau %8d Lernzyklen durchlaufen! ",s);
printf("\nDer summierte quadrierte Fehler lautet immer noch: %f ",err);
printf("\n\nAbbruch des Lernalgorithmus !!!\n");
}
}
while ((err>=epsilon)&&(s!=s_max));
}
void ausfuehren(void)
{
int i,j,p;
float H;
lese_x_test();
for (j=1;j<=m;j++)
{
y_test[j]=0.0;
for (p=1;p<=q;p++)
{
H=0.0;
for (i=1;i<=n;i++) {H=H+(w[i][p]*x_test[i]);}
y_test[j]=y_test[j]+g[p][j]*T(H-theta[p]);
}
}
printf("\n");
for (j=1;j<=m;j++) {printf("y[%1d] = %8.4f\n",j,y_test[j]);}
}
void veraendern(void)
{
int i,j,p;
s=0;
printf("\n");
printf("\nAnzahl n der Neuronen in der Eingabeschicht lautet %2d . ",n);
printf("\nAnzahl m der Neuronen in der Ausgabeschicht lautet %2d . ",m);
printf("\nAnzahl q der Neuronen in der verborgenen Schicht ? ");
scanf("%d",&q);
printf("Anzahl Pxy der x-y-Abtastpunkte (ergibt Pxy*Pxy Assoziationen) ? ");
scanf("%d",&Pxy);
t=Pxy*Pxy;
printf("Stauchungsparameter beta der Transferfunktion ? ");
scanf("%f",&beta);
printf("Lernrate lambda mit der iteriert werden soll ? ");
scanf("%f",&lambda);
printf("Anzahl s_max der maximal zu durchlaufenden Lernzyklen ? ");
scanf("%d",&s_max);
printf("Zu unterschreitender maximaler Fehler epsilon ? ");
scanf("%f",&epsilon);
for (i=1;i<=n;i++) {x[i][0]=0.0;}
for (j=1;j<=m;j++) {y[j][0]=0.0;}
for (p=1;p<=q;p++)
{
for (i=1;i<=n;i++) {w[i][p]=0.0;}
theta[p]=0.0;
}
for (j=1;j<=m;j++)
{
for (p=1;p<=q;p++) {g[p][j]=0.0;}
}
}
void zeigen(void)
{
int i,j,p;
printf("\nDie Gewichte w[i][p] lauten nach %8d Lernzyklen: \n",s);
for (p=1;p<=q;p++)
{
for (i=1;i<=n;i++)
{
printf("w[%1d][%1d]=%8.4f ",i,p,w[i][p]);
}
printf("\n");
}
printf("\nDie Schwellwerte theta[p] lauten nach %8d Lernzyklen: \n",s);
for (p=1;p<=q;p++)
{
printf("theta[%1d] = %8.4f\n",p,theta[p]);
}
printf("\nDie Gewichte g[p][j] lauten nach %8d Lernzyklen: \n",s);
for (j=1;j<=m;j++)
{
for (p=1;p<=q;p++)
{
printf("g[%1d][%1d]=%8.4f\n",p,j,g[p][j]);
}
printf("\n");
}
}
void speichern(void)
{
int i,j,p;
FILE *f;
char dat[20];
printf("\nWie lautet die Datei mit den Gewichten und Schwellwerten ? ");
scanf("%s",&dat);
f=fopen(dat,"w");
fprintf(f,"%d\n",n);
fprintf(f,"%d\n",q);
fprintf(f,"%d\n",m);
for (p=1;p<=q;p++)
{
for (i=1;i<=n;i++) {fprintf(f,"%f\n",w[i][p]);}
}
for (p=1;p<=q;p++) {fprintf(f,"%f\n",theta[p]);}
for (j=1;j<=m;j++)
{
for (p=1;p<=q;p++) {fprintf(f,"%f\n",g[p][j]);}
}
fclose(f);
}
void einlesen(void)
{
int i,j,p,r;
FILE *f;
char dat[20];
s=0;
printf("\nWie lautet die Datei mit den Gewichten und Schwellwerten ? ");
scanf("%s",&dat);
f=fopen(dat,"r");
fscanf(f,"%d",&r);
if (r==n)
{
fscanf(f,"%d",&r);
if (r==q)
{
fscanf(f,"%d",&r);
if (r==m)
{
for (p=1;p<=q;p++)
{
for (i=1;i<=n;i++) {fscanf(f,"%f",&w[i][p]);}
}
for (p=1;p<=q;p++) {fscanf(f,"%f",&theta[p]);}
for (j=1;j<=m;j++)
{
for (p=1;p<=q;p++) {fscanf(f,"%f",&g[p][j]);}
}
}
else
{
printf("\nFehler! m ist in Datei %2d statt %2d \n",r,m);
}
}
else
{
printf("\nFehler! q ist in Datei %2d statt %2d \n",r,q);
}
}
else
{
printf("\nFehler! n ist in Datei %2d statt %2d\n",r,n);
}
fclose(f);
}
/* Hauptprogramm */
int main(void)
{
veraendern();
do
{
printf("\nlernen ausfuehren zeigen veraendern speichern einlesen beenden:\n");
fflush(stdin);
scanf("%c",&com);
switch(com)
{
case 'l': lernen(); break;
case 'a': ausfuehren(); break;
case 'z': zeigen(); break;
case 'v': veraendern(); break;
case 's': speichern(); break;
case 'e': einlesen(); break;
default: break;
}
}
while (com!='b');
return(0);
}
Burkhard Lenze
Im Februar 2009