h2o в R: зависает расчет модели - PullRequest
0 голосов
/ 02 февраля 2020

Я не могу понять, почему мой случайный поиск в лесной сетке зависает. Я попробовал много вещей, предложенных на Stackoverflow, но ничего не работает. Прежде всего, вот мой код:

library(data.table)
library(h2o)
library(dplyr)

# Initialise H2O
localH2O = h2o.init(nthreads = -1, min_mem_size = "9240M", max_mem_size = "11336M")

h2o.removeAll()

# Specify some dirs, inputs etc. (not shown)
laufnummer  <- 10
set.seed(laufnummer)
maxmodels   <- 500

# Convert to h2o
h2o_input <- as.h2o(input)

# Split: 80% = train; 0 = valid; rest = 20% = test
splits <- h2o.splitFrame(h2o_input, c(0.80,0))
train  <- h2o.assign(splits[[1]], "train") # 80%
test   <- h2o.assign(splits[[3]], "test")  # 10%

Установить параметры:

# Select range of ntrees
min_ntrees      <- 10
max_ntrees      <- 2500
stepsize_ntrees <- 20
ntrees_opts <- seq(min_ntrees,max_ntrees, stepsize_ntrees)

# Select range of tries
min_mtries      <- 1
max_mtries      <- 12
stepsize_mtries <- 1
mtries_opts <- seq(min_mtries,max_mtries, stepsize_mtries)

# Cross-validation number of folds
nfolds <- 5

hyper_params_dl = list(ntrees = ntrees_opts,
                       mtries = mtries_opts)
search_criteria_dl = list(
  strategy = "RandomDiscrete",
  max_models = maxmodels)

Наконец, поиск по случайной сетке (это где он висит, почти всегда на 25%)

rf_grid <- h2o.grid(seed = laufnummer,
                    algorithm = "randomForest", 
                    grid_id = "dlgrid",
                    x = predictors, 
                    y = response, 
                    training_frame = train,
                    nfolds = nfolds,
                    keep_cross_validation_predictions = TRUE,
                    model_id = "rf_grid",
                    hyper_params = hyper_params_dl,
                    search_criteria = search_criteria_dl
)

Вот что я уже пробовал:

  1. Не задал nthreads в init: нет эффекта.
  2. Установите nthreads на 4: нет эффекта.
  3. Установить нижнюю память (у меня 16 ГБ): без эффекта.
  4. Добавлен параллелизм = 0 при поиске по сетке: без эффекта
  5. Не использовать h2o.removeAll (): без эффекта
  6. Всегда использовал h2o.shutdown (prompt = FALSE) в конце: без эффекта
  7. Использовал другую версию JDK, R и h2o. (теперь используются самые последние для всех)

Проблема в том, что прогресс поиска по сетке останавливается на уровне около 25%, иногда меньше.

Что помогает, так это переключение кода на GBM вместо RF, но иногда там тоже висит (а мне нужен RF!). Также помогло уменьшить количество моделей до 500 вместо 5000, но только для NN и GBM, а не RF.

После нескольких недель попыток я был бы очень признателен за любую помощь !! Спасибо!

ОБНОВЛЕНИЕ: Спасибо за ваши предложения, вот что я попробовал: 1. Импортировал уже разделенные файлы с помощью h2o.importfile (): безрезультатно. Не удивительно, потому что это такой маленький набор данных и загрузка занимает несколько секунд. 2. Установите для nthreads значение 1: без эффекта. 3. Не используйте xgboost: я не знаю, что я его использую. 4. Не используйте RF: невозможно, потому что я пытаюсь сравнить алгоритмы машинного обучения. 5. h2o.init (jvm_custom_args = c ("- XX: + PrintGCDetails", "-XX: + PrintGCTimeStamps")): не работает, поскольку h2o не запускается с добавлением этого параметра. 6. Купили дополнительные 8 ГБ ОЗУ и установите max_mem_size на 18 и 22 ГБ соответственно: эффект = останавливается на уровне около 65% и 80% вместо 25%. Что интересно, индикатор выполнения становится все медленнее и медленнее, пока не остановится полностью. Затем происходит нечто вроде аппаратного сброса, поскольку я использую другую раскладку клавиатуры (Win10), и для нее установлено значение по умолчанию ... Примечание: 500 ГБ или NN работают нормально с тем же набором данных. 7. Уменьшено количество моделей до 300: безрезультатно.

