I have a GLMM with a binomial distribution and a logit link function and I have the feeling that an important aspect of the data is not well represented in the model.

To test this, I would like to know whether or not the data is well described by a linear function on the logit scale. Hence, I would like to know whether the residuals are well-behaved. However, I can not find out at which residuals plot to plot and how to interpret the plot.

Note that I am using the new version of lme4 (the development version from GitHub):

## [1] ‘1.1.0’

My question is: How do I inspect and interpret the residuals of a binomial generalized linear mixed models with a logit link function?

The following data represents only 17% of my real data, but fitting already takes around 30 seconds on my machine, so I leave it like this:

options(contrasts=c('contr.sum', 'contr.poly'))

dat <- read.table("http://pastebin.com/raw.php?i=vRy66Bif")
dat$V1 <- factor(dat$V1)

m1 <- glmer(true ~ distance*(consequent+direction+dist)^2 + (direction+dist|V1), dat, family = binomial)

The simplest plot (?plot.merMod) produces the following:


enter image description here

Does this already tell me something?

  • 1
    $\begingroup$ I might find time to come back and take a crack at this, but I think the general answer is that it's hard to do a great deal with the residuals from binary models. My main discovery so far from zooming in on a bit on the plot you have above, and adding a smoothed line (using type=c("p","smooth") in plot.merMod, or moving to ggplot if you want confidence intervals) is that it looks like there's a small but significant pattern, which you might be able to fix by adopting a different link function. That's it so far ... $\endgroup$ – Ben Bolker Oct 2 '13 at 15:00
  • $\begingroup$ @BenBolker Thanks. And can you not just post this and the link to freakonomics as a response to the question? Then at least you would get the 150 points. $\endgroup$ – Henrik Oct 2 '13 at 15:32
  • 3
    $\begingroup$ I found this CV thread, stats.stackexchange.com/questions/63566/…, to be very helpful. The post explains how to create a binned residuals plot in R. $\endgroup$ – Nova Aug 18 '14 at 20:09
  • $\begingroup$ @Henrik Would you please explain me how does the model true ~ distance*(consequent+direction+dist)^2 + (direction+dist|V1) work ? Will the model give estimate of interaction between distance*consequent , distance*direction , distance*dist and slope of direction and dist that varies with V1 ? What does the square in (consequent+direction+dist)^2 denote ? $\endgroup$ – ABC Jul 20 '15 at 10:48
  • $\begingroup$ @Henrik I ran your code and it shows the Warning message: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model failed to converge with max|grad| = 0.123941 (tol = 0.001, component 1) . Why ? $\endgroup$ – ABC Jul 20 '15 at 10:49

Short answer since I don't have time for better: this is a challenging problem; binary data almost always requires some kind of binning or smoothing to assess goodness of fit. It was somewhat helpful to use fortify.lmerMod (from lme4, experimental) in conjunction with ggplot2 and particularly geom_smooth() to draw essentially the same residual-vs-fitted plot you have above, but with confidence intervals (I also narrowed the y limits a bit to zoom in on the (-5,5) region). That suggested some systematic variation that could be improved by tweaking the link function. (I also tried plotting residuals against the other predictors, but it wasn't too useful.)

I tried fitting the model with all 3-way interactions, but it wasn't much of an improvement either in deviance or in the shape of the smoothed residual curve.

Then I used this bit of brute force to try inverse-link functions of the form $(\mbox{logistic}(x))^\lambda$, for $\lambda$ ranging from 0.5 to 2.0:

## uses (fragile) internal C calls for speed; could use plogis(),
##  qlogis() for readability and stability instead
logitpower <- function(lambda) {
    L <- list(linkfun=function(mu)
              mu.eta=function(eta) {
                  mu <-  .Call(stats:::C_logit_linkinv,eta,PACKAGE="stats")
                  mu.eta <-  .Call(stats:::C_logit_mu_eta,eta,PACKAGE="stats")
              valideta = function(eta) TRUE ,
    class(L) <- "link-glm"

I found that a $\lambda$ of 0.75 was slightly better than the original model, although not significantly so -- I may have been overinterpreting the data.

See also: http://freakonometrics.hypotheses.org/8210

| cite | improve this answer | |

This is very common theme on biostatistics/epidemiology courses, and there are not very good solutions for it, basically due to the nature of the model. Often the solution has been to avoid detailed diagnostics using the residuals.

Ben already wrote that diagnostics often require either binning or smoothing. Binning of residuals is (or was) available in the R package arm, see e.g., this thread. In addition, there are some work done that uses predicted probabilities; one possibility is the separation plot that has been discussed earlier in this thread. Those might or might not directly help in your case, but could possible help the interpretation.

| cite | improve this answer | |

You can plot the residuals against the predictors using simulation techniques in DHARMa package, it also offers a range of diagnostics such as overdispersion, and outliers, I think its a practical and simple assessment tool for GLMM. Check it out: https://cran.r-project.org/web/packages/DHARMa/vignettes/DHARMa.html

| cite | improve this answer | |

You could use AIC instead of residual plots to check fit of model. Command in R: AIC(model1) it will give you a number...so then you need to compare this with another model (with more predictors, for example) -- AIC(model2), which will yield another number. Compare the two outputs, and you'll want the model with the lower AIC value.

By the way, things like AIC and log likelihood ratio are already listed when you get the summary of your glmer model, and both will give you useful info on fit of model. You want a large negative number for log likelihood ratio to reject the null hypothesis.

| cite | improve this answer | |
  • 4
    $\begingroup$ This would be more useful if OP was trying to compare competing models, but it doesn't seem like that's what they're trying to do, and AIC cannot be used to evaluate absolute model fit. $\endgroup$ – Patrick Coulombe Mar 18 '16 at 1:04

Fitted vs residuals plot should not show any (clear) pattern. The plot shows that the model does not work well with the data. See http://www.r-bloggers.com/model-validation-interpreting-residual-plots/

| cite | improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.