Merge branch 'master' into cereal

Signed-off-by: Omar Shrit <omar@shrit.me>
This commit is contained in:
Omar Shrit
2020-10-03 12:58:14 +02:00
23 changed files with 895 additions and 563 deletions
+59 -1
View File
@@ -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')"
+3 -1
View File
@@ -132,7 +132,9 @@ Copyright:
Copyright 2020, Lakshya Ojha <ojhalakshya@gmail.com>
Copyright 2020, Bisakh Mondal <bisakhmondal00@gmail.com>
Copyright 2020, Benson Muite <benson_muite@emailplus.org>
Copyright 2020, Sarthak Bhardwaj <7sarthakbhardwaj@gmail.com>
Copyright 2020, Sarthak Bhardwaj <7sarthakbhardwaj@gmail.com>
Copyright 2020, Aakash Kaushik <kaushikaakash7539@gmail.com>
Copyright 2020, Anush Kini <anushkini@gmail.com>
License: BSD-3-clause
All rights reserved.
+2
View File
@@ -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
@@ -116,6 +116,8 @@ set(SOURCES
celu_impl.hpp
softshrink.hpp
softshrink_impl.hpp
softmin.hpp
softmin_impl.hpp
)
# Add directory name to sources.
+3
View File
@@ -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
*/
@@ -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.
*/
+1
View File
@@ -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"
+6
View File
@@ -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
*/
+97
View File
@@ -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 <mlpack/prereqs.hpp>
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<typename InputType, typename OutputType>
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<typename eT>
void Backward(const arma::Mat<eT>& input,
const arma::Mat<eT>& gy,
arma::Mat<eT>& 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<typename Archive>
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
@@ -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<typename InputDataType, typename OutputDataType>
Softmin<InputDataType, OutputDataType>::Softmin()
{
// Nothing to do here.
}
template<typename InputDataType, typename OutputDataType>
template<typename InputType, typename OutputType>
void Softmin<InputDataType, OutputDataType>::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<typename InputDataType, typename OutputDataType>
template<typename eT>
void Softmin<InputDataType, OutputDataType>::Backward(
const arma::Mat<eT>& input,
const arma::Mat<eT>& gy,
arma::Mat<eT>& g)
{
g = input % (gy - arma::repmat(arma::sum(gy % input), input.n_rows, 1));
}
template<typename InputDataType, typename OutputDataType>
template<typename Archive>
void Softmin<InputDataType, OutputDataType>::serialize(
Archive& /* ar */,
const unsigned int /* version */)
{
// Nothing to do here.
}
} // namespace ann
} // namespace mlpack
#endif
+10 -11
View File
@@ -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)
@@ -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<arma::colvec>(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<GaussianFunction>(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);
}
+34
View File
@@ -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);
}
+43 -46
View File
@@ -11,18 +11,17 @@
*/
#include <mlpack/core.hpp>
#include <boost/test/unit_test.hpp>
#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<mat>(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();
+64 -68
View File
@@ -13,17 +13,15 @@
#include <mlpack/methods/dbscan/dbscan.hpp>
#include <mlpack/methods/dbscan/random_point_selection.hpp>
#include <boost/test/unit_test.hpp>
#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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<size_t> 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();
+158 -162
View File
@@ -36,19 +36,17 @@
#include <mlpack/methods/ann/init_rules/nguyen_widrow_init.hpp>
#include <mlpack/methods/ann/ffn.hpp>
#include <boost/test/unit_test.hpp>
#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();
+46 -41
View File
@@ -19,8 +19,8 @@ static const std::string testName = "DBSCAN";
#include "test_helper.hpp"
#include <mlpack/methods/dbscan/dbscan_main.cpp>
#include <boost/test/unit_test.hpp>
#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<arma::Row<size_t>>("assignments").n_cols,
inputSize);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::Row<size_t>>("assignments").n_rows,
1);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("centroids").n_rows, 4);
BOOST_REQUIRE_GE(IO::GetParam<arma::mat>("centroids").n_cols, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("assignments").n_cols == inputSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("assignments").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("centroids").n_rows == 4);
REQUIRE(IO::GetParam<arma::mat>("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<arma::Row<size_t>>("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<size_t> output2;
output2 = std::move(IO::GetParam<arma::Row<size_t>>("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<size_t> output2;
output2 = std::move(IO::GetParam<arma::Row<size_t>>("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<size_t> randomOutput;
randomOutput = std::move(IO::GetParam<arma::Row<size_t>>("assignments"));
BOOST_REQUIRE_GT(arma::accu(orderedOutput != randomOutput), 0);
REQUIRE(arma::accu(orderedOutput != randomOutput) > 0);
}
BOOST_AUTO_TEST_SUITE_END();
+40 -29
View File
@@ -12,15 +12,16 @@
#include <string>
#define BINDING_TYPE BINDING_TYPE_TEST
static const std::string testName = "MeanShift";
#include <mlpack/core.hpp>
static const std::string testName = "MeanShift";
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/methods/mean_shift/mean_shift_main.cpp>
#include "test_helper.hpp"
#include <boost/test/unit_test.hpp>
#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<arma::mat>("output").n_rows, 3 + 1);
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == 3 + 1);
// Check number of output points are the same.
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, 100);
REQUIRE(IO::GetParam<arma::mat>("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<arma::mat>("output").n_rows, 1);
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == 1);
// Check number of output points are the same.
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, 100);
REQUIRE(IO::GetParam<arma::mat>("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<arma::mat>("output").n_rows, numRows + 1);
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == numRows + 1);
// Check number of output points are the same.
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, numCols);
REQUIRE(IO::GetParam<arma::mat>("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<arma::mat>("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<arma::mat>("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<arma::mat>("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();
+16 -17
View File
@@ -19,8 +19,7 @@ static const std::string testName = "PrincipalComponentAnalysis";
#include "test_helper.hpp"
#include <mlpack/methods/pca/pca_main.cpp>
#include <boost/test/unit_test.hpp>
#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<arma::mat>(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<arma::mat>("output").n_rows, 3);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, 5);
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == 3);
REQUIRE(IO::GetParam<arma::mat>("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<arma::mat>(4, 5);
@@ -77,14 +76,15 @@ BOOST_AUTO_TEST_CASE(PCAVarRetainTest)
mlpackMain();
// Check that the output has 5 dimensions.
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_rows, 4);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, 5);
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == 4);
REQUIRE(IO::GetParam<arma::mat>("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<arma::mat>(5, 5);
@@ -96,14 +96,15 @@ BOOST_AUTO_TEST_CASE(PCANoVarRetainTest)
mlpackMain();
// Check that the output has 1 dimensions.
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_rows, 1);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, 5);
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("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<arma::mat>(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();
@@ -18,8 +18,8 @@ static const std::string testName = "RandomForest";
#include <mlpack/methods/random_forest/random_forest_main.cpp>
#include "test_helper.hpp"
#include <boost/test/unit_test.hpp>
#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<size_t> 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<arma::Row<size_t>>("predictions").n_cols,
testSize);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_cols,
testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("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<arma::Row<size_t>>("predictions").n_rows,
1);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_rows, 3);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("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<size_t> 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<arma::Row<size_t>>("predictions").n_cols,
testSize);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_cols,
testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("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<arma::Row<size_t>>("predictions").n_rows,
1);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_rows, 3);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 3);
// Check that initial predictions and predictions using saved model are same.
CheckMatrices(predictions, IO::GetParam<arma::Row<size_t>>("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<size_t> 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<size_t> 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<size_t> 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<size_t> 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<RandomForestModel*>("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<size_t> 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<size_t> 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<size_t> 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<RandomForestModel*>("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<size_t> 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();
+11 -15
View File
@@ -12,15 +12,13 @@
#include <mlpack/methods/mean_shift/mean_shift.hpp>
#include <boost/test/unit_test.hpp>
#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<arma::mat>(3, 3));
GaussianDistribution g2("5.0 5.0 5.0", 2 * arma::eye<arma::mat>(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();
+49 -55
View File
@@ -17,10 +17,7 @@
#include <mlpack/methods/pca/decomposition_policies/randomized_svd_method.hpp>
#include <mlpack/methods/pca/decomposition_policies/randomized_block_krylov_method.hpp>
#include <boost/test/unit_test.hpp>
#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<ExactSVDPolicy>();
}
@@ -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<RandomizedBlockKrylovSVDPolicy>(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<RandomizedSVDPolicy>();
}
@@ -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<ExactSVDPolicy>();
}
@@ -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<RandomizedBlockKrylovSVDPolicy>(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<RandomizedSVDPolicy>();
}
@@ -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<ExactSVDPolicy>();
}
@@ -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();
+52 -56
View File
@@ -13,20 +13,18 @@
#include <mlpack/methods/random_forest/random_forest.hpp>
#include <mlpack/methods/decision_tree/random_dimension_select.hpp>
#include <boost/test/unit_test.hpp>
#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<arma::rowvec>(1000, 1999, 1000);
@@ -44,16 +42,16 @@ BOOST_AUTO_TEST_CASE(BootstrapNoWeightsTest)
Bootstrap<false>(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<arma::rowvec>(1000, 1999, 1000);
@@ -79,19 +77,19 @@ BOOST_AUTO_TEST_CASE(BootstrapWeightsTest)
Bootstrap<true>(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<size_t> 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<size_t> 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<size_t> 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<size_t> labels;
@@ -400,20 +398,20 @@ BOOST_AUTO_TEST_CASE(RandomForestNumericTrainReturnEntropy)
RandomForest<GiniGain, RandomDimensionSelect> 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<GiniGain, RandomDimensionSelect> 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<size_t> 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<size_t> 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();