Я думаю , что это сводится к первоначальным значениям , которые используются в glm.fit
из family$initialize
которых делает метод divergere. Насколько я знаю, glm.fit
решить эту проблему, сформировав QR-разложение где - матрица проектирования, а - диагональ с квадратными корнями из элементов, как описаноW--√ИксИксW--√ здесь . То есть использует метод Ньютона-Рафсона.
Соответствующий $intialize
код:
if (NCOL(y) == 1) {
if (is.factor(y))
y <- y != levels(y)[1L]
n <- rep.int(1, nobs)
y[weights == 0] <- 0
if (any(y < 0 | y > 1))
stop("y values must be 0 <= y <= 1")
mustart <- (weights * y + 0.5)/(weights + 1)
m <- weights * y
if (any(abs(m - round(m)) > 0.001))
warning("non-integer #successes in a binomial glm!")
}
Вот упрощенная версия, glm.fit
которая показывает мою точку зрения
> #####
> # setup
> y <- matrix(c(1,0,0,0), ncol = 1)
> weights <- 1:nrow(y) * 1000
> nobs <- length(y)
> family <- binomial()
> X <- matrix(rep(1, nobs), ncol = 1) # design matrix used later
>
> # set mu start as with family$initialize
> if (NCOL(y) == 1) {
+ n <- rep.int(1, nobs)
+ y[weights == 0] <- 0
+ mustart <- (weights * y + 0.5)/(weights + 1)
+ m <- weights * y
+ if (any(abs(m - round(m)) > 0.001))
+ warning("non-integer #successes in a binomial glm!")
+ }
>
> mustart # starting value
[,1]
[1,] 0.9995004995
[2,] 0.0002498751
[3,] 0.0001666111
[4,] 0.0001249688
> (eta <- family$linkfun(mustart))
[,1]
[1,] 7.601402
[2,] -8.294300
[3,] -8.699681
[4,] -8.987322
>
> #####
> # Start loop to fit
> mu <- family$linkinv(eta)
> mu_eta <- family$mu.eta(eta)
> z <- drop(eta + (y - mu) / mu_eta)
> w <- drop(sqrt(weights * mu_eta^2 / family$variance(mu = mu)))
>
> # code is simpler here as (X^T W X) is a scalar
> X_w <- X * w
> (.coef <- drop(crossprod(X_w)^-1 * ((w * z) %*% X_w)))
[1] -5.098297
> (eta <- .coef * X)
[,1]
[1,] -5.098297
[2,] -5.098297
[3,] -5.098297
[4,] -5.098297
>
> # repeat a few times from "start loop to fit"
Мы можем повторить последнюю часть еще два раза, чтобы увидеть, что метод Ньютона-Рафсона расходится:
> #####
> # Start loop to fit
> mu <- family$linkinv(eta)
> mu_eta <- family$mu.eta(eta)
> z <- drop(eta + (y - mu) / mu_eta)
> w <- drop(sqrt(weights * mu_eta^2 / family$variance(mu = mu)))
>
> # code is simpler here as (X^T W X) is a scalar
> X_w <- X * w
> (.coef <- drop(crossprod(X_w)^-1 * ((w * z) %*% X_w)))
[1] 10.47049
> (eta <- .coef * X)
[,1]
[1,] 10.47049
[2,] 10.47049
[3,] 10.47049
[4,] 10.47049
>
>
> #####
> # Start loop to fit
> mu <- family$linkinv(eta)
> mu_eta <- family$mu.eta(eta)
> z <- drop(eta + (y - mu) / mu_eta)
> w <- drop(sqrt(weights * mu_eta^2 / family$variance(mu = mu)))
>
> # code is simpler here as (X^T W X) is a scalar
> X_w <- X * w
> (.coef <- drop(crossprod(X_w)^-1 * ((w * z) %*% X_w)))
[1] -31723.76
> (eta <- .coef * X)
[,1]
[1,] -31723.76
[2,] -31723.76
[3,] -31723.76
[4,] -31723.76
Этого не произойдет, если вы начнете с weights <- 1:nrow(y)
или говорите weights <- 1:nrow(y) * 100
.
Обратите внимание, что вы можете избежать расхождений, установив mustart
аргумент. Например сделать
> glm(Y ~ 1,weights = w * 1000, family = binomial, mustart = rep(0.5, 4))
Call: glm(formula = Y ~ 1, family = binomial, weights = w * 1000, mustart = rep(0.5,
4))
Coefficients:
(Intercept)
-2.197
Degrees of Freedom: 3 Total (i.e. Null); 3 Residual
Null Deviance: 6502
Residual Deviance: 6502 AIC: 6504
weights
аргумент заканчивается в двух местах внутриglm.fit
функции (в glm.R ), что и делает работа в R: 1) в остатках отклонения, через функцию Cbinomial_dev_resids
(в family.c ) и 2) на этапе IWLS посредствомCdqrls
(в lm.c ). Я не знаю достаточно C, чтобы больше помочь в отслеживании логики