에 기본 시작 값이 어떻게 지정되어 있는지 궁금합니다 glm
.
이 게시물 에서는 기본값이 0으로 설정되어 있다고 제안합니다. 이 사람은 그러나 관련 링크가 깨진 뒤에 알고리즘이 있다는 것을 말한다.
알고리즘 추적으로 간단한 로지스틱 회귀 모델을 맞추려고했습니다.
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)))
먼저 초기 값을 지정하지 않은 경우 :
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
첫 번째 단계에서 초기 값은 NULL
입니다.
둘째, 시작 값을 0으로 설정했습니다.
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
그리고 우리는 첫 번째와 두 번째 접근법 사이의 반복이 다르다는 것을 알 수 있습니다.
지정된 초기 값을 보려면 glm
한 번의 반복으로 모델을 맞추려고했습니다.
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
모수의 추정치 (놀랍지 않게도)는 두 번째 반복의 첫 번째 접근법의 추정치에 해당합니다. 즉, [1] 0.386379 1.106234
이 값을 초기 값으로 설정하면 첫 번째 접근법과 동일한 반복 시퀀스가됩니다.
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
문제는 이러한 값이 어떻게 계산 되는가입니다.
답변
TL; DR
start=c(b0,b1)
eta를b0+x*b1
(mu to 1 / (1 + exp (-eta)))로 초기화합니다.start=c(0,0)
y 또는 x 값에 관계없이 eta를 0 (mu ~ 0.5)으로 초기화합니다.start=NULL
x 값에 관계없이 y = 1 인 경우 eta = 1.098612 (mu = 0.75)를 초기화합니다.-
start=NULL
x 값에 관계없이 y = 0 인 경우 eta = -1.098612 (mu = 0.25)를 초기화합니다. -
일단 eta (및 결과적으로 mu 및 var (mu))가 계산되고
w
,z
계산되어의 개념으로 QR 솔버로 전송됩니다qr.solve(cbind(1,x) * w, z*w)
.
롱폼
롤랜드의 코멘트 떨어져 건물 : 내가 만들어 glm.fit.truncated()
내가 어디로 데려 갔는지, glm.fit
받는 사람 아래로 C_Cdqrls
다음 호출과하면을 주석. glm.fit.truncated
출력 z
과 w
값 (및 계산에 사용되는 양의 값으로 z
하고 w
) 다음에 전달 될 C_Cdqrls
호 :
## call Fortran code via C wrapper
fit <- .Call(C_Cdqrls, x[good, , drop = FALSE] * w, z * w,
min(1e-7, control$epsilon/1000), check=FALSE)
자세한 내용은 C_Cdqrls
여기를 참조하십시오 . 운 좋게도, qr.solve
기본 R 의 기능 은에서 호출되는 LINPACK 버전으로 직접 연결됩니다 glm.fit()
.
따라서 glm.fit.truncated
다른 시작 값 사양으로 실행 한 다음 qr.solve
w 및 z 값 으로 호출 하면 “시작 값”(또는 첫 번째로 표시되는 반복 값)이 어떻게 계산되는지 확인합니다. 롤랜드, 표시된 지정하는 것과 start=NULL
또는 start=c(0,0)
GLM에서 () w 및 z에 대한 영향을 계산 하지 를 들어 start
.
start = NULL의 경우 : z
요소의 값이 2.431946 또는 -2.431946 w
인 벡터이며 모든 요소가 0.4330127 인 벡터입니다.
start.is.null <- glm.fit.truncated(x,y,family=binomial(), start=NULL)
start.is.null
w <- start.is.null$w
z <- start.is.null$z
## if start is NULL, the first displayed values are:
qr.solve(cbind(1,x) * w, z*w)
# > qr.solve(cbind(1,x) * w, z*w)
# x
# 0.386379 1.106234
start = c (0,0)의 경우 : z
요소의 값이 2 또는 -2 w
인 벡터이고 모든 요소가 0.5 인 벡터입니다.
## if start is c(0,0)
start.is.00 <- glm.fit.truncated(x,y,family=binomial(), start=0)
start.is.00
w <- start.is.00$w
z <- start.is.00$z
## if start is c(0,0), the first displayed values are:
qr.solve(cbind(1,x) * w, z*w)
# > qr.solve(cbind(1,x) * w, z*w)
# x
# 0.3177530 0.9097521
그래서 그것은 모두 훌륭하지만 우리는 w
과를 z
어떻게 계산 합니까? glm.fit.truncated()
우리 는 바닥 근처에
z <- (eta - offset)[good] + (y - mu)[good]/mu.eta.val[good]
w <- sqrt((weights[good] * mu.eta.val[good]^2)/variance(mu)[good])
계산에 사용되는 수량의 출력 값 사이에 다음의 비교에서 봐 z
및 w
:
cbind(y, start.is.null$mu, start.is.00$mu)
cbind(y, start.is.null$eta, start.is.00$eta)
cbind(start.is.null$var_mu, start.is.00$var_mu)
cbind(start.is.null$mu.eta.val, start.is.00$mu.eta.val)
참고 start.is.00
벡터를 가질 것이다 mu
ETA 0 및 MU (ETA)로 설정되어 있기 때문에, 0.5 만 값은 1 / (1 + EXP (-0)) = 0.5. start.is.null
y = 1 인 경우 mu = 0.75 (eta = 1.098612에 해당) 및 y = 0 인 경우 mu = 0.25 (eta = -1.098612에 해당)로 설정하여 var_mu
= 0.75 * 0.25 = 0.1875입니다.
그러나 시드를 변경하고 모든 것을 다시 가져오고 y =의 경우 mu = 0.75, y = 0의 경우 mu = 0.25 (따라서 다른 양은 동일하게 유지됨)에 주목해야합니다. 다시 말해서, 시작 = NULL이 동일한 야기 제공한다 w
과 z
관계없이 어떤 y
및 x
y는 1과 에타 = -1.098612 (MU = 0.25), Y = 0 인 경우를 = 경우가 ETA = 1.098612 (MU = 0.75)를 초기화하기 때문에,됩니다.
따라서 인터셉트 계수 및 X 계수의 시작 값은 start = NULL로 설정되지 않지만 y 값에 따라 x 값과 독립적으로 eta에 초기 값이 제공됩니다. 거기에서 w
와 z
계산, 다음과 함께 전송 x
qr.solver합니다.
위의 청크 전에 실행할 코드 :
set.seed(123)
x <- rnorm(100)
p <- 1/(1 + exp(-x))
y <- rbinom(100, size = 1, prob = p)
glm.fit.truncated <- function(x, y, weights = rep.int(1, nobs),
start = 0,etastart = NULL, mustart = NULL,
offset = rep.int(0, nobs),
family = binomial(),
control = list(),
intercept = TRUE,
singular.ok = TRUE
){
control <- do.call("glm.control", control)
x <- as.matrix(x)
xnames <- dimnames(x)[[2L]]
ynames <- if(is.matrix(y)) rownames(y) else names(y)
conv <- FALSE
nobs <- NROW(y)
nvars <- ncol(x)
EMPTY <- nvars == 0
## define weights and offset if needed
if (is.null(weights))
weights <- rep.int(1, nobs)
if (is.null(offset))
offset <- rep.int(0, nobs)
## get family functions:
variance <- family$variance
linkinv <- family$linkinv
if (!is.function(variance) || !is.function(linkinv) )
stop("'family' argument seems not to be a valid family object", call. = FALSE)
dev.resids <- family$dev.resids
aic <- family$aic
mu.eta <- family$mu.eta
unless.null <- function(x, if.null) if(is.null(x)) if.null else x
valideta <- unless.null(family$valideta, function(eta) TRUE)
validmu <- unless.null(family$validmu, function(mu) TRUE)
if(is.null(mustart)) {
## calculates mustart and may change y and weights and set n (!)
eval(family$initialize)
} else {
mukeep <- mustart
eval(family$initialize)
mustart <- mukeep
}
if(EMPTY) {
eta <- rep.int(0, nobs) + offset
if (!valideta(eta))
stop("invalid linear predictor values in empty model", call. = FALSE)
mu <- linkinv(eta)
## calculate initial deviance and coefficient
if (!validmu(mu))
stop("invalid fitted means in empty model", call. = FALSE)
dev <- sum(dev.resids(y, mu, weights))
w <- sqrt((weights * mu.eta(eta)^2)/variance(mu))
residuals <- (y - mu)/mu.eta(eta)
good <- rep_len(TRUE, length(residuals))
boundary <- conv <- TRUE
coef <- numeric()
iter <- 0L
} else {
coefold <- NULL
eta <-
if(!is.null(etastart)) etastart
else if(!is.null(start))
if (length(start) != nvars)
stop(gettextf("length of 'start' should equal %d and correspond to initial coefs for %s", nvars, paste(deparse(xnames), collapse=", ")),
domain = NA)
else {
coefold <- start
offset + as.vector(if (NCOL(x) == 1L) x * start else x %*% start)
}
else family$linkfun(mustart)
mu <- linkinv(eta)
if (!(validmu(mu) && valideta(eta)))
stop("cannot find valid starting values: please specify some", call. = FALSE)
## calculate initial deviance and coefficient
devold <- sum(dev.resids(y, mu, weights))
boundary <- conv <- FALSE
##------------- THE Iteratively Reweighting L.S. iteration -----------
for (iter in 1L:control$maxit) {
good <- weights > 0
varmu <- variance(mu)[good]
if (anyNA(varmu))
stop("NAs in V(mu)")
if (any(varmu == 0))
stop("0s in V(mu)")
mu.eta.val <- mu.eta(eta)
if (any(is.na(mu.eta.val[good])))
stop("NAs in d(mu)/d(eta)")
## drop observations for which w will be zero
good <- (weights > 0) & (mu.eta.val != 0)
if (all(!good)) {
conv <- FALSE
warning(gettextf("no observations informative at iteration %d",
iter), domain = NA)
break
}
z <- (eta - offset)[good] + (y - mu)[good]/mu.eta.val[good]
w <- sqrt((weights[good] * mu.eta.val[good]^2)/variance(mu)[good])
# ## call Fortran code via C wrapper
# fit <- .Call(C_Cdqrls, x[good, , drop = FALSE] * w, z * w,
# min(1e-7, control$epsilon/1000), check=FALSE)
#
#print(iter)
#print(z)
#print(w)
}
}
return(list(z=z, w=w, mustart=mustart, etastart=etastart, eta=eta, offset=offset, mu=mu, mu.eta.val=mu.eta.val,
weight=weights, var_mu=variance(mu)))
}