[Index for tmp_for_tar/levmar] [Return to Master Index]

levmar_min

(tmp_for_tar/levmar/levmar_min.m)


Function Synopsis

[xbest,vbest,niter,hbest,y] = \
      levmar_min(u,func,d2func,xinit,...)

Help text

       [x,v,niter,h,y] = levmar_min(u,func,d2func,xinit,options)
        ^ ^  ^    ^ ^
        | |  |    | \ 
        | |  |    \  See below
        | |   \    Pseudo-inverse of Hessian
        |  \   Number of iterations
        |   Value at x
 Best "x" found

 Not-quite Levenberg-Marquardt method for minimizing the norm of
 func(u,x) starting from "xinit".

 "Not quite" because it minimizes a general function, given an
 implementation of the function, and of its 1st (gradient vector) and
 2nd (Hessian matrix) derivatives, while Levenberg-Marquart is for
 minimizing a sum-of-squares, given a (vector-valued) function and its
 1st derivatives.

 Somewhat like Levenberg-Marquardt in the way of avoiding the pitfall
 of Newton methods that are not garanteed to be non-increasing.

 So it's some sort of bastard optimization function ...

 Arguments :

 - xinit is a N-by-1 column vector. 

 - "func" is the cost function : v = func(u,x), or v = func(u,x,y) if
   an extra argument "y" is specified amongst the options.

 - "d2func" returns the cost (1x1), its differential (1xN) and the
   *pseudo-inverse* of its second differential (NxN) :

    [v,dv,d2v]=d2func(u,x[,y]). "y" is again optional.

 Options :

 "vinit",v     : Value of the function at xinit. Saves one evaluation.

 "maxouter", m : Max number of outer loop iterations (default : 500)

 "maxinner", m : Max number of inner loop iterations (default :  30)

 "mimprov", w  : Stop if best_value over new_best_value is above w,
                 which should be 0<w<1.              (default:0.999)

 "mingrad", w  : Stop if gradient has 2-norm smaller than w. 
                 (default : eps) 

 "y",       y  : Extra argument to func,d2func.

 "code",code   : The passed string will be evaluated after each outer
                 loop that produced some (any) improvement. "x", the
                 best parameter found, "v" the best value and
                 eventually "y" are visible from the code.

 Last modified: March 2000



Cross-Reference Information

This function calls

Listing of function file tmp_for_tar/levmar/levmar_min.m

##       [x,v,niter,h,y] = levmar_min(u,func,d2func,xinit,options)
##        ^ ^  ^    ^ ^
##        | |  |    | \ 
##        | |  |    \  See below
##        | |   \    Pseudo-inverse of Hessian
##        |  \   Number of iterations
##        |   Value at x
## Best "x" found
##
## Not-quite Levenberg-Marquardt method for minimizing the norm of
## func(u,x) starting from "xinit".
##
## "Not quite" because it minimizes a general function, given an
## implementation of the function, and of its 1st (gradient vector) and
## 2nd (Hessian matrix) derivatives, while Levenberg-Marquart is for
## minimizing a sum-of-squares, given a (vector-valued) function and its
## 1st derivatives.
##
## Somewhat like Levenberg-Marquardt in the way of avoiding the pitfall
## of Newton methods that are not garanteed to be non-increasing.
##
## So it's some sort of bastard optimization function ...
## 
## Arguments :
##
## - xinit is a N-by-1 column vector. 
##
## - "func" is the cost function : v = func(u,x), or v = func(u,x,y) if
##   an extra argument "y" is specified amongst the options.
##
## - "d2func" returns the cost (1x1), its differential (1xN) and the
##   *pseudo-inverse* of its second differential (NxN) :
##
##    [v,dv,d2v]=d2func(u,x[,y]). "y" is again optional.
##
## Options :
##
## "vinit",v     : Value of the function at xinit. Saves one evaluation.
##
## "maxouter", m : Max number of outer loop iterations (default : 500)
##
## "maxinner", m : Max number of inner loop iterations (default :  30)
##
## "mimprov", w  : Stop if best_value over new_best_value is above w,
##                 which should be 0<w<1.              (default:0.999)
##
## "mingrad", w  : Stop if gradient has 2-norm smaller than w. 
##                 (default : eps) 
##
## "y",       y  : Extra argument to func,d2func.
##
## "code",code   : The passed string will be evaluated after each outer
##                 loop that produced some (any) improvement. "x", the
##                 best parameter found, "v" the best value and
##                 eventually "y" are visible from the code.

