home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume14
/
back-prop
/
part04
/
int.c
next >
Wrap
C/C++ Source or Header
|
1990-09-15
|
14KB
|
471 lines
/* *********************************************************** */
/* file int.c: Contains the network evaluation and weight */
/* adjustment procedures for the integer versions */
/* bp and sbp. */
/* */
/* Copyright (c) 1990 by Donald R. Tveter */
/* */
/* The code here has been optimized for use with the Motorola */
/* MC 68010 processor and version 3.5 of the UNIX (tm) PC */
/* C compiler where UNIX is a trademark of Bell Laboratories. */
/* *********************************************************** */
#include "ibp.h"
#include <stdio.h>
extern WTTYPE alpha;
extern char backprop;
extern WTTYPE D;
extern WTTYPE decay;
extern char deriv;
extern WTTYPE eta;
extern WTTYPE eta2;
extern WTTYPE etamax;
extern WTTYPE kappa;
extern LAYER *last;
extern LAYER *start;
extern WTTYPE theta1;
extern WTTYPE theta2;
extern WTTYPE toler;
extern int totaldiff;
extern char update;
void forward() /* computes unit activations */
{
register WTNODE *w;
register UNIT *u;
register UNIT *predu;
LAYER *layer;
register int sum;
register int x;
register short fract;
register short val;
register int intpart;
layer = start->next;
while (layer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
sum = 0;
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
predu = (UNIT *) w->backunit;
#ifdef SMART
# ifdef SYMMETRIC
sum = sum + (*(w->weight) * predu->oj) / 1024;
# else
sum = sum + (w->weight * predu->oj) / 1024;
# endif
#else
# ifdef SYMMETRIC
x = (*(w->weight) * predu->oj);
# else
x = w->weight * predu->oj;
# endif
if (x >= 0) sum = sum + (x >> 10);
else sum = sum - ( (-x) >> 10);
#endif
w = w->next;
};
sum = (D * sum) / 1024;
if (sum > 0) x = sum; else x = -sum;
intpart = x >> 10;
fract = x - (intpart << 10);
switch (intpart)
{
case 0: val = 512 + ((237 * fract) >> 10); /* 0 <= x < 1 */
break;
case 1: val = 748 + ((153 * fract) >> 10); /* 1 <= x < 2 */
break;
case 2: val = 901 + ((73 * fract) >> 10); /* 2 <= x < 3 */
break;
case 3:
case 4: val = 976 + (((x - 3072) * 20) >> 10); /* 3 <= x < 5 */
break;
default: val = 1024; /* x >= 5 */
};
if (sum < 0) u->oj = 1024 - val; else u->oj = val;
u = u->next;
};
layer = layer->next;
};
};
short backoutput() /* computes weight changes from the output layer */
{
register short deltaj;
register int temp;
register short temp2;
register short temp3;
register short adiff;
register UNIT *bunit;
register WTNODE *w;
register UNIT *u;
register PATNODE *t;
register short notclose;
notclose = last->unitcount;
u = (UNIT *) last->units;
t = (PATNODE *) last->currentpat->pats;
while (u != NULL)
{
temp3 = u->oj;
temp2 = t->val - temp3;
if (temp2 > 0) adiff = temp2; else adiff = -temp2;
if (adiff < toler) notclose = notclose - 1;
totaldiff = totaldiff + adiff;
if (adiff >= toler || backprop) /* then compute errors */
{
if (deriv == 'd') /* diff. step size method */
deltaj = temp2;
else if (deriv == 'f') /* Fahlman's derivative */
{
temp = temp2 * (104448 + temp3 * ((short)(1024 - temp3)));
if (temp > 0) deltaj = (temp + 524288) >> 20;
else deltaj = -((524288 - temp) >> 20);
}
else /* the derivative in the original formula */
{
temp = temp2 * (temp3 * ((short)(1024 - temp3)));
if (temp > 0) deltaj = (temp + 524288) >> 20;
else deltaj = -((524288 - temp) >> 20);
}
w = (WTNODE *) u->wtlist;
#ifdef SYMMETRIC
while (w->next != NULL) /* skips threshold unit at end */
#else
while (w != NULL)
#endif
{
bunit = (UNIT *) w->backunit;
#ifdef SYMMETRIC
*(w->total) = *(w->total) + deltaj * bunit->oj;
#else
w->total = w->total + deltaj * bunit->oj;
if (bunit->layernumber > 1)
bunit->error = bunit->error + deltaj * w->weight;
#endif
w = w->next;
}
};
u = u->next;
t = t->next;
};
return(notclose);
}
#ifndef SYMMETRIC
void backinner() /* Computes slopes and passes back */
{ /* errors from hidden layers. */
register short deltaj;
register int temp;
register short temp3;
register UNIT *bunit;
register WTNODE *w;
register UNIT *u;
LAYER *layer;
layer = last->backlayer;
while (layer->backlayer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
temp3 = u->oj;
if (deriv == 'f') /* Fahlman's derivative */
temp = (((short)((temp3*((short)(1024-temp3))+512) >> 10))
+ 102) * u->error;
else /* either for the original or diff. step size */
temp = ((short)((temp3*((short)(1024-temp3))+512) >> 10))
* u->error;
if (temp > 0) deltaj = (temp + 524288) >> 20;
else deltaj = -((524288 - temp) >> 20);
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
bunit = (UNIT *) w->backunit;
w->total = w->total + deltaj * bunit->oj;
if (bunit->layernumber > 1)
bunit->error = bunit->error + deltaj * w->weight;
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
#endif
void updatej() /* Jacob's delta-bar-delta method for weight updates */
{
register short rkappa;
register short temp2;
register short dbarm1;
register short rdecay;
register int temp;
register UNIT *u;
register WTNODE *w;
LAYER *layer;
/* w->olddw is used for delta-bar minus 1 */
rkappa = kappa;
rdecay = decay;
layer = last;
while (layer->backlayer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
#ifdef SYMMETRIC
if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
{
if (*(w->total) > 0) temp2 = (*(w->total) + 512) >> 10;
else temp2 = -((512 - *(w->total)) >> 10);
dbarm1 = *(w->olddw);
temp = theta2 * temp2 + theta1 * dbarm1;
if (temp > 0) *(w->olddw) = (temp + 512) >> 10;
else *(w->olddw) = -((512 - temp) >> 10);
if ((temp2 > 0) && (dbarm1 > 0))
*(w->eta) = *(w->eta) + rkappa;
else if ((temp2 < 0) && (dbarm1 < 0))
*(w->eta) = *(w->eta) + rkappa;
else if ((temp2 > 0) && (dbarm1 < 0))
*(w->eta) = (*(w->eta) * rdecay) >> 10;
else if ((temp2 < 0) && (dbarm1 > 0))
*(w->eta) = (*(w->eta) * rdecay) >> 10;
if (*(w->eta) > etamax) *(w->eta) = etamax;
temp = temp2 * *(w->eta);
if (temp > 0) temp2 = (temp + 512) >> 10;
else temp2 = -((512 - temp) >> 10);
*(w->weight) = *(w->weight) + temp2;
};
#else
if (w->total > 0) temp2 = (w->total + 512) >> 10;
else temp2 = -((512 - w->total) >> 10);
dbarm1 = w->olddw;
temp = theta2 * temp2 + theta1 * dbarm1;
if (temp > 0) w->olddw = (temp + 512) >> 10;
else w->olddw = -((512 - temp) >> 10);
if (temp2 > 0 && dbarm1 > 0) w->eta = w->eta + rkappa;
else if (temp2 < 0 && dbarm1 < 0) w->eta = w->eta + rkappa;
else if (temp2 > 0 && dbarm1 < 0)
w->eta = (w->eta * rdecay) >> 10;
else if (temp2 < 0 && dbarm1 > 0)
w->eta = (w->eta * rdecay) >> 10;
if (w->eta > etamax) w->eta = etamax;
temp = temp2 * w->eta;
if (temp > 0) temp2 = (temp + 512) >> 10;
else temp2 = -((512 - temp) >> 10);
w->weight = w->weight + temp2;
#endif
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
void updateo() /* update weights for the original method */
{ /* and the differential step size algorithm */
register short reta;
register short ralpha;
register int temp;
register UNIT *u;
register WTNODE *w;
LAYER *layer;
ralpha = alpha;
reta = eta;
layer = last;
while (layer->backlayer != NULL)
{
if (layer != last && update == 'd') reta = eta2;
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
#ifdef SYMMETRIC
if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
{
if (*(w->total) > 0)
temp = ((*(w->total) + 512) >> 10) * reta
+ ralpha * *(w->olddw);
else temp = -((512 - *(w->total)) >> 10) * reta
+ ralpha * *(w->olddw);
if (temp > 0) *(w->olddw) = (temp + 512) >> 10;
else *(w->olddw) = -((512 - temp) >> 10);
*(w->weight) = *(w->weight) + *(w->olddw);
};
#else
if (w->total > 0)
temp = ((w->total + 512) >> 10) * reta + ralpha * w->olddw;
else
temp = -((512 - w->total) >> 10) * reta + ralpha * w->olddw;
if (temp > 0) w->olddw = (temp + 512) >> 10;
else w->olddw = -((512 - temp) >> 10);
w->weight = w->weight + w->olddw;
#endif
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
short cbackoutput() /* The continuous update version */
{ /* of back-propagation */
register short deltaj;
register int etadeltaj;
register int temp;
register int temp2;
register short temp3;
register short adiff;
register UNIT *bunit;
register WTNODE *w;
register UNIT *u;
register PATNODE *t;
register short ralpha;
register short notclose;
ralpha = alpha;
notclose = last->unitcount;
u = (UNIT *) last->units;
t = (PATNODE *) last->currentpat->pats;
while (u != NULL)
{
temp3 = u->oj;
temp2 = t->val - temp3;
if (temp2 > 0) adiff = temp2; else adiff = -temp2;
if (adiff < toler) notclose = notclose - 1;
totaldiff = totaldiff + adiff;
if (adiff >= toler || backprop)
{
if (deriv == 'd') /* the differential step size method */
deltaj = temp2;
else if (deriv == 'f') /* Fahlman's derivative */
{ /* deltaj = (t->val - u->oj) * [0.1 + u->oj*(1.0 - u->oj)] */
temp = temp2 * (104448 + temp3 * ((short)(1024 - temp3)));
if(temp > 0) deltaj = (temp + 524288) >> 20;
else deltaj = -((524288 - temp) >> 20);
}
else /* the original derivative */
{ /* deltaj = (t->val - u->oj) * u->oj * (1.0 - u->oj) */
temp = temp2 * (temp3 * ((short)(1024 - temp3)));
if(temp > 0) deltaj = (temp + 524288) >> 20;
else deltaj = -((524288 - temp) >> 20);
};
etadeltaj = deltaj * eta;
w = (WTNODE *) u->wtlist;
#ifdef SYMMETRIC
while (w->next != NULL)
#else
while (w != NULL)
#endif
{ /* get a slope for each weight */
bunit = (UNIT *) w->backunit;
temp = etadeltaj * bunit->oj;
if(temp > 0) temp = (temp + 524288) >> 20;
else temp = -((524288 - temp) >> 20);
#ifdef SYMMETRIC
temp2 = ralpha * *(w->olddw);
#else
temp2 = ralpha * w->olddw;
#endif
if (temp2 > 0) temp3 = temp + ((temp2 + 512) >> 10);
else temp3 = temp - ((512 - temp2) >> 10);
#ifdef SYMMETRIC
*(w->olddw) = temp3;
#else
w->olddw = temp3;
#endif
/* w->weight = w->weight + w->olddw */
#ifdef SYMMETRIC
temp3 = *(w->weight) + temp3;
*(w->weight) = temp3;
#else
temp3 = w->weight + temp3;
w->weight = temp3;
if (bunit->layernumber > 1)
bunit->error = bunit->error + deltaj * temp3;
#endif
w = w->next;
}
}
u = u->next;
t = t->next;
}
return(notclose);
}
#ifndef SYMMETRIC
void cbackinner() /* Same as cbackoutput, except errors are */
{ /* calculated differently */
register short deltaj;
register int etadeltaj;
register int temp;
register int temp2;
register short temp3;
register short reta;
register short ralpha;
register UNIT *bunit;
register WTNODE *w;
register UNIT *u;
LAYER *layer;
if (update == 'C') reta = eta2; else reta = eta;
ralpha = alpha;
layer = last->backlayer;
while (layer->backlayer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
temp3 = u->oj;
if (deriv == 'f') /* Fahlman's derivative */
temp = (((temp3 * ((short)(1024 - temp3)) + 512) >> 10) + 102)
* u->error;
else /* diff. step size and original derivative */
temp = ((temp3 * ((short)(1024 - temp3)) + 512) >> 10)
* u->error;
if (temp > 0) deltaj = (temp + 524288) >> 20;
else deltaj = -((524288 - temp) >> 20);
etadeltaj = reta * deltaj;
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
bunit = (UNIT *) w->backunit;
temp = etadeltaj * bunit->oj;
if (temp > 0) temp = (temp + 524288) >> 20;
else temp = -((524288 - temp) >> 20);
temp2 = ralpha * w->olddw;
if (temp2 > 0) temp3 = temp + ((temp2 + 512) >> 10);
else temp3 = temp - ((512 - temp2) >> 10);
w->olddw = temp3;
temp3 = w->weight + temp3;
w->weight = temp3;
if (bunit->layernumber > 1)
bunit->error = bunit->error + deltaj * temp3;
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
#endif