www.pudn.com > BPËã·¨Ô´Âë.zip > int.c
/* *********************************************************** */
/* file int.c: Contains the network evaluation and weight */
/* adjustment procedures for the integer versions */
/* bp and sbp. */
/* */
/* Copyright (c) 1993 by Donald R. Tveter */
/* */
/* *********************************************************** */
#ifdef INTEGER
#include "ibp.h"
#else
#include "rbp.h"
#endif
extern char deriv, whittled, wtlimithit, zeroderiv;
extern char outstr[OUTSTRSIZE];
extern WTTYPE alpha, decay, eta, eta2, etamax, kappa, qpeta;
extern WTTYPE qpnoise, mu, noise, theta1, theta2, toler;
extern WTTYPE rpaccel, rpdecay, rpinitial, rpdeltamax, rpdeltamin;
extern WTTYPE ssaccel, ssdecay, sseta, ssetamax, ssmo;
extern char qpslope;
extern LAYER *last, *start;
extern INT32 totaldiff;
extern REAL qpdecayh, qpdecayo;
extern REAL unscale();
#ifdef LOOKUP
extern WTTYPE sigmoid[];
#endif
void forward() /* computes unit activations */
{
register INT32 sum;
register WTNODE *w;
register UNIT *predu, *u;
LAYER *layer;
register INT32 x, intpart;
register short fract, val;
char actfun;
WTTYPE D;
int denom;
double rsum;
layer = start->next;
while (layer != NULL)
{
actfun = layer->activation;
D = layer->D;
u = (UNIT *) layer->units;
while (u != NULL)
{
sum = 0;
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
predu = (UNIT *) w->backunit;
#ifdef SYMMETRIC
sum = sum + (INT32) *(w->weight) * predu->oj / 1024;
#else
sum = sum + (INT32) w->weight * predu->oj / 1024;
#endif
w = w->next;
};
sum = D * sum / 1024;
#ifdef LOOKUP
if (actfun == 's')
{
if (sum >= 0)
{
if (sum >= 7808)
{
u->oj = 1024;
zeroderiv = 1;
}
else u->oj = sigmoid[sum];
}
else
{
if (sum <= -7808)
{
u->oj = 0;
zeroderiv = 1;
}
else u->oj = 1024 - sigmoid[-sum];
};
}
#else
if (actfun == 's')
{
rsum = ((double) sum) / 1024.0;
rsum = 1.0 / (1.0 + exp(-rsum));
u->oj = (WTTYPE) (rsum * 1024.0 + 0.5);
}
#endif
else if (actfun == 'l') u->oj = sum;
u = u->next;
};
layer = layer->next;
};
}
short backoutput() /* computes weight changes from the output layer */
{
register short deltaj, temp2, temp3, D;
register INT32 temp;
register UNIT *bunit, *u;
register WTNODE *w;
register short adiff, notclose;
PATLIST *pl;
PATNODE *target;
char actfun;
actfun = last->activation;
D = last->D;
notclose = last->unitcount;
u = (UNIT *) last->units;
pl = last->currentpat[TRAIN];
target = pl->pats;
while (u != NULL)
{
temp3 = u->oj;
temp2 = target->val - temp3;
target++;
if (temp2 > 0) adiff = temp2; else adiff = -temp2;
if (adiff < toler) notclose = notclose - 1;
totaldiff = totaldiff + adiff;
if (deriv == 'd') deltaj = temp2;
else if (deriv == 'f')
switch (actfun) {
case 'l': deltaj = temp2 + 102;
break;
case 's': temp = (INT32) temp2 *
((INT32) 104448 + (INT32) temp3 * ((short)(1024 - temp3)));
if (temp > 0) deltaj = (INT32) (temp + 524288) >> 20;
else deltaj = -((INT32) (524288 - temp) >> 20);
break;}
else /* the derivative in the original formula */
switch (actfun) {
case 'l': deltaj = temp2;
break;
case 's': temp = (INT32) temp2 *
((INT32) temp3 * ((short)(1024 - temp3)));
if (temp > 0) deltaj = (INT32) (temp + 524288) >> 20;
else deltaj = -((INT32) (524288 - temp) >> 20);
break;}
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) + (INT32) deltaj * bunit->oj;
#else
w->total = w->total + (INT32) deltaj * bunit->oj;
if (bunit->layernumber > 1)
bunit->error = bunit->error + (INT32) deltaj * w->weight;
#endif
w = w->next;
};
u = u->next;
};
return(notclose);
}
#ifndef SYMMETRIC
void backinner() /* Computes slopes and passes back */
{ /* errors from hidden layers. */
register short deltaj, temp3;
register INT32 temp;
register WTTYPE D;
register UNIT *bunit, *u;
register WTNODE *w;
char actfun;
LAYER *layer;
layer = last->backlayer;
while (layer->backlayer != NULL)
{
actfun = layer->activation;
D = layer->D;
u = (UNIT *) layer->units;
while (u != NULL)
{
temp3 = u->oj;
switch (actfun) {
case 'l': deltaj = u->error;
break;
case 's': temp = (INT32) ((short)(((INT32) temp3 *
((short)(1024-temp3))+512) >> 10)) * u->error;
if (temp > 0) deltaj = (INT32) (temp + 524288) >> 20;
else deltaj = -((INT32) (524288 - temp) >> 20);
break;}
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
bunit = (UNIT *) w->backunit;
w->total = w->total + (INT32) deltaj * bunit->oj;
if (bunit->layernumber > 1)
bunit->error = bunit->error + (INT32) deltaj * w->weight;
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
#endif
void periodic_update() /* update weights for the original method */
{ /* and the differential step size algorithm */
register short reta, ralpha;
register INT32 temp;
register short temp2;
register UNIT *u;
register WTNODE *w;
LAYER *layer;
ralpha = alpha;
layer = last;
while (layer->backlayer != NULL)
{
if (layer == last) reta = eta; else reta = eta2;
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
if (w->inuse)
{
#ifdef SYMMETRIC
if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
{
if (*(w->total) > 0) temp = (INT32) ((INT32)(*(w->total) + 512) >> 10) * reta
+ (INT32) ralpha * *(w->olddw);
else temp = (INT32) -(((INT32) 512 - *(w->total)) >> 10) * reta
+ (INT32) ralpha * *(w->olddw);
if (temp > 0) temp2 = (INT32) (temp + 512) >> 10;
else temp2 = -(((INT32) 512 - temp) >> 10);
*(w->olddw) = temp2;
temp = (INT32) *(w->weight) + temp2;
if (temp > MAXSHORT)
{
wtlimithit = 1;
*(w->weight) = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
*(w->weight) = MINSHORT;
}
else *(w->weight) = temp;
};
#else
if (w->total > 0)
temp = (INT32) (((INT32) w->total + 512) >> 10) * reta + (INT32) ralpha * w->olddw;
else
temp = (INT32) -(((INT32) 512 - w->total) >> 10) * reta + (INT32) ralpha * w->olddw;
if (temp > 0) temp2 = (INT32) (temp + 512) >> 10;
else temp2 = -(((INT32) 512 - temp) >> 10);
w->olddw = temp2;
temp = (INT32) w->weight + temp2;
if (temp > MAXSHORT)
{
wtlimithit = 1;
w->weight = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
w->weight = MINSHORT;
}
else w->weight = temp;
#endif
};
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
#ifndef SYMMETRIC
void dbd_update() /* the delta-bar-delta method for weight updates */
{
register short rkappa, temp2, dbarm1, rdecay;
register INT32 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)
{
if (w->inuse)
{
if (w->total > 0) temp2 = (INT32) (w->total + 512) >> 10;
else temp2 = -((INT32) (512 - w->total) >> 10);
dbarm1 = w->olddw;
temp = (INT32) theta2 * temp2 + (INT32) theta1 * dbarm1;
if (temp > 0) w->olddw = (INT32) (temp + 512) >> 10;
else w->olddw = -((INT32) (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 = ((INT32) w->eta * rdecay) >> 10;
else if (temp2 < 0 && dbarm1 > 0)w->eta = ((INT32) w->eta * rdecay) >> 10;
if (w->eta > etamax) w->eta = etamax;
temp = (INT32) temp2 * w->eta;
if (temp > 0) temp2 = (INT32) (temp + 512) >> 10;
else if (temp < 0) temp2 = -((INT32) (512 - temp) >> 10);
else if (w->slope == 0)
{if (w->total < 0) temp2 = noise; else temp2 = -noise;}
w->slope = temp2;
temp = (INT32) w->weight + temp2;
if (temp > MAXSHORT)
{
wtlimithit = 1;
w->weight = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
w->weight = MINSHORT;
}
else w->weight = temp;
};
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
void qp_update()
{
register INT32 temp, s, nextdw;
register WTNODE *w;
register short rmu, reta, shrinkfactor, rqpdecay, addslope;
register UNIT *u;
LAYER *layer;
rmu = mu;
shrinkfactor = ((INT32) rmu * 1024 + 512) / (1024 + rmu);
reta = qpeta;
if (qpslope == '+') addslope = 1; else addslope = 0;
layer = last;
while (layer->backlayer != NULL)
{
if (layer == last) rqpdecay = 1000000.0 * qpdecayo + 0.5;
else rqpdecay = 1000000.0 * qpdecayh + 0.5;
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
if (w->inuse)
{
if (w->weight > 0)
s = (((INT32) rqpdecay * w->weight + 512) >> 10) - w->total;
else s = -(((INT32) 512 - (INT32) rqpdecay * w->weight) >> 10) - w->total;
if (s > 0) s = (s + 512) >> 10;
else s = -(((INT32) 512 - s) >> 10);
if (w->olddw < 0)
{
if (s >= (((INT32) shrinkfactor * w->eta) >> 10))
nextdw = - (((INT32) 512 - (INT32) rmu * w->olddw) >> 10);
else nextdw = ((INT32) w->olddw * s) / (w->eta - s);
if (addslope && s > 0)
nextdw = nextdw - (((INT32) reta * s + 512) >> 10);
}
else if (w->olddw > 0)
{
if (s <= (((INT32) shrinkfactor * w->eta) >> 10))
nextdw = (((INT32) rmu * w->olddw + 512) >> 10);
else nextdw = ((INT32) w->olddw * s) / (w->eta - s);
if (addslope && s < 0)
nextdw = nextdw + (((INT32) 512 - (INT32) reta * s) >> 10);
}
else
{
temp = (INT32) reta * s;
if (temp > 0) nextdw = - ((temp + 512) >> 10);
else if (temp < 0) nextdw = (((INT32) 512 - temp) >> 10);
else if (s > 0) nextdw = qpnoise;
else nextdw = -qpnoise;
};
if (nextdw > MAXSHORT) nextdw = MAXSHORT;
else if (nextdw < MINSHORT) nextdw = MINSHORT;
w->olddw = nextdw;
temp = (INT32) w->weight + nextdw;
if (temp > MAXSHORT)
{
wtlimithit = 1;
w->weight = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
w->weight = MINSHORT;
}
else w->weight = temp;
if (s > MAXSHORT) w->eta = MAXSHORT;
else if (s < MINSHORT) w->eta = MINSHORT;
else w->eta = s;
};
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
#else
void dbd_update() {};
void qp_update() {};
#endif
void tdupdate() {}; /* never programmed for the integer version */
short cbackoutput() /* The continuous update version of back- */
{ /* propagation that changes upper level */
register short deltaj; /* weights before passing back errors. */
register INT32 etadeltaj, temp, temp2;
register short temp3, adiff;
register UNIT *bunit;
register WTNODE *w;
register UNIT *u;
register short ralpha, reta, notclose, D;
PATNODE *target;
char actfun;
PATLIST *pl;
actfun = last->activation;
D = last->D;
ralpha = alpha;
reta = eta;
notclose = last->unitcount;
u = (UNIT *) last->units;
pl = last->currentpat[TRAIN];
target = pl->pats;
while (u != NULL)
{
temp3 = u->oj;
temp2 = target->val - temp3;
target++;
if (temp2 > 0) adiff = temp2; else adiff = -temp2;
if (adiff < toler) notclose = notclose - 1;
totaldiff = totaldiff + adiff;
if (deriv == 'd') deltaj = temp2;
else if (deriv == 'f')
switch (actfun) {
case 'l': deltaj = temp2 + 102;
break;
case 's': temp = (INT32) temp2 * ((INT32) 104448 +
(INT32) temp3 * ((short)(1024 - temp3)));
if(temp > 0) deltaj = (INT32) (temp + 524288) >> 20;
else deltaj = -(((INT32) 524288 - temp) >> 20);
break;}
etadeltaj = (INT32) deltaj * reta;
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 = (INT32) etadeltaj * bunit->oj;
if(temp > 0) temp = (INT32) (temp + 524288) >> 20;
else temp = -(((INT32) 524288 - temp) >> 20);
#ifdef SYMMETRIC
temp2 = (INT32) ralpha * *(w->olddw);
#else
temp2 = (INT32) ralpha * w->olddw;
#endif
if (temp2 > 0) temp3 = temp + (((INT32) temp2 + 512) >> 10);
else temp3 = temp - (((INT32) 512 - temp2) >> 10);
#ifdef SYMMETRIC
*(w->olddw) = temp3;
#else
w->olddw = temp3;
#endif
/* w->weight = w->weight + w->olddw */
#ifdef SYMMETRIC
temp = (INT32) *(w->weight) + temp3;
if (temp > MAXSHORT)
{
wtlimithit = 1;
*(w->weight) = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
*(w->weight) = MINSHORT;
}
else *(w->weight) = temp;
#else
temp = (INT32) w->weight + temp3;
if (temp > MAXSHORT)
{
wtlimithit = 1;
temp3 = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
temp3 = MINSHORT;
}
else temp3 = temp;
w->weight = temp3;
if (bunit->layernumber > 1)
bunit->error = bunit->error + (INT32) deltaj * temp3;
#endif
w = w->next;
};
u = u->next;
}
return(notclose);
}
#ifndef SYMMETRIC
void cbackinner()
{
register short deltaj;
register INT32 etadeltaj, temp, temp2;
register short temp3, reta, ralpha;
register UNIT *bunit;
register WTNODE *w;
register UNIT *u;
register WTTYPE D;
char actfun;
LAYER *layer;
reta = eta2;
ralpha = alpha;
layer = last->backlayer;
while (layer->backlayer != NULL)
{
actfun = layer->activation;
D = layer->D;
u = (UNIT *) layer->units;
while (u != NULL)
{
temp3 = u->oj;
switch (actfun) {
case 'l': deltaj = u->error;
break;
case 's': temp = (((INT32) temp3*((short)(1024-temp3))+512) >> 10)
* u->error;
if (temp > 0) deltaj = (INT32) (temp + 524288) >> 20;
else deltaj = -(((INT32) 524288 - temp) >> 20);
break;}
etadeltaj = (INT32) reta * deltaj;
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
bunit = (UNIT *) w->backunit;
temp = (INT32) etadeltaj * bunit->oj;
if (temp > 0) temp = (INT32) (temp + 524288) >> 20;
else temp = -(((INT32) 524288 - temp) >> 20);
temp2 = (INT32) ralpha * w->olddw;
if (temp2 > 0) temp3 = temp + ((INT32) (temp2 + 512) >> 10);
else temp3 = temp - (((INT32) 512 - temp2) >> 10);
w->olddw = temp3;
temp = (INT32) w->weight + temp3;
if (temp > MAXSHORT)
{
wtlimithit = 1;
temp3 = MAXSHORT;
}
else if (temp < MINSHORT)
{
wtlimithit = 1;
temp3 = MINSHORT;
}
else temp3 = temp;
w->weight = temp3;
if (bunit->layernumber > 1)
bunit->error = bunit->error + (INT32) deltaj * temp3;
w = w->next;
};
u = u->next;
};
layer = layer->backlayer;
};
}
#endif
void maze() {} /* never programmed for the integer version */