R中lmer()混合效应模型的预测间隔


37

我想从lmer()模型获得围绕预测的预测间隔。我发现了一些有关此的讨论:

http://rstudio-pubs-static.s3.amazonaws.com/24365_2803ab8299934e888a60e7b16113f619.html

http://glmm.wikidot.com/faq

但他们似乎并未考虑随机效应的不确定性。

这是一个具体的例子。我在比赛金鱼。我有过去100场比赛的数据。考虑到我的RE估算和FE估算的不确定性,我想预测第101位。我包括鱼的随机拦截(有10种不同的鱼)和重量的固定效应(较轻的鱼更快)。

library("lme4")

fish <- as.factor(rep(letters[1:10], each=100))
race <- as.factor(rep(900:999, 10))
oz <- round(1 + rnorm(1000)/10, 3)
sec <- 9 + rep(1:10, rep(100,10))/10 + oz + rnorm(1000)/10

fishDat <- data.frame(fishID = fish, 
      raceID = race, fishWt = oz, time = sec)
head(fishDat)
plot(fishDat$fishID, fishDat$time)

lme1 <- lmer(time ~ fishWt + (1 | fishID), data=fishDat)
summary(lme1)

现在,来预测第101场比赛。鱼已经过称重,可以出发了:

newDat <- data.frame(fishID = letters[1:10], 
    raceID = rep(1000, 10),
    fishWt = 1 + round(rnorm(10)/10, 3))
newDat$pred <- predict(lme1, newDat)
newDat

   fishID raceID fishWt     pred
1       a   1000  1.073 10.15348
2       b   1000  1.001 10.20107
3       c   1000  0.945 10.25978
4       d   1000  1.110 10.51753
5       e   1000  0.910 10.41511
6       f   1000  0.848 10.44547
7       g   1000  0.991 10.68678
8       h   1000  0.737 10.56929
9       i   1000  0.993 10.89564
10      j   1000  0.649 10.65480

鱼D确实放手了(1.11盎司),并且实际上被预测输给了鱼E和鱼F,他俩都比过去更好。但是,现在我想说:“鱼E(重0.91盎司)将以概率p击败鱼D(重1.11盎司)”。有没有办法使用lme4做出这样的声明?我希望我的概率p在固定效应和随机效应中都考虑到我的不确定性。

谢谢!

PS查看该predict.merMod文档,它表示“无法计算预测的标准误差,因为很难定义一种将方差参数中包含不确定性的有效方法;我们建议bootMer针对此任务,”但是,天哪,我看不到如何使用bootMer来做到这一点。它似乎bootMer将用于获取估计参数的自举置信区间,但我可能是错的。

问:

好的,我想我问错了问题。我想说:“鱼A的重量为oz,将具有90%的比赛时间(lcl,ucl)。”

在我列出的示例中,重达1.0盎司的鱼A的9 + 0.1 + 1 = 10.1 sec平均竞速时间为0.1,标准偏差为。因此,他观察到的比赛时间将介于

x <- rnorm(mean = 10.1, sd = 0.1, n=10000)
quantile(x, c(0.05,0.50,0.95))
       5%       50%       95% 
 9.938541 10.100032 10.261243 

90%的时间。我想要一个预测函数,试图给我这个答案。全部设置fishWt = 1.0newDat,重新运行sim并使用(如下面的Ben Bolker所建议)

predFun <- function(fit) {
  predict(fit,newDat)
}
bb <- bootMer(lme1,nsim=1000,FUN=predFun, use.u = FALSE)
predMat <- bb$t

> quantile(predMat[,1], c(0.05,0.50,0.95))
      5%      50%      95% 
10.01362 10.55646 11.05462 

这似乎实际上是以人口平均数为中心吗?好像没有考虑FishID的影响?我以为可能是样本量问题,但是当我将观察到的种族数从100增加到10000时,我仍然得到类似的结果。

我会默认记录bootMer使用use.u=FALSE情况。另一方面,使用

bb <- bootMer(lme1,nsim=1000,FUN=predFun, use.u = TRUE)

> quantile(predMat[,1], c(0.05,0.50,0.95))
      5%      50%      95% 
10.09970 10.10128 10.10270 

该间隔太窄,对于鱼A的平均时间来说似乎是一个置信区间。我想要一个关于Fish A观察到的比赛时间的置信区间,而不是他的平均比赛时间。我该怎么办?

更新2,几乎:

