diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c973a6650d..698d06aecd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,13 +8,31 @@ on: - master release: types: [published, created, edited] +name: R CMD check mlpack jobs: + cancel: + name: 'Cancel Previous Builds' + if: ${{ github.event_name == 'pull_request' && github.repository == 'mlpack/mlpack' }} + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - name: Get all workflow ids and set to env variable + run: echo ::set-env name=WORKFLOW_IDS_TO_CANCEL::$(curl https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/workflows -s | jq -r '.workflows | map(.id|tostring) | join(",")') + + - uses: styfle/cancel-workflow-action@0.5.0 + with: + workflow_id: ${{ env.WORKFLOW_IDS_TO_CANCEL }} + access_token: ${{ secrets.GITHUB_TOKEN }} + jobR: - name: mlpack-R + name: Build mlpack_r_tarball + if: ${{ github.repository == 'mlpack/mlpack' }} runs-on: ubuntu-20.04 + outputs: r_bindings: ${{ steps.mlpack_version.outputs.mlpack_r_package }} + steps: - uses: actions/checkout@v2 @@ -27,6 +45,23 @@ jobs: MLPACK_VERSION_VALUE=${MLPACK_VERSION_MAJOR}.${MLPACK_VERSION_MINOR}.${MLPACK_VERSION_PATCH} echo ::set-output name=mlpack_r_package::$(echo mlpack_"$MLPACK_VERSION_VALUE".tar.gz) + - uses: r-lib/actions/setup-r@master + with: + r-version: release + + - name: Query dependencies + run: | + cp src/mlpack/bindings/R/mlpack/DESCRIPTION.in DESCRIPTION + Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps(dependencies = TRUE), 'depends.Rds')" + + - name: Cache R packages + if: runner.os != 'Windows' + uses: actions/cache@v1 + with: + path: ${{ env.R_LIBS_USER }} + key: ${{ runner.os }}-r-release-${{ hashFiles('depends.Rds') }} + restore-keys: ${{ runner.os }}-r-release- + - name: Install Build Dependencies run: | sudo apt-get update @@ -38,6 +73,12 @@ jobs: sudo apt-get install -y r-base-core sudo Rscript -e "install.packages(c('Rcpp', 'RcppArmadillo', 'RcppEnsmallen', 'BH', 'roxygen2', 'testthat', 'Rcereal'))" + - name: Install R-bindings dependencies + run: | + remotes::install_deps(dependencies = TRUE) + remotes::install_cran("roxygen2") + shell: Rscript {0} + - name: CMake run: | mkdir build @@ -58,6 +99,7 @@ jobs: runs-on: ${{ matrix.config.os }} name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + if: ${{ github.repository == 'mlpack/mlpack' }} strategy: fail-fast: false @@ -74,6 +116,8 @@ jobs: R_CHECK_ARGS: "--no-build-vignettes" _R_CHECK_FORCE_SUGGESTS: 0 R_REMOTES_NO_ERRORS_FROM_WARNINGS: true + RSPM: ${{ matrix.config.rspm }} + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/download-artifact@v2 @@ -86,10 +130,24 @@ jobs: - uses: r-lib/actions/setup-pandoc@master + - name: Query dependencies + run: Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE), 'depends.Rds')" + + - name: Cache R packages + if: runner.os != 'Windows' + uses: actions/cache@v1 + with: + path: ${{ env.R_LIBS_USER }} + key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('depends.Rds') }} + restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}- + - name: Install dependencies run: | Rscript -e "install.packages('remotes')" -e "remotes::install_cran('rcmdcheck')" Rscript -e "install.packages(c('Rcpp', 'RcppArmadillo', 'RcppEnsmallen', 'BH', 'roxygen2', 'testthat', 'Rcereal'))" + remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) + remotes::install_cran("rcmdcheck") + shell: Rscript {0} - name: Check run: Rscript -e "rcmdcheck::rcmdcheck('${{ needs.jobR.outputs.r_bindings }}', args = c('--no-manual','--as-cran'), error_on = 'warning', check_dir = 'check')" diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 0613e4ed15..7368556d59 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -132,7 +132,9 @@ Copyright: Copyright 2020, Lakshya Ojha Copyright 2020, Bisakh Mondal Copyright 2020, Benson Muite - Copyright 2020, Sarthak Bhardwaj <7sarthakbhardwaj@gmail.com> + Copyright 2020, Sarthak Bhardwaj <7sarthakbhardwaj@gmail.com> + Copyright 2020, Aakash Kaushik + Copyright 2020, Anush Kini License: BSD-3-clause All rights reserved. diff --git a/HISTORY.md b/HISTORY.md index d7a2437e9e..5acdedcb4f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,8 @@ ###### ????-??-?? * Added Mean Absolute Percentage Error. + * Added Softmin activation function as layer in ann/layer. + ### mlpack 3.4.1 ###### 2020-09-07 * Fix incorrect parsing of required matrix/model parameters for command-line diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index 34ea03c6a7..b4726b0c6f 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -116,6 +116,8 @@ set(SOURCES celu_impl.hpp softshrink.hpp softshrink_impl.hpp + softmin.hpp + softmin_impl.hpp ) # Add directory name to sources. diff --git a/src/mlpack/methods/ann/layer/add.hpp b/src/mlpack/methods/ann/layer/add.hpp index 7963d33d05..5fd498e704 100644 --- a/src/mlpack/methods/ann/layer/add.hpp +++ b/src/mlpack/methods/ann/layer/add.hpp @@ -100,6 +100,9 @@ class Add //! Get the output size. size_t OutputSize() const { return outSize; } + //! Get the size of weights. + size_t WeightSize() const { return outSize; } + /** * Serialize the layer */ diff --git a/src/mlpack/methods/ann/layer/atrous_convolution.hpp b/src/mlpack/methods/ann/layer/atrous_convolution.hpp index ec6b3cfb69..478f62abe2 100644 --- a/src/mlpack/methods/ann/layer/atrous_convolution.hpp +++ b/src/mlpack/methods/ann/layer/atrous_convolution.hpp @@ -257,6 +257,12 @@ class AtrousConvolution //! Modify the internal Padding layer. ann::Padding<>& Padding() { return padding; } + //! Get size of the weight matrix. + size_t WeightSize() const + { + return (outSize * inSize * kernelWidth * kernelHeight) + outSize; + } + /** * Serialize the layer. */ diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index d005d1eb42..947395fd6b 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -66,6 +66,7 @@ #include "sequential.hpp" #include "softshrink.hpp" #include "softmax.hpp" +#include "softmin.hpp" #include "spatial_dropout.hpp" #include "subview.hpp" #include "transposed_convolution.hpp" diff --git a/src/mlpack/methods/ann/layer/linear.hpp b/src/mlpack/methods/ann/layer/linear.hpp index 6fe8087685..f2c8015e04 100644 --- a/src/mlpack/methods/ann/layer/linear.hpp +++ b/src/mlpack/methods/ann/layer/linear.hpp @@ -146,6 +146,12 @@ class Linear //! Modify the bias weights of the layer. OutputDataType& Bias() { return bias; } + //! Get the size of the weights. + size_t WeightSize() const + { + return (inSize * outSize) + outSize; + } + /** * Serialize the layer */ diff --git a/src/mlpack/methods/ann/layer/softmin.hpp b/src/mlpack/methods/ann/layer/softmin.hpp new file mode 100644 index 0000000000..a7b882c942 --- /dev/null +++ b/src/mlpack/methods/ann/layer/softmin.hpp @@ -0,0 +1,97 @@ +/** + * @file methods/ann/layer/softmin.hpp + * @author Aakash Kaushik + * + * Definition of the Softmin class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MLPACK_METHODS_ANN_LAYER_SOFTMIN_HPP +#define MLPACK_METHODS_ANN_LAYER_SOFTMIN_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Implementation of the Softmin layer. The Softmin function takes as a input + * a vector of K real numbers, rescaling them so that the elements of the + * K-dimensional output vector lie in the range [0, 1] and sum to 1. + * + * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + * @tparam OutputDataType Type of the output data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + */ +template < + typename InputDataType = arma::mat, + typename OutputDataType = arma::mat +> +class Softmin +{ + public: + /** + * Create the Softmin object. + */ + Softmin(); + + /** + * Ordinary feed forward pass of a neural network, evaluating the function + * f(x) by propagating the activity forward through f. + * + * @param input Input data used for evaluating the specified function. + * @param output Resulting output activation. + */ + template + void Forward(const InputType& input, OutputType& output); + + /** + * Ordinary feed backward pass of a neural network, calculating the function + * f(x) by propagating x backwards through f. Using the results from the feed + * forward pass. + * + * @param input The propagated input activation. + * @param gy The backpropagated error. + * @param g The calculated gradient. + */ + template + void Backward(const arma::Mat& input, + const arma::Mat& gy, + arma::Mat& g); + + //! Get the output parameter. + OutputDataType& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the delta. + InputDataType& Delta() const { return delta; } + //! Modify the delta. + InputDataType& Delta() { return delta; } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& /* ar */, const unsigned int /* version */); + + private: + //! Locally-stored delta object. + OutputDataType delta; + + //! Locally stored output parameter object. + OutputDataType outputParameter; +}; // class Softmin + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "softmin_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/softmin_impl.hpp b/src/mlpack/methods/ann/layer/softmin_impl.hpp new file mode 100644 index 0000000000..7693ca11dd --- /dev/null +++ b/src/mlpack/methods/ann/layer/softmin_impl.hpp @@ -0,0 +1,61 @@ +/** + * @file methods/ann/layer/softmin_impl.hpp + * @author Aakash Kaushik + * + * Implementation of the Softmin class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_METHODS_ANN_LAYER_SOFTMIN_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_SOFTMIN_IMPL_HPP + +// In case it hasn't yet been included. +#include "softmin.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +template +Softmin::Softmin() +{ + // Nothing to do here. +} + +template +template +void Softmin::Forward( + const InputType& input, + OutputType& output) +{ + InputType inputMin = arma::repmat(arma::min(input,0), input.n_rows, 1); + output = arma::repmat(arma::log(arma::sum( + arma::exp(-(input - inputMin)),0)), input.n_rows, 1); + output = arma::exp(-(input - inputMin) - output); +} + +template +template +void Softmin::Backward( + const arma::Mat& input, + const arma::Mat& gy, + arma::Mat& g) +{ + g = input % (gy - arma::repmat(arma::sum(gy % input), input.n_rows, 1)); +} + +template +template +void Softmin::serialize( + Archive& /* ar */, + const unsigned int /* version */) +{ + // Nothing to do here. +} + +} // namespace ann +} // namespace mlpack + +#endif diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index c9aa63ca03..560e017d21 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -1,6 +1,5 @@ # mlpack test executable. add_executable(mlpack_test - arma_extend_test.cpp async_learning_test.cpp augmented_rnns_tasks_test.cpp callback_test.cpp @@ -8,7 +7,6 @@ add_executable(mlpack_test cli_binding_test.cpp io_test.cpp cosine_tree_test.cpp - dbscan_test.cpp dcgan_test.cpp det_test.cpp distribution_test.cpp @@ -34,12 +32,10 @@ add_executable(mlpack_test local_coordinate_coding_test.cpp log_test.cpp logistic_regression_test.cpp - loss_functions_test.cpp lsh_test.cpp math_test.cpp matrix_completion_test.cpp maximal_inputs_test.cpp - mean_shift_test.cpp metric_test.cpp mlpack_test.cpp mock_categorical_data.hpp @@ -47,14 +43,12 @@ add_executable(mlpack_test nmf_test.cpp nystroem_method_test.cpp octree_test.cpp - pca_test.cpp perceptron_test.cpp prefixedoutstream_test.cpp python_binding_test.cpp q_learning_test.cpp qdafn_test.cpp radical_test.cpp - random_forest_test.cpp random_test.cpp range_search_test.cpp rectangle_tree_test.cpp @@ -80,7 +74,6 @@ add_executable(mlpack_test wgan_mnist_test.cpp wgan_gp_mnist_test.cpp main_tests/cf_test.cpp - main_tests/dbscan_test.cpp main_tests/det_test.cpp main_tests/emst_test.cpp main_tests/fastmks_test.cpp @@ -100,13 +93,10 @@ add_executable(mlpack_test main_tests/local_coordinate_coding_test.cpp main_tests/logistic_regression_test.cpp main_tests/lsh_test.cpp - main_tests/mean_shift_test.cpp main_tests/nbc_test.cpp main_tests/nmf_test.cpp - main_tests/pca_test.cpp main_tests/perceptron_test.cpp main_tests/radical_test.cpp - main_tests/random_forest_test.cpp main_tests/range_search_test.cpp main_tests/test_helper.hpp ) @@ -122,6 +112,7 @@ add_executable(mlpack_catch_test ann_test_tools.hpp ann_visitor_test.cpp armadillo_svd_test.cpp + arma_extend_test.cpp bayesian_linear_regression_test.cpp bias_svd_test.cpp binarize_test.cpp @@ -129,6 +120,7 @@ add_executable(mlpack_catch_test convolutional_network_test.cpp convolution_test.cpp cv_test.cpp + dbscan_test.cpp decision_stump_test.cpp decision_tree_test.cpp feedforward_network_test.cpp @@ -143,10 +135,14 @@ add_executable(mlpack_catch_test knn_test.cpp linear_regression_test.cpp load_save_test.cpp + loss_functions_test.cpp main.cpp + mean_shift_test.cpp nca_test.cpp one_hot_encoding_test.cpp + pca_test.cpp quic_svd_test.cpp + random_forest_test.cpp randomized_svd_test.cpp rbm_network_test.cpp recurrent_network_test.cpp @@ -166,6 +162,7 @@ add_executable(mlpack_catch_test main_tests/adaboost_test.cpp main_tests/approx_kfn_test.cpp main_tests/bayesian_linear_regression_test.cpp + main_tests/dbscan_test.cpp main_tests/decision_stump_test.cpp main_tests/decision_tree_test.cpp main_tests/image_converter_test.cpp @@ -174,12 +171,15 @@ add_executable(mlpack_catch_test main_tests/kmeans_test.cpp main_tests/knn_test.cpp main_tests/linear_regression_test.cpp + main_tests/mean_shift_test.cpp main_tests/nca_test.cpp + main_tests/pca_test.cpp main_tests/preprocess_binarize_test.cpp main_tests/preprocess_imputer_test.cpp main_tests/preprocess_one_hot_encode_test.cpp main_tests/preprocess_scale_test.cpp main_tests/preprocess_split_test.cpp + main_tests/random_forest_test.cpp main_tests/softmax_regression_test.cpp main_tests/sparse_coding_test.cpp main_tests/test_helper.hpp @@ -276,4 +276,3 @@ add_test(NAME "catch_test" COMMAND mlpack_catch_test WORKING_DIRECTORY ${CMAKE_B # Use RUN_SERIAL for long running parallel tests set_tests_properties(${parallel_tests} PROPERTIES RUN_SERIAL TRUE) - diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 2c1fe63398..9ee1ebcaf9 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -558,6 +558,58 @@ void CheckCELUDerivativeCorrect(const arma::colvec input, } } +/** + * Implementation of the Softmin activation function test. The function is + * implemented as Softmin layer in the file softmin.hpp. + * + * @param input Input data used for evaluating the Softmin activation function. + * @param target Target data used to evaluate the Softmin activation. + */ +void CheckSoftminActivationCorrect(const arma::colvec input, + const arma::colvec target) +{ + // Initialize Softmin object. + Softmin<> softmin; + + // Test the activation function using the entire vector as input. + arma::colvec activations; + softmin.Forward(input,activations); + for (size_t i = 0; i < activations.n_elem; ++i) + { + REQUIRE(activations.at(i) == Approx(target.at(i)).epsilon(1e-5)); + } +} + +/** + * Implementation of the Softmin activation function derivative test. + * The function is implemented as Softmin layer in the file softmin.hpp. + * + * @param input Input data used for evaluating the Softmin activation function. + * @param target Target data used to evaluate the Softmin activation. + */ +void CheckSoftminDerivativeCorrect(const arma::colvec input, + const arma::colvec target) +{ + // Initialize Softmin object. + Softmin<> softmin; + + // Test the calculation of the derivatives using the entire vector as input. + arma::colvec derivatives, activations; + + // This error vector will be set to [[1.0],[0.0],[1.0],[0.0]] + // to get the derivatives. + arma::colvec error = arma::ones(input.n_elem); + error(1) = 0.0; + error(3) = 0.0; + softmin.Forward(input, activations); + softmin.Backward(activations, error, derivatives); + for (size_t i = 0; i < derivatives.n_elem; ++i) + { + REQUIRE(derivatives.at(i) == Approx(target.at(i)).epsilon(1e-5)); + } + +} + /** * Basic test of the tanh function. */ @@ -1063,3 +1115,23 @@ TEST_CASE("GaussianFunctionTest", "[ActivationFunctionsTest]") CheckDerivativeCorrect(desiredActivations, desiredDerivatives); } + +/** + * Basic test of the Softmin function. + */ +TEST_CASE("SoftminFunctionTest", "[ActivationFunctionsTest]") +{ + const arma::colvec activationData("4.2 2.4 7.0 6.4"); + + // Hand-calculated Values. + const arma::colvec desiredActivations("0.1384799751 0.8377550303 \ + 0.008420976 0.0153440186"); + + const arma::colvec desiredDerivatives("0.1181371351 -0.12306701070 \ + 0.0071839266 -0.0022540509"); + + CheckSoftminActivationCorrect(activationData, + desiredActivations); + CheckSoftminDerivativeCorrect(activationData, + desiredDerivatives); +} diff --git a/src/mlpack/tests/ann_visitor_test.cpp b/src/mlpack/tests/ann_visitor_test.cpp index 1b01308ff3..ccf3cca35f 100644 --- a/src/mlpack/tests/ann_visitor_test.cpp +++ b/src/mlpack/tests/ann_visitor_test.cpp @@ -52,3 +52,37 @@ TEST_CASE("BiasSetVisitorTest", "[ANNVisitorTest]") boost::apply_visitor(DeleteVisitor(), linear); } + +/** + * Test that WeightSetVisitor works properly. + */ +TEST_CASE("WeightSetVisitorTest", "[ANNVisitorTest]") +{ + size_t randomSize = arma::randi(arma::distr_param(1, 100)); + + LayerTypes<> linear = new Linear<>(randomSize, randomSize); + + arma::mat layerWeights(randomSize * randomSize + randomSize, 1); + layerWeights.zeros(); + + size_t setWeights = boost::apply_visitor(WeightSetVisitor(layerWeights, 0), + linear); + + REQUIRE(setWeights == randomSize * randomSize + randomSize); +} + +/** + * Test that WeightSizeVisitor works properly. + */ +TEST_CASE("WeightSizeVisitorTest", "[ANNVisitorTest]") +{ + size_t randomSize = arma::randi(arma::distr_param(1, 100)); + + LayerTypes<> linear = new Linear<>(randomSize, randomSize); + + size_t weightSize = boost::apply_visitor(WeightSizeVisitor(), + linear); + + REQUIRE(weightSize == randomSize * randomSize + randomSize); +} + diff --git a/src/mlpack/tests/arma_extend_test.cpp b/src/mlpack/tests/arma_extend_test.cpp index e6fe005c80..34adaa2b29 100644 --- a/src/mlpack/tests/arma_extend_test.cpp +++ b/src/mlpack/tests/arma_extend_test.cpp @@ -11,18 +11,17 @@ */ #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace arma; -BOOST_AUTO_TEST_SUITE(ArmaExtendTest); /** * Test const_row_col_iterator for basic functionality. */ -BOOST_AUTO_TEST_CASE(ConstRowColIteratorTest) +TEST_CASE("ConstRowColIteratorTest", "[ArmaExtendTest]") { mat X; X.zeros(5, 5); @@ -39,15 +38,15 @@ BOOST_AUTO_TEST_CASE(ConstRowColIteratorTest) for (it = X.begin_row_col(); it != X.end_row_col(); ++it) { // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); ++count; } - BOOST_REQUIRE_EQUAL(count, 25); + REQUIRE(count == 25); it = X.end_row_col(); do { @@ -55,20 +54,20 @@ BOOST_AUTO_TEST_CASE(ConstRowColIteratorTest) --count; // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); } while (it != X.begin_row_col()); - BOOST_REQUIRE_EQUAL(count, 0); + REQUIRE(count == 0); } /** * Test row_col_iterator for basic functionality. */ -BOOST_AUTO_TEST_CASE(RowColIteratorTest) +TEST_CASE("RowColIteratorTest", "[ArmaExtendTest]") { mat X; X.zeros(5, 5); @@ -85,15 +84,15 @@ BOOST_AUTO_TEST_CASE(RowColIteratorTest) for (it = X.begin_row_col(); it != X.end_row_col(); ++it) { // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); ++count; } - BOOST_REQUIRE_EQUAL(count, 25); + REQUIRE(count == 25); it = X.end_row_col(); do { @@ -101,20 +100,20 @@ BOOST_AUTO_TEST_CASE(RowColIteratorTest) --count; // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); } while (it != X.begin_row_col()); - BOOST_REQUIRE_EQUAL(count, 0); + REQUIRE(count == 0); } /** * Operator-- test for mat::row_col_iterator and mat::const_row_col_iterator */ -BOOST_AUTO_TEST_CASE(MatRowColIteratorDecrementOperatorTest) +TEST_CASE("MatRowColIteratorDecrementOperatorTest", "[ArmaExtendTest]") { mat test = ones(5, 5); @@ -124,14 +123,14 @@ BOOST_AUTO_TEST_CASE(MatRowColIteratorDecrementOperatorTest) // Check that postfix-- does not decrement the position when position is // pointing to the beginning. auto junk = it2--; (void)(junk); - BOOST_REQUIRE_EQUAL(it1.row(), it2.row()); - BOOST_REQUIRE_EQUAL(it1.col(), it2.col()); + REQUIRE(it1.row() == it2.row()); + REQUIRE(it1.col() == it2.col()); // Check that prefix-- does not decrement the position when position is // pointing to the beginning. --it2; - BOOST_REQUIRE_EQUAL(it1.row(), it2.row()); - BOOST_REQUIRE_EQUAL(it1.col(), it2.col()); + REQUIRE(it1.row() == it2.row()); + REQUIRE(it1.col() == it2.col()); } // These tests don't work when the sparse iterators hold references and not @@ -140,7 +139,7 @@ BOOST_AUTO_TEST_CASE(MatRowColIteratorDecrementOperatorTest) /** * Test sparse const_row_col_iterator for basic functionality. */ -BOOST_AUTO_TEST_CASE(ConstSpRowColIteratorTest) +TEST_CASE("ConstSpRowColIteratorTest", "[ArmaExtendTest]") { sp_mat X(5, 5); for (size_t i = 0; i < 5; ++i) @@ -156,15 +155,15 @@ BOOST_AUTO_TEST_CASE(ConstSpRowColIteratorTest) for (it = X.begin_row_col(); it != X.end_row_col(); ++it) { // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == (count % 5) * 3 + (count / 5)); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); ++count; } - BOOST_REQUIRE_EQUAL(count, 25); + REQUIRE(count == 25); it = X.end_row_col(); do { @@ -172,20 +171,20 @@ BOOST_AUTO_TEST_CASE(ConstSpRowColIteratorTest) --count; // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); } while (it != X.begin_row_col()); - BOOST_REQUIRE_EQUAL(count, 1); + REQUIRE(count == 1); } /** * Test sparse row_col_iterator for basic functionality. */ -BOOST_AUTO_TEST_CASE(SpRowColIteratorTest) +TEST_CASE("SpRowColIteratorTest", "[ArmaExtendTest]") { sp_mat X(5, 5); for (size_t i = 0; i < 5; ++i) @@ -201,15 +200,15 @@ BOOST_AUTO_TEST_CASE(SpRowColIteratorTest) for (it = X.begin_row_col(); it != X.end_row_col(); ++it) { // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); ++count; } - BOOST_REQUIRE_EQUAL(count, 25); + REQUIRE(count == 25); it = X.end_row_col(); do { @@ -217,14 +216,12 @@ BOOST_AUTO_TEST_CASE(SpRowColIteratorTest) --count; // Check iterator value. - BOOST_REQUIRE_EQUAL(*it, (count % 5) * 3 + (count / 5)); + REQUIRE(*it == ((count % 5) * 3 + (count / 5))); // Check iterator position. - BOOST_REQUIRE_EQUAL(it.row(), count % 5); - BOOST_REQUIRE_EQUAL(it.col(), count / 5); + REQUIRE(it.row() == count % 5); + REQUIRE(it.col() == count / 5); } while (it != X.begin_row_col()); - BOOST_REQUIRE_EQUAL(count, 1); + REQUIRE(count == 1); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/dbscan_test.cpp b/src/mlpack/tests/dbscan_test.cpp index 1e385773db..81ea97edc3 100644 --- a/src/mlpack/tests/dbscan_test.cpp +++ b/src/mlpack/tests/dbscan_test.cpp @@ -13,17 +13,15 @@ #include #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::range; using namespace mlpack::dbscan; using namespace mlpack::distribution; -BOOST_AUTO_TEST_SUITE(DBSCANTest); - -BOOST_AUTO_TEST_CASE(OneClusterTest) +TEST_CASE("OneClusterTest", "[DBSCANTest]") { // Make sure that if we have points in the unit box, and if we set epsilon // large enough, all points end up as in one cluster. @@ -34,16 +32,16 @@ BOOST_AUTO_TEST_CASE(OneClusterTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_EQUAL(clusters, 1); - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); + REQUIRE(clusters == 1); + REQUIRE(assignments.n_elem == points.n_cols); for (size_t i = 0; i < assignments.n_elem; ++i) - BOOST_REQUIRE_EQUAL(assignments[i], 0); + REQUIRE(assignments[i] == 0); } /** * When epsilon is small enough, every point returned should be noise. */ -BOOST_AUTO_TEST_CASE(TinyEpsilonTest) +TEST_CASE("TinyEpsilonTest", "[DBSCANTest]") { arma::mat points(10, 200, arma::fill::randu); @@ -52,16 +50,16 @@ BOOST_AUTO_TEST_CASE(TinyEpsilonTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_EQUAL(clusters, 0); - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); + REQUIRE(clusters == 0); + REQUIRE(assignments.n_elem == points.n_cols); for (size_t i = 0; i < assignments.n_elem; ++i) - BOOST_REQUIRE_EQUAL(assignments[i], SIZE_MAX); + REQUIRE(assignments[i] == SIZE_MAX); } /** * Check that outliers are properly labeled as noise. */ -BOOST_AUTO_TEST_CASE(OutlierTest) +TEST_CASE("OutlierTest", "[DBSCANTest]") { arma::mat points(2, 200, arma::fill::randu); @@ -75,17 +73,17 @@ BOOST_AUTO_TEST_CASE(OutlierTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_GT(clusters, 0); - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); - BOOST_REQUIRE_EQUAL(assignments[15], SIZE_MAX); - BOOST_REQUIRE_EQUAL(assignments[45], SIZE_MAX); - BOOST_REQUIRE_EQUAL(assignments[101], SIZE_MAX); + REQUIRE(clusters > 0); + REQUIRE(assignments.n_elem == points.n_cols); + REQUIRE(assignments[15] == SIZE_MAX); + REQUIRE(assignments[45] == SIZE_MAX); + REQUIRE(assignments[101] == SIZE_MAX); } /** * Check that the Gaussian clusters are correctly found. */ -BOOST_AUTO_TEST_CASE(GaussiansTest) +TEST_CASE("GaussiansTest", "[DBSCANTest]") { arma::mat points(3, 300); @@ -105,7 +103,7 @@ BOOST_AUTO_TEST_CASE(GaussiansTest) arma::Row assignments; arma::mat centroids; const size_t clusters = d.Cluster(points, assignments, centroids); - BOOST_REQUIRE_EQUAL(clusters, 3); + REQUIRE(clusters == 3); // Our centroids should be close to one of our Gaussians. arma::Row matches(3); @@ -120,35 +118,35 @@ BOOST_AUTO_TEST_CASE(GaussiansTest) matches(2) = j; } - BOOST_REQUIRE_NE(matches(0), matches(1)); - BOOST_REQUIRE_NE(matches(1), matches(2)); - BOOST_REQUIRE_NE(matches(2), matches(0)); + REQUIRE(matches(0) != matches(1)); + REQUIRE(matches(1) != matches(2)); + REQUIRE(matches(2) != matches(0)); - BOOST_REQUIRE_NE(matches(0), 3); - BOOST_REQUIRE_NE(matches(1), 3); - BOOST_REQUIRE_NE(matches(2), 3); + REQUIRE(matches(0) != 3); + REQUIRE(matches(1) != 3); + REQUIRE(matches(2) != 3); for (size_t i = 0; i < 100; ++i) { // Each point should either be noise or in cluster matches(0). - BOOST_REQUIRE_NE(assignments(i), matches(1)); - BOOST_REQUIRE_NE(assignments(i), matches(2)); + REQUIRE(assignments(i) != matches(1)); + REQUIRE(assignments(i) != matches(2)); } for (size_t i = 100; i < 200; ++i) { - BOOST_REQUIRE_NE(assignments(i), matches(0)); - BOOST_REQUIRE_NE(assignments(i), matches(2)); + REQUIRE(assignments(i) != matches(0)); + REQUIRE(assignments(i) != matches(2)); } for (size_t i = 200; i < 300; ++i) { - BOOST_REQUIRE_NE(assignments(i), matches(0)); - BOOST_REQUIRE_NE(assignments(i), matches(1)); + REQUIRE(assignments(i) != matches(0)); + REQUIRE(assignments(i) != matches(1)); } } -BOOST_AUTO_TEST_CASE(OneClusterSingleModeTest) +TEST_CASE("OneClusterSingleModeTest", "[DBSCANTest]") { // Make sure that if we have points in the unit box, and if we set epsilon // large enough, all points end up as in one cluster. @@ -159,16 +157,16 @@ BOOST_AUTO_TEST_CASE(OneClusterSingleModeTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_EQUAL(clusters, 1); - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); + REQUIRE(clusters == 1); + REQUIRE(assignments.n_elem == points.n_cols); for (size_t i = 0; i < assignments.n_elem; ++i) - BOOST_REQUIRE_EQUAL(assignments[i], 0); + REQUIRE(assignments[i] == 0); } /** * When epsilon is small enough, every point returned should be noise. */ -BOOST_AUTO_TEST_CASE(TinyEpsilonSingleModeTest) +TEST_CASE("TinyEpsilonSingleModeTest", "[DBSCANTest]") { arma::mat points(10, 200, arma::fill::randu); @@ -177,16 +175,16 @@ BOOST_AUTO_TEST_CASE(TinyEpsilonSingleModeTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_EQUAL(clusters, 0); - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); + REQUIRE(clusters == 0); + REQUIRE(assignments.n_elem == points.n_cols); for (size_t i = 0; i < assignments.n_elem; ++i) - BOOST_REQUIRE_EQUAL(assignments[i], SIZE_MAX); + REQUIRE(assignments[i] == SIZE_MAX); } /** * Check that outliers are properly labeled as noise. */ -BOOST_AUTO_TEST_CASE(OutlierSingleModeTest) +TEST_CASE("OutlierSingleModeTest", "[DBSCANTest]") { arma::mat points(2, 200, arma::fill::randu); @@ -200,17 +198,17 @@ BOOST_AUTO_TEST_CASE(OutlierSingleModeTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_GT(clusters, 0); - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); - BOOST_REQUIRE_EQUAL(assignments[15], SIZE_MAX); - BOOST_REQUIRE_EQUAL(assignments[45], SIZE_MAX); - BOOST_REQUIRE_EQUAL(assignments[101], SIZE_MAX); + REQUIRE(clusters > 0); + REQUIRE(assignments.n_elem == points.n_cols); + REQUIRE(assignments[15] == SIZE_MAX); + REQUIRE(assignments[45] == SIZE_MAX); + REQUIRE(assignments[101] == SIZE_MAX); } /** * Check that the Gaussian clusters are correctly found. */ -BOOST_AUTO_TEST_CASE(GaussiansSingleModeTest) +TEST_CASE("GaussiansSingleModeTest", "[DBSCANTest]") { arma::mat points(3, 300); @@ -230,7 +228,7 @@ BOOST_AUTO_TEST_CASE(GaussiansSingleModeTest) arma::Row assignments; arma::mat centroids; const size_t clusters = d.Cluster(points, assignments, centroids); - BOOST_REQUIRE_EQUAL(clusters, 3); + REQUIRE(clusters == 3); // Our centroids should be close to one of our Gaussians. arma::Row matches(3); @@ -245,38 +243,38 @@ BOOST_AUTO_TEST_CASE(GaussiansSingleModeTest) matches(2) = j; } - BOOST_REQUIRE_NE(matches(0), matches(1)); - BOOST_REQUIRE_NE(matches(1), matches(2)); - BOOST_REQUIRE_NE(matches(2), matches(0)); + REQUIRE(matches(0) != matches(1)); + REQUIRE(matches(1) != matches(2)); + REQUIRE(matches(2) != matches(0)); - BOOST_REQUIRE_NE(matches(0), 3); - BOOST_REQUIRE_NE(matches(1), 3); - BOOST_REQUIRE_NE(matches(2), 3); + REQUIRE(matches(0) != 3); + REQUIRE(matches(1) != 3); + REQUIRE(matches(2) != 3); for (size_t i = 0; i < 100; ++i) { // Each point should either be noise or in cluster matches(0). - BOOST_REQUIRE_NE(assignments(i), matches(1)); - BOOST_REQUIRE_NE(assignments(i), matches(2)); + REQUIRE(assignments(i) != matches(1)); + REQUIRE(assignments(i) != matches(2)); } for (size_t i = 100; i < 200; ++i) { - BOOST_REQUIRE_NE(assignments(i), matches(0)); - BOOST_REQUIRE_NE(assignments(i), matches(2)); + REQUIRE(assignments(i) != matches(0)); + REQUIRE(assignments(i) != matches(2)); } for (size_t i = 200; i < 300; ++i) { - BOOST_REQUIRE_NE(assignments(i), matches(0)); - BOOST_REQUIRE_NE(assignments(i), matches(1)); + REQUIRE(assignments(i) != matches(0)); + REQUIRE(assignments(i) != matches(1)); } } /** * Check that OrderedPointSelection works correctly. */ -BOOST_AUTO_TEST_CASE(OrderedPointSelectionTest) +TEST_CASE("OrderedPointSelectionTest", "[DBSCANTest]") { arma::mat points(10, 200, arma::fill::randu); @@ -285,16 +283,16 @@ BOOST_AUTO_TEST_CASE(OrderedPointSelectionTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_EQUAL(clusters, 1); + REQUIRE(clusters == 1); // The number of assignments returned should be the same as points. - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); + REQUIRE(assignments.n_elem == points.n_cols); } /** * Check that RandomPointSelection works correctly. */ -BOOST_AUTO_TEST_CASE(RandomPointSelectionTest) +TEST_CASE("RandomPointSelectionTest", "[DBSCANTest]") { arma::mat points(10, 200, arma::fill::randu); @@ -303,10 +301,8 @@ BOOST_AUTO_TEST_CASE(RandomPointSelectionTest) arma::Row assignments; const size_t clusters = d.Cluster(points, assignments); - BOOST_REQUIRE_EQUAL(clusters, 1); + REQUIRE(clusters == 1); // The number of assignments returned should be the same as points. - BOOST_REQUIRE_EQUAL(assignments.n_elem, points.n_cols); + REQUIRE(assignments.n_elem == points.n_cols); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/loss_functions_test.cpp b/src/mlpack/tests/loss_functions_test.cpp index 65996f205f..cb814d021e 100644 --- a/src/mlpack/tests/loss_functions_test.cpp +++ b/src/mlpack/tests/loss_functions_test.cpp @@ -36,19 +36,17 @@ #include #include -#include -#include "test_tools.hpp" +#include "catch.hpp" +#include "test_catch_tools.hpp" #include "ann_test_tools.hpp" using namespace mlpack; using namespace mlpack::ann; -BOOST_AUTO_TEST_SUITE(LossFunctionsTest); - /** * Simple Huber Loss test. */ -BOOST_AUTO_TEST_CASE(HuberLossTest) +TEST_CASE("HuberLossTest", "[LossFunctionsTest]") { arma::mat input, target, output; HuberLoss<> module; @@ -57,7 +55,7 @@ BOOST_AUTO_TEST_CASE(HuberLossTest) input = arma::mat("17.45 12.91 13.63 29.01 7.12 15.47 31.52 31.97"); target = arma::mat("16.52 13.11 13.67 29.51 24.31 15.03 30.72 34.07"); double loss = module.Forward(input, target); - BOOST_REQUIRE_CLOSE_FRACTION(loss, 2.410631, 0.00001); + REQUIRE(loss == Approx(2.410631).epsilon(1e-5)); // Test the backward function. module.Backward(input, target, output); @@ -66,16 +64,16 @@ BOOST_AUTO_TEST_CASE(HuberLossTest) // [0.1162 -0.0250 -0.0050 -0.0625 -0.1250 0.0550 0.1000 -0.1250] // Sum of Expected Output = -0.07125. double expectedOutputSum = arma::accu(output); - BOOST_REQUIRE_CLOSE_FRACTION(expectedOutputSum, -0.07125, 0.00001); + REQUIRE(expectedOutputSum == Approx(-0.07125).epsilon(1e-5)); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); } /** * Poisson Negative Log Likelihood Loss function test. */ -BOOST_AUTO_TEST_CASE(PoissonNLLLossTest) +TEST_CASE("PoissonNLLLossTest", "[LossFunctionsTest]") { arma::mat input, target, input4, target4; arma::mat output1, output2, output3, output4; @@ -98,10 +96,10 @@ BOOST_AUTO_TEST_CASE(PoissonNLLLossTest) double loss2 = module2.Forward(input, target); double loss3 = module3.Forward(input, target); double loss4 = module4.Forward(input4, target4); - BOOST_REQUIRE_CLOSE_FRACTION(loss1, 4.8986, 0.0001); - BOOST_REQUIRE_CLOSE_FRACTION(loss2, 45.4139, 0.0001); - BOOST_REQUIRE_CLOSE_FRACTION(loss3, 5.6767, 0.0001); - BOOST_REQUIRE_CLOSE_FRACTION(loss4, 3.742157, 0.0001); + REQUIRE(loss1 == Approx(4.8986).epsilon(1e-4)); + REQUIRE(loss2 == Approx(45.4139).epsilon(1e-4)); + REQUIRE(loss3 == Approx(5.6767).epsilon(1e-4)); + REQUIRE(loss4 == Approx(3.742157).epsilon(1e-4)); // Test the Backward function. module1.Backward(input, target, output1); @@ -118,31 +116,31 @@ BOOST_AUTO_TEST_CASE(PoissonNLLLossTest) expOutput4 = arma::mat("-0.064825 -0.716511 -0.062224 -0.680027 \ -0.087030 -9.386517 -0.329736 -0.202650"); - BOOST_REQUIRE_EQUAL(output1.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output1.n_cols, input.n_cols); + REQUIRE(output1.n_rows == input.n_rows); + REQUIRE(output1.n_cols == input.n_cols); - BOOST_REQUIRE_EQUAL(output2.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output2.n_cols, input.n_cols); + REQUIRE(output2.n_rows == input.n_rows); + REQUIRE(output2.n_cols == input.n_cols); - BOOST_REQUIRE_EQUAL(output3.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output3.n_cols, input.n_cols); + REQUIRE(output3.n_rows == input.n_rows); + REQUIRE(output3.n_cols == input.n_cols); - BOOST_REQUIRE_EQUAL(output4.n_rows, input4.n_rows); - BOOST_REQUIRE_EQUAL(output4.n_cols, input4.n_cols); + REQUIRE(output4.n_rows == input4.n_rows); + REQUIRE(output4.n_cols == input4.n_cols); for (size_t i = 0; i < expOutput1.n_elem; ++i) { - BOOST_REQUIRE_CLOSE_FRACTION(output1[i], expOutput1[i], 0.0001); - BOOST_REQUIRE_CLOSE_FRACTION(output2[i], expOutput2[i], 0.0001); - BOOST_REQUIRE_CLOSE_FRACTION(output3[i], expOutput3[i], 0.0001); - BOOST_REQUIRE_CLOSE_FRACTION(output4[i], expOutput4[i], 0.0001); + REQUIRE(output1[i] == Approx(expOutput1[i]).epsilon(1e-4)); + REQUIRE(output2[i] == Approx(expOutput2[i]).epsilon(1e-4)); + REQUIRE(output3[i] == Approx(expOutput3[i]).epsilon(1e-4)); + REQUIRE(output4[i] == Approx(expOutput4[i]).epsilon(1e-4)); } } /** * Simple KL Divergence test. The loss should be zero if input = target. */ -BOOST_AUTO_TEST_CASE(SimpleKLDivergenceTest) +TEST_CASE("SimpleKLDivergenceTest", "[LossFunctionsTest]") { arma::mat input, target, output; double loss; @@ -152,13 +150,13 @@ BOOST_AUTO_TEST_CASE(SimpleKLDivergenceTest) input = arma::ones(10, 1); target = arma::ones(10, 1); loss = module.Forward(input, target); - BOOST_REQUIRE_SMALL(loss, 0.00001); + REQUIRE(loss == Approx(0.0).margin(1e-5)); } /* * Simple test for the mean squared logarithmic error function. */ -BOOST_AUTO_TEST_CASE(SimpleMeanSquaredLogarithmicErrorTest) +TEST_CASE("SimpleMeanSquaredLogarithmicErrorTest", "[LossFunctionsTest]") { arma::mat input, output, target; MeanSquaredLogarithmicError<> module; @@ -168,31 +166,31 @@ BOOST_AUTO_TEST_CASE(SimpleMeanSquaredLogarithmicErrorTest) input = arma::zeros(1, 8); target = arma::zeros(1, 8); double error = module.Forward(input, target); - BOOST_REQUIRE_SMALL(error, 0.00001); + REQUIRE(error == Approx(0.0).margin(1e-5)); // Test the Backward function. module.Backward(input, target, output); // The output should be equal to 0. CheckMatrices(input, output); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the error function on a single input. input = arma::mat("2"); target = arma::mat("3"); error = module.Forward(input, target); - BOOST_REQUIRE_CLOSE(error, 0.082760974810151655, 0.001); + REQUIRE(error == Approx(0.082760974810151655).epsilon(1e-3)); // Test the Backward function on a single input. module.Backward(input, target, output); - BOOST_REQUIRE_CLOSE(arma::accu(output), -0.1917880483011872, 0.001); - BOOST_REQUIRE_EQUAL(output.n_elem, 1); + REQUIRE(arma::accu(output) == Approx(-0.1917880483011872).epsilon(1e-3)); + REQUIRE(output.n_elem == 1); } /** * Test to check KL Divergence loss function when we take mean. */ -BOOST_AUTO_TEST_CASE(KLDivergenceMeanTest) +TEST_CASE("KLDivergenceMeanTest", "[LossFunctionsTest]") { arma::mat input, target, output; double loss; @@ -203,17 +201,17 @@ BOOST_AUTO_TEST_CASE(KLDivergenceMeanTest) target = arma::exp(arma::mat("2 1 1 1 1 1 1 1 1 1")); loss = module.Forward(input, target); - BOOST_REQUIRE_CLOSE_FRACTION(loss, -1.1 , 0.00001); + REQUIRE(loss == Approx(-1.1 ).epsilon(1e-5)); // Test the Backward function. module.Backward(input, target, output); - BOOST_REQUIRE_CLOSE_FRACTION(arma::as_scalar(output), -0.1, 0.00001); + REQUIRE(arma::as_scalar(output) == Approx(-0.1).epsilon(1e-5)); } /** * Test to check KL Divergence loss function when we do not take mean. */ -BOOST_AUTO_TEST_CASE(KLDivergenceNoMeanTest) +TEST_CASE("KLDivergenceNoMeanTest", "[LossFunctionsTest]") { arma::mat input, target, output; double loss; @@ -224,17 +222,17 @@ BOOST_AUTO_TEST_CASE(KLDivergenceNoMeanTest) target = arma::exp(arma::mat("2 1 1 1 1 1 1 1 1 1")); loss = module.Forward(input, target); - BOOST_REQUIRE_CLOSE_FRACTION(loss, -11, 0.00001); + REQUIRE(loss == Approx(-11).epsilon(1e-5)); // Test the Backward function. module.Backward(input, target, output); - BOOST_REQUIRE_CLOSE_FRACTION(arma::as_scalar(output), -1, 0.00001); + REQUIRE(arma::as_scalar(output) == Approx(-1).epsilon(1e-5)); } /* * Simple test for the mean squared error performance function. */ -BOOST_AUTO_TEST_CASE(SimpleMeanSquaredErrorTest) +TEST_CASE("SimpleMeanSquaredErrorTest", "[LossFunctionsTest]") { arma::mat input, output, target; MeanSquaredError<> module; @@ -244,7 +242,7 @@ BOOST_AUTO_TEST_CASE(SimpleMeanSquaredErrorTest) input = arma::mat("1.0 0.0 1.0 0.0 -1.0 0.0 -1.0 0.0"); target = arma::zeros(1, 8); double error = module.Forward(input, target); - BOOST_REQUIRE_EQUAL(error, 0.5); + REQUIRE(error == 0.5); // Test the Backward function. module.Backward(input, target, output); @@ -252,26 +250,26 @@ BOOST_AUTO_TEST_CASE(SimpleMeanSquaredErrorTest) // output = 2 * (input - target) / target.n_cols, // output * nofColumns / 2 should be equal to input. CheckMatrices(input, output * output.n_cols / 2); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the error function on a single input. input = arma::mat("2"); target = arma::mat("3"); error = module.Forward(input, target); - BOOST_REQUIRE_EQUAL(error, 1.0); + REQUIRE(error == 1.0); // Test the Backward function on a single input. module.Backward(input, target, output); // Test whether the output is negative. - BOOST_REQUIRE_EQUAL(arma::accu(output), -2); - BOOST_REQUIRE_EQUAL(output.n_elem, 1); + REQUIRE(arma::accu(output) == -2); + REQUIRE(output.n_elem == 1); } /* * Simple test for the cross-entropy error performance function. */ -BOOST_AUTO_TEST_CASE(SimpleCrossEntropyErrorTest) +TEST_CASE("SimpleCrossEntropyErrorTest", "[LossFunctionsTest]") { arma::mat input1, input2, output, target1, target2; CrossEntropyError<> module(1e-6); @@ -281,40 +279,40 @@ BOOST_AUTO_TEST_CASE(SimpleCrossEntropyErrorTest) input1 = arma::mat("0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5"); target1 = arma::zeros(1, 8); double error1 = module.Forward(input1, target1); - BOOST_REQUIRE_SMALL(error1 - 8 * std::log(2), 2e-5); + REQUIRE(error1 - 8 * std::log(2) == Approx(0.0).margin(2e-5)); input2 = arma::mat("0 1 1 0 1 0 0 1"); target2 = arma::mat("0 1 1 0 1 0 0 1"); double error2 = module.Forward(input2, target2); - BOOST_REQUIRE_SMALL(error2, 1e-5); + REQUIRE(error2 == Approx(0.0).margin(1e-5)); // Test the Backward function. module.Backward(input1, target1, output); for (double el : output) { // For the 0.5 constant vector we should get 1 / (1 - 0.5) = 2 everywhere. - BOOST_REQUIRE_SMALL(el - 2, 5e-6); + REQUIRE(el - 2 == Approx(0.0).margin(5e-6)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input1.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input1.n_cols); + REQUIRE(output.n_rows == input1.n_rows); + REQUIRE(output.n_cols == input1.n_cols); module.Backward(input2, target2, output); for (size_t i = 0; i < 8; ++i) { double el = output.at(0, i); if (input2.at(i) == 0) - BOOST_REQUIRE_SMALL(el - 1, 2e-6); + REQUIRE(el - 1 == Approx(0.0).margin(2e-6)); else - BOOST_REQUIRE_SMALL(el + 1, 2e-6); + REQUIRE(el + 1 == Approx(0.0).margin(2e-6)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input2.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input2.n_cols); + REQUIRE(output.n_rows == input2.n_rows); + REQUIRE(output.n_cols == input2.n_cols); } /** * Simple test for the Sigmoid Cross Entropy performance function. */ -BOOST_AUTO_TEST_CASE(SimpleSigmoidCrossEntropyErrorTest) +TEST_CASE("SimpleSigmoidCrossEntropyErrorTest", "[LossFunctionsTest]") { arma::mat input1, input2, input3, output, target1, target2, target3, expectedOutput; @@ -327,35 +325,35 @@ BOOST_AUTO_TEST_CASE(SimpleSigmoidCrossEntropyErrorTest) double error1 = module.Forward(input1, target1); double expected = 0.97407699; // Value computed using tensorflow. - BOOST_REQUIRE_SMALL(error1 / input1.n_elem - expected, 1e-7); + REQUIRE(error1 / input1.n_elem - expected == Approx(0.0).margin(1e-7)); input2 = arma::mat("1 2 3 4 5"); target2 = arma::mat("0 0 1 0 1"); double error2 = module.Forward(input2, target2); expected = 1.5027283; - BOOST_REQUIRE_SMALL(error2 / input2.n_elem - expected, 1e-6); + REQUIRE(error2 / input2.n_elem - expected == Approx(0.0).margin(1e-6)); input3 = arma::mat("0 -1 -1 0 -1 0 0 -1"); target3 = arma::mat("0 -1 -1 0 -1 0 0 -1"); double error3 = module.Forward(input3, target3); expected = 0.00320443; - BOOST_REQUIRE_SMALL(error3 / input3.n_elem - expected, 1e-6); + REQUIRE(error3 / input3.n_elem - expected == Approx(0.0).margin(1e-6)); // Test the Backward function. module.Backward(input1, target1, output); expected = 0.62245929; for (size_t i = 0; i < output.n_elem; ++i) - BOOST_REQUIRE_SMALL(output(i) - expected, 1e-5); - BOOST_REQUIRE_EQUAL(output.n_rows, input1.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input1.n_cols); + REQUIRE(output(i) - expected == Approx(0.0).margin(1e-5)); + REQUIRE(output.n_rows == input1.n_rows); + REQUIRE(output.n_cols == input1.n_cols); expectedOutput = arma::mat( "0.7310586 0.88079709 -0.04742587 0.98201376 -0.00669285"); module.Backward(input2, target2, output); for (size_t i = 0; i < output.n_elem; ++i) - BOOST_REQUIRE_SMALL(output(i) - expectedOutput(i), 1e-5); - BOOST_REQUIRE_EQUAL(output.n_rows, input2.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input2.n_cols); + REQUIRE(output(i) - expectedOutput(i) == Approx(0.0).margin(1e-5)); + REQUIRE(output.n_rows == input2.n_rows); + REQUIRE(output.n_cols == input2.n_cols); module.Backward(input3, target3, output); expectedOutput = arma::mat("0.5 1.2689414"); @@ -363,18 +361,18 @@ BOOST_AUTO_TEST_CASE(SimpleSigmoidCrossEntropyErrorTest) { double el = output.at(0, i); if (std::abs(input3.at(i) - 0.0) < 1e-5) - BOOST_REQUIRE_SMALL(el - expectedOutput[0], 2e-6); + REQUIRE(el - expectedOutput[0] == Approx(0.0).margin(2e-6)); else - BOOST_REQUIRE_SMALL(el - expectedOutput[1], 2e-6); + REQUIRE(el - expectedOutput[1] == Approx(0.0).margin(2e-6)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input3.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input3.n_cols); + REQUIRE(output.n_rows == input3.n_rows); + REQUIRE(output.n_cols == input3.n_cols); } /** * Simple test for the Earth Mover Distance Layer. */ -BOOST_AUTO_TEST_CASE(SimpleEarthMoverDistanceLayerTest) +TEST_CASE("SimpleEarthMoverDistanceLayerTest", "[LossFunctionsTest]") { arma::mat input1, input2, output, target1, target2, expectedOutput; EarthMoverDistance<> module; @@ -385,34 +383,34 @@ BOOST_AUTO_TEST_CASE(SimpleEarthMoverDistanceLayerTest) target1 = arma::zeros(1, 8); double error1 = module.Forward(input1, target1); double expected = 0.0; - BOOST_REQUIRE_SMALL(error1 / input1.n_elem - expected, 1e-7); + REQUIRE(error1 / input1.n_elem - expected == Approx(0.0).margin(1e-7)); input2 = arma::mat("1 2 3 4 5"); target2 = arma::mat("1 0 1 0 1"); double error2 = module.Forward(input2, target2); expected = -1.8; - BOOST_REQUIRE_SMALL(error2 / input2.n_elem - expected, 1e-6); + REQUIRE(error2 / input2.n_elem - expected == Approx(0.0).margin(1e-6)); // Test the Backward function. module.Backward(input1, target1, output); expected = 0.0; for (size_t i = 0; i < output.n_elem; ++i) - BOOST_REQUIRE_SMALL(output(i) - expected, 1e-5); - BOOST_REQUIRE_EQUAL(output.n_rows, input1.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input1.n_cols); + REQUIRE(output(i) - expected == Approx(0.0).margin(1e-5)); + REQUIRE(output.n_rows == input1.n_rows); + REQUIRE(output.n_cols == input1.n_cols); expectedOutput = arma::mat("-1 0 -1 0 -1"); module.Backward(input2, target2, output); for (size_t i = 0; i < output.n_elem; ++i) - BOOST_REQUIRE_SMALL(output(i) - expectedOutput(i), 1e-5); - BOOST_REQUIRE_EQUAL(output.n_rows, input2.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input2.n_cols); + REQUIRE(output(i) - expectedOutput(i) == Approx(0.0).margin(1e-5)); + REQUIRE(output.n_rows == input2.n_rows); + REQUIRE(output.n_cols == input2.n_cols); } /* * Mean Squared Error numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientMeanSquaredErrorTest) +TEST_CASE("GradientMeanSquaredErrorTest", "[LossFunctionsTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -449,13 +447,13 @@ BOOST_AUTO_TEST_CASE(GradientMeanSquaredErrorTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /* * Reconstruction Loss numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientReconstructionLossTest) +TEST_CASE("GradientReconstructionLossTest", "[LossFunctionsTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -492,13 +490,13 @@ BOOST_AUTO_TEST_CASE(GradientReconstructionLossTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /* * Simple test for the dice loss function. */ -BOOST_AUTO_TEST_CASE(DiceLossTest) +TEST_CASE("DiceLossTest", "[LossFunctionsTest]") { arma::mat input1, input2, target, output; double loss; @@ -508,38 +506,38 @@ BOOST_AUTO_TEST_CASE(DiceLossTest) input1 = arma::ones(10, 1); target = arma::ones(10, 1); loss = module.Forward(input1, target); - BOOST_REQUIRE_SMALL(loss, 0.00001); + REQUIRE(loss == Approx(0.0).margin(1e-5)); // Test the Forward function. Loss should be 0.185185185. input2 = arma::ones(10, 1) * 0.5; loss = module.Forward(input2, target); - BOOST_REQUIRE_CLOSE(loss, 0.185185185, 0.00001); + REQUIRE(loss == Approx(0.185185185).epsilon(1e-5)); // Test the Backward function for input = target. module.Backward(input1, target, output); for (double el : output) { // For input = target we should get 0.0 everywhere. - BOOST_REQUIRE_CLOSE(el, 0.0, 0.00001); + REQUIRE(el == Approx(0.0).epsilon(1e-5)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input1.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input1.n_cols); + REQUIRE(output.n_rows == input1.n_rows); + REQUIRE(output.n_cols == input1.n_cols); // Test the Backward function. module.Backward(input2, target, output); for (double el : output) { // For the 0.5 constant vector we should get -0.0877914951989026 everywhere. - BOOST_REQUIRE_CLOSE(el, -0.0877914951989026, 0.00001); + REQUIRE(el == Approx(-0.0877914951989026).epsilon(1e-5)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input2.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input2.n_cols); + REQUIRE(output.n_rows == input2.n_rows); + REQUIRE(output.n_cols == input2.n_cols); } /* * Simple test for the mean bias error performance function. */ -BOOST_AUTO_TEST_CASE(SimpleMeanBiasErrorTest) +TEST_CASE("SimpleMeanBiasErrorTest", "[LossFunctionsTest]") { arma::mat input, output, target; MeanBiasError<> module; @@ -549,35 +547,35 @@ BOOST_AUTO_TEST_CASE(SimpleMeanBiasErrorTest) input = arma::mat("1.0 0.0 1.0 -1.0 -1.0 0.0 -1.0 0.0"); target = arma::zeros(1, 8); double error = module.Forward(input, target); - BOOST_REQUIRE_EQUAL(error, 0.125); + REQUIRE(error == 0.125); // Test the Backward function. module.Backward(input, target, output); // We should get a vector with -1 everywhere. for (double el : output) { - BOOST_REQUIRE_EQUAL(el, -1); + REQUIRE(el == -1); } - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the error function on a single input. input = arma::mat("2"); target = arma::mat("3"); error = module.Forward(input, target); - BOOST_REQUIRE_EQUAL(error, 1.0); + REQUIRE(error == 1.0); // Test the Backward function on a single input. module.Backward(input, target, output); // Test whether the output is negative. - BOOST_REQUIRE_EQUAL(arma::accu(output), -1); - BOOST_REQUIRE_EQUAL(output.n_elem, 1); + REQUIRE(arma::accu(output) == -1); + REQUIRE(output.n_elem == 1); } /** * Simple test for the Log-Hyperbolic-Cosine loss function. */ -BOOST_AUTO_TEST_CASE(LogCoshLossTest) +TEST_CASE("LogCoshLossTest", "[LossFunctionsTest]") { arma::mat input, target, output; double loss; @@ -587,36 +585,36 @@ BOOST_AUTO_TEST_CASE(LogCoshLossTest) input = arma::ones(10, 1); target = arma::ones(10, 1); loss = module.Forward(input, target); - BOOST_REQUIRE_EQUAL(loss, 0); + REQUIRE(loss == 0); // Test the Backward function for input = target. module.Backward(input, target, output); for (double el : output) { // For input = target we should get 0.0 everywhere. - BOOST_REQUIRE_CLOSE(el, 0.0, 1e-5); + REQUIRE(el == Approx(0.0).epsilon(1e-5)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the Forward function. Loss should be 0.546621. input = arma::mat("1 2 3 4 5"); target = arma::mat("1 2.4 3.4 4.2 5.5"); loss = module.Forward(input, target); - BOOST_REQUIRE_CLOSE(loss, 0.546621, 1e-3); + REQUIRE(loss == Approx(0.546621).epsilon(1e-3)); // Test the Backward function. module.Backward(input, target, output); - BOOST_REQUIRE_CLOSE(arma::accu(output), 2.46962, 1e-3); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::accu(output) == Approx(2.46962).epsilon(1e-3)); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); } /** * Simple test for the Hinge Embedding loss function. */ -BOOST_AUTO_TEST_CASE(HingeEmbeddingLossTest) +TEST_CASE("HingeEmbeddingLossTest", "[LossFunctionsTest]") { arma::mat input, target, output; double loss; @@ -626,36 +624,36 @@ BOOST_AUTO_TEST_CASE(HingeEmbeddingLossTest) input = arma::ones(10, 1); target = arma::ones(10, 1); loss = module.Forward(input, target); - BOOST_REQUIRE_EQUAL(loss, 0); + REQUIRE(loss == 0); // Test the Backward function for input = target. module.Backward(input, target, output); for (double el : output) { // For input = target we should get 0.0 everywhere. - BOOST_REQUIRE_CLOSE(el, 0.0, 1e-5); + REQUIRE(el == Approx(0.0).epsilon(1e-5)); } - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the Forward function. Loss should be 0.84. input = arma::mat("0.1 0.8 0.6 0.0 0.5"); target = arma::mat("0 1.0 1.0 0 0"); loss = module.Forward(input, target); - BOOST_REQUIRE_CLOSE(loss, 0.84, 1e-3); + REQUIRE(loss == Approx(0.84).epsilon(1e-3)); // Test the Backward function. module.Backward(input, target, output); - BOOST_REQUIRE_CLOSE(arma::accu(output), -2, 1e-3); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::accu(output) == Approx(-2).epsilon(1e-3)); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); } /** * Simple test for the l1 loss function. */ -BOOST_AUTO_TEST_CASE(SimpleL1LossTest) +TEST_CASE("SimpleL1LossTest", "[LossFunctionsTest]") { arma::mat input1, input2, output, target1, target2; L1Loss<> module(false); @@ -665,33 +663,33 @@ BOOST_AUTO_TEST_CASE(SimpleL1LossTest) input1 = arma::mat("0.5 0.5 0.5 0.5 0.5 0.5 0.5"); target1 = arma::zeros(1, 7); double error1 = module.Forward(input1, target1); - BOOST_REQUIRE_EQUAL(error1, 3.5); + REQUIRE(error1 == 3.5); input2 = arma::mat("0 1 1 0 1 0 0 1"); target2 = arma::mat("0 1 1 0 1 0 0 1"); double error2 = module.Forward(input2, target2); - BOOST_REQUIRE_CLOSE(error2, 0.0, 0.00001); + REQUIRE(error2 == Approx(0.0).epsilon(1e-5)); // Test the Backward function. module.Backward(input1, target1, output); for (double el : output) - BOOST_REQUIRE_EQUAL(el , 1); + REQUIRE(el == 1); - BOOST_REQUIRE_EQUAL(output.n_rows, input1.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input1.n_cols); + REQUIRE(output.n_rows == input1.n_rows); + REQUIRE(output.n_cols == input1.n_cols); module.Backward(input2, target2, output); for (double el : output) - BOOST_REQUIRE_EQUAL(el, 0); + REQUIRE(el == 0); - BOOST_REQUIRE_EQUAL(output.n_rows, input2.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input2.n_cols); + REQUIRE(output.n_rows == input2.n_rows); + REQUIRE(output.n_cols == input2.n_cols); } /** * Simple test for the Cosine Embedding loss function. */ -BOOST_AUTO_TEST_CASE(CosineEmbeddingLossTest) +TEST_CASE("CosineEmbeddingLossTest", "[LossFunctionsTest]") { arma::mat input1, input2, y, output; double loss; @@ -705,20 +703,20 @@ BOOST_AUTO_TEST_CASE(CosineEmbeddingLossTest) y = arma::mat(1, 1); y.ones(); loss = module.Forward(input1, input1); - BOOST_REQUIRE_SMALL(loss, 1e-6); + REQUIRE(loss == Approx(0.0).margin(1e-6)); // Test the Backward function. module.Backward(input1, input1, output); - BOOST_REQUIRE_SMALL(arma::accu(output), 1e-6); + REQUIRE(arma::accu(output) == Approx(0.0).margin(1e-6)); // Check for dissimilarity. module.Similarity() = false; loss = module.Forward(input1, input1); - BOOST_REQUIRE_CLOSE(loss, 1.0, 1e-4); + REQUIRE(loss == Approx(1.0).epsilon(1e-4)); // Test the Backward function. module.Backward(input1, input1, output); - BOOST_REQUIRE_SMALL(arma::accu(output), 1e-6); + REQUIRE(arma::accu(output) == Approx(0.0).margin(1e-6)); input1 = arma::mat(3, 2); input2 = arma::mat(3, 2); @@ -730,11 +728,11 @@ BOOST_AUTO_TEST_CASE(CosineEmbeddingLossTest) input2(2) = 2; loss = module.Forward(input1, input2); // Calculated using torch.nn.CosineEmbeddingLoss(). - BOOST_REQUIRE_CLOSE(loss, 2.897367, 1e-3); + REQUIRE(loss == Approx(2.897367).epsilon(1e-3)); // Test the Backward function. module.Backward(input1, input2, output); - BOOST_REQUIRE_CLOSE(arma::accu(output), 0.06324556, 1e-3); + REQUIRE(arma::accu(output) == Approx(0.06324556).epsilon(1e-3)); // Check for correctness for cube. CosineEmbeddingLoss<> module2(0.5, true); @@ -754,31 +752,31 @@ BOOST_AUTO_TEST_CASE(CosineEmbeddingLossTest) input4(11) = 2; loss = module2.Forward(input3, input4); // Calculated using torch.nn.CosineEmbeddingLoss(). - BOOST_REQUIRE_CLOSE(loss, 0.55395, 1e-3); + REQUIRE(loss == Approx(0.55395).epsilon(1e-3)); // Test the Backward function. module2.Backward(input3, input4, output); - BOOST_REQUIRE_CLOSE(arma::accu(output), -0.36649111, 1e-3); + REQUIRE(arma::accu(output) == Approx(-0.36649111).epsilon(1e-3)); // Check Output for mean type of reduction. CosineEmbeddingLoss<> module3(0.0, true, true); loss = module3.Forward(input3, input4); - BOOST_REQUIRE_CLOSE(loss, 0.092325, 1e-3); + REQUIRE(loss == Approx(0.092325).epsilon(1e-3)); // Check correctness for cube. module3.Similarity() = false; loss = module3.Forward(input3, input4); - BOOST_REQUIRE_CLOSE(loss, 0.90767498236, 1e-3); + REQUIRE(loss == Approx(0.90767498236).epsilon(1e-3)); // Test the Backward function. module3.Backward(input3, input4, output); - BOOST_REQUIRE_CLOSE(arma::accu(output), 0.36649111, 1e-4); + REQUIRE(arma::accu(output) == Approx(0.36649111).epsilon(1e-4)); } /* * Simple test for the Margin Ranking Loss function. */ -BOOST_AUTO_TEST_CASE(MarginRankingLossTest) +TEST_CASE("MarginRankingLossTest", "[LossFunctionsTest]") { arma::mat input, input1, input2, target, output; MarginRankingLoss<> module; @@ -791,15 +789,15 @@ BOOST_AUTO_TEST_CASE(MarginRankingLossTest) target = arma::mat("1 -1 -1 1 -1 1"); double error = module.Forward(input, target); // Computed using torch.nn.functional.margin_ranking_loss() - BOOST_REQUIRE_CLOSE(error, 2.66667, 1e-3); + REQUIRE(error == Approx(2.66667).epsilon(1e-3)); // Test the Backward function. module.Backward(input, target, output); CheckMatrices(output, arma::mat("-0.000000 0.166667 -1.500000 0.666667 " "0.000000 -0.000000"), 1e-3); - BOOST_REQUIRE_EQUAL(output.n_rows, target.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, target.n_cols); + REQUIRE(output.n_rows == target.n_rows); + REQUIRE(output.n_cols == target.n_cols); // Test the error function on another input. input1 = arma::mat("0.4287 -1.6208 -1.5006 -0.4473 1.5208 -4.5184 9.3574 " @@ -809,7 +807,7 @@ BOOST_AUTO_TEST_CASE(MarginRankingLossTest) input = arma::join_cols(input1, input2); target = arma::mat("1 1 -1 1 -1 1 1 1 -1 1"); error = module.Forward(input, target); - BOOST_REQUIRE_CLOSE(error, 3.03530, 1e-3); + REQUIRE(error == Approx(3.03530).epsilon(1e-3)); // Test the Backward function on the second input. module.Backward(input, target, output); @@ -821,7 +819,7 @@ BOOST_AUTO_TEST_CASE(MarginRankingLossTest) /** * Simple test for the Softmargin Loss function. */ -BOOST_AUTO_TEST_CASE(SoftMarginLossTest) +TEST_CASE("SoftMarginLossTest", "[LossFunctionsTest]") { arma::mat input, target, output, expectedOutput; double loss; @@ -844,13 +842,13 @@ BOOST_AUTO_TEST_CASE(SoftMarginLossTest) // Test the Forward function. Loss should be 6.41456. // Value calculated using torch.nn.SoftMarginLoss(reduction='sum'). loss = module1.Forward(input, target); - BOOST_REQUIRE_CLOSE(loss, 6.41456, 1e-3); + REQUIRE(loss == Approx(6.41456).epsilon(1e-3)); // Test the Backward function. module1.Backward(input, target, output); - BOOST_REQUIRE_CLOSE(arma::as_scalar(arma::accu(output)), -1.48227, 1e-3); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::as_scalar(arma::accu(output)) == Approx(-1.48227).epsilon(1e-3)); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); CheckMatrices(output, expectedOutput, 0.1); // Test for mean reduction. @@ -863,19 +861,19 @@ BOOST_AUTO_TEST_CASE(SoftMarginLossTest) // Test the Forward function. Loss should be 0.712729. // Value calculated using torch.nn.SoftMarginLoss(reduction='mean'). loss = module2.Forward(input, target); - BOOST_REQUIRE_CLOSE(loss, 0.712729, 1e-3); + REQUIRE(loss == Approx(0.712729).epsilon(1e-3)); // Test the Backward function. module2.Backward(input, target, output); - BOOST_REQUIRE_CLOSE(arma::as_scalar(arma::accu(output)), -0.164697, 1e-3); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::as_scalar(arma::accu(output)) == Approx(-0.164697).epsilon(1e-3)); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); CheckMatrices(output, expectedOutput, 0.1); } /** * Simple test for the Mean Absolute Percentage Error function. */ -BOOST_AUTO_TEST_CASE(MeanAbsolutePercentageErrorTest) +TEST_CASE("MeanAbsolutePercentageErrorTest", "[LossFunctionsTest]") { arma::mat input, target, output, expectedOutput; MeanAbsolutePercentageError<> module; @@ -887,14 +885,12 @@ BOOST_AUTO_TEST_CASE(MeanAbsolutePercentageErrorTest) // Test the Forward function. Loss should be 95.625. // Loss value calculated manually. double loss = module.Forward(input,target); - BOOST_REQUIRE_CLOSE(loss, 95.625, 1e-1); + REQUIRE(loss == Approx(95.625).epsilon(1e-1)); // Test the Backward function. module.Backward(input, target, output); - BOOST_REQUIRE_CLOSE(arma::as_scalar(arma::accu(output)), -105.625, 1e-3); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::as_scalar(arma::accu(output)) == Approx(-105.625).epsilon(1e-3)); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); CheckMatrices(output, expectedOutput, 0.1); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/dbscan_test.cpp b/src/mlpack/tests/main_tests/dbscan_test.cpp index 2a8221e27c..ead1975c25 100644 --- a/src/mlpack/tests/main_tests/dbscan_test.cpp +++ b/src/mlpack/tests/main_tests/dbscan_test.cpp @@ -19,8 +19,8 @@ static const std::string testName = "DBSCAN"; #include "test_helper.hpp" #include -#include -#include "../test_tools.hpp" +#include "../catch.hpp" +#include "../test_catch_tools.hpp" using namespace mlpack; @@ -41,17 +41,16 @@ struct DBSCANTestFixture } }; -BOOST_FIXTURE_TEST_SUITE(DBSCANMainTest, DBSCANTestFixture); - /** * Check that number of output labels and number of input * points are equal. */ -BOOST_AUTO_TEST_CASE(DBSCANOutputDimensionTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANOutputDimensionTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); size_t inputSize = inputData.n_cols; @@ -60,45 +59,45 @@ BOOST_AUTO_TEST_CASE(DBSCANOutputDimensionTest) mlpackMain(); // Check that number of predicted labels is equal to the input test points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("assignments").n_cols, - inputSize); - BOOST_REQUIRE_EQUAL(IO::GetParam>("assignments").n_rows, - 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("centroids").n_rows, 4); - BOOST_REQUIRE_GE(IO::GetParam("centroids").n_cols, 1); + REQUIRE(IO::GetParam>("assignments").n_cols == inputSize); + REQUIRE(IO::GetParam>("assignments").n_rows == 1); + REQUIRE(IO::GetParam("centroids").n_rows == 4); + REQUIRE(IO::GetParam("centroids").n_cols >= 1); } /** * Check that radius of search(epsilon) is always non-negative. */ -BOOST_AUTO_TEST_CASE(DBSCANEpsilonTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANEpsilonTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); SetInputParam("epsilon", (double) -0.5); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Check that minimum size of cluster is always non-negative. */ -BOOST_AUTO_TEST_CASE(DBSCANMinSizeTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANMinSizeTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); SetInputParam("min_size", (int) -1); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -106,11 +105,12 @@ BOOST_AUTO_TEST_CASE(DBSCANMinSizeTest) * Check that no point is labelled as noise point * when min_size is equal to 1. */ -BOOST_AUTO_TEST_CASE(DBSCANClusterNumberTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANClusterNumberTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); SetInputParam("min_size", (int) 1); @@ -122,18 +122,19 @@ BOOST_AUTO_TEST_CASE(DBSCANClusterNumberTest) output = std::move(IO::GetParam>("assignments")); for (size_t i = 0; i < output.n_elem; ++i) - BOOST_REQUIRE_LT(output[i], inputData.n_cols); + REQUIRE(output[i] < inputData.n_cols); } /** * Check that the cluster assignment is different for different * values of epsilon. */ -BOOST_AUTO_TEST_CASE(DBSCANDiffEpsilonTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANDiffEpsilonTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); SetInputParam("epsilon", (double) 1.0); @@ -156,18 +157,19 @@ BOOST_AUTO_TEST_CASE(DBSCANDiffEpsilonTest) arma::Row output2; output2 = std::move(IO::GetParam>("assignments")); - BOOST_REQUIRE_GT(arma::accu(output1 != output2), 1); + REQUIRE(arma::accu(output1 != output2) > 1); } /** * Check that the cluster assignment is different for different * values of Min Size. */ -BOOST_AUTO_TEST_CASE(DBSCANDiffMinSizeTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANDiffMinSizeTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); SetInputParam("epsilon", (double) 0.4); @@ -193,7 +195,7 @@ BOOST_AUTO_TEST_CASE(DBSCANDiffMinSizeTest) arma::Row output2; output2 = std::move(IO::GetParam>("assignments")); - BOOST_REQUIRE_GT(arma::accu(output1 != output2), 1); + REQUIRE(arma::accu(output1 != output2) > 1); } /** @@ -201,17 +203,18 @@ BOOST_AUTO_TEST_CASE(DBSCANDiffMinSizeTest) * tree types. ’kd’, ’r’, ’r-star’, ’x’, ’hilbert-r’, ’r-plus’, * ’r-plus-plus’, ’cover’, ’ball’. */ -BOOST_AUTO_TEST_CASE(DBSCANTreeTypeTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANTreeTypeTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", std::move(inputData)); SetInputParam("tree_type", std::string("binary")); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -219,11 +222,12 @@ BOOST_AUTO_TEST_CASE(DBSCANTreeTypeTest) * Check that the assignment of cluster is same if * different tree type is used for search. */ -BOOST_AUTO_TEST_CASE(DBSCANDiffTreeTypeTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANDiffTreeTypeTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); // Tree type = kd tree. @@ -369,11 +373,12 @@ BOOST_AUTO_TEST_CASE(DBSCANDiffTreeTypeTest) * Check that the assignment of cluster is same if * single tree is used for search. */ -BOOST_AUTO_TEST_CASE(DBSCANSingleTreeTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANSingleTreeTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); @@ -401,11 +406,12 @@ BOOST_AUTO_TEST_CASE(DBSCANSingleTreeTest) * Check that the assignment of cluster is same if * single tree is used for search. */ -BOOST_AUTO_TEST_CASE(DBSCANNaiveSearchTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANNaiveSearchTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); @@ -433,11 +439,12 @@ BOOST_AUTO_TEST_CASE(DBSCANNaiveSearchTest) * Check that the assignment of cluster is different if * point selection policies are different. */ -BOOST_AUTO_TEST_CASE(DBSCANRandomSelectionFlagTest) +TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANRandomSelectionFlagTest", + "[DBSCANMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("iris.csv", inputData)) - BOOST_FAIL("Unable to load dataset iris.csv!"); + FAIL("Unable to load dataset iris.csv!"); SetInputParam("input", inputData); SetInputParam("epsilon", (double) 0.358); @@ -466,7 +473,5 @@ BOOST_AUTO_TEST_CASE(DBSCANRandomSelectionFlagTest) arma::Row randomOutput; randomOutput = std::move(IO::GetParam>("assignments")); - BOOST_REQUIRE_GT(arma::accu(orderedOutput != randomOutput), 0); + REQUIRE(arma::accu(orderedOutput != randomOutput) > 0); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/mean_shift_test.cpp b/src/mlpack/tests/main_tests/mean_shift_test.cpp index eea3ceb3c7..5da1c28b95 100644 --- a/src/mlpack/tests/main_tests/mean_shift_test.cpp +++ b/src/mlpack/tests/main_tests/mean_shift_test.cpp @@ -12,15 +12,16 @@ #include #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "MeanShift"; #include +static const std::string testName = "MeanShift"; + #include #include -#include "test_helper.hpp" -#include -#include "../test_tools.hpp" +#include "test_helper.hpp" +#include "../test_catch_tools.hpp" +#include "../catch.hpp" using namespace mlpack; @@ -48,13 +49,13 @@ static void ResetSettings() IO::RestoreSettings(testName); } -BOOST_FIXTURE_TEST_SUITE(MeanShiftMainTest, MeanShiftTestFixture); - /** * Ensure that the output has 1 extra row for the labels and * check the number of points for output remain the same. */ -BOOST_AUTO_TEST_CASE(MeanShiftOutputDimensionTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftOutputDimensionTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; x.randu(3, 100); // 100 points in 3 dimension @@ -65,16 +66,18 @@ BOOST_AUTO_TEST_CASE(MeanShiftOutputDimensionTest) mlpackMain(); // Now check that the output has 1 extra row for labels. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_rows, 3 + 1); + REQUIRE(IO::GetParam("output").n_rows == 3 + 1); // Check number of output points are the same. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_cols, 100); + REQUIRE(IO::GetParam("output").n_cols == 100); } /** * Ensure that if we ask for labels_only, output has 1 row and * same number of columns for each point's label. */ -BOOST_AUTO_TEST_CASE(MeanShiftLabelOnlyOutputDimensionTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftLabelOnlyOutputDimensionTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; x.randu(3, 100); // 100 points in 3 dimension @@ -86,9 +89,9 @@ BOOST_AUTO_TEST_CASE(MeanShiftLabelOnlyOutputDimensionTest) mlpackMain(); // Check that there is only 1 row containing all the labels. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_rows, 1); + REQUIRE(IO::GetParam("output").n_rows == 1); // Check number of output points are the same. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_cols, 100); + REQUIRE(IO::GetParam("output").n_cols == 100); } /** @@ -96,11 +99,13 @@ BOOST_AUTO_TEST_CASE(MeanShiftLabelOnlyOutputDimensionTest) * and check the number of points remain the same if the --in_place * flag is set. */ -BOOST_AUTO_TEST_CASE(MeanShiftInPlaceTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftInPlaceTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; if (!data::Load("iris_test.csv", x)) - BOOST_FAIL("Cannot load test dataset iris_test.csv!"); + FAIL("Cannot load test dataset iris_test.csv!"); // Get initial number of rows and columns in file. int numRows = x.n_rows; @@ -113,20 +118,22 @@ BOOST_AUTO_TEST_CASE(MeanShiftInPlaceTest) mlpackMain(); // Now check that the output has 1 extra row for labels. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_rows, numRows + 1); + REQUIRE(IO::GetParam("output").n_rows == numRows + 1); // Check number of output points are the same. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_cols, numCols); + REQUIRE(IO::GetParam("output").n_cols == numCols); } /** * Ensure that force_convergence is used by testing that the * force_convergence flag makes a difference in the program. */ -BOOST_AUTO_TEST_CASE(MeanShiftForceConvergenceTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftForceConvergenceTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; if (!data::Load("iris_test.csv", x)) - BOOST_FAIL("Cannot load test dataset iris_test.csv!"); + FAIL("Cannot load test dataset iris_test.csv!"); // Input random data points. SetInputParam("input", x); @@ -150,18 +157,20 @@ BOOST_AUTO_TEST_CASE(MeanShiftForceConvergenceTest) const int numCentroids2 = IO::GetParam("centroid").n_cols; // Resulting number of centroids should be different. - BOOST_REQUIRE_NE(numCentroids1, numCentroids2); + REQUIRE(numCentroids1 != numCentroids2); } /** * Ensure that radius is used by testing that the radius * makes a difference in the program. */ -BOOST_AUTO_TEST_CASE(MeanShiftRadiusTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftRadiusTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; if (!data::Load("iris_test.csv", x)) - BOOST_FAIL("Cannot load test dataset iris_test.csv!"); + FAIL("Cannot load test dataset iris_test.csv!"); // Input random data points. SetInputParam("input", x); @@ -183,18 +192,20 @@ BOOST_AUTO_TEST_CASE(MeanShiftRadiusTest) const int numCentroids2 = IO::GetParam("centroid").n_cols; // Resulting number of centroids should be different. - BOOST_REQUIRE_NE(numCentroids1, numCentroids2); + REQUIRE(numCentroids1 != numCentroids2); } /** * Ensure that max_iterations is used by testing that the * max_iteration makes a difference in the program. */ -BOOST_AUTO_TEST_CASE(MeanShiftMaxIterationsTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftMaxIterationsTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; if (!data::Load("iris_test.csv", x)) - BOOST_FAIL("Cannot load test dataset iris_test.csv!"); + FAIL("Cannot load test dataset iris_test.csv!"); // Input random data points. SetInputParam("input", x); @@ -216,13 +227,15 @@ BOOST_AUTO_TEST_CASE(MeanShiftMaxIterationsTest) const int numCentroids2 = IO::GetParam("centroid").n_cols; // Resulting number of centroids should be different. - BOOST_REQUIRE_NE(numCentroids1, numCentroids2); + REQUIRE(numCentroids1 != numCentroids2); } /** * Ensure that we can't specify an invalid max number of iterations. */ -BOOST_AUTO_TEST_CASE(MeanShiftInvalidMaxIterationsTest) +TEST_CASE_METHOD( + MeanShiftTestFixture, "MeanShiftInvalidMaxIterationsTest", + "[MeanShiftMainTest][BindingTests]") { arma::mat x; x.randu(3, 100); // 100 points in 3 dimension @@ -233,8 +246,6 @@ BOOST_AUTO_TEST_CASE(MeanShiftInvalidMaxIterationsTest) SetInputParam("max_iterations", (int) -1); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/pca_test.cpp b/src/mlpack/tests/main_tests/pca_test.cpp index 9be5658c9f..dfc018103c 100644 --- a/src/mlpack/tests/main_tests/pca_test.cpp +++ b/src/mlpack/tests/main_tests/pca_test.cpp @@ -19,8 +19,7 @@ static const std::string testName = "PrincipalComponentAnalysis"; #include "test_helper.hpp" #include -#include -#include "../test_tools.hpp" +#include "../catch.hpp" using namespace mlpack; @@ -41,12 +40,11 @@ struct PCATestFixture } }; -BOOST_FIXTURE_TEST_SUITE(PCAMainTest, PCATestFixture); - /** * Make sure that if we ask for a dataset in 3 dimensions back, we get it. */ -BOOST_AUTO_TEST_CASE(PCADimensionTest) +TEST_CASE_METHOD(PCATestFixture, "PCADimensionTest", + "[PCAMainTest][BindingTests]") { arma::mat x = arma::randu(5, 5); @@ -57,15 +55,16 @@ BOOST_AUTO_TEST_CASE(PCADimensionTest) mlpackMain(); // Now check that the output has 3 dimensions. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_rows, 3); - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_cols, 5); + REQUIRE(IO::GetParam("output").n_rows == 3); + REQUIRE(IO::GetParam("output").n_cols == 5); } /** * Ensure that if we retain all variance, we get back a matrix with the same * dimensionality. */ -BOOST_AUTO_TEST_CASE(PCAVarRetainTest) +TEST_CASE_METHOD(PCATestFixture, "PCAVarRetainTest", + "[PCAMainTest][BindingTests]") { arma::mat x = arma::randu(4, 5); @@ -77,14 +76,15 @@ BOOST_AUTO_TEST_CASE(PCAVarRetainTest) mlpackMain(); // Check that the output has 5 dimensions. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_rows, 4); - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_cols, 5); + REQUIRE(IO::GetParam("output").n_rows == 4); + REQUIRE(IO::GetParam("output").n_cols == 5); } /** * Ensure that if we retain no variance, we get back no dimensions. */ -BOOST_AUTO_TEST_CASE(PCANoVarRetainTest) +TEST_CASE_METHOD(PCATestFixture, "PCANoVarRetainTest", + "[PCAMainTest][BindingTests]") { arma::mat x = arma::randu(5, 5); @@ -96,14 +96,15 @@ BOOST_AUTO_TEST_CASE(PCANoVarRetainTest) mlpackMain(); // Check that the output has 1 dimensions. - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_rows, 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("output").n_cols, 5); + REQUIRE(IO::GetParam("output").n_rows == 1); + REQUIRE(IO::GetParam("output").n_cols == 5); } /** * Check that we can't specify an invalid new dimensionality. */ -BOOST_AUTO_TEST_CASE(PCATooHighNewDimensionalityTest) +TEST_CASE_METHOD(PCATestFixture, "PCATooHighNewDimensionalityTest", + "[PCAMainTest][BindingTests]") { arma::mat x = arma::randu(5, 5); @@ -111,8 +112,6 @@ BOOST_AUTO_TEST_CASE(PCATooHighNewDimensionalityTest) SetInputParam("new_dimensionality", (int) 7); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index 63769a539e..47a56170f9 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -18,8 +18,8 @@ static const std::string testName = "RandomForest"; #include #include "test_helper.hpp" -#include -#include "../test_tools.hpp" +#include "../catch.hpp" +#include "../test_catch_tools.hpp" using namespace mlpack; @@ -40,25 +40,24 @@ struct RandomForestTestFixture } }; -BOOST_FIXTURE_TEST_SUITE(RandomForestMainTest, RandomForestTestFixture); - /** * Check that number of output points and number of input * points are equal and have appropriate number of classes. */ -BOOST_AUTO_TEST_CASE(RandomForestOutputDimensionTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestOutputDimensionTest", + "[RandomForestMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); arma::mat testData; if (!data::Load("vc2_test.csv", testData)) - BOOST_FAIL("Cannot load test dataset vc2.csv!"); + FAIL("Cannot load test dataset vc2.csv!"); size_t testSize = testData.n_cols; @@ -72,34 +71,32 @@ BOOST_AUTO_TEST_CASE(RandomForestOutputDimensionTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(IO::GetParam("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predictions. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_rows, - 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_rows, 3); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(IO::GetParam("probabilities").n_rows == 3); } /** * Ensure that saved model can be used again. */ -BOOST_AUTO_TEST_CASE(RandomForestModelReuseTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestModelReuseTest", + "[RandomForestMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); arma::mat testData; if (!data::Load("vc2_test.csv", testData)) - BOOST_FAIL("Cannot load test dataset vc2.csv!"); + FAIL("Cannot load test dataset vc2.csv!"); size_t testSize = testData.n_cols; @@ -130,16 +127,13 @@ BOOST_AUTO_TEST_CASE(RandomForestModelReuseTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(IO::GetParam("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predicitions. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_rows, - 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_rows, 3); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(IO::GetParam("probabilities").n_rows == 3); // Check that initial predictions and predictions using saved model are same. CheckMatrices(predictions, IO::GetParam>("predictions")); @@ -149,75 +143,79 @@ BOOST_AUTO_TEST_CASE(RandomForestModelReuseTest) /** * Make sure number of trees specified is always a positive number. */ -BOOST_AUTO_TEST_CASE(RandomForestNumOfTreesTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestNumOfTreesTest", + "[RandomForestMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); SetInputParam("num_trees", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure minimum leaf size specified is always a positive number. */ -BOOST_AUTO_TEST_CASE(RandomForestMinimumLeafSizeTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestMinimumLeafSizeTest", + "[RandomForestMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); SetInputParam("minimum_leaf_size", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure maximum depth specified is always a positive number. */ -BOOST_AUTO_TEST_CASE(RandomForestMaximumDepthTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestMaximumDepthTest", + "[RandomForestMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); SetInputParam("maximum_depth", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure only one of training data or pre-trained model is passed. */ -BOOST_AUTO_TEST_CASE(RandomForestTrainingVerTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingVerTest", + "[RandomForestMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); // Input training data. SetInputParam("training", std::move(inputData)); @@ -230,7 +228,7 @@ BOOST_AUTO_TEST_CASE(RandomForestTrainingVerTest) IO::GetParam("output_model")); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -254,16 +252,17 @@ inline bool CheckDifferentTrees(const TreeType& nodeA, const TreeType& nodeB) * Ensure that the trees have different structure as the minimum leaf size is * changed. */ -BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMinLeafSizeTest", + "[RandomForestMainTest][BindingTests]") { // Train for minimum leaf size 20. arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); // Input training data. SetInputParam("training", inputData); @@ -310,8 +309,8 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest) // Check that each tree is different. for (size_t i = 0; i < rf1->rf.NumTrees(); ++i) { - BOOST_REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf2->rf.Tree(i))); - BOOST_REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf3->rf.Tree(i))); + REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf2->rf.Tree(i))); + REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf3->rf.Tree(i))); } delete rf1; @@ -323,24 +322,25 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest) * Ensure that the number of trees are different when num_trees is specified * differently. */ -BOOST_AUTO_TEST_CASE(RandomForestDiffNumTreeTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffNumTreeTest", + "[RandomForestMainTest][BindingTests]") { // Train for num_trees 1. arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); arma::mat testData; if (!data::Load("vc2_test.csv", testData)) - BOOST_FAIL("Cannot load test dataset vc2_test.csv!"); + FAIL("Cannot load test dataset vc2_test.csv!"); arma::Row testLabels; if (!data::Load("vc2_test_labels.txt", testLabels)) - BOOST_FAIL("Cannot load labels for vc2__test_labels.txt"); + FAIL("Cannot load labels for vc2__test_labels.txt"); // Input training data. SetInputParam("training", inputData); @@ -383,23 +383,24 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffNumTreeTest) const size_t numTrees3 = IO::GetParam("output_model")->rf.NumTrees(); - BOOST_REQUIRE_NE(numTrees1, numTrees2); - BOOST_REQUIRE_NE(numTrees2, numTrees3); + REQUIRE(numTrees1 != numTrees2); + REQUIRE(numTrees2 != numTrees3); } /** * Ensure that the maximum_depth parameter makes a difference. */ -BOOST_AUTO_TEST_CASE(RandomForestDiffMaxDepthTest) +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMaxDepthTest", + "[RandomForestMainTest][BindingTests]") { // Train for minimum leaf size 20. arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load train dataset vc2.csv!"); + FAIL("Cannot load train dataset vc2.csv!"); arma::Row labels; if (!data::Load("vc2_labels.txt", labels)) - BOOST_FAIL("Cannot load labels for vc2_labels.txt"); + FAIL("Cannot load labels for vc2_labels.txt"); // Input training data. SetInputParam("training", inputData); @@ -444,13 +445,11 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffMaxDepthTest) // Check that each tree is different. for (size_t i = 0; i < rf1->rf.NumTrees(); ++i) { - BOOST_REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf2->rf.Tree(i))); - BOOST_REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf3->rf.Tree(i))); + REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf2->rf.Tree(i))); + REQUIRE(CheckDifferentTrees(rf1->rf.Tree(i), rf3->rf.Tree(i))); } delete rf1; delete rf2; delete rf3; } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/mean_shift_test.cpp b/src/mlpack/tests/mean_shift_test.cpp index 818602f632..9f6c229639 100644 --- a/src/mlpack/tests/mean_shift_test.cpp +++ b/src/mlpack/tests/mean_shift_test.cpp @@ -12,15 +12,13 @@ #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::meanshift; using namespace mlpack::distribution; -BOOST_AUTO_TEST_SUITE(MeanShiftTest); - // Generate dataset; written transposed because it's easier to read. arma::mat meanShiftData(" 0.0 0.0;" // Class 1. " 0.3 0.4;" @@ -57,7 +55,7 @@ arma::mat meanShiftData(" 0.0 0.0;" // Class 1. /** * 30-point 3-class test case for Mean Shift. */ -BOOST_AUTO_TEST_CASE(MeanShiftSimpleTest) +TEST_CASE("MeanShiftSimpleTest", "[MeanShiftTest]") { MeanShift<> meanShift; @@ -70,29 +68,29 @@ BOOST_AUTO_TEST_CASE(MeanShiftSimpleTest) size_t firstClass = assignments(0); for (size_t i = 1; i < 13; ++i) - BOOST_REQUIRE_EQUAL(assignments(i), firstClass); + REQUIRE(assignments(i) == firstClass); size_t secondClass = assignments(13); // To ensure that class 1 != class 2. - BOOST_REQUIRE_NE(firstClass, secondClass); + REQUIRE(firstClass != secondClass); for (size_t i = 13; i < 20; ++i) - BOOST_REQUIRE_EQUAL(assignments(i), secondClass); + REQUIRE(assignments(i) == secondClass); size_t thirdClass = assignments(20); // To ensure that this is the third class which we haven't seen yet. - BOOST_REQUIRE_NE(firstClass, thirdClass); - BOOST_REQUIRE_NE(secondClass, thirdClass); + REQUIRE(firstClass != thirdClass); + REQUIRE(secondClass != thirdClass); for (size_t i = 20; i < 30; ++i) - BOOST_REQUIRE_EQUAL(assignments(i), thirdClass); + REQUIRE(assignments(i) == thirdClass); } // Generate samples from four Gaussians, and make sure mean shift nearly // recovers those four centers. -BOOST_AUTO_TEST_CASE(GaussianClustering) +TEST_CASE("GaussianClustering", "[MeanShiftTest]") { GaussianDistribution g1("0.0 0.0 0.0", arma::eye(3, 3)); GaussianDistribution g2("5.0 5.0 5.0", 2 * arma::eye(3, 3)); @@ -162,7 +160,5 @@ BOOST_AUTO_TEST_CASE(GaussianClustering) break; } - BOOST_REQUIRE_EQUAL(success, true); + REQUIRE(success == true); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/pca_test.cpp b/src/mlpack/tests/pca_test.cpp index d270c15d20..fff63d0024 100644 --- a/src/mlpack/tests/pca_test.cpp +++ b/src/mlpack/tests/pca_test.cpp @@ -17,10 +17,7 @@ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(PCATest); +#include "catch.hpp" using namespace arma; using namespace mlpack; @@ -50,9 +47,9 @@ void ArmaComparisonPCA( for (size_t i = 0; i < eigVal.n_elem; ++i) { if (eigVal[i] == 0.0) - BOOST_REQUIRE_SMALL(eigVal1[i], 1e-15); + REQUIRE(eigVal1[i] == Approx(0.0).margin(1e-15)); else - BOOST_REQUIRE_CLOSE(eigVal[i], eigVal1[i], 0.0001); + REQUIRE(eigVal[i] == Approx(eigVal1[i]).epsilon(1e-6)); } } @@ -88,14 +85,14 @@ void PCADimensionalityReduction( ++trial; } - BOOST_REQUIRE_EQUAL(success, true); + REQUIRE(success == true); // Compare with correct results. mat correct("-1.53781086 -3.51358020 -0.16139887 -1.87706634 7.08985628;" " 1.29937798 3.45762685 -2.69910005 -3.15620704 1.09830225"); - BOOST_REQUIRE_EQUAL(data.n_rows, correct.n_rows); - BOOST_REQUIRE_EQUAL(data.n_cols, correct.n_cols); + REQUIRE(data.n_rows == correct.n_rows); + REQUIRE(data.n_cols == correct.n_cols); // If the eigenvectors are pointed opposite directions, they will cancel // each other out in this summation. @@ -110,10 +107,10 @@ void PCADimensionalityReduction( for (size_t row = 0; row < 2; row++) for (size_t col = 0; col < 5; col++) - BOOST_REQUIRE_CLOSE(data(row, col), correct(row, col), 1e-3); + REQUIRE(data(row, col) == Approx(correct(row, col)).epsilon(1e-5)); // Check that the amount of variance retained is right. - BOOST_REQUIRE_CLOSE(varRetained, 0.904876047045906, 1e-5); + REQUIRE(varRetained == Approx(0.904876047045906).epsilon(1e-7)); } /** @@ -141,50 +138,50 @@ void PCAVarianceRetained() arma::mat origData = data; double varRetained = p.Apply(data, 0.1); - BOOST_REQUIRE_EQUAL(data.n_rows, 1); - BOOST_REQUIRE_EQUAL(data.n_cols, 5); - BOOST_REQUIRE_CLOSE(varRetained, 0.616237391936100, 1e-5); + REQUIRE(data.n_rows == 1); + REQUIRE(data.n_cols == 5); + REQUIRE(varRetained == Approx(0.616237391936100).epsilon(1e-7)); data = origData; varRetained = p.Apply(data, 0.5); - BOOST_REQUIRE_EQUAL(data.n_rows, 1); - BOOST_REQUIRE_EQUAL(data.n_cols, 5); - BOOST_REQUIRE_CLOSE(varRetained, 0.616237391936100, 1e-5); + REQUIRE(data.n_rows == 1); + REQUIRE(data.n_cols == 5); + REQUIRE(varRetained == Approx(0.616237391936100).epsilon(1e-7)); data = origData; varRetained = p.Apply(data, 0.7); - BOOST_REQUIRE_EQUAL(data.n_rows, 2); - BOOST_REQUIRE_EQUAL(data.n_cols, 5); - BOOST_REQUIRE_CLOSE(varRetained, 0.904876047045906, 1e-5); + REQUIRE(data.n_rows == 2); + REQUIRE(data.n_cols == 5); + REQUIRE(varRetained == Approx(0.904876047045906).epsilon(1e-7)); data = origData; varRetained = p.Apply(data, 0.904); - BOOST_REQUIRE_EQUAL(data.n_rows, 2); - BOOST_REQUIRE_EQUAL(data.n_cols, 5); - BOOST_REQUIRE_CLOSE(varRetained, 0.904876047045906, 1e-5); + REQUIRE(data.n_rows == 2); + REQUIRE(data.n_cols == 5); + REQUIRE(varRetained == Approx(0.904876047045906).epsilon(1e-7)); data = origData; varRetained = p.Apply(data, 0.905); - BOOST_REQUIRE_EQUAL(data.n_rows, 3); - BOOST_REQUIRE_EQUAL(data.n_cols, 5); - BOOST_REQUIRE_CLOSE(varRetained, 1.0, 1e-5); + REQUIRE(data.n_rows == 3); + REQUIRE(data.n_cols == 5); + REQUIRE(varRetained == Approx(1.0).epsilon(1e-7)); data = origData; varRetained = p.Apply(data, 1.0); - BOOST_REQUIRE_EQUAL(data.n_rows, 3); - BOOST_REQUIRE_EQUAL(data.n_cols, 5); - BOOST_REQUIRE_CLOSE(varRetained, 1.0, 1e-5); + REQUIRE(data.n_rows == 3); + REQUIRE(data.n_cols == 5); + REQUIRE(varRetained == Approx(1.0).epsilon(1e-7)); } /** * Compare the output of our exact PCA implementation with Armadillo's. */ -BOOST_AUTO_TEST_CASE(ArmaComparisonExactPCATest) +TEST_CASE("ArmaComparisonExactPCATest", "[PCATest]") { ArmaComparisonPCA(); } @@ -193,7 +190,7 @@ BOOST_AUTO_TEST_CASE(ArmaComparisonExactPCATest) * Compare the output of our randomized block krylov PCA implementation with * Armadillo's. */ -BOOST_AUTO_TEST_CASE(ArmaComparisonRandomizedBlockKrylovPCATest) +TEST_CASE("ArmaComparisonRandomizedBlockKrylovPCATest", "[PCATest]") { RandomizedBlockKrylovSVDPolicy decomposition(5); ArmaComparisonPCA(false, decomposition); @@ -202,7 +199,7 @@ BOOST_AUTO_TEST_CASE(ArmaComparisonRandomizedBlockKrylovPCATest) /** * Compare the output of our randomized-SVD PCA implementation with Armadillo's. */ -BOOST_AUTO_TEST_CASE(ArmaComparisonRandomizedPCATest) +TEST_CASE("ArmaComparisonRandomizedPCATest", "[PCATest]") { ArmaComparisonPCA(); } @@ -211,7 +208,7 @@ BOOST_AUTO_TEST_CASE(ArmaComparisonRandomizedPCATest) * Test that dimensionality reduction with exact-svd PCA works the same way * MATLAB does (which should be correct!). */ -BOOST_AUTO_TEST_CASE(ExactPCADimensionalityReductionTest) +TEST_CASE("ExactPCADimensionalityReductionTest", "[PCATest]") { PCADimensionalityReduction(); } @@ -220,7 +217,7 @@ BOOST_AUTO_TEST_CASE(ExactPCADimensionalityReductionTest) * Test that dimensionality reduction with randomized block krylov PCA works the * same way MATLAB does (which should be correct!). */ -BOOST_AUTO_TEST_CASE(RandomizedBlockKrylovPCADimensionalityReductionTest) +TEST_CASE("RandomizedBlockKrylovPCADimensionalityReductionTest", "[PCATest]") { RandomizedBlockKrylovSVDPolicy decomposition(5); PCADimensionalityReduction(false, @@ -231,7 +228,7 @@ BOOST_AUTO_TEST_CASE(RandomizedBlockKrylovPCADimensionalityReductionTest) * Test that dimensionality reduction with randomized-svd PCA works the same way * MATLAB does (which should be correct!). */ -BOOST_AUTO_TEST_CASE(RandomizedPCADimensionalityReductionTest) +TEST_CASE("RandomizedPCADimensionalityReductionTest", "[PCATest]") { PCADimensionalityReduction(); } @@ -240,7 +237,7 @@ BOOST_AUTO_TEST_CASE(RandomizedPCADimensionalityReductionTest) * Test that dimensionality reduction with QUIC-SVD PCA works the same way * as the Exact-SVD PCA method. */ -BOOST_AUTO_TEST_CASE(QUICPCADimensionalityReductionTest) +TEST_CASE("QUICPCADimensionalityReductionTest", "[PCATest]") { arma::mat data, data1; data::Load("test_data_3_1000.csv", data); @@ -275,16 +272,16 @@ BOOST_AUTO_TEST_CASE(QUICPCADimensionalityReductionTest) } } - BOOST_REQUIRE_GE(successes, 1); - BOOST_REQUIRE_EQUAL(data.n_rows, data1.n_rows); - BOOST_REQUIRE_EQUAL(data.n_cols, data1.n_cols); + REQUIRE(successes >= 1); + REQUIRE(data.n_rows == data1.n_rows); + REQUIRE(data.n_cols == data1.n_cols); } /** * Test that setting the variance retained parameter to perform dimensionality * reduction works using the exact svd PCA method. */ -BOOST_AUTO_TEST_CASE(ExactPCAVarianceRetainedTest) +TEST_CASE("ExactPCAVarianceRetainedTest", "[PCATest]") { PCAVarianceRetained(); } @@ -292,7 +289,7 @@ BOOST_AUTO_TEST_CASE(ExactPCAVarianceRetainedTest) /** * Test that scaling PCA works. */ -BOOST_AUTO_TEST_CASE(PCAScalingTest) +TEST_CASE("PCAScalingTest", "[PCATest]") { // Generate an artificial dataset in 3 dimensions. arma::mat data(3, 5000); @@ -317,25 +314,22 @@ BOOST_AUTO_TEST_CASE(PCAScalingTest) // The first two components of the eigenvector with largest eigenvalue should // be somewhere near sqrt(2) / 2. The third component should be close to // zero. There is noise, of course... - BOOST_REQUIRE_CLOSE(std::abs(eigvec(0, 0)), sqrt(2) / 2, 0.35); - BOOST_REQUIRE_CLOSE(std::abs(eigvec(1, 0)), sqrt(2) / 2, 0.35); - BOOST_REQUIRE_SMALL(eigvec(2, 0), 0.1); // Large tolerance for noise. + REQUIRE(std::abs(eigvec(0, 0)) == Approx(sqrt(2) / 2).epsilon(0.0035)); + REQUIRE(std::abs(eigvec(1, 0)) == Approx(sqrt(2) / 2).epsilon(0.0035)); + REQUIRE(eigvec(2, 0) == Approx(0.0).margin(0.1)); // Large tolerance for noise. // The second component should be focused almost entirely in the third // dimension. - BOOST_REQUIRE_SMALL(eigvec(0, 1), 0.1); - BOOST_REQUIRE_SMALL(eigvec(1, 1), 0.1); - BOOST_REQUIRE_CLOSE(std::abs(eigvec(2, 1)), 1.0, 0.35); + REQUIRE(eigvec(0, 1) == Approx(0.0).margin(0.1)); + REQUIRE(eigvec(1, 1) == Approx(0.0).margin(0.1)); + REQUIRE(std::abs(eigvec(2, 1)) == Approx(1.0).epsilon(0.0035)); // The third component should have the same absolute value characteristics as - // the first (plus 20% tolerance). - BOOST_REQUIRE_CLOSE(std::abs(eigvec(0, 0)), sqrt(2) / 2, 0.35); - BOOST_REQUIRE_CLOSE(std::abs(eigvec(1, 0)), sqrt(2) / 2, 0.35); - BOOST_REQUIRE_SMALL(eigvec(2, 0), 0.1); // Large tolerance for noise. + // the first (plus tolerance). + REQUIRE(std::abs(eigvec(0, 0)) == Approx(sqrt(2) / 2).epsilon(0.0035)); + REQUIRE(std::abs(eigvec(1, 0)) == Approx(sqrt(2) / 2).epsilon(0.0035)); + REQUIRE(eigvec(2, 0) == Approx(0.0).margin(0.1)); // Large tolerance for noise. // The eigenvalues should sum to three. - BOOST_REQUIRE_CLOSE(accu(eigval), 3.0, 0.1); // 10% tolerance. + REQUIRE(accu(eigval) == Approx(3.0).epsilon(0.001)); } - - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index f9b07fddc5..b916ac446f 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -13,20 +13,18 @@ #include #include -#include -#include "test_tools.hpp" -#include "serialization.hpp" +#include "serialization_catch.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" #include "mock_categorical_data.hpp" using namespace mlpack; using namespace mlpack::tree; -BOOST_AUTO_TEST_SUITE(RandomForestTest); - /** * Make sure bootstrap sampling produces numbers in the dataset. */ -BOOST_AUTO_TEST_CASE(BootstrapNoWeightsTest) +TEST_CASE("BootstrapNoWeightsTest", "[RandomForestTest]") { arma::mat dataset(1, 1000); dataset.row(0) = arma::linspace(1000, 1999, 1000); @@ -44,16 +42,16 @@ BOOST_AUTO_TEST_CASE(BootstrapNoWeightsTest) Bootstrap(dataset, labels, weights, bootstrapDataset, bootstrapLabels, bootstrapWeights); - BOOST_REQUIRE_EQUAL(bootstrapDataset.n_cols, 1000); - BOOST_REQUIRE_EQUAL(bootstrapDataset.n_rows, 1); - BOOST_REQUIRE_EQUAL(bootstrapLabels.n_elem, 1000); + REQUIRE(bootstrapDataset.n_cols == 1000); + REQUIRE(bootstrapDataset.n_rows == 1); + REQUIRE(bootstrapLabels.n_elem == 1000); // Check each dataset element. for (size_t i = 0; i < dataset.n_cols; ++i) { - BOOST_REQUIRE_GE(bootstrapDataset(0, i), 1000); - BOOST_REQUIRE_LE(bootstrapDataset(0, i), 1999); - BOOST_REQUIRE_EQUAL(bootstrapLabels[i], 1); + REQUIRE(bootstrapDataset(0, i) >= 1000); + REQUIRE(bootstrapDataset(0, i) <= 1999); + REQUIRE(bootstrapLabels[i] == 1); } } } @@ -61,7 +59,7 @@ BOOST_AUTO_TEST_CASE(BootstrapNoWeightsTest) /** * Make sure bootstrap sampling produces numbers in the dataset. */ -BOOST_AUTO_TEST_CASE(BootstrapWeightsTest) +TEST_CASE("BootstrapWeightsTest", "[RandomForestTest]") { arma::mat dataset(1, 1000); dataset.row(0) = arma::linspace(1000, 1999, 1000); @@ -79,19 +77,19 @@ BOOST_AUTO_TEST_CASE(BootstrapWeightsTest) Bootstrap(dataset, labels, weights, bootstrapDataset, bootstrapLabels, bootstrapWeights); - BOOST_REQUIRE_EQUAL(bootstrapDataset.n_cols, 1000); - BOOST_REQUIRE_EQUAL(bootstrapDataset.n_rows, 1); - BOOST_REQUIRE_EQUAL(bootstrapLabels.n_elem, 1000); - BOOST_REQUIRE_EQUAL(bootstrapWeights.n_elem, 1000); + REQUIRE(bootstrapDataset.n_cols == 1000); + REQUIRE(bootstrapDataset.n_rows == 1); + REQUIRE(bootstrapLabels.n_elem == 1000); + REQUIRE(bootstrapWeights.n_elem == 1000); // Check each dataset element. for (size_t i = 0; i < dataset.n_cols; ++i) { - BOOST_REQUIRE_GE(bootstrapDataset(0, i), 1000); - BOOST_REQUIRE_LE(bootstrapDataset(0, i), 1999); - BOOST_REQUIRE_EQUAL(bootstrapLabels[i], 1); - BOOST_REQUIRE_GE(bootstrapWeights[i], 0.0); - BOOST_REQUIRE_LE(bootstrapWeights[i], 1.0); + REQUIRE(bootstrapDataset(0, i) >= 1000); + REQUIRE(bootstrapDataset(0, i) <= 1999); + REQUIRE(bootstrapLabels[i] == 1); + REQUIRE(bootstrapWeights[i] >= 0.0); + REQUIRE(bootstrapWeights[i] <= 1.0); } } } @@ -99,7 +97,7 @@ BOOST_AUTO_TEST_CASE(BootstrapWeightsTest) /** * Make sure an empty forest cannot predict. */ -BOOST_AUTO_TEST_CASE(EmptyClassifyTest) +TEST_CASE("EmptyClassifyTest", "[RandomForestTest]") { RandomForest<> rf; // No training. @@ -108,11 +106,11 @@ BOOST_AUTO_TEST_CASE(EmptyClassifyTest) arma::mat probabilities; size_t prediction; arma::vec pointProbabilities; - BOOST_REQUIRE_THROW(rf.Classify(points, predictions), std::invalid_argument); - BOOST_REQUIRE_THROW(rf.Classify(points.col(0)), std::invalid_argument); - BOOST_REQUIRE_THROW(rf.Classify(points, predictions, probabilities), + REQUIRE_THROWS_AS(rf.Classify(points, predictions), std::invalid_argument); + REQUIRE_THROWS_AS(rf.Classify(points.col(0)), std::invalid_argument); + REQUIRE_THROWS_AS(rf.Classify(points, predictions, probabilities), std::invalid_argument); - BOOST_REQUIRE_THROW(rf.Classify(points.col(0), prediction, + REQUIRE_THROWS_AS(rf.Classify(points.col(0), prediction, pointProbabilities), std::invalid_argument); } @@ -120,7 +118,7 @@ BOOST_AUTO_TEST_CASE(EmptyClassifyTest) * Test unweighted numeric learning, making sure that we get better performance * than a single decision tree. */ -BOOST_AUTO_TEST_CASE(UnweightedNumericLearningTest) +TEST_CASE("UnweightedNumericLearningTest", "[RandomForestTest]") { // Load the vc2 dataset. arma::mat dataset; @@ -148,15 +146,15 @@ BOOST_AUTO_TEST_CASE(UnweightedNumericLearningTest) size_t rfCorrect = arma::accu(rfPredictions == testLabels); size_t dtCorrect = arma::accu(dtPredictions == testLabels); - BOOST_REQUIRE_GE(rfCorrect, dtCorrect * 0.9); - BOOST_REQUIRE_GE(rfCorrect, size_t(0.7 * testDataset.n_cols)); + REQUIRE(rfCorrect >= dtCorrect * 0.9); + REQUIRE(rfCorrect >= size_t(0.7 * testDataset.n_cols)); } /** * Test weighted numeric learning, making sure that we get better performance * than a single decision tree. */ -BOOST_AUTO_TEST_CASE(WeightedNumericLearningTest) +TEST_CASE("WeightedNumericLearningTest", "[RandomForestTest]") { arma::mat dataset; arma::Row labels; @@ -200,15 +198,15 @@ BOOST_AUTO_TEST_CASE(WeightedNumericLearningTest) size_t rfCorrect = arma::accu(rfPredictions == testLabels); size_t dtCorrect = arma::accu(dtPredictions == testLabels); - BOOST_REQUIRE_GE(rfCorrect, dtCorrect * 0.9); - BOOST_REQUIRE_GE(rfCorrect, size_t(0.7 * testDataset.n_cols)); + REQUIRE(rfCorrect >= dtCorrect * 0.9); + REQUIRE(rfCorrect >= size_t(0.7 * testDataset.n_cols)); } /** * Test unweighted categorical learning. Ensure that we get better performance * with a random forest. */ -BOOST_AUTO_TEST_CASE(UnweightedCategoricalLearningTest) +TEST_CASE("UnweightedCategoricalLearningTest", "[RandomForestTest]") { arma::mat d; arma::Row l; @@ -237,14 +235,14 @@ BOOST_AUTO_TEST_CASE(UnweightedCategoricalLearningTest) size_t rfCorrect = arma::accu(rfPredictions == testLabels); size_t dtCorrect = arma::accu(dtPredictions == testLabels); - BOOST_REQUIRE_GE(rfCorrect, dtCorrect - 25); - BOOST_REQUIRE_GE(rfCorrect, size_t(0.7 * testData.n_cols)); + REQUIRE(rfCorrect >= dtCorrect - 25); + REQUIRE(rfCorrect >= size_t(0.7 * testData.n_cols)); } /** * Test weighted categorical learning. */ -BOOST_AUTO_TEST_CASE(WeightedCategoricalLearningTest) +TEST_CASE("WeightedCategoricalLearningTest", "[RandomForestTest]") { arma::mat d; arma::Row l; @@ -295,14 +293,14 @@ BOOST_AUTO_TEST_CASE(WeightedCategoricalLearningTest) size_t rfCorrect = arma::accu(rfPredictions == testLabels); size_t dtCorrect = arma::accu(dtPredictions == testLabels); - BOOST_REQUIRE_GE(rfCorrect, dtCorrect - 25); - BOOST_REQUIRE_GE(rfCorrect, size_t(0.7 * testData.n_cols)); + REQUIRE(rfCorrect >= dtCorrect - 25); + REQUIRE(rfCorrect >= size_t(0.7 * testData.n_cols)); } /** * Test that a leaf size equal to the dataset size learns nothing. */ -BOOST_AUTO_TEST_CASE(LeafSizeDatasetTest) +TEST_CASE("LeafSizeDatasetTest", "[RandomForestTest]") { // Load the vc2 dataset. arma::mat dataset; @@ -324,19 +322,19 @@ BOOST_AUTO_TEST_CASE(LeafSizeDatasetTest) size_t majorityClass = predictions[0]; arma::vec majorityProbs = probabilities.col(0); - BOOST_REQUIRE_EQUAL(probabilities.n_rows, 3); - BOOST_REQUIRE_EQUAL(probabilities.n_cols, dataset.n_cols); - BOOST_REQUIRE_EQUAL(predictions.n_elem, dataset.n_cols); + REQUIRE(probabilities.n_rows == 3); + REQUIRE(probabilities.n_cols == dataset.n_cols); + REQUIRE(predictions.n_elem == dataset.n_cols); for (size_t i = 1; i < predictions.n_cols; ++i) { - BOOST_REQUIRE_EQUAL(predictions[i], majorityClass); + REQUIRE(predictions[i] == majorityClass); for (size_t j = 0; j < probabilities.n_rows; ++j) - BOOST_REQUIRE_CLOSE(probabilities(j, i), majorityProbs[j], 1e-5); + REQUIRE(probabilities(j, i) == Approx(majorityProbs[j]).epsilon(1e-7)); } } // Make sure we can serialize a random forest. -BOOST_AUTO_TEST_CASE(SerializationTest) +TEST_CASE("RandomForestSerializationTest", "[RandomForestTest]") { // Load the vc2 dataset. arma::mat dataset; @@ -372,7 +370,7 @@ BOOST_AUTO_TEST_CASE(SerializationTest) * Test that RandomForest::Train() returns finite average entropy on numeric * dataset. */ -BOOST_AUTO_TEST_CASE(RandomForestNumericTrainReturnEntropy) +TEST_CASE("RandomForestNumericTrainReturnEntropy", "[RandomForestTest]") { arma::mat dataset; arma::Row labels; @@ -400,20 +398,20 @@ BOOST_AUTO_TEST_CASE(RandomForestNumericTrainReturnEntropy) RandomForest rf; double entropy = rf.Train(dataset, labels, 3, 10, 1); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); // Test random forest on weighted numeric dataset. RandomForest wrf; entropy = wrf.Train(dataset, labels, 3, weights, 10, 1); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); } /** * Test that RandomForest::Train() returns finite average entropy on categorical * dataset. */ -BOOST_AUTO_TEST_CASE(RandomForestCategoricalTrainReturnEntropy) +TEST_CASE("RandomForestCategoricalTrainReturnEntropy", "[RandomForestTest]") { arma::mat d; arma::Row l; @@ -447,20 +445,20 @@ BOOST_AUTO_TEST_CASE(RandomForestCategoricalTrainReturnEntropy) double entropy = rf.Train(fullData, di, fullLabels, 5, 15 /* 15 trees */, 1, 1e-7, 0, MultipleRandomDimensionSelect(3)); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); // Test random forest on weighted categorical dataset. RandomForest<> wrf; entropy = wrf.Train(fullData, di, fullLabels, 5, weights, 15 /* 15 trees */, 1, 1e-7, 0, MultipleRandomDimensionSelect(3)); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); } /** * Test that different trees get generated. */ -BOOST_AUTO_TEST_CASE(DifferentTreesTest) +TEST_CASE("DifferentTreesTest", "[RandomForestTest]") { arma::mat d(10, 100, arma::fill::randu); arma::Row l(100); @@ -484,7 +482,5 @@ BOOST_AUTO_TEST_CASE(DifferentTreesTest) ++trial; } - BOOST_REQUIRE_EQUAL(success, true); + REQUIRE(success == true); } - -BOOST_AUTO_TEST_SUITE_END();