tests/testthat/test-interface.R

context("User interface")

# Dimensions
n_rows <- 100
n_cols_X <- 4
n_cols_y <- 3
X_names <- c('aa', 'bb', 'cc', 'dd')
y_names <- c('a', 'b', 'c')
NN_dims <- c(10, 10)
AE_dims <- c(10, 2, 10)
n_elem_X <- n_cols_X * n_rows
n_elem_y <- n_cols_y * n_rows

# Generate random data
X <- matrix(runif(n = n_elem_X), nrow = n_rows, ncol = n_cols_X)
colnames(X) <- X_names
y_regr <- matrix(runif(n = n_elem_y), nrow = n_rows, ncol = n_cols_y)
colnames(y_regr) <- y_names
y_class <- sample(y_names, size = n_rows, replace = TRUE)

# Construct ANN2 objects
NN_regr <- neuralnetwork(X = X, 
                         y = y_regr,
                         hidden.layers = NN_dims,
                         regression = TRUE,
                         loss.type = 'squared',
                         val.prop = 0,
                         verbose = FALSE)

NN_class <- neuralnetwork(X = X, 
                          y = y_class,
                          hidden.layers = NN_dims,
                          val.prop = 0,
                          verbose = FALSE)

AE <- autoencoder(X = X, 
                  hidden.layers = AE_dims,
                  val.prop = 0,
                  verbose = FALSE)


test_that("the neuralnetwork() function works correctly",
{
  expect_s3_class(NN_regr, 'ANN')
  expect_s3_class(NN_class, 'ANN')
  expect_s4_class(NN_regr$Rcpp_ANN, 'Rcpp_ANN')
  expect_s4_class(NN_class$Rcpp_ANN, 'Rcpp_ANN')
  
  # Test meta data for regression
  meta <- NN_regr$Rcpp_ANN$getMeta()
  expect_false( meta$no_hidden )
  expect_false( meta$autoencoder )
  expect_true( meta$regression )
  expect_equal( meta$n_hidden, length(NN_dims) )
  expect_equal( meta$n_in, n_cols_X )
  expect_equal( meta$n_out, n_cols_y )
  expect_equal( meta$y_names, y_names )
  expect_equal( meta$num_nodes, c(n_cols_X, NN_dims, n_cols_y) )
  
  # Test meta data for classification
  meta <- NN_class$Rcpp_ANN$getMeta()
  expect_false( meta$no_hidden )
  expect_false( meta$autoencoder )
  expect_false( meta$regression )
  expect_equal( meta$n_hidden, length(NN_dims) )
  expect_equal( meta$n_in, n_cols_X )
  expect_equal( meta$n_out, n_cols_y )
  expect_equal( meta$y_names, y_names )
  expect_equal( meta$num_nodes, c(n_cols_X, NN_dims, n_cols_y) )
  
  # Test set.seed
  NN_class_1 <- neuralnetwork(X = X, 
                              y = y_class,
                              hidden.layers = NN_dims,
                              val.prop = 0,
                              verbose = FALSE)
  NN_class_2 <- neuralnetwork(X = X, 
                              y = y_class,
                              hidden.layers = NN_dims,
                              val.prop = 0,
                              verbose = FALSE, 
                              random.seed = 42)
  NN_class_3 <- neuralnetwork(X = X, 
                              y = y_class,
                              hidden.layers = NN_dims,
                              val.prop = 0,
                              verbose = FALSE, 
                              random.seed = 42)
  p1 <- NN_class_1$Rcpp_ANN$getParams()
  p2 <- NN_class_2$Rcpp_ANN$getParams()
  p3 <- NN_class_3$Rcpp_ANN$getParams()
  expect_false(isTRUE(all.equal(p1, p2)))
  expect_false(isTRUE(all.equal(p1, p3)))
  expect_identical(p2, p3)
})

test_that("the autoencoder() function works correctly",
{
  expect_s3_class(AE, 'ANN')
  expect_s4_class(AE$Rcpp_ANN, 'Rcpp_ANN')
  
  # Test meta data
  meta <- AE$Rcpp_ANN$getMeta()
  expect_false( meta$no_hidden )
  expect_true( meta$autoencoder )
  expect_true( meta$regression )
  expect_equal( meta$n_hidden, length(AE_dims) )
  expect_equal( meta$n_in, n_cols_X )
  expect_equal( meta$n_out, n_cols_X )
  expect_equal( meta$y_names, X_names )
  expect_equal( meta$num_nodes, c(n_cols_X, AE_dims, n_cols_X) )
  
})
  
