【问题标题】:h2o in R: model calculation hangsR中的h2o:模型计算挂起
【发布时间】:2020-05-18 08:34:38
【问题描述】:

我无法弄清楚为什么我的随机森林网格搜索会挂起。我尝试了 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. 未在 init 中设置 nthreads:无效。
  2. 将 nthreads 设置为 4:无效。
  3. 设置较低的内存(我有 16 GB):没有效果。
  4. 在网格搜索中添加并行度 = 0:无效
  5. 没有使用 h2o.removeAll():没有效果
  6. 最后总是使用 h2o.shutdown(prompt = FALSE):无效
  7. 使用了不同版本的 JDK、R 和 h2o。 (现在使用最新的)

问题是网格搜索进度停止在 25% 左右,有时甚至更少。

有什么帮助是将代码切换到 GBM 而不是 RF, 但它有时也会挂在那里(我需要射频!)。 还有助于将模型数量从 5000 个减少到 500 个,但仅限于 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 GB RAM 并将 max_mem_size 分别设置为 18 和 22 GB:效果 = 停止在大约 65% 和 80% 而不是 25%。有趣的是进度条越来越慢,直到完全停止。然后发生类似硬重置的事情,因为我使用了不同的键盘布局(Win10)并且设置为默认值...... 注意:500 GBM 或 NN 使用相同的数据集运行良好。 7. 模型数量减少到 300:没有效果。

所以,我的结论是这绝对是内存问题,但我无法真正监控它。任务管理器中的 RAM 不是 100%,而是分配的 max_mem_size。 非常感谢任何可以帮助我进一步查明问题的帮助 - 谢谢大家!

【问题讨论】:

  • 您的资源似乎用完了。你试过 AWS / Azure 集群吗?
  • 谢谢。不,我没有尝试集群。我不在乎我的机器上是否需要 1-2 天,但它不应该挂起......而且限制到 1 个 CPU 也无济于事,所以这可能(?)不是原因。
  • 您可能想直接在他们的h2o gitter 流上联系 h2o 并链接到这个 SO 问题。但他们需要知道您的数据集的大小。

标签: r random-forest h2o freeze


【解决方案1】:

挂起的原因很可能是内存不足。您要么需要使用更少的内存,要么在具有更多内存的系统上运行您的作业。

这里有许多因素在起作用,除非您了解底层资源使用情况,否则如何调试它们并不一定很明显。

以下是关于如何监控内存使用、如何减少内存使用以及如何让系统拥有更多内存的建议的三个部分。


以下是一些内存监控建议:

  1. 监控您的物理内存使用情况。在 Mac 或 Linux 上使用像 top 这样的程序来做到这一点。需要查看的一个重要数字是 RSS(驻留集大小),它表示主机上正在使用的实际物理内存量。

  2. 监控任何交换。确保您的系统没有交换到磁盘。当您尝试使用的虚拟内存(一次)多于主机上的物理内存时,就会发生交换。在 linux 上,vmstat 命令非常适合显示交换。

  3. 使用 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 打开 java GC 日志记录,您将获得更多日志输出,这将显示 java 本身是否因内存不足而陷入困境。这很有可能。这是一个示例,说明如何在从 R 内部启动 H2O-3 时传递 jvm_custom_args 标志:

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 文件现在将包含 GC 日志输出,如下所示:

...
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]

“分配失败”消息看起来很吓人,但实际上是完全正常的。当您看到需要大量“实际秒数”的背靠背 Full GC 周期时,就该担心了。


以下是使用更少内存的一些建议:

  • 将数据拆分一次并将其保存到磁盘,然后通过两个单独的 as.h2o 或 h2o.importFile 步骤将其读回新的新 H2O-3 集群中。

    在您的示例中,您正在执行 splitFrame。这会在内存中复制您的数据。

  • 首选 h2o.importFile 而不是 as.h2o。

    我不知道这对您的情况有多大影响,但 h2o.importFile 是针对大数据设计和测试的,而 as.h2o 不是。

  • 使用更少的数据。

    你没有说你的数据的形状,但如果 automl 或网格搜索适用于 GBM 而不是 DRF,那肯定是内存不足。这两种算法在计算方面几乎完全相同,但 DRF 模型往往更大,因为 DRF 具有更高的树深度,这意味着它需要更多的内存来存储模型。

  • 使用 nthreads 选项减少并发工作线程的数量。

    您运行的活动并发线程越多,您需要的内存就越多,因为每个线程都需要一些工作内存。例如,您可以尝试将 nthreads 设置为您拥有的 CPU 内核数的一半。

  • 不要使用 xgboost。

    Xgboost 在使用内存的方式上很特别,因为它会在 Java 堆之外制作数据的第二份副本。这意味着当您使用 xgboost 时,您不想将整个主机的内存分配给 java max_mem_size(或 Xmx),否则您可能会遇到问题(尤其是交换)。

  • 不要使用 DRF。

    DRF 树更深,因此生成的模型更大。或者,构建(并保留在内存中)更少的 DRF 模型、更浅的 DRF 模型或具有更少树的模型。


获得更多内存的最佳快速建议是在云中运行。您不一定需要多节点设置。如果可以充分解决问题,则单个大型节点更易于使用。在你的情况下,它可能会。鉴于您在上面所说的(即您现在有 16 GB,如果您不使用 DRF,它将完成),我将首先使用 EC2 中的 m5.4xlarge 实例,该实例具有 64 GB 的 RAM,成本低于 1 美元/hr 并给它一个 48G 的 max_mem_size。

【讨论】:

  • 非常感谢您的详细回答。我会在接下来的几天里尝试这些建议。但是,数据集非常小(263 行 x 25 列)并且我设置了最大内存,所以我不确定会出现多少内存?但让我们拭目以待,看看测试会带来什么。
  • 我会先尝试不同/更大的主机,以排除您自己计算机上的一些未知问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-18
  • 2017-10-20
  • 2015-07-03
  • 2018-08-05
  • 2018-01-28
  • 2020-11-28
相关资源
最近更新 更多