saveRDS膨胀对象的大小

时间:2017-02-14 16:07:54

标签: r save gzip

这是一个棘手的问题,因为我无法提供可重复的例子,但我希望其他人可能有过处理这个问题的经验。

本质上我有一个函数可以从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> 然而,这有一些很大的缺点。

首先是试验和错误,没有明确的逻辑顺序,频繁崩溃,并且花了几个小时来构建列表对象,这是一个非常长的调试周期。

其次,这意味着我的主要功能将是数百行,这将使未来的更改和调试变得更加棘手。

我的问题是:

之前有没有人遇到过这个问题?

关于是什么导致它的任何假设?

有没有人找到合理的非试错法?

感谢您的帮助。

2 个答案:

答案 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()

这在我的特定用例中为我提供了帮助,对我来说似乎更省钱...