逻辑回归预测的置信区间

时间:2013-01-20 09:45:48

标签: r statistics glm confidence-interval

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

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

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

2 个答案:

答案 0 :(得分:66)

通常的方法是在线性预测器的比例上计算置信区间,其中事物将更加正常(高斯),然后应用链接函数的逆来将置信区间从线性预测器比例映射到回应量表。

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

  1. 使用predict()
  2. 致电type = "link"
  3. 使用predict()致电se.fit = TRUE
  4. 第一个产生线性预测器尺度的预测,第二个返回预测的标准误差。在伪代码中

    ## 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)
    

    preds是一个包含fitse.fit组件的列表。

    然后,线性预测器的置信区间为

    critval <- 1.96 ## approx 95% CI
    upr <- preds$fit + (critval * preds$se.fit)
    lwr <- preds$fit - (critval * preds$se.fit)
    fit <- preds$fit
    

    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
    

    现在,对于fituprlwr,我们需要将链接功能的反转应用于它们。

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

    现在您可以绘制所有三个和数据。

    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") 
    

    enter image description here

答案 1 :(得分:0)

我偶然发现了 Liu WenSui 的 method,它使用 bootstrap 或模拟方法来解决泊松估计的问题。

作者的例子

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)