Итак, я пришел к выводу, что это определенно проблема с памятью, но я не могу реально контролировать ее. Объем оперативной памяти в диспетчере задач не на 100%, а на выделенном значении max_mem_size. Любая помощь, которая может помочь мне точно определить проблему, очень ценится - спасибо, ребята !!

1 Ответ

1 голос
/ 02 февраля 2020

Скорее всего, причина зависания - нехватка памяти. Вам нужно либо использовать меньше памяти, либо запустить свою работу в системе с большим объемом памяти.

Здесь работает ряд факторов, и не всегда очевидно, как их отлаживать, если вы не знаете о базовое использование ресурсов.

Ниже приведены три раздела с предложениями о том, как отслеживать использование памяти, как уменьшить использование памяти и как получить систему с большим объемом памяти.


Вот некоторые из них Рекомендации по мониторингу памяти:

  1. Контролируйте использование физической памяти. Сделайте это с помощью программы типа top на Ma c или на Linux. Важное число, на которое нужно обратить внимание, - это RSS (размер резидентного набора), который представляет фактический объем физической памяти, используемой на хосте.

  2. Отслеживание любой перестановки. Убедитесь, что ваша система не загружается на диск. Обмен происходит, когда вы пытаетесь использовать больше виртуальной памяти (за один раз), чем у вас есть физическая память на вашем хосте. На linux команда vmstat подходит для показа подкачки.

  3. Включение java G C ведение журнала с помощью -XX: + PrintGCDetails -XX: + PrintGCTimeStamps you получит больше записей журнала, которые покажут вам, если java просто отключается из-за нехватки памяти. Это очень вероятно. Вот пример того, как это сделать, передав флаг jvm_custom_args при запуске H2O-3 изнутри R:

h2o.init(jvm_custom_args = c("-XX:+PrintGCDetails", "-XX:+PrintGCTimeStamps"))

Вы увидите сообщение, показывающее:

H2O is not running yet, starting it now...

Note:  In case of errors look at the following log files:
    /var/folders/vv/pkzvhy8x5hsfbsjg75_6q4ch0000gn/T//RtmpUsdTRQ/h2o_tomk_started_from_r.out
    /var/folders/vv/pkzvhy8x5hsfbsjg75_6q4ch0000gn/T//RtmpUsdTRQ/h2o_tomk_started_from_r.err

Файл .out выше теперь будет содержать вывод журнала G C, как вы можете видеть ниже:

