2015-02-24 5 views
3

Я пытаюсь использовать H2O через R для создания нескольких моделей с использованием подмножеств одного большого массива данных (~ 10 ГБ). Данные - данные за один год, и я пытаюсь построить 51 модель (т. Е. Поезд на 1-й неделе, предсказать на 2-й неделе и т. Д.), Причем каждая неделя составляет около 1,5-2,5 млн строк с 8 переменными.R H2O - Управление памятью

Я сделал это внутри цикла, который, как я знаю, не всегда является лучшим способом в Р. Еще одна проблема, которую я обнаружил, заключалась в том, что объект 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 (~ 64 ГБ RAM + 12 процессоров)) для этого типа процесса? Должен ли я убивать и воссоздавать объект H2O после каждого цикла (это был оригинальный процесс, но чтение данных из файла каждый раз добавляло ~ 10 минут на итерацию)? Есть ли правильный способ сбора мусора или выпуска памяти после каждого цикла?

Любые предложения будут оценены.

+0

Вы можете удалить все, что хотите, по ключу: 'h2o.rm (localH2O," keyDataWhichIWantDelete ")' –

ответ

6

Этот ответ предназначен для оригинального проекта H2O (версии 2.x.y.z).

В исходном проекте H2O пакет H2O R создает много временных объектов H2O в кластере H2O DKV (хранилище распределенных ключей/значений) с префиксом «Last.value».

Это видно как в магазине Вид с веб-интерфейс и по телефону h2o.ls() из R.

Что я рекомендую делать это:

  • в нижней части каждой итерации цикла , используйте h2o.assign(), чтобы сделать глубокую копию всего, что вы хотите сохранить, до известного имени ключа.
  • используйте h2o.rm(), чтобы удалить все, что вы не хотите сохранить, в частности «Last.value "temps
  • вызов gc() явно в R где-то в цикле

Вот функция, которая удаляет для вас объекты Tem. 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) 
    } 
} 

Вот ссылка на тест R в H2O хранилище GitHub, который использует эту технику и может работать неопределенно долго без запуска из памяти:

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

3

Новое предложение от 15.12.2011: обновление до последней стабильной (Tibshirani 3.6.0.8 или новее). Мы полностью переработали как R & H2O обрабатывают внутренние временные переменные, а управление памятью намного более плавное.

Далее: H2O могут удерживаться «живыми» R мертвыми переменными ... поэтому запустите R gc() каждую итерацию цикла.После того, как GC GC удалит мертвые переменные, H2O вернет эту память.

После этого кластер должен удержать только определенные вещи, такие как загруженные наборы данных и модели. Их вам нужно будет удалить примерно так же быстро, как вы их делаете, чтобы избежать накопления больших данных в магазине K/V.

Пожалуйста, дайте нам знать, если у вас есть какие-либо больше проблем, размещая в группу h2o поток Google: https://groups.google.com/forum/#!forum/h2ostream

Клифф

+0

Как насчет Python? – user90772

2

Самый последний ответ на этот вопрос в том, что вы, вероятно, следует использовать только h2o.grid() вместо написания цикла.