2015-02-24 35 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()功能而不是寫循環。