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 */