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

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

## -----------------------------------------------------------------------------
#  model <- keras_model_sequential()
#  
#  model %>%
#  
#    # Adds a densely-connected layer with 64 units to the model:
#    layer_dense(units = 64, activation = 'relu') %>%
#  
#    # Add another:
#    layer_dense(units = 64, activation = 'relu') %>%
#  
#    # Add a softmax layer with 10 output units:
#    layer_dense(units = 10, activation = 'softmax')

## -----------------------------------------------------------------------------
#  # Create a sigmoid layer:
#  layer_dense(units = 64, activation ='sigmoid')
#  
#  # A linear layer with L1 regularization of factor 0.01 applied to the kernel matrix:
#  layer_dense(units = 64, kernel_regularizer = regularizer_l1(0.01))
#  
#  # A linear layer with L2 regularization of factor 0.01 applied to the bias vector:
#  layer_dense(units = 64, bias_regularizer = regularizer_l2(0.01))
#  
#  # A linear layer with a kernel initialized to a random orthogonal matrix:
#  layer_dense(units = 64, kernel_initializer = 'orthogonal')
#  
#  # A linear layer with a bias vector initialized to 2.0:
#  layer_dense(units = 64, bias_initializer = initializer_constant(2.0))

## -----------------------------------------------------------------------------
#  model %>% compile(
#    optimizer = 'adam',
#    loss = 'categorical_crossentropy',
#    metrics = list('accuracy')
#  )

## -----------------------------------------------------------------------------
#  # Configure a model for mean-squared error regression.
#  model %>% compile(
#    optimizer = 'adam',
#    loss = 'mse',           # mean squared error
#    metrics = list('mae')   # mean absolute error
#  )
#  
#  # Configure a model for categorical classification.
#  model %>% compile(
#    optimizer = optimizer_rmsprop(lr = 0.01),
#    loss = "categorical_crossentropy",
#    metrics = list("categorical_accuracy")
#  )

## -----------------------------------------------------------------------------
#  
#  data <- matrix(rnorm(1000 * 32), nrow = 1000, ncol = 32)
#  labels <- matrix(rnorm(1000 * 10), nrow = 1000, ncol = 10)
#  
#  model %>% fit(
#    data,
#    labels,
#    epochs = 10,
#    batch_size = 32
#  )

## -----------------------------------------------------------------------------
#  data <- matrix(rnorm(1000 * 32), nrow = 1000, ncol = 32)
#  labels <- matrix(rnorm(1000 * 10), nrow = 1000, ncol = 10)
#  
#  val_data <- matrix(rnorm(1000 * 32), nrow = 100, ncol = 32)
#  val_labels <- matrix(rnorm(100 * 10), nrow = 100, ncol = 10)
#  
#  model %>% fit(
#    data,
#    labels,
#    epochs = 10,
#    batch_size = 32,
#    validation_data = list(val_data, val_labels)
#  )

## ---- eval = FALSE------------------------------------------------------------
#  model %>% evaluate(test_data, test_labels, batch_size = 32)
#  
#  model %>% evaluate(test_dataset, steps = 30)

## ---- eval = FALSE------------------------------------------------------------
#  model %>% predict(test_data, batch_size = 32)
#  
#  model %>% predict(test_dataset, steps = 30)

## -----------------------------------------------------------------------------
#  inputs <- layer_input(shape = (32))  # Returns a placeholder tensor
#  
#  predictions <- inputs %>%
#    layer_dense(units = 64, activation = 'relu') %>%
#    layer_dense(units = 64, activation = 'relu') %>%
#    layer_dense(units = 10, activation = 'softmax')
#  
#  # Instantiate the model given inputs and outputs.
#  model <- keras_model(inputs = inputs, outputs = predictions)
#  
#  # The compile step specifies the training configuration.
#  model %>% compile(
#    optimizer = optimizer_rmsprop(lr = 0.001),
#    loss = 'categorical_crossentropy',
#    metrics = list('accuracy')
#  )
#  
#  # Trains for 5 epochs
#  model %>% fit(
#    data,
#    labels,
#    batch_size = 32,
#    epochs = 5
#  )

