为什么插入符号列车占用了这么多记忆?

Yan*_*ang 20 memory r glm r-caret

当我训练只是使用时glm,一切正常,我甚至没有接近耗尽记忆.但是当我跑步时train(..., method='glm'),我的内存耗尽.

这是因为train为交叉验证的每次迭代存储了大量数据(或者无论trControl程序是什么)?我在看,trainControl我找不到如何防止这种...任何提示?我只关心性能总结和预测的响应.

(我知道它与存储参数调整网格搜索的每次迭代中的数据无关,因为我认为没有glm的网格.)

Rei*_*son 37

这个问题有两个问题.ⅰ) train并不仅仅适合经由模型glm(),它会引导该模型,因此,即使与所述默认值,train()将做25个bootstrap样本,其中,加上问题ii)中(或一个您的问题的)源和ⅱ) train()简单地调用glm()与功能默认设置.并且这些默认值是存储模型框架(自变量model = TRUE?glm),其中包括数据的模型框架样式的副本.返回的对象train()已经存储了数据的副本$trainingData,并且该"glm"对象$finalModel也具有实际数据的副本.

在这一点上,只需运行glm()使用train()将生产的完全展开的25个人副本model.frame 原始数据,这将都需要在内存中的重采样过程举行-这些是否同时举行或连续不从快看不清楚在代码中,重新采样发生在lapply()呼叫中.还将有25份原始数据.

重新采样完成后,返回的对象将包含2个原始数据副本和完整副本model.frame.如果您的训练数据相对于可用的RAM很大或者包含许多要扩展的因素model.frame,那么您可能很容易使用大量内存来携带数据副本.

如果您加入model = FALSE火车通话,那可能会有所不同.以下是使用以下clotting数据的小例子?glm:

clotting <- data.frame(u = c(5,10,15,20,30,40,60,80,100),
                       lot1 = c(118,58,42,35,27,25,21,19,18),
                       lot2 = c(69,35,26,21,18,16,13,12,12))
require(caret)
Run Code Online (Sandbox Code Playgroud)

然后

> m1 <- train(lot1 ~ log(u), data=clotting, family = Gamma, method = "glm", 
+             model = TRUE)
Fitting: parameter=none 
Aggregating results
Fitting model on full training set
> m2 <- train(lot1 ~ log(u), data=clotting, family = Gamma, method = "glm",
+             model = FALSE)
Fitting: parameter=none 
Aggregating results
Fitting model on full training set
> object.size(m1)
121832 bytes
> object.size(m2)
116456 bytes
> ## ordinary glm() call:
> m3 <- glm(lot1 ~ log(u), data=clotting, family = Gamma)
> object.size(m3)
47272 bytes
> m4 <- glm(lot1 ~ log(u), data=clotting, family = Gamma, model = FALSE)
> object.size(m4)
42152 bytes
Run Code Online (Sandbox Code Playgroud)

因此返回的对象存在大小差异,并且训练期间的内存使用将更低.低多少将取决于在重采样过程中是否train()保留model.frame内存中的所有副本的内部.

返回的对象train()也明显大于glm()- 由@DWin在下面的注释中提到的对象.

为了进一步借此,要么更仔细地研究代码,或通过电子邮件发送最大库恩的维护者插入符号,打听选项,以减少内存占用.


小智 31

加文的答案是现场.我建立了易于使用的功能,而不是速度或效率[1]

首先,当您拥有大量预测变量时,使用公式界面可能会成为一个问题.这是R Core可以解决的问题; 公式方法需要terms()保留一个非常大但稀疏的矩阵,并且R具有有效处理该问题的包.例如,当n = 3,000和p = 2,000时,3树随机森林模型对象的大小是1.5倍,使用公式界面时需要花费23倍的时间(282s vs 12s).

其次,您不必保留训练数据(参见returnData参数trainControl()).

此外,由于R没有任何真正的共享内存基础结构,Gavin对于保留在内存中的数据副本的数量是正确的.基本上,为每个重新采样创建一个列表,lapply()用于处理列表,然后仅返回重新采样的估计值.另一种方法是顺序制作一份数据(对于当前的重采样),进行所需的操作,然后重复进行剩余的迭代.问题是I/O和无法进行任何并行处理.[2]

如果你有一个大数据集,我建议使用非公式接口(即使实际模型,如glm,最终使用公式).此外,对于大型数据集,train()保存重采样索引以供其使用resamples()和其他功能.你也可以删除它们.

杨 - 通过str(data)这样了解更多关于数据的信息会很好,所以我们可以理解维度和其他方面(例如,多层次的因素等).

我希望有帮助,

马克斯

[1]我不应该尽我们所能尽可能少地使用尽可能少的模型."子模型"技巧用于许多模型,例如pls,gbm,rpart,earth和许多其他模型.此外,当模型具有公式和非公式接口时(例如,lda()或者earth(),我们默认为非公式接口.

[2]每隔一段时间我就会疯狂地重新启动这项train()功能.使用foreach可能会解决其中一些问题.


Gar*_*oap 5

我认为上面的答案有点过时了。caret 和 caretEnsemble 包现在在 trainControl 'trim' 中包含一个附加参数。Trim 最初设置为 FALSE,但将其更改为 TRUE 将显着减小模型大小。您应该将它与 returnData=FALSE 结合使用,以获得尽可能小的模型尺寸。如果您使用的是模型集成,您还应该在 greedy/stack ensemble trainControl 中指定这两个参数。

就我而言,1.6gb 模型在集成控制中使用两个参数缩小到 ~500mb,并使用贪婪集成控制中的参数进一步缩小到 ~300mb。

Ensemble_control_A9 <- trainControl(trim=TRUE, method = "repeatedcv", number = 3, repeats = 2, verboseIter = TRUE, returnData = FALSE, returnResamp = "all", classProbs = TRUE, summaryFunction = twoClassSummary, savePredictions = TRUE, allowParallel = TRUE, sampling = "up")


Ensemble_greedy_A5 <- caretEnsemble(Ensemble_list_A5, metric="ROC",  trControl=trainControl(number=2, trim=TRUE, returnData = FALSE, summaryFunction=twoClassSummary, classProbs=TRUE))
Run Code Online (Sandbox Code Playgroud)