非线性混合模型(NLME)的预测置信区间


12

我想获得非线性混合nlme模型预测的95%置信区间。由于没有提供任何标准来执行此操作nlme,因此我想知道使用“人口预测间隔”方法是否正确(如Ben Bolker的书章所述,该模型基于最大似然的模型)根据拟合模型的方差-协方差矩阵对固定效应参数进行重采样,基于此模拟进行预测,然后取这些预测的95%百分数得到95%的置信区间?

执行此操作的代码如下:(我在这里使用nlme帮助文件中的“ Loblolly”数据)

library(effects)
library(nlme)
library(MASS)

fm1 <- nlme(height ~ SSasymp(age, Asym, R0, lrc),
    data = Loblolly,
    fixed = Asym + R0 + lrc ~ 1,
    random = Asym ~ 1,
    start = c(Asym = 103, R0 = -8.5, lrc = -3.3))

xvals=seq(min(Loblolly$age),max(Loblolly$age),length.out=100)
nresamp=1000
pars.picked = mvrnorm(nresamp, mu = fixef(fm1), Sigma = vcov(fm1)) # pick new parameter values by sampling from multivariate normal distribution based on fit
yvals = matrix(0, nrow = nresamp, ncol = length(xvals))

for (i in 1:nresamp) 
{
    yvals[i,] = sapply(xvals,function (x) SSasymp(x,pars.picked[i,1], pars.picked[i,2], pars.picked[i,3]))
} 

quant = function(col) quantile(col, c(0.025,0.975)) # 95% percentiles
conflims = apply(yvals,2,quant) # 95% confidence intervals

现在我有了置信度限制,我创建了一个图形:

meany = sapply(xvals,function (x) SSasymp(x,fixef(fm1)[[1]], fixef(fm1)[[2]], fixef(fm1)[[3]]))

par(cex.axis = 2.0, cex.lab=2.0)
plot(0, type='n', xlim=c(3,25), ylim=c(0,65), axes=F, xlab="age", ylab="height");
axis(1, at=c(3,1:5 * 5), labels=c(3,1:5 * 5)) 
axis(2, at=0:6 * 10, labels=0:6 * 10)   

for(i in 1:14)
{
    data = subset(Loblolly, Loblolly$Seed == unique(Loblolly$Seed)[i])   
    lines(data$age, data$height, col = "red", lty=3)
}

lines(xvals,meany, lwd=3)
lines(xvals,conflims[1,])
lines(xvals,conflims[2,])

这是通过这种方式获得的95%置信区间的图:

所有数据(红线),均值和置信度限制(黑线)

这种方法是否有效,或者是否有其他方法或更好的方法可以对非线性混合模型的预测计算出95%的置信区间?我不完全确定如何处理模型的随机效应结构。。。应该平均一个随机效应水平吗?还是对一个平均主题有一个置信区间可以吗?这似乎更接近我现在的水平了吗?


这里没有问题。请清楚您的要求。
adunaic

我现在想更精确地提出问题……
Piet van den Berg

正如我之前在Stack Overflow上问过的那样,我不认为非线性参数的正态性假设是合理的。
罗兰

我没有读过Ben的书,但他似乎在本章中并未提到混合模型。也许您在参考他的书时应该澄清一下。
罗兰

是的,这是在最大似然模型的背景下进行的,但是想法应该是相同的……我已经澄清了……
Piet van den Berg

Answers:


10

