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) 1991 by Donald R. Tveter */
- /* */
- /* *********************************************************** */
-
- #include "rbp.h"
- #include <stdio.h>
-
- extern char activation, backprop, deriv;
- extern REAL alpha, D, decay, eta, eta2, etamax, kappa;
- extern REAL noise, theta1, theta2, toler, totaldiff;
- extern LAYER *last, *start;
-
- extern double exp(); /* built-in functions */
-
- void forward() /* computes unit activations */
- {
- UNIT *u, *predu;
- LAYER *layer;
- WTNODE *b;
- register REAL fract, x, sum;
- REAL val; /* should be in a register, but UNIX pc C-compiler does */
- /* not handle it correctly */
- 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 == 'p' || activation == 't')
- {
- 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 = (REAL) val;
- if (activation == 't') u->oj = (u->oj - 0.5) * 2;
- } /* end of p or t */
- else if (activation == 's') u->oj = 1.0 / (1.0 + exp(-sum));
- else if (activation == 'l') u->oj = sum;
- else if (activation == 'T') u->oj = 2.0 / (1.0 + exp(-sum)) - 1.0;
- u = u->next;
- };
- layer = layer->next;
- };
- }
-
- short backoutput() /* back propagate errors from the output units */
- { /* send down errors for any previous layers */
- register REAL deltaj, diff, adiff, uoj;
- register UNIT *u, *bunit;
- register WTNODE *w;
- register short notclose;
-
- notclose = last->unitcount;
- u = (UNIT *) last->units;
- while (u != NULL)
- {
- diff = u->tj - 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' || deriv == 'F') /* Fahlman's derivative */
- {
- if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
- else uoj = u->oj;
- deltaj = diff * (0.1 + uoj * (1.0 - uoj));
- }
- else /* the original derivative */
- {
- if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
- else uoj = u->oj;
- deltaj = diff * uoj * (1.0 - uoj);
- };
- 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;
- }
- return(notclose);
- }
-
- #ifndef SYMMETRIC
-
- void backinner() /* compute weight changes for hidden layers */
- { /* send down errors for any previous layers */
- LAYER *layer;
- register REAL deltaj, uoj;
- register UNIT *bunit;
- register WTNODE *w;
- register UNIT *u;
-
- layer = last->backlayer;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
- else uoj = u->oj;
- if (deriv == 'f') /* Fahlman's derivative */
- deltaj = (0.1 + uoj * (1.0 - uoj)) * u->error;
- else /* for o, d and F */
- deltaj = (uoj * (1.0 - uoj)) * 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
-
- #ifdef SYMMETRIC
- void dbd_update() {pg("symmetric dbd update no longer supported\n");}
- #else
- void dbd_update() /* delta-bar-delta method for changing weights */
- {
- register short stotal,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)
- {
- 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->eta * w->total;
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
- #endif
-
- void periodic_update() /* the original periodic method */
- {
- register REAL reta, ralpha;
- 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)
- {
- #ifdef SYMMETRIC
- if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
- {
- *(w->olddw) = *(w->total) * reta + ralpha * *(w->olddw);
- *(w->weight) = *(w->weight) + *(w->olddw);
- };
- #else
- w->olddw = w->total * reta + ralpha * w->olddw;
- w->weight = w->weight + w->olddw;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- void qp_update() {pg("quickprop not yet finished\n");}
- void supersab() {pg("supersab not yet finished\n");}
-
- short cbackoutput() /* backoutput for continuous updates */
- {
- register REAL deltaj, etadeltaj, diff, adiff, uoj, reta, ralpha;
- register UNIT *u, *bunit;
- register WTNODE *b;
- register short notclose;
-
- reta = eta;
- ralpha = alpha;
- notclose = last->unitcount;
- u = (UNIT *) last->units;
- while (u != NULL)
- {
- diff = u->tj - 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' || deriv == 'F') /* Fahlman's derivative */
- {
- if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
- else uoj = u->oj;
- deltaj = diff * (0.1 + uoj * (1.0 - uoj));
- }
- else /* the original derivative */
- {
- if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
- else uoj = u->oj;
- deltaj = diff * uoj * (1.0 - uoj);
- };
- etadeltaj = deltaj * reta;
- 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 + ralpha * *(b->olddw);
- *(b->weight) = *(b->weight) + *(b->olddw);
- #else
- b->olddw = etadeltaj * bunit->oj + ralpha * 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;
- }
- return(notclose);
- }
-
- #ifndef SYMMETRIC
-
- void cbackinner() /* backinner for continuous updates */
- {
- LAYER *layer;
- register REAL deltaj, etadeltaj, reta, uoj, ralpha;
- register UNIT *bunit, *u;
- register WTNODE *b;
-
- reta = eta2;
- ralpha = alpha;
- layer = last->backlayer;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
- else uoj = u->oj;
- if (deriv == 'f') /* Fahlman's derivative */
- deltaj = (0.1 + uoj * (1.0 - uoj)) * u->error;
- else /* for o, d and F */
- deltaj = (uoj * (1.0 - uoj)) * u->error;
- etadeltaj = reta * deltaj;
- b = (WTNODE *) u->wtlist;
- while (b != NULL)
- {
- bunit = (UNIT *) b->backunit;
- b->olddw = etadeltaj * bunit->oj + ralpha * 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
-