From b92a3e5a2de20914fd379bd1f804e5da2f78ec80 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 18 Sep 2017 15:31:12 +0200 Subject: [PATCH] Add SPALERA optimizer test case. --- src/mlpack/tests/CMakeLists.txt | 1 + src/mlpack/tests/spalera_sgd_test.cpp | 89 +++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/mlpack/tests/spalera_sgd_test.cpp diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 24d3f33054..880b137fe5 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -106,6 +106,7 @@ add_executable(mlpack_test snapshot_ensembles.cpp softmax_regression_test.cpp sort_policy_test.cpp + spalera_sgd_test.cpp sparse_autoencoder_test.cpp sparse_coding_test.cpp spill_tree_test.cpp diff --git a/src/mlpack/tests/spalera_sgd_test.cpp b/src/mlpack/tests/spalera_sgd_test.cpp new file mode 100644 index 0000000000..c07e337054 --- /dev/null +++ b/src/mlpack/tests/spalera_sgd_test.cpp @@ -0,0 +1,89 @@ +/** + * @file spalera_sgd_test.cpp + * @author Marcus Edel + * + * Test file for SGD (stochastic gradient descent). + * + * 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. + */ +#include +#include +#include + +#include +#include "test_tools.hpp" + +using namespace mlpack; +using namespace mlpack::optimization; +using namespace mlpack::distribution; +using namespace mlpack::regression; + +BOOST_AUTO_TEST_SUITE(SPALeRASGDTest); + +/** + * Run SPALeRA SGD on logistic regression and make sure the results are + * acceptable. + */ +BOOST_AUTO_TEST_CASE(LogisticRegressionTest) +{ + // Generate a two-Gaussian dataset. + GaussianDistribution g1(arma::vec("1.0 1.0 1.0"), arma::eye(3, 3)); + GaussianDistribution g2(arma::vec("9.0 9.0 9.0"), arma::eye(3, 3)); + + arma::mat data(3, 500); + arma::Row responses(500); + for (size_t i = 0; i < 250; ++i) + { + data.col(i) = g1.Random(); + responses[i] = 0; + } + for (size_t i = 250; i < 500; ++i) + { + data.col(i) = g2.Random(); + responses[i] = 1; + } + + // Shuffle the dataset. + arma::uvec indices = arma::shuffle(arma::linspace(0, + data.n_cols - 1, data.n_cols)); + arma::mat shuffledData(3, 500); + arma::Row shuffledResponses(500); + for (size_t i = 0; i < data.n_cols; ++i) + { + shuffledData.col(i) = data.col(indices[i]); + shuffledResponses[i] = responses[indices[i]]; + } + + // Create a test set. + arma::mat testData(3, 500); + arma::Row testResponses(500); + for (size_t i = 0; i < 250; ++i) + { + testData.col(i) = g1.Random(); + testResponses[i] = 0; + } + for (size_t i = 250; i < 500; ++i) + { + testData.col(i) = g2.Random(); + testResponses[i] = 1; + } + + // Now run mini-batch SGD with a couple of batch sizes. + for (size_t batchSize = 5; batchSize < 50; batchSize += 5) + { + SPALeRASGD<> mbsgd(batchSize, 0.01, 10000, 1e-3); + LogisticRegression<> lr(shuffledData, shuffledResponses, mbsgd, 0.5); + + // Ensure that the error is close to zero. + const double acc = lr.ComputeAccuracy(data, responses); + BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance. + + const double testAcc = lr.ComputeAccuracy(testData, testResponses); + BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance. + } +} + +BOOST_AUTO_TEST_SUITE_END();