`lm` return `model` 是否出于 `predict` 以外的原因

Does `lm` return `model` for reasons other than `predict`

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

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

不需要回答,但我也想知道出于 predict 以外的原因存储数据的模型。

例子

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

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

动机

为了分享我的动力,twidlr package forces users to provide data when using predict. If this makes copying the dataset when learning unnecessary, it seems reasonable to save memory by defaulting to model = FALSE. I've opened a relevant issue here

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

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

让我们看一个小例子。

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)

失败了?

这是我一年前回答/调查过的一个问题:有人要求 survival 包。这个例子真的很极端:即使我们提供 newdata,我们仍然会出错。保留模型框架是唯一的方法!


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


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