test_that("the predict() function works correctly",
{
  y_regr_pred <- predict(NN_regr, X)
  y_class_pred <- predict(NN_class, X)
  ae_pred <- predict(AE, X)
  
  # Check predictions for regressions
  expect_identical(names(y_regr_pred), c('predictions'))
  expect_identical(colnames(y_regr_pred$predictions), y_names)
  expect_equal(NROW(y_regr_pred$predictions), n_rows)
  expect_equal(NCOL(y_regr_pred$predictions), n_cols_y)
  expect_true( !any(is.na(y_regr_pred$predictions)) )
  
  # Check predictions for classification
  expect_identical(names(y_class_pred), c('predictions', 'probabilities'))
  expect_identical(colnames(y_class_pred$probabilities), paste0('class_', y_names))
  expect_identical(sort(unique(y_class_pred$predictions)), y_names)
  expect_equal(NROW(y_class_pred$predictions), n_rows)
  expect_equal(NCOL(y_class_pred$predictions), 1)
  expect_equal(NROW(y_class_pred$probabilities), n_rows)
  expect_equal(NCOL(y_class_pred$probabilities), n_cols_y)
  expect_equal( rowSums(y_class_pred$probabilities), rep(1, n_rows))
  expect_true( !any(is.na(y_class_pred$predictions)) )
  expect_true( !any(is.na(y_class_pred$probabilities)) )
  
  # Check predictions for autoencoder
  expect_identical(names(ae_pred), c('predictions'))
  expect_identical(colnames(ae_pred$predictions), X_names)
  expect_equal(NROW(ae_pred$predictions), n_rows)
  expect_equal(NCOL(ae_pred$predictions), n_cols_X)
  expect_true( !any(is.na(ae_pred$predictions)) )
  
})

test_that("the train() function works correctly",
{
  n_epoch <- 25
  
  # Classification
  epoch_nn_class_before <- NN_class$Rcpp_ANN$getTrainHistory()$n_epoch
  train(NN_class, X, y_class, val.prop = 0, n.epochs = n_epoch)
  epoch_nn_class_after <- NN_class$Rcpp_ANN$getTrainHistory()$n_epoch
  expect_equal( epoch_nn_class_after - epoch_nn_class_before, n_epoch )
  
  # Regression
  epoch_nn_regr_before <- NN_regr$Rcpp_ANN$getTrainHistory()$n_epoch
  train(NN_regr, X, y_regr, val.prop = 0, n.epochs = n_epoch)
  epoch_nn_regr_after <- NN_regr$Rcpp_ANN$getTrainHistory()$n_epoch
  expect_equal( epoch_nn_regr_after - epoch_nn_regr_before, n_epoch )
  
  # Autoencoder
  epoch_ae_before <- AE$Rcpp_ANN$getTrainHistory()$n_epoch
  train(AE, X, val.prop = 0, n.epochs = n_epoch)
  epoch_ae_after <- AE$Rcpp_ANN$getTrainHistory()$n_epoch
  expect_equal( epoch_ae_after - epoch_ae_before, n_epoch )
  
})

test_that("the reconstruct() function works correctly",
{
  expect_error(reconstruct(NN_class, X))
  expect_error(reconstruct(NN_regr, X))
  
  X_recr <- reconstruct(AE, X)
  expect_equal( length(X_recr$anomaly_scores), n_rows )
  expect_equal( dim(X_recr$reconstructed), dim(X) )
  expect_equal( colnames(X_recr$reconstructed), X_names )
})

# Needed for encode() / decode() tests
X_enc <- encode(AE, X)
X_dec <- decode(AE, X_enc)

callAE <- function(hidden_layers) {
  AE_ambig <- autoencoder(X = X, 
                          hidden.layers = hidden_layers, 
                          verbose = FALSE, 
                          val.prop = 0)
}

test_that("the encode() function works correctly",
{
  expect_equal( dim(X_enc), c(n_rows, AE_dims[2]) )
  expect_equal( colnames(X_enc), paste0('node_', 1:AE_dims[2]) )
  expect_error( encode(AE, X[,1:3]) ) # Incorrect data dimensions
  
  # Check for error when compression layer is ambiguous
  expect_error( encode( callAE( c(3,3,3) ), X ) )
  expect_error( encode( callAE( c(3,2,2) ), X ) )
})

test_that("the decode() function works correctly",
{
  expect_equal( dim(X_dec), dim(X) )
  expect_equal( colnames(X_dec), X_names )
  expect_error( decode(AE, X_enc[,1]) ) # Incorrect data dimensions
  
  # Check for error when compression layer is ambiguous
  expect_error( decode( callAE( c(3,3,3) ), X_enc ) )
  expect_error( decode( callAE( c(3,2,2) ), X_enc ) )
  
  expect_identical( X_dec, reconstruct(AE, X)$reconstructed )
})

Try the ANN2 package in your browser

Any scripts or data that you put into this service are public.

ANN2 documentation built on Dec. 1, 2020, 5:08 p.m.