[R-sig-ME] Contribution to lme4Eigen
Joehanes, Roby (NIH/NHLBI) [F]
roby.joehanes at nih.gov
Thu Mar 1 20:15:54 CET 2012
Ouch. Apparently, the mail daemon ate my attachment.
So, here it is (pasted). Sorry for the mail bomb.
-----------------------
lmer <- function(formula, data, REML = TRUE, sparseX = FALSE,
control = list(), start = NULL,
verbose = 0L, subset, weights, na.action, offset,
contrasts = NULL, devFunOnly=FALSE, optimizer=c("NelderMead","bobyqa"), ...)
{
if (sparseX) warning("sparseX = TRUE has no effect at present")
mf <- mc <- match.call()
## '...' handling up front, safe-guarding against typos ("familiy") :
if(length(l... <- list(...))) {
if (!is.null(l...$family)) { # call glmer if family specified
mc[[1]] <- as.name("glmer")
return(eval(mc, parent.frame()) )
}
## Check for method argument which is no longer used
if (!is.null(method <- l...$method)) {
msg <- paste("Argument", sQuote("method"), "is deprecated.")
if (match.arg(method, c("Laplace", "AGQ")) == "Laplace") {
warning(msg)
l... <- l...[names(l...) != "method"]
} else stop(msg)
}
if(length(l...))
warning("extra argument(s) ",
paste(sQuote(names(l...)), collapse=", "),
" disregarded")
}
stopifnot(length(formula <- as.formula(formula)) == 3)
if (missing(data)) data <- environment(formula)
# evaluate and install the model frame :
m <- match(c("data", "subset", "weights", "na.action", "offset"),
names(mf), 0)
mf <- mf[c(1, m)]
mf$drop.unused.levels <- TRUE
mf[[1]] <- as.name("model.frame")
fr.form <- subbars(formula) # substituted "|" by "+" -
environment(fr.form) <- environment(formula)
mf$formula <- fr.form
fr <- eval(mf, parent.frame())
# random effects and terms modules
reTrms <- mkReTrms(findbars(formula[[3]]), fr)
if (any(unlist(lapply(reTrms$flist, nlevels)) >= nrow(fr)))
stop("number of levels of each grouping factor must be less than number of obs")
## fixed-effects model matrix X - remove random effects from formula:
form <- formula
form[[3]] <- if(is.null(nb <- nobars(form[[3]]))) 1 else nb
X <- model.matrix(form, fr, contrasts)#, sparse = FALSE, row.names = FALSE) ## sparseX not yet
p <- ncol(X)
if ((qrX <- qr(X))$rank < p)
stop(gettextf("rank of X = %d < ncol(X) = %d", qrX$rank, p))
rho <- new.env(parent=parent.env(environment()))
rho$pp <- do.call(merPredD$new, c(reTrms[c("Zt","theta","Lambdat","Lind")], n=nrow(X), list(X=X)))
rho$resp <- mkRespMod(fr, if(REML) p else 0L)
devfun <- mkdevfun(rho, 0L)
devfun(reTrms$theta) # one evaluation to ensure all values are set
if (devFunOnly) return(devfun)
lower <- reTrms$lower
# RJ's changes begin
opt <- switch(match.arg(optimizer),
bobyqa = {
if(!is.numeric(control$rhobeg)) control$rhobeg <- 0.0002
if(!is.numeric(control$rhoend)) control$rhoend <- 2e-7
rho$control <- control
# Delete unused options to prevent warning from showing up
control$FtolAbs <- NULL
control$FtolRel <- NULL
bobyqa(rho$pp$theta, devfun, lower, control=control)
},
NelderMead = {
## FIXME: this code is replicated in lmer/glmer/nlmer ...
## it seems good to have it in R rather than C++ code but maybe it should go within Nelder_Mead() ??
control$iprint <- switch(as.character(min(verbose,3L)), "0"=0, "1"=20,"2"=10,"3"=1)
xst <- rep.int(0.1, length(lower))
# RJ -- allow user control of xst, xt
ctl <- control
if(!is.numeric(control$xstFactor))
xstFactor <- 0.2
else
xstFactor <- control$xstFactor
if(!is.numeric(control$xtFactor))
xtFactor <- 0.0001
else
xtFactor <- control$xtFactor
ctl$xstFactor <- NULL
ctl$xtFactor <- NULL
Nelder_Mead(devfun, x0=rho$pp$theta, xst=xstFactor*xst, xt=xst*xtFactor, lower=lower, control=ctl)
})
if(optimizer=="NelderMead") {
if (opt$ierr < 0L) {
if (opt$ierr > -4L)
stop("convergence failure, code ", opt$ierr, " in NelderMead")
else
warning("failure to converge in", opt$control$maxfun, "evaluations")
}
} else if (optimizer=="bobyqa") {
if (opt$ierr > 0L)
warning("convergence problem, code ", opt$ierr, " in bobyqa")
}
# RJ's changes end
mkMerMod(environment(devfun), opt, reTrms, fr, mc)
}## { lmer }
On Mar 1, 2012, at 2:11 PM, Joehanes, Roby (NIH/NHLBI) [F] wrote:
> Hi lme4 developers,
>
> I hope I can contribute to something positive to the community. I noticed that even in the latest version of lme4Eigen the lmer function only use Nelder-Mead optimizer. I would like to get Bobyqa optimizer back as an option (because I really like Bobyqa optimizer). So, I patched the code a little bit. I used the (hopefully) latest revision from SVN version 1631. I also added control for xst and xt factor multiplier (a FIXME item list). I hope this change is also acceptable. If you feel I am ignorant of your code style, I apologize.
>
> Here is the code (only the lmer function). I clearly marked my changes. If you need a diff file with the current HEAD, I'll be happy to provide you with one. The function seems to be running happily without error or warning on my machine. I hope the changes can make it to the main trunk.
>
> Sincerely,
> Roby
More information about the R-sig-mixed-models
mailing list