...
02-02 08:30:29.785 127.0.0.1:54321       21814  main      INFO: Open H2O Flow in your web browser: http://127.0.0.1:54321
02-02 08:30:29.785 127.0.0.1:54321       21814  main      INFO:
02-02 08:30:29.886 127.0.0.1:54321       21814  #84503-22 INFO: GET /, parms: {}
02-02 08:30:29.946 127.0.0.1:54321       21814  #84503-20 INFO: GET /, parms: {}
02-02 08:30:29.959 127.0.0.1:54321       21814  #84503-21 INFO: GET /, parms: {}
02-02 08:30:29.980 127.0.0.1:54321       21814  #84503-22 INFO: GET /3/Capabilities/API, parms: {}
02-02 08:30:29.981 127.0.0.1:54321       21814  #84503-22 INFO: Locking cloud to new members, because water.api.schemas3.CapabilitiesV3
02-02 08:30:30.005 127.0.0.1:54321       21814  #84503-25 INFO: GET /3/InitID, parms: {}
14.334: [GC (Allocation Failure) [PSYoungGen: 94891K->3020K(153088K)] 109101K->56300K(299008K), 0.0193290 secs] [Times: user=0.22 sys=0.01, real=0.02 secs]
14.371: [GC (Allocation Failure) [PSYoungGen: 120914K->3084K(153088K)] 174194K->173560K(338432K), 0.0256458 secs] [Times: user=0.29 sys=0.04, real=0.03 secs]
14.396: [Full GC (Ergonomics) [PSYoungGen: 3084K->0K(153088K)] [ParOldGen: 170475K->163650K(435200K)] 173560K->163650K(588288K), [Metaspace: 22282K->22282K(1069056K)], 0.0484233 secs] [Times: user=0.47 sys=0.00, real=0.05 secs]
14.452: [GC (Allocation Failure) [PSYoungGen: 118503K->160K(281088K)] 282153K->280997K(716288K), 0.0273738 secs] [Times: user=0.30 sys=0.05, real=0.02 secs]
14.479: [Full GC (Ergonomics) [PSYoungGen: 160K->0K(281088K)] [ParOldGen: 280837K->280838K(609792K)] 280997K->280838K(890880K), [Metaspace: 22282K->22282K(1069056K)], 0.0160751 secs] [Times: user=0.09 sys=0.00, real=0.02 secs]
14.516: [GC (Allocation Failure) [PSYoungGen: 235456K->160K(281088K)] 516294K->515373K(890880K), 0.0320757 secs] [Times: user=0.30 sys=0.10, real=0.03 secs]
14.548: [Full GC (Ergonomics) [PSYoungGen: 160K->0K(281088K)] [ParOldGen: 515213K->515213K(969216K)] 515373K->515213K(1250304K), [Metaspace: 22282K->22282K(1069056K)], 0.0171208 secs] [Times: user=0.09 sys=0.00, real=0.02 secs]

Сообщения «Ошибка выделения» выглядят страшно, но на самом деле полностью нормальный. Время беспокоиться, когда вы видите параллельные полные циклы G C, которые занимают большое количество «реальных секунд».


Вот несколько советов по использованию меньшего количества памяти:

  • Разделите данные один раз и сохраните их на диск, а затем прочитайте их обратно в новом кластере fre sh H2O-3 в два отдельных этапа as.h2o или h2o.importFile.

    В вашем примере вы делаете splitFrame. Это делает копию ваших данных в памяти.

  • Предпочитаю h2o.importFile as.h2o.

    Я не знаю, какая разница на самом деле в вашем случае, но h2o.importFile был разработан и протестирован для больших данных, а as.h2o - нет.

  • Использовать меньше данных.

    Вы не сказали что-нибудь о форме ваших данных, но если автоматический поиск или поиск по сетке работает с GBM, но не с DRF, это определенно указывает на нехватку памяти. Эти два алгоритма выполняют почти одинаковые вычисления, но модели DRF имеют тенденцию быть больше, поскольку DRF имеет большую глубину дерева, что означает, что для хранения моделей требуется больше памяти.

  • Используйте параметр nthreads, чтобы уменьшить количество одновременных рабочих потоков.

    Чем больше активных параллельных потоков у вас работает, тем больше памяти вам нужно, потому что каждому потоку нужна некоторая рабочая память. Вы можете попробовать установить nthreads равным половине количества ядер вашего процессора, например.

  • Не используйте xgboost.

    Xgboost особенный в том смысле, что он использует память, потому что создает вторую копию данных вне кучи java. Это означает, что когда вы используете xgboost, вы не хотите давать java max_mem_size (или Xmx) всей памяти вашего хоста, или вы можете столкнуться с проблемами (особенно с подкачкой).

  • Не используйте DRF.

    Деревья DRF глубже, и, следовательно, производимые модели больше. Альтернативно, создайте (и сохраните в памяти) меньше моделей DRF, более мелких моделей DRF или моделей с меньшим количеством деревьев.


Лучшее быстрое предложение для получения большего объема памяти - запустить в облаке. Вам не обязательно нужна установка с несколькими узлами. С одним большим узлом легче работать, если это адекватно решит проблему. В вашем случае это, вероятно, будет. Учитывая то, что вы сказали выше (то есть, у вас есть 16 ГБ сейчас, и оно заканчивается, если вы не используете DRF), я бы начал с использования экземпляра m5.4xlarge в EC2, который имеет 64 ГБ ОЗУ и стоит менее $ 1. / ч и дайте ему максимальный размер 48G.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...