## ----setup, include = FALSE---------------------------------------------------
library(keras)
knitr::opts_chunk$set(comment = NA, eval = FALSE)

## -----------------------------------------------------------------------------
# library(keras)
# 
# # input layer
# inputs <- layer_input(shape = c(784))
# 
# # outputs compose input + dense layers
# predictions <- inputs %>%
#   layer_dense(units = 64, activation = 'relu') %>%
#   layer_dense(units = 64, activation = 'relu') %>%
#   layer_dense(units = 10, activation = 'softmax')
# 
# # create and compile model
# model <- keras_model(inputs = inputs, outputs = predictions)
# model %>% compile(
#   optimizer = 'rmsprop',
#   loss = 'categorical_crossentropy',
#   metrics = c('accuracy')
# )

## -----------------------------------------------------------------------------
# x <- layer_input(shape = c(784))
# # This works, and returns the 10-way softmax we defined above.
# y <- x %>% model

## -----------------------------------------------------------------------------
# # Input tensor for sequences of 20 timesteps,
# # each containing a 784-dimensional vector
# input_sequences <- layer_input(shape = c(20, 784))
# 
# # This applies our previous model to the input sequence
# processed_sequences <- input_sequences %>%
#   time_distributed(model)

## -----------------------------------------------------------------------------
# library(keras)
# 
# main_input <- layer_input(shape = c(100), dtype = 'int32', name = 'main_input')
# 
# lstm_out <- main_input %>%
#   layer_embedding(input_dim = 10000, output_dim = 512, input_length = 100) %>%
#   layer_lstm(units = 32)

## -----------------------------------------------------------------------------
# auxiliary_output <- lstm_out %>%
#   layer_dense(units = 1, activation = 'sigmoid', name = 'aux_output')

## -----------------------------------------------------------------------------
# auxiliary_input <- layer_input(shape = c(5), name = 'aux_input')
# 
# main_output <- layer_concatenate(c(lstm_out, auxiliary_input)) %>%
#   layer_dense(units = 64, activation = 'relu') %>%
#   layer_dense(units = 64, activation = 'relu') %>%
#   layer_dense(units = 64, activation = 'relu') %>%
#   layer_dense(units = 1, activation = 'sigmoid', name = 'main_output')

## -----------------------------------------------------------------------------
# model <- keras_model(
#   inputs = c(main_input, auxiliary_input),
#   outputs = c(main_output, auxiliary_output)
# )

## -----------------------------------------------------------------------------
# summary(model)

## -----------------------------------------------------------------------------
# model %>% compile(
#   optimizer = 'rmsprop',
#   loss = 'binary_crossentropy',
#   loss_weights = c(1.0, 0.2)
# )

## ----eval = FALSE-------------------------------------------------------------
# model %>% fit(
#   x = list(headline_data, additional_data),
#   y = list(labels, labels),
#   epochs = 50,
#   batch_size = 32
# )

## ----eval = FALSE-------------------------------------------------------------
# model %>% compile(
#   optimizer = 'rmsprop',
#   loss = list(main_output = 'binary_crossentropy', aux_output = 'binary_crossentropy'),
#   loss_weights = list(main_output = 1.0, aux_output = 0.2)
# )
# 
# # And trained it via:
# model %>% fit(
#   x = list(main_input = headline_data, aux_input = additional_data),
#   y = list(main_output = labels, aux_output = labels),
#   epochs = 50,
#   batch_size = 32
# )

## -----------------------------------------------------------------------------
# library(keras)
# 
# tweet_a <- layer_input(shape = c(280, 256))
# tweet_b <- layer_input(shape = c(280, 256))

## ----eval=FALSE---------------------------------------------------------------
# # This layer can take as input a matrix and will return a vector of size 64
# shared_lstm <- layer_lstm(units = 64)
# 
# # When we reuse the same layer instance multiple times, the weights of the layer are also
# # being reused (it is effectively *the same* layer)
# encoded_a <- tweet_a %>% shared_lstm
# encoded_b <- tweet_b %>% shared_lstm
# 
# # We can then concatenate the two vectors and add a logistic regression on top
# predictions <- layer_concatenate(c(encoded_a, encoded_b), axis=-1) %>%
#   layer_dense(units = 1, activation = 'sigmoid')
# 
# # We define a trainable model linking the tweet inputs to the predictions
# model <- keras_model(inputs = c(tweet_a, tweet_b), outputs = predictions)
# 
# model %>% compile(
#   optimizer = 'rmsprop',
#   loss = 'binary_crossentropy',
#   metrics = c('accuracy')
# )
# 
# model %>% fit(list(data_a, data_b), labels, epochs = 10)
# 

## -----------------------------------------------------------------------------
# a <- layer_input(shape = c(280, 256))
# 
# lstm <- layer_lstm(units = 32)
# 
# encoded_a <- a %>% lstm
# 
# lstm$output

## -----------------------------------------------------------------------------
# a <- layer_input(shape = c(280, 256))
# b <- layer_input(shape = c(280, 256))
# 
# lstm <- layer_lstm(units = 32)
# 
# encoded_a <- a %>% lstm
# encoded_b <- b %>% lstm
# 
# lstm$output

## -----------------------------------------------------------------------------
# get_output_at(lstm, 1)
# get_output_at(lstm, 2)

## -----------------------------------------------------------------------------
# a <- layer_input(shape = c(32, 32, 3))
# b <- layer_input(shape = c(64, 64, 3))
# 
# conv <- layer_conv_2d(filters = 16, kernel_size = c(3,3), padding = 'same')
# 
# conved_a <- a %>% conv
# 
# # only one input so far, the following will work
# conv$input_shape
# 
# conved_b <- b %>% conv
# # now the `$input_shape` property wouldn't work, but this does:
# get_input_shape_at(conv, 1)
# get_input_shape_at(conv, 2)

