【问题标题】:How to minimize size of object of class "lm" without compromising it being passed to predict()如何在不影响传递给 predict() 的情况下最小化“lm”类对象的大小
【发布时间】:2014-03-20 17:09:19
【问题描述】:

我想在一个大型数据集上运行 lm(),该数据集包含 5000 万多个观测值和 2 个预测变量。分析在只有 10GB 存储数据的远程服务器上运行。我已经对从数据中采样的 10K 观察结果进行了“lm()”测试,结果对象的大小为 2GB+。

我只需要从lm() 返回的“lm”类对象来生成模型的汇总统计信息 (summary(lm_object)) 并进行预测 (predict(lm_object))。

我对@9​​87654327@ 的选项model, x, y, qr 做了一些实验。如果我将它们全部设置为FALSE,我会将大小减小 38%

library(MASS)
fit1=lm(medv~lstat,data=Boston)
size1 <- object.size(fit1)
print(size1, units = "Kb")
# 127.4 Kb bytes
fit2=lm(medv~lstat,data=Boston,model=F,x=F,y=F,qr=F)
size2 <- object.size(fit2)
print(size2, units = "Kb")
# 78.5 Kb Kb bytes
- ((as.integer(size1) - as.integer(size2)) / as.integer(size1)) * 100
# -38.37994

但是

summary(fit2)
# Error in qr.lm(object) : lm object does not have a proper 'qr' component.
#  Rank zero or should not have used lm(.., qr=FALSE).
predict(fit2,data=Boston)
# Error in qr.lm(object) : lm object does not have a proper 'qr' component.
#  Rank zero or should not have used lm(.., qr=FALSE).

显然我需要保留qr=TRUE,如果与默认对象相比,它只会将对象大小减少 9%

fit3=lm(medv~lstat,data=Boston,model=F,x=F,y=F,qr=T)
size3 <- object.size(fit3)
print(size3, units = "Kb")
# 115.8 Kb
- ((as.integer(size1) - as.integer(size3)) / as.integer(size1)) * 100
# -9.142752

如何在不将大量不需要的信息转储到内存和存储中的情况下将“lm”对象的大小降至最低?

【问题讨论】:

  • +1 有趣的问题。您还没有尝试过自己切换每个选项吗?顺便说一句,写出 TRUE 和 FALSE 更安全,因为您以后可能会忘记并使用这些名称创建变量。
  • 我相信您会在stackoverflow.com/questions/15260429/… 或链接的其中一个问题中找到答案
  • 我看不出lm 仅使用 10000 个观察值如何产生 2GB 的对象。您的数据集中有多少列?
  • @HongOoi 我在模型中使用了两个预测变量。我认为包含我没有建模的变量的数据集有 5 列
  • 10000x5 的数据集不可能产生 2GB 的对象。我会检查以确保您不会意外包含大型环境。你是从另一个函数内部调用lm 来操作你的大数据集吗?

标签: r memory lm


【解决方案1】:

我也在尝试处理同样的问题。我使用的对其他东西并不完美,但适用于预测,您基本上可以取出 lm 中 qr 插槽的 qr 插槽:

lmFull <- lm(Volume~Girth+Height,data=trees)
lmSlim <- lmFull
lmSlim$fitted.values <- lmSlim$qr$qr <- lmSlim$residuals <- lmSlim$model <- lmSlim$effects <- NULL
pred1 <- predict(lmFull,newdata=data.frame(Girth=c(1,2,3),Height=c(2,3,4)))
pred2 <- predict(lmSlim,newdata=data.frame(Girth=c(1,2,3),Height=c(2,3,4)))
identical(pred1,pred2)
[1] TRUE

as.numeric((object.size(lmFull) - object.size(lmSlim)) / object.size(lmFull))
[1] 0.6550523

【讨论】:

    【解决方案2】:

    这里的链接提供了相关答案(glm object,它与lm output object非常相似)。

    http://www.win-vector.com/blog/2014/05/trimming-the-fat-from-glm-models-in-r/

    基本上,预测只使用glm输出中很小一部分的系数部分。下面的函数(从链接复制)修剪不会被预测使用的信息。

    它确实有一个警告。修剪后,它不能被 summary(fit) 或其他汇总函数使用,因为这些函数需要的比 predict 需要的更多。

    cleanModel1 = function(cm) {
      # just in case we forgot to set
      # y=FALSE and model=FALSE
      cm$y = c()
      cm$model = c()
    
      cm$residuals = c()
      cm$fitted.values = c()
      cm$effects = c()
      cm$qr$qr = c()
      cm$linear.predictors = c()
      cm$weights = c()
      cm$prior.weights = c()
      cm$data = c()
      cm
    }
    

    【讨论】:

    • 那篇文章声称减少了 99.7%(对于小型模型)到 99.985% 减少(大型)。另外,在修剪模型之前执行summary(fit2) 并保存到文本文件。
    • 我最近测试,发现输出对象中的元素或子元素可以进一步缩小,只需尝试清空它们中的每一个,如果它仍然有效,则将结果用于predict()。另一方面,该对象唯一有用的部分是 fit$coefficients。在引导练习中,我重新拟合了模型 1000 次,并且只保存了预测系数,这比保存 1000 个 glm 结果对象节省了更多的内存。
    【解决方案3】:

    xappp 的回答很好,但不是全部。还有一个巨大的环境变量你可以做一些事情(见:https://blogs.oracle.com/R/entry/is_the_size_of_your

    或者把这个添加到xappp的函数中

         e <- attr(cm$terms, ".Environment")
         parent.env(e) <- emptyenv()
         rm(list=ls(envir=e), envir=e)
    

    或者使用这个减少数据但允许你仍然使用summary()的版本

          cleanModel1 = function(cm) {
          # just in case we forgot to set
          # y=FALSE and model=FALSE
          cm$y = c()
          cm$model = c()
    
          e <- attr(cm$terms, ".Environment")
          parent.env(e) <- emptyenv()
          rm(list=ls(envir=e), envir=e)
          cm
          }
    

    【讨论】:

    • 只有在使用其他功能安装模型时才应该使用它。在全局环境中正常使用lm,这将开始删除搜索路径上的各种对象。
    猜你喜欢
    • 1970-01-01
    • 2012-01-20
    • 2014-08-09
    • 1970-01-01
    • 2021-03-29
    • 2016-04-18
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多