updating range_search_test with mlpack/master (#7)

* softmin activation function added

* shift added

* shift changed for inputmax to inputmin

* Test added for softmin forward function

* errors fixed

* suggested changes

* forward function fixed

* added softmin to HISTORY.md

* forward result calculation source changed

* space added in comment

* backward function added

* backward test function added, values left

* Added WeightSize() to

linear.hpp
atrous_convolution.hpp
add.hpp.

* tests made similar to softmax

* conflict fix

* fixed HISTORY.md conflict

* tests made similar to softmax

* Update activation_functions_test.cpp

* Removed header iostream

* Apply suggestions from code review

Co-authored-by: Marcus Edel <marcus.edel@fu-berlin.de>
Co-authored-by: Ryan Curtin <ryan@ratml.org>
Include bias term in linear layer.

* catch2 for mean_shift_test.cpp

* fixed backward function

* reverted changes to main/mean_shift_test.cpp

* corrected the test cases

* main/mean_shift_test.cpp from boost to catch2

* migrated mean_shift_test from boost to catch2

* tests changed

* tests changed

* Test for WeightSetVisitor and WeightSizeVisitor

* Fix common failures by increasing threshold

* Typo fix

* Auto Cancel build on new push and enable cache for build.

* Windows fix.

* Install R-bindings dependencies separately.

* rcmdcheck doesn't for building mlpack_r_tarball.

* Install roxygen2.

* Specify platform in windows build.

* Stop github actions running on a forked repo.

* softmin activation function added

shift added

shift changed for inputmax to inputmin

Test added for softmin forward function

errors fixed

suggested changes

forward function fixed

added softmin to HISTORY.md

forward result calculation source changed

space added in comment

backward function added

backward test function added, values left

tests made similar to softmax

conflict fix

fixed HISTORY.md conflict

tests made similar to softmax

Update activation_functions_test.cpp

Removed header iostream

fixed backward function

reverted changes to main/mean_shift_test.cpp

corrected the test cases

tests changed

tests changed

* Fix static issues

* All static issue fixed (hopefully)

* Migrate det and distribution test to catch2

Co-authored-by: Utkarsh Rai <utkarshrai491@gmail.com>
Co-authored-by: kartikdutt18 <kartikdutt@live.in>
Co-authored-by: Yashwant <yashwantsingh.sngh@gmail.com>
Co-authored-by: Ryan Curtin <ryan@ratml.org>
Co-authored-by: kartikdutt18 <39593019+kartikdutt18@users.noreply.github.com>
Co-authored-by: Ryan Birmingham <birm@gatech.edu>
Co-authored-by: jeffin143 <jeffinsam@karunya.edu.in>
This commit is contained in:
Aakash kaushik
2020-10-06 00:41:50 +05:30
committed by GitHub
co-authored by Utkarsh Rai kartikdutt18 Yashwant Ryan Curtin kartikdutt18 Ryan Birmingham jeffin143
parent d4c74c74ce
commit 403b11ebbe
20 changed files with 1055 additions and 700 deletions
+1
View File
@@ -78,6 +78,7 @@ steps:
msbuildVersion: $(MSBuildVersion)
configuration: 'Release'
msbuildArchitecture: 'x64'
platform: 'x64'
msbuildArguments: /m /p:BuildInParallel=true
maximumCpuCount: false
clean: false
+59 -7
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,16 +45,35 @@ 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
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev
curl https://data.kurg.org/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
cmake . && make && sudo make install && cd ..
sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu xenial-cran40/'
sudo apt-get -y update
sudo apt-get install -y r-base-core
sudo Rscript -e "install.packages(c('Rcpp', 'RcppArmadillo', 'RcppEnsmallen', 'BH', 'roxygen2', 'testthat'))"
- name: Install R-bindings dependencies
run: |
remotes::install_deps(dependencies = TRUE)
remotes::install_cran("roxygen2")
shell: Rscript {0}
- name: CMake
run: |
@@ -58,6 +95,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 +112,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 +126,22 @@ 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'))"
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')"
+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
+4 -4
View File
@@ -8,8 +8,6 @@ add_executable(mlpack_test
io_test.cpp
cosine_tree_test.cpp
dcgan_test.cpp
det_test.cpp
distribution_test.cpp
drusilla_select_test.cpp
emst_test.cpp
fastmks_test.cpp
@@ -36,7 +34,6 @@ add_executable(mlpack_test
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
@@ -92,7 +89,6 @@ 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/perceptron_test.cpp
@@ -122,6 +118,8 @@ add_executable(mlpack_catch_test
dbscan_test.cpp
decision_stump_test.cpp
decision_tree_test.cpp
det_test.cpp
distribution_test.cpp
feedforward_network_test.cpp
image_load_test.cpp
imputation_test.cpp
@@ -135,6 +133,7 @@ add_executable(mlpack_catch_test
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
@@ -168,6 +167,7 @@ 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
@@ -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);
}
+93 -108
View File
@@ -87,11 +87,10 @@ TEST_CASE("GradientAddLayerTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -416,11 +415,10 @@ TEST_CASE("GradientLinearLayerTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -508,13 +506,12 @@ TEST_CASE("GradientLinear3DLayerTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
inSize(4),
outSize(1),
nPoints(2),
batchSize(4)
{
const size_t inSize = 4;
const size_t outSize = 1;
const size_t nPoints = 2;
const size_t batchSize = 4;
input = arma::randu(inSize * nPoints, batchSize);
target = arma::zeros(outSize * nPoints, batchSize);
target(0, 0) = 1;
@@ -545,6 +542,10 @@ TEST_CASE("GradientLinear3DLayerTest", "[ANNLayerTest]")
FFN<MeanSquaredError<>, RandomInitialization>* model;
arma::mat input, target;
const size_t inSize;
const size_t outSize;
const size_t nPoints;
const size_t batchSize;
} function;
REQUIRE(CheckGradient(function) <= 1e-7);
@@ -591,11 +592,10 @@ TEST_CASE("GradientNoisyLinearLayerTest", "[ANNLayerTest]")
// Noisy linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -695,11 +695,10 @@ TEST_CASE("GradientLinearNoBiasLayerTest", "[ANNLayerTest]")
// LinearNoBias function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -797,11 +796,10 @@ TEST_CASE("GradientFlexibleReLULayerTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(2, 1)),
target(arma::mat("1"))
{
input = arma::randu(2, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, RandomInitialization>(
NegativeLogLikelihood<>(), RandomInitialization(0.1, 0.5));
@@ -1017,10 +1015,10 @@ TEST_CASE("GradientLSTMLayerTest", "[ANNLayerTest]")
// LSTM function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(1, 1, 5)),
target(arma::ones(1, 1, 5))
{
input = arma::randu(1, 1, 5);
target.ones(1, 1, 5);
const size_t rho = 5;
model = new RNN<NegativeLogLikelihood<> >(rho);
@@ -1122,10 +1120,10 @@ TEST_CASE("GradientFastLSTMLayerTest", "[ANNLayerTest]")
// Fast LSTM function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(1, 1, 5)),
target(arma::ones(1, 1, 5))
{
input = arma::randu(1, 1, 5);
target = arma::ones(1, 1, 5);
const size_t rho = 5;
model = new RNN<NegativeLogLikelihood<> >(rho);
@@ -1391,10 +1389,10 @@ TEST_CASE("GradientGRULayerTest", "[ANNLayerTest]")
// GRU function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(1, 1, 5)),
target(arma::ones(1, 1, 5))
{
input = arma::randu(1, 1, 5);
target = arma::ones(1, 1, 5);
const size_t rho = 5;
model = new RNN<NegativeLogLikelihood<> >(rho);
@@ -1631,11 +1629,10 @@ TEST_CASE("GradientConcatLayerTest", "[ANNLayerTest]")
// Concat function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -1700,11 +1697,10 @@ TEST_CASE("GradientConcatenateLayerTest", "[ANNLayerTest]")
// Concatenate function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -1905,11 +1901,10 @@ TEST_CASE("GradientSoftmaxTest", "[ANNLayerTest]")
// Softmax function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1; 0"))
{
input = arma::randu(10, 1);
target = arma::mat("1; 0");
model = new FFN<MeanSquaredError<>, RandomInitialization>;
model->Predictors() = input;
model->Responses() = target;
@@ -2109,12 +2104,10 @@ TEST_CASE("GradientBatchNormTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randn(32, 2048)),
target(arma::ones(1, 2048))
{
input = arma::randn(32, 2048);
arma::mat target;
target.ones(1, 2048);
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -2184,12 +2177,11 @@ TEST_CASE("GradientVirtualBatchNormTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randn(5, 256)),
target(arma::ones(1, 256))
{
input = arma::randn(5, 256);
arma::mat referenceBatch = arma::mat(input.memptr(), input.n_rows, 16);
arma::mat target;
target.ones(1, 256);
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
@@ -2247,12 +2239,10 @@ TEST_CASE("MiniBatchDiscriminationTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randn(5, 4)),
target(arma::ones(1, 4))
{
input = arma::randn(5, 4);
arma::mat target;
target.ones(1, 4);
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -2427,11 +2417,10 @@ TEST_CASE("GradientTransposedConvolutionLayerTest", "[ANNLayerTest]")
{
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::linspace<arma::colvec>(0, 35, 36)),
target(arma::mat("1"))
{
input = arma::linspace<arma::colvec>(0, 35, 36);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, RandomInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -2544,11 +2533,10 @@ TEST_CASE("GradientAtrousConvolutionLayerTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::linspace<arma::colvec>(0, 35, 36)),
target(arma::mat("1"))
{
input = arma::linspace<arma::colvec>(0, 35, 36);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, RandomInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -2575,7 +2563,7 @@ TEST_CASE("GradientAtrousConvolutionLayerTest", "[ANNLayerTest]")
arma::mat input, target;
} function;
// TODO: this tolerance seems far higher than necessary. The implementation
// TODO: this tolerance seems far higher than necessary. The implementation
// should be checked.
REQUIRE(CheckGradient(function) <= 0.2);
}
@@ -2726,12 +2714,10 @@ TEST_CASE("GradientLayerNormTest", "[ANNLayerTest]")
// Add function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randn(10, 256)),
target(arma::ones(1, 256))
{
input = arma::randn(10, 256);
arma::mat target;
target.ones(1, 256);
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -3048,11 +3034,10 @@ TEST_CASE("GradientReparametrizationLayerTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -3092,11 +3077,10 @@ TEST_CASE("GradientReparametrizationLayerBetaTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 2)),
target(arma::mat("1 1"))
{
input = arma::randu(10, 2);
target = arma::mat("1 1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -3248,11 +3232,10 @@ TEST_CASE("GradientHighwayLayerTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(5, 1)),
target(arma::mat("1"))
{
input = arma::randu(5, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -3300,11 +3283,10 @@ TEST_CASE("GradientSequentialLayerTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -3351,11 +3333,10 @@ TEST_CASE("GradientWeightNormLayerTest", "[ANNLayerTest]")
// Linear function gradient instantiation.
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randu(10, 1)),
target(arma::mat("1"))
{
input = arma::randu(10, 1);
target = arma::mat("1");
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -4185,12 +4166,10 @@ TEST_CASE("GradientBatchNormWithMiniBatchesTest", "[ANNLayerTest]")
{
struct GradientFunction
{
GradientFunction()
GradientFunction() :
input(arma::randn(16, 1024)),
target(arma::ones(1, 1024))
{
input = arma::randn(16, 1024);
arma::mat target;
target.ones(1, 1024);
model = new FFN<NegativeLogLikelihood<>, NguyenWidrowInitialization>();
model->Predictors() = input;
model->Responses() = target;
@@ -4683,7 +4662,13 @@ TEST_CASE("GradientMultiheadAttentionTest", "[ANNLayerTest]")
{
struct GradientFunction
{
GradientFunction()
GradientFunction() :
tgtSeqLen(2),
srcSeqLen(2),
embedDim(4),
nHeads(2),
vocabSize(5),
batchSize(2)
{
input = arma::randu(embedDim * (tgtSeqLen + 2 * srcSeqLen), batchSize);
target = arma::zeros(vocabSize, batchSize);
@@ -4736,13 +4721,13 @@ TEST_CASE("GradientMultiheadAttentionTest", "[ANNLayerTest]")
MultiheadAttention<>* attnModule;
arma::mat input, target, attnMask, keyPaddingMask;
const size_t tgtSeqLen = 2;
const size_t srcSeqLen = 2;
const size_t embedDim = 4;
const size_t nHeads = 2;
const size_t vocabSize = 5;
const size_t batchSize = 2;
const size_t tgtSeqLen;
const size_t srcSeqLen;
const size_t embedDim;
const size_t nHeads;
const size_t vocabSize;
const size_t batchSize;
} function;
REQUIRE(CheckGradient(function) <= 2e-06);
REQUIRE(CheckGradient(function) <= 3e-06);
}
+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);
}
+236 -233
View File
@@ -11,8 +11,7 @@
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <mlpack/core.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
// This trick does not work on Windows. We will have to comment out the tests
// that depend on it.
@@ -33,13 +32,11 @@ using namespace mlpack;
using namespace mlpack::det;
using namespace std;
BOOST_AUTO_TEST_SUITE(DETTest);
// Tests for the private functions. We cannot perform these if we are on
// Windows because we cannot make private functions accessible using the macro
// trick above.
#ifndef _WIN32
BOOST_AUTO_TEST_CASE(TestGetMaxMinVals)
TEST_CASE("TestGetMaxMinVals", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -49,15 +46,15 @@ BOOST_AUTO_TEST_CASE(TestGetMaxMinVals)
DTree<arma::mat> tree(testData);
BOOST_REQUIRE_EQUAL(tree.MaxVals()[0], 7);
BOOST_REQUIRE_EQUAL(tree.MinVals()[0], 3);
BOOST_REQUIRE_EQUAL(tree.MaxVals()[1], 7);
BOOST_REQUIRE_EQUAL(tree.MinVals()[1], 0);
BOOST_REQUIRE_EQUAL(tree.MaxVals()[2], 8);
BOOST_REQUIRE_EQUAL(tree.MinVals()[2], 1);
REQUIRE(tree.MaxVals()[0] == 7);
REQUIRE(tree.MinVals()[0] == 3);
REQUIRE(tree.MaxVals()[1] == 7);
REQUIRE(tree.MinVals()[1] == 0);
REQUIRE(tree.MaxVals()[2] == 8);
REQUIRE(tree.MinVals()[2] == 1);
}
BOOST_AUTO_TEST_CASE(TestComputeNodeError)
TEST_CASE("TestComputeNodeError", "[DETTest]")
{
arma::vec maxVals("7 7 8");
arma::vec minVals("3 0 1");
@@ -65,17 +62,18 @@ BOOST_AUTO_TEST_CASE(TestComputeNodeError)
DTree<arma::mat> testDTree(maxVals, minVals, 5);
double trueNodeError = -log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE((double) testDTree.logNegError, trueNodeError, 1e-10);
REQUIRE((double) testDTree.logNegError ==
Approx(trueNodeError).epsilon(1e-12));
testDTree.start = 3;
testDTree.end = 5;
double nodeError = testDTree.LogNegativeError(5);
trueNodeError = 2 * log(2.0 / 5.0) - log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE(nodeError, trueNodeError, 1e-10);
REQUIRE(nodeError == Approx(trueNodeError).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestWithinRange)
TEST_CASE("TestWithinRange", "[DETTest]")
{
arma::vec maxVals("7 7 8");
arma::vec minVals("3 0 1");
@@ -85,14 +83,14 @@ BOOST_AUTO_TEST_CASE(TestWithinRange)
arma::vec testQuery(3);
testQuery << 4.5 << 2.5 << 2;
BOOST_REQUIRE_EQUAL(testDTree.WithinRange(testQuery), true);
REQUIRE(testDTree.WithinRange(testQuery) == true);
testQuery << 8.5 << 2.5 << 2;
BOOST_REQUIRE_EQUAL(testDTree.WithinRange(testQuery), false);
REQUIRE(testDTree.WithinRange(testQuery) == false);
}
BOOST_AUTO_TEST_CASE(TestFindSplit)
TEST_CASE("TestFindSplit", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -108,20 +106,21 @@ BOOST_AUTO_TEST_CASE(TestFindSplit)
size_t trueDim = 2;
double trueSplit = 5.5;
double trueLeftError = 2 * log(2.0 / 5.0) - (log(7.0) + log(4.0) + log(4.5));
double trueRightError = 2 * log(3.0 / 5.0) - (log(7.0) + log(4.0) + log(2.5));
double trueRightError = 2 * log(3.0 / 5.0) - (log(7.0) + log(4.0) +
log(2.5));
testDTree.logVolume = log(7.0) + log(4.0) + log(7.0);
BOOST_REQUIRE(testDTree.FindSplit(
REQUIRE(testDTree.FindSplit(
testData, obDim, obSplit, obLeftError, obRightError, 1));
BOOST_REQUIRE(trueDim == obDim);
BOOST_REQUIRE_CLOSE(trueSplit, obSplit, 1e-10);
REQUIRE(trueDim == obDim);
REQUIRE(trueSplit == Approx(obSplit).epsilon(1e-12));
BOOST_REQUIRE_CLOSE(trueLeftError, obLeftError, 1e-10);
BOOST_REQUIRE_CLOSE(trueRightError, obRightError, 1e-10);
REQUIRE(trueLeftError == Approx(obLeftError).epsilon(1e-12));
REQUIRE(trueRightError == Approx(obRightError).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestSplitData)
TEST_CASE("TestSplitData", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -140,16 +139,16 @@ BOOST_AUTO_TEST_CASE(TestSplitData)
size_t splitInd = testDTree.SplitData(
testData, splitDim, trueSplitVal, oTest);
BOOST_REQUIRE_EQUAL(splitInd, 2); // 2 points on left side.
REQUIRE(splitInd == 2); // 2 points on left side.
BOOST_REQUIRE_EQUAL(oTest[0], 1);
BOOST_REQUIRE_EQUAL(oTest[1], 4);
BOOST_REQUIRE_EQUAL(oTest[2], 3);
BOOST_REQUIRE_EQUAL(oTest[3], 2);
BOOST_REQUIRE_EQUAL(oTest[4], 5);
REQUIRE(oTest[0] == 1);
REQUIRE(oTest[1] == 4);
REQUIRE(oTest[2] == 3);
REQUIRE(oTest[3] == 2);
REQUIRE(oTest[4] == 5);
}
BOOST_AUTO_TEST_CASE(TestSparseFindSplit)
TEST_CASE("TestSparseFindSplit", "[DETTest]")
{
arma::mat realData(4, 7);
@@ -173,17 +172,17 @@ BOOST_AUTO_TEST_CASE(TestSparseFindSplit)
(log(7.0) + log(6.5) + log(8.0) + log(6.0));
testDTree.logVolume = log(7.0) + log(7.0) + log(8.0) + log(6.0);
BOOST_REQUIRE(testDTree.FindSplit(
REQUIRE(testDTree.FindSplit(
testData, obDim, obSplit, obLeftError, obRightError, 1));
BOOST_REQUIRE(trueDim == obDim);
BOOST_REQUIRE_CLOSE(trueSplit, obSplit, 1e-10);
REQUIRE(trueDim == obDim);
REQUIRE(trueSplit == Approx(obSplit).epsilon(1e-12));
BOOST_REQUIRE_CLOSE(trueLeftError, obLeftError, 1e-10);
BOOST_REQUIRE_CLOSE(trueRightError, obRightError, 1e-10);
REQUIRE(trueLeftError == Approx(obLeftError).epsilon(1e-12));
REQUIRE(trueRightError == Approx(obRightError).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestSparseSplitData)
TEST_CASE("TestSparseSplitData", "[DETTest]")
{
arma::mat realData(4, 7);
@@ -205,22 +204,22 @@ BOOST_AUTO_TEST_CASE(TestSparseSplitData)
size_t splitInd = testDTree.SplitData(
testData, splitDim, trueSplitVal, oTest);
BOOST_REQUIRE_EQUAL(splitInd, 3); // 2 points on left side.
REQUIRE(splitInd == 3); // 2 points on left side.
BOOST_REQUIRE_EQUAL(oTest[0], 1);
BOOST_REQUIRE_EQUAL(oTest[1], 4);
BOOST_REQUIRE_EQUAL(oTest[2], 3);
BOOST_REQUIRE_EQUAL(oTest[3], 2);
BOOST_REQUIRE_EQUAL(oTest[4], 5);
BOOST_REQUIRE_EQUAL(oTest[5], 6);
BOOST_REQUIRE_EQUAL(oTest[6], 7);
REQUIRE(oTest[0] == 1);
REQUIRE(oTest[1] == 4);
REQUIRE(oTest[2] == 3);
REQUIRE(oTest[3] == 2);
REQUIRE(oTest[4] == 5);
REQUIRE(oTest[5] == 6);
REQUIRE(oTest[6] == 7);
}
#endif
// Tests for the public functions.
BOOST_AUTO_TEST_CASE(TestGrow)
TEST_CASE("TestGrow", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -244,34 +243,36 @@ BOOST_AUTO_TEST_CASE(TestGrow)
DTree<arma::mat> testDTree(testData);
double alpha = testDTree.Grow(testData, oTest, false, 2, 1);
BOOST_REQUIRE_EQUAL(oTest[0], 0);
BOOST_REQUIRE_EQUAL(oTest[1], 3);
BOOST_REQUIRE_EQUAL(oTest[2], 1);
BOOST_REQUIRE_EQUAL(oTest[3], 2);
BOOST_REQUIRE_EQUAL(oTest[4], 4);
REQUIRE(oTest[0] == 0);
REQUIRE(oTest[1] == 3);
REQUIRE(oTest[2] == 1);
REQUIRE(oTest[3] == 2);
REQUIRE(oTest[4] == 4);
// Test the structure of the tree.
BOOST_REQUIRE(testDTree.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree.Right()->Right()->Right() == NULL);
REQUIRE(testDTree.Left()->Left() == NULL);
REQUIRE(testDTree.Left()->Right() == NULL);
REQUIRE(testDTree.Right()->Left()->Left() == NULL);
REQUIRE(testDTree.Right()->Left()->Right() == NULL);
REQUIRE(testDTree.Right()->Right()->Left() == NULL);
REQUIRE(testDTree.Right()->Right()->Right() == NULL);
BOOST_REQUIRE(testDTree.SubtreeLeaves() == 3);
REQUIRE(testDTree.SubtreeLeaves() == 3);
BOOST_REQUIRE(testDTree.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree.SplitDim() == 2);
REQUIRE(testDTree.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree.Right()->SplitDim() == 1);
REQUIRE(testDTree.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
// Test node errors for every node (these are private functions).
#ifndef _WIN32
BOOST_REQUIRE_CLOSE(testDTree.logNegError, rootError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Left()->logNegError, lError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Right()->logNegError, rError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Right()->Left()->logNegError, rlError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Right()->Right()->logNegError, rrError, 1e-10);
REQUIRE(testDTree.logNegError == Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.Left()->logNegError == Approx(lError).epsilon(1e-12));
REQUIRE(testDTree.Right()->logNegError == Approx(rError).epsilon(1e-12));
REQUIRE(testDTree.Right()->Left()->logNegError ==
Approx(rlError).epsilon(1e-12));
REQUIRE(testDTree.Right()->Right()->logNegError ==
Approx(rrError).epsilon(1e-12));
#endif
// Test alpha.
@@ -281,10 +282,10 @@ BOOST_AUTO_TEST_CASE(TestGrow)
rAlpha = std::log(-(std::exp(rError) - (std::exp(rlError) +
std::exp(rrError))));
BOOST_REQUIRE_CLOSE(alpha, min(rootAlpha, rAlpha), 1e-10);
REQUIRE(alpha == Approx(min(rootAlpha, rAlpha)).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestPruneAndUpdate)
TEST_CASE("TestPruneAndUpdate", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -298,18 +299,19 @@ BOOST_AUTO_TEST_CASE(TestPruneAndUpdate)
double alpha = testDTree.Grow(testData, oTest, false, 2, 1);
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
BOOST_REQUIRE_CLOSE(alpha, numeric_limits<double>::max(), 1e-10);
BOOST_REQUIRE(testDTree.SubtreeLeaves() == 1);
REQUIRE(alpha == Approx(numeric_limits<double>::max()).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeaves() == 1);
double rootError = -log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE(testDTree.LogNegError(), rootError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.SubtreeLeavesLogNegError(), rootError, 1e-10);
BOOST_REQUIRE(testDTree.Left() == NULL);
BOOST_REQUIRE(testDTree.Right() == NULL);
REQUIRE(testDTree.LogNegError() == Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeavesLogNegError() ==
Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.Left() == NULL);
REQUIRE(testDTree.Right() == NULL);
}
BOOST_AUTO_TEST_CASE(TestComputeValue)
TEST_CASE("TestComputeValue", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -334,22 +336,22 @@ BOOST_AUTO_TEST_CASE(TestComputeValue)
double d2 = (1.0 / 5.0) / exp(log(4.0) + log(0.5) + log(2.5));
double d3 = (2.0 / 5.0) / exp(log(4.0) + log(6.5) + log(2.5));
BOOST_REQUIRE_CLOSE(d1, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d2, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d3, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d1 == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d2 == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d3 == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0));
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestVariableImportance)
TEST_CASE("TestVariableImportance", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -377,12 +379,14 @@ BOOST_AUTO_TEST_CASE(TestVariableImportance)
testDTree.ComputeVariableImportance(imps);
BOOST_REQUIRE_CLOSE((double) 0.0, imps[0], 1e-10);
BOOST_REQUIRE_CLOSE((double) (rError - (rlError + rrError)), imps[1], 1e-10);
BOOST_REQUIRE_CLOSE((double) (rootError - (lError + rError)), imps[2], 1e-10);
REQUIRE((double) 0.0 == Approx(imps[0]).epsilon(1e-12));
REQUIRE((double) (rError - (rlError + rrError)) ==
Approx(imps[1]).epsilon(1e-12));
REQUIRE((double) (rootError - (lError + rError)) ==
Approx(imps[2]).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestSparsePruneAndUpdate)
TEST_CASE("TestSparsePruneAndUpdate", "[DETTest]")
{
arma::mat realData(3, 5);
@@ -399,18 +403,19 @@ BOOST_AUTO_TEST_CASE(TestSparsePruneAndUpdate)
double alpha = testDTree.Grow(testData, oTest, false, 2, 1);
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
BOOST_REQUIRE_CLOSE(alpha, numeric_limits<double>::max(), 1e-10);
BOOST_REQUIRE(testDTree.SubtreeLeaves() == 1);
REQUIRE(alpha == Approx(numeric_limits<double>::max()).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeaves() == 1);
double rootError = -log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE(testDTree.LogNegError(), rootError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.SubtreeLeavesLogNegError(), rootError, 1e-10);
BOOST_REQUIRE(testDTree.Left() == NULL);
BOOST_REQUIRE(testDTree.Right() == NULL);
REQUIRE(testDTree.LogNegError() == Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeavesLogNegError() ==
Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.Left() == NULL);
REQUIRE(testDTree.Right() == NULL);
}
BOOST_AUTO_TEST_CASE(TestSparseComputeValue)
TEST_CASE("TestSparseComputeValue", "[DETTest]")
{
arma::mat realData(3, 5);
@@ -438,25 +443,25 @@ BOOST_AUTO_TEST_CASE(TestSparseComputeValue)
double d2 = (1.0 / 5.0) / exp(log(4.0) + log(0.5) + log(2.5));
double d3 = (2.0 / 5.0) / exp(log(4.0) + log(6.5) + log(2.5));
BOOST_REQUIRE_CLOSE(d1, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d2, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d3, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d1 == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d2 == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d3 == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0));
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
}
/**
* These are not yet implemented.
*
BOOST_AUTO_TEST_CASE(TestTagTree)
TEST_CASE("TestTagTree", "[DETTest]")
{
MatType testData(3, 5);
@@ -469,7 +474,7 @@ BOOST_AUTO_TEST_CASE(TestTagTree)
delete testDTree;
}
BOOST_AUTO_TEST_CASE(TestFindBucket)
TEST_CASE("TestFindBucket", "[DETTest]")
{
MatType testData(3, 5);
@@ -484,24 +489,24 @@ BOOST_AUTO_TEST_CASE(TestFindBucket)
// Test functions in dt_utils.hpp
BOOST_AUTO_TEST_CASE(TestTrainer)
TEST_CASE("TestTrainer", "[DETTest]")
{
}
BOOST_AUTO_TEST_CASE(TestPrintVariableImportance)
TEST_CASE("TestPrintVariableImportance", "[DETTest]")
{
}
BOOST_AUTO_TEST_CASE(TestPrintLeafMembership)
TEST_CASE("TestPrintLeafMembership", "[DETTest]")
{
}
*/
// Test the copy constructor and the copy operator.
BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorTest)
TEST_CASE("CopyConstructorAndOperatorTest", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -544,76 +549,76 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorTest)
delete testDTree;
// Test the data of copied tree (using copy constructor).
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[2], minVals2);
REQUIRE(testDTree2.MaxVals()[0] == maxVals0);
REQUIRE(testDTree2.MinVals()[0] == minVals0);
REQUIRE(testDTree2.MaxVals()[1] == maxVals1);
REQUIRE(testDTree2.MinVals()[1] == minVals1);
REQUIRE(testDTree2.MaxVals()[2] == maxVals2);
REQUIRE(testDTree2.MinVals()[2] == minVals2);
// Test the data of the copied tree (using the copy operator).
BOOST_REQUIRE_EQUAL(testDTree3.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree3.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree3.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree3.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree3.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree3.MinVals()[2], minVals2);
REQUIRE(testDTree3.MaxVals()[0] == maxVals0);
REQUIRE(testDTree3.MinVals()[0] == minVals0);
REQUIRE(testDTree3.MaxVals()[1] == maxVals1);
REQUIRE(testDTree3.MinVals()[1] == minVals1);
REQUIRE(testDTree3.MaxVals()[2] == maxVals2);
REQUIRE(testDTree3.MinVals()[2] == minVals2);
// Test the structure of the tree copied using the copy constructor.
BOOST_REQUIRE(testDTree2.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
REQUIRE(testDTree2.Left()->Left() == NULL);
REQUIRE(testDTree2.Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
// Test the structure of the tree copied using the copy operator.
BOOST_REQUIRE(testDTree3.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree3.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Right()->Right() == NULL);
REQUIRE(testDTree3.Left()->Left() == NULL);
REQUIRE(testDTree3.Left()->Right() == NULL);
REQUIRE(testDTree3.Right()->Left()->Left() == NULL);
REQUIRE(testDTree3.Right()->Left()->Right() == NULL);
REQUIRE(testDTree3.Right()->Right()->Left() == NULL);
REQUIRE(testDTree3.Right()->Right()->Right() == NULL);
// Test the data of the tree copied using the copy constructor.
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree2.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree2.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree2.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree2.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree2.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree2.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree2.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree2.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree2.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree2.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree2.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree2.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree2.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree2.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree2.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree2.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree2.SplitDim() == 2);
REQUIRE(testDTree2.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree2.Right()->SplitDim() == 1);
REQUIRE(testDTree2.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
// Test the data of the tree copied using the copy operator.
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree3.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree3.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree3.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree3.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree3.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree3.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree3.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree3.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree3.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree3.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree3.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree3.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree3.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree3.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree3.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree3.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree3.SplitDim() == 2);
REQUIRE(testDTree3.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree3.Right()->SplitDim() == 1);
REQUIRE(testDTree3.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
}
// Test the move constructor.
BOOST_AUTO_TEST_CASE(MoveConstructorTest)
TEST_CASE("MoveConstructorTest", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -653,50 +658,50 @@ BOOST_AUTO_TEST_CASE(MoveConstructorTest)
DTree<arma::mat> testDTree2(std::move(*testDTree));
// Check default values of the original tree.
BOOST_REQUIRE_EQUAL(testDTree->LogNegError(), -DBL_MAX);
BOOST_REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
BOOST_REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->LogNegError() == -DBL_MAX);
REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
// Delete the original tree.
delete testDTree;
// Test the data of the moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[2], minVals2);
REQUIRE(testDTree2.MaxVals()[0] == maxVals0);
REQUIRE(testDTree2.MinVals()[0] == minVals0);
REQUIRE(testDTree2.MaxVals()[1] == maxVals1);
REQUIRE(testDTree2.MinVals()[1] == minVals1);
REQUIRE(testDTree2.MaxVals()[2] == maxVals2);
REQUIRE(testDTree2.MinVals()[2] == minVals2);
// Test the structure of the moved tree.
BOOST_REQUIRE(testDTree2.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
REQUIRE(testDTree2.Left()->Left() == NULL);
REQUIRE(testDTree2.Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
// Test the data of the moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree2.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree2.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree2.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree2.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree2.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree2.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree2.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree2.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree2.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree2.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree2.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree2.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree2.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree2.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree2.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree2.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree2.SplitDim() == 2);
REQUIRE(testDTree2.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree2.Right()->SplitDim() == 1);
REQUIRE(testDTree2.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
}
// Test the move operator.
BOOST_AUTO_TEST_CASE(MoveOperatorTest)
TEST_CASE("MoveOperatorTest", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -736,46 +741,44 @@ BOOST_AUTO_TEST_CASE(MoveOperatorTest)
DTree<arma::mat> testDTree2 = std::move(*testDTree);
// Check default values of the original tree.
BOOST_REQUIRE_EQUAL(testDTree->LogNegError(), -DBL_MAX);
BOOST_REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
BOOST_REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->LogNegError() == -DBL_MAX);
REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
// Delete the original tree.
delete testDTree;
// Test the data of the moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[2], minVals2);
REQUIRE(testDTree2.MaxVals()[0] == maxVals0);
REQUIRE(testDTree2.MinVals()[0] == minVals0);
REQUIRE(testDTree2.MaxVals()[1] == maxVals1);
REQUIRE(testDTree2.MinVals()[1] == minVals1);
REQUIRE(testDTree2.MaxVals()[2] == maxVals2);
REQUIRE(testDTree2.MinVals()[2] == minVals2);
// Test the structure of the moved tree.
BOOST_REQUIRE(testDTree2.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
REQUIRE(testDTree2.Left()->Left() == NULL);
REQUIRE(testDTree2.Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
// Test the data of moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree2.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree2.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree2.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree2.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree2.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree2.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree2.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree2.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree2.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree2.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree2.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree2.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree2.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree2.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree2.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree2.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree2.SplitDim() == 2);
REQUIRE(testDTree2.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree2.Right()->SplitDim() == 1);
REQUIRE(testDTree2.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
}
BOOST_AUTO_TEST_SUITE_END();
File diff suppressed because it is too large Load Diff
@@ -148,10 +148,10 @@ TEST_CASE("CheckCopyMovingVanillaNetworkTest", "[FeedForwardNetworkTest]")
model1->Add<Linear<> >(8, 3);
model1->Add<LogSoftMax<> >();
// Check whether copy cpnstructor is working or not.
// Check whether copy constructor is working or not.
CheckCopyFunction<>(model, trainData, trainLabels, 1);
// Check whether move cpnstructor is working or not.
// Check whether move constructor is working or not.
CheckMoveFunction<>(model1, trainData, trainLabels, 1);
}
@@ -489,7 +489,7 @@ TEST_CASE("FFNMiscTest", "[FeedForwardNetworkTest]")
auto copiedModel(model);
copiedModel = model;
auto movedModel(std::move(model));
movedModel = std::move(copiedModel);
auto moveOperator = std::move(copiedModel);
}
/**
@@ -764,7 +764,7 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]")
model.Add<Linear<> >(8, 3);
// RBFN neural net with MeanSquaredError.
TestNetwork<>(model, trainData, trainLabels1, testData, testLabels, 10, 0.1);
TestNetwork<>(model, trainData, trainLabels1, testData, testLabels, 10, 0.2);
arma::mat dataset;
dataset.load("mnist_first250_training_4s_and_9s.arm");
@@ -796,5 +796,5 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]")
model1.Add<Linear<> >(140, 2);
// RBFN neural net with MeanSquaredError.
TestNetwork<>(model1, dataset, labels1, dataset, labels, 10, 0.1);
TestNetwork<>(model1, dataset, labels1, dataset, labels, 10, 0.2);
}
+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();
+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();
+2 -1
View File
@@ -13,8 +13,9 @@
#include <mlpack/methods/random_forest/random_forest.hpp>
#include <mlpack/methods/decision_tree/random_dimension_select.hpp>
#include "serialization_catch.hpp"
#include "test_catch_tools.hpp"
#include "catch.hpp"
#include "serialization.hpp"
#include "mock_categorical_data.hpp"
using namespace mlpack;