home *** CD-ROM | disk | FTP | other *** search
- /* *********************************************************** */
- /* file real.c: contains the network evaluation and weight */
- /* adjustment procedures for the 64-bit floating point program */
- /* */
- /* Copyright (c) 1990 by Donald R. Tveter */
- /* */
- /* *********************************************************** */
-
- #include "rbp.h"
- #include <stdio.h>
-
- extern char activation;
- extern double alpha;
- extern char backprop;
- extern double D;
- extern double decay;
- extern char deriv;
- extern double eta;
- extern double eta2;
- extern double etamax;
- extern double kappa;
- extern LAYER *last;
- extern LAYER *start;
- extern double theta1;
- extern double theta2;
- extern double toler;
- extern double totaldiff;
- extern char update;
-
- extern double exp(); /* a built-in function */
-
- void forward() /* computes unit activations */
- {
- UNIT *u, *predu;
- LAYER *layer;
- WTNODE *b;
- double fract, x, val;
- double sum;
- int intpart;
-
- layer = start->next;
- while (layer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- sum = 0.0;
- b = (WTNODE *) u->wtlist;
- while (b != NULL)
- {
- predu = (UNIT *) b->backunit;
- #ifdef SYMMETRIC
- sum = sum + *(b->weight) * predu->oj;
- #else
- sum = sum + b->weight * predu->oj;
- #endif
- b = b->next;
- };
- sum = sum * D;
- if (activation == 's') u->oj = 1.0 / (1.0 + exp(-sum));
- else
- { /* piecewise linear, the fast way */
- if (sum >= 0.0) x = sum; else x = - sum;
- intpart = x;
- fract = x - intpart;
- switch (intpart)
- {
- case 0: val = 0.5 + 0.231 * fract; /* 0 <= x < 1 */
- break;
- case 1: val = 0.731059 + 0.149738 * fract; /* 1 <= x < 2 */
- break;
- case 2: val = 0.880797 + 0.071777 * fract; /* 2 <= x < 3 */
- break;
- case 3:
- case 4: val = 0.9525741 + (x - 3.0) * 0.02; /* 3 <= x < 5 */
- break;
- default: val = 1.0; /* x >= 5 */
- };
- if (sum < 0.0) u->oj = 1.0 - val; else u->oj = val;
- } /* end of the fast way */
- u = u->next;
- };
- layer = layer->next;
- };
- }
-
- short backoutput() /* back propagate errors from the output units */
- { /* send down errors for any previous layers */
- double deltaj, diff, adiff;
- register UNIT *u, *bunit;
- register WTNODE *w;
- register PATNODE *t;
- register short notclose;
-
- notclose = last->unitcount;
- u = (UNIT *) last->units;
- t = (PATNODE *) last->currentpat->pats;
- while (u != NULL)
- {
- diff = t->val - u->oj;
- if (diff > 0) adiff = diff; else adiff = -diff;
- if (adiff < toler) notclose = notclose - 1;
- totaldiff = totaldiff + adiff;
- if (adiff >= toler || backprop)
- {
- if (deriv == 'd') /* differential step size */
- deltaj = diff;
- else if (deriv == 'f') /* Fahlman's derivative */
- deltaj = diff * (0.1 + u->oj * (1.0 - u->oj));
- else /* the original derivative */
- deltaj = diff * u->oj * (1.0 - u->oj);
- w = (WTNODE *) u->wtlist;
- #ifdef SYMMETRIC
- while (w->next != NULL)
- #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) /* pass back the error */
- bunit->error = bunit->error + deltaj * w->weight;
- #endif
- w = w->next;
- };
- }
- u = u->next;
- t = t->next;
- }
- return(notclose);
- }
-
- #ifndef SYMMETRIC
-
- void backinner() /* compute weight changes for hidden layers */
- { /* send down errors for any previous layers */
- LAYER *layer;
- double deltaj;
- register UNIT *bunit;
- register WTNODE *w;
- register UNIT *u;
-
- layer = last->backlayer;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- if (deriv == 'f') /* Fahlman's derivative */
- deltaj = (0.1 + u->oj * (1.0 - u->oj)) * u->error;
- else /* original and diff. step size derivative */
- deltaj = (u->oj * (1.0 - u->oj)) * u->error;
- 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 changing weights */
- {
- register short stotal;
- register short sdbarm1;
- register UNIT *u;
- register WTNODE *w;
- LAYER *layer;
-
- /* w->olddw is used for delta-bar minus 1 */
-
- 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) stotal = 1;
- else if (*(w->total) < 0) stotal = -1;
- else stotal = 0;
- if (*(w->olddw) > 0) sdbarm1 = 1;
- else if (*(w->olddw) < 0) sdbarm1 = -1;
- else sdbarm1 = 0;
- *(w->olddw) = theta2 * *(w->total) + theta1 * *(w->olddw);
- if ((stotal > 0) && (sdbarm1 > 0))
- *(w->eta) = *(w->eta) + kappa;
- else if ((stotal < 0) && (sdbarm1 < 0))
- *(w->eta) = *(w->eta) + kappa;
- else if ((stotal > 0) && (sdbarm1 < 0))
- *(w->eta) = *(w->eta) * decay;
- else if ((stotal < 0) && (sdbarm1 > 0))
- *(w->eta) = *(w->eta) * decay;
- if (*(w->eta) > etamax) *(w->eta) = etamax;
- *(w->weight) = *(w->weight) + *(w->total) * *(w->eta);
- };
- #else
- if (w->total > 0) stotal = 1;
- else if (w->total < 0) stotal = -1;
- else stotal = 0;
- if (w->olddw > 0) sdbarm1 = 1;
- else if (w->olddw < 0) sdbarm1 = -1;
- else sdbarm1 = 0;
- w->olddw = theta2 * w->total + theta1 * w->olddw;
- if ((stotal > 0) && (sdbarm1 > 0)) w->eta = w->eta + kappa;
- else if ((stotal < 0) && (sdbarm1 < 0)) w->eta = w->eta + kappa;
- else if ((stotal > 0) && (sdbarm1 < 0)) w->eta = w->eta * decay;
- else if ((stotal < 0) && (sdbarm1 > 0)) w->eta = w->eta * decay;
- if (w->eta > etamax) w->eta = etamax;
- w->weight = w->weight + w->total * w->eta;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- void updateo() /* update weights for the original and the */
- { /* differential step size methods */
- double reta;
- register UNIT *u;
- register WTNODE *w;
- LAYER *layer;
-
- 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)
- {
- *(w->olddw) = *(w->total) * reta + alpha * *(w->olddw);
- *(w->weight) = *(w->weight) + *(w->olddw);
- };
- #else
- w->olddw = w->total * reta + alpha * w->olddw;
- w->weight = w->weight + w->olddw;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- short cbackoutput() /* backoutput for continuous updates */
- {
- double deltaj, etadeltaj, diff, adiff;
- register UNIT *u, *bunit;
- register WTNODE *b;
- register PATNODE *t;
- register short notclose;
-
- notclose = last->unitcount;
- u = (UNIT *) last->units;
- t = (PATNODE *) last->currentpat->pats;
- while (u != NULL)
- {
- diff = t->val - u->oj;
- if (diff > 0) adiff = diff; else adiff = -diff;
- if (adiff < toler) notclose = notclose - 1;
- totaldiff = totaldiff + adiff;
- if (adiff >= toler || backprop)
- {
- if (deriv == 'd') /* differential step size derivative */
- deltaj = diff;
- else if (deriv == 'f') /* Fahlman's derivative */
- deltaj = diff * (0.1 + u->oj * (1.0 - u->oj));
- else /* the original derivative */
- deltaj = diff * u->oj * (1.0 - u->oj);
- etadeltaj = deltaj * eta;
- b = (WTNODE *) u->wtlist;
- #ifdef SYMMETRIC
- while (b->next != NULL)
- #else
- while (b != NULL)
- #endif
- {
- bunit = (UNIT *) b->backunit;
- #ifdef SYMMETRIC
- *(b->olddw) = etadeltaj * bunit->oj + alpha * *(b->olddw);
- *(b->weight) = *(b->weight) + *(b->olddw);
- #else
- b->olddw = etadeltaj * bunit->oj + alpha * b->olddw;
- b->weight = b->weight + b->olddw;
- if (bunit->layernumber > 1)
- bunit->error = bunit->error + deltaj * b->weight;
- #endif
- b = b->next;
- };
- };
- u = u->next;
- t = t->next;
- }
- return(notclose);
- }
-
- #ifndef SYMMETRIC
-
- void cbackinner() /* backinner for continuous updates */
- {
- LAYER *layer;
- double deltaj, etadeltaj, reta;
- register UNIT *bunit, *u;
- register WTNODE *b;
-
- if (update == 'D') reta = eta2; else reta = eta;
- layer = last->backlayer;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- if (deriv == 'f') /* Fahlman's derivative */
- deltaj = (0.1 + u->oj * (1.0 - u->oj)) * u->error;
- else /* the diff. step size and original derivative */
- deltaj = (u->oj * (1.0 - u->oj)) * u->error;
- etadeltaj = reta * deltaj;
- b = (WTNODE *) u->wtlist;
- while (b != NULL)
- {
- bunit = (UNIT *) b->backunit;
- b->olddw = etadeltaj * bunit->oj + alpha * b->olddw;
- b->weight = b->weight + b->olddw;
- if (bunit->layernumber > 1)
- bunit->error = bunit->error + deltaj * b->weight;
- b = b->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
- #endif
-