## -----------------------------------------------------------------------------
#  library(keras)
#  
#  CustomLayer <- R6::R6Class("CustomLayer",
#  
#    inherit = KerasLayer,
#  
#    public = list(
#  
#      output_dim = NULL,
#  
#      kernel = NULL,
#  
#      initialize = function(output_dim) {
#        self$output_dim <- output_dim
#      },
#  
#      build = function(input_shape) {
#        self$kernel <- self$add_weight(
#          name = 'kernel',
#          shape = list(input_shape[[2]], self$output_dim),
#          initializer = initializer_random_normal(),
#          trainable = TRUE
#        )
#      },
#  
#      call = function(x, mask = NULL) {
#        k_dot(x, self$kernel)
#      },
#  
#      compute_output_shape = function(input_shape) {
#        list(input_shape[[1]], self$output_dim)
#      }
#    )
#  )

## -----------------------------------------------------------------------------
#  # define layer wrapper function
#  layer_custom <- function(object, output_dim, name = NULL, trainable = TRUE) {
#    create_layer(CustomLayer, object, list(
#      output_dim = as.integer(output_dim),
#      name = name,
#      trainable = trainable
#    ))
#  }
#  

## -----------------------------------------------------------------------------
#  model <- keras_model_sequential()
#  model %>%
#    layer_dense(units = 32, input_shape = c(32,32)) %>%
#    layer_custom(output_dim = 32)

## ---- eval = FALSE------------------------------------------------------------
#  my_model <- function(input_dim, output_dim, 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)
#      # note: the layers have to be created on the self object!
#      self$dense1 <- layer_dense(units = 64, activation = 'relu', input_shape = input_dim)
#      self$dense2 <- layer_dense(units = 64, activation = 'relu')
#      self$dense3 <- layer_dense(units = 10, activation = 'softmax')
#  
#      # implement call (this code executes during training & inference)
#      function(inputs, mask = NULL) {
#        x <- inputs %>%
#          self$dense1() %>%
#          self$dense2() %>%
#          self$dense3()
#        x
#      }
#    })
#  }
#  
#  model <- my_model(input_dim = 32, output_dim = 10)
#  
#  model %>% compile(
#    optimizer = optimizer_rmsprop(lr = 0.001),
#    loss = 'categorical_crossentropy',
#    metrics = list('accuracy')
#  )
#  
#  # Trains for 5 epochs
#  model %>% fit(
#    data,
#    labels,
#    batch_size = 32,
#    epochs = 5
#  )

## -----------------------------------------------------------------------------
#  callbacks <- list(
#    callback_early_stopping(patience = 2, monitor = 'val_loss'),
#    callback_tensorboard(log_dir = './logs')
#  )
#  
#  model %>% fit(
#    data,
#    labels,
#    batch_size = 32,
#    epochs = 5,
#    callbacks = callbacks,
#    validation_data = list(val_data, val_labels)
#  )

## -----------------------------------------------------------------------------
#  # save in SavedModel format
#  model %>% save_model_weights_tf('my_model/')
#  
#  # Restore the model's state,
#  # this requires a model with the same architecture.
#  model %>% load_model_weights_tf('my_model/')

## -----------------------------------------------------------------------------
#  # Serialize a model to JSON format
#  json_string <- model %>% model_to_json()
#  
#  # Recreate the model (freshly initialized)
#  fresh_model <- model_from_json(json_string)
#  
#  # Serializes a model to YAML format
#  yaml_string <- model %>% model_to_yaml()
#  
#  # Recreate the model
#  fresh_model <- model_from_yaml(yaml_string)

## -----------------------------------------------------------------------------
#  # Save entire model to the SavedModel format
#  model %>% save_model_tf('my_model/')
#  
#  # Recreate the exact same model, including weights and optimizer.
#  model <- load_model_tf('my_model/')

