【问题标题】:Confidence intervals for predictions from logistic regression逻辑回归预测的置信区间
【发布时间】:2013-01-03 14:29:25
【问题描述】:

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

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

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

【问题讨论】:

  • 也许从经验分布开始,即引导样本几次,然后您可以将样本值与经验分布进行比较。
  • confint() 将给出模型项的轮廓似然区间,但 OP 想要一个预测区间。 IIRC 在 GLM 中置信区间和预测区间之间没有区别。
  • 但是summary(mod) 中引用的标准错误没有给你什么? predict.lm() 使用模型为预测变量的值提供响应值。它可以给出预测和置信区间。在 GLM、IIRC 中,这些是同一回事。因此,我在答案中展示的是如何做 predict.lm() 所做的,但对于 GLM,仅基于预测的标准误差。
  • @Arun 另请注意,confint.default() 假定正常,GLMS IIRC 不一定是这种情况。轮廓似然的形状将有助于确定正态性是否是一个合理的假设。
  • @Arun 另外,没有理由期望 GLM 的置信区间在响应尺度上是对称的。您链接到的页面假定这一点。很容易看出,那里使用的方法可能会产生不符合响应所施加限制的置信区间(即二项式中的 0-1 尺度,泊松的非负值等)。我在我的答案中做了与该帖子类似的事情,但我在线性预测器的规模上进行计算,然后将它们转换为 GLM 的拟合值通过链接函数的逆转换。

标签: r statistics glm confidence-interval


【解决方案1】:

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

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

  1. type = "link" 致电predict(),然后
  2. 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)

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 根据需要从 tz(正态)分布中选择(我现在完全忘记了使用哪种类型的 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") 

【讨论】:

  • @LadislavNado 谢谢。不,我们依赖于线性预测器上的(大约)正态分布。
  • 小心这些间隔!它们是置信区间,而不是在这种情况下所需的预测区间。在此处关注 caracal 的评论:stats.stackexchange.com/q/41074/5509
  • @skan exp(confint(fit)) 将为您提供模型的 参数 上的 Wald 或轮廓似然性(取决于加载的 pkgs)置信区间,而不是模型的拟合值.
  • @skan 不,我们不应该对我展示的内容使用二项分布(在拟合值上产生置信区间)。渐近地,事物在线性预测器的尺度上是高斯的。此外,如果您的意思是与模拟有关:通过模拟生成二项式数据的预测区间几乎没有意义,因为会产生的唯一两个值是 1 和 0,因此区间是 0(全 1 或 0)或 1 (1s 和 0s 的混合)用于给定模型拟合的模拟数据。
  • @GavinSimpson 我浏览了代码,做了一些数学运算,阅读了predict.glm 的文档和您的帖子,但仍然不明白preds$se.fit 是什么。我们假设线性预测中存在逻辑分布的噪声,这会导致斜率和截距估计的误差。但是如何计算预测误差?我使用预测概率将结果与 Wald CI 进行了比较。但他们不一样。那么preds$se.fit 是如何计算的?
【解决方案2】:

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

作者的例子

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)

【讨论】:

    猜你喜欢
    • 2018-05-05
    • 2016-12-12
    • 1970-01-01
    • 2019-03-05
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2022-11-27
    相关资源
    最近更新 更多