Wrappers to allow use of alternative optimizers, from the NLopt
library (via list("nloptr")) or elsewhere, for the nonlinear optimization stage.
nloptwrap (par, fn, lower, upper, control = list(),...)nlminbwrap(par, fn, lower, upper, control = list(),...)
Arguments
par: starting parameter vector
fn: objective function
lower, upper: numeric vector of lower and upper bounds.
control: list of control parameters, corresponding to optCtrl = *, e.g., in lmerControl(). For nloptwrap, see defaultControl in Details .
...: additional arguments to be passed to objective function
Returns
par: estimated parameters
fval: objective function value at minimum
feval: number of function evaluations
conv: convergence code (0 if no error)
message: convergence message
Details
Using alternative optimizers is an important trouble-shooting tool for mixed models. These wrappers provide convenient access to the optimizers provided by Steven Johnson's NLopt library (via the list("nloptr") R package), and to the nlminb
optimizer from base R. nlminb is also available via the list("optimx") package; this wrapper provides access to nlminb()
without the need to install/link the package, and without the additional post-fitting checks that are implemented by list("optimx") (see examples below).
One important difference between the list("nloptr")-provided implementation of BOBYQA and the list("minqa")-provided version accessible via optimizer="bobyqa" is that it provides simpler access to optimization tolerances. bobyqa provides only the rhoend parameter ([t]he smallest value of the trust region radius that is allowed ), while nloptr provides a more standard set of tolerances for relative or absolute change in the objective function or the parameter values (ftol_rel, ftol_abs, xtol_rel, xtol_abs).
The default (empty) control list corresponds to the following settings:
nlminbwrap:: control exactly corresponds to nlminb()'s defaults, see there.
nloptwrap:: environment(nloptwrap)$defaultControl
contains the defaults, notably `algorithm = "NLOPT_LN_BOBYQA"`.
`nloptr::nloptr.print.options()` shows and explains the many possible algorithm and options.
Examples
library(lme4)ls.str(environment(nloptwrap))# 'defaultControl' algorithm "NLOPT_LN_BOBYQA"## Note that 'optimizer = "nloptwrap"' is now the default for lmer() :fm1 <- lmer(Reaction ~ Days +(Days|Subject), sleepstudy)## tighten tolerancesfm1B <- update(fm1, control= lmerControl(optCtrl = list(xtol_abs=1e-8, ftol_abs=1e-8)))## run for longer (no effect in this case)fm1C <- update(fm1,control = lmerControl(optCtrl = list(maxeval=10000))) logLik(fm1B)- logLik(fm1)## small difference in log likelihoodc(logLik(fm1C)- logLik(fm1))## no difference in LL## Nelder-Meadfm1_nloptr_NM <- update(fm1, control= lmerControl(optimizer ="nloptwrap", optCtrl = list(algorithm ="NLOPT_LN_NELDERMEAD")))## other nlOpt algorithm options include NLOPT_LN_COBYLA, NLOPT_LN_SBPLX, seeif(interactive()) nloptr::nloptr.print.options()fm1_nlminb <- update(fm1, control=lmerControl(optimizer ="nlminbwrap"))if(require(optimx)){## the 'optimx'-based nlminb : fm1_nlminb2 <- update(fm1, control= lmerControl(optimizer ="optimx", optCtrl = list(method="nlminb", kkt=FALSE))) cat("Likelihood difference (typically zero): ", c(logLik(fm1_nlminb)- logLik(fm1_nlminb2)),"\n")}