以为自己在Gelman and Hill(2007),第273页中找到了所需的内容arm。需要利用该软件包。

library("arm")

对于鱼A:

x.tilde <- 1    #observed fishWt for new race
sigma.y.hat <- sigma.hat(lme1)$sigma$data        #get uncertainty estimate of our model
coef.hat <- as.matrix(coef(lme1)$fishID)[1,]    #get intercept (random) and fishWt (fixed) parameter estimates
y.tilde <- rnorm(1000, coef.hat %*% c(1, x.tilde), sigma.y.hat) #simulate
quantile (y.tilde, c(.05, .5, .95))

  5%       50%       95% 
 9.930695 10.100209 10.263551 

对于所有鱼类:

x.tilde <- rep(1,10)  #assume all fish weight 1 oz
#x.tilde <- 1 + rnorm(10)/10  #alternatively, draw random weights as in original example
sigma.y.hat <- sigma.hat(lme1)$sigma$data
coef.hat <- as.matrix(coef(lme1)$fishID)
y.tilde <- matrix(rnorm(1000, coef.hat %*% matrix(c(rep(1,10), x.tilde), nrow = 2 , byrow = TRUE), sigma.y.hat), ncol = 10, byrow = TRUE)
quantile (y.tilde[,1], c(.05, .5, .95))
       5%       50%       95% 
 9.937138 10.102627 10.234616 

实际上,这可能并不是我想要的。我仅考虑整体模型的不确定性。例如,在我有5个观察到的关于K鱼的比赛和1000个观察到的关于L鱼的比赛的情况下,我认为与我对Fish K的预测相关的不确定性应该比与我对Fish L的预测相关的不确定性大得多。

我们将进一步研究Gelman and Hill2007。我觉得我可能最终不得不改用BUGS(或Stan)。

更新第三个:

也许我在概念上做得不好。predictInterval()在下面的答案中使用Jared Knowles给出的功能,得出的间隔与我期望的不完全相同。

library("lattice")
library("lme4")
library("ggplot2")

fish <- c(rep(letters[1:10], each = 100), rep("k", 995), rep("l", 5))
oz <- round(1 + rnorm(2000)/10, 3)
sec <- 9 + c(rep(1:10, each = 100)/10,rep(1.1, 995), rep(1.2, 5)) + oz + rnorm(2000)

fishDat <- data.frame(fishID = fish, fishWt = oz, time = sec)
dim(fishDat)
head(fishDat)
plot(fishDat$fishID, fishDat$time)

lme1 <- lmer(time ~ fishWt + (1 | fishID), data=fishDat)
summary(lme1)
dotplot(ranef(lme1, condVar = TRUE))

我添加了两条新鱼。观察到995个种族的Fish K,观察到5个种族的FishL。我们已经观察了鱼AJ的100场比赛。我适合lmer()以前。望着dotplot()lattice包:

FishID估算

默认情况下,dotplot()将随机效果按其点估计重新排序。鱼L的估计值位于第一行,并且具有非常宽的置信区间。鱼K在第三行,并且具有非常窄的置信区间。这对我来说很有意义。我们有很多有关Fish K的数据,但没有有关Fish L的大量数据,因此我们对Fish K的真实游泳速度的猜测更加自信。现在,我认为这将导致Fish K的预测间隔变窄,而Fish L的预测间隔变宽predictInterval()。豪瓦:

newDat <- data.frame(fishID = letters[1:12],
                     fishWt = 1)

preds <- predictInterval(lme1, newdata = newDat, n.sims = 999)
preds
ggplot(aes(x=letters[1:12], y=fit, ymin=lwr, ymax=upr), data=preds) +
  geom_point() + 
  geom_linerange() +
  labs(x="Index", y="Prediction w/ 95% PI") + theme_bw()

鱼的预测间隔

所有这些预测间隔的宽度似乎都相同。为什么我们对Fish K的预测没有缩小?为什么我们对Fish L的预测没有比其他人更广泛?


1
predictInterval包括固定效应和随机效应项的误差/不确定性。在dotplot你只看到了不确定性,由于预测的随机部分,基本上是围绕着鱼截取特定的估计的不确定性。如果您的模型的固定参数有很多不确定性,fishWt并且此参数驱动了大多数预测值,则任何特定鱼的截距周围的不确定性都是微不足道的,并且您不会在间隔宽度上看到很大的差异。我们应该在predictInterval结果中更清楚地说明这一点。
jknowles