## Author:        Etienne Grossmann  <etienne@isr.ist.utl.pt>
## Last modified: March 2000

function [xbest,vbest,niter,hbest,y] = \
      levmar_min(u,func,d2func,xinit,...)

## Sometimes I suspect modified sources are not recompiled. This
## static variable is displayed each time this func is called, and
## should change at (almost) each recompilation.

## static dummy_levmar = floor(100*rand());
## dummy_levmar 

# Set the defaults (not all) #########################################
vinit = nan ;			# maximum distance

maxouter = 500 ;			
maxinner = 30 ;
mimprov = 0.999 ;
mingrad = eps ;

tcoeff = 0.5 ;			# Discount on total weight
ncoeff = 0.5 ;			# Discount on weight of newton
ocoeff = 1.5 ;			# Factor for outwards searching

report = 0 ;			# Never report
verbose = 0 ;			# Be quiet
prudent = 0 ;			# Check coherence of d2func and func?

niter = 0 ;
neval = 0 ;


## d2func = dfunc = 0 ;

# ####################################################################
# Read the options ###################################################
# ####################################################################
# Options with a value
opt1 = " vinit maxouter maxinner report mimprov mingrad code y " ;
# Boolean options 
opt0 = " verbose prudent " ;

va_start() ;
nargin = nargin - 4 ;
while nargin>0 ,
  tmp = va_arg() ; nargin-- ;
  if ! isstr(tmp) ,
    break			# Last option has been read. "tmp" is
				# first arg.
  end
  if index(opt1,[" ",tmp," "]) ,
    
    tmp2 = va_arg() ; nargin-- ;
    nargin-- ;
    eval([tmp,"=tmp2;"]) ;

    sayif(verbose ,"levmar_min : Read option : %s.\n",tmp) ;

  elseif index(opt0,[" ",tmp," "]) ,
    
    eval([tmp,"=1;"]) ;
    sayif(verbose ,"levmar_min : Read boolean option : %s\n",tmp) ;

  else
    printf("levmar_min : Unknown option : %s\n",tmp) ;
    keyboard
  end
endwhile

############################## Checking ##############################
if mimprov<=0 || mimprov>=1,
  printf("levmar_min : mimprov=%8.3g is not in ]0,1[ \n",mimprov) ;
  keyboard
end

if !isstr(d2func) && !isstr(dfunc),
  printf("levmar_min : I need dfunc and d2func to be strings!\n");
  keyboard
end

x = xinit ;
N = prod(size(x)) ;
x = reshape(x,N,1) ;

if isnan(vinit) , 
  if exist("y")==1,  v = feval( func , u, x, y ) ; 
  else               v = feval( func , u, x ) ; 
  end
else                 v = vinit ; 
end
## keyboard

xbest = x ;
vold = vbest = nan ;
hbest = nan ;

sayif( verbose,"levmar_min : Initially, v=%8.3g\n",v);

