⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 direcmin.c

📁 统计模式识别算法包
💻 C
📖 第 1 页 / 共 2 页
字号:
   xlow = x1 ;
   xhigh = x3 ;

   fbest = fsecbest = fthirdbest = current_err ;


/*
   Main loop.  For safety we impose a limit on iterations.
*/

   for (iter=0 ; iter<itmax ; iter++) {

      xmid = 0.5 * (xlow + xhigh) ;
      tol1 = tol * (fabs ( xbest ) + eps) ;
      tol2 = 2. * tol1 ;

/***************************************************************************      if (kbhit()) {          // Was a key pressed?
         key = getch () ;     // Read it if so
         while (kbhit())      // Flush key buffer in case function key
            getch () ;        // or key was held down
         if (key == 27) {     // ESCape
            user_quit = 1 ;
            break ;
            }
         }
**************************************************************************/
/*
   The following convergence test simultaneously makes sure xhigh and
   xlow are close relative to tol2, and that xbest is near the midpoint.
*/
      if (fabs ( xbest - xmid )  <=  (tol2 - 0.5 * (xhigh - xlow)))
         break ;

      if (fabs ( prevdist )  >  tol1) {  // If we moved far enough try parabolic fit
         t1 = (xbest - xsecbest) * (fbest - fthirdbest) ; // Temps for the
         t2 = (xbest - xthirdbest) * (fbest - fsecbest) ; // parabolic estimate
         numer = (xbest - xthirdbest) * t2  -  (xbest - xsecbest) * t1 ;
         denom = 2. * (t1 - t2) ;  // Estimate will be numer / denom
         testdist = prevdist ;     // Will soon verify interval is shrinking
         prevdist = step ;         // Save for next iteration
         if (denom != 0.0)         // Avoid dividing by zero
            step = numer / denom ; // This is the parabolic estimate to min
         else 
            step = 1.e30 ;         // Assures failure of next test

         if ((fabs ( step ) < fabs ( 0.5 * testdist ))// If shrinking
          && (step + xbest > xlow)             // and within known bounds
          && (step + xbest < xhigh)) {         // then we can use the
            xrecent = xbest + step ;           // parabolic estimate
            if ((xrecent - xlow  <  tol2)  ||  // If we are very close
                (xhigh - xrecent <  tol2)) {   // to known bounds
               if (xbest < xmid)               // then stabilize
                  step = tol1 ;
               else
                  step = -tol1 ;
               }
            }
         else {  // Parabolic estimate poor, so use golden section
            prevdist = (xbest >= xmid)  ?  xlow - xbest  :  xhigh - xbest ;          // Poor so use    
            step = .3819660 * prevdist ;
            }
         }
      else { // prevdist did not exceed tol1: we did not move far enough
             // to justify a parabolic fit.  Use golden section.
         prevdist = (xbest >= xmid)  ?  xlow - xbest  :  xhigh - xbest ;
         step = .3819660 * prevdist ;
         }

      if (fabs (step)  >=  tol1)     // In order to numerically justify
         xrecent = xbest + step ;    // another trial we must move a
      else {                         // decent distance.
         if (step > 0.)
            xrecent = xbest + tol1 ;
         else
            xrecent = xbest - tol1 ;
         }

/*
   At long last we have a trial point 'xrecent'.  Evaluate the function.
*/

      step_out ( xrecent , direc , base ) ;
      frecent = trial_error ( tptr ) ;

      if (frecent <= fbest) {    // If we improved...
         if (xrecent >= xbest)   // Shrink the (xlow,xhigh) interval by
            xlow = xbest ;       // replacing the appropriate endpoint
         else
            xhigh = xbest ;
         xthirdbest = xsecbest ; // Update x and f values for best,
         xsecbest = xbest ;      // second and third best
         xbest = xrecent ;
         fthirdbest = fsecbest ;
         fsecbest = fbest ;
         fbest = frecent ;
         }

      else {                  // We did not improve
         if (xrecent < xbest) // Shrink the (xlow,xhigh) interval by
            xlow = xrecent ;  // replacing the appropriate endpoint
         else
            xhigh = xrecent ;

         if ((frecent <= fsecbest)   // If we at least beat the second best
          || (xsecbest == xbest)) {  // or we had a duplication
            xthirdbest = xsecbest ;  // we can update the second and third
            xsecbest = xrecent ;     // best, though not the best.
            fthirdbest = fsecbest ;  // Recall that we started iters with
            fsecbest = frecent ;     // best, sec and third all equal.
            }
         else if ((frecent <= fthirdbest) // Oh well.  Maybe at least we can
           || (xthirdbest == xbest)       // beat the third best or rid
           || (xthirdbest == xsecbest)) { // ourselves of a duplication
            xthirdbest = xrecent ;        // (which is how we start the
            fthirdbest = frecent ;        // iterations)
            }
         }
      }
 
   step_out ( xbest , direc , base );//Leave coefs at min
   update_dir ( xbest , direc ) ;// Make it be the actual distance moved

   if (user_quit)
      return -fbest ;
   else 
      return fbest ;
}