Answers:


18

这个问题和出色的交流是predictIntervalmerTools程序包中创建功能的动力。bootMer是要走的路,但是对于某些问题,在计算上无法生成整个模型的自举拟合(在模型较大的情况下)。

在那些情况下,predictInterval被设计为使用arm::sim函数来生成模型中参数的分布,然后使用那些分布来生成newdata用户提供的给定响应的模拟值。使用简单-您需要做的只是:

library(merTools)
preds <- predictInterval(lme1, newdata = newDat, n.sims = 999)

您可以指定大量其他值,predictInterval包括设置预测间隔的间隔,选择报告分布的均值还是中位数以及选择是否包括模型的残差。

这不是一个完整的预测间隔,因为不包括对象中theta参数的可变性lmer,但是所有其他变化都通过此方法捕获,从而给出了相当不错的近似值。


3
看起来很棒!现在阅读小插图。谢谢!
hossibley 2015年

预测间隔与我预期的不完全相同。请参阅上面的更新3。
hossibley 2015年

难道predictInterval()不是这样嵌套的随机效应?例如,使用msleep数据ggplot2包中的数据集:mod <- lmer(sleep_total ~ bodywt + (1|vore/order), data=msleep); predInt <- predictInterval(merMod=mod, newdata=msleep) 返回错误:Error in '[.data.frame'(newdata, , j) : undefined columns selected
hossibley

我敢打赌,它不喜欢嵌套效果。我认为我们的测试套件中没有对此进行任何测试。我将在GitHub上提出一个问题进行调查。我还建议先尝试从GitHub尝试开发版本devtools::install_github("jknowles/merTools")
jknowles '16

2
作为更新,merTools的最新开发版本确实允许嵌套效果。它将很快被推送到CRAN。
jknowles

15

为此,请bootMer为每个参数引导程序副本生成一组预测:

predFun <- function(fit) {
    predict(fit,newDat)
}
bb <- bootMer(lme1,nsim=200,FUN=predFun,seed=101)

的输出bootMer在不是非常透明的"boot"对象中,但是我们可以从$t组件中获取原始预测。

鱼E击败鱼D有多少时间?

predMat <- bb$t
dim(predMat) ## 200 rows (PB reps) x 10 (predictions)

鱼E的时间在第5列中,鱼D的时间在第4列中,因此我们只需要知道第5列小于第4列的比例即可:

mean(predMat[,5]<predMat[,4])  ## 0.57

我得到了一些意想不到的结果。如果我在newDat中为所有鱼设置fishWt = 1,我希望鱼A的平均/中位数时间为〜10.1,鱼B〜10.2,...,鱼J〜11.0(因为它们在训练数据中的时间为定义为:)sec <- 9 + rep(1:10, rep(100,10))/10 + oz + rnorm(1000)/10。当我使用时predict(),如预期的那样,鱼A,E和J的预测时间为10.09、10.49和10.99。但是,所需的bootMer方法的中值时间为:10.52、10.59和10.50。我期望更多的协议吗?
hossibley 2015年

使用use.u=TRUE方式:bb <- bootMer(lme1,nsim=200,FUN=predFun,seed=101,use.u=TRUE)似乎给了我我想要的东西。谢谢!
hossibley 2015年

好的,这有点棘手。您需要查看的use.u参数bootMer。问题是,当您说“固定效应和随机效应的不确定性”时,“随机效应”是什么意思?您是说随机效应方差还是条件模式(即鱼类特有效应)中的不确定性?您可以使用use.u=TRUE,但我认为它不一定能满足您的要求……
Ben Bolker 2015年

如果使用use.u=TRUE,则“ u [stay]的值固定在其估计值”。我将其解释为意思,无论我们对鱼A的随机影响点估计是多少,只要您愿意,都将其视为上帝的诚实真理。bootMer假设我们的RE点估算没有错误。如果使用use.u=FALSE,是否完全bootMer考虑了RE点估算值?bootMer使用时的结果似乎与语句中的使用use.u=FALSE等效(或渐近等效)。真的吗?re.form=NApredict()
hossibley 2015年

1
我认为它没有实现ATM,但是您可以通过c(attr(ranef(lme1,condVar=TRUE)[[1]],"postVar"))(在此示例中它们都相同)提取条件模式/ BLUP的条件方差,然后对这些值进行采样。
本·博克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.