## -----------------------------------------------------------------------------
# library(keras)
# 
# input_img <- layer_input(shape = c(256, 256, 3))
# 
# tower_1 <- input_img %>%
#   layer_conv_2d(filters = 64, kernel_size = c(1, 1), padding='same', activation='relu') %>%
#   layer_conv_2d(filters = 64, kernel_size = c(3, 3), padding='same', activation='relu')
# 
# tower_2 <- input_img %>%
#   layer_conv_2d(filters = 64, kernel_size = c(1, 1), padding='same', activation='relu') %>%
#   layer_conv_2d(filters = 64, kernel_size = c(5, 5), padding='same', activation='relu')
# 
# tower_3 <- input_img %>%
#   layer_max_pooling_2d(pool_size = c(3, 3), strides = c(1, 1), padding = 'same') %>%
#   layer_conv_2d(filters = 64, kernel_size = c(1, 1), padding='same', activation='relu')
# 
# output <- layer_concatenate(c(tower_1, tower_2, tower_3), axis = 1)
# 

## -----------------------------------------------------------------------------
# # input tensor for a 3-channel 256x256 image
# x <- layer_input(shape = c(256, 256, 3))
# # 3x3 conv with 3 output channels (same as input channels)
# y <- x %>% layer_conv_2d(filters = 3, kernel_size =c(3, 3), padding = 'same')
# # this returns x + y.
# z <- layer_add(c(x, y))

## -----------------------------------------------------------------------------
# # First, define the vision model
# digit_input <- layer_input(shape = c(27, 27, 1))
# out <- digit_input %>%
#   layer_conv_2d(filters = 64, kernel_size = c(3, 3)) %>%
#   layer_conv_2d(filters = 64, kernel_size = c(3, 3)) %>%
#   layer_max_pooling_2d(pool_size = c(2, 2)) %>%
#   layer_flatten()
# 
# vision_model <- keras_model(digit_input, out)
# 
# # Then define the tell-digits-apart model
# digit_a <- layer_input(shape = c(27, 27, 1))
# digit_b <- layer_input(shape = c(27, 27, 1))
# 
# # The vision model will be shared, weights and all
# out_a <- digit_a %>% vision_model
# out_b <- digit_b %>% vision_model
# 
# out <- layer_concatenate(c(out_a, out_b)) %>%
#   layer_dense(units = 1, activation = 'sigmoid')
# 
# classification_model <- keras_model(inputs = c(digit_a, digit_b), out)

## -----------------------------------------------------------------------------
# # First, let's define a vision model using a Sequential model.
# # This model will encode an image into a vector.
# vision_model <- keras_model_sequential()
# vision_model %>%
#   layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = 'relu', padding = 'same',
#                 input_shape = c(224, 224, 3)) %>%
#   layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = 'relu') %>%
#   layer_max_pooling_2d(pool_size = c(2, 2)) %>%
#   layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = 'relu', padding = 'same') %>%
#   layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = 'relu') %>%
#   layer_max_pooling_2d(pool_size = c(2, 2)) %>%
#   layer_conv_2d(filters = 256, kernel_size = c(3, 3), activation = 'relu', padding = 'same') %>%
#   layer_conv_2d(filters = 256, kernel_size = c(3, 3), activation = 'relu') %>%
#   layer_conv_2d(filters = 256, kernel_size = c(3, 3), activation = 'relu') %>%
#   layer_max_pooling_2d(pool_size = c(2, 2)) %>%
#   layer_flatten()
# 
# # Now let's get a tensor with the output of our vision model:
# image_input <- layer_input(shape = c(224, 224, 3))
# encoded_image <- image_input %>% vision_model
# 
# # Next, let's define a language model to encode the question into a vector.
# # Each question will be at most 100 word long,
# # and we will index words as integers from 1 to 9999.
# question_input <- layer_input(shape = c(100), dtype = 'int32')
# encoded_question <- question_input %>%
#   layer_embedding(input_dim = 10000, output_dim = 256, input_length = 100) %>%
#   layer_lstm(units = 256)
# 
# # Let's concatenate the question vector and the image vector then
# # train a logistic regression over 1000 words on top
# output <- layer_concatenate(c(encoded_question, encoded_image)) %>%
#   layer_dense(units = 1000, activation='softmax')
# 
# # This is our final model:
# vqa_model <- keras_model(inputs = c(image_input, question_input), outputs = output)

## -----------------------------------------------------------------------------
# video_input <- layer_input(shape = c(100, 224, 224, 3))
# 
# # This is our video encoded via the previously trained vision_model (weights are reused)
# encoded_video <- video_input %>%
#   time_distributed(vision_model) %>%
#   layer_lstm(units = 256)
# 
# # This is a model-level representation of the question encoder, reusing the same weights as before:
# question_encoder <- keras_model(inputs = question_input, outputs = encoded_question)
# 
# # Let's use it to encode the question:
# video_question_input <- layer_input(shape = c(100), dtype = 'int32')
# encoded_video_question <- video_question_input %>% question_encoder
# 
# # And this is our video question answering model:
# output <- layer_concatenate(c(encoded_video, encoded_video_question)) %>%
#   layer_dense(units = 1000, activation = 'softmax')
# 
# video_qa_model <- keras_model(inputs= c(video_input, video_question_input), outputs = output)

