H2O R API:从网格搜索中检索最佳模型

8

我正在使用R中的h2o包(版本3.6.0),并构建了一个网格搜索模型。现在,我正在尝试访问在验证集上最小化MSE的模型。在Python的sklearn中,当使用RandomizedSearchCV时,这很容易实现:

## Pseudo code:
grid = RandomizedSearchCV(model, params, n_iter = 5)
grid.fit(X)
best = grid.best_estimator_

很遗憾,在h2o中这并不是那么容易的事情。以下是一个可以复现的示例:
library(h2o)
## assume you got h2o initialized...

X <- as.h2o(iris[1:100,]) # Note: only using top two classes for example 
grid <- h2o.grid(
    algorithm = 'gbm',
    x = names(X[,1:4]),
    y = 'Species',
    training_frame = X,
    hyper_params = list(
        distribution = 'bernoulli',
        ntrees = c(25,50)
    )
)

查看网格可以打印出大量信息,其中包括以下部分:

> grid
ntrees distribution status_ok                                                                 model_ids
 50    bernoulli        OK Grid_GBM_file1742e107fe5ba_csv_10.hex_11_model_R_1456492736353_16_model_1
 25    bernoulli        OK Grid_GBM_file1742e107fe5ba_csv_10.hex_11_model_R_1456492736353_16_model_0

通过一些挖掘,你可以访问每个单独的模型并查看所有可能的指标:

> h2o.getModel(grid@model_ids[[1]])
H2OBinomialModel: gbm
Model ID:  Grid_GBM_file1742e107fe5ba_csv_10.hex_11_model_R_1456492736353_18_model_1 
Model Summary: 
  number_of_trees model_size_in_bytes min_depth max_depth mean_depth min_leaves max_leaves mean_leaves
1              50                4387         1         1    1.00000          2          2     2.00000


H2OBinomialMetrics: gbm
** Reported on training data. **

MSE:  1.056927e-05
R^2:  0.9999577
LogLoss:  0.003256338
AUC:  1
Gini:  1

Confusion Matrix for F1-optimal threshold:
           setosa versicolor    Error    Rate
setosa         50          0 0.000000   =0/50
versicolor      0         50 0.000000   =0/50
Totals         50         50 0.000000  =0/100

Maximum Metrics: Maximum metrics at their respective thresholds
                      metric threshold    value idx
1                     max f1  0.996749 1.000000   0
2                     max f2  0.996749 1.000000   0
3               max f0point5  0.996749 1.000000   0
4               max accuracy  0.996749 1.000000   0
5              max precision  0.996749 1.000000   0
6           max absolute_MCC  0.996749 1.000000   0
7 max min_per_class_accuracy  0.996749 1.000000   0

经过大量的挖掘,你终于可以得到这个:

> h2o.getModel(grid@model_ids[[1]])@model$training_metrics@metrics$MSE
[1] 1.056927e-05

这似乎是很多复杂的工作,只是为了得到一个应该作为模型选择顶层指标的度量。在我的情况下,我有一个包含数百个模型的网格,而我目前的临时解决方案似乎不太符合R的风格。
model_select_ <- function(grid) {
  model_ids <- grid@model_ids
  min = Inf
  best_model = NULL

  for(model_id in model_ids) {
    model <- h2o.getModel(model_id)
    mse <- model@model$training_metrics@metrics$MSE
    if(mse < min) {
      min <- mse
      best_model <- model
    }
  }

  best_model
}

这似乎对于机器学习实践如此核心的事情来说有些过度,而且让我感到奇怪的是,h2o没有一种更加“干净”的方法来提取最佳模型,或者至少是模型指标。

我是否遗漏了什么?难道没有选择最佳模型的“开箱即用”方法吗?

3个回答

4
是的,有一种简单的方法可以提取H2O网格搜索的“顶级”模型。还有一些实用函数可以提取您一直在尝试访问的所有模型指标(例如h2o.mse)。如何执行这些操作的示例可以在h2o-r/demosh2o-py/demos子文件夹中找到,这些文件夹位于h2o-3 GitHub存储库中。
由于您正在使用R,因此这里提供了一个相关代码示例,其中包括一个网格搜索和排序结果。您还可以在h2o.getGrid函数的R文档中找到如何访问此信息的方法。
按验证AUC排序,打印所有模型的AUC:
auc_table <- h2o.getGrid(grid_id = "eeg_demo_gbm_grid", sort_by = "auc", decreasing = TRUE)
print(auc_table)

