Eu estou querendo saber como são os valores iniciais padrão especificados em glm
.
Esta publicação sugere que os valores padrão sejam definidos como zeros. Esta uma diz que existe um algoritmo por trás dele, no entanto link relevante é quebrado.
Tentei ajustar o modelo de regressão logística simples com o rastreamento de algoritmo:
set.seed(123)
x <- rnorm(100)
p <- 1/(1 + exp(-x))
y <- rbinom(100, size = 1, prob = p)
# to see parameter estimates in each step
trace(glm.fit, quote(print(coefold)), at = list(c(22, 4, 8, 4, 19, 3)))
Primeiro, sem especificação dos valores iniciais:
glm(y ~ x, family = "binomial")
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
NULL
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.386379 1.106234
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3991135 1.1653971
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3995188 1.1669508
Na primeira etapa, os valores iniciais são NULL
.
Segundo, defino os valores iniciais como zeros:
glm(y ~ x, family = "binomial", start = c(0, 0))
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0 0
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3177530 0.9097521
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3909975 1.1397163
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3994147 1.1666173
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3995191 1.1669518
E podemos ver que as iterações entre a primeira e a segunda abordagem diferem.
Para ver os valores iniciais especificados por glm
, tentei ajustar o modelo com apenas uma iteração:
glm(y ~ x, family = "binomial", control = list(maxit = 1))
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
NULL
Call: glm(formula = y ~ x, family = "binomial", control = list(maxit = 1))
Coefficients:
(Intercept) x
0.3864 1.1062
Degrees of Freedom: 99 Total (i.e. Null); 98 Residual
Null Deviance: 134.6
Residual Deviance: 115 AIC: 119
As estimativas dos parâmetros (sem surpresa) correspondem às estimativas da primeira abordagem na segunda iteração, ou seja, [1] 0.386379 1.106234
definir esses valores como valores iniciais leva à mesma sequência de iterações da primeira abordagem:
glm(y ~ x, family = "binomial", start = c(0.386379, 1.106234))
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.386379 1.106234
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3991135 1.1653971
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, .... step 22,4,8,4,19,3
[1] 0.3995188 1.1669508
Portanto, a questão é: como esses valores são calculados?
fonte
start
valores, eles serão usados no cálculo do que é passado para aC_Cdqrls
rotina. Caso contrário, os valores passados são calculados (incluindo uma chamadaeval(binomial()$initialize)
), masglm.fit
nunca calculam explicitamente os valores parastart
. Tome uma ou duas horas e estude oglm.fit
código.glm.fit
código, mas ainda não tenho idéia de como os valores iniciais são calculados.Respostas:
TL; DR
start=c(b0,b1)
inicializa eta parab0+x*b1
(mu para 1 / (1 + exp (-eta))))start=c(0,0)
inicializa eta para 0 (mu para 0,5), independentemente do valor de y ou x.start=NULL
inicializa eta = 1,098612 (mu = 0,75) se y = 1, independentemente do valor x.start=NULL
inicializa eta = -1,098612 (mu = 0,25) se y = 0, independentemente do valor x.Uma vez que eta (e consequentemente mu e var (mu)) foram calculados,
w
ez
são calculados e enviados para um solucionador de QR, no espírito deqr.solve(cbind(1,x) * w, z*w)
.Forma longa
Criando o comentário de Roland: Fiz um
glm.fit.truncated()
, onde atendiglm.fit
àC_Cdqrls
chamada e depois a comentei.glm.fit.truncated
gera os valoresz
ew
(assim como os valores das quantidades usadas para calcularz
ew
) que seriam passados para aC_Cdqrls
chamada:Mais pode ser lido
C_Cdqrls
aqui . Felizmente, a funçãoqr.solve
na base R toca diretamente nas versões LINPACK que são chamadasglm.fit()
.Por isso, corremos
glm.fit.truncated
para as diferentes especificações de valores iniciais e, em seguida, fazemos uma chamadaqr.solve
com os valores de z e vemos como os "valores iniciais" (ou os primeiros valores de iteração exibidos) são calculados. Como Roland indicou, especificarstart=NULL
oustart=c(0,0)
em glm () afeta os cálculos para w e z, não parastart
.Para o início = NULL:
z
é um vetor em que os elementos têm o valor 2.431946 ou -2.431946 ew
é um vetor em que todos os elementos são 0,4330127:Para o início = c (0,0):
z
é um vetor em que os elementos têm o valor 2 ou -2 ew
é um vetor em que todos os elementos são 0,5:Então, está tudo bem, mas como calculamos o
w
ez
? Perto do fundo doglm.fit.truncated()
que vemosObserve as seguintes comparações entre os valores de saída das quantidades usadas para calcular
z
ew
:Observe que
start.is.00
o vetor terámu
apenas os valores 0,5, porque eta está definido como 0 e mu (eta) = 1 / (1 + exp (-0)) = 0,5.start.is.null
define aqueles com y = 1 como mu = 0,75 (que corresponde a eta = 1,098612) e aqueles com y = 0 como mu = 0,25 (que corresponde a eta = -1,098612) e, portanto,var_mu
= 0,75 * 0,25 = 0,1875.No entanto, é interessante notar que mudei a semente e reran tudo e mu = 0,75 para y = 1 e mu = 0,25 para y = 0 (e, portanto, as outras quantidades permaneceram as mesmas). Ou seja, start = NULL dá origem ao mesmo
w
ez
independentemente do quey
ex
é , porque inicializam eta = 1,098612 (mu = 0,75) se y = 1 e eta = -1,098612 (mu = 0,25) se y = 0.Portanto, parece que um valor inicial para o coeficiente Intercept e para o coeficiente X não está definido para start = NULL, mas valores iniciais são dados a eta, dependendo do valor de y e independente do valor de x. De lá
w
ez
são calculados, em seguida, enviado juntamente comx
a qr.solver.Código a ser executado antes dos blocos acima:
fonte