这是一个棘手的问题,因为我无法提供可重复的例子,但我希望其他人可能有过处理这个问题的经验。
本质上我有一个函数可以从DB中提取大量数据,清理并减小大小并循环一些参数,以生成一系列lm模型对象,参数值和其他参考值。这被编译成一个总计大约10mb的复杂列表结构。
然后它应该保存为AWS s3上的RDS文件,在生产环境中检索它以构建预测。
e.g。
db.connection <- db.connection.object
build_model_list <- function(db.connection) {
clean_and_build_models <- function(db.connection, other.parameters) {
get_db_data <- function(db.connection, some.parameters) {# Retrieve db data} ## Externally defined
db.data <- get_db_data()
build_models <- function(db.data, some.parameters) ## Externally defined
clean_data <- function(db.data, some.parameters) {# Cleans and filters data based on parameters} ## Externally defined
clean.data <- clean_data()
lm_model <- function(clean.data) {# Builds lm model based on clean.data} ## Externally defined
lm.model <- lm_model()
return(list(lm.model, other.parameters))} ## Externally defined
looped.model.object <- llply(some.parameters, clean_and_build_models)
return(looped.model.object)}
model.list <- build_model_list()
saveRDS(model.list, "~/a_place/model_list.RDS")
我得到的问题是,当我在本地保存为RDS或尝试上传到AWS s3时,内存仅为10MB的'model.list'对象将膨胀为多GB。
我应该注意,尽管该函数处理了大量数据(约500万行),但输出中使用的数据不会超过几百行。
在Stack Exchange上读取有限的信息,我发现在main函数中移动一些外部定义的函数(作为包的一部分)(例如clean_data和lm_model)有助于减少RDS保存大小。 / p> 然而,这有一些很大的缺点。
首先是试验和错误,没有明确的逻辑顺序,频繁崩溃,并且花了几个小时来构建列表对象,这是一个非常长的调试周期。
其次,这意味着我的主要功能将是数百行,这将使未来的更改和调试变得更加棘手。
我的问题是:
之前有没有人遇到过这个问题?
关于是什么导致它的任何假设?
有没有人找到合理的非试错法?
感谢您的帮助。
答案 0 :(得分:5)
我花了一些时间进行挖掘,但实际上我确实找到了解决方案。
事实证明,这是lm模型对象是有罪的一方。基于这篇非常有用的文章:
https://blogs.oracle.com/R/entry/is_the_size_of_your
事实证明,lm.object $ terms组件包含一个环境组件,该组件在构建模型时引用全局环境中存在的对象。在某些情况下,当你保存RDS时,R会尝试将环境对象绘制到保存对象中。
由于我在全局环境中有~0.5GB的空间和大约200 lm模型对象的列表数组,这导致RDS对象在实际尝试压缩~100GB数据时显着膨胀。
测试这是否是造成问题的原因。执行以下代码:
as.matrix(lapply(lm.object, function(x) length(serialize(x,NULL))))
这将告诉您$ terms组件是否正在膨胀。
以下代码将从$ terms组件中删除环境引用:
rm(list=ls(envir = attr(lm.object$terms, ".Environment")), envir = attr(lm.object$terms, ".Environment"))
请注意,但它也会删除它引用的所有全局环境对象。
答案 1 :(得分:1)
对于模型对象,您还可以简单地删除对环境的引用。
例如这样的
ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14)
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69)
group <- gl(2, 10, 20, labels = c("Ctl","Trt"))
weight <- c(ctl, trt)
lm.D9 <- lm(weight ~ group)
attr(lm.D9$terms, ".Environment") <- NULL
saveRDS(lm.D9, file = "path_to_save.RDS")
这很遗憾破坏了模型-但是您可以在再次加载后手动添加环境。
readRDS("path_to_save.RDS")
attr(lm.D9$terms, ".Environment") <- globalenv()
这在我的特定用例中为我提供了帮助,对我来说似乎更省钱...