这是一个输出示例:
H2O Grid Details
================

Grid ID: eeg_demo_gbm_grid 
Used hyper parameters: 
  -  ntrees 
  -  max_depth 
  -  learn_rate 
Number of models: 18 
Number of failed models: 0 

Hyper-Parameter Search Summary: ordered by decreasing auc
   ntrees max_depth learn_rate                  model_ids               auc
1     100         5        0.2 eeg_demo_gbm_grid_model_17 0.967771493797284
2      50         5        0.2 eeg_demo_gbm_grid_model_16 0.949609591795923
3     100         5        0.1  eeg_demo_gbm_grid_model_8  0.94941792664595
4      50         5        0.1  eeg_demo_gbm_grid_model_7 0.922075196552274
5     100         3        0.2 eeg_demo_gbm_grid_model_14 0.913785959685157
6      50         3        0.2 eeg_demo_gbm_grid_model_13 0.887706691652792
7     100         3        0.1  eeg_demo_gbm_grid_model_5 0.884064379717198
8       5         5        0.2 eeg_demo_gbm_grid_model_15 0.851187402678818
9      50         3        0.1  eeg_demo_gbm_grid_model_4 0.848921799270639
10      5         5        0.1  eeg_demo_gbm_grid_model_6 0.825662907513139
11    100         2        0.2 eeg_demo_gbm_grid_model_11 0.812030639460551
12     50         2        0.2 eeg_demo_gbm_grid_model_10 0.785379521713437
13    100         2        0.1  eeg_demo_gbm_grid_model_2  0.78299280750123
14      5         3        0.2 eeg_demo_gbm_grid_model_12 0.774673686150002
15     50         2        0.1  eeg_demo_gbm_grid_model_1 0.754834657912535
16      5         3        0.1  eeg_demo_gbm_grid_model_3 0.749285131682721
17      5         2        0.2  eeg_demo_gbm_grid_model_9 0.692702793188135
18      5         2        0.1  eeg_demo_gbm_grid_model_0 0.676144542037133

表格中的顶行包含具有最佳AUC的模型,因此我们可以在下面获取该模型并提取验证AUC:
best_model <- h2o.getModel(auc_table@model_ids[[1]])
h2o.auc(best_model, valid = TRUE)

为了让h2o.getGrid函数能够按验证集上的指标进行排序,您需要实际传递一个validation_frameh2o.grid函数。在您上面的示例中,您没有传递validation_frame,因此无法在验证集上评估网格中的模型。

太好了,Erin。在可重复的示例中,我没有传递验证集,但在我的实际代码中我做了。谢谢! - TayTay
H2O.grid() 实际上不使用 validation_frame,它只使用 training_frame。它会忽略你传入的 validation_frame 用于评分目的。由此得出的模型自然会过拟合,因此是无用的。这个问题已经解决了吗?你可以查看搜索中获胜的模型,并直接查看其评分进展,例如训练_auc和验证_auc进行比较。如果你在那里查看,就会看到这个问题。 - Geoffrey Anderson
@GeoffreyAnderson 我们已经开了一个工单来跟踪您对 validation_frameh2o.grid 的观察和问题,并希望尽快解决。您可以在这里跟踪进展:https://0xdata.atlassian.net/browse/PUBDEV-4035 - Erin LeDell
1
@Erin L. 感谢您的关注。我想提醒一下,根据我所做的持续研究,实际上问题的源头并不是网格本身,而是模型训练函数(例如h2o.gbm(),h2o.randomForest())。如果我犯了用户错误,我会密切关注并进行修正;如果是软件错误,我将尽力找到解决方法。 - Geoffrey Anderson

3
这似乎仅适用于最新版本的h2o,对于3.8.2.3版本,您会收到一个Java异常,指出“auc”是一种无效的度量标准。 以下操作失败:
library(h2o)
library(jsonlite)
h2o.init()
iris.hex <- as.h2o(iris)
h2o.grid("gbm", grid_id = "gbm_grid_id", x = c(1:4), y = 5,
     training_frame = iris.hex, hyper_params = list(ntrees = c(1,2,3)))
