gpt4 book ai didi

r - 使用 glm 拟合逻辑回归的默认起始值

转载 作者:行者123 更新时间:2023-12-03 15:09:50 24 4
gpt4 key购买 nike

我想知道 glm 中的默认起始值​​是如何指定的.

这个post建议将默认值设置为零。这个one说它背后有一个算法,但是相关的链接被破坏了。

我试图用算法跟踪拟合简单的逻辑回归模型:

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 .

其次,我将起始值设置为零:
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;博士

  • start=c(b0,b1)将 eta 初始化为 b0+x*b1 (mu 到 1/(1+exp(-eta)))
  • start=c(0,0)无论 y 或 x 值如何,都将 eta 初始化为 0(mu 为 0.5)。
  • start=NULL如果 y=1,不管 x 值如何,初始化 eta= 1.098612 (mu=0.75)。
  • start=NULL如果 y=0,不管 x 值如何,初始化 eta=-1.098612 (mu=0.25)。
  • 一旦计算出 eta(以及随之而来的 mu 和 var(mu)),wz根据 qr.solve(cbind(1,x) * w, z*w) 的精神,计算并发送到 QR 求解器.

  • 长表
    根据 Roland 的评论:我做了一个 glm.fit.truncated() ,我带的地方 glm.fit下至 C_Cdqrls打电话,然后把它注释掉。 glm.fit.truncated输出 zw值(以及用于计算 zw 的数量的值),然后将其传递给 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 here .幸运的是,函数 qr.solve在基础 R 中,直接进入 glm.fit() 中调用的 LINPACK 版本.
    所以我们运行 glm.fit.truncated对于不同的起始值规范,然后调用 qr.solve使用 w 和 z 值,我们可以看到“起始值”(或第一个显示的迭代值)是如何计算的。正如 Roland 所指出的,指定 start=NULLstart=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
    所以这一切都很好,但是我们如何计算 wz ?接近 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只有值 0.5,因为 eta 设置为 0 并且 mu(eta) = 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=1 和 mu=0.75,对于 y=0(因此其他数量保持不变)。也就是说,start=NULL 产生同样的 wz不管是什么 yx是,因为如果 y=1,它们初始化 eta=1.098612 (mu=0.75),如果 y=0,则初始化 eta=-1.098612 (mu=0.25)。
    因此,截距系数和 X 系数的起始值似乎未设置为 start=NULL,而是根据 y 值和独立于 x 值将初始值赋予 eta。从那里 wz计算,然后与 x 一起发送到 qr.solver。
    在上面的 block 之前运行的代码:
    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)))

    }

    关于r - 使用 glm 拟合逻辑回归的默认起始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60526586/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com