R 中的 GLM 对象占用的 RAM 多于 GLM 对象的对象大小

GLM object in R takes more RAM than the object size of the GLM object

我正在尝试将多个 GLM 对象保存在一个列表中。一个 GLM 对象在大型数据集上进行训练,但是通过将 GLM 对象中所有不必要的数据设置为 NULL 来减小对象的大小。问题是我遇到了 RAM 问题,因为 R 保留的 RAM 比 GLM 对象的大小多得多。有人知道为什么会出现这个问题以及我该如何解决?在这个保存对象的背后导致一个比对象大小更大的文件。

示例:

> glm_full <- glm(formula = formule , data = dataset, family = binomial(), model = F, y = F)
> glm_full$data <- glm_full$model <- glm_full$residuals <- glm_full$fitted.values <- glm_full$effects <- glm_full$qr$qr <- glm_full$linear.predictors <- glm_full$weights <- glm_full$prior.weights <- glm_full$y <- NULL
> rm(list= ls()[!(ls() %in% c('glm_full'))])
> object.size(glm_full)
172040 bytes
> gc()
           used  (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells   944802  50.5    3677981  196.5   3862545  206.3
Vcells 83600126 637.9  503881514 3844.4 629722059 4804.4
> rm(glm_full)
> gc()
          used (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells  944208 50.5    2942384  157.2   3862545  206.3
Vcells 4474439 34.2  403105211 3075.5 629722059 4804.4

这里可以看到R为GLM对象预留了RAM,在环境中保存多个GLM对象会导致RAM不足的问题。

对此的粗略解释是,glm 隐藏了指向环境和环境中事物的指针,深入到 glm 对象内部(以及许多地方)。

您需要 glm 做什么?即使你已经消除了模型的很多 "fat",你的对象大小仍然会随着你的数据大小线性增长,当你通过存储多个 glm 对象来复合时,会碰到RAM 限制是一个明显的问题。

这是一个功能,可以让您切掉几乎所有非必要的东西,最好的部分是 glm 对象大小将保持不变,无论您的数据有多大。

stripGlmLR = function(cm) {
  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$family$variance = c()
  cm$family$dev.resids = c()
  cm$family$aic = c()
  cm$family$validmu = c()
  cm$family$simulate = c()
  attr(cm$terms,".Environment") = c()
  attr(cm$formula,".Environment") = c()

  cm
}

一些注意事项:

您可以完全取消 model$family 并且 predict 函数仍将 return 其默认值(因此,predict(model, newdata = data)) 将起作用)。但是,predict(model, newdata=data, type = 'response') 会失败。您可以通过将 link 值传递给反 link 函数来恢复 response:在逻辑回归的情况下,这是 sigmoid 函数 sigmoid(x) = 1/(1 + exp(-x))。 (不确定 type = 'terms'

最重要的是,除 predict 之外,您可能希望对 glm 模型执行的任何其他操作在精简版本上都将失败(因此 summary()anova()step() 都是不行的)。因此,明智的做法是从 glm 对象中提取所有这些信息,然后 运行 stripGlmLR 函数。

致谢:Nina Zumelglm 对象内存分配的精彩分析