Perché non riesco ad abbinare l'output glmer (family = binomial) con l'implementazione manuale dell'algoritmo Gauss-Newton?


15

Vorrei abbinare le uscite di lmer (davvero glmer) con un esempio binomiale di giocattoli. Ho letto le vignette e credo di capire cosa sta succedendo.

Ma a quanto pare non lo faccio. Dopo essermi bloccato, ho corretto la "verità" in termini di effetti casuali e ho seguito solo la stima degli effetti fissi. Sto includendo questo codice di seguito. Per vedere che è legittimo, puoi commentare + Z %*% b.ke corrisponderà ai risultati di un glm regolare. Spero di prendere in prestito un po 'di potere mentale per capire perché non sono in grado di eguagliare l'output di lmer quando sono inclusi gli effetti casuali.

# Setup - hard coding simple data set 
df <- data.frame(x1 = rep(c(1:5), 3), subject = sort(rep(c(1:3), 5)))
df$subject <- factor(df$subject)

# True coefficient values  
beta <- matrix(c(-3.3, 1), ncol = 1) # Intercept and slope, respectively 
u <- matrix(c(-.5, .6, .9), ncol = 1) # random effects for the 3 subjects 

# Design matrices Z (random effects) and X (fixed effects)
Z <- model.matrix(~ 0 + factor(subject), data = df)
X <- model.matrix(~ 1 + x1, data = df)

# Response  
df$y <- c(1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1)
    y <- df$y

### Goal: match estimates from the following lmer output! 
library(lme4)
my.lmer <- lmer( y ~ x1 + (1 | subject), data = df, family = binomial)
summary(my.lmer)
ranef(my.lmer)

### Matching effort STARTS HERE 

beta.k <- matrix(c(-3, 1.5), ncol = 1) # Initial values (close to truth)
b.k <- matrix(c(1.82478, -1.53618, -.5139356), ncol = 1) # lmer's random effects

# Iterative Gauss-Newton algorithm
for (iter in 1:6) {
  lin.pred <- as.numeric(X %*% beta.k +  Z %*% b.k)
  mu.k <- plogis(lin.pred)
  variances <- mu.k * (1 - mu.k)
  W.k <- diag(1/variances)

  y.star <- W.k^(.5) %*% (y - mu.k)
  X.star <- W.k^(.5) %*% (variances * X)
  delta.k <- solve(t(X.star) %*% X.star) %*% t(X.star) %*% y.star

  # Gauss-Newton Update 
  beta.k <- beta.k + delta.k
  cat(iter, "Fixed Effects: ", beta.k, "\n")
}

Risposte:


28

Se si modifica il comando di adattamento del modello nel modo seguente, l'approccio corrispondente funziona:

my.lmer <- glmer(y ~ x1 + (1 | subject), data = df, family = binomial, nAGQ = 0)

Il cambiamento chiave è il nAGQ = 0, che corrisponde al tuo approccio, mentre il default ( nAGQ = 1) no. nAGQsignifica "numero di punti adattativi di quadratura di Gauss-Hermite" e stabilisce come glmerintegrare gli effetti casuali quando si adatta il modello misto. Quando nAGQè maggiore di 1, viene utilizzata la quadratura adattiva con i nAGQpunti. QuandonAGQ = 1 viene utilizzata l'approssimazione di Laplace e quando nAGQ = 0l'integrale viene "ignorato". Senza essere troppo specifici (e quindi forse troppo tecnici), nAGQ = 0significa che gli effetti casuali influenzano le stime degli effetti fissi solo attraverso le loro modalità condizionate stimate - pertanto,nAGQ = 0non tiene conto completamente della casualità degli effetti casuali. Per rendere pienamente conto degli effetti casuali, devono essere integrati. Tuttavia, come hai scoperto questa differenza tra nAGQ = 0e nAGQ = 1spesso può essere abbastanza piccola.

Il tuo approccio di abbinamento non funzionerà nAGQ > 0. Questo perché in questi casi ci sono tre passaggi per l'ottimizzazione: (1) penalizzato i minimi quadrati iterativamente ripesati (PIRLS) per stimare le modalità condizionali degli effetti casuali, (2) (approssimativamente) integrare gli effetti casuali sulle loro modalità condizionali e (3) ottimizzazione non lineare della funzione obiettivo (ovvero il risultato dell'integrazione). Questi passaggi vengono ripetuti fino alla convergenza. Stai semplicemente eseguendo una corsa di minimi quadrati (IRLS) ripetutamente ripetuta, che presume bsia nota e sta inserendo Z%*%bun termine di offset. Il tuo approccio risulta essere equivalente a PIRLS, ma questa equivalenza vale solo perché usi glmerper ottenere modalità condizionate stimate (che altrimenti non sapresti).

Ci scusiamo se questo non è ben spiegato, ma non è un argomento che si presta bene ad una breve descrizione. Potresti trovare utile https://github.com/lme4/lme4pureR , che è un'implementazione (incompleta) lme4dell'approccio in puro codice R. lme4pureRè progettato per essere più leggibile di lme4se stesso (anche se molto più lento).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.