H2O R api:从网格搜索中检索最优模型
H2O R api: retrieving optimal model from grid search
我在 R 中使用 h2o
包 (v 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
打印了大量信息,包括以下部分:
> 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
为了得出一个应该是模型选择的顶级指标,这似乎是一项艰巨的工作。在我的情况下,我有一个包含数百个模型的网格,而我当前的 hacky 解决方案似乎不太 "R-esque":
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 没有 "cleaner" 提取最佳模型的方法,或者至少模型指标。
我错过了什么吗?没有"out of the box"选择最佳模型的方法吗?
是的,有一种简单的方法可以提取 H2O 网格搜索的 "top" 模型。还有实用函数可以提取您一直试图访问的所有模型指标(例如 h2o.mse
)。可以在 h2o-r/demos and h2o-py/demos subfolders on the h2o-3 GitHub 存储库中找到有关如何执行这些操作的示例。
由于您使用的是 R,这里有一个 relevant code example,其中包括一个网格搜索,结果已排序。您还可以在 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
table 中的第一行包含具有最佳 AUC 的模型,因此我们可以在下面获取该模型并提取验证 AUC:
best_model <- h2o.getModel(auc_table@model_ids[[1]])
h2o.auc(best_model, valid = TRUE)
为了使 h2o.getGrid
函数能够按验证集上的度量进行排序,您需要实际将 h2o.grid
函数传递给 validation_frame
。在上面的示例中,您没有传递 validation_frame,因此您无法在验证集上评估网格中的模型。
这似乎只对最新版本的 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',减少=F就可以了
不幸的是,当你将它们都传入时,H2O 网格函数使用 training_frame 而不是 validation_frame。因此,获胜模型极度过度拟合且无用。编辑:好吧,这里更正,为了学习曲线分析和偏差与方差分析的目的,像这样让训练偏差非常低实际上很有用。但需要明确的是,我还需要能够再次 运行 并获得一个验证数据集,用作最终模型拟合和选择的搜索标准。
例如,这是一个来自 GBM 上的网格函数的获胜模型,其中传入了 validation_frame,AUC 是搜索指标。你可以看到 validation_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
我在 R 中使用 h2o
包 (v 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
打印了大量信息,包括以下部分:
> 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
为了得出一个应该是模型选择的顶级指标,这似乎是一项艰巨的工作。在我的情况下,我有一个包含数百个模型的网格,而我当前的 hacky 解决方案似乎不太 "R-esque":
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 没有 "cleaner" 提取最佳模型的方法,或者至少模型指标。
我错过了什么吗?没有"out of the box"选择最佳模型的方法吗?
是的,有一种简单的方法可以提取 H2O 网格搜索的 "top" 模型。还有实用函数可以提取您一直试图访问的所有模型指标(例如 h2o.mse
)。可以在 h2o-r/demos and h2o-py/demos subfolders on the h2o-3 GitHub 存储库中找到有关如何执行这些操作的示例。
由于您使用的是 R,这里有一个 relevant code example,其中包括一个网格搜索,结果已排序。您还可以在 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
table 中的第一行包含具有最佳 AUC 的模型,因此我们可以在下面获取该模型并提取验证 AUC:
best_model <- h2o.getModel(auc_table@model_ids[[1]])
h2o.auc(best_model, valid = TRUE)
为了使 h2o.getGrid
函数能够按验证集上的度量进行排序,您需要实际将 h2o.grid
函数传递给 validation_frame
。在上面的示例中,您没有传递 validation_frame,因此您无法在验证集上评估网格中的模型。
这似乎只对最新版本的 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',减少=F就可以了
不幸的是,当你将它们都传入时,H2O 网格函数使用 training_frame 而不是 validation_frame。因此,获胜模型极度过度拟合且无用。编辑:好吧,这里更正,为了学习曲线分析和偏差与方差分析的目的,像这样让训练偏差非常低实际上很有用。但需要明确的是,我还需要能够再次 运行 并获得一个验证数据集,用作最终模型拟合和选择的搜索标准。
例如,这是一个来自 GBM 上的网格函数的获胜模型,其中传入了 validation_frame,AUC 是搜索指标。你可以看到 validation_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