我想运行带有日志链接和偏移量的高斯GLM。 出现以下问题:
y <- c(1,1,0,0)
t <- c(5,3,2,4)
没问题:
exp(coef(glm(y~1 + offset(log(t)), family=poisson)))
family=gaussian
,需要指定起始值,它可以在这里工作:
exp(coef(glm(y~1, family=gaussian(link=log), start=0)))
但在这里不起作用:
exp(coef(glm(y~1 + offset(log(t)), family=gaussian(link=log), start=0)))
eval中的错误(expr,envir,enclos):找不到有效的起始值:请指定一些“
有没有人看到什么是错的(希望只是在我的编码中)?
答案 0 :(得分:10)
我看起来start
在offset
出现时无法识别。您正尝试在y
值-Inf
中取0的日志。在glm
没有给予帮助的情况下寻找解决方案时,start
显然无法解决这个问题。 y
值中的小扰动将允许解决方案。
exp(coef(glm(I(y+.Machine$double.eps)~1 + offset(log(t)), family=gaussian(link=log))))
(Intercept)
0.1481481
答案 1 :(得分:9)
以下是一些考古学的结果,它解释了glm
函数内部正在发生的事情:
调试(使用debug("glm")
)并单步执行该功能表明它在以下调用时失败:
if (length(offset) && attr(mt, "intercept") > 0L) {
fit$null.deviance <- eval(call(if (is.function(method)) "method" else method,
x = X[, "(Intercept)", drop = FALSE], y = Y, weights = weights,
offset = offset, family = family, control = control,
intercept = TRUE))$deviance
}
这是尝试计算模型的零偏差。它仅评估是否存在截距项和偏移项(我不确定原因;可能是前一次调用glm
计算的默认空值偏差在这种情况下是错误的并且必须重新计算?) 。它调用glm.fit
(默认值method
),但没有起始值,因为对于仅限拦截模型,这些通常是不必要的。
现在在glm.fit
内部进行调试,看看会发生什么:我们进入
if (is.null(etastart) && is.null(start) && is.null(mustart) &&
((family$link == "inverse" && any(y == 0)) || (family$link ==
"log" && any(y <= 0))))
stop("cannot find valid starting values: please specify some")
我们看到因为没有传递起始值,因为使用了日志链接,并且因为某些y
值等于零,所以拟合失败。因此,如果(并且仅当?)指定了偏移量和截距,使用了日志链接,并且响应中没有值,则应该发生这种情况。
如果你dump("glm",file="glmtemp.R")
;添加行
start = start[1], etastart = etastart[1], mustart = mustart[1],
适合空偏离的调用(即上面所示的调用);和source("glmtemp.R")
,似乎工作正常......我认为这应该是一个合理的通用解决方案。如果有人想在R开发列表中提出这个问题,请随意。