This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code. To execute a code chunk, click Run (play) button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

If you’re viewing the Rmd file (code only), but you’d like to see the code and output rendered as an HTML document, an online HTML of this file is available here.

Start H2O

Load the h2o R library and initialize a local H2O cluster.

library(h2o)
h2o.init()
h2o.no_progress()  # Turn off progress bars for notebook readability

Load Data

For the AutoML binary classification demo, we use a subset of the Product Backorders dataset. The goal here is to predict whether or not a product will be put on backorder status, given a number of product metrics such as current inventory, transit time, demand forecasts and prior sales.

# Use local data file or download from GitHub
docker_data_path <- "/home/h2o/data/automl/product_backorders.csv"
if (file.exists(docker_data_path)) {
  data_path <- docker_data_path
} else {
  data_path <- "https://github.com/h2oai/h2o-tutorials/raw/master/h2o-world-2017/automl/data/product_backorders.csv"
}

# Load data into H2O
df <- h2o.importFile(data_path)

For classification, the response should be encoded as categorical (aka. “factor” or “enum”). Let’s take a look.

h2o.describe(df)

We will notice that the response column, "went_on_backorder", is already encoded as “enum”, so there’s nothing we need to do here. If it were encoded as a 0/1 “int”, then we’d have to convert the column as follows: df[,y] <- as.factor[,y]

Next, let’s identify the response & predictor columns by saving them as x and y. The "sku" column is a unique identifier so we’ll want to remove that from the set of our predictors.

y <- "went_on_backorder"
x <- setdiff(names(df), c(y, "sku"))

Run AutoML

Run AutoML, stopping after 10 models. The max_models argument specifies the number of individual (or “base”) models, and does not include the two ensemble models that are trained at the end.

aml <- h2o.automl(y = y, x = x,
                  training_frame = df,
                  max_models = 10,
                  seed = 1)

Leaderboard

Next, we will view the AutoML Leaderboard. Since we did not specify a leaderboard_frame in the h2o.automl() function for scoring and ranking the models, the AutoML leaderboard uses cross-validation metrics to rank the models.

A default performance metric for each machine learning task (binary classification, multiclass classification, regression) is specified internally and the leaderboard will be sorted by that metric. In the case of binary classification, the default ranking metric is Area Under the ROC Curve (AUC). In the future, the user will be able to specify any of the H2O metrics so that different metrics can be used to generate rankings on the leaderboard.

The leader model is stored at aml@leader and the leaderboard is stored at aml@leaderboard.

lb <- aml@leaderboard

Now we will view a snapshot of the top models. Here we should see the two Stacked Ensembles at or near the top of the leaderboard. Stacked Ensembles can almost always outperform a single model.

print(lb)

To view the entire leaderboard, specify the n argument of the print.H2OFrame() function as the total number of rows:

print(lb, n = nrow(lb))

Ensemble Exploration

To understand how the ensemble works, let’s take a peek inside the Stacked Ensemble “All Models” model. The “All Models” ensemble is an ensemble of all of the individual models in the AutoML run. This is often the top performing model on the leaderboard.

# Get model ids for all models in the AutoML Leaderboard
model_ids <- as.data.frame(aml@leaderboard$model_id)[,1]
# Get the "All Models" Stacked Ensemble model
se <- h2o.getModel(grep("StackedEnsemble_AllModels", model_ids, value = TRUE)[1])
# Get the Stacked Ensemble metalearner model
metalearner <- h2o.getModel(se@model$metalearner$name)

Examine the variable importance of the metalearner (combiner) algorithm in the ensemble. This shows us how much each base learner is contributing to the ensemble. The AutoML Stacked Ensembles use the default metalearner algorithm (GLM with non-negative weights), so the variable importance of the metalearner is actually the standardized coefficient magnitudes of the GLM.

h2o.varimp(metalearner)

We can also plot the base learner contributions to the ensemble.

h2o.varimp_plot(metalearner)

Save Leader Model

There are two ways to save the leader model – binary format and MOJO format. If you’re taking your leader model to production, then we’d suggest the MOJO format since it’s optimized for production use.

