如何模拟随机斜率模型

机器算法验证 r 混合模式 模拟
2022-03-13 13:20:17

我想为不平衡的数据集创建一个混合线性模型(每个主题的事件数量不同,某些时间点的一些缺失值)。我正在使用R version 3.2.1 (2015-06-18), package: nlme_3.1-120

模拟数据来了:

library(nlme)
set.seed(1)
subject    <- factor(rep(c(1, 1, 2, 3, 4, 4, 4, 5, 6, 7, 7, 8, 9, 9, 10, 
                           11, 11, 11, 12, 13), 10))
event      <- factor(rep(1:20, 10))
timepoint  <- rep(1:10, each = 20)
measure    <- rnorm(length(timepoint)) + timepoint*0.3
timepoint  <- factor(timepoint)
measure[sample(1:length(measure), rpois(5,4))] <- NA
data       <- data.frame(subject=subject, event=event, timepoint=timepoint, 
                         measure=measure)
str(data)

该模型应将不同时间点的变量“测量”预测为固定效应,并将受试者和事件预测为随机效应。

base      <- lme(measure ~ 1,         data=data, random= ~ 1|subject, 
                 na.action=na.exclude, method="ML")
intercept <- lme(measure ~ timepoint, data=data, random= ~ 1|subject, 
                 na.action=na.exclude, method="ML")
nested    <- lme(measure ~ timepoint, data=data, random= ~ 1|subject/event, 
                 na.action=na.exclude, method="ML")
anova(base, intercept, nested)

我想拟合随机截距和斜率,因为截距和斜率可能因主题和事件而异。但是,当我添加随机斜率效应时,模型不会收敛。它没有通过任何错误消息,但它运行到无穷大。我能做些什么来创建一个随机斜率收敛的模型?

洞穴模型无穷无尽

slope <- lme(measure ~ timepoint, data=data, random= ~ timepoint|subject, 
             na.action=na.exclude, method="ML")

我也试过这个

洞穴模型无穷无尽

slope2 <- lme(measure ~ timepoint, data=data, random= ~ timepoint|subject, 
              na.action=na.exclude, method="ML", control=list(opt="optim"))

洞穴某些模型可能会无休止地运行

slope3      <- lme(measure ~ timepoint, data=data, random= ~ timepoint|subject/event, 
                   na.action=na.exclude, method="ML", control = list(opt="optim"))
covariance  <- lme(measure ~ timepoint, data=data, random= ~ timepoint|subject, 
                   correlation=corAR1(),na.action = na.exclude, method="ML")
covariance2 <- lme(measure ~ timepoint, data=data, random= ~ timepoint|subject, 
                   correlation=corAR1(0), na.action=na.exclude, method="ML", 
                   control=list(opt="optim"))
covariance3 <- lme(measure ~ timepoint, data=data, random= ~ timepoint|subject, 
                   correlation=corAR1(0), na.action=na.exclude, method="ML", 
                   control=list(maxlter=1000))
2个回答

@AdamO 在识别代码中的特定错误方面做得很好。让我更笼统地回答这个问题。这是我模拟线性混合效果模型的方法:

混合效应模型假设每个单元都具有从多元正态分布中提取的随机效应。(在估计模型时,为随机效应估计的是多元正态的方差和协方差。)我首先指定此分布并生成(伪)随机值作为随机效应。将方差指定为通常很方便,因此协方差是斜率和截距之间的相关性(这对我来说更容易概念化)。 1

library(MASS)
ni = 13                                                 # number of subjects
RE = mvrnorm(ni, mu=c(0,0), Sigma=rbind(c(1.0, 0.3),
                                        c(0.3, 1.0) ))
colnames(RE) = c("ints","slopes");  t(round(RE,2))
#         [,1]  [,2]  [,3] [,4]  [,5]  [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
# ints    0.81 -0.52 -0.65 1.30 -0.29 -1.15 0.04 0.05 0.00 -0.29  2.40 -0.05 -0.47
# slopes -1.82  0.81 -0.70 1.28  0.82 -0.18 0.74 1.14 0.93 -0.20  0.04  0.68 -0.53

接下来,我将生成我的变量。我无法真正遵循您示例的逻辑,因此我将用作唯一的回归器。 Xtime