/*
--------------------------------------------------------------------------------

   Local routine to preserve coefs in 'base'

--------------------------------------------------------------------------------
*/

void LayerNet::preserve ( double *base )
{
   int n ;

   if (nhid1 == 0) {                // No hidden layer
      n = nout * (nin+1) ;
      memcpy ( base , out_coefs , n * sizeof(double) ) ;
      }

   else if (nhid2 == 0) {           // One hidden layer
      n = nhid1 * (nin+1) ;
      memcpy ( base , hid1_coefs , n * sizeof(double) ) ;
      base += n ;
      n = nout * (nhid1+1) ;
      memcpy ( base , out_coefs , n * sizeof(double) ) ;
      }

   else {                           // Two hidden layers
      n = nhid1 * (nin+1) ;
      memcpy ( base , hid1_coefs , n * sizeof(double) ) ;
      base += n ;
      n = nhid2 * (nhid1+1) ;
      memcpy ( base , hid2_coefs , n * sizeof(double) ) ;
      base += n ;
      n = nout * (nhid2+1) ;
      memcpy ( base , out_coefs , n * sizeof(double) ) ;
      }
}


/*
--------------------------------------------------------------------------------

   Local routine to step out from base

--------------------------------------------------------------------------------
*/

void LayerNet::step_out ( double step , double *direc , double *base )
{
   int i, n ;

   if (nhid1 == 0) {                // No hidden layer
      n = nout * (nin+1) ;
      for (i=0 ; i<n ; i++)
         out_coefs[i] = *(base++) + *(direc++) * step ;
      }

   else if (nhid2 == 0) {           // One hidden layer
      n = nhid1 * (nin+1) ;
      for (i=0 ; i<n ; i++)
         hid1_coefs[i] = *(base++) + *(direc++) * step ;
      n = nout * (nhid1+1) ;
      for (i=0 ; i<n ; i++)
         out_coefs[i] = *(base++) + *(direc++) * step ;
      }

   else {                           // Two hidden layers
      n = nhid1 * (nin+1) ;
      for (i=0 ; i<n ; i++)
         hid1_coefs[i] = *(base++) + *(direc++) * step ;
      n = nhid2 * (nhid1+1) ;
      for (i=0 ; i<n ; i++)
         hid2_coefs[i] = *(base++) + *(direc++) * step ;
      n = nout * (nhid2+1) ;
      for (i=0 ; i<n ; i++)
         out_coefs[i] = *(base++) + *(direc++) * step ;
      }
}

/*
--------------------------------------------------------------------------------

   Local routine to make 'dir' be the actual distance moved

--------------------------------------------------------------------------------
*/

void LayerNet::update_dir ( double step , double *direc )
{
   int n ;

  if (nhid1 == 0)               // No hidden layer
      n = nout * (nin+1) ;
   else if (nhid2 == 0)          // One hidden layer
      n = nhid1 * (nin+1) + nout * (nhid1+1) ;
   else                          // Two hidden layers
      n = nhid1 * (nin+1) + nhid2 * (nhid1+1) + nout * (nhid2+1) ;

   while (n--) {
      *direc *= step ;
      ++direc ;
      }
}

/*
--------------------------------------------------------------------------------

   Local routine to negate 'dir'

--------------------------------------------------------------------------------
*/

void LayerNet::negate_dir ( double *direc )
{
   int n ;

  if (nhid1 == 0)               // No hidden layer
      n = nout * (nin+1) ;
   else if (nhid2 == 0)          // One hidden layer
      n = nhid1 * (nin+1) + nout * (nhid1+1) ;
   else                          // Two hidden layers
      n = nhid1 * (nin+1) + nhid2 * (nhid1+1) + nout * (nhid2+1) ;

   while (n--) {
      *direc = -*direc ;
      ++direc ;
      }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -