R语言中foreach循环输出存为.Rdata文件体积过大的优化咨询
解决foreach并行拟合混合效应模型后.Rdata文件体积过大的问题
问题重现
串行拟合代码
library(lme4) mod_list <- vector("list", length = 5) for (i in 1:5) { # 使用唯一数据集拟合每个模型 m <- lmer(Reaction ~ Days + (1|Subject), sleepstudy[-i,]) mod_list[i] <- list(m) }
并行拟合代码
library(doParallel) library(foreach) UseCores <- detectCores() cl <- makeCluster(UseCores) registerDoParallel(cl) mod_list2 <- foreach(i=1:5) %dopar% { library(lme4) # 使用唯一数据集拟合每个模型 m <- lmer(Reaction ~ Days + (1|Subject), sleepstudy[-i,]) m } stopCluster(cl)
现象对比
内存中两个列表的大小一致:
print(object.size(mod_list), units = "auto") #> 143 Kb print(object.size(mod_list2), units = "auto") #> 143 Kb
但保存为.Rdata文件后体积差异显著:
mod_list对应文件:172 kBmod_list2对应文件:611 kB
原因分析
串行拟合的模型均绑定到全局环境:
lapply(1:5, function (x) attributes(attributes(mod_list[[x]]@frame)$terms)$.Environment) #> [[1]] <environment: R_GlobalEnv> #> [[2]] <environment: R_GlobalEnv> #> [[3]] <environment: R_GlobalEnv> #> [[4]] <environment: R_GlobalEnv> #> [[5]] <environment: R_GlobalEnv>
而foreach并行拟合的每个模型都绑定到独立的子环境,这些环境会被完整序列化保存,导致文件体积暴增:
lapply(1:5, function (x) attributes(attributes(mod_list2[[x]]@frame)$terms)$.Environment) #> [[1]] <environment: 0x00000166d0383b20> #> [[2]] <environment: 0x00000166d07f54d0> #> [[3]] <environment: 0x00000166cff38db0> #> [[4]] <environment: 0x00000166d1df1bb0> #> [[5]] <environment: 0x00000166d206ecc8>
解决方案
1. 重置模型的环境引用为全局环境
遍历并行得到的模型列表,将每个模型的terms环境替换为全局环境,消除独立子环境的冗余信息:
clean_model_env <- function(model) { attr(attr(model@frame, "terms"), ".Environment") <- .GlobalEnv model } # 清理并行模型列表 mod_list2_cleaned <- lapply(mod_list2, clean_model_env)
2. 在foreach循环体内直接清理环境
在并行任务内部完成环境重置,避免后续统一处理:
mod_list2 <- foreach(i=1:5) %dopar% { library(lme4) m <- lmer(Reaction ~ Days + (1|Subject), sleepstudy[-i,]) # 子进程内直接清理环境 attr(attr(m@frame, "terms"), ".Environment") <- .GlobalEnv m }
3. 拟合模型时减少冗余数据
若后续不需要从模型中提取原始数据,可使用keep.data=FALSE参数,进一步缩小对象体积:
mod_list2 <- foreach(i=1:5) %dopar% { library(lme4) m <- lmer(Reaction ~ Days + (1|Subject), sleepstudy[-i,], keep.data = FALSE) attr(attr(m@frame, "terms"), ".Environment") <- .GlobalEnv m }
4. 配合高压缩级别保存
清理环境后,可使用高压缩参数进一步缩小文件:
save(mod_list2_cleaned, file = "cleaned_models.Rdata", compress = "xz", compression_level = 9)
验证效果
清理后保存的文件体积会大幅降低,与串行拟合的模型文件体积基本一致。
内容的提问来源于stack exchange,提问作者Hanz
相关产品推荐
相关产品推荐