nj   = 10                              # number of timepoints
data = data.frame(ID   = rep(1:ni,   each=nj), 
                  time = rep(1:nj,   times=ni),
                  RE.i = rep(RE[,1], each=nj),
                  RE.s = rep(RE[,2], each=nj),
                  y    = NA                    )
head(data, 14)
#    ID time       RE.i       RE.s  y
# 1   1    1  0.8051709 -1.8152973 NA
# 2   1    2  0.8051709 -1.8152973 NA
# 3   1    3  0.8051709 -1.8152973 NA
# 4   1    4  0.8051709 -1.8152973 NA
# 5   1    5  0.8051709 -1.8152973 NA
# 6   1    6  0.8051709 -1.8152973 NA
# 7   1    7  0.8051709 -1.8152973 NA
# 8   1    8  0.8051709 -1.8152973 NA
# 9   1    9  0.8051709 -1.8152973 NA
# 10  1   10  0.8051709 -1.8152973 NA
# 11  2    1 -0.5174601  0.8135761 NA
# 12  2    2 -0.5174601  0.8135761 NA
# 13  2    3 -0.5174601  0.8135761 NA
# 14  2    4 -0.5174601  0.8135761 NA

生成随机效应和回归量后,您可以指定数据生成过程。由于您想要一些随机错过的时间点,因此这里存在一定程度的额外复杂性。(请注意,这些数据完全随机缺失;有关模拟缺失数据的更多信息,请参阅:如何模拟不同类型的缺失数据。)

y       = with(data, (0 + RE.i) + (.3 + RE.s)*time + rnorm(n=ni*nj, mean=0, sd=1))
m       = rbinom(n=ni*nj, size=1, prob=.1)  
y[m==1] = NA
data$y  = y
head(data, 14)
#    ID time       RE.i       RE.s           y
# 1   1    1  0.8051709 -1.8152973  -0.8659219
# 2   1    2  0.8051709 -1.8152973  -3.6961761
# 3   1    3  0.8051709 -1.8152973  -4.2188711
# 4   1    4  0.8051709 -1.8152973  -4.8380769
# 5   1    5  0.8051709 -1.8152973  -5.4126362
# 6   1    6  0.8051709 -1.8152973  -8.3894008
# 7   1    7  0.8051709 -1.8152973          NA
# 8   1    8  0.8051709 -1.8152973 -11.3710128
# 9   1    9  0.8051709 -1.8152973 -14.2095646
# 10  1   10  0.8051709 -1.8152973 -14.7627970
# 11  2    1 -0.5174601  0.8135761   0.2018260
# 12  2    2 -0.5174601  0.8135761          NA
# 13  2    3 -0.5174601  0.8135761   3.9232935
# 14  2    4 -0.5174601  0.8135761          NA

此时,您可以拟合您的模型。我通常使用这个lme4包。

library(lme4)
summary(lmer(y~time+(time|ID), data))
# Linear mixed model fit by REML ['lmerMod']
# Formula: y ~ time + (time | ID)
#    Data: data
# 
# REML criterion at convergence: 378.3
# 
# Scaled residuals: 
#      Min       1Q   Median       3Q      Max 
# -2.48530 -0.61824 -0.08551  0.59285  2.70687 
# 
# Random effects:
#   Groups   Name        Variance Std.Dev. Corr 
#   ID       (Intercept) 0.9970   0.9985        
#            time        0.8300   0.9110   -0.05
#   Residual             0.7594   0.8715        
# Number of obs: 112, groups:  ID, 13
# 
# Fixed effects:
#             Estimate Std. Error t value
# (Intercept)  0.03499    0.33247   0.105
# time         0.53454    0.25442   2.101
# 
# Correlation of Fixed Effects:
#      (Intr)
# time -0.100

您的模拟中有一个明显的错误。但是,一般来说,不可能生成数据以保证随机斜率模型收敛。

您需要应用的修复是时间点。时间点是一个因素。您不应该在随机斜率模型中使用因子水平变量,它与随机截距完全混叠。

尝试

data$timepoint <- as.numeric(data$timepoint)

slope <- lme(measure ~ factor(timepoint), data=data, 
  random=~timepoint|subject, na.action=na.exclude, method="ML")

这立即收敛。它也适当地嵌套在其他模型中。

充分利用该try()命令来“捕获”具有收敛失败的模拟输出。您可以使用处于其能力“边界”的数值求解器来探索有趣的行为。