grid <- h2o.getGrid("gbm_grid_id", sort_by = "auc", decreasing = T)

然而,将“auc”替换为“logloss”,并将“decrease=F”,那么就可以了。

Iris是一个多类问题,这就是为什么在上面的例子中不支持AUC的原因。错误消息准确地打印了适用于多类的指标:sort_by指定的参数无效。必须是以下之一:[r2、mean_per_class_accuracy、max_per_class_error、err、total_rows、rmse、accuracy、err_count、logloss、mse、mean_per_class_error] - Erin LeDell

-2

不幸的是,H2O网格功能在同时传递训练框架和验证框架时使用的是training_frame而不是validation_frame。因此,获胜模型非常过拟合且无用。编辑:好吧,这里需要更正,像这样使训练偏差非常低实际上是有用的,可以用于学习曲线分析和偏差与方差分析。但是要明确的是,我还需要能够再次运行并获取一个验证数据集,以用作最终模型拟合和选择的搜索标准。

例如,这里是一个GBM网格函数的获胜模型,其中传入了validation_frame,并且AUC是搜索指标。您可以看到,验证_auc从0.5开始,并在获胜模型的最终评分历史记录中恶化至0.44:

Scoring History: 
            timestamp          duration number_of_trees training_rmse
1 2017-02-06 10:09:19  6 min 13.153 sec               0       0.70436
2 2017-02-06 10:09:23  6 min 16.863 sec             100       0.70392
3 2017-02-06 10:09:27  6 min 20.950 sec             200       0.70343
4 2017-02-06 10:09:31  6 min 24.806 sec             300       0.70289
5 2017-02-06 10:09:35  6 min 29.244 sec             400       0.70232
6 2017-02-06 10:09:39  6 min 33.069 sec             500       0.70171
7 2017-02-06 10:09:43  6 min 37.243 sec             600       0.70107
  training_logloss training_auc training_lift training_classification_error
1          2.77317      0.50000       1.00000                       0.49997
2          2.69896      0.99980      99.42857                       0.00026
3          2.62768      0.99980      99.42857                       0.00020
4          2.55902      0.99982      99.42857                       0.00020
5          2.49675      0.99993      99.42857                       0.00020
6          2.43712      0.99994      99.42857                       0.00020
7          2.38071      0.99994      99.42857                       0.00013
  validation_rmse validation_logloss validation_auc validation_lift
1         0.06921            0.03058        0.50000         1.00000
2         0.06921            0.03068        0.45944         9.03557
3         0.06922            0.03085        0.46685         9.03557
4         0.06922            0.03107        0.46817         9.03557
5         0.06923            0.03133        0.45656         9.03557
6         0.06924            0.03163        0.44947         9.03557
7         0.06924            0.03192        0.44400         9.03557
  validation_classification_error
1                         0.99519
2                         0.00437
3                         0.00656
4                         0.00656
5                         0.00700
6                         0.00962
7                         0.00962

@GeoffreyAnderson 我们不需要在H2O中编写一个特殊的函数来获取软件包版本;这就是R中packageVersion()函数的作用。只需键入:packageVersion("h2o")h2o.init()即可查看版本号。 - Erin LeDell
@Erin L. H2O 集群版本:3.10.1.1 自 h2o.init() - Geoffrey Anderson Feb 7 - Geoffrey Anderson
@Darren Cook 按照度量指标对模型进行排序需要尊重验证框架来找到最佳模型。该文章的标题是 H2O R API:从网格搜索中检索最佳模型。 - Geoffrey Anderson
@Darren Cook 关于“开始一个新问题,并提供完全可重现的示例。”请参见h2o.ai论坛。如果您想要完全可重现的示例,那么您必须用比在stackexchange上简单的负投票更多的报酬来支付我。 - Geoffrey Anderson
@GeoffreyAnderson 对于你在 community.h2o.ai 上的问题,我指的是一个单一模型,但你在这里发布的问题是关于网格搜索的,这种情况下,你可以明确选择最佳 AUC。希望这能澄清事情。以下是从网格搜索中选择最佳 auc 的示例 https://github.com/h2oai/h2o-tutorials/blob/master/h2o-open-tour-2016/chicago/grid-search-model-selection.R#L160 - Lauren
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接