以下是一些考古学的结果,这些结果解释了函数深处发生的事情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
看看会发生什么:我们(在对家庭函数的调用中gaussian()
)得到:
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
值等于 0,所以拟合失败。因此,如果(且仅当?)同时指定了偏移量和截距,使用了日志链接并且响应中的值为零,则应该发生这种情况。
如果你dump("glm",file="glmtemp.R")
;添加行
start = start[1], etastart = etastart[1], mustart = mustart[1],
到适合零偏差的呼叫(即上面显示的那个);并且source("glmtemp.R")
,它似乎工作正常......我认为这应该是一个合理的通用解决方案。如果有人想在 R 开发列表中提出这个问题,请随意。