Логистическая регрессия возвращает ошибку, но работает нормально на сокращенном наборе данных
Я был бы признателен за ваш вклад в этом много!
Я работаю над логистической регрессией, но по какой-то причине она не работает:
mod1<-glm(survive~reLDM2+yr+yr2+reLDM2:yr +reLDM2:yr2+NestAge0,
family=binomial(link=logexp(NSSH1$exposure)),
data=NSSH1, control = list(maxit = 50))
Когда я запускаю ту же модель с меньшим количеством данных, это работает! Но с полным набором данных я получаю сообщения об ошибках и предупреждения:
Error: inner loop 1; cannot correct step size
In addition: Warning messages:
1: step size truncated due to divergence
2: step size truncated due to divergence
Это данные: https://www.dropbox.com/s/8ib8m1fh176556h/NSSH1.csv?dl=0
Зарегистрируйте функцию связи с экспозицией из пользовательской функции связи для glmer для моделирования выживания с известной судьбой:
library(MASS)
logexp <- function(exposure = 1) {
linkfun <- function(mu) qlogis(mu^(1/exposure))
## FIXME: is there some trick we can play here to allow
## evaluation in the context of the 'data' argument?
linkinv <- function(eta) plogis(eta)^exposure
mu.eta <- function(eta) exposure * plogis(eta)^(exposure-1) *
.Call(stats:::C_logit_mu_eta, eta, PACKAGE = "stats")
valideta <- function(eta) TRUE
link <- paste("logexp(", deparse(substitute(exposure)), ")",
sep="")
structure(list(linkfun = linkfun, linkinv = linkinv,
mu.eta = mu.eta, valideta = valideta,
name = link),
class = "link-glm")
}
1 ответ
TL; д-р вы попали в беду, потому что ваш yr
а также yr2
предикторы (предположительно год и год в квадрате) в сочетании с необычной функцией связи вызывают численные проблемы; Вы можете обойти это, используя пакет glm2, но я бы, по крайней мере, немного подумал о том, имеет ли смысл в этом случае подходить к квадратному году.
Обновление: метод грубой силы с mle2
началось ниже; еще не написал это, чтобы сделать полную модель с взаимодействиями.
Народная теорема Эндрю Гельмана, вероятно, применима и здесь:
Если у вас есть вычислительные проблемы, часто есть проблема с вашей моделью.
Я начал с упрощенной версии вашей модели, без взаимодействия...
NSSH1 <- read.csv("NSSH1.csv")
source("logexpfun.R") ## for logexp link
mod1 <- glm(survive~reLDM2+yr+yr2+NestAge0,
family=binomial(link=logexp(NSSH1$exposure)),
data=NSSH1, control = list(maxit = 50))
... который отлично работает Теперь давайте попробуем увидеть, в чем проблема:
mod2 <- update(mod1,.~.+reLDM2:yr) ## OK
mod3 <- update(mod1,.~.+reLDM2:yr2) ## OK
mod4 <- update(mod1,.~.+reLDM2:yr2+reLDM2:yr) ## bad
Итак, у нас проблемы с одновременным включением обоих взаимодействий. Как эти предикторы на самом деле связаны друг с другом? Посмотрим...
pairs(NSSH1[,c("reLDM2","yr","yr2")],gap=0)
yr
а также yr2
не идеально коррелированы, но они идеально коррелируют по рангу, и, конечно, неудивительно, что они взаимно обновляются друг с другом. Обновление: конечно, год и квадрат год выглядят так! даже используя poly(yr,2)
, который создает ортогональный многочлен, в этом случае не помогает... тем не менее, стоит посмотреть на параметры в случае, если он дает подсказку...
Как уже упоминалось выше, мы можем попробовать glm2
(вставная замена для glm
с более надежным алгоритмом) и посмотрим, что произойдет...
library(glm2)
mod5 <- glm2(survive~reLDM2+yr+yr2+reLDM2:yr +reLDM2:yr2+NestAge0,
family=binomial(link=logexp(NSSH1$exposure)),
data=NSSH1, control = list(maxit = 50))
Теперь мы получаем ответ. Если мы проверим cov2cor(vcov(mod5))
мы видим, что yr
а также yr2
параметры (и параметры для их взаимодействия с reLDM2
сильно отрицательно коррелированы (около -0,97). Давайте представим, что...
library(corrplot)
corrplot(cov2cor(vcov(mod5)),method="ellipse")
Что если мы попытаемся сделать это грубой силой?
library(bbmle)
link <- logexp(NSSH1$exposure)
fit <- mle2(survive~dbinom(prob=link$linkinv(eta),size=1),
parameters=list(eta~reLDM2+yr+yr2+NestAge0),
start=list(eta=0),
data=NSSH1,
method="Nelder-Mead") ## more robust than default BFGS
summary(fit)
## Estimate Std. Error z value Pr(z)
## eta.(Intercept) 4.3627816 0.0402640 108.3545 < 2e-16 ***
## eta.reLDM2 -0.0019682 0.0011738 -1.6767 0.09359 .
## eta.yr -6.0852108 0.2068159 -29.4233 < 2e-16 ***
## eta.yr2 5.7332780 0.1950289 29.3971 < 2e-16 ***
## eta.NestAge0 0.0612248 0.0051272 11.9411 < 2e-16 ***
Это кажется разумным (вы должны проверить прогнозируемые значения и убедиться, что они имеют смысл...), но...
cc <- confint(fit) ## "profiling has found a better solution"
Это возвращает mle2
объект, но один с искаженным слотом вызова, так что это неприятно печатать результаты.
coef(cc)
## eta.(Intercept) eta.reLDM2
## 4.329824508 -0.011996582
## eta.yr eta.yr2
## 0.101221970 0.093377127
## eta.NestAge0
## 0.003460453
##
vcov(cc) ## all NA values! problem?
Попробуйте перезапустить эти возвращенные значения...
fit2 <- update(fit,start=list(eta=unname(coef(cc))))
coef(summary(fit2))
## Estimate Std. Error z value Pr(z)
## eta.(Intercept) 4.452345889 0.033864818 131.474082 0.000000e+00
## eta.reLDM2 -0.013246977 0.001076194 -12.309102 8.091828e-35
## eta.yr 0.103013607 0.094643420 1.088439 2.764013e-01
## eta.yr2 0.109709373 0.098109924 1.118229 2.634692e-01
## eta.NestAge0 -0.006428657 0.004519983 -1.422274 1.549466e-01
Теперь мы можем получить доверительные интервалы...
ci2 <- confint(fit2)
## 2.5 % 97.5 %
## eta.(Intercept) 4.38644052 4.519116156
## eta.reLDM2 -0.01531437 -0.011092655
## eta.yr -0.08477933 0.286279919
## eta.yr2 -0.08041548 0.304251382
## eta.NestAge0 -0.01522353 0.002496006
Кажется, это работает, но я бы очень подозрительно относился к этим припадкам. Возможно, вам следует попробовать другие оптимизаторы, чтобы убедиться, что вы можете вернуться к тем же результатам. Может быть хорошей идеей является лучший инструмент оптимизации, такой как AD Model Builder или Template Model Builder.
Я не придерживаюсь бездумно отбрасывающих предикторов с сильно коррелированными оценками параметров, но это может быть разумным временем для его рассмотрения.