2015-02-24 68 views
3

我试图通过R使用H2O构建多个模型,使用一个大型数据集(〜10GB)的子集。这些数据是价值一年的数据,我试图建立51个模型(即,在第一周训练,在第二周预测等),每周有大约1.5-2.5百万行,其中有8个变量。R H2O - 内存管理

我在一个循环里面做了这个,我知道并不总是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分钟)?在每个循环之后有没有合适的方法来垃圾收集或释放内存?

任何建议,将不胜感激。

+0

你可以通过键删除所有你想要的东西:'h2o.rm(localH2O,“keyDataWhichIWantDelete”)' – 2015-02-27 16:43:45

回答

6

此答案适用于原始H2O项目(版本2.x.y.z)。

在最初的H2O项目中,H2O R软件包在H2O集群DKV(分布式键/值存储)中创建了大量临时H2O对象,并带有“Last.value”前缀。

这些都可见在商店查看从Web UI,并从R.

调用h2o.ls()

我的建议做的是:

  • 在每次循环的底部,使用h2o.assign()做任何你想保存到已知密钥名称的深层副本
  • 使用h2o.rm()删除任何你不想保留的东西,特别是“Last.value “temps
  • 在循环中某处显式地调用gc()

这是一个为您删除Last.value临时对象的函数。在H 2 O中的连接对象作为参数传递:

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

3

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

下一步:H2O temps可以通过R死变量保持“有效”......所以在每次循环迭代中运行R gc()。一旦R的GC删除死变量,H2O将回收该内存。

之后,您的群集应该只保留专门命名的东西,如加载的数据集和模型。这些您需要大致尽可能快地删除,以避免在K/V存储中累积大量数据。

请让我们知道,如果你通过发布到谷歌组H2O中有任何更多的问题: ​​

+0

Python怎么样? – user90772 2017-07-24 13:34:06

2

最当前的这个问题的答案是,你应该只使用h2o.grid()功能而不是写循环。