saveRDS膨胀对象的大小
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了saveRDS膨胀对象的大小相关的知识,希望对你有一定的参考价值。
这是一个棘手的问题,因为我不能提供一个可重复的例子,但我希望其他人可能有过处理这个问题的经验。
基本上我有一个函数可以从DB中提取大量数据,清理并减小大小并循环一些参数,以生成一系列lm模型对象,参数值和其他参考值。这被编译成一个总计大约10mb的复杂列表结构。
然后它应该在AWS s3上保存为RDS文件,在生产环境中检索它以构建预测。
EG
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保存大小。
然而,这有一些很大的缺点。
首先是它的试验和错误,没有明确的逻辑顺序,经常崩溃和建立列表对象需要几个小时,这是一个非常长的调试周期。
其次,这意味着我的主要功能将是数百行,这将使未来的更改和调试变得更加棘手。
我的问题是:
有没有人遇到过这个问题?
关于是什么导致它的任何假设?
有人找到了合乎逻辑的非试错法吗?
谢谢你的帮助。
它需要一些挖掘,但我确实找到了最终的解决方案。
事实证明,这是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"))
请注意,虽然它也会删除它引用的所有全球环境对象。
对于模型对象,您还可以简单地删除对环境的引用。
像这样的例子
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()
这对我的具体用例有所帮助,对我来说看起来有点安全......
以上是关于saveRDS膨胀对象的大小的主要内容,如果未能解决你的问题,请参考以下文章
Android TabLayout ViewPager 不会在 backstack 上膨胀标签片段