为什么插页训练占用这么多的记忆?

当我使用glm训练时,一切都有效,而且我甚至不会耗尽记忆。 但是当我运行train(..., method='glm') ,我用完了内存。

这是否是因为train为交叉验证的每次迭代(或者trControl过程)存储了大量数据? 我在看trainControl ,我无法找到如何防止这...任何提示? 我只关心绩效总结,可能是预测的回应。

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


问题有两个。 i) train不仅仅通过glm()适合模型,它将引导该模型,所以即使使用默认值, train()也会执行25个bootstrap样本,它与问题ii)结合起来是一个(或一个)源你的问题,和ii) train()简单地调用glm()函数的默认值。 这些默认值是存储模型框架(参数model = TRUE ?glm model = TRUE ),其中包括模型框架样式中的数据副本。 train()返回的对象已经将数据的一个副本存储在$trainingData ,而$finalModel"glm"对象也具有实际数据的副本。

在这一点上,简单地使用train()运行glm()将产生完全展开的model.frame和原始数据的25个副本,这些数据在重新采样过程中都需要保存在内存中 - 无论这些数据是同时保存的还是通过lapply()调用发生重采样时,快速查看代码并不会立即清除它。 还将有25份原始数据。

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

如果您在列车呼叫中添加model = FALSE ,那可能会有所不同。 这里是一个使用?glmclotting数据的小例子:

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)

然后

> 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

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

train()返回的对象也显着大于glm()返回的对象 - 正如@DWin在下面的注释中提到的那样。

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


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

首先,当你有很多预测因子时,使用公式接口可能会成为一个问题。 这是R核心可以解决的问题; 公式方法需要保留非常大但稀疏的terms()矩阵,并且R有包来有效处理该问题。 例如,对于n = 3,000和p = 2,000,3树随机森林模型对象的大小是其1.5倍,使用公式界面(282s vs 12s)时执行时间要长23倍。

其次,你没有保持训练数据(见returnData在参数trainControl()

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

如果你有一个大的数据集,我建议使用非公式接口(尽管像glm这样的实际模型最终使用公式)。 此外,对于大数据集, train()保存resamples()和其他函数使用的resamples()采样索引。 你也可以删除这些。

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

我希望这有助于,

马克斯

[1]我们不应该尽我们所能去尽可能地减少模型的数量。 “子模型”技巧用于许多模型,例如pls,gbm,rpart,earth和其他许多模型。 另外,当模型具有公式和非公式接口(例如, lda()earth() ,我们默认为非公式接口。

[2]每隔一段时间,我都会得到重启train()函数的疯狂冲动。 使用foreach可能会解决其中的一些问题。


我认为上面的答案有点过时了。 脱字符和caretEnsemble包现在在trainControl'trim'中包含一个附加参数。 修剪初始设置为FALSE,但将其更改为TRUE将显着减小模型大小。 对于可能的最小模型大小,您应该结合使用returnData = FALSE。 如果您使用的是模型集合,则还应该在贪婪/堆栈集合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))
链接地址: http://www.djcxy.com/p/38379.html

上一篇: Why is caret train taking up so much memory?

下一篇: Automatically split function output (list) into component data.frames