AIC, errore anova: i modelli non sono tutti adattati allo stesso numero di osservazioni, i modelli non sono stati tutti adattati alla stessa dimensione del set di dati


9

Ho modelli come questo:

require(nlme)

set.seed(123)
n <- 100
k <- 5
cat <- as.factor(rep(1:k, n))
cat_i <- 1:k # intercept per kategorie
x <- rep(1:n, each = k)
sigma <- 0.2
alpha <- 0.001
y <- cat_i[cat] + alpha * x + rnorm(n*k, 0, sigma)
plot(x, y)

m1 <- lm(y ~ x)
summary(m1)

m2 <- lm(y ~ cat + x)
summary(m2)

m3 <- lme(y ~ x, random = ~ 1|cat, na.action = na.omit)
summary(m3)

Ora sto cercando di valutare se l'effetto casuale dovrebbe essere presente nel modello. Quindi confronto i modelli usando AIC o anova e ottengo il seguente errore:

> AIC(m1, m2, m3)
   df       AIC
m1  3 1771.4696
m2  7 -209.1825
m3  4 -154.0245
Warning message:
In AIC.default(m1, m2, m3) :
  models are not all fitted to the same number of observations  
> anova(m2, m3)
Error in anova.lmlist(object, ...) : 
  models were not all fitted to the same size of dataset

Come puoi vedere, in entrambi i casi utilizzo lo stesso set di dati. Ho trovato due rimedi, ma non li considero soddisfacenti:

  1. Aggiunta method = "ML"alla chiamata lme ​​() - non sono sicuro se è una buona idea cambiare il metodo.
  2. Usando lmer()invece. Sorprendentemente, questo funziona, nonostante il fatto che lmer () usi il metodo REML. Tuttavia, questa soluzione non mi piace perché lmer()non mostra i valori p per i coefficienti - mi piace usare lme()invece più vecchi .

Hai idea se questo è un bug o no e come possiamo aggirarlo?

Risposte:


6

Una rapida ricerca mostra che è possibile (anche se devo ammettere che pensavo non lo fosse) e che non è un bug ... solo un altro caso in cui i metodi in R sono nascosti e si traducono in cose che sembrano 'inaspettate ", ma la folla di RTFM dice" È nella documentazione ". Ad ogni modo ... la tua soluzione ha a che fare anovacon il lmeprimo argomento e i lmmodelli come secondo (e terzo se preferisci) argomento (i). Se questo sembra strano, è perché è un po 'strano. Il motivo è che quando si chiama anova, il anova.lmemetodo viene chiamato solo se il primo argomento è un lmeoggetto. Altrimenti, chiama anova.lm(che a sua volta chiama anova.lmlist; se scavi in anova.lm, vedrai perché). Per i dettagli su come si desidera chiamareanovain questo caso, chiedere aiuto per anova.lme. Vedrai che puoi confrontare altri modelli con lmemodelli, ma devono essere in una posizione diversa dal primo argomento. Apparentemente è anche possibile usare anovasu modelli adatti usando la glsfunzione senza preoccuparsi troppo dell'ordine degli argomenti del modello. Ma non conosco abbastanza i dettagli per determinare se questa è una buona idea o no, o cosa implica esattamente (sembra probabilmente bene, ma la tua chiamata). Da che puntano a confronto lma lmesembra essere ben documentato e ha citato come un metodo, quindi mi piacerebbe erro in quella direzione, fossi in te.

In bocca al lupo.


1
Oh, e la risposta di user11852 in merito ad AIC con l'appendice di Gavin, non c'è AIC.lme speciale o altro per affrontare quel problema e l'intera cosa inizia a scivolare oltre il mio voto
russellpierce

3

m2m3MLREMLykkX=0method="ML"

