R logistic回归预测的置信区间

R logistic回归预测的置信区间,r,statistics,glm,confidence-interval,R,Statistics,Glm,Confidence Interval,在R predict中,lm根据线性回归的结果计算预测,并提供计算这些预测的置信区间的功能。根据手册,这些间隔基于拟合的误差方差,而不是系数的误差间隔 另一方面,predict.glm基于逻辑和泊松回归(以及其他一些)计算预测,没有置信区间选项。我甚至很难想象这样的置信区间是如何计算出来的,从而为泊松和逻辑回归提供有意义的见解 是否存在为此类预测提供置信区间有意义的情况?如何解释?这些情况下的假设是什么?通常的方法是计算线性预测量表上的置信区间,其中情况将更正常(高斯),然后应用链接函数的倒数将

在R predict中,lm根据线性回归的结果计算预测,并提供计算这些预测的置信区间的功能。根据手册,这些间隔基于拟合的误差方差,而不是系数的误差间隔

另一方面,predict.glm基于逻辑和泊松回归(以及其他一些)计算预测,没有置信区间选项。我甚至很难想象这样的置信区间是如何计算出来的,从而为泊松和逻辑回归提供有意义的见解


是否存在为此类预测提供置信区间有意义的情况?如何解释?这些情况下的假设是什么?

通常的方法是计算线性预测量表上的置信区间,其中情况将更正常(高斯),然后应用链接函数的倒数将置信区间从线性预测量表映射到响应量表

