## ----setup, include=FALSE------------------------------------------------
knitr::opts_chunk$set(echo = TRUE, eval = FALSE)

## ------------------------------------------------------------------------
#  library(keras)

## ------------------------------------------------------------------------
#  inputs <- layer_input(shape = 784, name = "digits")
#  outputs <- inputs %>%
#    layer_dense(units = 64, activation = "relu", name = "dense_1") %>%
#    layer_dense(units = 64, activation = "relu", name = "dense_2") %>%
#    layer_dense(units = 10, activation = "softmax", name = "predictions")
#  model <- keras_model(inputs, outputs)
#  summary(model)

## ------------------------------------------------------------------------
#  c(c(x_train, y_train), c(x_test, y_test)) %<-% dataset_mnist()
#  x_train <- x_train %>% array_reshape(dim = c(60000, 784))/255
#  x_test <- x_test %>% array_reshape(dim = c(10000, 784))/255
#  
#  model %>% compile(loss = "sparse_categorical_crossentropy",
#                    optimizer = optimizer_rmsprop())
#  
#  history <- model %>% fit(x_train, y_train, batch_size = 64, epochs = 1)

## ------------------------------------------------------------------------
#  # Save predictions for future checks
#  predictions <- predict(model, x_test)

## ------------------------------------------------------------------------
#  # Save the model
#  save_model_hdf5(model, "model.h5")
#  
#  # Recreate the exact same model purely from the file
#  new_model <- load_model_hdf5("model.h5")

## ------------------------------------------------------------------------
#  # Check that the state is preserved
#  new_predictions <- predict(new_model, x_test)
#  all.equal(predictions, new_predictions)

## ------------------------------------------------------------------------
#  # Export the model to a SavedModel
#  model_to_saved_model(model, "model/")
#  
#  # Recreate the exact same model
#  new_model <- model_from_saved_model("model/")
#  
#  # Check that the state is preserved
#  new_predictions <- predict(new_model, x_test)
#  all.equal(predictions, new_predictions)

## ----eval=FALSE----------------------------------------------------------
#  export_savedmodel(model, "savedmodel/")
#  new_predictions <- tfdeploy::predict_savedmodel(x_test, "savedmodel/")

## ------------------------------------------------------------------------
#  config <- get_config(model)
#  reinitialized_model <- from_config(config)

## ------------------------------------------------------------------------
#  # Note that the model state is not preserved! We only saved the architecture.
#  new_predictions <- predict(reinitialized_model, x_test)
#  all.equal(predictions, new_predictions)

## ------------------------------------------------------------------------
#  json_config <- model_to_json(model)
#  reinitialized_model <- model_from_json(json_config)

## ------------------------------------------------------------------------
#  weights <- get_weights(model)
#  set_weights(reinitialized_model, weights)
#  
#  new_predictions <- predict(reinitialized_model, x_test)
#  all.equal(predictions, new_predictions)

## ------------------------------------------------------------------------
#  config <- get_config(model)
#  weights <- get_weights(model)
#  
#  new_model <- from_config(config)
#  set_weights(new_model, weights)
#  
#  # Check that the state is preserved
#  new_predictions <- predict(new_model, x_test)
#  all.equal(predictions, new_predictions)

## ------------------------------------------------------------------------
#  # Save JSON config to disk
#  json_config <- model_to_json(model)
#  writeLines(json_config, "model_config.json")
#  
#  # Save weights to disk
#  save_model_weights_hdf5(model, "model_weights.h5")
#  
#  # Reload the model from the 2 files we saved
#  json_config <- readLines("model_config.json")
#  new_model <- model_from_json(json_config)
#  load_model_weights_hdf5(new_model, "model_weights.h5")
#  
#  # Check that the state is preserved
#  new_predictions <- predict(new_model, x_test)
#  all.equal(predictions, new_predictions)

## ------------------------------------------------------------------------
#  save_model_hdf5(model, "model.h5")
#  new_model <- load_model_hdf5("model.h5")

## ------------------------------------------------------------------------
#  save_model_weights_tf(model, "model_weights")

## ------------------------------------------------------------------------
#  keras_model_simple_mlp <- function(num_classes,
#                                     use_bn = FALSE, use_dp = FALSE,
#                                     name = NULL) {
#  
#    # define and return a custom model
#    keras_model_custom(name = name, function(self) {
#  
#      # create layers we'll need for the call (this code executes once)
#      self$dense1 <- layer_dense(units = 32, activation = "relu")
#      self$dense2 <- layer_dense(units = num_classes, activation = "softmax")
#      if (use_dp)
#        self$dp <- layer_dropout(rate = 0.5)
#      if (use_bn)
#        self$bn <- layer_batch_normalization(axis = -1)
#  
#      # implement call (this code executes during training & inference)
#      function(inputs, mask = NULL) {
#        x <- self$dense1(inputs)
#        if (use_dp)
#          x <- self$dp(x)
#        if (use_bn)
#          x <- self$bn(x)
#        self$dense2(x)
#      }
#    })
#  }
#  
#  model <- keras_model_simple_mlp(num_classes = 10)

## ------------------------------------------------------------------------
#  model %>% compile(loss = "sparse_categorical_crossentropy",
#                    optimizer = optimizer_rmsprop())
#  
#  history <- model %>% fit(x_train, y_train, batch_size = 64, epochs = 1)

## ------------------------------------------------------------------------
#  save_model_weights_tf(model, "my_weights")

## ------------------------------------------------------------------------
#  # Save predictions for future checks
#  predictions <- predict(model, x_test)
#  # Also save the loss on the first batch
#  # to later assert that the optimizer state was preserved
#  first_batch_loss <- train_on_batch(model, x_train[1:64,], y_train[1:64])

## ------------------------------------------------------------------------
#  new_model <- keras_model_simple_mlp(num_classes = 10)
#  new_model %>% compile(loss = "sparse_categorical_crossentropy",
#                    optimizer = optimizer_rmsprop())
#  
#  # This initializes the variables used by the optimizers,
#  # as well as any stateful metric variables
#  train_on_batch(new_model, x_train[1:5,], y_train[1:5])
#  
#  # Load the state of the old model
#  load_model_weights_tf(new_model, "my_weights")
#  
#  # Check that the model state has been preserved
#  new_predictions <- predict(new_model, x_test)
#  all.equal(predictions, new_predictions)
#  
#  # The optimizer state is preserved as well,
#  # so you can resume training where you left off
#  new_first_batch_loss <- train_on_batch(new_model, x_train[1:64,], y_train[1:64])
#  first_batch_loss == new_first_batch_loss

