AIC, anova error: Моделі не всі підходили до однакової кількості спостережень, моделі не всі були встановлені на однаковий розмір набору даних


10

У мене є такі моделі:

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)

Зараз я намагаюся оцінити, чи має бути випадковий ефект у моделі. Тому я порівнюю моделі, що використовують AIC або anova, і отримую таку помилку:

> 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

Як бачите, в обох випадках я використовую один і той же набір даних. Я знайшов два засоби захисту, але не вважаю їх задоволеннями:

  1. Додавання method = "ML"до виклику lme () - не впевнений, чи корисно змінити метод.
  2. Використовуючи lmer()замість цього. Дивно, але це працює, незважаючи на те, що lmer () використовує метод REML. Однак мені не подобається це рішення, оскільки lmer()не показує значення p для коефіцієнтів - я люблю використовувати старіші lme().

Чи маєте ви уявлення, це помилка чи ні, і як ми можемо обійти це?

Відповіді:


7

Швидкий пошук показує, що це можливо (хоча я повинен визнати, що я думав, що це не так) і що це не помилка ... просто інший випадок, коли методи в R приховані і призводять до того, що здається "несподіваним ", але натовп RTFM кажуть:" Це в документації ". У будь-якому випадку ... ваше рішення anovaстосується lmeяк першого аргументу, так і lmмоделей як другого (і третього, якщо вам подобається) аргументів. Якщо це здається дивним, це тому, що це трохи дивно. Причина полягає в тому, що при виклику anova, то anova.lmeвикликається метод , тільки якщо перший аргумент є lmeоб'єктом. В іншому випадку він дзвонить anova.lm(що в свою чергу дзвонить anova.lmlist; якщо ви заглибитесь anova.lm, ви побачите чому). Докладніше про те, як ви хочете телефонуватиanovaу цьому випадку підтягніть довідку anova.lme. Ви побачите, що ви можете порівнювати інші моделі з lmeмоделями, але вони повинні бути в іншій позиції, ніж перший аргумент. Мабуть, це також можна використовувати anovaна моделях, які відповідають glsфункції, не надто піклуючись про порядок аргументів моделі. Але я не знаю достатньо деталей, щоб визначити, чи це гарна ідея чи ні, або що саме це має на увазі (це, мабуть, добре, але ваш дзвінок). З цього посилання порівняння lmз lmeвидається добре задокументованим і цитується як метод, тож я б помилився в цьому напрямку, якби ти був.

Удачі.


1
О, і відповідь user11852 щодо АПК з доповненням Гевіна, немає спеціального AIC.lme або нічого, щоб вирішити цю проблему, і вся справа починає виходити за межі моєї категорії оплати
russellpierce

4

Це властиво однозначно. Перша думка: коли ми робимо порівняння моделей, коли моделі мають різні структури фіксованих ефектів ( m2і, m3наприклад,), нам найкращеМLяк REML"зміниться"у. (Це примножить його нак, де кХ=0) Це цікаво, що він працює за допомогою method="ML"якого змушує мене повірити, що це не помилка. Здається, майже так, як це застосовує "добру практику".

Сказавши це, давайте подивимось під капот:

 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")
     }     
 }

де у вашому випадку ви бачите це:

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

і очевидно logLikробить щось (можливо?) несподіване ...? ні, не дуже, якщо ви подивитеся на документацію logLik, ?logLikпобачите, що це прямо вказано:

 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’)

що повертає нас до початкової точки, яку ви повинні використовувати ML.

Використовувати загальну приказку в CS: "Це не помилка; це (реальна) особливість!"

РЕДАКТИРУЙТЕ : (Просто для вирішення Вашого коментаря :) Припустимо, Ви використовуєте іншу модель, використовуючи lmerцей час:

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

і ви робите наступне:

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

Це здається очевидним розбіжністю між ними, але насправді це не так, як пояснив Гевін. Просто констатуйте очевидне:

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

Є вагома причина, чому це відбувається з точки зору методології, я думаю. lmeнамагається зрозуміти регрес LME для вас, коли lmerпри порівнянні моделей вона одразу повертається до результатів ML. Я думаю, що в цьому питанні немає жодних помилок, lmeа lmerза різними обгрунтуваннями за кожним пакетом.

Дивіться також коментар Гевіна Сімпосона щодо більш проникливого пояснення того, що було далі anova()(те ж саме відбувається і з AIC)


"Ви повинні використовувати ML" - але як ви можете пояснити, що lmerвикористовується REML (див. резюме моделі) та працює добре в AIC? Отже, є дві можливості: 1) повідомлення про помилку - це * функція , а не помилка, а те, для чого вона працює, lmer- це помилка. Або 2) повідомлення про помилку - це помилка , а не функція.
Цікаво

Дивіться оновлений пост (мені довелося включити якийсь код). Я сам помітив вашу дійсну точку під час написання вашої оригінальної відповіді, але спочатку я вирішив не допустити цього, тому обґрунтування моєї відповіді суворо ґрунтується на обчисленнях.
usεr11852

4
@Tomas lmer() не використовує REML, коли ви запитуєте його порівняння. У IIRC вони включали деякий фантазійний цукор, lmer()тому вам не довелося переробляти модель, MLщоб просто порівняти підходи, коли ви хочете, REMLщоб окремі підходи отримували найкращі оцінки параметрів дисперсії. Подивіться ?lmer, запустіть перший приклад LME до та включаючи anova(fm1, fm2)виклик. Подивіться на ймовірності журналу, про які повідомлялося, anova()та ті, про які повідомлялося раніше, у друкованому випуску. anova()Оцінки стає ML для вас.
Гевін Сімпсон

Хороший момент, Гевін, я забуваю, що lmerотримав і те й інше (він використовує PLS, тому він одночасно оцінює лише один). Я забув перевірити те, що ви згадали.
usεr11852

2
@rpierce: АІК повідомили вanova() це один заснований на ML. Звіт про АПК AIC()- це лише той, який базується на REML.
usεr11852
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.