要做到这一点,你需要两件事

  • 使用
    type=“link”
    调用
    predict()
  • 使用
    se.fit=TRUE调用
    predict()
  • 第一个生成线性预测量的预测,第二个返回预测的标准误差。伪码

    ## foo <- mtcars[,c("mpg","vs")]; names(foo) <- c("x","y") ## Working example data
    mod <- glm(y ~ x, data = foo, family = binomial)
    preddata <- with(foo, data.frame(x = seq(min(x), max(x), length = 100)))
    preds <- predict(mod, newdata = preddata, type = "link", se.fit = TRUE)
    
    critval
    根据需要从t或z(正态)分布中选择(我现在完全忘记了使用哪种类型的GLM以及属性是什么),并具有所需的覆盖率。
    1.96
    是覆盖率为95%的高斯分布值:

    > qnorm(0.975) ## 0.975 as this is upper tail, 2.5% also in lower tail
    [1] 1.959964
    
    现在对于
    fit
    upr
    lwr
    我们需要对它们应用链接函数的逆函数

    fit2 <- mod$family$linkinv(fit)
    upr2 <- mod$family$linkinv(upr)
    lwr2 <- mod$family$linkinv(lwr)
    

    fit2我偶然发现了刘文穗的方法,他使用自举或模拟方法来解决泊松估计的问题

    作者的例子

    pkgs <- c('doParallel', 'foreach')
    lapply(pkgs, require, character.only = T)
    registerDoParallel(cores = 4)
     
    data(AutoCollision, package = "insuranceData")
    df <- rbind(AutoCollision, AutoCollision)
    mdl <- glm(Claim_Count ~ Age + Vehicle_Use, data = df, family = poisson(link = "log"))
    new_fake <- df[1:5, 1:2]
    
    boot_pi <- function(model, pdata, n, p) {
      odata <- model$data
      lp <- (1 - p) / 2
      up <- 1 - lp
      set.seed(2016)
      seeds <- round(runif(n, 1, 1000), 0)
      boot_y <- foreach(i = 1:n, .combine = rbind) %dopar% {
        set.seed(seeds[i])
        bdata <- odata[sample(seq(nrow(odata)), size = nrow(odata), replace = TRUE), ]
        bpred <- predict(update(model, data = bdata), type = "response", newdata = pdata)
        rpois(length(bpred), lambda = bpred)
      }
      boot_ci <- t(apply(boot_y, 2, quantile, c(lp, up)))
      return(data.frame(pred = predict(model, newdata = pdata, type = "response"), lower = boot_ci[, 1], upper = boot_ci[, 2]))
    }
     
    boot_pi(mdl, new_fake, 1000, 0.95)
    
    sim_pi <- function(model, pdata, n, p) {
      odata <- model$data
      yhat <- predict(model, type = "response")
      lp <- (1 - p) / 2
      up <- 1 - lp
      set.seed(2016)
      seeds <- round(runif(n, 1, 1000), 0)
      sim_y <- foreach(i = 1:n, .combine = rbind) %dopar% {
        set.seed(seeds[i])
        sim_y <- rpois(length(yhat), lambda = yhat)
        sdata <- data.frame(y = sim_y, odata[names(model$x)])
        refit <- glm(y ~ ., data = sdata, family = poisson)
        bpred <- predict(refit, type = "response", newdata = pdata)
        rpois(length(bpred),lambda = bpred)
      }
      sim_ci <- t(apply(sim_y, 2, quantile, c(lp, up)))
      return(data.frame(pred = predict(model, newdata = pdata, type = "response"), lower = sim_ci[, 1], upper = sim_ci[, 2]))
    }
     
    sim_pi(mdl, new_fake, 1000, 0.95)
    

    pkgs可能从经验分布中进行,也就是说,将样本引导几次,然后您可以将样本值与经验分布进行比较。
    confint()
    将给出模型项的轮廓似然区间,但OP需要预测区间。IIRC GLM中的置信区间和预测区间之间没有区别。但是,如果
    summary(mod)
    中引用的标准误差不存在,那么这会给您带来什么
    predict.lm()
    使用模型给出预测值的响应值。它可以给出预测和置信区间。在GLM,IIRC中,这些是相同的东西。因此,我在回答中展示的是如何做
    predict.lm()
    所做的事情,但对于GLM,仅基于预测的标准错误。@Arun还要注意,
    confint.default()
    假设为正态,而GLMS IIRC则不必如此。轮廓可能性的形状将有助于确定正态性是否是合理的假设。@Arun此外,没有理由期望GLM的置信区间在响应量表上是对称的。您链接到的页面采用这种方式。很容易看出,此处使用的方法可能会产生不满足响应所施加限制的置信区间(即二项式0-1标度,泊松非负等)。我在我的回答中做了类似的事情,但我在线性预测的尺度上进行计算,然后转换它们,就像GLM中的拟合值通过链接函数的倒数进行转换一样。@LadislavNado,谢谢。不,我们依赖于线性预测的分布(近似)正态。小心这些间隔!它们是置信区间,而不是这种情况下需要的预测区间。请遵循caracal的评论:@skan
    exp(confint(fit))
    将根据模型的参数而不是模型的拟合值,为您提供Wald或profile似然(取决于加载的PKG)置信区间。@skan不,我们不应该对我显示的内容使用二项分布(产生拟合值的置信区间)。渐近地,在线性预测量的尺度上,情况是高斯的。此外,如果你是指与模拟相关的情况:通过模拟为二项式数据生成预测区间没有什么意义,因为只有两个值会生成1和0,所以区间要么是0(所有1或0)要么是1(1和0的混合)对于给定模型拟合的模拟数据。@GavinSimpson我通读了代码,做了一些数学运算,阅读了
    predict.glm
    和你的帖子的文档,但仍然没有得到
    preds$se.fit
    这里是什么。我们假设线性预测中存在逻辑分布噪声,这会导致斜率和跨步估计的错误t、 但是预测误差是如何计算的呢?我使用预测概率将结果与Wald CI进行了比较。但是它们不一样。那么,
    preds$se.fit
    是如何计算的呢?
    preddata$lwr <- lwr2 
    preddata$upr <- upr2 
    ggplot(data=foo, mapping=aes(x=x,y=y)) + geom_point() +         
       stat_smooth(method="glm", method.args=list(family=binomial)) + 
       geom_line(data=preddata, mapping=aes(x=x, y=upr), col="red") + 
       geom_line(data=preddata, mapping=aes(x=x, y=lwr), col="red") 
    
    pkgs <- c('doParallel', 'foreach')
    lapply(pkgs, require, character.only = T)
    registerDoParallel(cores = 4)
     
    data(AutoCollision, package = "insuranceData")
    df <- rbind(AutoCollision, AutoCollision)
    mdl <- glm(Claim_Count ~ Age + Vehicle_Use, data = df, family = poisson(link = "log"))
    new_fake <- df[1:5, 1:2]
    
    boot_pi <- function(model, pdata, n, p) {
      odata <- model$data
      lp <- (1 - p) / 2
      up <- 1 - lp
      set.seed(2016)
      seeds <- round(runif(n, 1, 1000), 0)
      boot_y <- foreach(i = 1:n, .combine = rbind) %dopar% {
        set.seed(seeds[i])
        bdata <- odata[sample(seq(nrow(odata)), size = nrow(odata), replace = TRUE), ]
        bpred <- predict(update(model, data = bdata), type = "response", newdata = pdata)
        rpois(length(bpred), lambda = bpred)
      }
      boot_ci <- t(apply(boot_y, 2, quantile, c(lp, up)))
      return(data.frame(pred = predict(model, newdata = pdata, type = "response"), lower = boot_ci[, 1], upper = boot_ci[, 2]))
    }
     
    boot_pi(mdl, new_fake, 1000, 0.95)
    
    sim_pi <- function(model, pdata, n, p) {
      odata <- model$data
      yhat <- predict(model, type = "response")
      lp <- (1 - p) / 2
      up <- 1 - lp
      set.seed(2016)
      seeds <- round(runif(n, 1, 1000), 0)
      sim_y <- foreach(i = 1:n, .combine = rbind) %dopar% {
        set.seed(seeds[i])
        sim_y <- rpois(length(yhat), lambda = yhat)
        sdata <- data.frame(y = sim_y, odata[names(model$x)])
        refit <- glm(y ~ ., data = sdata, family = poisson)
        bpred <- predict(refit, type = "response", newdata = pdata)
        rpois(length(bpred),lambda = bpred)
      }
      sim_ci <- t(apply(sim_y, 2, quantile, c(lp, up)))
      return(data.frame(pred = predict(model, newdata = pdata, type = "response"), lower = sim_ci[, 1], upper = sim_ci[, 2]))
    }
     
    sim_pi(mdl, new_fake, 1000, 0.95)