while niter++ <= maxouter ,

  if exist("y")==1, [v,d,h] = feval(d2func,u,x,y) ;
  else              [v,d,h] = feval(d2func,u,x) ;
  end

  if prudent,
    if exist("y")==1, v2 = feval(func,u,x,y) ;
    else              v2 = feval(func,u,x) ;
    end
    if abs(v2-v)>0.001*sqrt(eps),
      printf("levmar_min : func and d2func disagree %8.3g\n",abs(v2-v));
      keyboard
    end
  end
  xbest = x ;
  vold = vbest = v ;
  hbest = h ;

  ## printf("vold=%8.3g , v=%8.3g *****************************\n",vold,v);
  
  sayif( verbose || report && (rem(niter,report) == 1) ,...
	"levmar_min : niter=%d, v=%8.3g\n",niter,v ); 
  wn = 1 ;			# Weight of Newton step
  wt = 1 ;			# Total weight

  if msq(d) < mingrad,
    sayif( verbose || report ,...
	  "levmar_min : exiting 'cause low gradient\n");
    ## keyboard
    break
  end

  dnewton = -h*d' ;
  done_inner = 0;		# 0=not found. 1=Ready to quit inner.

  ninner = 0 ;
  while ninner++ < maxinner,
		       
    dx = wt*(wn*dnewton - (1-wn)*d') ;
    xnew = x+dx ;

    sayif( verbose, ...
	  ["Weight : total=%8.3g, newtons's=%8.3g  vbest=%8.3g ",...
	   "Norm:Newton=%8.3g, deriv=%8.3g\n"],...
	  wt,wn,vbest,norm(wt*wn*dnewton),norm(wt*(1-wn)*d'));
    
    if any(isnan(xnew)),
      printf("levmar_min : Whoa!! any(isnan(xnew)) (1)\n"); 
      keyboard
    end
    
    if exist("y")==1, vnew = feval( func , u, xnew, y ) ; 
    else              vnew = feval( func , u, xnew ) ; 
    end
    ## vnew = feval(func,u,xnew) ;
    neval++ ;
    if vnew<vbest ,
      dbest = dx ; vbest = vnew; xbest = xnew; 
      done_inner = 1 ;		# Will go out at next increase
      sayif( verbose,"levmar_min : going down\n" );
      
    elseif done_inner == 1,	# Time to go out
      sayif( verbose,"levmar_min : quitting %d th inner loop\n",niter); 
      break			
    end
    wt = wt*tcoeff ;
    wn = wn*ncoeff ;
  end				# End of inner loop

  if ninner >= maxinner ,	# There was a problem
    printf("levmar_min : inner looping forever (vnew=%8.3g)\n",vnew);

  else				# Look for improvement along dbest
    wn = 1.5 ; 
    xnew = x+wn*dbest;
    if any(isnan(xnew)),
      printf("levmar_min : Whoa!! any(isnan(xnew)) (1)\n"); 
      keyboard
    end
    if exist("y")==1, vnew = feval( func , u, xnew, y ) ; 
    else              vnew = feval( func , u, xnew ) ; 
    end
    ## vnew = feval(func,u,xnew) ;
    while vnew < vbest,
      vbest = vnew; xbest = xnew; 
      wn = wn*ocoeff ;
      xnew = x+wn*dbest;
      if exist("y")==1, vnew = feval( func , u, xnew, y ) ; 
      else              vnew = feval( func , u, xnew ) ; 
      end
      ## vnew = feval(func,u,xnew) ;
    end
  end				# End of improving along dbest
  if verbose || rem(niter,report) == 1,...
    if vold,
      printf("levmar_min : done inner vbest=%8.5g, vbest/vold=%8.5g\n",...
	     vbest,vbest/vold);
    else
      printf("levmar_min : done inner vbest=%8.5g, vold=0\n",...
	     vbest);
    end
  end
  if vbest < vold ,
    if prudent,
      tmpv = feval(func,u,xbest,y);
      if abs(tmpv-vbest)>eps,
	printf("levmar_min : Whoa! best value is changing\n");
	keyboard
      end
    end
    v = vbest; x = xbest;
    if exist("code")==1, 
      sayif( verbose,"levmar_min : Gonna eval(\"%s\"\n",code); 
      eval(code); 
      if prudent,
	tmpv = feval(func,u,x,y);
	if abs(tmpv-vbest)>eps,
	  printf("levmar_min : Whoa! best value changes after eval(code)\n");
	  keyboard
	end
      end
    end
  end
  ## printf("vold=%8.3g , v=%8.3g, vbest=%8.3g\n",vold,v,vbest);
  ## [feval( func , u, x, y ), feval( d2func , u, x, y ) , v; ...
  ## feval( func , u, xbest, y ), feval( d2func , u, xbest, y ) , vbest  ]
  if vbest > mimprov*vold , 
    if verbose || report ,
      printf("levmar_min : quitting, niter=%-3d v=%8.3g, ",niter,v);
      if vold, printf("v/vold=%8.3g ",v/vold);
      else     printf("vold  =0     ",v);
      end
    end
    ## keyboard
    break ; 
  end   
end

if niter >= maxouter ,
  printf("levmar_min : outer looping forever\n");
end

Produced by oct2html on Mon Mar 13 20:23:26 2000
Cross-Directory links are: ON