Merge branch 'master' of https://github.com/KARTHEEKCIC/mlpack into KARTHEEKCIC-master
This commit is contained in:
@@ -90,6 +90,7 @@ Copyright:
|
||||
Copyright 2018, Projyal Dev <projyal@gmail.com>
|
||||
Copyright 2018, Nikhil Goel <nikhilgoel199797@gmail.com>
|
||||
Copyright 2018, Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
|
||||
Copyright 2018, B Kartheek Reddy <bkartheekreddy@gmail.com>
|
||||
|
||||
License: BSD-3-clause
|
||||
All rights reserved.
|
||||
|
||||
@@ -233,6 +233,7 @@
|
||||
* - Projyal Dev <projyal@gmail.com>
|
||||
* - Nikhil Goel <nikhilgoel199797@gmail.com>
|
||||
* - Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
|
||||
* - B Kartheek Reddy <bkartheekreddy@gmail.com>
|
||||
*/
|
||||
|
||||
// First, include all of the prerequisites.
|
||||
|
||||
@@ -161,6 +161,14 @@ static void mlpackMain()
|
||||
ReportIgnoredParam({{ "test", false }}, "output");
|
||||
ReportIgnoredParam({{ "test", false }}, "output_probabilities");
|
||||
|
||||
// Max Iterations needs to be positive.
|
||||
RequireParamValue<int>("max_iterations", [](int x) { return x >= 0; },
|
||||
true, "max_iterations must be positive or zero");
|
||||
|
||||
// Batch Size needs to be greater than zero.
|
||||
RequireParamValue<int>("batch_size", [](int x) { return x > 0; },
|
||||
true, "batch_size must be greater than zero");
|
||||
|
||||
// Tolerance needs to be positive.
|
||||
RequireParamValue<double>("tolerance", [](double x) { return x >= 0.0; },
|
||||
true, "tolerance must be positive or zero");
|
||||
@@ -230,6 +238,13 @@ static void mlpackMain()
|
||||
}
|
||||
else if (CLI::HasParam("training"))
|
||||
{
|
||||
// Checking the size of training data if no labels are passed.
|
||||
if (regressors.n_rows < 2)
|
||||
{
|
||||
Log::Fatal << "Can't get responses from training data "
|
||||
"since it has less than 2 rows." << endl;
|
||||
}
|
||||
|
||||
// The initial predictors for y, Nx1.
|
||||
responses = arma::conv_to<arma::Row<size_t>>::from(
|
||||
regressors.row(regressors.n_rows - 1));
|
||||
@@ -274,6 +289,14 @@ static void mlpackMain()
|
||||
{
|
||||
testSet = std::move(CLI::GetParam<arma::mat>("test"));
|
||||
|
||||
// Checking the dimensionality of the test data.
|
||||
if (testSet.n_rows != model->Parameters().n_cols - 1)
|
||||
{
|
||||
Log::Fatal << "Test data dimensionality (" << testSet.n_rows << ") must "
|
||||
<< "be the same as the dimensionality of the Training Data ("
|
||||
<< model->Parameters().n_cols-1 << ")!" << endl;
|
||||
}
|
||||
|
||||
// We must perform predictions on the test set. Training (and the
|
||||
// optimizer) are irrelevant here; we'll pass in the model we have.
|
||||
if (CLI::HasParam("output"))
|
||||
|
||||
@@ -177,9 +177,23 @@ static void mlpackMain()
|
||||
if (CLI::HasParam("labels"))
|
||||
{
|
||||
labelsIn = std::move(CLI::GetParam<Row<size_t>>("labels"));
|
||||
|
||||
// Checking the size of the responses and training data.
|
||||
if (labelsIn.n_cols != trainingData.n_cols)
|
||||
{
|
||||
Log::Fatal << "The responses must have the same number of columns "
|
||||
"as the training set." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Checking the size of training data if no labels are passed.
|
||||
if (trainingData.n_rows < 2)
|
||||
{
|
||||
Log::Fatal << "Can't get responses from training data "
|
||||
"since it has less than 2 rows." << endl;
|
||||
}
|
||||
|
||||
// Use the last row of the training data as the labels.
|
||||
Log::Info << "Using the last dimension of training set as labels."
|
||||
<< endl;
|
||||
|
||||
@@ -133,6 +133,7 @@ add_executable(mlpack_test
|
||||
main_tests/decision_tree_test.cpp
|
||||
main_tests/decision_stump_test.cpp
|
||||
main_tests/linear_regression_test.cpp
|
||||
main_tests/logistic_regression_test.cpp
|
||||
main_tests/nbc_test.cpp
|
||||
main_tests/pca_test.cpp
|
||||
main_tests/perceptron_test.cpp
|
||||
|
||||
@@ -0,0 +1,650 @@
|
||||
/**
|
||||
* @file logistic_regression_test.cpp
|
||||
* @author B Kartheek Reddy
|
||||
*
|
||||
* Test mlpackMain() of logistic_regression_main.cpp
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#define BINDING_TYPE BINDING_TYPE_TEST
|
||||
|
||||
static const std::string testName = "LogisticRegression";
|
||||
|
||||
#include <mlpack/core.hpp>
|
||||
#include <mlpack/methods/logistic_regression/logistic_regression_main.cpp>
|
||||
#include <mlpack/core/util/mlpack_main.hpp>
|
||||
#include "test_helper.hpp"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace mlpack;
|
||||
|
||||
|
||||
struct LogisticRegressionTestFixture
|
||||
{
|
||||
public:
|
||||
LogisticRegressionTestFixture()
|
||||
{
|
||||
// Cache in the options for this program.
|
||||
CLI::RestoreSettings(testName);
|
||||
}
|
||||
|
||||
~LogisticRegressionTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(LogisticRegressionMainTest,
|
||||
LogisticRegressionTestFixture);
|
||||
|
||||
/**
|
||||
* Ensuring that absence of training data is checked.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRNoTrainingData)
|
||||
{
|
||||
arma::Row<size_t> trainY;
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << arma::endr;
|
||||
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// Training data is not provided. Should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that absence of responses is checked.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LRNoResponses)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 1;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
SetInputParam("training", std::move(trainX));
|
||||
|
||||
// Labels to the training data is not provided. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking that that size and dimensionality of prediction is correct.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LRPridictionSizeCheck)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
constexpr int M = 15;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << arma::endr;
|
||||
arma::mat testX = arma::randu<arma::mat>(D, M);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// Training the model.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output predictions of the test data.
|
||||
const arma::Row<size_t> &testY = CLI::GetParam<arma::Row<size_t>>("output");
|
||||
|
||||
// Output predictions size must match the test data set size.
|
||||
BOOST_REQUIRE_EQUAL(testY.n_rows, 1);
|
||||
BOOST_REQUIRE_EQUAL(testY.n_cols, M);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that the response size is checked.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRWrongResponseSizeTest)
|
||||
{
|
||||
constexpr int D = 3;
|
||||
constexpr int N = 10;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY; // Response vector with wrong size.
|
||||
|
||||
// 8 responses - incorrect size.
|
||||
trainY << 0 << 0 << 1 << 0 << 1 << 1 << 1 << 0 << arma::endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// Labels with incorrect size. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(LRResponsesRepresentationTest)
|
||||
{
|
||||
arma::mat trainX1({{1.0, 2.0, 3.0}, {1.0, 4.0, 9.0}, {0, 1, 1}});
|
||||
arma::mat testX({{4.0, 5.0}, {1.0, 6.0}});
|
||||
|
||||
SetInputParam("training", std::move(trainX1));
|
||||
SetInputParam("test", testX);
|
||||
|
||||
// The first solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output.
|
||||
const arma::Row<size_t> testY1 =
|
||||
std::move(CLI::GetParam<arma::Row<size_t>>("output"));
|
||||
|
||||
// Reset the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
CLI::RestoreSettings(testName);
|
||||
|
||||
// Now train by providing labels as extra parameter.
|
||||
arma::mat trainX2({{1.0, 2.0, 3.0}, {1.0, 4.0, 9.0}});
|
||||
arma::Row<size_t> trainY2({0, 1, 1});
|
||||
|
||||
SetInputParam("training", std::move(trainX2));
|
||||
SetInputParam("labels", std::move(trainY2));
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// The second solution.
|
||||
mlpackMain();
|
||||
|
||||
// get the output
|
||||
const arma::Row<size_t> &testY2 =
|
||||
CLI::GetParam<arma::Row<size_t>>("output");
|
||||
|
||||
// Both solutions should be equal.
|
||||
BOOST_REQUIRE_EQUAL_COLLECTIONS(testY1.begin(), testY1.end(),
|
||||
testY2.begin(), testY2.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that model can saved / loaded and used. Ensuring that results are the
|
||||
* same.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LRModelReload)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
constexpr int M = 15;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << arma::endr;
|
||||
|
||||
arma::mat testX = arma::randu<arma::mat>(D, M);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("test", testX);
|
||||
|
||||
// First solution
|
||||
mlpackMain();
|
||||
|
||||
// Get the output model obtained from training.
|
||||
LogisticRegression<>* model =
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model");
|
||||
// Get the output.
|
||||
const arma::Row<size_t> testY1 =
|
||||
std::move(CLI::GetParam<arma::Row<size_t>>("output"));
|
||||
|
||||
// Reset the data passed.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
CLI::GetSingleton().Parameters()["labels"].wasPassed = false;
|
||||
CLI::GetSingleton().Parameters()["test"].wasPassed = false;
|
||||
|
||||
SetInputParam("input_model", model);
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// Second solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output.
|
||||
const arma::Row<size_t> &testY2 =
|
||||
CLI::GetParam<arma::Row<size_t>>("output");
|
||||
|
||||
// Both solutions must be equal.
|
||||
BOOST_REQUIRE_EQUAL_COLLECTIONS(testY1.begin(), testY1.end(),
|
||||
testY2.begin(), testY2.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking for dimensionality of the test data set.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRWrongDimOfTestData)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 4;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << arma::endr;
|
||||
|
||||
// Test data with wrong dimensionality.
|
||||
arma::mat testX = arma::randu<arma::mat>(D-1, N);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// Dimensionality of test data is wrong. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that test data dimensionality is checked when model is loaded.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LRWrongDimOfTestData2)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
constexpr int M = 15;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
// 10 responses
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << arma::endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// Training the model.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output model obtained from training.
|
||||
LogisticRegression<>* model =
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model");
|
||||
|
||||
// Reset the data passed.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
CLI::GetSingleton().Parameters()["labels"].wasPassed = false;
|
||||
|
||||
// Test data with Wrong dimensionality.
|
||||
arma::mat testX = arma::randu<arma::mat>(D - 1, M);
|
||||
SetInputParam("input_model", model);
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// Test data dimensionality is wrong. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that training responses contain only two classes (0 or 1).
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRTrainWithMoreThanTwoClasses)
|
||||
{
|
||||
constexpr int N = 8;
|
||||
constexpr int D = 2;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 8 responses containing more than two classes.
|
||||
trainY << 0 << 1 << 0 << 1 << 2 << 1 << 3 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// Training data contains more than two classes. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that max iteration for optimizers is non negative.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRNonNegativeMaxIterationTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << arma::endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("max_iterations", int(-1));
|
||||
|
||||
// Maximum iterations is negative. It should a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that step size for optimizer is non negative.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRNonNegativeStepSizeTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 2;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("optimizer", std::string("sgd"));
|
||||
SetInputParam("step_size", double(-0.01));
|
||||
|
||||
// Step size for optimizer is negative. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that tolerance is non negative.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRNonNegativeToleranceTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 1 << 1 << 0 << 1 << 0 << 0 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("tolerance", double(-0.01));
|
||||
|
||||
// Tolerance is negative. It should throw a runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring changing Maximum number of iterations changes the output model.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRMaxIterationsChangeTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 1 << 0 << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", trainX);
|
||||
SetInputParam("labels", trainY);
|
||||
SetInputParam("max_iterations", int(1));
|
||||
|
||||
// First solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after first training.
|
||||
const arma::rowvec parameters1 =
|
||||
std::move(CLI::GetParam<LogisticRegression<>*>("output_model")
|
||||
->Parameters());
|
||||
|
||||
// Reset the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
CLI::RestoreSettings(testName);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("max_iterations", int(100));
|
||||
|
||||
// Second solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after second training.
|
||||
const arma::rowvec ¶meters2 =
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model")->Parameters();
|
||||
|
||||
// Check that the parameters (parameters1 and parameters2) are not equal
|
||||
// which ensures Max Iteration changes the output model.
|
||||
// arma::all function checks that each element of the vector is equal to zero.
|
||||
BOOST_REQUIRE_MESSAGE(!arma::all((parameters1-parameters2) == 0),
|
||||
"Parameter(Max Iteration) has no effect on the output");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that lambda has some effects on the output.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRLambdaChangeTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 4;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 1 << 0 << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", trainX);
|
||||
SetInputParam("labels", trainY);
|
||||
SetInputParam("lambda", double(0));
|
||||
|
||||
// First solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after first training.
|
||||
const arma::rowvec parameters1 =
|
||||
std::move(CLI::GetParam<LogisticRegression<>*>("output_model")
|
||||
->Parameters());
|
||||
|
||||
// Reset the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
CLI::RestoreSettings(testName);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("lambda", double(1000));
|
||||
|
||||
// Second solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after second training.
|
||||
const arma::rowvec ¶meters2 =
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model")->Parameters();
|
||||
|
||||
// Check that the parameters (parameters1 and parameters2) are not equal
|
||||
// which ensures lambda changes the output model.
|
||||
// arma::all function checks that each element of the vector is equal to zero.
|
||||
BOOST_REQUIRE_MESSAGE(!arma::all((parameters1-parameters2) == 0),
|
||||
"Parameter(lambda) has no effect on the output");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that Step size has some effects on the output.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRStepSizeChangeTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 1 << 0 << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", trainX);
|
||||
SetInputParam("labels", trainY);
|
||||
SetInputParam("optimizer", std::string("sgd"));
|
||||
SetInputParam("step_size", double(0.02));
|
||||
|
||||
// First solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after first training.
|
||||
const arma::rowvec parameters1 =
|
||||
std::move(CLI::GetParam<LogisticRegression<>*>("output_model")
|
||||
->Parameters());
|
||||
|
||||
// Reset the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
CLI::RestoreSettings(testName);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("optimizer", std::string("sgd"));
|
||||
SetInputParam("step_size", double(1.02));
|
||||
|
||||
// Second solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after second training.
|
||||
const arma::rowvec ¶meters2 =
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model")->Parameters();
|
||||
|
||||
// Check that the parameters (parameters1 and parameters2) are not equal
|
||||
// which ensures Step Size changes the output model.
|
||||
// arma::all function checks that each element of the vector is equal to zero.
|
||||
BOOST_REQUIRE_MESSAGE(!arma::all((parameters1-parameters2) == 0),
|
||||
"Parameter(Step Size) has no effect on the output");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that lbfgs optimizer converges to a different result than sgd.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LROptimizerChangeTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 1 << 0 << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
SetInputParam("training", trainX);
|
||||
SetInputParam("labels", trainY);
|
||||
SetInputParam("optimizer", std::string("lbfgs"));
|
||||
SetInputParam("max_iterations", int(1000));
|
||||
|
||||
// First solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after first training.
|
||||
const arma::rowvec parameters1 =
|
||||
std::move(CLI::GetParam<LogisticRegression<>*>("output_model")
|
||||
->Parameters());
|
||||
|
||||
// Reset the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
CLI::RestoreSettings(testName);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("optimizer", std::string("sgd"));
|
||||
SetInputParam("max_iterations", int(1000));
|
||||
|
||||
// Second solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the parameters of the output model obtained after second training.
|
||||
const arma::rowvec ¶meters2 =
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model")->Parameters();
|
||||
|
||||
// Check that the parameters (parameters1 and parameters2) are not equal which
|
||||
// ensures that different optimizer converge to different results.
|
||||
// arma::all function checks that each element of the vector is equal to zero.
|
||||
BOOST_REQUIRE_MESSAGE(!arma::all((parameters1-parameters2) == 0),
|
||||
"Parameter(Step Size) has no effect on the output");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring decision_boundary parameter does something.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(LRDecisionBoundaryTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
constexpr int M = 15;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 1 << 0 << 0 << 1 << 0 << 1 << 0 << 1 << 0 << 1 << arma::endr;
|
||||
|
||||
arma::mat testX = arma::randu<arma::mat>(D, M);
|
||||
|
||||
SetInputParam("training", trainX);
|
||||
SetInputParam("labels", trainY);
|
||||
SetInputParam("decision_boundary", double(1));
|
||||
SetInputParam("test", testX);
|
||||
|
||||
// First solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output after first training.
|
||||
const arma::Row<size_t> &output1 = CLI::GetParam<arma::Row<size_t>>("output");
|
||||
|
||||
// Check that the parameters (parameters1 and parameters2) are not equal which
|
||||
// ensures that decision boundary has some effect on the output.
|
||||
// arma::all function checks that each element of the vector is equal to zero.
|
||||
BOOST_REQUIRE_MESSAGE(arma::all(output1 == 0),
|
||||
"Parameter(Decision Boudary) has"
|
||||
"no effect on the output");
|
||||
|
||||
// Reset the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
CLI::RestoreSettings(testName);
|
||||
|
||||
SetInputParam("training", trainX);
|
||||
SetInputParam("labels", trainY);
|
||||
SetInputParam("decision_boundary", double(0));
|
||||
SetInputParam("test", testX);
|
||||
|
||||
// Second solution.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output after second training.
|
||||
const arma::Row<size_t> &output2 = CLI::GetParam<arma::Row<size_t>>("output");
|
||||
|
||||
// Check that the parameters (parameters1 and parameters2) are not equal which
|
||||
// ensures that decision boundary has som effect on the output.
|
||||
// arma::all function checks that each element of the vector is equal to one.
|
||||
BOOST_REQUIRE_MESSAGE(arma::all(output2 == 1),
|
||||
"Parameter(Decision Boudary) has"
|
||||
"no effect on the output");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -232,4 +232,184 @@ BOOST_AUTO_TEST_CASE(PerceptronMaxItrTest)
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that re-training of an existing model
|
||||
* with different of classes is checked.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(PerceptronReTrainWithWrongClasses)
|
||||
{
|
||||
arma::mat trainX1;
|
||||
arma::Row<size_t> labelsX1;
|
||||
|
||||
// Loading a train data set with 3 classes.
|
||||
if (!data::Load("vc2.csv", trainX1))
|
||||
{
|
||||
BOOST_FAIL("Could not load the train data (vc2.csv)");
|
||||
}
|
||||
|
||||
// Loading the corresponding labels to the dataset.
|
||||
if (!data::Load("vc2_labels.txt", labelsX1))
|
||||
{
|
||||
BOOST_FAIL("Could not load the train data (vc2_labels.csv)");
|
||||
}
|
||||
|
||||
SetInputParam("training", std::move(trainX1)); // Training data.
|
||||
// Labels for the training data.
|
||||
SetInputParam("labels", std::move(labelsX1));
|
||||
|
||||
// Training model using first training dataset.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output model obtained after training.
|
||||
PerceptronModel* model =
|
||||
CLI::GetParam<PerceptronModel*>("output_model");
|
||||
|
||||
// Reset the data passed.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
CLI::GetSingleton().Parameters()["labels"].wasPassed = false;
|
||||
|
||||
// Creating training data with five classes.
|
||||
constexpr int D = 3;
|
||||
constexpr int N = 10;
|
||||
arma::mat trainX2 = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> labelsX2;
|
||||
|
||||
// 10 responses.
|
||||
labelsX2 << 0 << 1 << 4 << 1 << 2 << 1 << 0 << 3 << 3 << 0 << endr;
|
||||
|
||||
// Last column of trainX2 contains the class labels.
|
||||
SetInputParam("training", std::move(trainX2));
|
||||
SetInputParam("input_model", model);
|
||||
|
||||
// Re-training an existing model of 3 classes
|
||||
// with training data of 5 classes. It should give runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking for dimensionality of the test data set.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(PerceptronWrongDimOfTestData)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 4;
|
||||
constexpr int M = 20;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << endr;
|
||||
|
||||
// Test data with wrong dimensionality.
|
||||
arma::mat testX = arma::randu<arma::mat>(D-3, M);
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// Test data set with wrong dimensionality. It should give runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that the response size is checked.
|
||||
**/
|
||||
BOOST_AUTO_TEST_CASE(PerceptronWrongResponseSizeTest)
|
||||
{
|
||||
constexpr int D = 2;
|
||||
constexpr int N = 10;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY; // Response vector with wrong size.
|
||||
|
||||
// 8 responses.
|
||||
trainY << 0 << 0 << 1 << 0 << 1 << 1 << 1 << 0 << endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// Labels for training data have wrong size. It should give runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that absence of responses is checked.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(PerceptronNoResponsesTest)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 1;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
SetInputParam("training", std::move(trainX));
|
||||
|
||||
// No labels for training data. It should give runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that absence of training data is checked.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(PerceptronNoTrainingDataTest)
|
||||
{
|
||||
arma::Row<size_t> trainY;
|
||||
trainY << 1 << 1 << 0 << 1 << 0 << 0 <<endr;
|
||||
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// No training data. It should give runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that test data dimensionality is checked when model is loaded.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(PerceptronWrongDimOfTestData2)
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 3;
|
||||
constexpr int M = 15;
|
||||
|
||||
arma::mat trainX = arma::randu<arma::mat>(D, N);
|
||||
arma::Row<size_t> trainY;
|
||||
|
||||
// 10 responses.
|
||||
trainY << 0 << 1 << 0 << 1 << 1 << 1 << 0 << 1 << 0 << 0 << endr;
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
SetInputParam("labels", std::move(trainY));
|
||||
|
||||
// Training the model.
|
||||
mlpackMain();
|
||||
|
||||
// Get the output model obtained after the training.
|
||||
PerceptronModel* model =
|
||||
CLI::GetParam<PerceptronModel*>("output_model");
|
||||
|
||||
// Reset the data passed.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
CLI::GetSingleton().Parameters()["labels"].wasPassed = false;
|
||||
|
||||
// Test data with Wrong dimensionality.
|
||||
arma::mat testX = arma::randu<arma::mat>(D - 1, M);
|
||||
SetInputParam("input_model", model);
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
// Wrong dimensionality of test data. It should give runtime error.
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
Reference in New Issue
Block a user