R/init.R

#' Brain
#'
#' Create a brain.
#'
#' @examples brain()
#'
#' @importFrom graphics par plot points
#' @importFrom stats sd
#'
#' @examples
#' brain() %>%
#'   perceptron(c(2,3,1))
#'
#' @export
brain <- function(){
  brain <- V8::new_context()
  err <- tryCatch(brain$reset(), error = function(e) e)
  brain$source(system.file("htmlwidgets/lib/synaptic/synaptic.min.js", package = "brain"))
  brain$source(system.file("activations/custom.js", package = "brain"))
  brain <- structure(list(brain = brain, opts = list()), class = "brain")
  brain$opts$architecture <- "undefined"
  return(brain)
}

#' Architecture
#'
#' Define architecture.
#'
#' @param brain An object of class \code{brain} as returned by \code{brain}.
#' @param layers A single integer or a vector of integer specifying the size of each layer.
#' @param input,pool,output The size as an integer.
#' @param connections Number of random connections.
#' @param gates Number of random gates amongst the \code{connections}.
#'
#' @section Functions:
#' \itemize{
#'   \item{\code{perceptron}: This architecture allows you to create multilayer perceptrons, also known as feed-forward neural networks. They consist of a sequence of layers, each fully connected to the next one.}
#'   \item{\code{lstm}: The long short-term memory is an architecture well-suited to learn from experience to classify, process and predict time series when there are very long time lags of unknown size between important events.}
#'   \item{\code{liquid}: The Liquid architecture allows you to create Liquid State Machines. In these networks, neurons are randomly connected to each other. The recurrent nature of the connections turns the time varying input into a spatio-temporal pattern of activations in the network nodes.}
#'   \item{\code{hopfield}: The Hopfield architecture serves as content-addressable memory. They are trained to remember patterns and then when feeding new patterns to the network it returns the most similar one from the patterns it was trained to remember.}
#' }
#'
#' @note Hopfield is trained and ran with different functions, see \code{\link{hopfield}}.
#'
#' @examples
#' brain() %>%
#'   perceptron(c(2,3,1))
#'
#' @seealso \code{\link{squash}} to set activation functions.
#'
#' @name architecture
#' @export
perceptron <- function(brain, layers){
  .architect(brain, "perceptron", layers)
}

#' @rdname architecture
#' @export
lstm <- function(brain, layers){
  .architect(brain, "lstm", layers)
}

#' @rdname architecture
#' @export
liquid <- function(brain, input, pool, output, connections, gates){

  if(missing(input) || missing(pool) || missing(output) || missing(connections) || missing(gates))
    stop("missing input, pool, output, connections, or gates", call. = FALSE)

  inputs <- c(input, pool, output, connections, gates)
  .architect(brain, "liquid", inputs)
}

#' @rdname architecture
#' @export
hopfield <- function(brain, layers){
  .architect(brain, "hopfield", layers)
}


#' Squash
#'
#' Set activation functions for your layers.
#'
#' @inheritParams architecture
#' @param bias A bias, numerical.
#' @param squash A object of class \code{squash} as returned by \code{\link{squash_function}}.
#'
#' @examples
#' brain() %>%
#'   perceptron(c(2,3,1)) %>%
#'   squash_input(
#'     squash_function("tanh")
#'   )
#'
#' @seealso \code{\link{squash_function}} for valid activation functions.
#'
#' @name squash
#' @export
squash_input <- function(brain, squash, bias = NULL){

  brain <- .squash(brain, "net.layers.input", squash, bias)

  brain$brain$eval("net.setOptimize(false)")
  brain$opts$layers$prt[1] <- gsub("_activation", "", tolower(squash))

  return(brain)

}

#' @rdname squash
#' @export
squash_output <- function(brain, squash, bias = NULL){

  brain <- .squash(brain, "net.layers.output", squash, bias)

  brain$brain$eval("net.setOptimize(false)")
  brain$opts$layers$prt[3] <- gsub("_activation", "", tolower(squash))

  return(brain)

}

#' @rdname squash
#' @export
squash_hidden <- function(brain, squash, bias = NULL){

  if(missing(squash))
    stop("missing squash function", call. = FALSE)

  if(!inherits(squash, "squash_function"))
    stop("squash must be a squash function, see squash_function", call. = FALSE)

  brain$opts$layers$prt[2] <- gsub("_activation", "", tolower(squash))

  bias <- .null2js(bias)

  opts <- paste0(
    "{squash: ", squash, ", bias: ", bias, "}"
  )

  ev <- paste0(
    "net.layers.hidden.forEach(function(hiddenLayer){
      hiddenLayer.set(", opts, ")
    });"
  )

  brain$brain$eval("net.setOptimize(false)")
  brain$brain$eval(ev)

  return(brain)
}
brain-r/brain documentation built on May 21, 2019, 4:05 a.m.