首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么插入符号训练会占用这么多内存?

为什么插入符号训练会占用这么多内存?
EN

Stack Overflow用户
提问于 2011-07-01 13:38:06
回答 3查看 9.3K关注 0票数 21

当我只使用glm进行训练时,一切都会正常工作,而且我甚至不会耗尽内存。但是当我运行train(..., method='glm')时,我耗尽了内存。

这是因为train为交叉验证的每次迭代(或trControl过程)存储了大量数据吗?我正在查看trainControl,但我找不到如何防止this...any提示?我只关心性能总结,也许还有预测的响应。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-01 16:19:29

这个问题有两个方面。i) train不只是通过glm()来拟合模型,它会引导该模型,所以即使使用默认值,train()也会执行25个引导示例,再加上问题ii)就是问题的根源,而ii) train()只是使用其默认值调用glm()函数。这些默认值是存储模型框架(?glm的参数model = TRUE ),其中包括模型框架样式中的数据副本。train()返回的对象已经在$trainingData中存储了数据的副本,$finalModel中的"glm"对象也有实际数据的副本。

此时,只需使用train()运行glm()就会生成完全扩展的model.frame和原始数据的25个副本,这些副本都需要在重采样过程中保存在内存中-由于重采样发生在lapply()调用中,因此通过快速查看代码不能立即确定这些副本是并发的还是连续的。还将有25份原始数据副本。

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

如果您将model = FALSE添加到您的火车呼叫中,这可能会有所不同。下面是一个在?glm中使用clotting数据的小示例

代码语言:javascript
复制
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)

然后

代码语言:javascript
复制
> 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在下面的评论中提到的那样。

要进一步了解这一点,可以更仔细地研究代码,或者向插入符号的维护者Max Kuhn发送电子邮件,询问减少内存占用的方法。

票数 38
EN

Stack Overflow用户

发布于 2011-07-02 11:52:51

加文的回答说得很对。我构建这个函数是为了方便使用,而不是为了速度或效率1

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

其次,您不必保留训练数据(请参阅trainControl()中的returnData参数)。

此外,由于R没有任何真正的共享内存基础设施,因此Gavin对内存中保留的数据副本数量的估计是正确的。基本上,每次重采样都会创建一个列表,并使用lapply()来处理该列表,然后只返回重采样的估计值。另一种方法是顺序地制作数据的一个副本(对于当前的重采样),执行所需的操作,然后对剩余的迭代重复。这里的问题是I/O和无法进行任何并行处理。2

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

杨-通过str(data)了解更多关于数据的信息将是一件好事,这样我们就可以了解维度和其他方面(例如。具有多层次的因素等)。

我希望这能帮上忙

最大值

1我不应该说,当我们可以的时候,我们会不遗余力地去适应尽可能少的模型。“子模型”技巧被用于许多模型,例如pls,gbm,rpart,earth和许多其他模型。此外,当模型具有公式和非公式界面时(例如,lda()earth(),默认为非公式界面。

2每隔一段时间,我就有一种疯狂的冲动,想要重启train()功能。使用foreach可能会绕过其中的一些问题。

票数 32
EN

Stack Overflow用户

发布于 2018-03-05 08:27:28

我认为上面的答案有点过时了。插入符号和caretEnsemble包现在在trainControl 'trim.‘’中包含了一个额外的参数。Trim最初设置为FALSE,但将其更改为TRUE将显著减小模型大小。对于尽可能小的模型尺寸,应将其与returnData=FALSE结合使用。如果您正在使用模型集成,则还应该在贪婪/堆栈集成trainControl中指定这两个参数。

对于我的情况,1.6 to的模型在集成控制中使用这两个参数时缩小到~500mb,并使用贪婪集成控制中的参数进一步缩小到~300mb。

代码语言:javascript
复制
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))
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6543999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档