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