您在这里所做的事情看起来很合理。简短的答案是,在大多数情况下,从混合模型和非线性模型预测置信区间的问题或多或少是正交的,也就是说,您需要担心这两组问题,但是它们并不需要(我知道的互动方式很奇怪。

  • 混合模型问题:您是要在总体水平还是群体水平进行预测?您如何考虑随机效应参数的可变性?您是否以小组级别的观察为条件?
  • 非线性模型问题:参数的采样分布是否为正态?传播错误时如何考虑非线性?

在整个过程中,我将假设您是在总体水平上进行预测,并以总体水平来构建置信区间-换句话说,您正在尝试绘制典型组的预测值,而不在您的置信度中包括组间差异间隔。这简化了混合模型问题。下图比较了三种方法(有关代码转储,请参见下文):

  • 人口预测间隔:这是您上面尝试的方法。假设模型是正确的,并且固定效果参数的采样分布为多元正态;它也忽略了随机效应参数的不确定性
  • 引导程序:我实现了分层引导程序;我们在组级别和组内都重新采样。组内采样对残差进行采样并将其添加回预测中。这种方法的假设最少。
  • 增量法(delta method):这既假定了抽样分布的多元正态性,又假定非线性很弱,无法进行二阶近似。

我们还可以进行参数引导...

这是配置项以及数据...

在此处输入图片说明

...但是我们几乎看不到差异。

通过减去预测值进行放大(红色=引导程序,蓝色= PPI,青色=增量法)

在此处输入图片说明

在这种情况下,引导间隔实际上是最窄的(例如,假设参数的采样分布实际上比“正常” 略微稀疏),而PPI和增量方法间隔则非常相似。

library(nlme)
library(MASS)

fm1 <- nlme(height ~ SSasymp(age, Asym, R0, lrc),
            data = Loblolly,
            fixed = Asym + R0 + lrc ~ 1,
            random = Asym ~ 1,
            start = c(Asym = 103, R0 = -8.5, lrc = -3.3))

xvals <-  with(Loblolly,seq(min(age),max(age),length.out=100))
nresamp <- 1000
## pick new parameter values by sampling from multivariate normal distribution based on fit
pars.picked <- mvrnorm(nresamp, mu = fixef(fm1), Sigma = vcov(fm1))

## predicted values: useful below
pframe <- with(Loblolly,data.frame(age=xvals))
pframe$height <- predict(fm1,newdata=pframe,level=0)

## utility function
get_CI <- function(y,pref="") {
    r1 <- t(apply(y,1,quantile,c(0.025,0.975)))
    setNames(as.data.frame(r1),paste0(pref,c("lwr","upr")))
}

set.seed(101)
yvals <- apply(pars.picked,1,
               function(x) { SSasymp(xvals,x[1], x[2], x[3]) }
)
c1 <- get_CI(yvals)

## bootstrapping
sampfun <- function(fitted,data,idvar="Seed") {
    pp <- predict(fitted,levels=1)
    rr <- residuals(fitted)
    dd <- data.frame(data,pred=pp,res=rr)
    ## sample groups with replacement
    iv <- levels(data[[idvar]])
    bsamp1 <- sample(iv,size=length(iv),replace=TRUE)
    bsamp2 <- lapply(bsamp1,
        function(x) {
        ## within groups, sample *residuals* with replacement
        ddb <- dd[dd[[idvar]]==x,]
        ## bootstrapped response = pred + bootstrapped residual
        ddb$height <- ddb$pred +
            sample(ddb$res,size=nrow(ddb),replace=TRUE)
        return(ddb)
    })
    res <- do.call(rbind,bsamp2)  ## collect results
    if (is(data,"groupedData"))
        res <- groupedData(res,formula=formula(data))
    return(res)
}

pfun <- function(fm) {
    predict(fm,newdata=pframe,level=0)
}

set.seed(101)
yvals2 <- replicate(nresamp,
                    pfun(update(fm1,data=sampfun(fm1,Loblolly,"Seed"))))
c2 <- get_CI(yvals2,"boot_")

## delta method
ss0 <- with(as.list(fixef(fm1)),SSasymp(xvals,Asym,R0,lrc))
gg <- attr(ss0,"gradient")
V <- vcov(fm1)
delta_sd <- sqrt(diag(gg %*% V %*% t(gg)))
c3 <- with(pframe,data.frame(delta_lwr=height-1.96*delta_sd,
                             delta_upr=height+1.96*delta_sd))

pframe <- data.frame(pframe,c1,c2,c3)

library(ggplot2); theme_set(theme_bw())
ggplot(Loblolly,aes(age,height))+
    geom_line(alpha=0.2,aes(group=Seed))+
    geom_line(data=pframe,col="red")+
    geom_ribbon(data=pframe,aes(ymin=lwr,ymax=upr),colour=NA,alpha=0.3,
                fill="blue")+
    geom_ribbon(data=pframe,aes(ymin=boot_lwr,ymax=boot_upr),
                colour=NA,alpha=0.3,
                fill="red")+
    geom_ribbon(data=pframe,aes(ymin=delta_lwr,ymax=delta_upr),
                colour=NA,alpha=0.3,
                fill="cyan")


ggplot(Loblolly,aes(age))+
    geom_hline(yintercept=0,lty=2)+
    geom_ribbon(data=pframe,aes(ymin=lwr-height,ymax=upr-height),
                colour="blue",
                fill=NA)+
    geom_ribbon(data=pframe,aes(ymin=boot_lwr-height,ymax=boot_upr-height),
                colour="red",
                fill=NA)+
    geom_ribbon(data=pframe,aes(ymin=delta_lwr-height,ymax=delta_upr-height),
                colour="cyan",
                fill=NA)

因此,如果我理解正确,这将是典型组的置信区间。您还会知道如何将置信区间内的组间差异包括在内吗?那么,是否应该在随机效应水平上取平均值?
Tom Wenseleers
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.