h2o.saveModel(aml@leader, path = "./product_backorders_model_bin")
h2o.download_mojo(aml@leader, path = "./")
LS0tDQp0aXRsZTogIkgyTyBBdXRvTUwgQmluYXJ5IENsYXNzaWZpY2F0aW9uIERlbW8iDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIFRvIGV4ZWN1dGUgYSBjb2RlIGNodW5rLCBjbGljayAqUnVuKiAocGxheSkgYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDbWQrU2hpZnQrRW50ZXIqLiANCg0KSWYgeW91J3JlIHZpZXdpbmcgdGhlIFJtZCBmaWxlIChjb2RlIG9ubHkpLCBidXQgeW91J2QgbGlrZSB0byBzZWUgdGhlIGNvZGUgKmFuZCogb3V0cHV0IHJlbmRlcmVkIGFzIGFuIEhUTUwgZG9jdW1lbnQsIGFuIG9ubGluZSBIVE1MIG9mIHRoaXMgZmlsZSBpcyBhdmFpbGFibGUgW2hlcmVdKGh0dHA6Ly9odG1scHJldmlldy5naXRodWIuaW8vP2h0dHBzOi8vZ2l0aHViLmNvbS9oMm9haS9oMm8tdHV0b3JpYWxzL2Jsb2IvbWFzdGVyL2gyby13b3JsZC0yMDE3L2F1dG9tbC9SL2F1dG9tbF9iaW5hcnlfY2xhc3NpZmljYXRpb25fcHJvZHVjdF9iYWNrb3JkZXJzLmh0bWwpLg0KDQojIyMgU3RhcnQgSDJPDQoNCkxvYWQgdGhlICoqaDJvKiogUiBsaWJyYXJ5IGFuZCBpbml0aWFsaXplIGEgbG9jYWwgSDJPIGNsdXN0ZXIuDQoNCmBgYHtyfQ0KbGlicmFyeShoMm8pDQpoMm8uaW5pdCgpDQpoMm8ubm9fcHJvZ3Jlc3MoKSAgIyBUdXJuIG9mZiBwcm9ncmVzcyBiYXJzIGZvciBub3RlYm9vayByZWFkYWJpbGl0eQ0KYGBgDQoNCiMjIyBMb2FkIERhdGENCg0KRm9yIHRoZSBBdXRvTUwgYmluYXJ5IGNsYXNzaWZpY2F0aW9uIGRlbW8sIHdlIHVzZSBhIHN1YnNldCBvZiB0aGUgW1Byb2R1Y3QgQmFja29yZGVyc10oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS90aXJlZGdlZWsvcHJlZGljdC1iby10cmlhbC9kYXRhKSBkYXRhc2V0LiAgVGhlIGdvYWwgaGVyZSBpcyB0byBwcmVkaWN0IHdoZXRoZXIgb3Igbm90IGEgcHJvZHVjdCB3aWxsIGJlIHB1dCBvbiBiYWNrb3JkZXIgc3RhdHVzLCBnaXZlbiBhIG51bWJlciBvZiBwcm9kdWN0IG1ldHJpY3Mgc3VjaCBhcyBjdXJyZW50IGludmVudG9yeSwgdHJhbnNpdCB0aW1lLCBkZW1hbmQgZm9yZWNhc3RzIGFuZCBwcmlvciBzYWxlcy4NCg0KYGBge3J9DQojIFVzZSBsb2NhbCBkYXRhIGZpbGUgb3IgZG93bmxvYWQgZnJvbSBHaXRIdWINCmRvY2tlcl9kYXRhX3BhdGggPC0gIi9ob21lL2gyby9kYXRhL2F1dG9tbC9wcm9kdWN0X2JhY2tvcmRlcnMuY3N2Ig0KaWYgKGZpbGUuZXhpc3RzKGRvY2tlcl9kYXRhX3BhdGgpKSB7DQogIGRhdGFfcGF0aCA8LSBkb2NrZXJfZGF0YV9wYXRoDQp9IGVsc2Ugew0KICBkYXRhX3BhdGggPC0gImh0dHBzOi8vZ2l0aHViLmNvbS9oMm9haS9oMm8tdHV0b3JpYWxzL3Jhdy9tYXN0ZXIvaDJvLXdvcmxkLTIwMTcvYXV0b21sL2RhdGEvcHJvZHVjdF9iYWNrb3JkZXJzLmNzdiINCn0NCg0KIyBMb2FkIGRhdGEgaW50byBIMk8NCmRmIDwtIGgyby5pbXBvcnRGaWxlKGRhdGFfcGF0aCkNCmBgYA0KDQoNCkZvciBjbGFzc2lmaWNhdGlvbiwgdGhlIHJlc3BvbnNlIHNob3VsZCBiZSBlbmNvZGVkIGFzIGNhdGVnb3JpY2FsIChha2EuICJmYWN0b3IiIG9yICJlbnVtIikuIExldCdzIHRha2UgYSBsb29rLg0KYGBge3J9DQpoMm8uZGVzY3JpYmUoZGYpDQpgYGANCldlIHdpbGwgbm90aWNlIHRoYXQgdGhlIHJlc3BvbnNlIGNvbHVtbiwgYCJ3ZW50X29uX2JhY2tvcmRlciJgLCBpcyBhbHJlYWR5IGVuY29kZWQgYXMgImVudW0iLCBzbyB0aGVyZSdzIG5vdGhpbmcgd2UgbmVlZCB0byBkbyBoZXJlLiAgSWYgaXQgd2VyZSBlbmNvZGVkIGFzIGEgMC8xICJpbnQiLCB0aGVuIHdlJ2QgaGF2ZSB0byBjb252ZXJ0IHRoZSBjb2x1bW4gYXMgZm9sbG93czogIGBkZlsseV0gPC0gYXMuZmFjdG9yWyx5XWANCg0KDQpOZXh0LCBsZXQncyBpZGVudGlmeSB0aGUgcmVzcG9uc2UgJiBwcmVkaWN0b3IgY29sdW1ucyBieSBzYXZpbmcgdGhlbSBhcyBgeGAgYW5kIGB5YC4gIFRoZSBgInNrdSJgIGNvbHVtbiBpcyBhIHVuaXF1ZSBpZGVudGlmaWVyIHNvIHdlJ2xsIHdhbnQgdG8gcmVtb3ZlIHRoYXQgZnJvbSB0aGUgc2V0IG9mIG91ciBwcmVkaWN0b3JzLg0KYGBge3J9DQp5IDwtICJ3ZW50X29uX2JhY2tvcmRlciINCnggPC0gc2V0ZGlmZihuYW1lcyhkZiksIGMoeSwgInNrdSIpKQ0KYGBgDQoNCg0KIyMgUnVuIEF1dG9NTCANCg0KUnVuIEF1dG9NTCwgc3RvcHBpbmcgYWZ0ZXIgMTAgbW9kZWxzLiAgVGhlIGBtYXhfbW9kZWxzYCBhcmd1bWVudCBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBpbmRpdmlkdWFsIChvciAiYmFzZSIpIG1vZGVscywgYW5kIGRvZXMgbm90IGluY2x1ZGUgdGhlIHR3byBlbnNlbWJsZSBtb2RlbHMgdGhhdCBhcmUgdHJhaW5lZCBhdCB0aGUgZW5kLg0KYGBge3J9DQphbWwgPC0gaDJvLmF1dG9tbCh5ID0geSwgeCA9IHgsDQogICAgICAgICAgICAgICAgICB0cmFpbmluZ19mcmFtZSA9IGRmLA0KICAgICAgICAgICAgICAgICAgbWF4X21vZGVscyA9IDEwLA0KICAgICAgICAgICAgICAgICAgc2VlZCA9IDEpDQpgYGANCg0KDQojIyBMZWFkZXJib2FyZA0KDQpOZXh0LCB3ZSB3aWxsIHZpZXcgdGhlIEF1dG9NTCBMZWFkZXJib2FyZC4gIFNpbmNlIHdlIGRpZCBub3Qgc3BlY2lmeSBhIGBsZWFkZXJib2FyZF9mcmFtZWAgaW4gdGhlIGBoMm8uYXV0b21sKClgIGZ1bmN0aW9uIGZvciBzY29yaW5nIGFuZCByYW5raW5nIHRoZSBtb2RlbHMsIHRoZSBBdXRvTUwgbGVhZGVyYm9hcmQgdXNlcyBjcm9zcy12YWxpZGF0aW9uIG1ldHJpY3MgdG8gcmFuayB0aGUgbW9kZWxzLiAgDQoNCkEgZGVmYXVsdCBwZXJmb3JtYW5jZSBtZXRyaWMgZm9yIGVhY2ggbWFjaGluZSBsZWFybmluZyB0YXNrIChiaW5hcnkgY2xhc3NpZmljYXRpb24sIG11bHRpY2xhc3MgY2xhc3NpZmljYXRpb24sIHJlZ3Jlc3Npb24pIGlzIHNwZWNpZmllZCBpbnRlcm5hbGx5IGFuZCB0aGUgbGVhZGVyYm9hcmQgd2lsbCBiZSBzb3J0ZWQgYnkgdGhhdCBtZXRyaWMuICBJbiB0aGUgY2FzZSBvZiBiaW5hcnkgY2xhc3NpZmljYXRpb24sIHRoZSBkZWZhdWx0IHJhbmtpbmcgbWV0cmljIGlzIEFyZWEgVW5kZXIgdGhlIFJPQyBDdXJ2ZSAoQVVDKS4gIEluIHRoZSBmdXR1cmUsIHRoZSB1c2VyIHdpbGwgYmUgYWJsZSB0byBzcGVjaWZ5IGFueSBvZiB0aGUgSDJPIG1ldHJpY3Mgc28gdGhhdCBkaWZmZXJlbnQgbWV0cmljcyBjYW4gYmUgdXNlZCB0byBnZW5lcmF0ZSByYW5raW5ncyBvbiB0aGUgbGVhZGVyYm9hcmQuDQoNClRoZSBsZWFkZXIgbW9kZWwgaXMgc3RvcmVkIGF0IGBhbWxAbGVhZGVyYCBhbmQgdGhlIGxlYWRlcmJvYXJkIGlzIHN0b3JlZCBhdCBgYW1sQGxlYWRlcmJvYXJkYC4NCmBgYHtyfQ0KbGIgPC0gYW1sQGxlYWRlcmJvYXJkDQpgYGANCg0KTm93IHdlIHdpbGwgdmlldyBhIHNuYXBzaG90IG9mIHRoZSB0b3AgbW9kZWxzLiAgSGVyZSB3ZSBzaG91bGQgc2VlIHRoZSB0d28gU3RhY2tlZCBFbnNlbWJsZXMgYXQgb3IgbmVhciB0aGUgdG9wIG9mIHRoZSBsZWFkZXJib2FyZC4gIFN0YWNrZWQgRW5zZW1ibGVzIGNhbiBhbG1vc3QgYWx3YXlzIG91dHBlcmZvcm0gYSBzaW5nbGUgbW9kZWwuDQpgYGB7cn0NCnByaW50KGxiKQ0KYGBgDQoNClRvIHZpZXcgdGhlIGVudGlyZSBsZWFkZXJib2FyZCwgc3BlY2lmeSB0aGUgYG5gIGFyZ3VtZW50IG9mIHRoZSBgcHJpbnQuSDJPRnJhbWUoKWAgZnVuY3Rpb24gYXMgdGhlIHRvdGFsIG51bWJlciBvZiByb3dzOg0KYGBge3J9DQpwcmludChsYiwgbiA9IG5yb3cobGIpKQ0KYGBgDQoNCg0KIyMgRW5zZW1ibGUgRXhwbG9yYXRpb24NCg0KVG8gdW5kZXJzdGFuZCBob3cgdGhlIGVuc2VtYmxlIHdvcmtzLCBsZXQncyB0YWtlIGEgcGVlayBpbnNpZGUgdGhlIFN0YWNrZWQgRW5zZW1ibGUgIkFsbCBNb2RlbHMiIG1vZGVsLiAgVGhlICJBbGwgTW9kZWxzIiBlbnNlbWJsZSBpcyBhbiBlbnNlbWJsZSBvZiBhbGwgb2YgdGhlIGluZGl2aWR1YWwgbW9kZWxzIGluIHRoZSBBdXRvTUwgcnVuLiAgVGhpcyBpcyBvZnRlbiB0aGUgdG9wIHBlcmZvcm1pbmcgbW9kZWwgb24gdGhlIGxlYWRlcmJvYXJkLg0KDQoNCmBgYHtyfQ0KIyBHZXQgbW9kZWwgaWRzIGZvciBhbGwgbW9kZWxzIGluIHRoZSBBdXRvTUwgTGVhZGVyYm9hcmQNCm1vZGVsX2lkcyA8LSBhcy5kYXRhLmZyYW1lKGFtbEBsZWFkZXJib2FyZCRtb2RlbF9pZClbLDFdDQojIEdldCB0aGUgIkFsbCBNb2RlbHMiIFN0YWNrZWQgRW5zZW1ibGUgbW9kZWwNCnNlIDwtIGgyby5nZXRNb2RlbChncmVwKCJTdGFja2VkRW5zZW1ibGVfQWxsTW9kZWxzIiwgbW9kZWxfaWRzLCB2YWx1ZSA9IFRSVUUpWzFdKQ0KIyBHZXQgdGhlIFN0YWNrZWQgRW5zZW1ibGUgbWV0YWxlYXJuZXIgbW9kZWwNCm1ldGFsZWFybmVyIDwtIGgyby5nZXRNb2RlbChzZUBtb2RlbCRtZXRhbGVhcm5lciRuYW1lKQ0KYGBgDQoNCkV4YW1pbmUgdGhlIHZhcmlhYmxlIGltcG9ydGFuY2Ugb2YgdGhlIG1ldGFsZWFybmVyIChjb21iaW5lcikgYWxnb3JpdGhtIGluIHRoZSBlbnNlbWJsZS4gIFRoaXMgc2hvd3MgdXMgaG93IG11Y2ggZWFjaCBiYXNlIGxlYXJuZXIgaXMgY29udHJpYnV0aW5nIHRvIHRoZSBlbnNlbWJsZS4gVGhlIEF1dG9NTCBTdGFja2VkIEVuc2VtYmxlcyB1c2UgdGhlIGRlZmF1bHQgbWV0YWxlYXJuZXIgYWxnb3JpdGhtIChHTE0gd2l0aCBub24tbmVnYXRpdmUgd2VpZ2h0cyksIHNvIHRoZSB2YXJpYWJsZSBpbXBvcnRhbmNlIG9mIHRoZSBtZXRhbGVhcm5lciBpcyBhY3R1YWxseSB0aGUgc3RhbmRhcmRpemVkIGNvZWZmaWNpZW50IG1hZ25pdHVkZXMgb2YgdGhlIEdMTS4gDQpgYGB7cn0NCmgyby52YXJpbXAobWV0YWxlYXJuZXIpDQpgYGANCg0KV2UgY2FuIGFsc28gcGxvdCB0aGUgYmFzZSBsZWFybmVyIGNvbnRyaWJ1dGlvbnMgdG8gdGhlIGVuc2VtYmxlLg0KYGBge3J9DQpoMm8udmFyaW1wX3Bsb3QobWV0YWxlYXJuZXIpDQpgYGANCg0KIyMgU2F2ZSBMZWFkZXIgTW9kZWwNCg0KVGhlcmUgYXJlIHR3byB3YXlzIHRvIHNhdmUgdGhlIGxlYWRlciBtb2RlbCAtLSBiaW5hcnkgZm9ybWF0IGFuZCBNT0pPIGZvcm1hdC4gIElmIHlvdSdyZSB0YWtpbmcgeW91ciBsZWFkZXIgbW9kZWwgdG8gcHJvZHVjdGlvbiwgdGhlbiB3ZSdkIHN1Z2dlc3QgdGhlIE1PSk8gZm9ybWF0IHNpbmNlIGl0J3Mgb3B0aW1pemVkIGZvciBwcm9kdWN0aW9uIHVzZS4NCmBgYHtyfQ0KaDJvLnNhdmVNb2RlbChhbWxAbGVhZGVyLCBwYXRoID0gIi4vcHJvZHVjdF9iYWNrb3JkZXJzX21vZGVsX2JpbiIpDQpgYGANCg0KYGBge3J9DQpoMm8uZG93bmxvYWRfbW9qbyhhbWxAbGVhZGVyLCBwYXRoID0gIi4vIikNCmBgYA0KDQo=