将线性混合模型拟合到非常大的数据集

ste*_*eve 5 parallel-processing r bigdata lme4 mixed-models

我想lme4::lmer在以下格式的60M观测值上运行混合模型(使用); 所有预测变量/因变量都是连续因变量的分类(因子)tc; patient是随机拦截项的分组变量.我有64位R和16Gb RAM,我在中央服务器上工作.RStudio是最新的服务器版本.

model <- lmer(tc~sex+age+lho+atc+(1|patient),
              data=master,REML=TRUE)

lho sex tc      age         atc patient
18  M   16.61   45-54       H   628143
7   F   10.52   12-15       G   2013855
30  M   92.73   35-44       N   2657693
19  M   24.92   70-74       G   2420965
12  F   17.44   65-69       A   2833610
31  F   7.03    75 and over A   1090322
3   F   28.59   70-74       A   2718649
29  F   4.09    75 and over C   384578
16  F   67.22   65-69       R   1579355
23  F   7.7     70-74       C   896374
Run Code Online (Sandbox Code Playgroud)

我收到了一个cannot allocate a vector of 25.5Gb错误.我在服务器上分配40Gb并使用25,所以我想这意味着我需要另外10个左右.我认为我不能分配任何额外的空间.

我不知道关于并行处理的第一件事,除了我目前正在使用四个核心之一.任何人都可以为这个模型建议并行代码,或者可能是另一个修复程序

Ben*_*ker 5

正如 Carl Witthoft 所指出的,R 中的标准并行化工具通过为每个工作人员创建数据副本来工作(我最初称其为共享内存模型,但我认为这不准确),因此在具有以下功能的系统上运行它们:单块内存(与例如“简单的工作站网络”(SNOW)相反,其中每个进程位于不同的机器上)它们将使事情变得更糟而不是更好(它们的主要目的是通过以下方式加速计算密集型作业)使用多个处理器)。

在短期内,您可以通过将分类固定效应预测变量 ( ageatc) 视为随机效应但强制其方差变大来节省一些内存。我不知道这是否足以拯救你;它将大量压缩固定效应模型矩阵,但模型框架仍将与模型对象一起存储/复制......

dd1 <- read.table(header=TRUE,
text="lho sex tc      age         atc patient
18  M   16.61   45-54       H   628143
7   F   10.52   12-15       G   2013855
30  M   92.73   35-44       N   2657693
19  M   24.92   70-74       G   2420965
12  F   17.44   65-69       A   2833610
31  F   7.03    75_and_over A   1090322
3   F   28.59   70-74       A   2718649
29  F   4.09    75_and_over C   384578
16  F   67.22   65-69       R   1579355
23  F   7.7     70-74       C   896374")
n <- 1e5
set.seed(101)
dd2 <- with(dd1,
      data.frame(tc=rnorm(n,mean=mean(tc),sd=sd(tc)),
                 lho=round(runif(n,min=min(lho),max=max(lho))),
                 sex=sample(levels(sex),size=n,replace=TRUE),
                 age=sample(levels(age),size=n,replace=TRUE),
                 atc=sample(levels(atc),size=n,replace=TRUE),
                 patient=sample(1:1000,size=n,replace=TRUE)))
library("lme4")
m1 <- lmer(tc~sex+(1|lho)+(1|age)+(1|atc)+(1|patient),
           data=dd2,REML=TRUE)
Run Code Online (Sandbox Code Playgroud)

随机效应会按照级别数从最大到最小的顺序自动排序。按照帮助页面中描述的机制进行操作?modular

lmod <- lFormula(tc~sex+(1|lho)+(1|age)+(1|atc)+(1|patient),
                  data=dd2,REML=TRUE)
names(lmod$reTrms$cnms)  ## ordering
devfun <- do.call(mkLmerDevfun, lmod)
wrapfun <- function(tt,bigsd=1000) {
    devfun(c(tt,rep(bigsd,3)))
}
wrapfun(1)
opt <- optim(fn=wrapfun,par=1,method="Brent",lower=0,upper=1000)
opt$fval <- opt$value  ## rename/copy
res <- mkMerMod(environment(devfun), opt, lmod$reTrms, fr=lmod$fr)
res
Run Code Online (Sandbox Code Playgroud)

您可以忽略分类项的报告差异,并用于 ranef()恢复其(未缩小的)估计值。

从长远来看,解决这个问题的正确方法可能是将其与分布式内存模型并行化。换句话说,您希望将数据分块分发到不同的服务器;使用 中描述的机制?modular建立似然函数(实际上是 REML 准则函数),该函数将数据子集的 REML 准则作为参数的函数给出;然后运行一个中央优化器,该优化器采用一组参数并通过将参数提交到每个服务器、从每个服务器检索值并将它们相加来评估 REML 标准。我在实现这一点时看到的唯一两个问题是(1)我实际上不知道如何在 R 中实现分布式内存计算(根据这个介绍文档,似乎Rmpi​​ / doMPI包可能是正确的方法) ; (2) 在实现的默认方式中lmer,固定效应参数被分析出来,而不是明确地成为参数向量的一部分。