R H2O – 内存管理

我试图通过R使用H2O来使用一个大数据集(~10GB)的子集构建多个模型。 数据是一年的数据,我正在尝试建立51个模型(即第1周训练,第2周预测等),每周约有1.5-250万行,有8个变量。

我已经在循环中完成了这个,我知道这并不总是R中最好的方法。我发现的另一个问题是H2O实体会积累先前的对象,所以我创建了一个函数来删除除主数据之外的所有它们组。

h2o.clean <- function(clust = localH2O, verbose = TRUE, vte = c()){ # Find all objects on server keysToKill <- h2o.ls(clust)$Key # Remove items to be excluded, if any keysToKill <- setdiff(keysToKill, vte) # Loop thru and remove items to be removed for(i in keysToKill){ h2o.rm(object = clust, keys = i) if(verbose == TRUE){ print(i);flush.console() } } # Print remaining objects in cluster. h2o.ls(clust) } 

该脚本运行良好一段时间然后崩溃 – 通常抱怨内存不足和交换到磁盘。

这里有一些伪代码来描述这个过程

 # load h2o library library(h2o) # create h2o entity localH2O = h2o.init(nthreads = 4, max_mem_size = "6g") # load data dat1.hex = h2o.importFile(localH2O, inFile, key = "dat1.hex") # Start loop for(i in 1:51){ # create test/train hex objects train1.hex <- dat1.hex[dat1.hex$week_num == i,] test1.hex <- dat1.hex[dat1.hex$week_num == i + 1,] # train gbm dat1.gbm <- h2o.gbm(y = 'click_target2', x = xVars, data = train1.hex , nfolds = 3 , importance = T , distribution = 'bernoulli' , n.trees = 100 , interaction.depth = 10, , shrinkage = 0.01 ) # calculate out of sample performance test2.hex <- cbind.H2OParsedData(test1.hex,h2o.predict(dat1.gbm, test1.hex)) colnames(test2.hex) <- names(head(test2.hex)) gbmAuc <- h2o.performance(test2.hex$X1, test2.hex$click_target2)@model$auc # clean h2o entity h2o.clean(clust = localH2O, verbose = F, vte = c('dat1.hex')) } # end loop 

我的问题是,如果有的话,在一个独立的实体中管理数据和内存的正确方法(这不是在hadoop或集群上运行 – 只是一个大型的EC2实例(~64gb RAM + 12个CPU))过程? 我应该在每次循环后杀死并重新创建H2O实体(这是原始过程,但每次从文件读取数据每次迭代增加约10分钟)? 在每次循环后有没有正确的方法来垃圾收集或释放内存?

任何建议,将不胜感激。

这个答案适用于原始的H2O项目(发布2.xyz)。

在最初的H2O项目中,H2O R包在H2O集群DKV(分布式键/值存储)中创建了许多临时H2O对象,其前缀为“Last.value”。

这些在Web UI的Store View和从R调用h2o.ls()都可见。

我建议做的是:

  • 在每个循环迭代的底部,使用h2o.assign()对要保存到已知键名的任何内容进行深层复制
  • 使用h2o.rm()删除任何你不想保留的东西,特别是“Last.value”的临时值
  • 在R中的某个地方显式调用gc()

这是一个为您删除Last.value临时对象的函数。 传入H2O连接对象作为参数:

 removeLastValues <- function(conn) { df <- h2o.ls(conn) keys_to_remove <- grep("^Last\\.value\\.", perl=TRUE, x=df$Key, value=TRUE) unique_keys_to_remove = unique(keys_to_remove) if (length(unique_keys_to_remove) > 0) { h2o.rm(conn, unique_keys_to_remove) } } 

以下是H2O github存储库中R测试的链接,该存储库使用此技术并且可以无限期运行而不会耗尽内存:

https://github.com/h2oai/h2o/blob/master/R/tests/testdir_misc/runit_looping_slice_quantile.R

截至2015年12月15日的新建议:更新到最新的稳定版(Tibshirani 3.6.0.8或更高版本)。 我们已经完全重写了R&H2O如何处理内部临时变量,并且内存管理更加顺畅。

Next:H2O temps可以通过R死变量保持“活着”…所以每次循环迭代运行一个R gc()。 一旦R的GC移除死变量,H2O将回收该内存。

之后,您的群集应该只保留特定命名的内容,例如已加载的数据集和模型。 这些您需要大致删除它们,以避免在K / V存储中累积大数据。

如果您有任何问题,请通过发布到Google论坛h2o流告诉我们: https ://groups.google.com/forum/#!forum / h2ostream

悬崖

这个问题的最新答案是你应该只使用h2o.grid()函数而不是编写循环。