Nothing
## #' AutoEncoder
## #'
## #' An S4 Class implementing an Autoencoder
## #'
## #' Autoencoders are neural networks that try to reproduce their input. Consider
## #' this method unstable, as the internals may still be changed.
## #'
## #' @template dimRedMethodSlots
## #'
## #' @template dimRedMethodGeneralUsage
## #'
## #' @section Parameters:
## #' Autoencoder can take the following parameters:
## #' \describe{
## #' \item{ndim}{The number of dimensions for reduction.}
## #' \item{n_hidden}{The number of neurons in the hidden
## #' layers, the length specifies the number of layers,
## #' the length must be impair, the middle number must
## #' be the same as ndim.}
## #' \item{activation}{The activation functions for the layers,
## #' one of "tanh", "sigmoid", "relu", "elu", everything
## #' else will silently be ignored and there will be no
## #' activation function for the layer.}
## #' \item{weight_decay}{the coefficient for weight decay,
## #' set to 0 if no weight decay desired.}
## #' \item{learning_rate}{The learning rate for gradient descend}
## #' \item{graph}{Optional: A list of bits and pieces that define the
## #' autoencoder in tensorflow, see details.}
## #' \item{keras_graph}{Optional: A list of keras layers that define
## #' the encoder and decoder, specifying this, will ignore all
## #' other topology related variables, see details.}
## #' \item{batchsize}{If NA, all data will be used for training,
## #' else only a random subset of size batchsize will be used}
## #' \item{n_steps}{the number of training steps.}
## #' }
## #'
## #' @section Details:
## #' There are several ways to specify an autoencoder, the simplest is to pass the
## #' number of neurons per layer in \code{n_hidden}, this must be a vector of
## #' integers of impair length and it must be symmetric and the middle number must
## #' be equal to \code{ndim}, For every layer an activation function can be
## #' specified with \code{activation}.
## #'
## #' For regularization weight decay can be specified by setting
## #' \code{weight_decay} > 0.
## #'
## #' Currently only a gradient descent optimizer is used, the learning rate can be
## #' specified by setting \code{learning_rate}.
## #' The learner can operate on batches if \code{batchsize} is not \code{NA}.
## #' The number of steps the learner uses is specified using \code{n_steps}.
## #'
## #' @section Further training a model:
## #' If the model did not converge in the first training phase or training with
## #' different data is desired, the \code{\link{dimRedResult}} object may be
## #' passed as \code{autoencoder} parameter; In this case all topology related
## #' parameters will be ignored.
## #'
## #' @section Using Keras layers:
## #' The encoder and decoder part can be specified using a list of \pkg{keras}
## #' layers. This requires a list with two entries, \code{encoder} should contain
## #' a LIST of keras layers WITHOUT the \code{\link[keras]{layer_input}}
## #' that will be concatenated in order to form the encoder part.
## #' \code{decoder} should be
## #' defined accordingly, the output of \code{decoder} must have the same number
## #' of dimensions as the input data.
## #'
## #' @section Using Tensorflow:
## #' The model can be entirely defined in \pkg{tensorflow}, it must contain a
## #' list with the following entries:
## #' \describe{
## #' \item{encoder}{A tensor that defines the encoder.}
## #' \item{decoder}{A tensor that defines the decoder.}
## #' \item{network}{A tensor that defines the reconstruction (encoder + decoder).}
## #' \item{loss}{A tensor that calculates the loss (network + loss function).}
## #' \item{in_data}{A \code{placeholder} that points to the data input of
## #' the network AND the encoder.}
## #' \item{in_decoder}{A \code{placeholder} that points to the input of
## #' the decoder.}
## #' \item{session}{A \pkg{tensorflow} \code{Session} object that holds
## #' the values of the tensors.}
## #' }
## #'
## #' @section Implementation:
## #' Uses \pkg{tensorflow} as a backend, for details an
## #' problems relating tensorflow, see \url{https://tensorflow.rstudio.com}.
## #'
## #' @examples
## #' \dontrun{
## #' dat <- loadDataSet("3D S Curve")
## #'
## #' emb <- embed(dat, "AutoEncoder")
## #'
## #' # predicting is possible:
## #' samp <- sample(floor(nrow(dat) / 10))
## #' emb2 <- embed(dat[samp])
## #' emb3 <- predict(emb2, dat[-samp])
## #'
## #' plot(emb, type = "2vars")
## #' plot(emb2, type = "2vars")
## #' points(getData(emb3))
## #' }
## #'
## #' @include dimRedResult-class.R
## #' @include dimRedMethod-class.R
## #' @family dimensionality reduction methods
## #' @export AutoEncoder
## #' @exportClass AutoEncoder
## AutoEncoder <- setClass(
## "AutoEncoder",
## contains = "dimRedMethod",
## prototype = list(
## stdpars = list(ndim = 2,
## n_hidden = c(10, 2, 10),
## activation = c("tanh", "lin", "tanh"),
## learning_rate = 0.15,
## loss = "mse",
## optimizer = "adam",
## encoder = NULL,
## decoder = NULL,
## ## is.na() of an S4 class gives a warning
## batchsize = 20,
## epochs = 5,
## validation_split = 0.2),
## fun = function (data, pars,
## keep.org.data = TRUE) {
## chckpkg("keras3")
## indata <- data@data
## indims <- ncol(indata)
## ndim <- pars$ndim
## input_data <- keras3::layer_input(shape = indims)
## input_hidden <- keras3::layer_input(shape = ndim)
## ## if the user did not specify encoder and decoder, we build them from the
## ## parameters
## if (is.null(pars$encoder) || is.null(pars$decoder)) {
## depth <- length(pars$n_hidden)
## if (depth %% 2 == 0) {
## stop("the number of layers must be impair")
## }
## if (ndim != pars$n_hidden[ceiling(depth / 2)]) {
## stop("the middle of n_hidden must be equal to ndim")
## }
## if (depth != length(pars$activation)) {
## stop("declare an activation function for each layer")
## }
## in_depth <- ceiling(depth / 2)
## out_depth <- depth - in_depth
## layers <- mapply(
## function(s, n) keras3::layer_dense(units = n, activation = s),
## pars$activation, pars$n_hidden,
## SIMPLIFY = FALSE
## )
## encoder <- c(input_data, layers[1:in_depth])
## decoder <- c(input_hidden, layers[(in_depth + 1):depth])
## } else {
## encoder <- c(input_data, pars$encoder)
## decoder <- c(input_hidden, pars$decoder)
## }
## ## now build the actual model, compile it and fit it
## autoencoder <- c(input_data, encoder, decoder)
## encoder <- encoder %>%
## chain_list() %>%
## keras3::keras_model()
## decoder <- decoder %>%
## chain_list() %>%
## keras3::keras_model()
## autoencoder <- autoencoder %>%
## chain_list() %>%
## keras3::keras_model()
## autoencoder %>%
## keras3::compile(
## optimizer = pars$optimizer,
## loss = pars$loss
## )
## history <- autoencoder %>%
## keras3::fit(
## indata, indata,
## epochs = pars$epochs,
## batch_size = pars$batchsize,
## validation_split = pars$validation_split,
## verbose = 0
## )
## meta <- data@meta
## orgdata <- if (keep.org.data) data@data else NULL
## indata <- data@data
## appl <- function(x) {
## appl.meta <- if (inherits(x, "dimRedData")) x@meta else data.frame()
## proj <- if (inherits(x, "dimRedData")) x@data else x
## if (ncol(proj) != ncol(data@data))
## stop("x must have the same number of dimensions ",
## "as the original data")
## res <- encoder(proj)
## colnames(res) <- paste0("AE", seq_len(ncol(res)))
## new("dimRedData", data = res, meta = appl.meta)
## }
## inv <- function(x) {
## appl.meta <- if (inherits(x, "dimRedData")) x@meta else data.frame()
## proj <- if (inherits(x, "dimRedData")) x@data else x
## if (ncol(proj) != pars$ndim)
## stop("x must have the same number of dimensions ",
## "as ndim data")
## res <- decoder(proj)
## colnames(res) <- colnames(indata)
## new("dimRedData", data = res, meta = appl.meta)
## }
## colnames(outdata) <- paste0("AE", seq_len(ncol(outdata)))
## return(new(
## "dimRedResult",
## data = new("dimRedData",
## data = outdata,
## meta = meta),
## org.data = orgdata,
## apply = appl,
## inverse = inv,
## has.apply = TRUE,
## has.inverse = TRUE,
## has.org.data = keep.org.data,
## method = "AutoEncoder",
## pars = pars
## ))
## },
## requires = c("tensorflow", "keras3"))
## )
## ## no idea why these and variants do not work:
## ## chain_list <- function(x1, x2) Reduce(`%>%`, x2, init = x1)
## ## chain_list <- function(x) Reduce(`%>%`, x)
## chain_list <- function(x1, x2 = NULL) {
## if (is.null(x2)) {
## stopifnot(is.list(x1))
## result <- x1[[1]]
## if (length(x1) > 1) for (i in 2:length(x1)) {
## result <- result %>% (x1[[i]])
## }
## } else {
## stopifnot(is.list(x2))
## result <- x1
## for (i in 1:length(x2)) {
## result <- result %>% (x2[[i]])
## }
## }
## return(result)
## }
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.