Merge branch 'master' into master

This commit is contained in:
Ryan Birmingham
2020-07-24 00:28:15 -04:00
committed by GitHub
5 changed files with 68 additions and 64 deletions
+3 -3
View File
@@ -52,7 +52,6 @@ add_executable(mlpack_test
lars_test.cpp
layer_names_test.cpp
lin_alg_test.cpp
linear_regression_test.cpp
linear_svm_test.cpp
lmnn_test.cpp
load_save_test.cpp
@@ -141,7 +140,6 @@ add_executable(mlpack_test
main_tests/kmeans_test.cpp
main_tests/knn_test.cpp
main_tests/krann_test.cpp
main_tests/linear_regression_test.cpp
main_tests/linear_svm_test.cpp
main_tests/lmnn_test.cpp
main_tests/local_coordinate_coding_test.cpp
@@ -169,12 +167,14 @@ add_executable(mlpack_catch_test
activation_functions_test.cpp
convolutional_network_test.cpp
convolution_test.cpp
image_load_test.cpp
linear_regression_test.cpp
main.cpp
serialization_catch.cpp
serialization_catch.hpp
test_catch_tools.hpp
image_load_test.cpp
main_tests/image_converter_test.cpp
main_tests/linear_regression_test.cpp
main_tests/test_helper.hpp
)
+2 -1
View File
@@ -12,6 +12,7 @@
#include <mlpack/core.hpp>
#include "serialization_catch.hpp"
#include "test_catch_tools.hpp"
#include "catch.hpp"
using namespace mlpack;
@@ -128,7 +129,7 @@ TEST_CASE("SaveImageMatAPITest", "[ImageLoadTest]")
REQUIRE(input.n_cols == output.n_cols);
REQUIRE(input.n_rows == output.n_rows);
for (size_t i = 0; i < input.n_elem; ++i)
REQUIRE(input[i] == Approx(output[i]).epsilon(1e-5 / 100));
REQUIRE(input[i] == Approx(output[i]).epsilon(1e-7));
remove("APITest.bmp");
}
+24 -27
View File
@@ -11,20 +11,18 @@
#include <mlpack/core.hpp>
#include <mlpack/methods/linear_regression/linear_regression.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"
using namespace mlpack;
using namespace mlpack::regression;
BOOST_AUTO_TEST_SUITE(LinearRegressionTest);
/**
* Creates two 10x3 random matrices and one 10x1 "results" matrix.
* Finds B in y=BX with one matrix, then predicts against the other.
*/
BOOST_AUTO_TEST_CASE(LinearRegressionTestCase)
TEST_CASE("LinearRegressionTestCase", "[LinearRegressionTest]")
{
// Predictors and points are 10x3 matrices.
arma::mat predictors(3, 10);
@@ -66,13 +64,13 @@ BOOST_AUTO_TEST_CASE(LinearRegressionTestCase)
// Output result and verify we have less than 5% error from "correct" value
// for each point.
for (size_t i = 0; i < predictions.n_cols; ++i)
BOOST_REQUIRE_SMALL(predictions(i) - responses(i), .05);
REQUIRE(predictions(i) - responses(i) == Approx(0.0).margin(0.05));
}
/**
* Check the functionality of ComputeError().
*/
BOOST_AUTO_TEST_CASE(ComputeErrorTest)
TEST_CASE("ComputeErrorTest", "[LinearRegressionTest]")
{
arma::mat predictors;
predictors << 0 << 1 << 2 << 4 << 8 << 16 << arma::endr
@@ -83,14 +81,14 @@ BOOST_AUTO_TEST_CASE(ComputeErrorTest)
// This dataset gives a cost of 1.189500337 (as calculated in Octave).
LinearRegression lr(predictors, responses);
BOOST_REQUIRE_CLOSE(lr.ComputeError(predictors, responses), 1.189500337,
1e-3);
REQUIRE(lr.ComputeError(predictors, responses) ==
Approx(1.189500337).epsilon(1e-5));
}
/**
* Ensure that the cost is 0 when a perfectly-fitting dataset is given.
*/
BOOST_AUTO_TEST_CASE(ComputeErrorPerfectFitTest)
TEST_CASE("ComputeErrorPerfectFitTest", "[LinearRegressionTest]")
{
// Linear regression should perfectly model this dataset.
arma::mat predictors;
@@ -100,14 +98,14 @@ BOOST_AUTO_TEST_CASE(ComputeErrorPerfectFitTest)
LinearRegression lr(predictors, responses);
BOOST_REQUIRE_SMALL(lr.ComputeError(predictors, responses), 1e-25);
REQUIRE(lr.ComputeError(predictors, responses) == Approx(0.0).margin(1e-25));
}
/**
* Test ridge regression using an empty dataset, which is not invertible. But
* the ridge regression part should make it invertible.
*/
BOOST_AUTO_TEST_CASE(RidgeRegressionTest)
TEST_CASE("RidgeRegressionTest", "[LinearRegressionTest]")
{
// Create empty dataset.
arma::mat data;
@@ -126,7 +124,7 @@ BOOST_AUTO_TEST_CASE(RidgeRegressionTest)
lr.Predict(data, predictedResponses);
for (size_t i = 0; i < 5000; ++i)
BOOST_REQUIRE_SMALL((double) predictedResponses[i], 1e-20);
REQUIRE((double) predictedResponses[i] == Approx(0.0).margin(1e-20));
}
/**
@@ -134,7 +132,7 @@ BOOST_AUTO_TEST_CASE(RidgeRegressionTest)
* Finds B in y=BX with one matrix, then predicts against the other, but uses
* ridge regression with an extremely small lambda value.
*/
BOOST_AUTO_TEST_CASE(RidgeRegressionTestCase)
TEST_CASE("RidgeRegressionTestCase", "[LinearRegressionTest]")
{
// Predictors and points are 10x3 matrices.
arma::mat predictors(3, 10);
@@ -176,14 +174,14 @@ BOOST_AUTO_TEST_CASE(RidgeRegressionTestCase)
// Output result and verify we have less than 5% error from "correct" value
// for each point.
for (size_t i = 0; i < predictions.n_cols; ++i)
BOOST_REQUIRE_SMALL(predictions(i) - responses(i), .05);
REQUIRE(predictions(i) - responses(i) == Approx(0.0).margin(0.05));
}
/**
* Test that a LinearRegression model trained in the constructor and trained in
* the Train() method give the same model.
*/
BOOST_AUTO_TEST_CASE(LinearRegressionTrainTest)
TEST_CASE("LinearRegressionTrainTest", "[LinearRegressionTest]")
{
// Random dataset.
arma::mat dataset = arma::randu<arma::mat>(5, 1000);
@@ -195,15 +193,16 @@ BOOST_AUTO_TEST_CASE(LinearRegressionTrainTest)
lrTrain.Train(dataset, responses);
BOOST_REQUIRE_EQUAL(lr.Parameters().n_elem, lrTrain.Parameters().n_elem);
REQUIRE(lr.Parameters().n_elem == lrTrain.Parameters().n_elem);
for (size_t i = 0; i < lr.Parameters().n_elem; ++i)
BOOST_REQUIRE_CLOSE(lr.Parameters()[i], lrTrain.Parameters()[i], 1e-5);
REQUIRE(lr.Parameters()[i] ==
Approx(lrTrain.Parameters()[i]).epsilon(1e-7));
}
/*
* Linear regression serialization test.
*/
BOOST_AUTO_TEST_CASE(LinearRegressionTest)
TEST_CASE("LinearRegressionTest", "[LinearRegressionTest]")
{
// Generate some random data.
arma::mat data;
@@ -216,9 +215,9 @@ BOOST_AUTO_TEST_CASE(LinearRegressionTest)
SerializeObjectAll(lr, xmlLr, textLr, binaryLr);
BOOST_REQUIRE_CLOSE(lr.Lambda(), xmlLr.Lambda(), 1e-8);
BOOST_REQUIRE_CLOSE(lr.Lambda(), textLr.Lambda(), 1e-8);
BOOST_REQUIRE_CLOSE(lr.Lambda(), binaryLr.Lambda(), 1e-8);
REQUIRE(lr.Lambda() == Approx(xmlLr.Lambda()).epsilon(1e-10));
REQUIRE(lr.Lambda() == Approx(textLr.Lambda()).epsilon(1e-10));
REQUIRE(lr.Lambda() == Approx(binaryLr.Lambda()).epsilon(1e-10));
CheckMatrices(lr.Parameters(), xmlLr.Parameters(), textLr.Parameters(),
binaryLr.Parameters());
@@ -227,7 +226,7 @@ BOOST_AUTO_TEST_CASE(LinearRegressionTest)
/**
* Test that LinearRegression::Train() returns finite OLS error.
*/
BOOST_AUTO_TEST_CASE(LinearRegressionTrainReturnObjective)
TEST_CASE("LinearRegressionTrainReturnObjective", "[LinearRegressionTest]")
{
arma::mat predictors(3, 10);
arma::mat points(3, 10);
@@ -265,7 +264,5 @@ BOOST_AUTO_TEST_CASE(LinearRegressionTrainReturnObjective)
LinearRegression lr;
double error = lr.Train(predictors, responses);
BOOST_REQUIRE_EQUAL(std::isfinite(error), true);
REQUIRE(std::isfinite(error) == true);
}
BOOST_AUTO_TEST_SUITE_END();
@@ -18,6 +18,7 @@ static const std::string testName = "ImageConverter";
#include <mlpack/methods/preprocess/image_converter_main.cpp>
#include "test_helper.hpp"
#include "../test_catch_tools.hpp"
#include "../catch.hpp"
@@ -43,7 +44,7 @@ struct ImageConverterTestFixture
};
TEST_CASE_METHOD(ImageConverterTestFixture, "LoadImageTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
SetInputParam<vector<string>>("input", {"test_image.png", "test_image.png"});
@@ -55,7 +56,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "LoadImageTest",
}
TEST_CASE_METHOD(ImageConverterTestFixture, "SaveImageTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
arma::mat testimage = arma::conv_to<arma::mat>::from(
arma::randi<arma::Mat<unsigned char>>((5 * 5 * 3), 2));
@@ -82,7 +83,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "SaveImageTest",
REQUIRE(output.n_rows == 5 * 5 * 3);
REQUIRE(output.n_cols == 2);
for (size_t i = 0; i < output.n_elem; ++i)
REQUIRE(testimage[i] == Approx(output[i]).epsilon(1e-5 / 100));
REQUIRE(testimage[i] == Approx(output[i]).epsilon(1e-7));
}
/**
@@ -90,7 +91,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "SaveImageTest",
* specified.
*/
TEST_CASE_METHOD(ImageConverterTestFixture, "IncompleteTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
arma::mat testimage = arma::conv_to<arma::mat>::from(
arma::randi<arma::Mat<unsigned char>>((5 * 5 * 3), 2));
@@ -110,7 +111,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "IncompleteTest",
* Check for invalid height values.
*/
TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidInputTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
arma::mat testimage = arma::conv_to<arma::mat>::from(
arma::randi<arma::Mat<unsigned char>>((5 * 5 * 3), 2));
@@ -132,7 +133,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidInputTest",
* Check for invalid width values.
*/
TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidWidthTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
arma::mat testimage = arma::conv_to<arma::mat>::from(
arma::randi<arma::Mat<unsigned char>>((5 * 5 * 3), 2));
@@ -153,7 +154,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidWidthTest",
* Check for invalid channel values.
*/
TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidChannelTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
arma::mat testimage = arma::conv_to<arma::mat>::from(
arma::randi<arma::Mat<unsigned char>>((5 * 5 * 3), 2));
@@ -174,7 +175,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidChannelTest",
* Check for invalid input values.
*/
TEST_CASE_METHOD(ImageConverterTestFixture, "EmptyInputTest",
"ImageConverterMainTest")
"[ImageConverterMainTest][BindingTests]")
{
SetInputParam<vector<string>>("input", {});
SetInputParam("height", 50);
@@ -19,8 +19,8 @@ static const std::string testName = "LinearRegression";
#include "test_helper.hpp"
#include <mlpack/methods/linear_regression/linear_regression_main.cpp>
#include <boost/test/unit_test.hpp>
#include "../test_tools.hpp"
#include "../test_catch_tools.hpp"
#include "../catch.hpp"
using namespace mlpack;
@@ -47,13 +47,12 @@ void ResetSettings()
IO::RestoreSettings(testName);
}
BOOST_FIXTURE_TEST_SUITE(LinearRegressionMainTest, LRTestFixture);
/**
* Training a model with different regularization parameter and ensuring that
* predictions are different.
*/
BOOST_AUTO_TEST_CASE(LRDifferentLambdas)
TEST_CASE_METHOD(LRTestFixture, "LRDifferentLambdas",
"[LinearRegressionMainTest][BindingTests]")
{
// A required minimal difference between solutions.
const double delta = 0.1;
@@ -85,7 +84,7 @@ BOOST_AUTO_TEST_CASE(LRDifferentLambdas)
// Second solution has stronger regularization,
// so the predicted value should be smaller.
BOOST_REQUIRE_GT(testY1 - delta, testY2);
REQUIRE(testY1 - delta > testY2);
}
@@ -93,7 +92,8 @@ BOOST_AUTO_TEST_CASE(LRDifferentLambdas)
* Checking two options of specifying responses (extra row in train matrix and
* extra parameter) and ensuring that predictions are the same.
*/
BOOST_AUTO_TEST_CASE(LRResponsesRepresentation)
TEST_CASE_METHOD(LRTestFixture, "LRResponsesRepresentation",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr double delta = 1e-5;
@@ -119,14 +119,15 @@ BOOST_AUTO_TEST_CASE(LRResponsesRepresentation)
mlpackMain();
const double testY2 = IO::GetParam<arma::rowvec>("output_predictions")(0);
BOOST_REQUIRE(fabs(testY1 - testY2) < delta);
REQUIRE(fabs(testY1 - testY2) < delta);
}
/**
* Check that model can saved / loaded and used. Ensuring that results are the
* same.
*/
BOOST_AUTO_TEST_CASE(LRModelReload)
TEST_CASE_METHOD(LRTestFixture, "LRModelReload",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr double delta = 1e-5;
constexpr int N = 10;
@@ -155,13 +156,14 @@ BOOST_AUTO_TEST_CASE(LRModelReload)
const arma::rowvec testY2 = IO::GetParam<arma::rowvec>("output_predictions");
double norm = arma::norm(testY1 - testY2, 2);
BOOST_REQUIRE(norm < delta);
REQUIRE(norm < delta);
}
/**
* Ensuring that response size is checked.
*/
BOOST_AUTO_TEST_CASE(LRWrongResponseSizeTest)
TEST_CASE_METHOD(LRTestFixture, "LRWrongResponseSizeTest",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr int N = 10;
constexpr int D = 2;
@@ -173,14 +175,15 @@ BOOST_AUTO_TEST_CASE(LRWrongResponseSizeTest)
SetInputParam("training_responses", std::move(trainY));
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
}
/**
* Ensuring that test data dimensionality is checked.
*/
BOOST_AUTO_TEST_CASE(LRWrongDimOfDataTest1)
TEST_CASE_METHOD(LRTestFixture, "LRWrongDimOfDataTest1t",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr int N = 10;
constexpr int D = 3;
@@ -195,14 +198,15 @@ BOOST_AUTO_TEST_CASE(LRWrongDimOfDataTest1)
SetInputParam("test", std::move(testX));
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
}
/**
* Ensuring that test data dimensionality is checked when model is loaded.
*/
BOOST_AUTO_TEST_CASE(LRWrongDimOfDataTest2)
TEST_CASE_METHOD(LRTestFixture, "LRWrongDimOfDataTest2",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr int N = 10;
constexpr int D = 3;
@@ -225,14 +229,15 @@ BOOST_AUTO_TEST_CASE(LRWrongDimOfDataTest2)
SetInputParam("test", std::move(testX));
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
}
/**
* Checking that that size and dimensionality of prediction is correct.
*/
BOOST_AUTO_TEST_CASE(LRPredictionSizeCheck)
TEST_CASE_METHOD(LRTestFixture, "LRPredictionSizeCheck",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr int N = 10;
constexpr int D = 3;
@@ -250,14 +255,15 @@ BOOST_AUTO_TEST_CASE(LRPredictionSizeCheck)
const arma::rowvec testY = IO::GetParam<arma::rowvec>("output_predictions");
BOOST_REQUIRE_EQUAL(testY.n_rows, 1);
BOOST_REQUIRE_EQUAL(testY.n_cols, M);
REQUIRE(testY.n_rows == 1);
REQUIRE(testY.n_cols == M);
}
/**
* Ensuring that absence of responses is checked.
*/
BOOST_AUTO_TEST_CASE(LRNoResponses)
TEST_CASE_METHOD(LRTestFixture, "LRNoResponses",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr int N = 10;
constexpr int D = 1;
@@ -266,14 +272,15 @@ BOOST_AUTO_TEST_CASE(LRNoResponses)
SetInputParam("training", std::move(trainX));
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
}
/**
* Ensuring that absence of training data is checked.
*/
BOOST_AUTO_TEST_CASE(LRNoTrainingData)
TEST_CASE_METHOD(LRTestFixture, "LRNoTrainingData",
"[LinearRegressionMainTest][BindingTests]")
{
constexpr int N = 10;
@@ -281,8 +288,6 @@ BOOST_AUTO_TEST_CASE(LRNoTrainingData)
SetInputParam("training_responses", std::move(trainY));
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();