home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / backprop / part04 / real.c < prev   
Encoding:
C/C++ Source or Header  |  1992-02-23  |  9.2 KB  |  351 lines

  1. /* *********************************************************** */
  2. /* file real.c:  contains the network evaluation and weight    */
  3. /* adjustment procedures for the 64-bit floating point program */
  4. /*                                                             */
  5. /* Copyright (c) 1991 by Donald R. Tveter                      */
  6. /*                                                             */
  7. /* *********************************************************** */
  8.  
  9. #include "rbp.h"
  10. #include <stdio.h>
  11.  
  12. extern char activation, backprop, deriv;
  13. extern REAL alpha, D, decay, eta, eta2, etamax, kappa;
  14. extern REAL noise, theta1, theta2, toler, totaldiff;
  15. extern LAYER *last, *start;
  16.  
  17. extern double exp(); /* built-in functions */
  18.  
  19. void forward()       /* computes unit activations */
  20. {
  21. UNIT *u, *predu;
  22. LAYER *layer;
  23. WTNODE *b;
  24. register REAL fract, x, sum;
  25. REAL val; /* should be in a register, but UNIX pc C-compiler does */
  26.           /* not handle it correctly */
  27. int intpart;
  28.  
  29. layer = start->next;
  30. while (layer != NULL)
  31.  {
  32.   u = (UNIT *) layer->units;
  33.   while (u != NULL)
  34.    {
  35.     sum = 0.0;
  36.     b = (WTNODE *) u->wtlist;
  37.     while (b != NULL)
  38.      {
  39.       predu = (UNIT *) b->backunit;
  40. #ifdef SYMMETRIC
  41.       sum = sum + *(b->weight) * predu->oj;
  42. #else
  43.       sum = sum + b->weight * predu->oj;
  44. #endif
  45.       b = b->next;
  46.      };
  47.     sum = sum * D;
  48.     if (activation == 'p' || activation == 't')
  49.      {
  50.       if (sum >= 0.0) x = sum; else x = - sum;
  51.       intpart = x;
  52.       fract = x - intpart;
  53.       switch (intpart) {
  54. case 0:  val = 0.5 + 0.231 * fract;          /* 0 <= x < 1 */
  55.          break;
  56. case 1:  val = 0.731059 + 0.149738 * fract;  /* 1 <= x < 2 */
  57.          break;
  58. case 2:  val = 0.880797 + 0.071777 * fract;  /* 2 <= x < 3 */
  59.          break;
  60. case 3:
  61. case 4:  val = 0.9525741 + (x - 3.0) * 0.02; /* 3 <= x < 5 */
  62.          break;
  63. default: val = 1.0;                          /* x >= 5 */
  64.             };
  65.       if (sum < 0.0) u->oj = 1.0 - val; else u->oj = (REAL) val;
  66.       if (activation == 't') u->oj = (u->oj - 0.5) * 2;
  67.      }  /* end of p or t */
  68.     else if (activation == 's') u->oj = 1.0 / (1.0 + exp(-sum));
  69.     else if (activation == 'l') u->oj = sum;
  70.     else if (activation == 'T') u->oj = 2.0 / (1.0 + exp(-sum)) - 1.0;
  71.     u = u->next;
  72.    };
  73.   layer = layer->next;
  74.  };
  75. }
  76.  
  77. short backoutput()  /* back propagate errors from the output units */
  78. {                   /* send down errors for any previous layers    */
  79. register REAL deltaj, diff, adiff, uoj;
  80. register UNIT *u, *bunit;
  81. register WTNODE *w;
  82. register short notclose;
  83.  
  84. notclose = last->unitcount;
  85. u = (UNIT *) last->units;
  86. while (u != NULL)
  87.  {
  88.   diff = u->tj - u->oj;
  89.   if (diff > 0) adiff = diff; else adiff = -diff;
  90.   if (adiff < toler) notclose = notclose - 1;
  91.   totaldiff = totaldiff + adiff;
  92.   if (adiff >= toler || backprop)
  93.    {
  94.     if (deriv == 'd') /* differential step size */
  95.        deltaj = diff;
  96.     else if (deriv == 'f' || deriv == 'F') /* Fahlman's derivative */
  97.      {
  98.       if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
  99.       else uoj = u->oj;
  100.       deltaj = diff * (0.1 + uoj * (1.0 - uoj));
  101.      }
  102.     else /* the original derivative */
  103.      {
  104.       if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
  105.       else uoj = u->oj;
  106.       deltaj = diff * uoj * (1.0 - uoj);
  107.      };
  108.     w = (WTNODE *) u->wtlist;
  109. #ifdef SYMMETRIC
  110.     while (w->next != NULL)
  111. #else
  112.     while (w != NULL)
  113. #endif
  114.      {
  115.       bunit = (UNIT *) w->backunit;
  116. #ifdef SYMMETRIC
  117.       *(w->total) = *(w->total) + deltaj * bunit->oj;
  118. #else
  119.       w->total = w->total + deltaj * bunit->oj;
  120.       if (bunit->layernumber > 1)  /* pass back the error */
  121.          bunit->error = bunit->error + deltaj * w->weight;
  122. #endif
  123.       w = w->next;
  124.      };
  125.    }
  126.   u = u->next;
  127.  }
  128. return(notclose);
  129. }
  130.  
  131. #ifndef SYMMETRIC
  132.  
  133. void backinner()  /* compute weight changes for hidden layers */
  134. {                 /* send down errors for any previous layers */
  135. LAYER *layer;
  136. register REAL deltaj, uoj;
  137. register UNIT *bunit;
  138. register WTNODE *w;
  139. register UNIT *u;
  140.  
  141. layer = last->backlayer;
  142. while (layer->backlayer != NULL)
  143.  {
  144.   u = (UNIT *) layer->units;
  145.   while (u != NULL)
  146.    {
  147.     if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
  148.     else uoj = u->oj;
  149.     if (deriv == 'f') /* Fahlman's derivative */
  150.        deltaj = (0.1 + uoj * (1.0 - uoj)) * u->error;
  151.     else /* for o, d and F */
  152.        deltaj = (uoj * (1.0 - uoj)) * u->error;
  153.     w = (WTNODE *) u->wtlist;
  154.     while (w != NULL)
  155.      {
  156.       bunit = (UNIT *) w->backunit;
  157.       w->total = w->total + deltaj * bunit->oj;
  158.       if (bunit->layernumber > 1)
  159.          bunit->error = bunit->error + deltaj * w->weight;
  160.       w = w->next;
  161.      };
  162.     u = u->next;
  163.    };
  164.   layer = layer->backlayer;
  165.  };
  166. }
  167.  
  168. #endif
  169.  
  170. #ifdef SYMMETRIC
  171. void dbd_update() {pg("symmetric dbd update no longer supported\n");}
  172. #else
  173. void dbd_update() /* delta-bar-delta method for changing weights */
  174. {
  175. register short stotal,sdbarm1;
  176. register UNIT *u;
  177. register WTNODE *w;
  178. LAYER *layer;
  179.  
  180. /* w->olddw is used for delta-bar minus 1 */
  181.  
  182. layer = last;
  183. while (layer->backlayer != NULL)
  184.  {
  185.   u = (UNIT *) layer->units;
  186.   while (u != NULL)
  187.    {
  188.     w = (WTNODE *) u->wtlist;
  189.     while (w != NULL)
  190.      {
  191.       if (w->total > 0) stotal = 1;
  192.         else if (w->total < 0) stotal = -1;
  193.          else stotal = 0;
  194.       if (w->olddw > 0) sdbarm1 = 1;
  195.         else if (w->olddw < 0) sdbarm1 = -1;
  196.          else sdbarm1 = 0;
  197.       w->olddw = theta2 * w->total + theta1 * w->olddw;
  198.       if ((stotal > 0) && (sdbarm1 > 0)) w->eta = w->eta + kappa;
  199.       else if ((stotal < 0) && (sdbarm1 < 0)) w->eta = w->eta + kappa;
  200.       else if ((stotal > 0) && (sdbarm1 < 0)) w->eta = w->eta * decay;
  201.       else if ((stotal < 0) && (sdbarm1 > 0)) w->eta = w->eta * decay;
  202.       if (w->eta > etamax) w->eta = etamax;
  203.       w->weight = w->weight + w->eta * w->total;
  204.       w = w->next;
  205.      };
  206.     u = u->next;
  207.    };
  208.   layer = layer->backlayer;
  209.  };
  210. }
  211. #endif
  212.  
  213. void periodic_update()  /* the original periodic method */
  214. {
  215. register REAL reta, ralpha;
  216. register UNIT *u;
  217. register WTNODE *w;
  218. LAYER *layer;
  219.  
  220. ralpha = alpha;
  221. layer = last;
  222. while (layer->backlayer != NULL)
  223.  {
  224.   if (layer == last) reta = eta; else reta = eta2;
  225.   u = (UNIT *) layer->units;
  226.   while (u != NULL)
  227.    {
  228.     w = (WTNODE *) u->wtlist;
  229.     while (w != NULL)
  230.      {
  231. #ifdef SYMMETRIC
  232.       if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
  233.        {
  234.         *(w->olddw) = *(w->total) * reta + ralpha * *(w->olddw);
  235.         *(w->weight) = *(w->weight) + *(w->olddw);
  236.        };
  237. #else
  238.       w->olddw = w->total * reta + ralpha * w->olddw;
  239.       w->weight = w->weight + w->olddw;
  240. #endif
  241.       w = w->next;
  242.      };
  243.     u = u->next;
  244.    };
  245.   layer = layer->backlayer;
  246.  };
  247. }
  248.  
  249. void qp_update() {pg("quickprop not yet finished\n");}
  250. void supersab() {pg("supersab not yet finished\n");}
  251.  
  252. short cbackoutput()  /* backoutput for continuous updates */
  253. {
  254. register REAL deltaj, etadeltaj, diff, adiff, uoj, reta, ralpha;
  255. register UNIT *u, *bunit;
  256. register WTNODE *b;
  257. register short notclose;
  258.  
  259. reta = eta;
  260. ralpha = alpha;
  261. notclose = last->unitcount;
  262. u = (UNIT *) last->units;
  263. while (u != NULL)
  264.  {
  265.   diff = u->tj - u->oj;
  266.   if (diff > 0) adiff = diff; else adiff = -diff;
  267.   if (adiff < toler) notclose = notclose - 1;
  268.   totaldiff = totaldiff + adiff;
  269.   if (adiff >= toler || backprop)
  270.    {
  271.     if (deriv == 'd') /* differential step size derivative */
  272.        deltaj = diff;
  273.     else if (deriv == 'f' || deriv == 'F') /* Fahlman's derivative */
  274.      {
  275.       if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
  276.       else uoj = u->oj;
  277.       deltaj = diff * (0.1 + uoj * (1.0 - uoj));
  278.      }
  279.     else /* the original derivative */
  280.      {
  281.       if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
  282.       else uoj = u->oj;
  283.       deltaj = diff * uoj * (1.0 - uoj);
  284.      };
  285.     etadeltaj = deltaj * reta;
  286.     b = (WTNODE *) u->wtlist;
  287. #ifdef SYMMETRIC
  288.     while (b->next != NULL)
  289. #else
  290.     while (b != NULL)
  291. #endif
  292.      {
  293.       bunit = (UNIT *) b->backunit;
  294. #ifdef SYMMETRIC
  295.       *(b->olddw) = etadeltaj * bunit->oj + ralpha * *(b->olddw);
  296.       *(b->weight) = *(b->weight) + *(b->olddw);
  297. #else
  298.       b->olddw = etadeltaj * bunit->oj + ralpha * b->olddw;
  299.       b->weight = b->weight + b->olddw;
  300.       if (bunit->layernumber > 1)
  301.          bunit->error = bunit->error + deltaj * b->weight;
  302. #endif
  303.       b = b->next;
  304.      };
  305.    };
  306.   u = u->next;
  307.  }
  308. return(notclose);
  309. }
  310.  
  311. #ifndef SYMMETRIC
  312.  
  313. void cbackinner()  /* backinner for continuous updates */
  314. {
  315. LAYER *layer;
  316. register REAL deltaj, etadeltaj, reta, uoj, ralpha;
  317. register UNIT *bunit, *u;
  318. register WTNODE *b;
  319.  
  320. reta = eta2;
  321. ralpha = alpha;
  322. layer = last->backlayer;
  323. while (layer->backlayer != NULL)
  324.  {
  325.   u = (UNIT *) layer->units;
  326.   while (u != NULL)
  327.    {
  328.     if (activation == 't' || activation == 'T') uoj = u->oj / 2 + 0.5;
  329.     else uoj = u->oj;
  330.     if (deriv == 'f') /* Fahlman's derivative */
  331.        deltaj = (0.1 + uoj * (1.0 - uoj)) * u->error;
  332.     else /* for o, d and F */
  333.        deltaj = (uoj * (1.0 - uoj)) * u->error;
  334.     etadeltaj = reta * deltaj;
  335.     b = (WTNODE *) u->wtlist;
  336.     while (b != NULL)
  337.      {
  338.       bunit = (UNIT *) b->backunit;
  339.       b->olddw = etadeltaj * bunit->oj + ralpha * b->olddw;
  340.       b->weight = b->weight + b->olddw;
  341.       if (bunit->layernumber > 1)
  342.          bunit->error = bunit->error + deltaj * b->weight;
  343.       b = b->next;
  344.      };
  345.     u = u->next;
  346.    };
  347.   layer = layer->backlayer;
  348.  };
  349. }
  350. #endif
  351.