【问题标题】:Does `lm` return `model` for reasons other than `predict``lm` 是否因为`predict` 以外的原因返回`model`
【发布时间】:2017-11-27 14:09:54
【问题描述】:

lm 默认设置model = TRUE,这意味着用于学习的整个数据集被复制并与拟合对象一起返回。这由predict 使用,但会产生内存开销(示例如下)。

我想知道,复制的数据集是否用于predict以外的任何其他原因?

没有必要回答,但我也想知道以 predict 以外的原因存储数据的模型。

示例

object.size(lm(mpg ~ ., mtcars))
#> 45768 bytes
object.size(lm(mpg ~ ., mtcars, model = FALSE))
#> 28152 bytes

更大的数据集 = 更大的开销。

动机

为了分享我的动机,twidlr 包强制用户在使用predict 时提供数据。如果这使得在学习时复制数据集变得不必要,那么默认为model = FALSE 来节省内存似乎是合理的。我已经打开了一个相关的问题here

次要动机 - 您可以轻松地将 lm 等许多模型与 pipelearner 匹配,但每次复制数据都会产生大量开销。所以找到减少内存需求的方法会非常方便!

【问题讨论】:

  • 不确定这是否相关,但 data.frame 有时有助于确定创建模型的数据的特征。例如,如果您拟合这样的模型lm(mpg ~ drat^2, data=mtcars),data.frame 将为您提供mpgdrat 的实际值,否则您将不知道drat 的分布以及它是否由于平方数据的转换,可能会呈现正值或负值。
  • 如果我知道 data.frame 的分布,我可以更好地了解在进行新预测时我是从模型中插值还是外推。
  • 感谢@StevenMortimer。虽然这不是我所追求的,但我同意了解数据的属性很重要。但是,我倾向于在建模之前执行此操作,而不是先拟合模型然后检查复制的数据。
  • 是的,没错,但有时您会得到其他人的模型,原始数据会丢失或无法供您检查。
  • 对我来说,存储数据的频率不足以保证存储数据(尤其是当您可能要拟合 1000 多个模型和/或基于大型数据集时),但我明白您的意思。如果像这样传递它们,我希望人们能正确记录合适的模型。我的问题的另一个原因是lm 以外的许多模型指向而不是复制数据。例如,见gist.github.com/drsimonj/5b2cfc428fce350676db5dc77c059052

标签: r memory lm


【解决方案1】:

我认为返回模型框架是为了防止非标准评估。

我们来看一个小例子。

dat <- data.frame(x = runif(10), y = rnorm(10))
FIT <- lm(y ~ x, data = dat)
fit <- FIT; fit$model <- NULL

有什么区别

model.frame(FIT)
model.frame(fit)

??检查methods(model.frame)stats:::model.frame.lm 表明,在第一种情况下,模型框架是从FIT$model 中有效提取的;而在第二种情况下,它将从fit$callmodel.frame.default 重构。这样的差异也导致了两者之间的差异

# depends on `model.frame`
model.matrix(FIT)
model.matrix(fit)

因为模型矩阵是从模型框架构建的。如果我们进一步挖掘,我们会发现这些也是不同的,

# depends on `model.matrix`
predict(FIT)
predict(fit)

# depends on `predict.lm`
plot(FIT)
plot(fit)

请注意,这可能是问题所在。如果我们故意去掉dat,我们无法重建模型框架,那么这一切都会失败:

rm(dat)
model.frame(fit)
model.matrix(fit)
predict(fit)
plot(fit)

使用FIT 时会起作用。


这还不够糟糕。下面这个非标准评价下的例子真的很糟糕!

fitting <- function (myformula, mydata, keep.mf = FALSE) {
  b <- lm(formula = myformula, data = mydata, model = keep.mf)
  par(mfrow = c(2,2))
  plot(b)
  predict(b)
  }

现在让我们再次创建一个数据框(我们之前已将其删除)

dat <- data.frame(x = runif(10), y = rnorm(10))

你能看到吗

fitting(y ~ x, dat, keep.mf = TRUE)

有效但

fitting(y ~ x, dat, keep.mf = FALSE)

失败了?

这是我一年前回答/调查的一个问题:R - model.frame() and non-standard evaluation 它被要求提供survival 包。这个例子真的很极端:即使我们提供newdata,我们仍然会出错。保留模型框架是唯一的方法!


最后关于您对内存成本的观察。事实上,$model 并不是主要负责潜在的大 lm 对象。 $qr 是,因为它与模型矩阵具有相同的维度。考虑一个有很多因素的模型,或者像bsnspoly这样的非线性项,模型框架与模型矩阵相比要小得多。因此省略模型帧返回无助于减少lm 对象大小。这实际上是开发biglm 的动机之一。


由于我不可避免地提到了biglm,我再次强调,这种方法只有助于减少最终模型对象的大小,而不是模型拟合期间的 RAM 使用量。

【讨论】:

  • 很好的答案!谢谢。从您的回答中,我看到plot 是个问题。另外,我注意到 qr 占用了内存,但我认为有必要进行预测(而模型框架不是)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-12
  • 2016-10-16
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 2019-01-29
相关资源
最近更新 更多