Detto questo, diamo un'occhiata sotto il cofano:

 methods(AIC)  
 getAnywhere('AIC.default')

 A single object matching AIC.default was found
 It was found in the following places
   registered S3 method for AIC from namespace stats
   namespace:stats with value

 function (object, ..., k = 2) 
 {
     ll <- if ("stats4" %in% loadedNamespaces()) 
         stats4:::logLik
     else logLik
     if (!missing(...)) {
         lls <- lapply(list(object, ...), ll)
         vals <- sapply(lls, function(el) {
             no <- attr(el, "nobs") #THIS IS THE ISSUE!
             c(as.numeric(el), attr(el, "df"), if (is.null(no)) NA_integer_ else no)
         })
         val <- data.frame(df = vals[2L, ], ll = vals[1L, ])
         nos <- na.omit(vals[3L, ])
         if (length(nos) && any(nos != nos[1L])) 
             warning("models are not all fitted to the same number of observations")
         val <- data.frame(df = val$df, AIC = -2 * val$ll + k * val$df)
             Call <- match.call()
             Call$k <- NULL
         row.names(val) <- as.character(Call[-1L])
         val
     }
     else {
         lls <- ll(object)
         -2 * as.numeric(lls) + k * attr(lls, "df")
     }     
 }

dove nel tuo caso puoi vedere che:

  lls <- lapply(list(m2,m3), stats4::logLik)
  attr(lls[[1]], "nobs")
  #[1] 500
  attr(lls[[2]], "nobs")
  #[1] 498

e ovviamente logLiksta facendo qualcosa (forse?) inaspettato ...? no, non proprio, se guardi la documentazione di logLik, ?logLikvedrai che è esplicitamente dichiarato:

 There may be other attributes depending on the method used: see
 the appropriate documentation.  One that is used by several
 methods is "nobs"’, the number of observations used in estimation
 (after the restrictions if REML = TRUE’)

che ci riporta al nostro punto originale, dovresti usare ML.

Per usare un detto comune in CS: "Non è un bug; è una funzione (reale)!"

EDIT : (Solo per rispondere al tuo commento :) Supponi che ti adatti ad un altro modello usando lmerquesta volta:

m3lmer <- lmer(y ~ x + 1|cat)

e fai quanto segue:

lls <- lapply(list(m2,m3, m3lmer), stats4::logLik)
attr(lls[[3]], "nobs")
#[1] 500
 attr(lls[[2]], "nobs")
#[1] 498

Il che sembra una chiara discrepanza tra i due, ma in realtà non è come ha spiegato Gavin. Giusto per affermare l'ovvio:

 attr( logLik(lme(y ~ x, random = ~ 1|cat, na.action = na.omit, method="ML")),
 "nobs")
#[1] 500

C'è una buona ragione per cui questo accade in termini di metodologia, credo. lmecerca di dare un senso alla regressione di LME per te mentre, lmerquando si fa un confronto tra modelli, ricade immediatamente sui suoi risultati ML. Penso che non ci siano bug su questo argomento lmee lmersolo razionali differenti dietro ogni pacchetto.

Vedi anche il commento di Gavin Simposon su una spiegazione più approfondita di ciò che è anova()accaduto (la stessa cosa praticamente accade con AIC)


"dovresti usare ML" - ma come puoi spiegare che lmersta usando REML (vedi il sommario del modello) e funziona bene in AIC? Quindi ci sono due possibilità: 1) il messaggio di errore è * una funzione , non un bug, e il fatto che funzioni lmerè un bug. Oppure 2) il messaggio di errore è un bug , non una funzione.
Curioso

Vedi post aggiornato (ho dovuto includere un po 'di codice). Ho notato tu stesso il tuo punto valido quando ho scritto la tua risposta originale, ma inizialmente ho deciso di tenerlo fuori, quindi la logica alla base della mia risposta è strettamente basata sul calcolo.
usεr11852,

3
@Tomas lmer() non usa REML quando gli chiedi di fare dei confronti. IIRC includeva un po 'di zucchero fantasia in lmer()modo da non dover modificare il modello MLsolo per confrontare gli adattamenti quando si desidera REMLsugli adattamenti individuali per ottenere le migliori stime dei parametri di varianza. Guarda ?lmer, esegui il primo esempio di LME fino alla anova(fm1, fm2)chiamata inclusa . Guarda le probabilità di log riportate da anova()e quelle riportate in precedenza nell'output stampato. La anova()sta ottenendo ML stima per voi.
Gavin Simpson,

Buon punto Gavin, dimentico che li lmerho ottenuti entrambi allo stesso tempo (usa PLS, quindi va in giro a stimarne solo uno alla volta). Ho dimenticato di controllare ciò che hai menzionato.
usεr11852,

2
@rpierce: l'AIC riportato all'internoanova() è quello basato su ML. L'AIC riportato AIC()è proprio quello basato su REML.
usεr11852,
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.