From 24a19963370ef9b5188bf91dc90045e01846eb5a Mon Sep 17 00:00:00 2001 From: jeffinsam Date: Wed, 25 Sep 2019 00:19:55 +0530 Subject: [PATCH 001/729] Accelerate hmm and gmm --- src/mlpack/methods/gmm/diagonal_gmm.cpp | 50 ++++++++++++++++++ src/mlpack/methods/gmm/diagonal_gmm.hpp | 18 ++++++- src/mlpack/methods/gmm/gmm.cpp | 67 +++++++++++++++++++++++++ src/mlpack/methods/gmm/gmm.hpp | 21 +++++++- src/mlpack/methods/hmm/hmm_impl.hpp | 65 ++++++++++++++++++++---- src/mlpack/tests/gmm_test.cpp | 42 +++++++++++++++- 6 files changed, 249 insertions(+), 14 deletions(-) diff --git a/src/mlpack/methods/gmm/diagonal_gmm.cpp b/src/mlpack/methods/gmm/diagonal_gmm.cpp index e5ed0e6001..cc7385040f 100644 --- a/src/mlpack/methods/gmm/diagonal_gmm.cpp +++ b/src/mlpack/methods/gmm/diagonal_gmm.cpp @@ -67,6 +67,42 @@ double DiagonalGMM::LogProbability(const arma::vec& observation) const return sum; } +/** + * Return the log probability of the given observation GMM matrix. + * + * @param observation Observation matrix to compute log-probabilty. + * @param logProbs Stores the value of log-probability for input. + */ +void DiagonalGMM::LogProbability(const arma::mat& observation, + arma::vec& logProbs) const +{ + // Sum the probability for each Gaussian in our mixture (and we have to + // multiply by the prior for each Gaussian too). + logProbs.set_size(observation.n_cols); + + // Store log-probability value in a matrix. + arma::mat logProb(observation.n_cols, gaussians); + + // Assign value to the matrix. + for (size_t i = 0; i < gaussians; i++) + { + arma::vec temp(logProb.colptr(i), observation.n_cols, false, true); + dists[i].LogProbability(observation, temp); + } + + // Save log(weights) as a vector. + arma::vec logWeights = arma::log(weights); + // Compute Log Probability. + + logProb = logProb.t(); + + for (size_t j = 0; j < observation.n_cols; j++) + { + const arma::vec sumVec = logWeights + logProb.unsafe_col(j); + logProbs(j) = math::AccuLog(sumVec); + } +} + /** * Return the probability of the given observation being from this GMM. */ @@ -75,6 +111,20 @@ double DiagonalGMM::Probability(const arma::vec& observation) const return exp(LogProbability(observation)); } +/** + * Return the probability of the given observation GMM matrix. + * + * @param observation Observation matrix to compute probabilty. + * @param probs Stores the value of probability for observation. + */ +void DiagonalGMM::Probability(const arma::mat& observation, + arma::vec& probs) const +{ + LogProbability(observation, probs); + probs = exp(probs); +} + + /** * Return the log probability of the given observation being from the given * component in the mixture. diff --git a/src/mlpack/methods/gmm/diagonal_gmm.hpp b/src/mlpack/methods/gmm/diagonal_gmm.hpp index e5d9c17154..a0d8e65f26 100644 --- a/src/mlpack/methods/gmm/diagonal_gmm.hpp +++ b/src/mlpack/methods/gmm/diagonal_gmm.hpp @@ -166,14 +166,30 @@ class DiagonalGMM */ double Probability(const arma::vec& observation) const; + /** + * Return the probability that the given observation matrix. + * + * @param observation Observation to evaluate the probability of. + * @param probs Stores the value of probability for observation. + */ + void Probability(const arma::mat& observation, arma::vec& probs) const; + /** * Return the log probability that the given observation came from this * distribution. * - * @param observation Observation to evaluate the probability of. + * @param observation Observation to evaluate the log-probability of. */ double LogProbability(const arma::vec& observation) const; + /** + * Return the log probability that the given observation matrix. + * + * @param observation Observation to evaluate the log-probability of. + * @param logProbs Stores the value of log-probability for observation. + */ + void LogProbability(const arma::mat& observation, arma::vec& logProbs) const; + /** * Return the probability that the given observation came from the given * Gaussian component in this distribution. diff --git a/src/mlpack/methods/gmm/gmm.cpp b/src/mlpack/methods/gmm/gmm.cpp index 7eb7672fbc..45ec7c2afa 100644 --- a/src/mlpack/methods/gmm/gmm.cpp +++ b/src/mlpack/methods/gmm/gmm.cpp @@ -53,6 +53,8 @@ GMM& GMM::operator=(const GMM& other) /** * Return the log probability of the given observation being from this GMM. + * + * @param observation Observation vector to compute log-probabilty. */ double GMM::LogProbability(const arma::vec& observation) const { @@ -66,17 +68,72 @@ double GMM::LogProbability(const arma::vec& observation) const return sum; } +/** + * Return the log probability of the given observation GMM matrix. + * + * @param observation Observation matrix to compute log-probabilty. + * @param logProbs Stores the value of log-probability for Observation. + */ +void GMM::LogProbability(const arma::mat& observation, + arma::vec& logProbs) const +{ + // Sum the probability for each Gaussian in our mixture (and we have to + // multiply by the prior for each Gaussian too). + logProbs.set_size(observation.n_cols); + + // Store log-probability value in a matrix. + arma::mat logProb(observation.n_cols, gaussians); + + // Assign value to the matrix. + for (size_t i = 0; i < gaussians; i++) + { + arma::vec temp(logProb.colptr(i), observation.n_cols, false, true); + dists[i].LogProbability(observation, temp); + } + + // Save log(weights) as a vector. + arma::vec logWeights = arma::log(weights); + // Compute Log Probability. + + logProb = logProb.t(); + + for (size_t j = 0; j < observation.n_cols; j++) + { + const arma::vec sumVec = logWeights + logProb.unsafe_col(j); + logProbs(j) = math::AccuLog(sumVec); + } +} + /** * Return the probability of the given observation being from this GMM. + * + * @param observation Observation vector to compute probabilty. */ double GMM::Probability(const arma::vec& observation) const { return exp(LogProbability(observation)); } +/** + * Return the probability of the given observation GMM matrix. + * + * @param observation Observation matrix to compute probabilty. + * @param probs Stores the value of probability for x. + */ +void GMM::Probability(const arma::mat& observation, + arma::vec& probs) const +{ + LogProbability(observation, probs); + probs = exp(probs); +} + + /** * Return the log probability of the given observation being from the given * component in the mixture. + * + * @param observation Observation vector to compute log-probabilty. + * @param component Calculate the log-probability for given observation vector. */ double GMM::LogProbability(const arma::vec& observation, const size_t component) const @@ -89,6 +146,9 @@ double GMM::LogProbability(const arma::vec& observation, /** * Return the probability of the given observation being from the given * component in the mixture. + * + * @param observation Observation matrix to compute probabilty. + * @param component Calculate the probability for given component. */ double GMM::Probability(const arma::vec& observation, const size_t component) const @@ -124,6 +184,9 @@ arma::vec GMM::Random() const /** * Classify the given observations as being from an individual component in this * GMM. + * + * @param observation Observation matrix for classification. + * @param labels Save the labels for the given observation matrix. */ void GMM::Classify(const arma::mat& observations, arma::Row& labels) const @@ -151,6 +214,10 @@ void GMM::Classify(const arma::mat& observations, /** * Get the log-likelihood of this data's fit to the model. + * + * @param data Data matrix to compute log-likelihood. + * @parma distsL Vector of Gaussian distribution. + * @param weightsL Vector of weights for computing likelihoods. */ double GMM::LogLikelihood( const arma::mat& data, diff --git a/src/mlpack/methods/gmm/gmm.hpp b/src/mlpack/methods/gmm/gmm.hpp index a36a27a4b6..f2fb4a7c8d 100644 --- a/src/mlpack/methods/gmm/gmm.hpp +++ b/src/mlpack/methods/gmm/gmm.hpp @@ -160,18 +160,35 @@ class GMM * Return the probability that the given observation came from this * distribution. * - * @param observation Observation to evaluate the probability of. + * @param observation Observation vector to evaluate the probability of. */ double Probability(const arma::vec& observation) const; + /** + * Return the probability of the given observation matrix. + * + * @param observation Observation matrix. + * @param probs Vector to store probability value of observation x. + */ + void Probability(const arma::mat& observation, arma::vec& probs) const; + + /** * Return the log probability that the given observation came from this * distribution. * - * @param observation Observation to evaluate the probability of. + * @param observation Observation vector to evaluate the probability of. */ double LogProbability(const arma::vec& observation) const; + /** + * Return the log-probability of the given observation (x) matrix. + * + * @param observation Observation matrix. + * @param logProbs Vector to store log-probability value of observation. + */ + void LogProbability(const arma::mat& observation, arma::vec& logProbs) const; + /** * Return the probability that the given observation came from the given * Gaussian component in this distribution. diff --git a/src/mlpack/methods/hmm/hmm_impl.hpp b/src/mlpack/methods/hmm/hmm_impl.hpp index ae9521df9f..ea40c7e053 100644 --- a/src/mlpack/methods/hmm/hmm_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_impl.hpp @@ -143,6 +143,18 @@ double HMM::Train(const std::vector& dataSeq) for (size_t j = 0; j < transition.n_cols; ++j) newLogInitial[j] = math::LogAdd(newLogInitial[j], stateLogProb(j, 0)); + // Define a variable to store the value of log-probability for data. + arma::mat logProbs(dataSeq[seq].n_cols, transition.n_rows); + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq[seq], alias); + } + + // Now re-estimate the parameters. This is the M-step. // pi_i = sum_d ((1 / P(seq[d])) sum_t (f(i, 0) b(i, 0)) // T_ij = sum_d ((1 / P(seq[d])) sum_t (f(i, t) T_ij E_i(seq[d][t]) b(i, @@ -160,9 +172,8 @@ double HMM::Train(const std::vector& dataSeq) for (size_t i = 0; i < transition.n_rows; i++) { newLogTransition(i, j) = math::LogAdd(newLogTransition(i, j), - forwardLog(j, t) + backwardLog(i, t + 1) + - emission[i].LogProbability(dataSeq[seq].unsafe_col(t + 1)) - - logScales[t + 1]); + forwardLog(j, t) + backwardLog(i, t + 1) + logProbs(t + 1, i) + - logScales[t + 1]); } } @@ -464,6 +475,19 @@ double HMM::Predict(const arma::mat& dataSeq, // Store the best first state. arma::uword index; + + // Define a variable to store the value of log-probability for dataSeq. + arma::mat logProbs(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + for (size_t t = 1; t < dataSeq.n_cols; t++) { // Assemble the state probability for this element. @@ -472,8 +496,7 @@ double HMM::Predict(const arma::mat& dataSeq, for (size_t j = 0; j < transition.n_rows; j++) { arma::vec prob = logStateProb.col(t - 1) + logTrans.col(j); - logStateProb(j, t) = prob.max(index) + - emission[j].LogProbability(dataSeq.unsafe_col(t)); + logStateProb(j, t) = prob.max(index) + logProbs(t, j); stateSeqBack(j, t) = index; } } @@ -570,6 +593,18 @@ void HMM::Forward(const arma::mat& dataSeq, arma::mat logTrans = trans(log(transition)); + // Define a variable to store the value of log-probability for dataSeq. + arma::mat logProbs(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + // The first entry in the forward algorithm uses the initial state // probabilities. Note that MATLAB assumes that the starting state (at // t = -1) is state 0; this is not our assumption here. To force that @@ -577,8 +612,7 @@ void HMM::Forward(const arma::mat& dataSeq, // sequence and that should produce results in line with MATLAB. for (size_t state = 0; state < transition.n_rows; state++) { - forwardLogProb(state, 0) = log(initial(state)) + - emission[state].LogProbability(dataSeq.unsafe_col(0)); + forwardLogProb(state, 0) = log(initial(state)) + logProbs(0, state); } // Then normalize the column. @@ -595,8 +629,7 @@ void HMM::Forward(const arma::mat& dataSeq, // of the probability of the previous state transitioning to the current // state and emitting the given observation. arma::vec tmp = forwardLogProb.col(t - 1) + logTrans.col(j); - forwardLogProb(j, t) = math::AccuLog(tmp) + - emission[j].LogProbability(dataSeq.unsafe_col(t)); + forwardLogProb(j, t) = math::AccuLog(tmp) + logProbs(t, j); } // Normalize probability. @@ -620,6 +653,18 @@ void HMM::Backward(const arma::mat& dataSeq, // The last element probability is 1. backwardLogProb.col(dataSeq.n_cols - 1).fill(0); + // Define a variable to store the value of log-probability for dataSeq. + arma::mat logProbs(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + // Now step backwards through all other observations. for (size_t t = dataSeq.n_cols - 2; t + 1 > 0; t--) { @@ -633,7 +678,7 @@ void HMM::Backward(const arma::mat& dataSeq, { backwardLogProb(j, t) = math::LogAdd(backwardLogProb(j, t), logTrans(state, j) + backwardLogProb(state, t + 1) - + emission[state].LogProbability(dataSeq.unsafe_col(t + 1))); + + logProbs(t + 1, state)); } // Normalize by the weights from the forward algorithm. diff --git a/src/mlpack/tests/gmm_test.cpp b/src/mlpack/tests/gmm_test.cpp index f0a523bdff..f3982b9638 100644 --- a/src/mlpack/tests/gmm_test.cpp +++ b/src/mlpack/tests/gmm_test.cpp @@ -28,7 +28,7 @@ using namespace mlpack::gmm; BOOST_AUTO_TEST_SUITE(GMMTest); /** - * Test GMM::Probability() for a single observation for a few cases. + * Test GMM::Probability() for a different observation for a few cases. */ BOOST_AUTO_TEST_CASE(GMMProbabilityTest) { @@ -45,6 +45,46 @@ BOOST_AUTO_TEST_CASE(GMMProbabilityTest) BOOST_REQUIRE_CLOSE(gmm.Probability("3 3"), 0.06432759685, 1e-5); BOOST_REQUIRE_CLOSE(gmm.Probability("-1 5.3"), 2.503171278804e-6, 1e-5); BOOST_REQUIRE_CLOSE(gmm.Probability("1.4 0"), 0.024676682176, 1e-5); + + arma::vec probs; + + arma::mat obs("0 1;" + "0 1;"); + + gmm.Probability(obs, probs); + + BOOST_REQUIRE_EQUAL(probs.n_elem, 2); + + BOOST_REQUIRE_CLOSE(probs(0), 0.05094887202, 1e-5); + BOOST_REQUIRE_CLOSE(probs(1), 0.03451996667, 1e-5); +} + +/** + * Test GMM::LogProbability() for different observation for a few cases. + */ +BOOST_AUTO_TEST_CASE(GMMLogProbabilityTest) +{ + // Create a GMM. + GMM gmm(2, 2); + gmm.Component(0) = distribution::GaussianDistribution("0 0", "1 0; 0 1"); + gmm.Component(1) = distribution::GaussianDistribution("3 3", "2 1; 1 2"); + gmm.Weights() = "0.3 0.7"; + + // Now test a couple observations. These comparisons are calculated by hand. + BOOST_REQUIRE_CLOSE(gmm.LogProbability("0 0"), -2.97693265851, 1e-5); + BOOST_REQUIRE_CLOSE(gmm.LogProbability("1 1"), -3.36621737829, 1e-5); + + arma::vec logProbs; + + arma::mat obs("0 1;" + "0 1;"); + + gmm.LogProbability(obs, logProbs); + + BOOST_REQUIRE_EQUAL(logProbs.n_elem, 2); + + BOOST_REQUIRE_CLOSE(logProbs(0), -2.97693265851, 1e-5); + BOOST_REQUIRE_CLOSE(logProbs(1), -3.36621737829, 1e-5); } /** From 269d719141ff4255773508f9e390ec8313e4bf04 Mon Sep 17 00:00:00 2001 From: jeffinsam Date: Tue, 5 Nov 2019 21:55:31 +0530 Subject: [PATCH 002/729] optimise hmm further --- src/mlpack/methods/gmm/gmm.hpp | 1 - src/mlpack/methods/hmm/hmm.hpp | 11 +++--- src/mlpack/methods/hmm/hmm_impl.hpp | 57 ++++++++++++++--------------- src/mlpack/tests/gmm_test.cpp | 2 +- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/mlpack/methods/gmm/gmm.hpp b/src/mlpack/methods/gmm/gmm.hpp index f2fb4a7c8d..77edae5427 100644 --- a/src/mlpack/methods/gmm/gmm.hpp +++ b/src/mlpack/methods/gmm/gmm.hpp @@ -172,7 +172,6 @@ class GMM */ void Probability(const arma::mat& observation, arma::vec& probs) const; - /** * Return the log probability that the given observation came from this * distribution. diff --git a/src/mlpack/methods/hmm/hmm.hpp b/src/mlpack/methods/hmm/hmm.hpp index 1c113d36c1..fc24dd3ae3 100644 --- a/src/mlpack/methods/hmm/hmm.hpp +++ b/src/mlpack/methods/hmm/hmm.hpp @@ -215,7 +215,7 @@ class HMM arma::mat& stateLogProb, arma::mat& forwardLogProb, arma::mat& backwardLogProb, - arma::vec& logScales) const; + arma::vec& logScales); /** * Estimate the probabilities of each hidden state at each time step for each @@ -239,7 +239,7 @@ class HMM arma::mat& stateProb, arma::mat& forwardProb, arma::mat& backwardProb, - arma::vec& scales) const; + arma::vec& scales); /** * Estimate the probabilities of each hidden state at each time step of each @@ -253,7 +253,7 @@ class HMM * @return Log-likelihood of most likely state sequence. */ double Estimate(const arma::mat& dataSeq, - arma::mat& stateProb) const; + arma::mat& stateProb); /** * Generate a random data sequence of the given length. The data sequence is @@ -290,7 +290,7 @@ class HMM * @param dataSeq Data sequence to evaluate the likelihood of. * @return Log-likelihood of the given sequence. */ - double LogLikelihood(const arma::mat& dataSeq) const; + double LogLikelihood(const arma::mat& dataSeq); /** * HMM filtering. Computes the k-step-ahead expected emission at each time @@ -320,7 +320,7 @@ class HMM * stored. */ void Smooth(const arma::mat& dataSeq, - arma::mat& smoothSeq) const; + arma::mat& smoothSeq); //! Return the vector of initial state probabilities. const arma::vec& Initial() const { return initial; } @@ -399,6 +399,7 @@ class HMM //! Tolerance of Baum-Welch algorithm. double tolerance; + arma::mat logProbs; }; } // namespace hmm diff --git a/src/mlpack/methods/hmm/hmm_impl.hpp b/src/mlpack/methods/hmm/hmm_impl.hpp index ea40c7e053..291666ff16 100644 --- a/src/mlpack/methods/hmm/hmm_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_impl.hpp @@ -329,8 +329,19 @@ double HMM::LogEstimate(const arma::mat& dataSeq, arma::mat& stateLogProb, arma::mat& forwardLogProb, arma::mat& backwardLogProb, - arma::vec& logScales) const + arma::vec& logScales) { + logProbs.resize(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + // First run the forward-backward algorithm. Forward(dataSeq, logScales, forwardLogProb); Backward(dataSeq, logScales, backwardLogProb); @@ -352,7 +363,7 @@ double HMM::Estimate(const arma::mat& dataSeq, arma::mat& stateProb, arma::mat& forwardProb, arma::mat& backwardProb, - arma::vec& scales) const + arma::vec& scales) { arma::mat stateLogProb; arma::mat forwardLogProb; @@ -376,7 +387,7 @@ double HMM::Estimate(const arma::mat& dataSeq, */ template double HMM::Estimate(const arma::mat& dataSeq, - arma::mat& stateProb) const + arma::mat& stateProb) { // We don't need to save these. arma::mat stateLogProb; @@ -517,11 +528,23 @@ double HMM::Predict(const arma::mat& dataSeq, * Compute the log-likelihood of the given data sequence. */ template -double HMM::LogLikelihood(const arma::mat& dataSeq) const +double HMM::LogLikelihood(const arma::mat& dataSeq) { arma::mat forwardLog; arma::vec logScales; + // This is needed here + logProbs.resize(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + Forward(dataSeq, logScales, forwardLog); // The log-likelihood is the log of the scales for each time step. @@ -559,7 +582,7 @@ void HMM::Filter(const arma::mat& dataSeq, */ template void HMM::Smooth(const arma::mat& dataSeq, - arma::mat& smoothSeq) const + arma::mat& smoothSeq) { // First run the forward algorithm. arma::mat stateLogProb; @@ -593,18 +616,6 @@ void HMM::Forward(const arma::mat& dataSeq, arma::mat logTrans = trans(log(transition)); - // Define a variable to store the value of log-probability for dataSeq. - arma::mat logProbs(dataSeq.n_cols, transition.n_rows); - - // Save the values of log-probability to logProbs. - for (size_t i = 0; i < transition.n_rows; i++) - { - // Define alias of desired column. - arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); - // Use advanced constructor for using logProbs directly. - emission[i].LogProbability(dataSeq, alias); - } - // The first entry in the forward algorithm uses the initial state // probabilities. Note that MATLAB assumes that the starting state (at // t = -1) is state 0; this is not our assumption here. To force that @@ -653,18 +664,6 @@ void HMM::Backward(const arma::mat& dataSeq, // The last element probability is 1. backwardLogProb.col(dataSeq.n_cols - 1).fill(0); - // Define a variable to store the value of log-probability for dataSeq. - arma::mat logProbs(dataSeq.n_cols, transition.n_rows); - - // Save the values of log-probability to logProbs. - for (size_t i = 0; i < transition.n_rows; i++) - { - // Define alias of desired column. - arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); - // Use advanced constructor for using logProbs directly. - emission[i].LogProbability(dataSeq, alias); - } - // Now step backwards through all other observations. for (size_t t = dataSeq.n_cols - 2; t + 1 > 0; t--) { diff --git a/src/mlpack/tests/gmm_test.cpp b/src/mlpack/tests/gmm_test.cpp index f3982b9638..003babe8eb 100644 --- a/src/mlpack/tests/gmm_test.cpp +++ b/src/mlpack/tests/gmm_test.cpp @@ -28,7 +28,7 @@ using namespace mlpack::gmm; BOOST_AUTO_TEST_SUITE(GMMTest); /** - * Test GMM::Probability() for a different observation for a few cases. + * Test GMM::Probability() with a single observation at a time for a few cases. */ BOOST_AUTO_TEST_CASE(GMMProbabilityTest) { From decc1b4df4afe7555dd947d092e65d7b3cecd3e9 Mon Sep 17 00:00:00 2001 From: jeffinsam Date: Tue, 5 Nov 2019 21:55:31 +0530 Subject: [PATCH 003/729] optimise hmm further --- src/mlpack/methods/gmm/gmm.hpp | 1 - src/mlpack/methods/hmm/hmm.hpp | 11 +++--- src/mlpack/methods/hmm/hmm_impl.hpp | 57 ++++++++++++++--------------- src/mlpack/tests/gmm_test.cpp | 2 +- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/mlpack/methods/gmm/gmm.hpp b/src/mlpack/methods/gmm/gmm.hpp index f2fb4a7c8d..77edae5427 100644 --- a/src/mlpack/methods/gmm/gmm.hpp +++ b/src/mlpack/methods/gmm/gmm.hpp @@ -172,7 +172,6 @@ class GMM */ void Probability(const arma::mat& observation, arma::vec& probs) const; - /** * Return the log probability that the given observation came from this * distribution. diff --git a/src/mlpack/methods/hmm/hmm.hpp b/src/mlpack/methods/hmm/hmm.hpp index 1c113d36c1..fc24dd3ae3 100644 --- a/src/mlpack/methods/hmm/hmm.hpp +++ b/src/mlpack/methods/hmm/hmm.hpp @@ -215,7 +215,7 @@ class HMM arma::mat& stateLogProb, arma::mat& forwardLogProb, arma::mat& backwardLogProb, - arma::vec& logScales) const; + arma::vec& logScales); /** * Estimate the probabilities of each hidden state at each time step for each @@ -239,7 +239,7 @@ class HMM arma::mat& stateProb, arma::mat& forwardProb, arma::mat& backwardProb, - arma::vec& scales) const; + arma::vec& scales); /** * Estimate the probabilities of each hidden state at each time step of each @@ -253,7 +253,7 @@ class HMM * @return Log-likelihood of most likely state sequence. */ double Estimate(const arma::mat& dataSeq, - arma::mat& stateProb) const; + arma::mat& stateProb); /** * Generate a random data sequence of the given length. The data sequence is @@ -290,7 +290,7 @@ class HMM * @param dataSeq Data sequence to evaluate the likelihood of. * @return Log-likelihood of the given sequence. */ - double LogLikelihood(const arma::mat& dataSeq) const; + double LogLikelihood(const arma::mat& dataSeq); /** * HMM filtering. Computes the k-step-ahead expected emission at each time @@ -320,7 +320,7 @@ class HMM * stored. */ void Smooth(const arma::mat& dataSeq, - arma::mat& smoothSeq) const; + arma::mat& smoothSeq); //! Return the vector of initial state probabilities. const arma::vec& Initial() const { return initial; } @@ -399,6 +399,7 @@ class HMM //! Tolerance of Baum-Welch algorithm. double tolerance; + arma::mat logProbs; }; } // namespace hmm diff --git a/src/mlpack/methods/hmm/hmm_impl.hpp b/src/mlpack/methods/hmm/hmm_impl.hpp index ea40c7e053..18d7493d40 100644 --- a/src/mlpack/methods/hmm/hmm_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_impl.hpp @@ -329,8 +329,19 @@ double HMM::LogEstimate(const arma::mat& dataSeq, arma::mat& stateLogProb, arma::mat& forwardLogProb, arma::mat& backwardLogProb, - arma::vec& logScales) const + arma::vec& logScales) { + logProbs.resize(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + // First run the forward-backward algorithm. Forward(dataSeq, logScales, forwardLogProb); Backward(dataSeq, logScales, backwardLogProb); @@ -352,7 +363,7 @@ double HMM::Estimate(const arma::mat& dataSeq, arma::mat& stateProb, arma::mat& forwardProb, arma::mat& backwardProb, - arma::vec& scales) const + arma::vec& scales) { arma::mat stateLogProb; arma::mat forwardLogProb; @@ -376,7 +387,7 @@ double HMM::Estimate(const arma::mat& dataSeq, */ template double HMM::Estimate(const arma::mat& dataSeq, - arma::mat& stateProb) const + arma::mat& stateProb) { // We don't need to save these. arma::mat stateLogProb; @@ -517,11 +528,23 @@ double HMM::Predict(const arma::mat& dataSeq, * Compute the log-likelihood of the given data sequence. */ template -double HMM::LogLikelihood(const arma::mat& dataSeq) const +double HMM::LogLikelihood(const arma::mat& dataSeq) { arma::mat forwardLog; arma::vec logScales; + // This is needed here. + logProbs.resize(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + Forward(dataSeq, logScales, forwardLog); // The log-likelihood is the log of the scales for each time step. @@ -559,7 +582,7 @@ void HMM::Filter(const arma::mat& dataSeq, */ template void HMM::Smooth(const arma::mat& dataSeq, - arma::mat& smoothSeq) const + arma::mat& smoothSeq) { // First run the forward algorithm. arma::mat stateLogProb; @@ -593,18 +616,6 @@ void HMM::Forward(const arma::mat& dataSeq, arma::mat logTrans = trans(log(transition)); - // Define a variable to store the value of log-probability for dataSeq. - arma::mat logProbs(dataSeq.n_cols, transition.n_rows); - - // Save the values of log-probability to logProbs. - for (size_t i = 0; i < transition.n_rows; i++) - { - // Define alias of desired column. - arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); - // Use advanced constructor for using logProbs directly. - emission[i].LogProbability(dataSeq, alias); - } - // The first entry in the forward algorithm uses the initial state // probabilities. Note that MATLAB assumes that the starting state (at // t = -1) is state 0; this is not our assumption here. To force that @@ -653,18 +664,6 @@ void HMM::Backward(const arma::mat& dataSeq, // The last element probability is 1. backwardLogProb.col(dataSeq.n_cols - 1).fill(0); - // Define a variable to store the value of log-probability for dataSeq. - arma::mat logProbs(dataSeq.n_cols, transition.n_rows); - - // Save the values of log-probability to logProbs. - for (size_t i = 0; i < transition.n_rows; i++) - { - // Define alias of desired column. - arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); - // Use advanced constructor for using logProbs directly. - emission[i].LogProbability(dataSeq, alias); - } - // Now step backwards through all other observations. for (size_t t = dataSeq.n_cols - 2; t + 1 > 0; t--) { diff --git a/src/mlpack/tests/gmm_test.cpp b/src/mlpack/tests/gmm_test.cpp index f3982b9638..003babe8eb 100644 --- a/src/mlpack/tests/gmm_test.cpp +++ b/src/mlpack/tests/gmm_test.cpp @@ -28,7 +28,7 @@ using namespace mlpack::gmm; BOOST_AUTO_TEST_SUITE(GMMTest); /** - * Test GMM::Probability() for a different observation for a few cases. + * Test GMM::Probability() with a single observation at a time for a few cases. */ BOOST_AUTO_TEST_CASE(GMMProbabilityTest) { From 6c1653d15a7bbd1dcf1dc52cf22073300023e2c5 Mon Sep 17 00:00:00 2001 From: jeffinsam Date: Fri, 15 Nov 2019 13:36:43 +0530 Subject: [PATCH 004/729] Remove logprobs as object --- src/mlpack/methods/hmm/hmm.hpp | 16 ++++++------ src/mlpack/methods/hmm/hmm_impl.hpp | 38 ++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/mlpack/methods/hmm/hmm.hpp b/src/mlpack/methods/hmm/hmm.hpp index fc24dd3ae3..ce9014f3ea 100644 --- a/src/mlpack/methods/hmm/hmm.hpp +++ b/src/mlpack/methods/hmm/hmm.hpp @@ -215,7 +215,7 @@ class HMM arma::mat& stateLogProb, arma::mat& forwardLogProb, arma::mat& backwardLogProb, - arma::vec& logScales); + arma::vec& logScales) const; /** * Estimate the probabilities of each hidden state at each time step for each @@ -239,7 +239,7 @@ class HMM arma::mat& stateProb, arma::mat& forwardProb, arma::mat& backwardProb, - arma::vec& scales); + arma::vec& scales) const; /** * Estimate the probabilities of each hidden state at each time step of each @@ -253,7 +253,7 @@ class HMM * @return Log-likelihood of most likely state sequence. */ double Estimate(const arma::mat& dataSeq, - arma::mat& stateProb); + arma::mat& stateProb) const; /** * Generate a random data sequence of the given length. The data sequence is @@ -290,7 +290,7 @@ class HMM * @param dataSeq Data sequence to evaluate the likelihood of. * @return Log-likelihood of the given sequence. */ - double LogLikelihood(const arma::mat& dataSeq); + double LogLikelihood(const arma::mat& dataSeq) const; /** * HMM filtering. Computes the k-step-ahead expected emission at each time @@ -367,7 +367,8 @@ class HMM */ void Forward(const arma::mat& dataSeq, arma::vec& logScales, - arma::mat& forwardLogProb) const; + arma::mat& forwardLogProb, + arma::mat& logProbs) const; /** * The Backward algorithm (part of the Forward-Backward algorithm). Computes @@ -382,7 +383,8 @@ class HMM */ void Backward(const arma::mat& dataSeq, const arma::vec& logScales, - arma::mat& backwardLogProb) const; + arma::mat& backwardLogProb, + arma::mat& logProbs) const; //! Set of emission probability distributions; one for each state. std::vector emission; @@ -399,7 +401,7 @@ class HMM //! Tolerance of Baum-Welch algorithm. double tolerance; - arma::mat logProbs; + }; } // namespace hmm diff --git a/src/mlpack/methods/hmm/hmm_impl.hpp b/src/mlpack/methods/hmm/hmm_impl.hpp index 18d7493d40..842dfae7a9 100644 --- a/src/mlpack/methods/hmm/hmm_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_impl.hpp @@ -329,9 +329,9 @@ double HMM::LogEstimate(const arma::mat& dataSeq, arma::mat& stateLogProb, arma::mat& forwardLogProb, arma::mat& backwardLogProb, - arma::vec& logScales) + arma::vec& logScales) const { - logProbs.resize(dataSeq.n_cols, transition.n_rows); + arma::mat logProbs(dataSeq.n_cols, transition.n_rows); // Save the values of log-probability to logProbs. for (size_t i = 0; i < transition.n_rows; i++) @@ -343,8 +343,8 @@ double HMM::LogEstimate(const arma::mat& dataSeq, } // First run the forward-backward algorithm. - Forward(dataSeq, logScales, forwardLogProb); - Backward(dataSeq, logScales, backwardLogProb); + Forward(dataSeq, logScales, forwardLogProb, logProbs); + Backward(dataSeq, logScales, backwardLogProb, logProbs); // Now assemble the state probability matrix based on the forward and backward // probabilities. @@ -363,7 +363,7 @@ double HMM::Estimate(const arma::mat& dataSeq, arma::mat& stateProb, arma::mat& forwardProb, arma::mat& backwardProb, - arma::vec& scales) + arma::vec& scales) const { arma::mat stateLogProb; arma::mat forwardLogProb; @@ -387,7 +387,7 @@ double HMM::Estimate(const arma::mat& dataSeq, */ template double HMM::Estimate(const arma::mat& dataSeq, - arma::mat& stateProb) + arma::mat& stateProb) const { // We don't need to save these. arma::mat stateLogProb; @@ -528,13 +528,13 @@ double HMM::Predict(const arma::mat& dataSeq, * Compute the log-likelihood of the given data sequence. */ template -double HMM::LogLikelihood(const arma::mat& dataSeq) +double HMM::LogLikelihood(const arma::mat& dataSeq) const { arma::mat forwardLog; arma::vec logScales; // This is needed here. - logProbs.resize(dataSeq.n_cols, transition.n_rows); + arma::mat logProbs(dataSeq.n_cols, transition.n_rows); // Save the values of log-probability to logProbs. for (size_t i = 0; i < transition.n_rows; i++) @@ -545,7 +545,7 @@ double HMM::LogLikelihood(const arma::mat& dataSeq) emission[i].LogProbability(dataSeq, alias); } - Forward(dataSeq, logScales, forwardLog); + Forward(dataSeq, logScales, forwardLog, logProbs); // The log-likelihood is the log of the scales for each time step. return accu(logScales); @@ -562,7 +562,19 @@ void HMM::Filter(const arma::mat& dataSeq, // First run the forward algorithm. arma::mat forwardLogProb; arma::vec logScales; - Forward(dataSeq, logScales, forwardLogProb); + // This is needed here. + arma::mat logProbs(dataSeq.n_cols, transition.n_rows); + + // Save the values of log-probability to logProbs. + for (size_t i = 0; i < transition.n_rows; i++) + { + // Define alias of desired column. + arma::vec alias(logProbs.colptr(i), logProbs.n_rows, false, true); + // Use advanced constructor for using logProbs directly. + emission[i].LogProbability(dataSeq, alias); + } + + Forward(dataSeq, logScales, forwardLogProb, logProbs); arma::mat forwardProb = exp(forwardLogProb); @@ -605,7 +617,8 @@ void HMM::Smooth(const arma::mat& dataSeq, template void HMM::Forward(const arma::mat& dataSeq, arma::vec& logScales, - arma::mat& forwardLogProb) const + arma::mat& forwardLogProb, + arma::mat& logProbs) const { // Our goal is to calculate the forward probabilities: // P(X_k | o_{1:k}) for all possible states X_k, for each time point k. @@ -653,7 +666,8 @@ void HMM::Forward(const arma::mat& dataSeq, template void HMM::Backward(const arma::mat& dataSeq, const arma::vec& logScales, - arma::mat& backwardLogProb) const + arma::mat& backwardLogProb, + arma::mat& logProbs) const { // Our goal is to calculate the backward probabilities: // P(X_k | o_{k + 1:T}) for all possible states X_k, for each time point k. From 123635533c9daa596651e11ade8093df6f18df8f Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Mon, 30 Nov 2020 19:53:13 +0530 Subject: [PATCH 005/729] Added template to data::Split --- src/mlpack/core/data/split_data.hpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 42b7e03b3a..bbc503e385 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -169,6 +169,7 @@ void StratifiedSplit(const arma::Mat& input, * testData, trainLabel, testLabel, 0.3); * @endcode * + * @tparam LabelsType Type of input labels. It must be arma::Mat or arma::row. * @param input Input dataset to split. * @param inputLabel Input labels to split. * @param trainData Matrix to store training data into. @@ -179,13 +180,15 @@ void StratifiedSplit(const arma::Mat& input, * @param shuffleData If true, the sample order is shuffled; otherwise, each * sample is visited in linear order. (Default true.) */ -template +template::value || + arma::is_Mat_only::value> > void Split(const arma::Mat& input, - const arma::Row& inputLabel, + const LabelsType& inputLabel, arma::Mat& trainData, arma::Mat& testData, - arma::Row& trainLabel, - arma::Row& testLabel, + LabelsType& trainLabel, + LabelsType& testLabel, const double testRatio, const bool shuffleData = true) { @@ -295,6 +298,7 @@ void Split(const arma::Mat& input, * auto splitResult = Split(input, label, 0.2); * @endcode * + * @tparam LabelsType Type of input labels. It must be arma::Mat or arma::row. * @param input Input dataset to split. * @param inputLabel Input labels to split. * @param testRatio Percentage of dataset to use for test set (between 0 and 1). @@ -306,18 +310,20 @@ void Split(const arma::Mat& input, * @return std::tuple containing trainData (arma::Mat), testData * (arma::Mat), trainLabel (arma::Row), and testLabel (arma::Row). */ -template -std::tuple, arma::Mat, arma::Row, arma::Row> +template::value || + arma::is_Mat_only::value> > +std::tuple, arma::Mat, LabelsType, LabelsType> Split(const arma::Mat& input, - const arma::Row& inputLabel, + const LabelsType& inputLabel, const double testRatio, const bool shuffleData = true, const bool stratifyData = false) { arma::Mat trainData; arma::Mat testData; - arma::Row trainLabel; - arma::Row testLabel; + LabelsType trainLabel; + LabelsType testLabel; if (stratifyData) { From cc4e5f4839a7e96e9391d40566c0cb177c3928c4 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Mon, 30 Nov 2020 21:13:31 +0530 Subject: [PATCH 006/729] Added support for field matrices --- src/mlpack/core/data/split_data.hpp | 222 ++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index bbc503e385..02395ad432 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -374,6 +374,228 @@ Split(const arma::Mat& input, std::move(testData)); } +/** + * Given an input dataset and labels, split into a training set and test set. + * Example usage below. This overload places the split dataset into the four + * output parameters given (trainData, testData, trainLabel, and testLabel). + * + * NOTE: Here FieldType could be arma::field or arma::field + * + * @code + * arma::field input = loadData(); + * arma::field label = loadLabel(); + * arma::field trainData; + * arma::field testData; + * arma::field trainLabel; + * arma::field testLabel; + * math::RandomSeed(100); // Set the seed if you like. + * + * // Split the dataset into a training and test set, with 30% of the data being + * // held out for the test set. + * Split(input, label, trainData, + * testData, trainLabel, testLabel, 0.3); + * @endcode + * + * @param input Input dataset to split. + * @param inputLabel Input labels to split. + * @param trainData FieldType to store training data into. + * @param testData FieldType test data into. + * @param trainLabel Field vector to store training labels into. + * @param testLabel Field vector to store test labels into. + * @param testRatio Percentage of dataset to use for test set (between 0 and 1). + * @param shuffleData If true, the sample order is shuffled; otherwise, each + * sample is visited in linear order. (Default true.) + */ +template ::value || + arma::is_Mat_only::value>> +void Split(FieldType& input, + arma::field& inputLabel, + FieldType& trainData, + arma::field& trainLabels, + FieldType& testData, + arma::field& testLabels, + const double testRatio, + const bool shuffleData = true) +{ + const size_t testSize = static_cast(input.n_cols * testRatio); + const size_t trainSize = input.n_cols - testSize; + + trainData.set_size(1, trainSize); + testData.set_size(1, testSize); + + arma::uvec order = arma::linspace(0, input.n_cols - 1, + input.n_cols); + if (shuffleData) + order = arma::shuffle(order); + + if (trainSize > 0) + { + trainLabels.set_size(1, trainSize); + + for (size_t i = 0; i < trainSize; i++) + trainData[i] = input(0, order(i)); + + for (size_t i = 0; i < trainSize; i++) + trainLabels(0, i) = inputLabel[i]; + } + + if (testSize <= input.n_cols) + { + for (size_t i = trainSize; i < input.n_cols - 1; i++) + testData[i - trainSize] = input(0, order(i)); + + testLabels.set_size(1, testSize); + for (size_t i = trainSize; i < input.n_cols; i++) + testLabels(0, i - trainSize) = inputLabel[i]; + } +} + +/** + * Given an input dataset, split into a training set and test set. + * Example usage below. This overload places the split dataset into the two + * output parameters given (trainData, testData). + * + * NOTE: Here FieldType could be arma::field or arma::field + * + * @code + * arma::field input = loadData(); + * arma::field trainData; + * arma::field testData; + * math::RandomSeed(100); // Set the seed if you like. + * + * // Split the dataset into a training and test set, with 30% of the data being + * // held out for the test set. + * Split(input, trainData, testData, 0.3); + * @endcode + * + * @param input Input dataset to split. + * @param trainData FieldType to store training data into. + * @param testData FieldType test data into. + * @param testRatio Percentage of dataset to use for test set (between 0 and 1). + * @param shuffleData If true, the sample order is shuffled; otherwise, each + * sample is visited in linear order. (Default true). + */ +template ::value || + arma::is_Mat_only::value>> +void Split(const FieldType& input, + FieldType& trainData, + FieldType& testData, + const double testRatio, + const bool shuffleData = true) +{ + const size_t testSize = static_cast(input.n_cols * testRatio); + const size_t trainSize = input.n_cols - testSize; + + trainData.set_size(1, trainSize); + testData.set_size(1, testSize); + + arma::uvec order = arma::linspace(0, input.n_cols - 1, + input.n_cols); + if (shuffleData) + order = arma::shuffle(order); + + if (trainSize > 0) + { + for (size_t i = 0; i < trainSize; i++) + trainData[i] = input(0, order(i)); + } + + if (testSize <= input.n_cols) + { + for (size_t i = trainSize; i < input.n_cols - 1; i++) + testData[i - trainSize] = input(0, order(i)); + } +} + +/** + * Given an input dataset and labels, split into a training set and test set. + * Example usage below. This overload returns the split dataset as a std::tuple + * with four elements: an FieldType containing the training data, an + * FieldType containing the test data, an arma::field containing the + * training labels, and an arma::field containing the test labels. + * + * NOTE: Here FieldType could be arma::field or arma::field + * + * @code + * arma::field input = loadData(); + * arma::field label = loadLabel(); + * auto splitResult = Split(input, label, 0.2); + * @endcode + * + * @param input Input dataset to split. + * @param inputLabel Input labels to split. + * @param testRatio Percentage of dataset to use for test set (between 0 and 1). + * @param shuffleData If true, the sample order is shuffled; otherwise, each + * sample is visited in linear order. (Default true). + * @return std::tuple containing trainData (FieldType), testData + * (FieldType), trainLabel (arma::field), and + * testLabel (arma::field). + */ +template ::value || + arma::is_Mat_only::value>> +std::tuple +Split(FieldType& input, + arma::field& inputLabel, + const double testRatio, + const bool shuffleData = true) +{ + FieldType trainData; + FieldType testData; + arma::field trainLabel; + arma::field testLabel; + + Split(input, inputLabel, trainData, testData, trainLabel, testLabel, + testRatio, shuffleData); + + return std::make_tuple(std::move(trainData), + std::move(testData), + std::move(trainLabel), + std::move(testLabel)); +} + +/** + * Given an input dataset, split into a training set and test set. + * Example usage below. This overload returns the split dataset as a std::tuple + * with two elements: an FieldType containing the training data and an + * FieldType containing the test data. + * + * NOTE: Here FieldType could be arma::field or arma::field + * + * @code + * arma::field input = loadData(); + * auto splitResult = Split(input, 0.2); + * @endcode + * + * @param input Input dataset to split. + * @param testRatio Percentage of dataset to use for test set (between 0 and 1). + * @param shuffleData If true, the sample order is shuffled; otherwise, each + * sample is visited in linear order. (Default true). + * @return std::tuple containing trainData (FieldType) + * and testData (FieldType). + */ +template ::value || + arma::is_Mat_only::value>> +std::tuple +Split(const FieldType& input, + const double testRatio, + const bool shuffleData = true) +{ + FieldType trainData; + FieldType testData; + Split(input, trainData, testData, testRatio, shuffleData); + + return std::make_tuple(std::move(trainData), + std::move(testData)); +} + } // namespace data } // namespace mlpack From e401c65c67a87547bed663225470875930f12693 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Mon, 30 Nov 2020 22:32:17 +0530 Subject: [PATCH 007/729] Test for field type in data::Split --- src/mlpack/tests/split_data_test.cpp | 24 ++++++++++++++++++++++++ src/mlpack/tests/test_catch_tools.hpp | 15 +++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 8de9d5f66b..996c6ccfa4 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -121,6 +121,30 @@ TEST_CASE("SplitDataResultMat", "[SplitDataTest]") CheckMatrices(input, concat); } +TEST_CASE("SplitDataResultField", "[SplitDataTest]") +{ + field input(1, 2); + + mat matA(2, 10); + mat matB(2, 10); + + size_t count = 0; // Counter for unique sequential values. + matA.imbue([&count]() { return ++count; }); + matB.imbue([&count]() { return ++count; }); + + input(0, 0) = matA; + input(0, 1) = matB; + + const auto value = Split(input, 0.5, false); + REQUIRE(std::get<0>(value).n_cols == 1); // Train data. + REQUIRE(std::get<1>(value).n_cols == 1); // Test data. + + field concat = {std::get<0>(value)(0), std::get<1>(value)(0)}; + // Order matters here. + CheckFields(input, concat); +} + + TEST_CASE("ZeroRatioSplitData", "[SplitDataTest]") { mat input(2, 10); diff --git a/src/mlpack/tests/test_catch_tools.hpp b/src/mlpack/tests/test_catch_tools.hpp index 1bac310ddc..7b34cfc150 100644 --- a/src/mlpack/tests/test_catch_tools.hpp +++ b/src/mlpack/tests/test_catch_tools.hpp @@ -50,6 +50,21 @@ inline void CheckMatrices(const arma::Mat& a, REQUIRE(a[i] == b[i]); } +template ::value>> +// Check the values of two field types +inline void CheckFields(const FieldType& a, + const FieldType& b) +{ + REQUIRE(a.n_rows == b.n_rows); + REQUIRE(a.n_cols == b.n_cols); + + for (size_t i = 0; i < a.n_slices; ++i) + CheckMatrices(a(i), b(i)); +} + + // Check the values of two cubes. inline void CheckMatrices(const arma::cube& a, const arma::cube& b, From b89af6ef324403b1c7c36abe13e6f721922061af Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 6 Jan 2021 10:25:39 +0530 Subject: [PATCH 008/729] Update src/mlpack/tests/test_catch_tools.hpp Co-authored-by: Ryan Curtin --- src/mlpack/tests/test_catch_tools.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/tests/test_catch_tools.hpp b/src/mlpack/tests/test_catch_tools.hpp index 7b34cfc150..dfd0577b19 100644 --- a/src/mlpack/tests/test_catch_tools.hpp +++ b/src/mlpack/tests/test_catch_tools.hpp @@ -64,7 +64,6 @@ inline void CheckFields(const FieldType& a, CheckMatrices(a(i), b(i)); } - // Check the values of two cubes. inline void CheckMatrices(const arma::cube& a, const arma::cube& b, From d50af3ee7bb2529638c6b22cee5bc6e4bdb3123f Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Wed, 6 Jan 2021 12:47:22 +0530 Subject: [PATCH 009/729] Added documentation for template parameter --- src/mlpack/core/data/split_data.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 02395ad432..8a50ceeaf3 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -169,6 +169,7 @@ void StratifiedSplit(const arma::Mat& input, * testData, trainLabel, testLabel, 0.3); * @endcode * + * @tparam T Type of the elements of the input matrix. * @tparam LabelsType Type of input labels. It must be arma::Mat or arma::row. * @param input Input dataset to split. * @param inputLabel Input labels to split. @@ -298,6 +299,7 @@ void Split(const arma::Mat& input, * auto splitResult = Split(input, label, 0.2); * @endcode * + * @tparam T Type of the elements of the input matrix. * @tparam LabelsType Type of input labels. It must be arma::Mat or arma::row. * @param input Input dataset to split. * @param inputLabel Input labels to split. From 6a79d4da99d3197cd3d997868a8be20029585908 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Thu, 14 Jan 2021 09:24:11 +0530 Subject: [PATCH 010/729] Fix Solaris(on CRAN) and windows issue. --- src/mlpack/bindings/R/mlpack/src/Makevars | 2 +- src/mlpack/bindings/R/mlpack/src/Makevars.win | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/bindings/R/mlpack/src/Makevars b/src/mlpack/bindings/R/mlpack/src/Makevars index bb6a88cc84..4cca03b1a5 100644 --- a/src/mlpack/bindings/R/mlpack/src/Makevars +++ b/src/mlpack/bindings/R/mlpack/src/Makevars @@ -1,3 +1,3 @@ -PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) +PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) CXX_STD = CXX11 diff --git a/src/mlpack/bindings/R/mlpack/src/Makevars.win b/src/mlpack/bindings/R/mlpack/src/Makevars.win index bb6a88cc84..4cca03b1a5 100644 --- a/src/mlpack/bindings/R/mlpack/src/Makevars.win +++ b/src/mlpack/bindings/R/mlpack/src/Makevars.win @@ -1,3 +1,3 @@ -PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) +PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) CXX_STD = CXX11 From 0c3ec81d4b024d214ef086e96768b3496fe62447 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Wed, 3 Feb 2021 00:14:26 +0530 Subject: [PATCH 011/729] Changed the restrictors from is_Row to is_arma_type --- src/mlpack/core/data/split_data.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 8a50ceeaf3..055045282f 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -170,7 +170,8 @@ void StratifiedSplit(const arma::Mat& input, * @endcode * * @tparam T Type of the elements of the input matrix. - * @tparam LabelsType Type of input labels. It must be arma::Mat or arma::row. + * @tparam LabelsType Type of input labels. It can be arma::Mat, arma::row, + * arma::Cube or arma::SpMat. * @param input Input dataset to split. * @param inputLabel Input labels to split. * @param trainData Matrix to store training data into. @@ -182,7 +183,7 @@ void StratifiedSplit(const arma::Mat& input, * sample is visited in linear order. (Default true.) */ template::value || + typename = std::enable_if_t::value || arma::is_Mat_only::value> > void Split(const arma::Mat& input, const LabelsType& inputLabel, @@ -300,7 +301,8 @@ void Split(const arma::Mat& input, * @endcode * * @tparam T Type of the elements of the input matrix. - * @tparam LabelsType Type of input labels. It must be arma::Mat or arma::row. + * @tparam LabelsType Type of input labels. It can be arma::Mat, arma::row, + * arma::Cube or arma::SpMat. * @param input Input dataset to split. * @param inputLabel Input labels to split. * @param testRatio Percentage of dataset to use for test set (between 0 and 1). @@ -313,7 +315,7 @@ void Split(const arma::Mat& input, * (arma::Mat), trainLabel (arma::Row), and testLabel (arma::Row). */ template::value || + typename = std::enable_if_t::value || arma::is_Mat_only::value> > std::tuple, arma::Mat, LabelsType, LabelsType> Split(const arma::Mat& input, From 591ac9670571c5040aa32b2dcd69127fb93bd345 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Wed, 3 Feb 2021 00:21:49 +0530 Subject: [PATCH 012/729] Improved documentation of overload of split for field --- src/mlpack/core/data/split_data.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 055045282f..1225e6cd8d 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -382,6 +382,8 @@ Split(const arma::Mat& input, * Given an input dataset and labels, split into a training set and test set. * Example usage below. This overload places the split dataset into the four * output parameters given (trainData, testData, trainLabel, and testLabel). + * + * The input dataset must be of type arma::field and have a single row. * * NOTE: Here FieldType could be arma::field or arma::field * @@ -460,6 +462,8 @@ void Split(FieldType& input, * Given an input dataset, split into a training set and test set. * Example usage below. This overload places the split dataset into the two * output parameters given (trainData, testData). + * + * The input dataset must be of type arma::field and have a single row. * * NOTE: Here FieldType could be arma::field or arma::field * @@ -521,6 +525,8 @@ void Split(const FieldType& input, * with four elements: an FieldType containing the training data, an * FieldType containing the test data, an arma::field containing the * training labels, and an arma::field containing the test labels. + * + * The input dataset must be of type arma::field and have a single row. * * NOTE: Here FieldType could be arma::field or arma::field * @@ -568,6 +574,8 @@ Split(FieldType& input, * Example usage below. This overload returns the split dataset as a std::tuple * with two elements: an FieldType containing the training data and an * FieldType containing the test data. + * + * The input dataset must be of type arma::field and have a single row. * * NOTE: Here FieldType could be arma::field or arma::field * From 66fcef9e0ccf7e622cdfc1da8db15f0191e5b073 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Thu, 4 Feb 2021 09:15:25 +0530 Subject: [PATCH 013/729] Removed redundant is_Mat_type restrictor --- src/mlpack/core/data/split_data.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 1225e6cd8d..4067e8af09 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -183,8 +183,7 @@ void StratifiedSplit(const arma::Mat& input, * sample is visited in linear order. (Default true.) */ template::value || - arma::is_Mat_only::value> > + typename = std::enable_if_t::value> void Split(const arma::Mat& input, const LabelsType& inputLabel, arma::Mat& trainData, @@ -315,8 +314,7 @@ void Split(const arma::Mat& input, * (arma::Mat), trainLabel (arma::Row), and testLabel (arma::Row). */ template::value || - arma::is_Mat_only::value> > + typename = std::enable_if_t::value> std::tuple, arma::Mat, LabelsType, LabelsType> Split(const arma::Mat& input, const LabelsType& inputLabel, From 0b06b2bfde43ce468a2207b120e48d85d6b39482 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Thu, 4 Feb 2021 09:35:46 +0530 Subject: [PATCH 014/729] Improved documentation --- src/mlpack/core/data/split_data.hpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 4067e8af09..561366de2b 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -381,7 +381,8 @@ Split(const arma::Mat& input, * Example usage below. This overload places the split dataset into the four * output parameters given (trainData, testData, trainLabel, and testLabel). * - * The input dataset must be of type arma::field and have a single row. + * The input dataset must be of type arma::field. It should have the shape - + * (n_rows = 1, n_cols = Number of samples, n_slices = 1) * * NOTE: Here FieldType could be arma::field or arma::field * @@ -461,7 +462,8 @@ void Split(FieldType& input, * Example usage below. This overload places the split dataset into the two * output parameters given (trainData, testData). * - * The input dataset must be of type arma::field and have a single row. + * The input dataset must be of type arma::field. It should have the shape - + * (n_rows = 1, n_cols = Number of samples, n_slices = 1) * * NOTE: Here FieldType could be arma::field or arma::field * @@ -524,7 +526,8 @@ void Split(const FieldType& input, * FieldType containing the test data, an arma::field containing the * training labels, and an arma::field containing the test labels. * - * The input dataset must be of type arma::field and have a single row. + * The input dataset must be of type arma::field. It should have the shape - + * (n_rows = 1, n_cols = Number of samples, n_slices = 1) * * NOTE: Here FieldType could be arma::field or arma::field * @@ -573,7 +576,8 @@ Split(FieldType& input, * with two elements: an FieldType containing the training data and an * FieldType containing the test data. * - * The input dataset must be of type arma::field and have a single row. + * The input dataset must be of type arma::field. It should have the shape - + * (n_rows = 1, n_cols = Number of samples, n_slices = 1) * * NOTE: Here FieldType could be arma::field or arma::field * From 7da50e3ba577906beb005808fc5efad71d7fe178 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Thu, 4 Feb 2021 12:25:24 +0530 Subject: [PATCH 015/729] Fixed brackets --- src/mlpack/core/data/split_data.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 561366de2b..e9358d23c9 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -183,7 +183,7 @@ void StratifiedSplit(const arma::Mat& input, * sample is visited in linear order. (Default true.) */ template::value> + typename = std::enable_if_t::value> > void Split(const arma::Mat& input, const LabelsType& inputLabel, arma::Mat& trainData, @@ -314,7 +314,7 @@ void Split(const arma::Mat& input, * (arma::Mat), trainLabel (arma::Row), and testLabel (arma::Row). */ template::value> + typename = std::enable_if_t::value> > std::tuple, arma::Mat, LabelsType, LabelsType> Split(const arma::Mat& input, const LabelsType& inputLabel, From cbb534daa150606b5b280902d4829741e14d39bb Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Thu, 4 Feb 2021 16:38:12 +0530 Subject: [PATCH 016/729] Added test case for matrix labels --- src/mlpack/tests/split_data_test.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 996c6ccfa4..d3d445796e 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -199,6 +199,26 @@ TEST_CASE("SplitLabeledDataResultMat", "[SplitDataTest]") CheckDuplication(std::get<2>(value), std::get<3>(value)); } +TEST_CASE("SplitMatrixLabeledDataResultMat", "[SplitDataTest]") +{ + mat input(2, 10); + input.randu(); + + const mat labels(2, 10, fill::randu); + + const auto value = Split(input, labels, 0.2); + REQUIRE(std::get<0>(value).n_cols == 8); + REQUIRE(std::get<1>(value).n_cols == 2); + REQUIRE(std::get<2>(value).n_cols == 8); + REQUIRE(std::get<3>(value).n_cols == 2); + + mat input_concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); + mat labels_concat = arma::join_rows(std::get<2>(value), std::get<3>(value)); + // Order matters here. + CheckMatrices(input, input_concat); + CheckMatrices(labels, labels_concat); +} + /** * The same test as above, but on a larger dataset. */ From f7289b8fd7ae085f87c5c1503c0971608f925f28 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Fri, 19 Feb 2021 21:37:53 +0530 Subject: [PATCH 017/729] Integrated Anush's Code --- src/mlpack/core/data/split_data.hpp | 93 +++++++++------------------- src/mlpack/tests/split_data_test.cpp | 45 +++----------- 2 files changed, 37 insertions(+), 101 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index e9358d23c9..5d8c6aa720 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -23,6 +23,8 @@ namespace data { * It is recommended to have the input labels between the range [0, n) where n * is the number of different labels. The NormalizeLabels() function in * mlpack::data can be used for this. + * Expects labels to be of type arma::Row<>. + * Throws a runtime error if this is not the case. * Example usage below. This overload places the stratified dataset into the * four output parameters given (trainData, testData, trainLabel, * and testLabel). @@ -52,56 +54,27 @@ namespace data { * @param shuffleData If true, the sample order is shuffled; otherwise, each * sample is visited in linear order. (Default true.) */ -template +template::value> > void StratifiedSplit(const arma::Mat& input, - const arma::Row& inputLabel, + const LabelsType& inputLabel, arma::Mat& trainData, arma::Mat& testData, - arma::Row& trainLabel, - arma::Row& testLabel, + LabelsType& trainLabel, + LabelsType& testLabel, const double testRatio, const bool shuffleData = true) { - /** - * Basic idea: - * Let us say we have to stratify a dataset based on labels: - * 0 0 0 0 0 (5 0s) - * 1 1 1 1 1 1 1 1 1 1 1 (11 1s) - * - * Let our test ratio be 0.2. - * Then, the number of 0 labels in our test set = floor(5 * 0.2) = 1. - * The number of 1 labels in our test set = floor(11 * 0.2) = 2. - * - * In our first pass over the dataset, - * We visit each label and keep count of each label in our 'labelCounts' uvec. - * - * We then take a second pass over the dataset. - * We now maintain an additional uvec 'testLabelCounts' to hold the label - * counts of our test set. - * - * In this pass, when we encounter a label we check the 'testLabelCounts' uvec - * for the count of this label in the test set. - * If this count is less than the required number of labels in the test set, - * we add the data to the test set and increment the label count in the uvec. - * If this count is equal to or more than the required count in the test set, - * we add this data to the train set. - * - * Based on the above steps, we get the following labels in the split set: - * Train set (4 0s, 9 1s) - * 0 0 0 0 - * 1 1 1 1 1 1 1 1 1 - * - * Test set (1 0s, 2 1s) - * 0 - * 1 1 - */ + if (!arma::is_Row::value) + throw std::runtime_error("data::Split(): when stratified sampling is done," + "labels must have type `arma::Row<>`!"); size_t trainIdx = 0; size_t testIdx = 0; size_t trainSize = 0; size_t testSize = 0; arma::uvec labelCounts; arma::uvec testLabelCounts; - U maxLabel = inputLabel.max(); + auto maxLabel = inputLabel.max(); labelCounts.zeros(maxLabel+1); testLabelCounts.zeros(maxLabel+1); @@ -114,7 +87,7 @@ void StratifiedSplit(const arma::Mat& input, order = arma::shuffle(order); } - for (U label : inputLabel) + for (auto label : inputLabel) { ++labelCounts[label]; } @@ -132,7 +105,7 @@ void StratifiedSplit(const arma::Mat& input, for (arma::uword i : order) { - U label = inputLabel[i]; + auto label = inputLabel[i]; if (testLabelCounts[label] < floor(labelCounts[label] * testRatio)) { testLabelCounts[label] += 1; @@ -197,36 +170,26 @@ void Split(const arma::Mat& input, const size_t trainSize = input.n_cols - testSize; trainData.set_size(input.n_rows, trainSize); testData.set_size(input.n_rows, testSize); - trainLabel.set_size(trainSize); - testLabel.set_size(testSize); + arma::uvec order = arma::linspace(0, input.n_cols - 1, + input.n_cols); if (shuffleData) { - arma::uvec order = arma::shuffle(arma::linspace( - 0, input.n_cols - 1, input.n_cols)); - if (trainSize > 0) - { - trainData = input.cols(order.subvec(0, trainSize - 1)); - trainLabel = inputLabel.cols(order.subvec(0, trainSize - 1)); - } - if (trainSize < input.n_cols) - { - testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); - testLabel = inputLabel.cols(order.subvec(trainSize, input.n_cols - 1)); - } + trainLabel.set_size(1, trainSize); + trainData = input.cols(order.subvec(0, trainSize - 1)); + + for (size_t i = 0; i < trainSize; i++) + trainLabel(0, i) = inputLabel(0, order(i)); } else + + if (trainSize < input.n_cols) { - if (trainSize > 0) - { - trainData = input.cols(0, trainSize - 1); - trainLabel = inputLabel.subvec(0, trainSize - 1); - } - if (trainSize < input.n_cols) - { - testData = input.cols(trainSize , input.n_cols - 1); - testLabel = inputLabel.subvec(trainSize , input.n_cols - 1); - } + testLabel.set_size(1, testSize); + testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); + + for (size_t i = trainSize; i < input.n_cols; i++) + testLabel(0, i - trainSize) = inputLabel(0, order(i)); } } @@ -309,7 +272,7 @@ void Split(const arma::Mat& input, * sample is visited in linear order. (Default true). * @param stratifyData If true, the train and test splits are stratified * so that the ratio of each class in the training and test sets is the same - * as in the original dataset. + * as in the original dataset. Expects labels to be of type arma::Row<>. * @return std::tuple containing trainData (arma::Mat), testData * (arma::Mat), trainLabel (arma::Row), and testLabel (arma::Row). */ diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index d3d445796e..41227097f3 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -322,47 +322,20 @@ TEST_CASE("StratifiedSplitDataResultTest", "[SplitDataTest]") CheckMatEqual(input, concat); } + /** - * Check if data is stratified according to labels on a larger data set. - * Example calculation to find resultant number of samples in the train and - * test set: - * - * Since there are 256 0s and the test ratio is 0.3, - * Number of 0s in the test set = 76 ( floor(256 * 0.3) = floor(76.8) ). - * Number of 0s in the train set = 180 ( 256 - 76 ). + * Check that Split() with stratifyData true throws a runtime error if labels + * are not of type arma::Row<>. */ -TEST_CASE("StratifiedSplitLargerDataResultTest", "[SplitDataTest]") +TEST_CASE("StratifiedSplitRunTimeErrorTest", "[SplitDataTest]") { mat input(3, 480); + mat labels(2, 480); input.randu(); + labels.randu(); - // 256 0s, 128 1s, 64 2s and 32 3s. - Row zero_label(256); - Row one_label(128); - Row two_label(64); - Row three_label(32); - - zero_label.fill(0); - one_label.fill(1); - two_label.fill(2); - three_label.fill(3); - - Row labels = arma::join_rows(zero_label, one_label); - labels = arma::join_rows(labels, two_label); - labels = arma::join_rows(labels, three_label); const double test_ratio = 0.3; - const auto value = Split(input, labels, test_ratio, false, true); - REQUIRE(static_cast(find(std::get<2>(value) == 0)).n_rows == 180); - REQUIRE(static_cast(find(std::get<2>(value) == 1)).n_rows == 90); - REQUIRE(static_cast(find(std::get<2>(value) == 2)).n_rows == 45); - REQUIRE(static_cast(find(std::get<2>(value) == 3)).n_rows == 23); - - REQUIRE(static_cast(find(std::get<3>(value) == 0)).n_rows == 76); - REQUIRE(static_cast(find(std::get<3>(value) == 1)).n_rows == 38); - REQUIRE(static_cast(find(std::get<3>(value) == 2)).n_rows == 19); - REQUIRE(static_cast(find(std::get<3>(value) == 3)).n_rows == 9); - - mat concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); - CheckMatEqual(input, concat); -} + REQUIRE_THROWS_AS(Split(input, labels, test_ratio, false, true), + std::runtime_error); +} \ No newline at end of file From 00778322a60661555cb8200d45e28e218df59528 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Sat, 20 Feb 2021 16:59:18 +0530 Subject: [PATCH 018/729] Fixed errors and added the accidentally removed testcase --- src/mlpack/core/data/split_data.hpp | 23 +++++++++-------- src/mlpack/tests/split_data_test.cpp | 38 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 5d8c6aa720..a4d10e389d 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -1,3 +1,4 @@ + /** * @file core/data/split_data.hpp * @author Tham Ngap Wei, Keon Kim @@ -174,6 +175,9 @@ void Split(const arma::Mat& input, arma::uvec order = arma::linspace(0, input.n_cols - 1, input.n_cols); if (shuffleData) + order = arma::shuffle(order); + + if (trainSize > 0) { trainLabel.set_size(1, trainSize); trainData = input.cols(order.subvec(0, trainSize - 1)); @@ -181,7 +185,6 @@ void Split(const arma::Mat& input, for (size_t i = 0; i < trainSize; i++) trainLabel(0, i) = inputLabel(0, order(i)); } - else if (trainSize < input.n_cols) { @@ -346,7 +349,7 @@ Split(const arma::Mat& input, * * The input dataset must be of type arma::field. It should have the shape - * (n_rows = 1, n_cols = Number of samples, n_slices = 1) - * + * * NOTE: Here FieldType could be arma::field or arma::field * * @code @@ -385,7 +388,7 @@ void Split(FieldType& input, FieldType& testData, arma::field& testLabels, const double testRatio, - const bool shuffleData = true) + const bool shuffleData = true) { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; @@ -406,7 +409,7 @@ void Split(FieldType& input, trainData[i] = input(0, order(i)); for (size_t i = 0; i < trainSize; i++) - trainLabels(0, i) = inputLabel[i]; + trainLabels(0, i) = inputLabel(0, order(i)); } if (testSize <= input.n_cols) @@ -416,7 +419,7 @@ void Split(FieldType& input, testLabels.set_size(1, testSize); for (size_t i = trainSize; i < input.n_cols; i++) - testLabels(0, i - trainSize) = inputLabel[i]; + testLabels(0, i - trainSize) = inputLabel(0, order(i)); } } @@ -427,7 +430,7 @@ void Split(FieldType& input, * * The input dataset must be of type arma::field. It should have the shape - * (n_rows = 1, n_cols = Number of samples, n_slices = 1) - * + * * NOTE: Here FieldType could be arma::field or arma::field * * @code @@ -491,7 +494,7 @@ void Split(const FieldType& input, * * The input dataset must be of type arma::field. It should have the shape - * (n_rows = 1, n_cols = Number of samples, n_slices = 1) - * + * * NOTE: Here FieldType could be arma::field or arma::field * * @code @@ -506,7 +509,7 @@ void Split(const FieldType& input, * @param shuffleData If true, the sample order is shuffled; otherwise, each * sample is visited in linear order. (Default true). * @return std::tuple containing trainData (FieldType), testData - * (FieldType), trainLabel (arma::field), and + * (FieldType), trainLabel (arma::field), and * testLabel (arma::field). */ template or arma::field * * @code @@ -576,4 +579,4 @@ Split(const FieldType& input, } // namespace data } // namespace mlpack -#endif +#endif \ No newline at end of file diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 41227097f3..f6136b8d99 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -322,6 +322,44 @@ TEST_CASE("StratifiedSplitDataResultTest", "[SplitDataTest]") CheckMatEqual(input, concat); } +/** + * Check if data is stratified according to labels on a larger data set. + * Example calculation to find resultant number of samples in the train and + * test set: + * + * Since there are 256 0s and the test ratio is 0.3, + * Number of 0s in the test set = 76 ( floor(256 * 0.3) = floor(76.8) ). + * Number of 0s in the train set = 180 ( 256 - 76 ). + */ +TEST_CASE("StratifiedSplitLargerDataResultTest", "[SplitDataTest]") +{ + mat input(3, 480); + input.randu(); + // 256 0s, 128 1s, 64 2s and 32 3s. + Row zero_label(256); + Row one_label(128); + Row two_label(64); + Row three_label(32); + zero_label.fill(0); + one_label.fill(1); + two_label.fill(2); + three_label.fill(3); + Row labels = arma::join_rows(zero_label, one_label); + labels = arma::join_rows(labels, two_label); + labels = arma::join_rows(labels, three_label); + const double test_ratio = 0.3; + const auto value = Split(input, labels, test_ratio, false, true); + REQUIRE(static_cast(find(std::get<2>(value) == 0)).n_rows == 180); + REQUIRE(static_cast(find(std::get<2>(value) == 1)).n_rows == 90); + REQUIRE(static_cast(find(std::get<2>(value) == 2)).n_rows == 45); + REQUIRE(static_cast(find(std::get<2>(value) == 3)).n_rows == 23); + REQUIRE(static_cast(find(std::get<3>(value) == 0)).n_rows == 76); + REQUIRE(static_cast(find(std::get<3>(value) == 1)).n_rows == 38); + REQUIRE(static_cast(find(std::get<3>(value) == 2)).n_rows == 19); + REQUIRE(static_cast(find(std::get<3>(value) == 3)).n_rows == 9); + mat concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); + CheckMatEqual(input, concat); +} /** * Check that Split() with stratifyData true throws a runtime error if labels From a2db3c92ed682f49d2a4360bf27b42fcb1607dd8 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 22 Feb 2021 18:26:45 +0530 Subject: [PATCH 019/729] Apply suggestions from code review Co-authored-by: Anush Kini <33577829+Abilityguy@users.noreply.github.com> Co-authored-by: Ryan Curtin --- src/mlpack/core/data/split_data.hpp | 26 +++++++++++++------------- src/mlpack/tests/split_data_test.cpp | 3 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index a4d10e389d..f4a75d871b 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -1,4 +1,3 @@ - /** * @file core/data/split_data.hpp * @author Tham Ngap Wei, Keon Kim @@ -67,7 +66,7 @@ void StratifiedSplit(const arma::Mat& input, const bool shuffleData = true) { if (!arma::is_Row::value) - throw std::runtime_error("data::Split(): when stratified sampling is done," + throw std::runtime_error("data::Split(): when stratified sampling is done, " "labels must have type `arma::Row<>`!"); size_t trainIdx = 0; size_t testIdx = 0; @@ -75,7 +74,7 @@ void StratifiedSplit(const arma::Mat& input, size_t testSize = 0; arma::uvec labelCounts; arma::uvec testLabelCounts; - auto maxLabel = inputLabel.max(); + typename LabelsType::elem_type maxLabel = inputLabel.max(); labelCounts.zeros(maxLabel+1); testLabelCounts.zeros(maxLabel+1); @@ -88,7 +87,7 @@ void StratifiedSplit(const arma::Mat& input, order = arma::shuffle(order); } - for (auto label : inputLabel) + for (typename LabelsType::elem_type label : inputLabel) { ++labelCounts[label]; } @@ -106,7 +105,7 @@ void StratifiedSplit(const arma::Mat& input, for (arma::uword i : order) { - auto label = inputLabel[i]; + typename LabelsType::elem_type label = inputLabel[i]; if (testLabelCounts[label] < floor(labelCounts[label] * testRatio)) { testLabelCounts[label] += 1; @@ -182,7 +181,7 @@ void Split(const arma::Mat& input, trainLabel.set_size(1, trainSize); trainData = input.cols(order.subvec(0, trainSize - 1)); - for (size_t i = 0; i < trainSize; i++) + for (size_t i = 0; i < trainSize; ++i) trainLabel(0, i) = inputLabel(0, order(i)); } @@ -191,7 +190,7 @@ void Split(const arma::Mat& input, testLabel.set_size(1, testSize); testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); - for (size_t i = trainSize; i < input.n_cols; i++) + for (size_t i = trainSize; i < input.n_cols; ++i) testLabel(0, i - trainSize) = inputLabel(0, order(i)); } } @@ -398,6 +397,7 @@ void Split(FieldType& input, arma::uvec order = arma::linspace(0, input.n_cols - 1, input.n_cols); + if (shuffleData) order = arma::shuffle(order); @@ -405,20 +405,20 @@ void Split(FieldType& input, { trainLabels.set_size(1, trainSize); - for (size_t i = 0; i < trainSize; i++) + for (size_t i = 0; i < trainSize; ++i) trainData[i] = input(0, order(i)); - for (size_t i = 0; i < trainSize; i++) + for (size_t i = 0; i < trainSize; ++i) trainLabels(0, i) = inputLabel(0, order(i)); } if (testSize <= input.n_cols) { - for (size_t i = trainSize; i < input.n_cols - 1; i++) + for (size_t i = trainSize; i < input.n_cols - 1; ++i) testData[i - trainSize] = input(0, order(i)); testLabels.set_size(1, testSize); - for (size_t i = trainSize; i < input.n_cols; i++) + for (size_t i = trainSize; i < input.n_cols; ++i) testLabels(0, i - trainSize) = inputLabel(0, order(i)); } } @@ -480,7 +480,7 @@ void Split(const FieldType& input, if (testSize <= input.n_cols) { - for (size_t i = trainSize; i < input.n_cols - 1; i++) + for (size_t i = trainSize; i < input.n_cols - 1; ++i) testData[i - trainSize] = input(0, order(i)); } } @@ -579,4 +579,4 @@ Split(const FieldType& input, } // namespace data } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index f6136b8d99..74862469ba 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -144,7 +144,6 @@ TEST_CASE("SplitDataResultField", "[SplitDataTest]") CheckFields(input, concat); } - TEST_CASE("ZeroRatioSplitData", "[SplitDataTest]") { mat input(2, 10); @@ -376,4 +375,4 @@ TEST_CASE("StratifiedSplitRunTimeErrorTest", "[SplitDataTest]") REQUIRE_THROWS_AS(Split(input, labels, test_ratio, false, true), std::runtime_error); -} \ No newline at end of file +} From 1b2ffe201f9139a4dc91c01fcadaee66ebdc56f4 Mon Sep 17 00:00:00 2001 From: Heisenbuug Date: Mon, 22 Feb 2021 19:08:50 +0530 Subject: [PATCH 020/729] Checking --- .../tests/feedforward_network_2_test.cpp | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/mlpack/tests/feedforward_network_2_test.cpp b/src/mlpack/tests/feedforward_network_2_test.cpp index 456367912c..104561cf03 100644 --- a/src/mlpack/tests/feedforward_network_2_test.cpp +++ b/src/mlpack/tests/feedforward_network_2_test.cpp @@ -31,12 +31,12 @@ using namespace mlpack::kmeans; /** * Train and evaluate a model with the specified structure. */ -template -void TestNetwork(ModelType& model, - MatType& trainData, - MatType& trainLabels, - MatType& testData, - MatType& testLabels, +template +void TestNetwork(ModelType &model, + MatType &trainData, + MatType &trainLabels, + MatType &testData, + MatType &testLabels, const size_t maxEpochs, const double classificationErrorThreshold) { @@ -50,7 +50,8 @@ void TestNetwork(ModelType& model, for (size_t i = 0; i < predictionTemp.n_cols; ++i) { prediction(i) = arma::as_scalar(arma::find( - arma::max(predictionTemp.col(i)) == predictionTemp.col(i), 1)) + 1; + arma::max(predictionTemp.col(i)) == predictionTemp.col(i), 1)) + + 1; } size_t correct = arma::accu(prediction == testLabels); @@ -65,7 +66,8 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot load dataset thyroid_train.csv") arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -77,7 +79,8 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") } arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv") arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -99,9 +102,9 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") KMeans<> kmeans; kmeans.Cluster(trainData, 8, centroids); - FFN > model; - model.Add >(trainData.n_rows, 8, centroids); - model.Add >(8, 3); + FFN> model; + model.Add>(trainData.n_rows, 8, centroids); + model.Add>(8, 3); // RBFN neural net with MeanSquaredError. TestNetwork<>(model, trainData, trainLabels1, testData, testLabels, 10, 0.1); @@ -131,9 +134,9 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") KMeans<> kmeans1; kmeans1.Cluster(dataset, 140, centroids1); - FFN > model1; - model1.Add >(dataset.n_rows, 140, centroids1, 4.1); - model1.Add >(140, 2); + FFN> model1; + model1.Add>(dataset.n_rows, 140, centroids1, 4.1); + model1.Add>(140, 2); // RBFN neural net with MeanSquaredError. TestNetwork<>(model1, dataset, labels1, dataset, labels, 10, 0.1); From 1f88bc9630472daf01efaa3ef448a71335208e44 Mon Sep 17 00:00:00 2001 From: Heisenbuug Date: Mon, 22 Feb 2021 20:32:12 +0530 Subject: [PATCH 021/729] Adding FAIL Messages --- .../tests/feedforward_network_2_test.cpp | 35 ++++++----- src/mlpack/tests/feedforward_network_test.cpp | 45 +++++++++----- src/mlpack/tests/io_test.cpp | 18 ++++-- src/mlpack/tests/kfn_test.cpp | 12 ++-- src/mlpack/tests/knn_test.cpp | 6 +- src/mlpack/tests/krann_search_test.cpp | 54 +++++++++++------ src/mlpack/tests/ksinit_test.cpp | 6 +- src/mlpack/tests/lars_test.cpp | 30 ++++++---- src/mlpack/tests/lin_alg_test.cpp | 3 +- src/mlpack/tests/lmnn_test.cpp | 12 ++-- src/mlpack/tests/load_save_test.cpp | 57 ++++++++++++------ src/mlpack/tests/lrsdp_test.cpp | 12 ++-- src/mlpack/tests/lsh_test.cpp | 45 +++++++++----- src/mlpack/tests/matrix_completion_test.cpp | 6 +- src/mlpack/tests/nbc_test.cpp | 60 ++++++++++++------- src/mlpack/tests/nystroem_method_test.cpp | 3 +- src/mlpack/tests/one_hot_encoding_test.cpp | 3 +- src/mlpack/tests/pca_test.cpp | 3 +- src/mlpack/tests/quic_svd_test.cpp | 3 +- src/mlpack/tests/radical_test.cpp | 6 +- src/mlpack/tests/random_forest_test.cpp | 42 ++++++++----- src/mlpack/tests/svd_incremental_test.cpp | 3 +- src/mlpack/tests/svdplusplus_test.cpp | 6 +- 23 files changed, 306 insertions(+), 164 deletions(-) diff --git a/src/mlpack/tests/feedforward_network_2_test.cpp b/src/mlpack/tests/feedforward_network_2_test.cpp index 104561cf03..3a57624d26 100644 --- a/src/mlpack/tests/feedforward_network_2_test.cpp +++ b/src/mlpack/tests/feedforward_network_2_test.cpp @@ -21,7 +21,7 @@ #include #include "catch.hpp" -#include "serialization_catch.hpp" +#include "serialization.hpp" #include "custom_layer.hpp" using namespace mlpack; @@ -31,12 +31,12 @@ using namespace mlpack::kmeans; /** * Train and evaluate a model with the specified structure. */ -template -void TestNetwork(ModelType &model, - MatType &trainData, - MatType &trainLabels, - MatType &testData, - MatType &testLabels, +template +void TestNetwork(ModelType& model, + MatType& trainData, + MatType& trainLabels, + MatType& testData, + MatType& testLabels, const size_t maxEpochs, const double classificationErrorThreshold) { @@ -50,8 +50,7 @@ void TestNetwork(ModelType &model, for (size_t i = 0; i < predictionTemp.n_cols; ++i) { prediction(i) = arma::as_scalar(arma::find( - arma::max(predictionTemp.col(i)) == predictionTemp.col(i), 1)) + - 1; + arma::max(predictionTemp.col(i)) == predictionTemp.col(i), 1)) + 1; } size_t correct = arma::accu(prediction == testLabels); @@ -67,7 +66,7 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") // Load the dataset. arma::mat trainData; if (!data::Load("thyroid_train.csv", trainData)) - FAIL("Cannot load dataset thyroid_train.csv") + Fail("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -80,7 +79,7 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") arma::mat testData; if (!data::Load("thyroid_test.csv", testData)) - FAIL("Cannot load dataset thyroid_test.csv") + Fail("Cannot open thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -102,9 +101,9 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") KMeans<> kmeans; kmeans.Cluster(trainData, 8, centroids); - FFN> model; - model.Add>(trainData.n_rows, 8, centroids); - model.Add>(8, 3); + FFN > model; + model.Add >(trainData.n_rows, 8, centroids); + model.Add >(8, 3); // RBFN neural net with MeanSquaredError. TestNetwork<>(model, trainData, trainLabels1, testData, testLabels, 10, 0.1); @@ -134,10 +133,10 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") KMeans<> kmeans1; kmeans1.Cluster(dataset, 140, centroids1); - FFN> model1; - model1.Add>(dataset.n_rows, 140, centroids1, 4.1); - model1.Add>(140, 2); + FFN > model1; + model1.Add >(dataset.n_rows, 140, centroids1, 4.1); + model1.Add >(140, 2); // RBFN neural net with MeanSquaredError. TestNetwork<>(model1, dataset, labels1, dataset, labels, 10, 0.1); -} +} \ No newline at end of file diff --git a/src/mlpack/tests/feedforward_network_test.cpp b/src/mlpack/tests/feedforward_network_test.cpp index 7188f69f50..c7386261bf 100644 --- a/src/mlpack/tests/feedforward_network_test.cpp +++ b/src/mlpack/tests/feedforward_network_test.cpp @@ -107,7 +107,8 @@ TEST_CASE("CheckCopyMovingVanillaNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -160,13 +161,15 @@ TEST_CASE("FFVanillaNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -307,13 +310,15 @@ TEST_CASE("DropoutNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -408,13 +413,15 @@ TEST_CASE("DropConnectNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -497,13 +504,15 @@ TEST_CASE("FFSerializationTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -546,13 +555,15 @@ TEST_CASE("CustomLayerTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -625,13 +636,15 @@ TEST_CASE("FFNTrainReturnObjective", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -695,13 +708,15 @@ TEST_CASE("OptimizerTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - data::Load("thyroid_train.csv", trainData, true); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); arma::mat testData; - data::Load("thyroid_test.csv", testData, true); + if (!data::Load("thyroid_test.csv", testData)) + FAIL("Cannot load dataset thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); diff --git a/src/mlpack/tests/io_test.cpp b/src/mlpack/tests/io_test.cpp index fa363face9..26319a8d79 100644 --- a/src/mlpack/tests/io_test.cpp +++ b/src/mlpack/tests/io_test.cpp @@ -413,7 +413,8 @@ TEST_CASE_METHOD(IOTestDestroyer, "OutputColParamTest", // Now load the vector back and make sure it was saved correctly. arma::vec dataset2; - data::Load("test.csv", dataset2); + if (!data::Load("test.csv", dataset2)) + FAIL("Cannot load dataset test.csv"); REQUIRE(dataset.n_rows == dataset2.n_rows); for (size_t i = 0; i < dataset.n_elem; ++i) @@ -461,7 +462,8 @@ TEST_CASE_METHOD(IOTestDestroyer, "OutputUnsignedColParamTest", // Now load the vector back and make sure it was saved correctly. arma::Col dataset2; - data::Load("test.csv", dataset2); + if (!data::Load("test.csv", dataset2)) + FAIL("Cannot load dataset test.csv"); REQUIRE(dataset.n_rows == dataset2.n_rows); for (size_t i = 0; i < dataset.n_elem; ++i) @@ -509,7 +511,8 @@ TEST_CASE_METHOD(IOTestDestroyer, "OutputRowParamTest", // Now load the row vector back and make sure it was saved correctly. arma::rowvec dataset2; - data::Load("test.csv", dataset2); + if (!data::Load("test.csv", dataset2)) + FAIL("Cannot load dataset test.csv"); REQUIRE(dataset.n_cols == dataset2.n_cols); for (size_t i = 0; i < dataset.n_elem; ++i) @@ -556,7 +559,8 @@ TEST_CASE_METHOD(IOTestDestroyer, "OutputUnsignedRowParamTest", "[IOTest]") // Now load the row vector back and make sure it was saved correctly. arma::Row dataset2; - data::Load("test.csv", dataset2); + if (!data::Load("test.csv", dataset2)) + FAIL("Cannot load dataset test.csv"); REQUIRE(dataset.n_cols == dataset2.n_cols); for (size_t i = 0; i < dataset.n_elem; ++i) @@ -784,7 +788,8 @@ TEST_CASE_METHOD(IOTestDestroyer, "OutputMatrixParamTest", // Now load the matrix back and make sure it was saved correctly. arma::mat dataset2; - data::Load("test.csv", dataset2); + if (!data::Load("test.csv", dataset2)) + FAIL("Cannot load dataset test.csv"); REQUIRE(dataset.n_cols == dataset2.n_cols); REQUIRE(dataset.n_rows == dataset2.n_rows); @@ -833,7 +838,8 @@ TEST_CASE_METHOD(IOTestDestroyer, "OutputMatrixNoTransposeParamTest", // Now load the matrix back and make sure it was saved correctly. arma::mat dataset2; - data::Load("test.csv", dataset2, true, false); + if (!data::Load("test.csv", dataset2, false, false)) + FAIL("Cannot load dataset test.csv"); REQUIRE(dataset.n_cols == dataset2.n_cols); REQUIRE(dataset.n_rows == dataset2.n_rows); diff --git a/src/mlpack/tests/kfn_test.cpp b/src/mlpack/tests/kfn_test.cpp index f3fefadb7a..1fb813b2e1 100644 --- a/src/mlpack/tests/kfn_test.cpp +++ b/src/mlpack/tests/kfn_test.cpp @@ -335,7 +335,7 @@ TEST_CASE("KFNDualTreeVsNaive1", "[KFNTest]") // Hard-coded filename: bad? if (!data::Load("test_data_3_1000.csv", dataset)) - FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv"); KFN kfn(dataset); @@ -369,7 +369,7 @@ TEST_CASE("KFNDualTreeVsNaive2", "[KFNTest]") // Hard-coded filename: bad? // Code duplication: also bad! if (!data::Load("test_data_3_1000.csv", dataset)) - FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv"); KFN kfn(dataset); @@ -403,7 +403,7 @@ TEST_CASE("KFNSingleTreeVsNaive", "[KFNTest]") // Hard-coded filename: bad! // Code duplication: also bad! if (!data::Load("test_data_3_1000.csv", dataset)) - FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv"); KFN kfn(dataset, SINGLE_TREE_MODE); @@ -466,7 +466,8 @@ TEST_CASE("KFNSingleCoverTreeTest", "[KFNTest]") TEST_CASE("KFNDualCoverTreeTest", "[KFNTest]") { arma::mat dataset; - data::Load("test_data_3_1000.csv", dataset); + if (!data::Load("test_data_3_1000.csv", dataset)) + FAIL("Cannot load test dataset test_data_3_1000.csv"); KFN tree(dataset); @@ -538,7 +539,8 @@ TEST_CASE("KFNSingleBallTreeTest", "[KFNTest]") TEST_CASE("KFNDualBallTreeTest", "[KFNTest]") { arma::mat dataset; - data::Load("test_data_3_1000.csv", dataset); + if (!data::Load("test_data_3_1000.csv", dataset)) + FAIL("Cannot load test dataset test_data_3_1000.csv"); KFN tree(dataset); diff --git a/src/mlpack/tests/knn_test.cpp b/src/mlpack/tests/knn_test.cpp index 7e84700843..5f151eb4b6 100644 --- a/src/mlpack/tests/knn_test.cpp +++ b/src/mlpack/tests/knn_test.cpp @@ -794,7 +794,8 @@ TEST_CASE("KNNSingleCoverTreeTest", "[KNNTest]") TEST_CASE("KNNDualCoverTreeTest", "[KNNTest]") { arma::mat dataset; - data::Load("test_data_3_1000.csv", dataset); + if (!data::Load("test_data_3_1000.csv", dataset)) + FAIL("Cannot load test dataset test_data_3_1000.csv"); KNN tree(dataset); @@ -865,7 +866,8 @@ TEST_CASE("KNNSingleBallTreeTest", "[KNNTest]") TEST_CASE("KNNDualBallTreeTest", "[KNNTest]") { arma::mat dataset; - data::Load("test_data_3_1000.csv", dataset); + if (!data::Load("test_data_3_1000.csv", dataset)) + FAIL("Cannot load test dataset test_data_3_1000.csv"); KNN tree(dataset); diff --git a/src/mlpack/tests/krann_search_test.cpp b/src/mlpack/tests/krann_search_test.cpp index 4efa022776..5bc13eb952 100644 --- a/src/mlpack/tests/krann_search_test.cpp +++ b/src/mlpack/tests/krann_search_test.cpp @@ -35,13 +35,16 @@ TEST_CASE("NaiveGuaranteeTest", "[KRANNTest]") arma::mat refData; arma::mat queryData; - data::Load("rann_test_r_3_900.csv", refData, true); - data::Load("rann_test_q_3_100.csv", queryData, true); + if (!data::Load("rann_test_r_3_900.csv", refData)) + FAIL("Cannot load dataset rann_test_r_3_900.csv"); + if (!data::Load("rann_test_q_3_100.csv", queryData)) + FAIL("Cannot load dataset rann_test_q_3_100.csv"); RASearch<> rsRann(refData, true, false, 1.0); arma::mat qrRanks; - data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; arma::Col numSuccessRounds(queryData.n_cols); @@ -88,8 +91,10 @@ TEST_CASE("SingleTreeSearch", "[KRANNTest]") arma::mat refData; arma::mat queryData; - data::Load("rann_test_r_3_900.csv", refData, true); - data::Load("rann_test_q_3_100.csv", queryData, true); + if (!data::Load("rann_test_r_3_900.csv", refData)) + FAIL("Cannot load dataset rann_test_r_3_900.csv"); + if (!data::Load("rann_test_q_3_100.csv", queryData)) + FAIL("Cannot load dataset rann_test_q_3_100.csv"); // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point // (rank error of 3). @@ -100,7 +105,8 @@ TEST_CASE("SingleTreeSearch", "[KRANNTest]") // The relative ranks for the given query reference pair arma::Mat qrRanks; - data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; arma::Col numSuccessRounds(queryData.n_cols); @@ -147,8 +153,10 @@ TEST_CASE("DualTreeSearch", "[KRANNTest]") arma::mat refData; arma::mat queryData; - data::Load("rann_test_r_3_900.csv", refData, true); - data::Load("rann_test_q_3_100.csv", queryData, true); + if (!data::Load("rann_test_r_3_900.csv", refData)) + FAIL("Cannot load dataset rann_test_r_3_900.csv"); + if (!data::Load("rann_test_q_3_100.csv", queryData)) + FAIL("Cannot load dataset rann_test_q_3_100.csv"); // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point // (rank error of 3). @@ -158,7 +166,8 @@ TEST_CASE("DualTreeSearch", "[KRANNTest]") RASearch<> tsdRann(refData, false, false, 1.0, 0.95, false, false, 5); arma::Mat qrRanks; - data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; arma::Col numSuccessRounds(queryData.n_cols); @@ -274,8 +283,10 @@ TEST_CASE("SingleCoverTreeTest", "[KRANNTest]") arma::mat refData; arma::mat queryData; - data::Load("rann_test_r_3_900.csv", refData, true); - data::Load("rann_test_q_3_100.csv", queryData, true); + if (!data::Load("rann_test_r_3_900.csv", refData)) + FAIL("Cannot load dataset rann_test_r_3_900.csv"); + if (!data::Load("rann_test_q_3_100.csv", queryData)) + FAIL("Cannot load dataset rann_test_q_3_100.csv"); // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point // (rank error of 3). @@ -289,7 +300,8 @@ TEST_CASE("SingleCoverTreeTest", "[KRANNTest]") // The relative ranks for the given query reference pair. arma::Mat qrRanks; - data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 100; arma::Col numSuccessRounds(queryData.n_cols); @@ -335,8 +347,10 @@ TEST_CASE("DualCoverTreeTest", "[KRANNTest]") arma::mat refData; arma::mat queryData; - data::Load("rann_test_r_3_900.csv", refData, true); - data::Load("rann_test_q_3_100.csv", queryData, true); + if (!data::Load("rann_test_r_3_900.csv", refData)) + FAIL("Cannot load dataset rann_test_r_3_900.csv"); + if (!data::Load("rann_test_q_3_100.csv", queryData)) + FAIL("Cannot load dataset rann_test_q_3_100.csv"); // Search for 1 rank-approximate nearest-neighbors in the top 30% of the point // (rank error of 3). @@ -354,7 +368,8 @@ TEST_CASE("DualCoverTreeTest", "[KRANNTest]") RACoverTreeSearch tsdRann(&refTree, false, 1.0, 0.95, false, false, 5); arma::Mat qrRanks; - data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 100; arma::Col numSuccessRounds(queryData.n_cols); @@ -623,8 +638,10 @@ TEST_CASE("RAModelTest", "[KRANNTest]") typedef RAModel KNNModel; arma::mat queryData, referenceData; - data::Load("rann_test_r_3_900.csv", referenceData, true); - data::Load("rann_test_q_3_100.csv", queryData, true); + if (!data::Load("rann_test_r_3_900.csv", referenceData)) + FAIL("Cannot load dataset rann_test_r_3_900.csv"); + if (!data::Load("rann_test_q_3_100.csv", queryData)) + FAIL("Cannot load dataset rann_test_q_3_100.csv"); // Build all the possible models. KNNModel models[20]; @@ -650,7 +667,8 @@ TEST_CASE("RAModelTest", "[KRANNTest]") models[19] = KNNModel(KNNModel::TreeTypes::OCTREE, true); arma::Mat qrRanks; - data::Load("rann_test_qr_ranks.csv", qrRanks, true, false); // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + FAIL("Cannot load dataset rann_test_qr_ranks.csv"); for (size_t j = 0; j < 3; ++j) { diff --git a/src/mlpack/tests/ksinit_test.cpp b/src/mlpack/tests/ksinit_test.cpp index 11d6cdae40..930df617e4 100644 --- a/src/mlpack/tests/ksinit_test.cpp +++ b/src/mlpack/tests/ksinit_test.cpp @@ -230,8 +230,10 @@ TEST_CASE("IrisDataset", "[KSInitialization]") arma::mat dataset, labels; - data::Load("iris.csv", dataset, true); - data::Load("iris_labels.txt", labels, true); + if (!data::Load("iris.csv", dataset)) + FAIL("Cannot load dataset iris.csv"); + if (!data::Load("iris_labels.txt", labels)) + FAIL("Cannot load dataset iris_labels.txt"); dataset.insert_rows(dataset.n_rows, labels); diff --git a/src/mlpack/tests/lars_test.cpp b/src/mlpack/tests/lars_test.cpp index ef030343ae..bb3a2aa767 100644 --- a/src/mlpack/tests/lars_test.cpp +++ b/src/mlpack/tests/lars_test.cpp @@ -111,8 +111,10 @@ TEST_CASE("CholeskySingularityTest", "[LARSTest]") arma::mat X; arma::mat Y; - data::Load("lars_dependent_x.csv", X); - data::Load("lars_dependent_y.csv", Y); + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); arma::rowvec y = Y.row(0); @@ -135,8 +137,10 @@ TEST_CASE("NoCholeskySingularityTest", "[LARSTest]") arma::mat X; arma::mat Y; - data::Load("lars_dependent_x.csv", X); - data::Load("lars_dependent_y.csv", Y); + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); arma::rowvec y = Y.row(0); @@ -357,8 +361,10 @@ TEST_CASE("LARSTrainReturnCorrelation", "[LARSTest]") arma::mat X; arma::mat Y; - data::Load("lars_dependent_x.csv", X); - data::Load("lars_dependent_y.csv", Y); + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); arma::rowvec y = Y.row(0); @@ -403,8 +409,10 @@ TEST_CASE("LARSTestComputeError", "[LARSTest]") arma::mat X; arma::mat Y; - data::Load("lars_dependent_x.csv", X); - data::Load("lars_dependent_y.csv", Y); + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); arma::rowvec y = Y.row(0); @@ -427,8 +435,10 @@ TEST_CASE("LARSCopyConstructorTest", "[LARSTest]") arma::rowvec targets; // Load training input and predictions for testing. - data::Load("lars_dependent_x.csv", features); - data::Load("lars_dependent_y.csv", Y); + if (!data::Load("lars_dependent_x.csv", features)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); targets = Y.row(0); // Check if the copy is accessible even after deleting the pointer to the diff --git a/src/mlpack/tests/lin_alg_test.cpp b/src/mlpack/tests/lin_alg_test.cpp index a43821d75d..4b8af04b79 100644 --- a/src/mlpack/tests/lin_alg_test.cpp +++ b/src/mlpack/tests/lin_alg_test.cpp @@ -91,7 +91,8 @@ TEST_CASE("TestOrthogonalize", "[LinAlgTest]") // Generate a random matrix; then, orthogonalize it and test if it's // orthogonal. mat tmp, orth; - data::Load("fake.csv", tmp); + if (!data::Load("fake.csv", tmp)) + FAIL("Cannot load dataset fake.csv"); Orthogonalize(tmp, orth); // test orthogonality diff --git a/src/mlpack/tests/lmnn_test.cpp b/src/mlpack/tests/lmnn_test.cpp index b767f4a940..4a0ce99360 100644 --- a/src/mlpack/tests/lmnn_test.cpp +++ b/src/mlpack/tests/lmnn_test.cpp @@ -699,8 +699,10 @@ TEST_CASE("LMNNFunctionGradientTest3", "[LMNNTest]") { arma::mat dataset; arma::Row labels; - data::Load("iris.csv", dataset); - data::Load("iris_labels.txt", labels); + if (!data::Load("iris.csv", dataset)) + FAIL("Cannot load dataset iris.csv"); + if (!data::Load("iris_labels.txt", labels)) + FAIL("Cannot load dataset iris_labels.txt"); LMNNFunction<> lmnnfn(dataset, labels, 1, 0.6, 1); @@ -716,8 +718,10 @@ TEST_CASE("LMNNFunctionGradientTest4", "[LMNNTest]") { arma::mat dataset; arma::Row labels; - data::Load("iris.csv", dataset); - data::Load("iris_labels.txt", labels); + if (!data::Load("iris.csv", dataset)) + FAIL("Cannot load dataset iris.csv"); + if (!data::Load("iris_labels.txt", labels)) + FAIL("Cannot load dataset iris_labels.txt"); LMNNFunction<> lmnnfn(dataset, labels, 1, 0.6, 1); diff --git a/src/mlpack/tests/load_save_test.cpp b/src/mlpack/tests/load_save_test.cpp index b9e8a839cf..bf7066c04f 100644 --- a/src/mlpack/tests/load_save_test.cpp +++ b/src/mlpack/tests/load_save_test.cpp @@ -1414,8 +1414,10 @@ TEST_CASE("RegularCSVDatasetInfoLoad", "[LoadSaveTest]") { arma::mat one, two; DatasetInfo info; - data::Load(testFiles[i], one); - data::Load(testFiles[i], two, info); + if (!data::Load(testFiles[i], one)) + FAIL("Cannot load dataset"); + if (!data::Load(testFiles[i], two, info); + FAIL("Cannot load dataset"); // Check that the matrices contain the same information. REQUIRE(one.n_elem == two.n_elem); @@ -1454,8 +1456,10 @@ TEST_CASE("NontransposedCSVDatasetInfoLoad", "[LoadSaveTest]") { arma::mat one, two; DatasetInfo info; - data::Load(testFiles[i], one, true, false); // No transpose. - data::Load(testFiles[i], two, info, true, false); + if (!data::Load(testFiles[i], one, false, false)) // No transpose. + FAIL("Cannot load dataset"); + if (!data::Load(testFiles[i], two, info, false, false)) + FAIL("Cannot load dataset"); // Check that the matrices contain the same information. REQUIRE(one.n_elem == two.n_elem); @@ -1494,7 +1498,8 @@ TEST_CASE("CategoricalCSVLoadTest00", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info); + if (!data::Load("test.csv", matrix, info)) + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 7); REQUIRE(matrix.n_rows == 3); @@ -1551,7 +1556,8 @@ TEST_CASE("CategoricalCSVLoadTest01", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true); + if (!data::Load("test.csv", matrix, info)) + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 4); REQUIRE(matrix.n_rows == 3); @@ -1596,7 +1602,8 @@ TEST_CASE("CategoricalCSVLoadTest02", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true); + if (!data::Load("test.csv", matrix, info)) + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 4); REQUIRE(matrix.n_rows == 3); @@ -1640,7 +1647,8 @@ TEST_CASE("CategoricalCSVLoadTest03", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true); + if (!data::Load("test.csv", matrix, info)) + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 4); REQUIRE(matrix.n_rows == 3); @@ -1684,7 +1692,8 @@ TEST_CASE("CategoricalCSVLoadTest04", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true); + if (!data::Load("test.csv", matrix, info)) + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 4); REQUIRE(matrix.n_rows == 3); @@ -1731,7 +1740,8 @@ TEST_CASE("CategoricalNontransposedCSVLoadTest00", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true, false); // No transpose. + if (!data::Load("test.csv", matrix, info, false, false)) // No transpose. + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 3); REQUIRE(matrix.n_rows == 7); @@ -1820,7 +1830,8 @@ TEST_CASE("CategoricalNontransposedCSVLoadTest01", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true, false); // No transpose. + if (!data::Load("test.csv", matrix, info, false, false)) // No transpose. + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 3); REQUIRE(matrix.n_rows == 4); @@ -1865,7 +1876,8 @@ TEST_CASE("CategoricalNontransposedCSVLoadTest02", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true, false); // No transpose. + if (!data::Load("test.csv", matrix, info, false, false)) // No transpose. + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 3); REQUIRE(matrix.n_rows == 4); @@ -1910,7 +1922,8 @@ TEST_CASE("CategoricalNontransposedCSVLoadTest03", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true, false); // No transpose. + if (!data::Load("test.csv", matrix, info, false, false)) // No transpose. + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 3); REQUIRE(matrix.n_rows == 4); @@ -1955,7 +1968,8 @@ TEST_CASE("CategoricalNontransposedCSVLoadTest04", "[LoadSaveTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info, true, false); // No transpose. + if (!data::Load("test.csv", matrix, info, false, false)) // No transpose. + FAIL("Cannot load dataset"); REQUIRE(matrix.n_cols == 3); REQUIRE(matrix.n_rows == 4); @@ -2003,7 +2017,8 @@ TEST_CASE("HarderKeonTest", "[LoadSaveTest]") // Load transposed. arma::mat dataset; data::DatasetInfo info; - data::Load("test.csv", dataset, info, true, true); + if (!data::Load("test.csv", dataset, info, false, true)) + FAIL("Cannot load dataset"); REQUIRE(dataset.n_rows == 5); REQUIRE(dataset.n_cols == 4); @@ -2017,7 +2032,8 @@ TEST_CASE("HarderKeonTest", "[LoadSaveTest]") // Now load non-transposed. data::DatasetInfo ntInfo; - data::Load("test.csv", dataset, ntInfo, true, false); + if (!data::Load("test.csv", dataset, ntInfo, false, false)) + FAIL("Cannot load dataset"); REQUIRE(dataset.n_rows == 4); REQUIRE(dataset.n_cols == 5); @@ -2052,7 +2068,8 @@ TEST_CASE("SimpleARFFTest", "[LoadSaveTest]") arma::mat dataset; DatasetInfo info; - data::Load("test.arff", dataset, info); + if (!data::Load("test.arff", dataset, info)) + FAIL("Cannot load dataset"); REQUIRE(info.Dimensionality() == 2); REQUIRE(info.Type(0) == Datatype::numeric); @@ -2093,7 +2110,8 @@ TEST_CASE("SimpleARFFCategoricalTest", "[LoadSaveTest]") arma::mat dataset; DatasetInfo info; - data::Load("test.arff", dataset, info); + if (!data::Load("test.arff", dataset, info)) + FAIL("Cannot load dataset"); REQUIRE(info.Dimensionality() == 3); @@ -2152,7 +2170,8 @@ TEST_CASE("HarderARFFTest", "[LoadSaveTest]") arma::mat dataset; DatasetInfo info; - data::Load("test.arff", dataset, info); + if (!data::Load("test.arff", dataset, info)) + FAIL("Cannot load dataset"); REQUIRE(info.Dimensionality() == 5); diff --git a/src/mlpack/tests/lrsdp_test.cpp b/src/mlpack/tests/lrsdp_test.cpp index f07b13ad7f..b2ac089997 100644 --- a/src/mlpack/tests/lrsdp_test.cpp +++ b/src/mlpack/tests/lrsdp_test.cpp @@ -95,7 +95,8 @@ BOOST_AUTO_TEST_CASE(Johnson844LovaszThetaSDP) { // Load the edges. arma::mat edges; - data::Load("johnson8-4-4.csv", edges, true); + if (!data::Load("johnson8-4-4.csv", edges)) + FAIL("Cannot load dataset johnson8-4-4.csv"); // The LRSDP itself and the initial point. arma::mat coordinates; @@ -150,7 +151,8 @@ BOOST_AUTO_TEST_CASE(ErdosRenyiRandomGraphMaxCutSDP) { // Load the edges. arma::mat edges; - data::Load("erdosrenyi-n100.csv", edges, true); + if (!data::Load("erdosrenyi-n100.csv", edges) + FAIL("Cannot load dataset erdosrenyi-n100.csv"); arma::sp_mat laplacian; CreateSparseGraphLaplacian(edges, laplacian); @@ -221,8 +223,10 @@ BOOST_AUTO_TEST_CASE(GaussianMatrixSensingSDP) arma::mat Xorig, A; // read the unknown matrix X and the measurement matrices A_i in - data::Load("sensing_X.csv", Xorig, true, false); - data::Load("sensing_A.csv", A, true, false); + if (!data::Load("sensing_X.csv", Xorig, false, false)) + FAIL("Cannot load dataset sensing_X.csv"); + if (!data::Load("sensing_A.csv", A, false, false)) + FAIL("Cannot load dataset sensing_A.csv"); const size_t m = Xorig.n_rows; const size_t n = Xorig.n_cols; diff --git a/src/mlpack/tests/lsh_test.cpp b/src/mlpack/tests/lsh_test.cpp index c9583d9853..7eca5fbcc5 100644 --- a/src/mlpack/tests/lsh_test.cpp +++ b/src/mlpack/tests/lsh_test.cpp @@ -115,8 +115,10 @@ TEST_CASE("NumTablesTest", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Run classic knn on reference data. KNN knn(rdata); @@ -187,8 +189,10 @@ TEST_CASE("HashWidthTest", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Run classic knn on reference data. KNN knn(rdata); @@ -247,8 +251,10 @@ TEST_CASE("NumProjTest", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Run classic knn on reference data. KNN knn(rdata); @@ -307,8 +313,10 @@ TEST_CASE("RecallTest", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Run classic knn on reference data. KNN knn(rdata); @@ -502,8 +510,10 @@ TEST_CASE("MultiprobeTest", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Add a slight amount of noise to the dataset, so that we don't end up with // points that have the same distance (hopefully). @@ -780,8 +790,10 @@ TEST_CASE("ParallelBichromatic", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Where to store neighbors and distances arma::Mat sequentialNeighbors; @@ -819,7 +831,8 @@ TEST_CASE("ParallelMonochromatic", "[LSHTest]") // Read iris training data as reference and query set. const string trainSet = "iris_train.csv"; arma::mat rdata; - data::Load(trainSet, rdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); // Where to store neighbors and distances arma::Mat sequentialNeighbors; @@ -936,8 +949,10 @@ TEST_CASE("SparseLSHTest", "[LSHTest]") const string testSet = "iris_test.csv"; arma::mat rdata; arma::mat qdata; - data::Load(trainSet, rdata, true); - data::Load(testSet, qdata, true); + if (!data::Load(trainSet, rdata)) + FAIL("Cannot load dataset"); + if (!data::Load(testSet, qdata)) + FAIL("Cannot load dataset"); // Run on dense data. LSHSearch<> denseLSH( diff --git a/src/mlpack/tests/matrix_completion_test.cpp b/src/mlpack/tests/matrix_completion_test.cpp index 104d169ef6..6fb3baff79 100644 --- a/src/mlpack/tests/matrix_completion_test.cpp +++ b/src/mlpack/tests/matrix_completion_test.cpp @@ -34,8 +34,10 @@ TEST_CASE("UniformMatrixCompletionSDP", "[MatrixCompletionTest]") arma::mat Xorig, values; arma::umat indices; - data::Load("completion_X.csv", Xorig, true, false); - data::Load("completion_indices.csv", indices, true, false); + if (!data::Load("completion_X.csv", Xorig, false, false)) + FAIL("Cannot load dataset completion_X.csv"); + if (!data::Load("completion_indices.csv", indices, false, false)) + FAIL("Cannot load dataset completion_indices.csv"); values.set_size(indices.n_cols); for (size_t i = 0; i < indices.n_cols; ++i) diff --git a/src/mlpack/tests/nbc_test.cpp b/src/mlpack/tests/nbc_test.cpp index ddc0487315..3b757d3b76 100644 --- a/src/mlpack/tests/nbc_test.cpp +++ b/src/mlpack/tests/nbc_test.cpp @@ -26,8 +26,10 @@ TEST_CASE("NaiveBayesClassifierTest", "[NBCTest]") size_t classes = 2; arma::mat trainData, trainRes, calcMat; - data::Load(trainFilename, trainData, true); - data::Load(trainResultFilename, trainRes, true); + if (!data::Load(trainFilename, trainData)) + FAIL("Cannot load dataset"); + if (!data::Load(trainResultFilename, trainRes)) + FAIL("Cannot load dataset"); // Get the labels out. arma::Row labels(trainData.n_cols); @@ -66,9 +68,12 @@ TEST_CASE("NaiveBayesClassifierTest", "[NBCTest]") arma::mat testResProbs; arma::Row calcVec; arma::mat calcProbs; - data::Load(testFilename, testData, true); - data::Load(testResultFilename, testRes, true); - data::Load(testResultProbsFilename, testResProbs, true); + if (!data::Load(testFilename, testData)) + FAIL("Cannot load dataset"); + if (!data::Load(testResultFilename, testRes)) + FAIL("Cannot load dataset"); + if (!data::Load(testResultProbsFilename, testResProbs)) + FAIL("Cannot load dataset"); testData.shed_row(testData.n_rows - 1); // Remove the labels. @@ -99,8 +104,10 @@ TEST_CASE("NaiveBayesClassifierIncrementalTest", "[NBCTest]") size_t classes = 2; arma::mat trainData, trainRes, calcMat; - data::Load(trainFilename, trainData, true); - data::Load(trainResultFilename, trainRes, true); + if (!data::Load(trainFilename, trainData)) + FAIL("Cannot load dataset"); + if (!data::Load(trainResultFilename, trainRes)) + FAIL("Cannot load dataset"); // Get the labels out. arma::Row labels(trainData.n_cols); @@ -139,9 +146,12 @@ TEST_CASE("NaiveBayesClassifierIncrementalTest", "[NBCTest]") arma::mat testResProba; arma::Row calcVec; arma::mat calcProbs; - data::Load(testFilename, testData, true); - data::Load(testResultFilename, testRes, true); - data::Load(testResultProbsFilename, testResProba, true); + if (!data::Load(testFilename, testData)) + FAIL("Cannot load dataset"); + if (!data::Load(testResultFilename, testRes)) + FAIL("Cannot load dataset"); + if (!data::Load(testResultProbsFilename, testResProba)) + FAIL("Cannot load dataset"); testData.shed_row(testData.n_rows - 1); // Remove the labels. @@ -170,8 +180,10 @@ TEST_CASE("SeparateTrainTest", "[NBCTest]") size_t classes = 2; arma::mat trainData, trainRes, calcMat; - data::Load(trainFilename, trainData, true); - data::Load(trainResultFilename, trainRes, true); + if (!data::Load(trainFilename, trainData)) + FAIL("Cannot load dataset"); + if (!data::Load(trainResultFilename, trainRes)) + FAIL("Cannot load dataset"); // Get the labels out. arma::Row labels(trainData.n_cols); @@ -228,8 +240,10 @@ TEST_CASE("SeparateTrainIncrementalTest", "[NBCTest]") size_t classes = 2; arma::mat trainData, trainRes, calcMat; - data::Load(trainFilename, trainData, true); - data::Load(trainResultFilename, trainRes, true); + if (!data::Load(trainFilename, trainData)) + FAIL("Cannot load dataset"); + if (!data::Load(trainResultFilename, trainRes)) + FAIL("Cannot load dataset"); // Get the labels out. arma::Row labels(trainData.n_cols); @@ -286,8 +300,10 @@ TEST_CASE("SeparateTrainIndividualIncrementalTest", "[NBCTest]") size_t classes = 2; arma::mat trainData, trainRes, calcMat; - data::Load(trainFilename, trainData, true); - data::Load(trainResultFilename, trainRes, true); + if (!data::Load(trainFilename, trainData)) + FAIL("Cannot load dataset"); + if (!data::Load(trainResultFilename, trainRes)) + FAIL("Cannot load dataset"); // Get the labels out. arma::Row labels(trainData.n_cols); @@ -356,8 +372,10 @@ TEST_CASE("NaiveBayesClassifierHighDimensionsTest", "[NBCTest]") // Create variables for training and assign data to them. arma::mat trainData; arma::Row trainLabels; - data::Load(trainFilename, trainData, true); - data::Load(trainLabelsFileName, trainLabels, true); + if (!data::Load(trainFilename, trainData)) + FAIL("Cannot load dataset"); + if (!data::Load(trainLabelsFileName, trainLabels)) + FAIL("Cannot load dataset"); // Initialize and train a NBC model. NaiveBayesClassifier<> nbcTest(trainData, trainLabels, classes); @@ -366,8 +384,10 @@ TEST_CASE("NaiveBayesClassifierHighDimensionsTest", "[NBCTest]") arma::mat testData, calcProbs; arma::Row testLabels; arma::Row calcVec; - data::Load(testFilename, testData, true); - data::Load(testLabelsFilename, testLabels, true); + if (!data::Load(testFilename, testData)) + FAIL("Cannot load dataset"); + if (!data::Load(testLabelsFilename, testLabels)) + FAIL("Cannot load dataset"); // Classify observations in the test dataset. To use Classify() method with // a parameter for probabilities of predictions, we pass 'calcProbs' to the diff --git a/src/mlpack/tests/nystroem_method_test.cpp b/src/mlpack/tests/nystroem_method_test.cpp index 1c99a7b7e6..32bf189d49 100644 --- a/src/mlpack/tests/nystroem_method_test.cpp +++ b/src/mlpack/tests/nystroem_method_test.cpp @@ -146,7 +146,8 @@ TEST_CASE("GermanTest", "[NystroemMethodTest]") { // Load the dataset. arma::mat dataset; - data::Load("german.csv", dataset, true); + if (!data::Load("german.csv", dataset)) + FAIL("Cannot load dataset german.csv"); // These are our tolerance bounds. double results[5] = { 32.0, 20.0, 15.0, 12.0, 9.0 }; diff --git a/src/mlpack/tests/one_hot_encoding_test.cpp b/src/mlpack/tests/one_hot_encoding_test.cpp index a3b19363f6..1844539f0f 100644 --- a/src/mlpack/tests/one_hot_encoding_test.cpp +++ b/src/mlpack/tests/one_hot_encoding_test.cpp @@ -191,7 +191,8 @@ TEST_CASE("OneHotEncodingDatasetinfoTest", "[OneHotEncodingTest]") // Load the test CSV. arma::umat matrix; DatasetInfo info; - data::Load("test.csv", matrix, info); + if (!data::Load("test.csv", matrix, info)) + FAIL("Cannot load dataset test.csv"); arma::umat output; data::OneHotEncoding(matrix, output, info); REQUIRE(output.n_cols == 7); diff --git a/src/mlpack/tests/pca_test.cpp b/src/mlpack/tests/pca_test.cpp index 6ccefbbaeb..1d4a1657ed 100644 --- a/src/mlpack/tests/pca_test.cpp +++ b/src/mlpack/tests/pca_test.cpp @@ -240,7 +240,8 @@ TEST_CASE("RandomizedPCADimensionalityReductionTest", "[PCATest]") TEST_CASE("QUICPCADimensionalityReductionTest", "[PCATest]") { arma::mat data, data1; - data::Load("test_data_3_1000.csv", data); + if (!data::Load("test_data_3_1000.csv", data)) + FAIL("Cannot load dataset test_data_3_1000.csv"); data1 = data; arma::mat backupData(data); diff --git a/src/mlpack/tests/quic_svd_test.cpp b/src/mlpack/tests/quic_svd_test.cpp index 9ae2e33a79..16cbfa98af 100644 --- a/src/mlpack/tests/quic_svd_test.cpp +++ b/src/mlpack/tests/quic_svd_test.cpp @@ -24,7 +24,8 @@ TEST_CASE("QUICSVDReconstructionError", "[QUICSVDTest]") { // Load the dataset. arma::mat dataset; - data::Load("test_data_3_1000.csv", dataset); + if (!data::Load("test_data_3_1000.csv", dataset)) + FAIL("Cannot load dataset test_data_3_1000.csv"); // The QUIC-SVD procedure can fail---the Monte Carlo error calculation is // random. Therefore we simply require at least one success. diff --git a/src/mlpack/tests/radical_test.cpp b/src/mlpack/tests/radical_test.cpp index feb687ee52..39b77a11f7 100644 --- a/src/mlpack/tests/radical_test.cpp +++ b/src/mlpack/tests/radical_test.cpp @@ -21,7 +21,8 @@ using namespace arma; TEST_CASE("Radical_Test_Radical3D", "[RadicalTest]") { mat matX; - data::Load("data_3d_mixed.txt", matX); + if (!data::Load("data_3d_mixed.txt", matX)) + FAIL("Cannot load dataset data_3d_mixed.txt"); Radical rad(0.175, 5, 100, matX.n_rows - 1); @@ -39,7 +40,8 @@ TEST_CASE("Radical_Test_Radical3D", "[RadicalTest]") } mat matS; - data::Load("data_3d_ind.txt", matS); + if (!data::Load("data_3d_ind.txt", matS)) + FAIL("Cannot load dataset data_3d_ind.txt"); rad.DoRadical(matS, matY, matW); matYT = trans(matY); diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index b916ac446f..20397641e0 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -122,9 +122,11 @@ TEST_CASE("UnweightedNumericLearningTest", "[RandomForestTest]") { // Load the vc2 dataset. arma::mat dataset; - data::Load("vc2.csv", dataset); + if (!data::Load("vc2.csv", dataset)) + FAIL("Cannot load dataset vc2.csv"); arma::Row labels; - data::Load("vc2_labels.txt", labels); + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load dataset vc2.csv"); // Build a random forest and a decision tree. RandomForest<> rf(dataset, labels, 3, 20 /* 20 trees */, 1, 1e-7); @@ -132,9 +134,11 @@ TEST_CASE("UnweightedNumericLearningTest", "[RandomForestTest]") // Get performance statistics on test data. arma::mat testDataset; - data::Load("vc2_test.csv", testDataset); + if (!data::Load("vc2_test.csv", testDataset)) + FAIL("Cannot load dataset vc2_test.csv"); arma::Row testLabels; - data::Load("vc2_test_labels.txt", testLabels); + if (!data::Load("vc2_test_labels.txt", testLabels)) + FAIL("Cannot load dataset vc2_test_labels.txt"); arma::Row rfPredictions; arma::Row dtPredictions; @@ -158,8 +162,10 @@ TEST_CASE("WeightedNumericLearningTest", "[RandomForestTest]") { arma::mat dataset; arma::Row labels; - data::Load("vc2.csv", dataset); - data::Load("vc2_labels.txt", labels); + if (!data::Load("vc2.csv", dataset)) + FAIL("Cannot load dataset vc2.csv"); + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load dataset vc2_labels.txt"); // Add some noise. arma::mat noise(dataset.n_rows, 1000, arma::fill::randu); @@ -184,9 +190,11 @@ TEST_CASE("WeightedNumericLearningTest", "[RandomForestTest]") // Get performance statistics on test data. arma::mat testDataset; - data::Load("vc2_test.csv", testDataset); + if (!data::Load("vc2_test.csv", testDataset)) + FAIL("Cannot load dataset vc2_test.csv"); arma::Row testLabels; - data::Load("vc2_test_labels.txt", testLabels); + if (!data::Load("vc2_test_labels.txt", testLabels)) + FAIL("Cannot load dataset vc2_test_labels.txt"); arma::Row rfPredictions; arma::Row dtPredictions; @@ -304,9 +312,11 @@ TEST_CASE("LeafSizeDatasetTest", "[RandomForestTest]") { // Load the vc2 dataset. arma::mat dataset; - data::Load("vc2.csv", dataset); + if (!data::Load("vc2.csv", dataset)) + FAIL("Cannot load dataset vc2.csv"); arma::Row labels; - data::Load("vc2_labels.txt", labels); + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load dataset vc2.csv"); // Build a random forest with a leaf size equal to the number of points in the // dataset. @@ -338,9 +348,11 @@ TEST_CASE("RandomForestSerializationTest", "[RandomForestTest]") { // Load the vc2 dataset. arma::mat dataset; - data::Load("vc2.csv", dataset); + if (!data::Load("vc2.csv", dataset)) + FAIL("Cannot load dataset vc2.csv"); arma::Row labels; - data::Load("vc2_labels.txt", labels); + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load dataset vc2.csv"); RandomForest<> rf(dataset, labels, 3, 10 /* 10 trees */, 1); @@ -374,8 +386,10 @@ TEST_CASE("RandomForestNumericTrainReturnEntropy", "[RandomForestTest]") { arma::mat dataset; arma::Row labels; - data::Load("vc2.csv", dataset); - data::Load("vc2_labels.txt", labels); + if (!data::Load("vc2.csv", dataset)) + FAIL("Cannot load dataset vc2.csv"); + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load dataset vc2_labels.txt"); // Add some noise. arma::mat noise(dataset.n_rows, 1000, arma::fill::randu); diff --git a/src/mlpack/tests/svd_incremental_test.cpp b/src/mlpack/tests/svd_incremental_test.cpp index 433a86755f..56a55459d7 100644 --- a/src/mlpack/tests/svd_incremental_test.cpp +++ b/src/mlpack/tests/svd_incremental_test.cpp @@ -98,7 +98,8 @@ class SpecificRandomInitialization TEST_CASE("SVDIncompleteIncrementalRegularizationTest", "[SVDIncrementalTest]") { mat dataset; - data::Load("GroupLensSmall.csv", dataset); + if (!data::Load("GroupLensSmall.csv", dataset)) + FAIL("Cannot load dataset GroupLensSmall.csv"); // Generate list of locations for batch insert constructor for sparse // matrices. diff --git a/src/mlpack/tests/svdplusplus_test.cpp b/src/mlpack/tests/svdplusplus_test.cpp index dbf1417397..4ca13e55ad 100644 --- a/src/mlpack/tests/svdplusplus_test.cpp +++ b/src/mlpack/tests/svdplusplus_test.cpp @@ -255,7 +255,8 @@ TEST_CASE("SVDplusPlusOutputSizeTest", "[SVDPlusPlusTest]") { // Load small GroupLens dataset. arma::mat data; - data::Load("GroupLensSmall.csv", data); + if (!data::Load("GroupLensSmall.csv", data)) + FAIL("Cannot load dataset GroupLensSmall.csv"); // Define useful constants. const size_t numUsers = max(data.row(0)) + 1; @@ -288,7 +289,8 @@ TEST_CASE("SVDPlusPlusCleanDataTest", "[SVDPlusPlusTest]") { // Load small GroupLens dataset. arma::mat data; - data::Load("GroupLensSmall.csv", data); + if (!data::Load("GroupLensSmall.csv", data)) + FAIL("Cannot load dataset GroupLensSmall.csv"); // Define useful constants. const size_t numUsers = max(data.row(0)) + 1; From 1b79ef0678a5ed7acdd27eb9cebb5d5fdf1593b6 Mon Sep 17 00:00:00 2001 From: Gopi M Tatiraju Date: Tue, 23 Feb 2021 00:08:27 +0530 Subject: [PATCH 022/729] Update load_save_test.cpp --- src/mlpack/tests/load_save_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/load_save_test.cpp b/src/mlpack/tests/load_save_test.cpp index bf7066c04f..015ece667f 100644 --- a/src/mlpack/tests/load_save_test.cpp +++ b/src/mlpack/tests/load_save_test.cpp @@ -1415,7 +1415,7 @@ TEST_CASE("RegularCSVDatasetInfoLoad", "[LoadSaveTest]") arma::mat one, two; DatasetInfo info; if (!data::Load(testFiles[i], one)) - FAIL("Cannot load dataset"); + FAIL("Cannot load dataset") if (!data::Load(testFiles[i], two, info); FAIL("Cannot load dataset"); From a71a968f17aad63984c2050bca7826d0364b2de4 Mon Sep 17 00:00:00 2001 From: Gopi M Tatiraju Date: Tue, 23 Feb 2021 00:09:24 +0530 Subject: [PATCH 023/729] Update load_save_test.cpp --- src/mlpack/tests/load_save_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/load_save_test.cpp b/src/mlpack/tests/load_save_test.cpp index 015ece667f..d4c5f6f58a 100644 --- a/src/mlpack/tests/load_save_test.cpp +++ b/src/mlpack/tests/load_save_test.cpp @@ -1415,8 +1415,8 @@ TEST_CASE("RegularCSVDatasetInfoLoad", "[LoadSaveTest]") arma::mat one, two; DatasetInfo info; if (!data::Load(testFiles[i], one)) - FAIL("Cannot load dataset") - if (!data::Load(testFiles[i], two, info); + FAIL("Cannot load dataset"); + if (!data::Load(testFiles[i], two, info) FAIL("Cannot load dataset"); // Check that the matrices contain the same information. From 656c29ba6d31ca237199d48f9f6a046123bf9e11 Mon Sep 17 00:00:00 2001 From: Gopi M Tatiraju Date: Tue, 23 Feb 2021 01:35:31 +0530 Subject: [PATCH 024/729] Update load_save_test.cpp --- src/mlpack/tests/load_save_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/load_save_test.cpp b/src/mlpack/tests/load_save_test.cpp index d4c5f6f58a..602533a84b 100644 --- a/src/mlpack/tests/load_save_test.cpp +++ b/src/mlpack/tests/load_save_test.cpp @@ -1416,7 +1416,7 @@ TEST_CASE("RegularCSVDatasetInfoLoad", "[LoadSaveTest]") DatasetInfo info; if (!data::Load(testFiles[i], one)) FAIL("Cannot load dataset"); - if (!data::Load(testFiles[i], two, info) + if (!data::Load(testFiles[i], two, info)) FAIL("Cannot load dataset"); // Check that the matrices contain the same information. From 34ca85cad3cbf3dd60397b632f6cbc2368a79839 Mon Sep 17 00:00:00 2001 From: Gopi M Tatiraju Date: Tue, 23 Feb 2021 16:00:09 +0530 Subject: [PATCH 025/729] Apply suggestions from code review Co-authored-by: Anush Kini <33577829+Abilityguy@users.noreply.github.com> --- src/mlpack/tests/feedforward_network_test.cpp | 21 +++++++++---------- src/mlpack/tests/krann_search_test.cpp | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/mlpack/tests/feedforward_network_test.cpp b/src/mlpack/tests/feedforward_network_test.cpp index c7386261bf..629df89749 100644 --- a/src/mlpack/tests/feedforward_network_test.cpp +++ b/src/mlpack/tests/feedforward_network_test.cpp @@ -161,7 +161,7 @@ TEST_CASE("FFVanillaNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) + if (!data::Load("thyroid_train.csv", trainData)) FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); @@ -310,7 +310,7 @@ TEST_CASE("DropoutNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) + if (!data::Load("thyroid_train.csv", trainData)) FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); @@ -413,7 +413,7 @@ TEST_CASE("DropConnectNetworkTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) + if (!data::Load("thyroid_train.csv", trainData)) FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); @@ -504,8 +504,8 @@ TEST_CASE("FFSerializationTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) - FAIL("Cannot open thyroid_train.csv"); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -555,8 +555,8 @@ TEST_CASE("CustomLayerTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) - FAIL("Cannot open thyroid_train.csv"); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -636,8 +636,8 @@ TEST_CASE("FFNTrainReturnObjective", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) - FAIL("Cannot open thyroid_train.csv"); + if (!data::Load("thyroid_train.csv", trainData)) + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -708,7 +708,7 @@ TEST_CASE("OptimizerTest", "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; - if (!data::Load("thyroid_train.csv", trainData)) + if (!data::Load("thyroid_train.csv", trainData)) FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); @@ -730,4 +730,3 @@ TEST_CASE("OptimizerTest", "[FeedForwardNetworkTest]") ens::DE opt(200, 1000, 0.6, 0.8, 1e-5); model.Train(trainData, trainLabels, opt); } - diff --git a/src/mlpack/tests/krann_search_test.cpp b/src/mlpack/tests/krann_search_test.cpp index 5bc13eb952..29aa5335ff 100644 --- a/src/mlpack/tests/krann_search_test.cpp +++ b/src/mlpack/tests/krann_search_test.cpp @@ -43,7 +43,7 @@ TEST_CASE("NaiveGuaranteeTest", "[KRANNTest]") RASearch<> rsRann(refData, true, false, 1.0); arma::mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; From 20b3754def07c7545501797da450e008dceb9d75 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Thu, 25 Feb 2021 13:51:20 +0530 Subject: [PATCH 026/729] Set flag using configure file. --- src/mlpack/bindings/R/CMakeLists.txt | 10 +- src/mlpack/bindings/R/mlpack/cleanup | 3 + src/mlpack/bindings/R/mlpack/configure.ac.in | 20 + src/mlpack/bindings/R/mlpack/configure.in | 2848 +++++++++++++++++ .../R/mlpack/src/{Makevars => Makevars.in} | 2 +- 5 files changed, 2881 insertions(+), 2 deletions(-) create mode 100644 src/mlpack/bindings/R/mlpack/configure.ac.in create mode 100755 src/mlpack/bindings/R/mlpack/configure.in rename src/mlpack/bindings/R/mlpack/src/{Makevars => Makevars.in} (76%) diff --git a/src/mlpack/bindings/R/CMakeLists.txt b/src/mlpack/bindings/R/CMakeLists.txt index a6e8ee16e1..34567a6acd 100644 --- a/src/mlpack/bindings/R/CMakeLists.txt +++ b/src/mlpack/bindings/R/CMakeLists.txt @@ -91,6 +91,14 @@ if (BUILD_R_BINDINGS) ${CMAKE_CURRENT_BINARY_DIR}/mlpack/DESCRIPTION @ONLY) + configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/configure.in + ${CMAKE_CURRENT_BINARY_DIR}/mlpack/configure + @ONLY) + + configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/configure.ac.in + ${CMAKE_CURRENT_BINARY_DIR}/mlpack/configure.ac + @ONLY) + # Create the empty NAMESPACE file that will include all export functions. file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/mlpack/NAMESPACE" @@ -100,7 +108,7 @@ if (BUILD_R_BINDINGS) set(CPP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/r_util.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/rcpp_mlpack.h" - "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars" + "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars.in" "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars.win" ) diff --git a/src/mlpack/bindings/R/mlpack/cleanup b/src/mlpack/bindings/R/mlpack/cleanup index 5347fead4a..38a04312ad 100755 --- a/src/mlpack/bindings/R/mlpack/cleanup +++ b/src/mlpack/bindings/R/mlpack/cleanup @@ -1,2 +1,5 @@ ## compilation and editing objects rm -f src/*.o src/*.so src/*.dylib src/*~ *~ + +## autoconf/configure leftovers +rm -rf autom4te.cache/ config.log config.status src/Makevars diff --git a/src/mlpack/bindings/R/mlpack/configure.ac.in b/src/mlpack/bindings/R/mlpack/configure.ac.in new file mode 100644 index 0000000000..58769fca5a --- /dev/null +++ b/src/mlpack/bindings/R/mlpack/configure.ac.in @@ -0,0 +1,20 @@ +## mlpack configure.ac +AC_PREREQ(2.61) + +## Process this file with autoconf to produce a configure script. +AC_INIT([mlpack], [@PACKAGE_VERSION@]) + +## Set R_HOME, respecting an environment variable if one is set +: ${R_HOME=$(R RHOME)} +if test -z "${R_HOME}"; then + AC_MSG_ERROR([Could not determine R_HOME.]) +fi + +## Check for Solaris. +RSysinfoName=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(Sys.info()[["sysname"]])') +if test x"${RSysinfoName}" = x"SunOS"; then + extra_flag="-ftrack-macro-expansion=0" +fi + +AC_SUBST([EXTRA_FLAG], ["${extra_flag}"]) +AC_OUTPUT(src/Makevars) diff --git a/src/mlpack/bindings/R/mlpack/configure.in b/src/mlpack/bindings/R/mlpack/configure.in new file mode 100755 index 0000000000..1305c150be --- /dev/null +++ b/src/mlpack/bindings/R/mlpack/configure.in @@ -0,0 +1,2848 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for mlpack @PACKAGE_VERSION@. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='mlpack' +PACKAGE_TARNAME='mlpack' +PACKAGE_VERSION='@PACKAGE_VERSION@' +PACKAGE_STRING='mlpack @PACKAGE_VERSION@' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_subst_vars='LTLIBOBJS +LIBOBJS +EXTRA_FLAG +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +' + ac_precious_vars='build_alias +host_alias +target_alias' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures mlpack @PACKAGE_VERSION@ to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/mlpack] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of mlpack @PACKAGE_VERSION@:";; + esac + cat <<\_ACEOF + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +mlpack configure @PACKAGE_VERSION@ +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by mlpack $as_me @PACKAGE_VERSION@, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +## Set R_HOME, respecting an environment variable if one is set +: ${R_HOME=$(R RHOME)} +if test -z "${R_HOME}"; then + as_fn_error $? "Could not determine R_HOME." "$LINENO" 5 +fi + +## Check for Solaris. +RSysinfoName=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(Sys.info()["sysname"])') +if test x"${RSysinfoName}" = x"SunOS"; then + extra_flag="-ftrack-macro-expansion=0" +fi + +EXTRA_FLAG="${extra_flag}" + +ac_config_files="$ac_config_files src/Makevars" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by mlpack $as_me @PACKAGE_VERSION@, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +mlpack config.status @PACKAGE_VERSION@ +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/src/mlpack/bindings/R/mlpack/src/Makevars b/src/mlpack/bindings/R/mlpack/src/Makevars.in similarity index 76% rename from src/mlpack/bindings/R/mlpack/src/Makevars rename to src/mlpack/bindings/R/mlpack/src/Makevars.in index 4cca03b1a5..c25a33701c 100644 --- a/src/mlpack/bindings/R/mlpack/src/Makevars +++ b/src/mlpack/bindings/R/mlpack/src/Makevars.in @@ -1,3 +1,3 @@ -PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 +PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) @EXTRA_FLAG@ PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) CXX_STD = CXX11 From 0abbbc2325c067b9f0ab71600cf825b425f797b5 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Thu, 25 Feb 2021 16:29:56 +0530 Subject: [PATCH 027/729] Correct configure file. --- src/mlpack/bindings/R/CMakeLists.txt | 18 +++++----- .../R/mlpack/{configure.in => configure} | 36 ++++++++++--------- .../mlpack/{configure.ac.in => configure.ac} | 9 +++-- 3 files changed, 36 insertions(+), 27 deletions(-) rename src/mlpack/bindings/R/mlpack/{configure.in => configure} (99%) rename src/mlpack/bindings/R/mlpack/{configure.ac.in => configure.ac} (82%) diff --git a/src/mlpack/bindings/R/CMakeLists.txt b/src/mlpack/bindings/R/CMakeLists.txt index 34567a6acd..f2f6d459ef 100644 --- a/src/mlpack/bindings/R/CMakeLists.txt +++ b/src/mlpack/bindings/R/CMakeLists.txt @@ -91,14 +91,6 @@ if (BUILD_R_BINDINGS) ${CMAKE_CURRENT_BINARY_DIR}/mlpack/DESCRIPTION @ONLY) - configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/configure.in - ${CMAKE_CURRENT_BINARY_DIR}/mlpack/configure - @ONLY) - - configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/configure.ac.in - ${CMAKE_CURRENT_BINARY_DIR}/mlpack/configure.ac - @ONLY) - # Create the empty NAMESPACE file that will include all export functions. file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/mlpack/NAMESPACE" @@ -211,6 +203,16 @@ if (BUILD_R_BINDINGS) DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/mlpack/") + file(COPY + "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/configure" + DESTINATION + "${CMAKE_CURRENT_BINARY_DIR}/mlpack/") + + file(COPY + "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/configure.ac" + DESTINATION + "${CMAKE_CURRENT_BINARY_DIR}/mlpack/") + # Do the actual build. add_custom_target(r_build ALL) diff --git a/src/mlpack/bindings/R/mlpack/configure.in b/src/mlpack/bindings/R/mlpack/configure similarity index 99% rename from src/mlpack/bindings/R/mlpack/configure.in rename to src/mlpack/bindings/R/mlpack/configure index 1305c150be..53f7df8624 100755 --- a/src/mlpack/bindings/R/mlpack/configure.in +++ b/src/mlpack/bindings/R/mlpack/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for mlpack @PACKAGE_VERSION@. +# Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -574,12 +574,12 @@ MFLAGS= MAKEFLAGS= # Identity of this package. -PACKAGE_NAME='mlpack' -PACKAGE_TARNAME='mlpack' -PACKAGE_VERSION='@PACKAGE_VERSION@' -PACKAGE_STRING='mlpack @PACKAGE_VERSION@' -PACKAGE_BUGREPORT='' -PACKAGE_URL='' +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= ac_subst_vars='LTLIBOBJS LIBOBJS @@ -671,7 +671,7 @@ localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' @@ -1180,7 +1180,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures mlpack @PACKAGE_VERSION@ to adapt to many kinds of systems. +\`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1229,7 +1229,7 @@ Fine tuning of the installation directories: --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/mlpack] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] @@ -1241,9 +1241,7 @@ _ACEOF fi if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of mlpack @PACKAGE_VERSION@:";; - esac + cat <<\_ACEOF Report bugs to the package provider. @@ -1309,7 +1307,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -mlpack configure @PACKAGE_VERSION@ +configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1326,7 +1324,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by mlpack $as_me @PACKAGE_VERSION@, which was +It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -1683,6 +1681,10 @@ fi ## Check for Solaris. RSysinfoName=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(Sys.info()["sysname"])') + +## Default the flag to the empty string. +extra_flag="" + if test x"${RSysinfoName}" = x"SunOS"; then extra_flag="-ftrack-macro-expansion=0" fi @@ -2233,7 +2235,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mlpack $as_me @PACKAGE_VERSION@, which was +This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -2286,7 +2288,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mlpack config.status @PACKAGE_VERSION@ +config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/src/mlpack/bindings/R/mlpack/configure.ac.in b/src/mlpack/bindings/R/mlpack/configure.ac similarity index 82% rename from src/mlpack/bindings/R/mlpack/configure.ac.in rename to src/mlpack/bindings/R/mlpack/configure.ac index 58769fca5a..74701f3a46 100644 --- a/src/mlpack/bindings/R/mlpack/configure.ac.in +++ b/src/mlpack/bindings/R/mlpack/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ(2.61) ## Process this file with autoconf to produce a configure script. -AC_INIT([mlpack], [@PACKAGE_VERSION@]) +AC_INIT() ## Set R_HOME, respecting an environment variable if one is set : ${R_HOME=$(R RHOME)} @@ -12,9 +12,14 @@ fi ## Check for Solaris. RSysinfoName=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(Sys.info()[["sysname"]])') + +## Default the flag to the empty string. +extra_flag="" + if test x"${RSysinfoName}" = x"SunOS"; then extra_flag="-ftrack-macro-expansion=0" fi AC_SUBST([EXTRA_FLAG], ["${extra_flag}"]) -AC_OUTPUT(src/Makevars) +AC_CONFIG_FILES([src/Makevars]) +AC_OUTPUT From 73bb3515ce29fb165606431f6d55a9f2aacea4ee Mon Sep 17 00:00:00 2001 From: Anush Kini <33577829+Abilityguy@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:53:17 +0530 Subject: [PATCH 028/729] Some review changes implemented. Changes implemented for the following reviews in 2746: 1. Using ```cols``` and ```subvec``` to avoid the for loop. 2. Changed instances of ```arma::row``` to ```arma::Row```. 3. Logic added where ```order``` is initialised only when ```shuffleData``` is true. 4. input fields made ```const```. 5. Removed extra new line where the line was less than 80 characters long. 6. Spacing fix (Refer line 566 in changed file). --- src/mlpack/core/data/split_data.hpp | 151 +++++++++++++++++----------- 1 file changed, 93 insertions(+), 58 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index f4a75d871b..370128dfc6 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -143,7 +143,7 @@ void StratifiedSplit(const arma::Mat& input, * @endcode * * @tparam T Type of the elements of the input matrix. - * @tparam LabelsType Type of input labels. It can be arma::Mat, arma::row, + * @tparam LabelsType Type of input labels. It can be arma::Mat, arma::Row, * arma::Cube or arma::SpMat. * @param input Input dataset to split. * @param inputLabel Input labels to split. @@ -170,28 +170,39 @@ void Split(const arma::Mat& input, const size_t trainSize = input.n_cols - testSize; trainData.set_size(input.n_rows, trainSize); testData.set_size(input.n_rows, testSize); + trainLabel.set_size(1, trainSize); + testLabel.set_size(1, testSize); - arma::uvec order = arma::linspace(0, input.n_cols - 1, - input.n_cols); if (shuffleData) - order = arma::shuffle(order); - - if (trainSize > 0) { - trainLabel.set_size(1, trainSize); - trainData = input.cols(order.subvec(0, trainSize - 1)); + arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, + input.n_cols)); - for (size_t i = 0; i < trainSize; ++i) - trainLabel(0, i) = inputLabel(0, order(i)); + if (trainSize > 0) + { + trainData = input.cols(order.subvec(0, trainSize - 1)); + trainLabel = inputLabel.cols(order.subvec(0, trainSize - 1)); + } + + if (trainSize < input.n_cols) + { + testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); + testLabel = inputLabel.cols(order.subvec(trainSize, input.n_cols - 1)); + } } - - if (trainSize < input.n_cols) + else { - testLabel.set_size(1, testSize); - testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); + if (trainSize > 0) + { + trainData = input.cols(0, trainSize - 1); + trainLabel = inputLabel.cols(0, trainSize - 1); + } - for (size_t i = trainSize; i < input.n_cols; ++i) - testLabel(0, i - trainSize) = inputLabel(0, order(i)); + if (trainSize < input.n_cols) + { + testData = input.cols(trainSize, input.n_cols - 1); + testLabel = inputLabel.cols(trainSize, inputLabel.n_cols - 1); + } } } @@ -265,7 +276,7 @@ void Split(const arma::Mat& input, * @endcode * * @tparam T Type of the elements of the input matrix. - * @tparam LabelsType Type of input labels. It can be arma::Mat, arma::row, + * @tparam LabelsType Type of input labels. It can be arma::Mat, arma::Row, * arma::Cube or arma::SpMat. * @param input Input dataset to split. * @param inputLabel Input labels to split. @@ -362,8 +373,7 @@ Split(const arma::Mat& input, * * // Split the dataset into a training and test set, with 30% of the data being * // held out for the test set. - * Split(input, label, trainData, - * testData, trainLabel, testLabel, 0.3); + * Split(input, label, trainData, testData, trainLabel, testLabel, 0.3); * @endcode * * @param input Input dataset to split. @@ -380,46 +390,56 @@ template ::value || arma::is_Mat_only::value>> -void Split(FieldType& input, - arma::field& inputLabel, +void Split(const FieldType& input, + const arma::field& inputLabel, FieldType& trainData, - arma::field& trainLabels, + arma::field& trainLabel, FieldType& testData, - arma::field& testLabels, + arma::field& testLabel, const double testRatio, const bool shuffleData = true) { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; - - trainData.set_size(1, trainSize); - testData.set_size(1, testSize); - - arma::uvec order = arma::linspace(0, input.n_cols - 1, - input.n_cols); + trainLabel.set_size(1, trainSize); + testLabel.set_size(1, testSize); if (shuffleData) - order = arma::shuffle(order); - - if (trainSize > 0) { - trainLabels.set_size(1, trainSize); + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); - for (size_t i = 0; i < trainSize; ++i) - trainData[i] = input(0, order(i)); + if (trainSize > 0) + { + trainData = input.cols(order.subvec(0, trainSize - 1)); - for (size_t i = 0; i < trainSize; ++i) - trainLabels(0, i) = inputLabel(0, order(i)); + for (size_t i = 0; i < trainSize; ++i) + trainLabel(0, i) = inputLabel(0, order(i)); + } + + if (trainSize < input.n_cols) + { + testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); + + for (size_t i = trainSize; i < input.n_cols; ++i) + testLabel(0, i - trainSize) = inputLabel(0, order(i)); + } } - - if (testSize <= input.n_cols) + else { - for (size_t i = trainSize; i < input.n_cols - 1; ++i) - testData[i - trainSize] = input(0, order(i)); + if (trainSize > 0) + { + trainData = input.cols(0, trainSize - 1); + for (size_t i = 0; i < trainSize; ++i) + trainLabel(0, i) = inputLabel(0, i); + } - testLabels.set_size(1, testSize); - for (size_t i = trainSize; i < input.n_cols; ++i) - testLabels(0, i - trainSize) = inputLabel(0, order(i)); + if (trainSize < input.n_cols) + { + testData = input.cols(trainSize, input.n_cols - 1); + for (size_t i = trainSize; i < input.n_cols; ++i) + testLabel(0, i - trainSize) = inputLabel(0, i); + } } } @@ -467,21 +487,36 @@ void Split(const FieldType& input, trainData.set_size(1, trainSize); testData.set_size(1, testSize); - arma::uvec order = arma::linspace(0, input.n_cols - 1, - input.n_cols); if (shuffleData) - order = arma::shuffle(order); - - if (trainSize > 0) { - for (size_t i = 0; i < trainSize; i++) - trainData[i] = input(0, order(i)); + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + + if (trainSize > 0) + { + for (size_t i = 0; i < trainSize; i++) + trainData[i] = input(0, order(i)); + } + + if (trainSize < input.n_cols) + { + for (size_t i = trainSize; i < input.n_cols - 1; ++i) + testData[i - trainSize] = input(0, order(i)); + } } - - if (testSize <= input.n_cols) + else { - for (size_t i = trainSize; i < input.n_cols - 1; ++i) - testData[i - trainSize] = input(0, order(i)); + if (trainSize > 0) + { + for (size_t i = 0; i < trainSize; i++) + trainData[i] = input(0, i); + } + + if (trainSize < input.n_cols) + { + for (size_t i = trainSize; i < input.n_cols - 1; ++i) + testData[i - trainSize] = input(0, i); + } } } @@ -517,8 +552,8 @@ template ::value || arma::is_Mat_only::value>> std::tuple -Split(FieldType& input, - arma::field& inputLabel, +Split(const FieldType& input, + const arma::field& inputLabel, const double testRatio, const bool shuffleData = true) { @@ -528,7 +563,7 @@ Split(FieldType& input, arma::field testLabel; Split(input, inputLabel, trainData, testData, trainLabel, testLabel, - testRatio, shuffleData); + testRatio, shuffleData); return std::make_tuple(std::move(trainData), std::move(testData), From e837763302237357b0b0fc2eadfb1ce9dfc6a4ff Mon Sep 17 00:00:00 2001 From: Anush Kini <33577829+Abilityguy@users.noreply.github.com> Date: Fri, 26 Feb 2021 17:02:22 +0530 Subject: [PATCH 029/729] Review changes made to test suite 1. Restored blank lines that were removed in a previous commit. 2. Edited test ```SplitMatrixLabeledDataResultMat``` to ```SplitMatrixLabeledData``` and made changes to fix this failing test. --- src/mlpack/tests/split_data_test.cpp | 97 ++++++++++++++++------------ 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 74862469ba..1419756e5b 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -121,29 +121,6 @@ TEST_CASE("SplitDataResultMat", "[SplitDataTest]") CheckMatrices(input, concat); } -TEST_CASE("SplitDataResultField", "[SplitDataTest]") -{ - field input(1, 2); - - mat matA(2, 10); - mat matB(2, 10); - - size_t count = 0; // Counter for unique sequential values. - matA.imbue([&count]() { return ++count; }); - matB.imbue([&count]() { return ++count; }); - - input(0, 0) = matA; - input(0, 1) = matB; - - const auto value = Split(input, 0.5, false); - REQUIRE(std::get<0>(value).n_cols == 1); // Train data. - REQUIRE(std::get<1>(value).n_cols == 1); // Test data. - - field concat = {std::get<0>(value)(0), std::get<1>(value)(0)}; - // Order matters here. - CheckFields(input, concat); -} - TEST_CASE("ZeroRatioSplitData", "[SplitDataTest]") { mat input(2, 10); @@ -198,26 +175,6 @@ TEST_CASE("SplitLabeledDataResultMat", "[SplitDataTest]") CheckDuplication(std::get<2>(value), std::get<3>(value)); } -TEST_CASE("SplitMatrixLabeledDataResultMat", "[SplitDataTest]") -{ - mat input(2, 10); - input.randu(); - - const mat labels(2, 10, fill::randu); - - const auto value = Split(input, labels, 0.2); - REQUIRE(std::get<0>(value).n_cols == 8); - REQUIRE(std::get<1>(value).n_cols == 2); - REQUIRE(std::get<2>(value).n_cols == 8); - REQUIRE(std::get<3>(value).n_cols == 2); - - mat input_concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); - mat labels_concat = arma::join_rows(std::get<2>(value), std::get<3>(value)); - // Order matters here. - CheckMatrices(input, input_concat); - CheckMatrices(labels, labels_concat); -} - /** * The same test as above, but on a larger dataset. */ @@ -334,28 +291,34 @@ TEST_CASE("StratifiedSplitLargerDataResultTest", "[SplitDataTest]") { mat input(3, 480); input.randu(); + // 256 0s, 128 1s, 64 2s and 32 3s. Row zero_label(256); Row one_label(128); Row two_label(64); Row three_label(32); + zero_label.fill(0); one_label.fill(1); two_label.fill(2); three_label.fill(3); + Row labels = arma::join_rows(zero_label, one_label); labels = arma::join_rows(labels, two_label); labels = arma::join_rows(labels, three_label); const double test_ratio = 0.3; + const auto value = Split(input, labels, test_ratio, false, true); REQUIRE(static_cast(find(std::get<2>(value) == 0)).n_rows == 180); REQUIRE(static_cast(find(std::get<2>(value) == 1)).n_rows == 90); REQUIRE(static_cast(find(std::get<2>(value) == 2)).n_rows == 45); REQUIRE(static_cast(find(std::get<2>(value) == 3)).n_rows == 23); + REQUIRE(static_cast(find(std::get<3>(value) == 0)).n_rows == 76); REQUIRE(static_cast(find(std::get<3>(value) == 1)).n_rows == 38); REQUIRE(static_cast(find(std::get<3>(value) == 2)).n_rows == 19); REQUIRE(static_cast(find(std::get<3>(value) == 3)).n_rows == 9); + mat concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); CheckMatEqual(input, concat); } @@ -376,3 +339,51 @@ TEST_CASE("StratifiedSplitRunTimeErrorTest", "[SplitDataTest]") REQUIRE_THROWS_AS(Split(input, labels, test_ratio, false, true), std::runtime_error); } + +/* + * Split with input of type field<>. + */ +TEST_CASE("SplitDataResultField", "[SplitDataTest]") +{ + field input(1, 2); + + mat matA(2, 10); + mat matB(2, 10); + + size_t count = 0; // Counter for unique sequential values. + matA.imbue([&count]() { return ++count; }); + matB.imbue([&count]() { return ++count; }); + + input(0, 0) = matA; + input(0, 1) = matB; + + const auto value = Split(input, 0.5, false); + REQUIRE(std::get<0>(value).n_cols == 1); // Train data. + REQUIRE(std::get<1>(value).n_cols == 1); // Test data. + + field concat = {std::get<0>(value)(0), std::get<1>(value)(0)}; + // Order matters here. + CheckFields(input, concat); +} + +/** + * Test for Split() with labels of type arma::Mat with shuffleData = False. + */ +TEST_CASE("SplitMatrixLabeledData", "[SplitDataTest]") +{ + const mat input(2, 10, fill::randu); + const mat labels(2, 10, fill::randu); + + const auto value = Split(input, labels, 0.2, false); + REQUIRE(std::get<0>(value).n_cols == 8); + REQUIRE(std::get<1>(value).n_cols == 2); + REQUIRE(std::get<2>(value).n_cols == 8); + REQUIRE(std::get<3>(value).n_cols == 2); + + mat input_concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); + mat labels_concat = arma::join_rows(std::get<2>(value), std::get<3>(value)); + + // Order matters here. + CheckMatrices(input, input_concat); + CheckMatrices(labels, labels_concat); +} From bda45a82be7f232441cc9abbebf855268d4738ad Mon Sep 17 00:00:00 2001 From: Yashwant Date: Sat, 27 Feb 2021 18:01:04 +0530 Subject: [PATCH 030/729] Implemented Dirk's idea. --- src/mlpack/bindings/R/CMakeLists.txt | 7 +- src/mlpack/bindings/R/mlpack/cleanup | 3 - src/mlpack/bindings/R/mlpack/configure | 2852 +---------------- src/mlpack/bindings/R/mlpack/configure.ac | 25 - .../R/mlpack/src/{Makevars.in => Makevars} | 2 +- 5 files changed, 7 insertions(+), 2882 deletions(-) delete mode 100644 src/mlpack/bindings/R/mlpack/configure.ac rename src/mlpack/bindings/R/mlpack/src/{Makevars.in => Makevars} (81%) diff --git a/src/mlpack/bindings/R/CMakeLists.txt b/src/mlpack/bindings/R/CMakeLists.txt index f2f6d459ef..56cdb36c31 100644 --- a/src/mlpack/bindings/R/CMakeLists.txt +++ b/src/mlpack/bindings/R/CMakeLists.txt @@ -100,7 +100,7 @@ if (BUILD_R_BINDINGS) set(CPP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/r_util.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/rcpp_mlpack.h" - "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars.in" + "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars" "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars.win" ) @@ -208,11 +208,6 @@ if (BUILD_R_BINDINGS) DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/mlpack/") - file(COPY - "${CMAKE_CURRENT_SOURCE_DIR}/mlpack/configure.ac" - DESTINATION - "${CMAKE_CURRENT_BINARY_DIR}/mlpack/") - # Do the actual build. add_custom_target(r_build ALL) diff --git a/src/mlpack/bindings/R/mlpack/cleanup b/src/mlpack/bindings/R/mlpack/cleanup index 38a04312ad..5347fead4a 100755 --- a/src/mlpack/bindings/R/mlpack/cleanup +++ b/src/mlpack/bindings/R/mlpack/cleanup @@ -1,5 +1,2 @@ ## compilation and editing objects rm -f src/*.o src/*.so src/*.dylib src/*~ *~ - -## autoconf/configure leftovers -rm -rf autom4te.cache/ config.log config.status src/Makevars diff --git a/src/mlpack/bindings/R/mlpack/configure b/src/mlpack/bindings/R/mlpack/configure index 53f7df8624..a571fb1119 100755 --- a/src/mlpack/bindings/R/mlpack/configure +++ b/src/mlpack/bindings/R/mlpack/configure @@ -1,2850 +1,8 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69. -# -# -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## +#!/bin/sh -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME= -PACKAGE_TARNAME= -PACKAGE_VERSION= -PACKAGE_STRING= -PACKAGE_BUGREPORT= -PACKAGE_URL= - -ac_subst_vars='LTLIBOBJS -LIBOBJS -EXTRA_FLAG -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -runstatedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -' - ac_precious_vars='build_alias -host_alias -target_alias' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures this package to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF -_ACEOF -fi - -if test -n "$ac_init_help"; then - - cat <<\_ACEOF - -Report bugs to the package provider. -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -configure -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by $as_me, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -## Set R_HOME, respecting an environment variable if one is set -: ${R_HOME=$(R RHOME)} -if test -z "${R_HOME}"; then - as_fn_error $? "Could not determine R_HOME." "$LINENO" 5 -fi - -## Check for Solaris. -RSysinfoName=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(Sys.info()["sysname"])') - -## Default the flag to the empty string. -extra_flag="" - -if test x"${RSysinfoName}" = x"SunOS"; then - extra_flag="-ftrack-macro-expansion=0" -fi - -EXTRA_FLAG="${extra_flag}" - -ac_config_files="$ac_config_files src/Makevars" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to the package provider." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES " -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - - esac - -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +if [ $(uname) = "SunOS" ] +then +sed -i '1 s/$/ -ftrack-macro-expansion=0/' ./src/Makevars fi +exit 0 diff --git a/src/mlpack/bindings/R/mlpack/configure.ac b/src/mlpack/bindings/R/mlpack/configure.ac deleted file mode 100644 index 74701f3a46..0000000000 --- a/src/mlpack/bindings/R/mlpack/configure.ac +++ /dev/null @@ -1,25 +0,0 @@ -## mlpack configure.ac -AC_PREREQ(2.61) - -## Process this file with autoconf to produce a configure script. -AC_INIT() - -## Set R_HOME, respecting an environment variable if one is set -: ${R_HOME=$(R RHOME)} -if test -z "${R_HOME}"; then - AC_MSG_ERROR([Could not determine R_HOME.]) -fi - -## Check for Solaris. -RSysinfoName=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(Sys.info()[["sysname"]])') - -## Default the flag to the empty string. -extra_flag="" - -if test x"${RSysinfoName}" = x"SunOS"; then - extra_flag="-ftrack-macro-expansion=0" -fi - -AC_SUBST([EXTRA_FLAG], ["${extra_flag}"]) -AC_CONFIG_FILES([src/Makevars]) -AC_OUTPUT diff --git a/src/mlpack/bindings/R/mlpack/src/Makevars.in b/src/mlpack/bindings/R/mlpack/src/Makevars similarity index 81% rename from src/mlpack/bindings/R/mlpack/src/Makevars.in rename to src/mlpack/bindings/R/mlpack/src/Makevars index c25a33701c..bb6a88cc84 100644 --- a/src/mlpack/bindings/R/mlpack/src/Makevars.in +++ b/src/mlpack/bindings/R/mlpack/src/Makevars @@ -1,3 +1,3 @@ -PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) @EXTRA_FLAG@ +PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) CXX_STD = CXX11 From c74ef9cc22a345a4a44b27bcf4c4c6fc62239b3d Mon Sep 17 00:00:00 2001 From: Anush V Kini Date: Sat, 27 Feb 2021 18:13:01 +0530 Subject: [PATCH 031/729] order is init in Stratified Split only when shuffleData is true --- src/mlpack/core/data/split_data.hpp | 67 ++++++++++++++++++----------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 370128dfc6..1c7b6578fe 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -23,7 +23,7 @@ namespace data { * It is recommended to have the input labels between the range [0, n) where n * is the number of different labels. The NormalizeLabels() function in * mlpack::data can be used for this. - * Expects labels to be of type arma::Row<>. + * Expects labels to be of type arma::Row<> or arma::Col<>. * Throws a runtime error if this is not the case. * Example usage below. This overload places the stratified dataset into the * four output parameters given (trainData, testData, trainLabel, @@ -65,7 +65,9 @@ void StratifiedSplit(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - if (!arma::is_Row::value) + const bool typeCheck = (arma::is_Row::value) + || (arma::is_Col::value); + if (!typeCheck) throw std::runtime_error("data::Split(): when stratified sampling is done, " "labels must have type `arma::Row<>`!"); size_t trainIdx = 0; @@ -79,18 +81,8 @@ void StratifiedSplit(const arma::Mat& input, labelCounts.zeros(maxLabel+1); testLabelCounts.zeros(maxLabel+1); - arma::uvec order = - arma::linspace(0, input.n_cols - 1, input.n_cols); - - if (shuffleData) - { - order = arma::shuffle(order); - } - for (typename LabelsType::elem_type label : inputLabel) - { ++labelCounts[label]; - } for (arma::uword labelCount : labelCounts) { @@ -103,21 +95,47 @@ void StratifiedSplit(const arma::Mat& input, trainLabel.set_size(trainSize); testLabel.set_size(testSize); - for (arma::uword i : order) + if (shuffleData) { - typename LabelsType::elem_type label = inputLabel[i]; - if (testLabelCounts[label] < floor(labelCounts[label] * testRatio)) + arma::uvec order = arma::shuffle( + arma::linspace(0, input.n_cols - 1, input.n_cols)); + + for (arma::uword i : order) { - testLabelCounts[label] += 1; - testData.col(testIdx) = input.col(i); - testLabel[testIdx] = inputLabel[i]; - testIdx += 1; + typename LabelsType::elem_type label = inputLabel[i]; + if (testLabelCounts[label] < floor(labelCounts[label] * testRatio)) + { + testLabelCounts[label] += 1; + testData.col(testIdx) = input.col(i); + testLabel[testIdx] = inputLabel[i]; + testIdx += 1; + } + else + { + trainData.col(trainIdx) = input.col(i); + trainLabel[trainIdx] = inputLabel[i]; + trainIdx += 1; + } } - else + } + else + { + for (arma::uword i = 0; i < input.n_cols; i++) { - trainData.col(trainIdx) = input.col(i); - trainLabel[trainIdx] = inputLabel[i]; - trainIdx += 1; + typename LabelsType::elem_type label = inputLabel[i]; + if (testLabelCounts[label] < floor(labelCounts[label] * testRatio)) + { + testLabelCounts[label] += 1; + testData.col(testIdx) = input.col(i); + testLabel[testIdx] = inputLabel[i]; + testIdx += 1; + } + else + { + trainData.col(trainIdx) = input.col(i); + trainLabel[trainIdx] = inputLabel[i]; + trainIdx += 1; + } } } } @@ -285,7 +303,8 @@ void Split(const arma::Mat& input, * sample is visited in linear order. (Default true). * @param stratifyData If true, the train and test splits are stratified * so that the ratio of each class in the training and test sets is the same - * as in the original dataset. Expects labels to be of type arma::Row<>. + * as in the original dataset. Expects labels to be of type arma::Row<> or + * arma::Col<>. * @return std::tuple containing trainData (arma::Mat), testData * (arma::Mat), trainLabel (arma::Row), and testLabel (arma::Row). */ From 26e311ac7286bb808b7a063e83db1578ec0184b2 Mon Sep 17 00:00:00 2001 From: Anush V Kini Date: Sat, 27 Feb 2021 20:41:54 +0530 Subject: [PATCH 032/729] Added test with label of type field and other review fixes --- src/mlpack/core/data/split_data.hpp | 38 +++++++++++++++++----------- src/mlpack/tests/split_data_test.cpp | 36 +++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 1c7b6578fe..da4c240ca2 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -420,8 +420,11 @@ void Split(const FieldType& input, { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; - trainLabel.set_size(1, trainSize); - testLabel.set_size(1, testSize); + + trainData.set_size(1, trainSize); + testData.set_size(1, testSize); + trainLabel.set_size(trainSize); + testLabel.set_size(testSize); if (shuffleData) { @@ -430,34 +433,39 @@ void Split(const FieldType& input, if (trainSize > 0) { - trainData = input.cols(order.subvec(0, trainSize - 1)); - for (size_t i = 0; i < trainSize; ++i) - trainLabel(0, i) = inputLabel(0, order(i)); + { + trainData[i] = input(0, order(i)); + trainLabel[i] = inputLabel(0, order(i)); + } } - if (trainSize < input.n_cols) { - testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); - for (size_t i = trainSize; i < input.n_cols; ++i) - testLabel(0, i - trainSize) = inputLabel(0, order(i)); + { + testData[i - trainSize] = input(0, order(i)); + testLabel[i - trainSize] = inputLabel(0, order(i)); + } } } else { if (trainSize > 0) { - trainData = input.cols(0, trainSize - 1); for (size_t i = 0; i < trainSize; ++i) - trainLabel(0, i) = inputLabel(0, i); + { + trainData[i] = input(0, i); + trainLabel[i] = inputLabel(0, i); + } } if (trainSize < input.n_cols) { - testData = input.cols(trainSize, input.n_cols - 1); for (size_t i = trainSize; i < input.n_cols; ++i) - testLabel(0, i - trainSize) = inputLabel(0, i); + { + testData[i - trainSize] = input(0, i); + testLabel[i - trainSize] = inputLabel(0, i); + } } } } @@ -570,7 +578,7 @@ template ::value || arma::is_Mat_only::value>> -std::tuple +std::tuple, arma::field> Split(const FieldType& input, const arma::field& inputLabel, const double testRatio, @@ -581,7 +589,7 @@ Split(const FieldType& input, arma::field trainLabel; arma::field testLabel; - Split(input, inputLabel, trainData, testData, trainLabel, testLabel, + Split(input, inputLabel, trainData, trainLabel, testData, testLabel, testRatio, shuffleData); return std::make_tuple(std::move(trainData), diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 1419756e5b..8d2b5e470e 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -341,7 +341,7 @@ TEST_CASE("StratifiedSplitRunTimeErrorTest", "[SplitDataTest]") } /* - * Split with input of type field<>. + * Split with input of type field. */ TEST_CASE("SplitDataResultField", "[SplitDataTest]") { @@ -387,3 +387,37 @@ TEST_CASE("SplitMatrixLabeledData", "[SplitDataTest]") CheckMatrices(input, input_concat); CheckMatrices(labels, labels_concat); } + +/* + * Split with input of type field and label of type field. + */ +TEST_CASE("SplitLabeledDataResultField", "[SplitDataTest]") +{ + field input(1, 2); + field label(1, 2); + + mat matA(2, 10, fill::randu); + mat matB(2, 10, fill::randu); + + vec vecA(10, fill::randu); + vec vecB(10, fill::randu); + + input(0, 0) = matA; + input(0, 1) = matB; + + label(0, 0) = vecA; + label(0, 1) = vecB; + + const auto value = Split(input, label, 0.5, false); + REQUIRE(std::get<0>(value).n_cols == 1); // Train data. + REQUIRE(std::get<1>(value).n_cols == 1); // Test data. + REQUIRE(std::get<2>(value).n_cols == 1); // Train label. + REQUIRE(std::get<3>(value).n_cols == 1); // Test label. + + field input_concat = {std::get<0>(value)(0), std::get<1>(value)(0)}; + field label_concat = {std::get<2>(value)(0), std::get<3>(value)(0)}; + + // Order matters here. + CheckFields(input, input_concat); + CheckFields(label, label_concat); +} From 332bbd4ea27cf3f397e8fbae41b724b7f193082d Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Sun, 12 Apr 2020 23:32:58 +0530 Subject: [PATCH 033/729] CheckSameSize() added --- src/mlpack/core/util/CMakeLists.txt | 1 + src/mlpack/core/util/facilities.hpp | 71 +++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/mlpack/core/util/facilities.hpp diff --git a/src/mlpack/core/util/CMakeLists.txt b/src/mlpack/core/util/CMakeLists.txt index 19ddff3293..4872652826 100644 --- a/src/mlpack/core/util/CMakeLists.txt +++ b/src/mlpack/core/util/CMakeLists.txt @@ -33,6 +33,7 @@ set(SOURCES to_lower.hpp version.hpp version.cpp + facilities.hpp ) # add directory name to sources diff --git a/src/mlpack/core/util/facilities.hpp b/src/mlpack/core/util/facilities.hpp new file mode 100644 index 0000000000..dee4cd7ee8 --- /dev/null +++ b/src/mlpack/core/util/facilities.hpp @@ -0,0 +1,71 @@ +/** + * @file facilities.hpp + * @author Kirill Mishchenko + * @author Bisakh Mondal + * + * Utility that is used for checking same size & same dimensionality between + * data & response. + * + * 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_UTIL_FACILITIES_HPP +#define MLPACK_UTIL_FACILITIES_HPP + +#include + +namespace mlpack { +namespace util { + +/** + * Check for if the given data points & labels have same size. + * + * @param data data. + * @param labels Labels. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @param mode For nature of comparision(default "CE"). + * types of mode: + * "CE" equivalent to (data.n_cols, labels.n_elem). + * "CC" equivalent to (data.n_cols, labels.n_cols). + */ +template +inline void CheckSameSizes(const DataType& data, + const LabelsType& labels, + const std::string& callerDescription, + const std::string& mode = "CE") +{ + if (mode == "CE") + { + if (data.n_cols != labels.n_elem) + { + std::ostringstream oss; + oss << callerDescription << ": number of points (" << data.n_cols << ") " + << "does not match number of labels (" << labels.n_elem << ")!" + << std::endl; + throw std::invalid_argument(oss.str()); + } + } + else if (mode == "CC") + { + if (data.n_cols != labels.n_cols) + { + std::ostringstream oss; + oss << callerDescription << ": number of points (" << data.n_cols << ") " + << "does not match number of responses (" << labels.n_cols << ")!" + << std::endl; + throw std::invalid_argument(oss.str()); + } + } + else + //For development purpose, not intended for user. + Log::Fatal << "Ensure Providing Correct mode!!" << std::endl; + +} + +} // namespace util +} // namespace mlpack + +#endif From 5a328bae3f6069e83bd09d8a947dc23b500297c1 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 02:05:52 +0530 Subject: [PATCH 034/729] CheckSameDimensionality() added --- src/mlpack/core/util/facilities.hpp | 56 +++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/mlpack/core/util/facilities.hpp b/src/mlpack/core/util/facilities.hpp index dee4cd7ee8..b466634eb2 100644 --- a/src/mlpack/core/util/facilities.hpp +++ b/src/mlpack/core/util/facilities.hpp @@ -3,8 +3,7 @@ * @author Kirill Mishchenko * @author Bisakh Mondal * - * Utility that is used for checking same size & same dimensionality between - * data & response. + * Utility for checking same size & same dimensionality. * * 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 @@ -33,9 +32,9 @@ namespace util { */ template inline void CheckSameSizes(const DataType& data, - const LabelsType& labels, - const std::string& callerDescription, - const std::string& mode = "CE") + const LabelsType& labels, + const std::string& callerDescription, + const std::string& mode = "CE") { if (mode == "CE") { @@ -59,13 +58,58 @@ inline void CheckSameSizes(const DataType& data, throw std::invalid_argument(oss.str()); } } + else + //For development purpose, not intended for user. + Log::Fatal << "Ensure Providing Correct mode." << std::endl; + +} + +/** + * Check for if the given dataset dimension matches with the model's. + * + * @param data dataset. + * @param dimension Dimension of the model. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @param mode For nature of comparision(default "R"). + * types of mode: + * "R" for comparision with number of rows of the dataset. + * "C" for comparision with number of columns of the dataset. + */ +template +inline void CheckSameDimentionality(const DataType& data, + const size_t& dimension, + const std::string& callerDescription, + const std::string& mode = "R") +{ + if (mode == "R") + { + if (data.n_rows != dimension) + { + std::ostringstream oss; + oss << callerDescription << ": dataset has " << data.n_rows + << " dimensions, but model has " << dimension << " dimensions!"; + throw std::invalid_argument(oss.str()); + } + } + else if (mode == "C") + { + if (data.n_cols != dimension) + { + std::ostringstream oss; + oss << callerDescription << ": dataset has " << data.n_cols + << " dimensions, but model has " << dimension << " dimensions!"; + throw std::invalid_argument(oss.str()); + } + } else //For development purpose, not intended for user. Log::Fatal << "Ensure Providing Correct mode!!" << std::endl; - + } } // namespace util } // namespace mlpack #endif + From 1dd543b5518bdab70c415f5844e30e97624fbb20 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 02:06:45 +0530 Subject: [PATCH 035/729] Added header file to core.hpp --- src/mlpack/core.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/core.hpp b/src/mlpack/core.hpp index b4645d2b09..7c73678163 100644 --- a/src/mlpack/core.hpp +++ b/src/mlpack/core.hpp @@ -89,6 +89,8 @@ #include #include #include +#include +#include // mlpack::backtrace only for linux #ifdef HAS_BFD_DL From ed6bb2af15079661cb34ec709e98427e12d8522c Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 02:07:28 +0530 Subject: [PATCH 036/729] Tests added --- src/mlpack/tests/facilities_test.cpp | 55 +++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp index 65b754bb4e..5d95734fca 100644 --- a/src/mlpack/tests/facilities_test.cpp +++ b/src/mlpack/tests/facilities_test.cpp @@ -1,8 +1,9 @@ /** * @file facilities_test.cpp * @author Khizir Siddiqui - * - * Test file for facilities in metrics. + * @author Bisakh Mondal + * + * Test file for Utility facilities. * * 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 @@ -14,11 +15,15 @@ #include #include #include +#include #include "catch.hpp" using namespace mlpack; using namespace mlpack::cv; +using namespace mlpack::util; + +BOOST_AUTO_TEST_SUITE(FacilityTest); /** * The unequal sizes for data and labels show throw an error. @@ -54,3 +59,49 @@ TEST_CASE("PairwiseDistanceTest", "[FacilitiesTest]") REQUIRE(dist(1, 0) == Approx(1.41421).epsilon(1e-5)); REQUIRE(dist(2, 0) == 3); } + + +/** + * Test that CheckSameSizes() works in different cases. + */ +BOOST_AUTO_TEST_CASE(CheckSizeTest) +{ + arma::mat data = arma::randu(20,30); + arma::colvec firstLabels = arma::randu(20); + arma::colvec secondLabels = arma::randu(30); + arma::mat thirdLabels = arma::randu(20,30); + + BOOST_REQUIRE_THROW(CheckSameSizes(data,firstLabels,"TestChecking"), + std::invalid_argument); + BOOST_REQUIRE_THROW(CheckSameSizes(data,firstLabels,"TestChecking","CC"), + std::invalid_argument); + BOOST_REQUIRE_THROW(CheckSameSizes(data,firstLabels,"TestChecking","AB"), + std::runtime_error); + + BOOST_REQUIRE_NO_THROW(CheckSameSizes(data,secondLabels,"TestChecking")); + BOOST_REQUIRE_NO_THROW(CheckSameSizes(data,thirdLabels,"TestChecking", + "CC")); + +} + + +/** + * Test that CheckSameDimensionality() works in different cases. + */ +BOOST_AUTO_TEST_CASE(CheckDimensioinality) +{ + arma::mat dataset = arma::randu(20,30); + + BOOST_REQUIRE_NO_THROW(CheckSameDimentionality(dataset,20,"TestingDim")); + BOOST_REQUIRE_NO_THROW(CheckSameDimentionality(dataset,30,"TestingDim", + "C")); + + BOOST_REQUIRE_THROW(CheckSameDimentionality(dataset, 100, "TestingDim"), + std::invalid_argument); + BOOST_REQUIRE_THROW(CheckSameDimentionality(dataset, 50, "TestingDim", "C"), + std::invalid_argument); + BOOST_REQUIRE_THROW(CheckSameDimentionality(dataset, 20, "TestingDim", "A"), + std::runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END(); From 2e0e08edbf6694df6f2db09a12493736b0405b98 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 04:04:50 +0530 Subject: [PATCH 037/729] Old updated --- src/mlpack/core/cv/metrics/CMakeLists.txt | 1 - src/mlpack/core/cv/metrics/accuracy_impl.hpp | 4 +--- src/mlpack/core/cv/metrics/f1_impl.hpp | 7 +++---- src/mlpack/core/cv/metrics/precision_impl.hpp | 7 +++---- src/mlpack/core/cv/metrics/recall_impl.hpp | 7 +++---- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/mlpack/core/cv/metrics/CMakeLists.txt b/src/mlpack/core/cv/metrics/CMakeLists.txt index b9edacaf9a..e2322e673c 100644 --- a/src/mlpack/core/cv/metrics/CMakeLists.txt +++ b/src/mlpack/core/cv/metrics/CMakeLists.txt @@ -6,7 +6,6 @@ set(SOURCES average_strategy.hpp f1.hpp f1_impl.hpp - facilities.hpp mse.hpp mse_impl.hpp precision.hpp diff --git a/src/mlpack/core/cv/metrics/accuracy_impl.hpp b/src/mlpack/core/cv/metrics/accuracy_impl.hpp index 91f3dc1c3e..b6f08332af 100644 --- a/src/mlpack/core/cv/metrics/accuracy_impl.hpp +++ b/src/mlpack/core/cv/metrics/accuracy_impl.hpp @@ -12,8 +12,6 @@ #ifndef MLPACK_CORE_CV_METRICS_ACCURACY_IMPL_HPP #define MLPACK_CORE_CV_METRICS_ACCURACY_IMPL_HPP -#include - namespace mlpack { namespace cv { @@ -22,7 +20,7 @@ double Accuracy::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Accuracy::Evaluate()"); + util::CheckSameSizes(data, labels, "Accuracy::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); diff --git a/src/mlpack/core/cv/metrics/f1_impl.hpp b/src/mlpack/core/cv/metrics/f1_impl.hpp index 6e89754941..5af0558a68 100644 --- a/src/mlpack/core/cv/metrics/f1_impl.hpp +++ b/src/mlpack/core/cv/metrics/f1_impl.hpp @@ -13,7 +13,6 @@ #define MLPACK_CORE_CV_METRICS_F1_IMPL_HPP #include -#include namespace mlpack { namespace cv { @@ -33,7 +32,7 @@ double F1::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "F1::Evaluate()"); + util::CheckSameSizes(data, labels, "F1::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); @@ -56,7 +55,7 @@ double F1::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "F1::Evaluate()"); + util::CheckSameSizes(data, labels, "F1::Evaluate()"); // Microaveraged F1 is really the same as microaveraged precision and // microaveraged recall, which are in turn the same as accuracy. @@ -70,7 +69,7 @@ double F1::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "F1::Evaluate()"); + util::CheckSameSizes(data, labels, "F1::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); diff --git a/src/mlpack/core/cv/metrics/precision_impl.hpp b/src/mlpack/core/cv/metrics/precision_impl.hpp index b8831fe132..25afd43454 100644 --- a/src/mlpack/core/cv/metrics/precision_impl.hpp +++ b/src/mlpack/core/cv/metrics/precision_impl.hpp @@ -13,7 +13,6 @@ #define MLPACK_CORE_CV_METRICS_PRECISION_IMPL_HPP #include -#include namespace mlpack { namespace cv { @@ -33,7 +32,7 @@ double Precision::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Precision::Evaluate()"); + util::CheckSameSizes(data, labels, "Precision::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); @@ -51,7 +50,7 @@ double Precision::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Precision::Evaluate()"); + util::CheckSameSizes(data, labels, "Precision::Evaluate()"); // Microaveraged precision turns out to be just accuracy. return Accuracy::Evaluate(model, data, labels); @@ -64,7 +63,7 @@ double Precision::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Precision::Evaluate()"); + util::CheckSameSizes(data, labels, "Precision::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); diff --git a/src/mlpack/core/cv/metrics/recall_impl.hpp b/src/mlpack/core/cv/metrics/recall_impl.hpp index 5ff7bd7400..bbfbe7071d 100644 --- a/src/mlpack/core/cv/metrics/recall_impl.hpp +++ b/src/mlpack/core/cv/metrics/recall_impl.hpp @@ -13,7 +13,6 @@ #define MLPACK_CORE_CV_METRICS_RECALL_IMPL_HPP #include -#include namespace mlpack { namespace cv { @@ -33,7 +32,7 @@ double Recall::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Recall::Evaluate()"); + util::CheckSameSizes(data, labels, "Recall::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); @@ -51,7 +50,7 @@ double Recall::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Recall::Evaluate()"); + util::CheckSameSizes(data, labels, "Recall::Evaluate()"); // Microaveraged recall is really the same as accuracy. return Accuracy::Evaluate(model, data, labels); @@ -64,7 +63,7 @@ double Recall::Evaluate(MLAlgorithm& model, const DataType& data, const arma::Row& labels) { - AssertSizes(data, labels, "Recall::Evaluate()"); + util::CheckSameSizes(data, labels, "Recall::Evaluate()"); arma::Row predictedLabels; model.Classify(data, predictedLabels); From e8cba43562a1013f9c74d192935f28ded8738d3f Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 04:08:04 +0530 Subject: [PATCH 038/729] unnecessary file removed --- src/mlpack/core/cv/metrics/facilities.hpp | 71 ----------------------- 1 file changed, 71 deletions(-) delete mode 100644 src/mlpack/core/cv/metrics/facilities.hpp diff --git a/src/mlpack/core/cv/metrics/facilities.hpp b/src/mlpack/core/cv/metrics/facilities.hpp deleted file mode 100644 index c7b9b4b70e..0000000000 --- a/src/mlpack/core/cv/metrics/facilities.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file core/cv/metrics/facilities.hpp - * @author Kirill Mishchenko - * @author Khizir Siddiqui - * - * Functionality that is used more than in one metric. - * - * 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_CORE_CV_METRICS_FACILITIES_HPP -#define MLPACK_CORE_CV_METRICS_FACILITIES_HPP - -#include -#include - -namespace mlpack { -namespace cv { - -/** - * Assert there is the same number of the given data points and labels. - * - * @param data Column-major data. - * @param labels Labels. - * @param callerDescription A description of the caller that can be used for - * error generation. - */ -template -void AssertSizes(const DataType& data, - const arma::Row& labels, - const std::string& callerDescription) -{ - if (data.n_cols != labels.n_elem) - { - std::ostringstream oss; - oss << callerDescription << ": number of points (" << data.n_cols << ") " - << "does not match number of labels (" << labels.n_elem << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } -} - -/** - * Pairwise distance of the given data. - * - * @param data Column-major matrix. - * @param metric Distance metric to be used. - */ -template -DataType PairwiseDistances(const DataType& data, - const Metric& metric) -{ - DataType distances = DataType(data.n_cols, data.n_cols, arma::fill::none); - for (size_t i = 0; i < data.n_cols; i++) - { - for (size_t j = 0; j < i; j++) - { - distances(i, j) = metric.Evaluate(data.col(i), data.col(j)); - distances(j, i) = distances(i, j); - } - } - distances.diag().zeros(); - return distances; -} - -} // namespace cv -} // namespace mlpack - -#endif From 72e000f09bdd7d509b3f621c259836a15e188752 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 09:41:30 +0530 Subject: [PATCH 039/729] spelling error corrected --- src/mlpack/core/util/facilities.hpp | 2 +- src/mlpack/tests/facilities_test.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mlpack/core/util/facilities.hpp b/src/mlpack/core/util/facilities.hpp index b466634eb2..5a7d22069e 100644 --- a/src/mlpack/core/util/facilities.hpp +++ b/src/mlpack/core/util/facilities.hpp @@ -77,7 +77,7 @@ inline void CheckSameSizes(const DataType& data, * "C" for comparision with number of columns of the dataset. */ template -inline void CheckSameDimentionality(const DataType& data, +inline void CheckSameDimensionality(const DataType& data, const size_t& dimension, const std::string& callerDescription, const std::string& mode = "R") diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp index 5d95734fca..4b1042fe72 100644 --- a/src/mlpack/tests/facilities_test.cpp +++ b/src/mlpack/tests/facilities_test.cpp @@ -88,19 +88,19 @@ BOOST_AUTO_TEST_CASE(CheckSizeTest) /** * Test that CheckSameDimensionality() works in different cases. */ -BOOST_AUTO_TEST_CASE(CheckDimensioinality) +BOOST_AUTO_TEST_CASE(CheckDimensionality) { arma::mat dataset = arma::randu(20,30); - BOOST_REQUIRE_NO_THROW(CheckSameDimentionality(dataset,20,"TestingDim")); - BOOST_REQUIRE_NO_THROW(CheckSameDimentionality(dataset,30,"TestingDim", + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset,20,"TestingDim")); + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset,30,"TestingDim", "C")); - BOOST_REQUIRE_THROW(CheckSameDimentionality(dataset, 100, "TestingDim"), + BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 100, "TestingDim"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameDimentionality(dataset, 50, "TestingDim", "C"), + BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 50, "TestingDim", "C"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameDimentionality(dataset, 20, "TestingDim", "A"), + BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 20, "TestingDim", "A"), std::runtime_error); } From f02fe11fbc7f7a430de879f281c13be7894d925e Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Mon, 13 Apr 2020 10:19:15 +0530 Subject: [PATCH 040/729] style issue fixed --- src/mlpack/core/util/facilities.hpp | 6 ++---- src/mlpack/tests/facilities_test.cpp | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/mlpack/core/util/facilities.hpp b/src/mlpack/core/util/facilities.hpp index 5a7d22069e..bd9605b460 100644 --- a/src/mlpack/core/util/facilities.hpp +++ b/src/mlpack/core/util/facilities.hpp @@ -59,9 +59,8 @@ inline void CheckSameSizes(const DataType& data, } } else - //For development purpose, not intended for user. + // For development purpose, not intended for user. Log::Fatal << "Ensure Providing Correct mode." << std::endl; - } /** @@ -103,9 +102,8 @@ inline void CheckSameDimensionality(const DataType& data, } } else - //For development purpose, not intended for user. + // For development purpose, not intended for user. Log::Fatal << "Ensure Providing Correct mode!!" << std::endl; - } } // namespace util diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp index 4b1042fe72..11ee5c68b1 100644 --- a/src/mlpack/tests/facilities_test.cpp +++ b/src/mlpack/tests/facilities_test.cpp @@ -66,22 +66,21 @@ TEST_CASE("PairwiseDistanceTest", "[FacilitiesTest]") */ BOOST_AUTO_TEST_CASE(CheckSizeTest) { - arma::mat data = arma::randu(20,30); + arma::mat data = arma::randu(20, 30); arma::colvec firstLabels = arma::randu(20); arma::colvec secondLabels = arma::randu(30); - arma::mat thirdLabels = arma::randu(20,30); + arma::mat thirdLabels = arma::randu(20, 30); - BOOST_REQUIRE_THROW(CheckSameSizes(data,firstLabels,"TestChecking"), + BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameSizes(data,firstLabels,"TestChecking","CC"), + BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "CC"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameSizes(data,firstLabels,"TestChecking","AB"), + BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "AB"), std::runtime_error); - BOOST_REQUIRE_NO_THROW(CheckSameSizes(data,secondLabels,"TestChecking")); - BOOST_REQUIRE_NO_THROW(CheckSameSizes(data,thirdLabels,"TestChecking", + BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, secondLabels, "TestChecking")); + BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, thirdLabels, "TestChecking", "CC")); - } @@ -90,10 +89,10 @@ BOOST_AUTO_TEST_CASE(CheckSizeTest) */ BOOST_AUTO_TEST_CASE(CheckDimensionality) { - arma::mat dataset = arma::randu(20,30); + arma::mat dataset = arma::randu(20, 30); - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset,20,"TestingDim")); - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset,30,"TestingDim", + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, 20, "TestingDim")); + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, 30, "TestingDim", "C")); BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 100, "TestingDim"), From bd8710d53483493407200defeaa6c7e368512df6 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Tue, 28 Apr 2020 21:49:36 +0530 Subject: [PATCH 041/729] Size Check Suite added --- src/mlpack/core/util/size_checks.hpp | 108 ++++++++++++++++++++++++++ src/mlpack/tests/size_checks_test.cpp | 62 +++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 src/mlpack/core/util/size_checks.hpp create mode 100644 src/mlpack/tests/size_checks_test.cpp diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp new file mode 100644 index 0000000000..7a02a2ee5e --- /dev/null +++ b/src/mlpack/core/util/size_checks.hpp @@ -0,0 +1,108 @@ +/** + * @file size_checks.hpp + * @author Kirill Mishchenko + * @author Bisakh Mondal + * + * Utility for checking same size & same dimensionality. + * + * 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_UTIL_SIZE_CHECKS_HPP +#define MLPACK_UTIL_SIZE_CHECKS_HPP + +#include + +namespace mlpack { +namespace util { + +/** + * Check for if the given data points & labels have same size. + * + * @param data data. + * @param labels Labels. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @param mode For nature of comparision(default "CE"). + * types of mode: + * "CE" equivalent to (data.n_cols, labels.n_elem). + * "CC" equivalent to (data.n_cols, labels.n_cols). + * @param addInfo An additional information about labels that can be used for + * precise error generation. Default is "labels". Another e.g. weights + */ +template +inline void CheckSameSizes(const DataType& data, + const LabelsType& labels, + const std::string& callerDescription, + const std::string& mode = "CE", + const std::string& addInfo = "labels") +{ + if (mode != "CE" && mode != "CC") + // For development purpose, not intended for user. + Log::Fatal << "Ensure Providing Correct mode." << std::endl; + + const size_t size1 = data.n_cols; + const size_t size2 = mode == "CE" ? labels.n_elem : labels.n_cols; + + if (size1 != size2) + { + std::ostringstream oss; + oss << callerDescription << ": number of points (" << size1 << ") " + << "does not match number of " << addInfo << " (" << size2 << ")!" + << std::endl; + throw std::invalid_argument(oss.str()); + } +} + +/** + * Check for if the given dataset dimension matches with the model's. + * + * @param data dataset. + * @param dimension Dimension of the model. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @param addInfo An additional information about data that can be used for + * precise error generation. Default is "dataset". Another e.g. weights. + */ +template +inline void CheckSameDimensionality(const DataType& data, + const DimType& dimension, + const std::string& callerDescription, + const std::string& addInfo = "dataset") +{ + if (data.n_rows != dimension.n_rows) + { + std::ostringstream oss; + oss << callerDescription << ": dimensionality of " << addInfo << " (" + << data.n_rows << ") is not equal to the dimensionality of the model" + " (" << dimension.n_rows << ")!"; + + throw std::invalid_argument(oss.str()); + } +} + +// An overload of CheckSameDimensionality() where second param is unsigned +// long int. +template +inline void CheckSameDimensionality(const DataType& data, + const size_t& dimension, + const std::string& callerDescription, + const std::string& addInfo = "dataset") +{ + if (data.n_rows != dimension) + { + std::ostringstream oss; + oss << callerDescription << ": dimensionality of " << addInfo << " (" + << data.n_rows << ") is not equal to the dimensionality of the model" + " (" << dimension << ")!"; + throw std::invalid_argument(oss.str()); + } +} + +} // namespace util +} // namespace mlpack + +#endif + diff --git a/src/mlpack/tests/size_checks_test.cpp b/src/mlpack/tests/size_checks_test.cpp new file mode 100644 index 0000000000..44539036b9 --- /dev/null +++ b/src/mlpack/tests/size_checks_test.cpp @@ -0,0 +1,62 @@ +/** + * @file size_checks_test.cpp + * @author Bisakh Mondal + * + * Test file for Utility size_checks. + * + * 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 + +using namespace mlpack; +using namespace mlpack::util; +BOOST_AUTO_TEST_SUITE(SizeCheckTest); + +/** + * Test that CheckSameSizes() works in different cases. + */ +BOOST_AUTO_TEST_CASE(CheckSizeTest) +{ + arma::mat data = arma::randu(20, 30); + arma::colvec firstLabels = arma::randu(20); + arma::colvec secondLabels = arma::randu(30); + arma::mat thirdLabels = arma::randu(20, 30); + + BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking"), + std::invalid_argument); + BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "CC"), + std::invalid_argument); + BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "AB"), + std::runtime_error); + + BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, secondLabels, "TestChecking")); + BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, thirdLabels, "TestChecking", + "CC")); +} + +/** + * Test that CheckSameDimensionality() works in different cases. + */ +BOOST_AUTO_TEST_CASE(CheckDimensionality) +{ + arma::mat dataset = arma::randu(20, 30); + arma::colvec refSet = arma::randu(20); + arma::colvec refSet2 = arma::randu(40); + + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, (size_t) 20, + "TestingDim")); + BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, (size_t) 100, + "TestingDim"), std::invalid_argument); + + BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, refSet2, "TestingDim"), + std::invalid_argument); + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, refSet, "TestingDim" + )); +} + +BOOST_AUTO_TEST_SUITE_END(); + From d4f0cad156307409924d3952d312507418f7042f Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Tue, 28 Apr 2020 21:59:52 +0530 Subject: [PATCH 042/729] updated implementations --- src/mlpack/core.hpp | 2 +- src/mlpack/core/cv/cv_base_impl.hpp | 10 +- src/mlpack/core/cv/metrics/mse_impl.hpp | 9 +- src/mlpack/core/cv/metrics/r2_score_impl.hpp | 10 +- src/mlpack/core/util/CMakeLists.txt | 2 +- src/mlpack/core/util/facilities.hpp | 113 ------------------ src/mlpack/core/util/size_checks.hpp | 2 +- .../decision_tree/decision_tree_impl.hpp | 60 +++++----- .../methods/linear_svm/linear_svm_impl.hpp | 8 +- src/mlpack/methods/lsh/lsh_search_impl.hpp | 10 +- .../range_search/range_search_impl.hpp | 10 +- .../softmax_regression/softmax_regression.cpp | 10 +- src/mlpack/tests/CMakeLists.txt | 4 +- src/mlpack/tests/facilities_test.cpp | 106 ---------------- 14 files changed, 46 insertions(+), 310 deletions(-) delete mode 100644 src/mlpack/core/util/facilities.hpp delete mode 100644 src/mlpack/tests/facilities_test.cpp diff --git a/src/mlpack/core.hpp b/src/mlpack/core.hpp index 7c73678163..c4522ba05f 100644 --- a/src/mlpack/core.hpp +++ b/src/mlpack/core.hpp @@ -90,7 +90,7 @@ #include #include #include -#include +#include // mlpack::backtrace only for linux #ifdef HAS_BFD_DL diff --git a/src/mlpack/core/cv/cv_base_impl.hpp b/src/mlpack/core/cv/cv_base_impl.hpp index a7017d770a..fc819603db 100644 --- a/src/mlpack/core/cv/cv_base_impl.hpp +++ b/src/mlpack/core/cv/cv_base_impl.hpp @@ -106,14 +106,8 @@ void CVBase::AssertDataConsistency(const MatType& xs, const PredictionsType& ys) { - if (xs.n_cols != ys.n_cols) - { - std::ostringstream oss; - oss << "CVBase::AssertDataConsistency(): number of data points (" - << xs.n_cols << ") does not match number of predictions (" << ys.n_cols - << ")!" << std::endl; - throw std::invalid_argument(oss.str()); - } + util::CheckSameSizes(xs, ys, "CVBase::AssertDataConsistency()", "CC", + "predictions"); } template::Evaluate(MLAlgorithm& model, const DataType& data, const ResponsesType& responses) { - if (data.n_cols != responses.n_cols) - { - std::ostringstream oss; - oss << "R2Score::Evaluate(): number of points (" << data.n_cols << ") " - << "does not match number of responses (" << responses.n_cols << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } + util::CheckSameSizes(data, responses, "R2Score::Evaluate()", "CC", + "responses"); ResponsesType predictedResponses; // Taking Predicted Output from the model. diff --git a/src/mlpack/core/util/CMakeLists.txt b/src/mlpack/core/util/CMakeLists.txt index 4872652826..ef21ff91ca 100644 --- a/src/mlpack/core/util/CMakeLists.txt +++ b/src/mlpack/core/util/CMakeLists.txt @@ -26,6 +26,7 @@ set(SOURCES prefixedoutstream_impl.hpp program_doc.hpp program_doc.cpp + size_checks.hpp sfinae_utility.hpp singletons.cpp timers.hpp @@ -33,7 +34,6 @@ set(SOURCES to_lower.hpp version.hpp version.cpp - facilities.hpp ) # add directory name to sources diff --git a/src/mlpack/core/util/facilities.hpp b/src/mlpack/core/util/facilities.hpp deleted file mode 100644 index bd9605b460..0000000000 --- a/src/mlpack/core/util/facilities.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file facilities.hpp - * @author Kirill Mishchenko - * @author Bisakh Mondal - * - * Utility for checking same size & same dimensionality. - * - * 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_UTIL_FACILITIES_HPP -#define MLPACK_UTIL_FACILITIES_HPP - -#include - -namespace mlpack { -namespace util { - -/** - * Check for if the given data points & labels have same size. - * - * @param data data. - * @param labels Labels. - * @param callerDescription A description of the caller that can be used for - * error generation. - * @param mode For nature of comparision(default "CE"). - * types of mode: - * "CE" equivalent to (data.n_cols, labels.n_elem). - * "CC" equivalent to (data.n_cols, labels.n_cols). - */ -template -inline void CheckSameSizes(const DataType& data, - const LabelsType& labels, - const std::string& callerDescription, - const std::string& mode = "CE") -{ - if (mode == "CE") - { - if (data.n_cols != labels.n_elem) - { - std::ostringstream oss; - oss << callerDescription << ": number of points (" << data.n_cols << ") " - << "does not match number of labels (" << labels.n_elem << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } - } - else if (mode == "CC") - { - if (data.n_cols != labels.n_cols) - { - std::ostringstream oss; - oss << callerDescription << ": number of points (" << data.n_cols << ") " - << "does not match number of responses (" << labels.n_cols << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } - } - else - // For development purpose, not intended for user. - Log::Fatal << "Ensure Providing Correct mode." << std::endl; -} - -/** - * Check for if the given dataset dimension matches with the model's. - * - * @param data dataset. - * @param dimension Dimension of the model. - * @param callerDescription A description of the caller that can be used for - * error generation. - * @param mode For nature of comparision(default "R"). - * types of mode: - * "R" for comparision with number of rows of the dataset. - * "C" for comparision with number of columns of the dataset. - */ -template -inline void CheckSameDimensionality(const DataType& data, - const size_t& dimension, - const std::string& callerDescription, - const std::string& mode = "R") -{ - if (mode == "R") - { - if (data.n_rows != dimension) - { - std::ostringstream oss; - oss << callerDescription << ": dataset has " << data.n_rows - << " dimensions, but model has " << dimension << " dimensions!"; - throw std::invalid_argument(oss.str()); - } - } - else if (mode == "C") - { - if (data.n_cols != dimension) - { - std::ostringstream oss; - oss << callerDescription << ": dataset has " << data.n_cols - << " dimensions, but model has " << dimension << " dimensions!"; - throw std::invalid_argument(oss.str()); - } - } - else - // For development purpose, not intended for user. - Log::Fatal << "Ensure Providing Correct mode!!" << std::endl; -} - -} // namespace util -} // namespace mlpack - -#endif - diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp index 7a02a2ee5e..318de15567 100644 --- a/src/mlpack/core/util/size_checks.hpp +++ b/src/mlpack/core/util/size_checks.hpp @@ -3,7 +3,7 @@ * @author Kirill Mishchenko * @author Bisakh Mondal * - * Utility for checking same size & same dimensionality. + * Utility for checking same size & same dimensionality. * * 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 diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index 1646608d0b..8967e88f1b 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -469,14 +469,7 @@ double DecisionTree::type; using TrueLabelsType = typename std::decay::type; @@ -518,14 +511,15 @@ double DecisionTree::type; using TrueLabelsType = typename std::decay::type; @@ -573,14 +567,15 @@ double DecisionTree::type>::value>*) { // Sanity check on data. - if (data.n_cols != labels.n_elem) - { - std::ostringstream oss; - oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") " - << "does not match number of labels (" << labels.n_elem << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } + // if (data.n_cols != labels.n_elem) + // { + // std::ostringstream oss; + // oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") " + // << "does not match number of labels (" << labels.n_elem << ")!" + // << std::endl; + // throw std::invalid_argument(oss.str()); + // } + util::CheckSameSizes(data, labels, "DecisionTree::Train()"); using TrueMatType = typename std::decay::type; using TrueLabelsType = typename std::decay::type; @@ -628,14 +623,15 @@ double DecisionTree::type>::value>*) { // Sanity check on data. - if (data.n_cols != labels.n_elem) - { - std::ostringstream oss; - oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") " - << "does not match number of labels (" << labels.n_elem << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } + // if (data.n_cols != labels.n_elem) + // { + // std::ostringstream oss; + // oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") " + // << "does not match number of labels (" << labels.n_elem << ")!" + // << std::endl; + // throw std::invalid_argument(oss.str()); + // } + util::CheckSameSizes(data, labels, "DecisionTree::Train()"); using TrueMatType = typename std::decay::type; using TrueLabelsType = typename std::decay::type; diff --git a/src/mlpack/methods/linear_svm/linear_svm_impl.hpp b/src/mlpack/methods/linear_svm/linear_svm_impl.hpp index 243ba772ce..69f0887f9d 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_impl.hpp +++ b/src/mlpack/methods/linear_svm/linear_svm_impl.hpp @@ -173,13 +173,7 @@ void LinearSVM::Classify( const MatType& data, arma::mat& scores) const { - if (data.n_rows != FeatureSize()) - { - std::ostringstream oss; - oss << "LinearSVM::Classify(): dataset has " << data.n_rows - << " dimensions, but model has " << FeatureSize() << " dimensions!"; - throw std::invalid_argument(oss.str()); - } + util::CheckSameDimensionality(data, FeatureSize(), "LinearSVM::Classify()"); if (fitIntercept) { diff --git a/src/mlpack/methods/lsh/lsh_search_impl.hpp b/src/mlpack/methods/lsh/lsh_search_impl.hpp index c3838bd4b6..6c3aeb8259 100644 --- a/src/mlpack/methods/lsh/lsh_search_impl.hpp +++ b/src/mlpack/methods/lsh/lsh_search_impl.hpp @@ -865,14 +865,8 @@ void LSHSearch::Search( const size_t T) { // Ensure the dimensionality of the query set is correct. - if (querySet.n_rows != referenceSet.n_rows) - { - std::ostringstream oss; - oss << "LSHSearch::Search(): dimensionality of query set (" - << querySet.n_rows << ") is not equal to the dimensionality the model " - << "was trained on (" << referenceSet.n_rows << ")!" << std::endl; - throw std::invalid_argument(oss.str()); - } + util::CheckSameDimensionality(querySet, referenceSet, "LSHSearch::Search()", + "query set"); if (k > referenceSet.n_cols) { diff --git a/src/mlpack/methods/range_search/range_search_impl.hpp b/src/mlpack/methods/range_search/range_search_impl.hpp index 03f90b3057..cce20339a3 100644 --- a/src/mlpack/methods/range_search/range_search_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_impl.hpp @@ -312,14 +312,8 @@ void RangeSearch::Search( std::vector>& neighbors, std::vector>& distances) { - if (querySet.n_rows != referenceSet->n_rows) - { - std::ostringstream oss; - oss << "RangeSearch::Search(): dimensionalities of query set (" - << querySet.n_rows << ") and reference set (" << referenceSet->n_rows - << ") do not match!"; - throw std::invalid_argument(oss.str()); - } + util::CheckSameDimensionality(querySet, *referenceSet, + "RangeSearch::Search()", "query set"); // If there are no points, there is no search to be done. if (referenceSet->n_cols == 0) diff --git a/src/mlpack/methods/softmax_regression/softmax_regression.cpp b/src/mlpack/methods/softmax_regression/softmax_regression.cpp index ae39513df6..b269c07690 100644 --- a/src/mlpack/methods/softmax_regression/softmax_regression.cpp +++ b/src/mlpack/methods/softmax_regression/softmax_regression.cpp @@ -11,6 +11,7 @@ */ #include "softmax_regression.hpp" +#include namespace mlpack { namespace regression { @@ -91,13 +92,8 @@ void SoftmaxRegression::Classify(const arma::mat& dataset, arma::mat& probabilities) const { - if (dataset.n_rows != FeatureSize()) - { - std::ostringstream oss; - oss << "SoftmaxRegression::Classify(): dataset has " << dataset.n_rows - << " dimensions, but model has " << FeatureSize() << " dimensions!"; - throw std::invalid_argument(oss.str()); - } + util::CheckSameDimensionality(dataset, FeatureSize(), + "SoftmaxRegression::Classify()"); // Calculate the probabilities for each test input. arma::mat hypothesis; diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index e6dd629266..a384be6825 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -30,8 +30,7 @@ add_executable(mlpack_test det_test.cpp distribution_test.cpp drusilla_select_test.cpp - emst_test.cpp - facilities_test.cpp + emst_test.cpp fastmks_test.cpp feedforward_network_test.cpp gan_test.cpp @@ -98,6 +97,7 @@ add_executable(mlpack_test reward_clipping_test.cpp rl_components_test.cpp scaling_test.cpp + size_checks_test.cpp serialization.cpp serialization.hpp serialization_test.cpp diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp deleted file mode 100644 index 11ee5c68b1..0000000000 --- a/src/mlpack/tests/facilities_test.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file facilities_test.cpp - * @author Khizir Siddiqui - * @author Bisakh Mondal - * - * Test file for Utility facilities. - * - * 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 - -#include "catch.hpp" - -using namespace mlpack; -using namespace mlpack::cv; -using namespace mlpack::util; - -BOOST_AUTO_TEST_SUITE(FacilityTest); - -/** - * The unequal sizes for data and labels show throw an error. - */ -TEST_CASE("AssertSizesTest", "[FacilitiesTest]") -{ - // Load the dataset. - arma::mat dataset; - if (!data::Load("iris_train.csv", dataset)) - FAIL("Cannot load test dataset iris_train.csv!"); - // Load the labels. - arma::Row labels; - if (!data::Load("iris_test_labels.csv", labels)) - FAIL("Cannot load test dataset iris_test_labels.csv!"); - - REQUIRE_THROWS_AS( - AssertSizes(dataset, labels, "test"), std::invalid_argument); -} - - -/** - * Pairwise distances. - */ -TEST_CASE("PairwiseDistanceTest", "[FacilitiesTest]") -{ - arma::mat X; - X = { { 0, 1, 1, 0, 0 }, - { 0, 1, 2, 0, 0 }, - { 1, 1, 3, 2, 0 } }; - metric::EuclideanDistance metric; - arma::mat dist = PairwiseDistances(X, metric); - REQUIRE(dist(0, 0) == 0); - REQUIRE(dist(1, 0) == Approx(1.41421).epsilon(1e-5)); - REQUIRE(dist(2, 0) == 3); -} - - -/** - * Test that CheckSameSizes() works in different cases. - */ -BOOST_AUTO_TEST_CASE(CheckSizeTest) -{ - arma::mat data = arma::randu(20, 30); - arma::colvec firstLabels = arma::randu(20); - arma::colvec secondLabels = arma::randu(30); - arma::mat thirdLabels = arma::randu(20, 30); - - BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking"), - std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "CC"), - std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "AB"), - std::runtime_error); - - BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, secondLabels, "TestChecking")); - BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, thirdLabels, "TestChecking", - "CC")); -} - - -/** - * Test that CheckSameDimensionality() works in different cases. - */ -BOOST_AUTO_TEST_CASE(CheckDimensionality) -{ - arma::mat dataset = arma::randu(20, 30); - - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, 20, "TestingDim")); - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, 30, "TestingDim", - "C")); - - BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 100, "TestingDim"), - std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 50, "TestingDim", "C"), - std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, 20, "TestingDim", "A"), - std::runtime_error); -} - -BOOST_AUTO_TEST_SUITE_END(); From e6e41199a007fb882d4fda8023e83515417fe7fd Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Tue, 28 Apr 2020 22:07:37 +0530 Subject: [PATCH 043/729] Deletion of Commented out code Done. --- .../decision_tree/decision_tree_impl.hpp | 24 ------------------- src/mlpack/tests/size_checks_test.cpp | 4 ++-- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index 8967e88f1b..b99075f5b2 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -511,14 +511,6 @@ double DecisionTree::type; @@ -567,14 +559,6 @@ double DecisionTree::type>::value>*) { // Sanity check on data. - // if (data.n_cols != labels.n_elem) - // { - // std::ostringstream oss; - // oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") " - // << "does not match number of labels (" << labels.n_elem << ")!" - // << std::endl; - // throw std::invalid_argument(oss.str()); - // } util::CheckSameSizes(data, labels, "DecisionTree::Train()"); using TrueMatType = typename std::decay::type; @@ -623,14 +607,6 @@ double DecisionTree::type>::value>*) { // Sanity check on data. - // if (data.n_cols != labels.n_elem) - // { - // std::ostringstream oss; - // oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") " - // << "does not match number of labels (" << labels.n_elem << ")!" - // << std::endl; - // throw std::invalid_argument(oss.str()); - // } util::CheckSameSizes(data, labels, "DecisionTree::Train()"); using TrueMatType = typename std::decay::type; diff --git a/src/mlpack/tests/size_checks_test.cpp b/src/mlpack/tests/size_checks_test.cpp index 44539036b9..d5ca71e6a8 100644 --- a/src/mlpack/tests/size_checks_test.cpp +++ b/src/mlpack/tests/size_checks_test.cpp @@ -54,8 +54,8 @@ BOOST_AUTO_TEST_CASE(CheckDimensionality) BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, refSet2, "TestingDim"), std::invalid_argument); - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, refSet, "TestingDim" - )); + BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, refSet, + "TestingDim")); } BOOST_AUTO_TEST_SUITE_END(); From 7e463525253bcd29fc347821cf78e9b080113595 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Wed, 29 Apr 2020 15:54:43 +0530 Subject: [PATCH 044/729] Updated --- src/mlpack/core/cv/cv_base_impl.hpp | 2 ++ src/mlpack/methods/decision_tree/decision_tree_impl.hpp | 1 + src/mlpack/methods/linear_svm/linear_svm_impl.hpp | 1 + src/mlpack/methods/lsh/lsh_search_impl.hpp | 1 + src/mlpack/methods/range_search/range_search_impl.hpp | 1 + 5 files changed, 6 insertions(+) diff --git a/src/mlpack/core/cv/cv_base_impl.hpp b/src/mlpack/core/cv/cv_base_impl.hpp index fc819603db..e5df5d8bca 100644 --- a/src/mlpack/core/cv/cv_base_impl.hpp +++ b/src/mlpack/core/cv/cv_base_impl.hpp @@ -12,6 +12,8 @@ #ifndef MLPACK_CORE_CV_CV_BASE_IMPL_HPP #define MLPACK_CORE_CV_CV_BASE_IMPL_HPP +#include + namespace mlpack { namespace cv { diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index b99075f5b2..171675a84b 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -13,6 +13,7 @@ #define MLPACK_METHODS_DECISION_TREE_DECISION_TREE_IMPL_HPP #include "decision_tree.hpp" +#include namespace mlpack { namespace tree { diff --git a/src/mlpack/methods/linear_svm/linear_svm_impl.hpp b/src/mlpack/methods/linear_svm/linear_svm_impl.hpp index 69f0887f9d..db7275eff8 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_impl.hpp +++ b/src/mlpack/methods/linear_svm/linear_svm_impl.hpp @@ -14,6 +14,7 @@ // In case it hasn't been included yet. #include "linear_svm.hpp" +#include namespace mlpack { namespace svm { diff --git a/src/mlpack/methods/lsh/lsh_search_impl.hpp b/src/mlpack/methods/lsh/lsh_search_impl.hpp index 6c3aeb8259..0eb69d850b 100644 --- a/src/mlpack/methods/lsh/lsh_search_impl.hpp +++ b/src/mlpack/methods/lsh/lsh_search_impl.hpp @@ -14,6 +14,7 @@ #include #include +#include namespace mlpack { namespace neighbor { diff --git a/src/mlpack/methods/range_search/range_search_impl.hpp b/src/mlpack/methods/range_search/range_search_impl.hpp index cce20339a3..0a8162301b 100644 --- a/src/mlpack/methods/range_search/range_search_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_impl.hpp @@ -17,6 +17,7 @@ // The rules for traversal. #include "range_search_rules.hpp" +#include namespace mlpack { namespace range { From 30299c0f039c64615576cc9edc6786fc03449e32 Mon Sep 17 00:00:00 2001 From: Bisakh Date: Wed, 24 Feb 2021 20:36:11 +0530 Subject: [PATCH 045/729] Two new utility APIs introduced --- src/mlpack/core.hpp | 1 - src/mlpack/core/cv/cv_base_impl.hpp | 14 +--- src/mlpack/core/cv/metrics/CMakeLists.txt | 1 + src/mlpack/core/cv/metrics/accuracy.hpp | 1 + src/mlpack/core/cv/metrics/facilities.hpp | 73 +++++++++++++++++++ src/mlpack/core/cv/metrics/mse_impl.hpp | 2 +- src/mlpack/core/cv/metrics/r2_score_impl.hpp | 2 +- src/mlpack/core/util/size_checks.hpp | 47 +++++++----- .../decision_tree/decision_tree_impl.hpp | 1 - .../methods/linear_svm/linear_svm_impl.hpp | 1 - src/mlpack/methods/lsh/lsh_search_impl.hpp | 1 - .../range_search/range_search_impl.hpp | 1 - .../softmax_regression/softmax_regression.cpp | 1 - src/mlpack/prereqs.hpp | 3 + src/mlpack/tests/CMakeLists.txt | 3 +- src/mlpack/tests/facilities_test.cpp | 56 ++++++++++++++ src/mlpack/tests/size_checks_test.cpp | 34 ++++----- 17 files changed, 184 insertions(+), 58 deletions(-) create mode 100644 src/mlpack/core/cv/metrics/facilities.hpp create mode 100644 src/mlpack/tests/facilities_test.cpp diff --git a/src/mlpack/core.hpp b/src/mlpack/core.hpp index c4522ba05f..34cf60dd09 100644 --- a/src/mlpack/core.hpp +++ b/src/mlpack/core.hpp @@ -90,7 +90,6 @@ #include #include #include -#include // mlpack::backtrace only for linux #ifdef HAS_BFD_DL diff --git a/src/mlpack/core/cv/cv_base_impl.hpp b/src/mlpack/core/cv/cv_base_impl.hpp index e5df5d8bca..0da9f8f4fa 100644 --- a/src/mlpack/core/cv/cv_base_impl.hpp +++ b/src/mlpack/core/cv/cv_base_impl.hpp @@ -12,7 +12,7 @@ #ifndef MLPACK_CORE_CV_CV_BASE_IMPL_HPP #define MLPACK_CORE_CV_CV_BASE_IMPL_HPP -#include +#include namespace mlpack { namespace cv { @@ -108,7 +108,7 @@ void CVBase::AssertDataConsistency(const MatType& xs, const PredictionsType& ys) { - util::CheckSameSizes(xs, ys, "CVBase::AssertDataConsistency()", "CC", + util::CheckSameSizes(xs, (size_t) ys.n_cols, "CVBase::AssertDataConsistency()", "predictions"); } @@ -125,14 +125,8 @@ void CVBase +#include namespace mlpack { namespace cv { diff --git a/src/mlpack/core/cv/metrics/facilities.hpp b/src/mlpack/core/cv/metrics/facilities.hpp new file mode 100644 index 0000000000..4cd2a8f36e --- /dev/null +++ b/src/mlpack/core/cv/metrics/facilities.hpp @@ -0,0 +1,73 @@ +/** + * @file core/cv/metrics/facilities.hpp + * @author Kirill Mishchenko + * @author Khizir Siddiqui + * + * Functionality that is used more than in one metric. + * + * 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_CORE_CV_METRICS_FACILITIES_HPP +#define MLPACK_CORE_CV_METRICS_FACILITIES_HPP + +#include +#include + +namespace mlpack { +namespace cv { + +/** + * Assert there is the same number of the given data points and labels. + * + * @param data Column-major data. + * @param labels Labels. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @deprecated Check the new versions, util::CheckSameSizes & + * util::CheckSameDimensionality. + */ +template +void AssertSizes(const DataType& data, + const arma::Row& labels, + const std::string& callerDescription) +{ + if (data.n_cols != labels.n_elem) + { + std::ostringstream oss; + oss << callerDescription << ": number of points (" << data.n_cols << ") " + << "does not match number of labels (" << labels.n_elem << ")!" + << std::endl; + throw std::invalid_argument(oss.str()); + } +} + +/** + * Pairwise distance of the given data. + * + * @param data Column-major matrix. + * @param metric Distance metric to be used. + */ +template +DataType PairwiseDistances(const DataType& data, + const Metric& metric) +{ + DataType distances = DataType(data.n_cols, data.n_cols, arma::fill::none); + for (size_t i = 0; i < data.n_cols; i++) + { + for (size_t j = 0; j < i; j++) + { + distances(i, j) = metric.Evaluate(data.col(i), data.col(j)); + distances(j, i) = distances(i, j); + } + } + distances.diag().zeros(); + return distances; +} + +} // namespace cv +} // namespace mlpack + +#endif diff --git a/src/mlpack/core/cv/metrics/mse_impl.hpp b/src/mlpack/core/cv/metrics/mse_impl.hpp index a55a0e7ed0..d4eb83cd97 100644 --- a/src/mlpack/core/cv/metrics/mse_impl.hpp +++ b/src/mlpack/core/cv/metrics/mse_impl.hpp @@ -20,7 +20,7 @@ double MSE::Evaluate(MLAlgorithm& model, const DataType& data, const ResponsesType& responses) { - util::CheckSameSizes(data, responses, "MSE::Evaluate()", "CC", "responses"); + util::CheckSameSizes(data,(size_t) responses.n_cols, "MSE::Evaluate()", "responses"); ResponsesType predictedResponses; model.Predict(data, predictedResponses); diff --git a/src/mlpack/core/cv/metrics/r2_score_impl.hpp b/src/mlpack/core/cv/metrics/r2_score_impl.hpp index dad46216eb..bb3d491447 100644 --- a/src/mlpack/core/cv/metrics/r2_score_impl.hpp +++ b/src/mlpack/core/cv/metrics/r2_score_impl.hpp @@ -21,7 +21,7 @@ double R2Score::Evaluate(MLAlgorithm& model, const DataType& data, const ResponsesType& responses) { - util::CheckSameSizes(data, responses, "R2Score::Evaluate()", "CC", + util::CheckSameSizes(data,(size_t) responses.n_cols, "R2Score::Evaluate()", "responses"); ResponsesType predictedResponses; diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp index 318de15567..ee06e29214 100644 --- a/src/mlpack/core/util/size_checks.hpp +++ b/src/mlpack/core/util/size_checks.hpp @@ -25,37 +25,45 @@ namespace util { * @param labels Labels. * @param callerDescription A description of the caller that can be used for * error generation. - * @param mode For nature of comparision(default "CE"). - * types of mode: - * "CE" equivalent to (data.n_cols, labels.n_elem). - * "CC" equivalent to (data.n_cols, labels.n_cols). - * @param addInfo An additional information about labels that can be used for + * @param addInfo Additional information about labels that can be used for * precise error generation. Default is "labels". Another e.g. weights */ template inline void CheckSameSizes(const DataType& data, - const LabelsType& labels, + const LabelsType& label, const std::string& callerDescription, - const std::string& mode = "CE", const std::string& addInfo = "labels") { - if (mode != "CE" && mode != "CC") - // For development purpose, not intended for user. - Log::Fatal << "Ensure Providing Correct mode." << std::endl; - - const size_t size1 = data.n_cols; - const size_t size2 = mode == "CE" ? labels.n_elem : labels.n_cols; - - if (size1 != size2) + if (data.n_cols != label.n_elem) { std::ostringstream oss; - oss << callerDescription << ": number of points (" << size1 << ") " - << "does not match number of " << addInfo << " (" << size2 << ")!" + oss << callerDescription << ": number of points (" << data.n_cols << ") " + << "does not match number of " << addInfo << " (" << label.n_elem << ")!" << std::endl; throw std::invalid_argument(oss.str()); } } +/** An overload of CheckSameSizes() where the size to be checked is known + * previously. The second parameter is of type unsigned int. + */ +template +inline void CheckSameSizes(const DataType& data, + const size_t& size, + const std::string& callerDescription, + const std::string& addInfo = "labels") +{ + if (data.n_cols != size) + { + std::ostringstream oss; + oss << callerDescription << ": number of points (" << data.n_cols << ") " + << "does not match number of " << addInfo << " (" << size << ")!" + << std::endl; + throw std::invalid_argument(oss.str()); + } +} + + /** * Check for if the given dataset dimension matches with the model's. * @@ -83,8 +91,9 @@ inline void CheckSameDimensionality(const DataType& data, } } -// An overload of CheckSameDimensionality() where second param is unsigned -// long int. +/** An overload of CheckSameDimensionality() where the dimension to be checked + * is known second param is unsigned long int. + */ template inline void CheckSameDimensionality(const DataType& data, const size_t& dimension, diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index 171675a84b..b99075f5b2 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -13,7 +13,6 @@ #define MLPACK_METHODS_DECISION_TREE_DECISION_TREE_IMPL_HPP #include "decision_tree.hpp" -#include namespace mlpack { namespace tree { diff --git a/src/mlpack/methods/linear_svm/linear_svm_impl.hpp b/src/mlpack/methods/linear_svm/linear_svm_impl.hpp index db7275eff8..69f0887f9d 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_impl.hpp +++ b/src/mlpack/methods/linear_svm/linear_svm_impl.hpp @@ -14,7 +14,6 @@ // In case it hasn't been included yet. #include "linear_svm.hpp" -#include namespace mlpack { namespace svm { diff --git a/src/mlpack/methods/lsh/lsh_search_impl.hpp b/src/mlpack/methods/lsh/lsh_search_impl.hpp index 0eb69d850b..6c3aeb8259 100644 --- a/src/mlpack/methods/lsh/lsh_search_impl.hpp +++ b/src/mlpack/methods/lsh/lsh_search_impl.hpp @@ -14,7 +14,6 @@ #include #include -#include namespace mlpack { namespace neighbor { diff --git a/src/mlpack/methods/range_search/range_search_impl.hpp b/src/mlpack/methods/range_search/range_search_impl.hpp index 0a8162301b..cce20339a3 100644 --- a/src/mlpack/methods/range_search/range_search_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_impl.hpp @@ -17,7 +17,6 @@ // The rules for traversal. #include "range_search_rules.hpp" -#include namespace mlpack { namespace range { diff --git a/src/mlpack/methods/softmax_regression/softmax_regression.cpp b/src/mlpack/methods/softmax_regression/softmax_regression.cpp index b269c07690..567241b35a 100644 --- a/src/mlpack/methods/softmax_regression/softmax_regression.cpp +++ b/src/mlpack/methods/softmax_regression/softmax_regression.cpp @@ -11,7 +11,6 @@ */ #include "softmax_regression.hpp" -#include namespace mlpack { namespace regression { diff --git a/src/mlpack/prereqs.hpp b/src/mlpack/prereqs.hpp index 4ec1031235..5eb9ee6fd7 100644 --- a/src/mlpack/prereqs.hpp +++ b/src/mlpack/prereqs.hpp @@ -140,4 +140,7 @@ or upgrade Boost to 1.59 or newer. // We need to be able to mark functions deprecated. #include +// Include ready to use utility function for better workflow. +#include + #endif diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index a384be6825..cf9628eea3 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -30,7 +30,8 @@ add_executable(mlpack_test det_test.cpp distribution_test.cpp drusilla_select_test.cpp - emst_test.cpp + emst_test.cpp + facilities_test.cpp fastmks_test.cpp feedforward_network_test.cpp gan_test.cpp diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp new file mode 100644 index 0000000000..65b754bb4e --- /dev/null +++ b/src/mlpack/tests/facilities_test.cpp @@ -0,0 +1,56 @@ +/** + * @file facilities_test.cpp + * @author Khizir Siddiqui + * + * Test file for facilities in metrics. + * + * 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 "catch.hpp" + +using namespace mlpack; +using namespace mlpack::cv; + +/** + * The unequal sizes for data and labels show throw an error. + */ +TEST_CASE("AssertSizesTest", "[FacilitiesTest]") +{ + // Load the dataset. + arma::mat dataset; + if (!data::Load("iris_train.csv", dataset)) + FAIL("Cannot load test dataset iris_train.csv!"); + // Load the labels. + arma::Row labels; + if (!data::Load("iris_test_labels.csv", labels)) + FAIL("Cannot load test dataset iris_test_labels.csv!"); + + REQUIRE_THROWS_AS( + AssertSizes(dataset, labels, "test"), std::invalid_argument); +} + + +/** + * Pairwise distances. + */ +TEST_CASE("PairwiseDistanceTest", "[FacilitiesTest]") +{ + arma::mat X; + X = { { 0, 1, 1, 0, 0 }, + { 0, 1, 2, 0, 0 }, + { 1, 1, 3, 2, 0 } }; + metric::EuclideanDistance metric; + arma::mat dist = PairwiseDistances(X, metric); + REQUIRE(dist(0, 0) == 0); + REQUIRE(dist(1, 0) == Approx(1.41421).epsilon(1e-5)); + REQUIRE(dist(2, 0) == 3); +} diff --git a/src/mlpack/tests/size_checks_test.cpp b/src/mlpack/tests/size_checks_test.cpp index d5ca71e6a8..d5c7f22e46 100644 --- a/src/mlpack/tests/size_checks_test.cpp +++ b/src/mlpack/tests/size_checks_test.cpp @@ -9,54 +9,48 @@ * 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 "catch.hpp" using namespace mlpack; using namespace mlpack::util; -BOOST_AUTO_TEST_SUITE(SizeCheckTest); /** * Test that CheckSameSizes() works in different cases. */ -BOOST_AUTO_TEST_CASE(CheckSizeTest) +TEST_CASE("CheckSizeTest", "[SizeCheckTest]") { arma::mat data = arma::randu(20, 30); arma::colvec firstLabels = arma::randu(20); arma::colvec secondLabels = arma::randu(30); - arma::mat thirdLabels = arma::randu(20, 30); + arma::mat thirdLabels = arma::randu(40, 30); - BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking"), + REQUIRE_THROWS_AS(CheckSameSizes(data, firstLabels, "TestChecking"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "CC"), + REQUIRE_THROWS_AS(CheckSameSizes(data, (size_t) 20, "TestChecking"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameSizes(data, firstLabels, "TestChecking", "AB"), - std::runtime_error); - BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, secondLabels, "TestChecking")); - BOOST_REQUIRE_NO_THROW(CheckSameSizes(data, thirdLabels, "TestChecking", - "CC")); + REQUIRE_NOTHROW(CheckSameSizes(data, secondLabels, "TestChecking")); + REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) 30, "TestChecking")); + REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) thirdLabels.n_cols, "TestChecking")); } /** * Test that CheckSameDimensionality() works in different cases. */ -BOOST_AUTO_TEST_CASE(CheckDimensionality) +TEST_CASE("CheckDimensionality", "[SizeCheckTest]") { arma::mat dataset = arma::randu(20, 30); arma::colvec refSet = arma::randu(20); arma::colvec refSet2 = arma::randu(40); - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, (size_t) 20, + REQUIRE_NOTHROW(CheckSameDimensionality(dataset, (size_t) 20, "TestingDim")); - BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, (size_t) 100, + REQUIRE_THROWS_AS(CheckSameDimensionality(dataset, (size_t) 100, "TestingDim"), std::invalid_argument); - BOOST_REQUIRE_THROW(CheckSameDimensionality(dataset, refSet2, "TestingDim"), + REQUIRE_THROWS_AS(CheckSameDimensionality(dataset, refSet2, "TestingDim"), std::invalid_argument); - BOOST_REQUIRE_NO_THROW(CheckSameDimensionality(dataset, refSet, + REQUIRE_NOTHROW(CheckSameDimensionality(dataset, refSet, "TestingDim")); } - -BOOST_AUTO_TEST_SUITE_END(); - From de67fb4faae8f7e31c3fd38daf4f9b7428f428af Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Wed, 24 Feb 2021 20:39:50 +0530 Subject: [PATCH 046/729] Grammar fix as suggested by @rcurtin Co-authored-by: Ryan Curtin --- src/mlpack/core/util/size_checks.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp index ee06e29214..1ef5555749 100644 --- a/src/mlpack/core/util/size_checks.hpp +++ b/src/mlpack/core/util/size_checks.hpp @@ -71,7 +71,7 @@ inline void CheckSameSizes(const DataType& data, * @param dimension Dimension of the model. * @param callerDescription A description of the caller that can be used for * error generation. - * @param addInfo An additional information about data that can be used for + * @param addInfo Additional information about data that can be used for * precise error generation. Default is "dataset". Another e.g. weights. */ template @@ -114,4 +114,3 @@ inline void CheckSameDimensionality(const DataType& data, } // namespace mlpack #endif - From c474e30378cfed52f5c03d664e69a0a03a8b8c0a Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Sat, 27 Feb 2021 21:49:20 +0530 Subject: [PATCH 047/729] Applying suggestions from code review by @rcurtin Co-authored-by: Ryan Curtin --- src/mlpack/core/cv/metrics/mse_impl.hpp | 3 +- src/mlpack/core/cv/metrics/r2_score_impl.hpp | 2 +- src/mlpack/core/util/size_checks.hpp | 42 ++++++++++---------- src/mlpack/prereqs.hpp | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/mlpack/core/cv/metrics/mse_impl.hpp b/src/mlpack/core/cv/metrics/mse_impl.hpp index d4eb83cd97..d2fdcf8e74 100644 --- a/src/mlpack/core/cv/metrics/mse_impl.hpp +++ b/src/mlpack/core/cv/metrics/mse_impl.hpp @@ -20,7 +20,8 @@ double MSE::Evaluate(MLAlgorithm& model, const DataType& data, const ResponsesType& responses) { - util::CheckSameSizes(data,(size_t) responses.n_cols, "MSE::Evaluate()", "responses"); + util::CheckSameSizes(data, (size_t) responses.n_cols, "MSE::Evaluate()", + "responses"); ResponsesType predictedResponses; model.Predict(data, predictedResponses); diff --git a/src/mlpack/core/cv/metrics/r2_score_impl.hpp b/src/mlpack/core/cv/metrics/r2_score_impl.hpp index bb3d491447..00eb9a1448 100644 --- a/src/mlpack/core/cv/metrics/r2_score_impl.hpp +++ b/src/mlpack/core/cv/metrics/r2_score_impl.hpp @@ -21,7 +21,7 @@ double R2Score::Evaluate(MLAlgorithm& model, const DataType& data, const ResponsesType& responses) { - util::CheckSameSizes(data,(size_t) responses.n_cols, "R2Score::Evaluate()", + util::CheckSameSizes(data, (size_t) responses.n_cols, "R2Score::Evaluate()", "responses"); ResponsesType predictedResponses; diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp index 1ef5555749..933655f475 100644 --- a/src/mlpack/core/util/size_checks.hpp +++ b/src/mlpack/core/util/size_checks.hpp @@ -19,15 +19,15 @@ namespace mlpack { namespace util { /** - * Check for if the given data points & labels have same size. - * - * @param data data. - * @param labels Labels. - * @param callerDescription A description of the caller that can be used for - * error generation. - * @param addInfo Additional information about labels that can be used for - * precise error generation. Default is "labels". Another e.g. weights - */ + * Check for if the given data points & labels have same size. + * + * @param data data. + * @param labels Labels. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @param addInfo Name to use for labels for precise error generation. Default + * is "labels"; for example, "weights" could also be used. + */ template inline void CheckSameSizes(const DataType& data, const LabelsType& label, @@ -44,7 +44,8 @@ inline void CheckSameSizes(const DataType& data, } } -/** An overload of CheckSameSizes() where the size to be checked is known +/** + * An overload of CheckSameSizes() where the size to be checked is known * previously. The second parameter is of type unsigned int. */ template @@ -65,15 +66,15 @@ inline void CheckSameSizes(const DataType& data, /** - * Check for if the given dataset dimension matches with the model's. - * - * @param data dataset. - * @param dimension Dimension of the model. - * @param callerDescription A description of the caller that can be used for - * error generation. - * @param addInfo Additional information about data that can be used for - * precise error generation. Default is "dataset". Another e.g. weights. - */ + * Check for if the given dataset dimension matches with the model's. + * + * @param data dataset. + * @param dimension Dimension of the model. + * @param callerDescription A description of the caller that can be used for + * error generation. + * @param addInfo Name to use for dataset for precise error generation. Default + * is "dataset"; for example, "weights" could also be used. + */ template inline void CheckSameDimensionality(const DataType& data, const DimType& dimension, @@ -91,7 +92,8 @@ inline void CheckSameDimensionality(const DataType& data, } } -/** An overload of CheckSameDimensionality() where the dimension to be checked +/** + * An overload of CheckSameDimensionality() where the dimension to be checked * is known second param is unsigned long int. */ template diff --git a/src/mlpack/prereqs.hpp b/src/mlpack/prereqs.hpp index 5eb9ee6fd7..1d049d711c 100644 --- a/src/mlpack/prereqs.hpp +++ b/src/mlpack/prereqs.hpp @@ -140,7 +140,7 @@ or upgrade Boost to 1.59 or newer. // We need to be able to mark functions deprecated. #include -// Include ready to use utility function for better workflow. +// Include ready to use utility function to check sizes of datasets. #include #endif From 970588c5daa9f15173c833be60558d5b8561e6f2 Mon Sep 17 00:00:00 2001 From: Bisakh Date: Sat, 27 Feb 2021 22:46:50 +0530 Subject: [PATCH 048/729] AssertSizes api has been replaced by CheckSameSizes --- src/mlpack/core/cv/metrics/facilities.hpp | 25 ------------------- .../core/cv/metrics/silhouette_score_impl.hpp | 6 ++--- src/mlpack/tests/facilities_test.cpp | 19 -------------- 3 files changed, 3 insertions(+), 47 deletions(-) diff --git a/src/mlpack/core/cv/metrics/facilities.hpp b/src/mlpack/core/cv/metrics/facilities.hpp index 4cd2a8f36e..fdd5b1216a 100644 --- a/src/mlpack/core/cv/metrics/facilities.hpp +++ b/src/mlpack/core/cv/metrics/facilities.hpp @@ -19,31 +19,6 @@ namespace mlpack { namespace cv { -/** - * Assert there is the same number of the given data points and labels. - * - * @param data Column-major data. - * @param labels Labels. - * @param callerDescription A description of the caller that can be used for - * error generation. - * @deprecated Check the new versions, util::CheckSameSizes & - * util::CheckSameDimensionality. - */ -template -void AssertSizes(const DataType& data, - const arma::Row& labels, - const std::string& callerDescription) -{ - if (data.n_cols != labels.n_elem) - { - std::ostringstream oss; - oss << callerDescription << ": number of points (" << data.n_cols << ") " - << "does not match number of labels (" << labels.n_elem << ")!" - << std::endl; - throw std::invalid_argument(oss.str()); - } -} - /** * Pairwise distance of the given data. * diff --git a/src/mlpack/core/cv/metrics/silhouette_score_impl.hpp b/src/mlpack/core/cv/metrics/silhouette_score_impl.hpp index 89041f736e..b271f0d6df 100644 --- a/src/mlpack/core/cv/metrics/silhouette_score_impl.hpp +++ b/src/mlpack/core/cv/metrics/silhouette_score_impl.hpp @@ -22,7 +22,7 @@ double SilhouetteScore::Overall(const DataType& X, const arma::Row& labels, const Metric& metric) { - AssertSizes(X, labels, "SilhouetteScore::Overall()"); + util::CheckSameSizes(X, labels, "SilhouetteScore::Overall()"); return arma::mean(SamplesScore(X, labels, metric)); } @@ -30,7 +30,7 @@ template arma::rowvec SilhouetteScore::SamplesScore(const DataType& distances, const arma::Row& labels) { - AssertSizes(distances, labels, "SilhouetteScore::SamplesScore()"); + util::CheckSameSizes(distances, labels, "SilhouetteScore::SamplesScore()"); // Stores the silhouette scores of individual samples. arma::rowvec sampleScores(distances.n_rows); @@ -76,7 +76,7 @@ arma::rowvec SilhouetteScore::SamplesScore(const DataType& X, const arma::Row& labels, const Metric& metric) { - AssertSizes(X, labels, "SilhouetteScore::SamplesScore()"); + util::CheckSameSizes(X, labels, "SilhouetteScore::SamplesScore()"); DataType distances = PairwiseDistances(X, metric); return SamplesScore(distances, labels); } diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp index 65b754bb4e..d4bcec3c3b 100644 --- a/src/mlpack/tests/facilities_test.cpp +++ b/src/mlpack/tests/facilities_test.cpp @@ -20,25 +20,6 @@ using namespace mlpack; using namespace mlpack::cv; -/** - * The unequal sizes for data and labels show throw an error. - */ -TEST_CASE("AssertSizesTest", "[FacilitiesTest]") -{ - // Load the dataset. - arma::mat dataset; - if (!data::Load("iris_train.csv", dataset)) - FAIL("Cannot load test dataset iris_train.csv!"); - // Load the labels. - arma::Row labels; - if (!data::Load("iris_test_labels.csv", labels)) - FAIL("Cannot load test dataset iris_test_labels.csv!"); - - REQUIRE_THROWS_AS( - AssertSizes(dataset, labels, "test"), std::invalid_argument); -} - - /** * Pairwise distances. */ From bf238ed213d2d09dfeae40c506f57402d6e04293 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 27 Feb 2021 16:09:13 -0500 Subject: [PATCH 049/729] Don't take a second argument for ToLower(). --- src/mlpack/core/util/to_lower.hpp | 5 +++-- src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp | 3 +-- src/mlpack/methods/ann/layer/convolution_impl.hpp | 3 +-- src/mlpack/methods/ann/layer/transposed_convolution_impl.hpp | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/mlpack/core/util/to_lower.hpp b/src/mlpack/core/util/to_lower.hpp index 866b160ffd..98f46de9b5 100644 --- a/src/mlpack/core/util/to_lower.hpp +++ b/src/mlpack/core/util/to_lower.hpp @@ -19,12 +19,13 @@ namespace util {  * Convert a string to lowercase letters.  *  * @param input The string to convert. - * @param output The string to be converted.  */ -inline void ToLower(const std::string& input, std::string& output) +inline std::string ToLower(const std::string& input) { + std::string output; std::transform(input.begin(), input.end(), output.begin(), [](unsigned char c){ return std::tolower(c); }); + return output; } } // namespace util diff --git a/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp b/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp index cfb200e3ec..2377ddee00 100644 --- a/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp +++ b/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp @@ -125,8 +125,7 @@ AtrousConvolution< weights.set_size(WeightSize(), 1); // Transform paddingType to lowercase. - std::string paddingTypeLow = paddingType; - util::ToLower(paddingType, paddingTypeLow); + const std::string paddingTypeLow = util::ToLower(paddingType); size_t padWLeft = std::get<0>(padW); size_t padWRight = std::get<1>(padW); diff --git a/src/mlpack/methods/ann/layer/convolution_impl.hpp b/src/mlpack/methods/ann/layer/convolution_impl.hpp index 5018593279..7e6cebf184 100644 --- a/src/mlpack/methods/ann/layer/convolution_impl.hpp +++ b/src/mlpack/methods/ann/layer/convolution_impl.hpp @@ -120,8 +120,7 @@ Convolution< weights.set_size(WeightSize(), 1); // Transform paddingType to lowercase. - std::string paddingTypeLow = paddingType; - util::ToLower(paddingType, paddingTypeLow); + const std::string paddingTypeLow = util::ToLower(paddingType); if (paddingTypeLow == "valid") { diff --git a/src/mlpack/methods/ann/layer/transposed_convolution_impl.hpp b/src/mlpack/methods/ann/layer/transposed_convolution_impl.hpp index 47cf2cd6c8..d932acb6a7 100644 --- a/src/mlpack/methods/ann/layer/transposed_convolution_impl.hpp +++ b/src/mlpack/methods/ann/layer/transposed_convolution_impl.hpp @@ -126,8 +126,7 @@ TransposedConvolution< { weights.set_size(WeightSize(), 1); // Transform paddingType to lowercase. - std::string paddingTypeLow = paddingType; - util::ToLower(paddingType, paddingTypeLow); + const std::string paddingTypeLow = util::ToLower(paddingType); if (paddingTypeLow == "valid") { From 355e6db33a2b187e9b06aa780a725aadc267320b Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 27 Feb 2021 16:50:39 -0500 Subject: [PATCH 050/729] Oops, use std::back_inserter(). --- src/mlpack/core/util/to_lower.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/util/to_lower.hpp b/src/mlpack/core/util/to_lower.hpp index 98f46de9b5..f427449baf 100644 --- a/src/mlpack/core/util/to_lower.hpp +++ b/src/mlpack/core/util/to_lower.hpp @@ -23,7 +23,7 @@ namespace util { inline std::string ToLower(const std::string& input) { std::string output; - std::transform(input.begin(), input.end(), output.begin(), + std::transform(input.begin(), input.end(), std::back_inserter(output), [](unsigned char c){ return std::tolower(c); }); return output; } From 12333a6b8b797807e658a5d513ead0e4148c0266 Mon Sep 17 00:00:00 2001 From: Bisakh Mondal Date: Sun, 28 Feb 2021 05:46:51 +0530 Subject: [PATCH 051/729] Update src/mlpack/core/util/size_checks.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/util/size_checks.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp index 933655f475..ab81a9b355 100644 --- a/src/mlpack/core/util/size_checks.hpp +++ b/src/mlpack/core/util/size_checks.hpp @@ -13,7 +13,6 @@ #ifndef MLPACK_UTIL_SIZE_CHECKS_HPP #define MLPACK_UTIL_SIZE_CHECKS_HPP -#include namespace mlpack { namespace util { From 6800e5a05885b15fadaf905cdce2ad156a866f65 Mon Sep 17 00:00:00 2001 From: Gopi M Tatiraju Date: Mon, 1 Mar 2021 15:34:06 +0530 Subject: [PATCH 052/729] Apply suggestions from code review Co-authored-by: Marcus Edel --- src/mlpack/tests/feedforward_network_2_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/tests/feedforward_network_2_test.cpp b/src/mlpack/tests/feedforward_network_2_test.cpp index 3a57624d26..90ba3c3fbd 100644 --- a/src/mlpack/tests/feedforward_network_2_test.cpp +++ b/src/mlpack/tests/feedforward_network_2_test.cpp @@ -66,7 +66,7 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") // Load the dataset. arma::mat trainData; if (!data::Load("thyroid_train.csv", trainData)) - Fail("Cannot open thyroid_train.csv"); + FAIL("Cannot open thyroid_train.csv"); arma::mat trainLabels = trainData.row(trainData.n_rows - 1); trainData.shed_row(trainData.n_rows - 1); @@ -79,7 +79,7 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") arma::mat testData; if (!data::Load("thyroid_test.csv", testData)) - Fail("Cannot open thyroid_test.csv"); + FAIL("Cannot open thyroid_test.csv"); arma::mat testLabels = testData.row(testData.n_rows - 1); testData.shed_row(testData.n_rows - 1); @@ -139,4 +139,4 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") // RBFN neural net with MeanSquaredError. TestNetwork<>(model1, dataset, labels1, dataset, labels, 10, 0.1); -} \ No newline at end of file +} From f33f003c3e9d9ea0d8906706e47be92dd9f98c58 Mon Sep 17 00:00:00 2001 From: onikolskyy Date: Mon, 1 Mar 2021 15:03:08 +0100 Subject: [PATCH 053/729] fix default values of cmake config for bindings in docs --- doc/guide/build.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index d889652e81..9996f5132d 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -175,9 +175,13 @@ The full list of options mlpack allows: (i.e. \c mlpack_knn, \c mlpack_kfn, \c mlpack_logistic_regression, etc.) (default ON) - BUILD_PYTHON_BINDINGS=(ON/OFF): compile the bindings for Python, if the - necessary Python libraries are available (default ON except on Windows) + necessary Python libraries are available (default OFF) + - BUILD_R_BINDINGS=(ON/OFF): compile the bindings for R, if R is found + (default OFF) + - BUILD_GO_BINDINGS=(ON/OFF): compile Go bindings, if Go and the necessary Go + and Gonum exist. (default OFF) - BUILD_JULIA_BINDINGS=(ON/OFF): compile Julia bindings, if Julia is found - (default ON) + (default OFF) - BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to static libraries (default ON) - TEST_VERBOSE=(ON/OFF): run test cases in \c mlpack_test with verbose output From 89163f648332d7c8a1d7137ea4c17bb01e5b3274 Mon Sep 17 00:00:00 2001 From: RishabhGarg108 Date: Tue, 2 Mar 2021 13:01:13 +0530 Subject: [PATCH 054/729] Templated labels for field labels --- src/mlpack/core/data/split_data.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index da4c240ca2..61f9860f54 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -405,16 +405,16 @@ Split(const arma::Mat& input, * @param shuffleData If true, the sample order is shuffled; otherwise, each * sample is visited in linear order. (Default true.) */ -template ::value || arma::is_Mat_only::value>> void Split(const FieldType& input, - const arma::field& inputLabel, + const arma::field& inputLabel, FieldType& trainData, - arma::field& trainLabel, + arma::field& trainLabel, FieldType& testData, - arma::field& testLabel, + arma::field& testLabel, const double testRatio, const bool shuffleData = true) { @@ -574,20 +574,20 @@ void Split(const FieldType& input, * (FieldType), trainLabel (arma::field), and * testLabel (arma::field). */ -template ::value || arma::is_Mat_only::value>> -std::tuple, arma::field> +std::tuple, arma::field> Split(const FieldType& input, - const arma::field& inputLabel, + const arma::field& inputLabel, const double testRatio, const bool shuffleData = true) { FieldType trainData; FieldType testData; - arma::field trainLabel; - arma::field testLabel; + arma::field trainLabel; + arma::field testLabel; Split(input, inputLabel, trainData, trainLabel, testData, testLabel, testRatio, shuffleData); From 9bffdb6d6e15e82d8b14ad3489909aa7c7b6657f Mon Sep 17 00:00:00 2001 From: Tru Hoang Date: Tue, 2 Mar 2021 13:51:51 -0800 Subject: [PATCH 055/729] Add CMake linking for OpenMP . Fixes build error for macOS 10.15 Catalina (#2412) * Update CMakeLists for macOS Catalina build * The XCode switch is probably not necessary with the new version. * Test OpenMP on macOS 10.15. * Update CMakeLists.txt Add guard condition for OpenMP_CXX_LIBRARIES for compatible CMake versions Co-authored-by: Ryan Birmingham * Update CMakeLists.txt Add endif() Co-authored-by: Ryan Birmingham * export OMP_NUM_THREADS in CI script * Empty commit to set up deployments * Use macOS latest image. * Add name to list of contributors Co-authored-by: Marcus Edel Co-authored-by: Ryan Birmingham --- .ci/macos-steps.yaml | 4 ++-- CMakeLists.txt | 3 +++ COPYRIGHT.txt | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.ci/macos-steps.yaml b/.ci/macos-steps.yaml index 85e92fe3b3..ce3c7796f5 100644 --- a/.ci/macos-steps.yaml +++ b/.ci/macos-steps.yaml @@ -14,7 +14,7 @@ steps: set -e sudo xcode-select --switch /Applications/Xcode_12.2.app/Contents/Developer unset BOOST_ROOT - brew install openblas armadillo boost cereal + brew install libomp openblas armadillo boost cereal if [ "$(binding)" == "python" ]; then pip install --upgrade pip @@ -65,4 +65,4 @@ steps: inputs: pathtoPublish: 'build/Testing/' artifactName: 'Tests' - displayName: 'Publish artifacts test results' + displayName: 'Publish artifacts test results' \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e0be77df06..2ecd13769c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -467,6 +467,9 @@ if (OPENMP_FOUND) add_definitions(-DHAS_OPENMP) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + if(OpenMP_CXX_FOUND) + set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${OpenMP_CXX_LIBRARIES}) + endif () else () # Disable warnings for all the unknown OpenMP pragmas. if (NOT MSVC) diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index d2d177da71..a3c8f90f38 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -141,6 +141,7 @@ Copyright: Copyright 2020, Alex Nguyen Copyright 2020, Gaurav Ghati Copyright 2020, Anmolpreet Singh + Copyright 2021, Tru Hoang License: BSD-3-clause All rights reserved. From 08d2a6d68db1eb4b7ecc3b043789684b6ab6806e Mon Sep 17 00:00:00 2001 From: Oleksandr Nikolskyy Date: Thu, 4 Mar 2021 20:33:56 +0100 Subject: [PATCH 056/729] add WeightSize() Method for linear_no_bias and radial_basis_function --- src/mlpack/methods/ann/layer/linear_no_bias.hpp | 6 ++++++ src/mlpack/methods/ann/layer/linear_no_bias_impl.hpp | 2 +- src/mlpack/methods/ann/layer/radial_basis_function.hpp | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/linear_no_bias.hpp b/src/mlpack/methods/ann/layer/linear_no_bias.hpp index 7182e84238..5426f1ff4f 100644 --- a/src/mlpack/methods/ann/layer/linear_no_bias.hpp +++ b/src/mlpack/methods/ann/layer/linear_no_bias.hpp @@ -123,6 +123,12 @@ class LinearNoBias //! Modify the gradient. OutputDataType& Gradient() { return gradient; } + //! Get the size of the weights. + size_t WeightSize() const + { + return inSize * outSize; + } + //! Get the shape of the input. size_t InputShape() const { diff --git a/src/mlpack/methods/ann/layer/linear_no_bias_impl.hpp b/src/mlpack/methods/ann/layer/linear_no_bias_impl.hpp index 032552f599..dbea56e94f 100644 --- a/src/mlpack/methods/ann/layer/linear_no_bias_impl.hpp +++ b/src/mlpack/methods/ann/layer/linear_no_bias_impl.hpp @@ -38,7 +38,7 @@ LinearNoBias::LinearNoBias( outSize(outSize), regularizer(regularizer) { - weights.set_size(outSize * inSize, 1); + weights.set_size(WeightSize(), 1); } template Date: Thu, 4 Mar 2021 20:42:12 +0100 Subject: [PATCH 057/729] add WeightSize() Method for constant --- src/mlpack/methods/ann/layer/constant.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mlpack/methods/ann/layer/constant.hpp b/src/mlpack/methods/ann/layer/constant.hpp index b908a0018e..9a0956ddf8 100644 --- a/src/mlpack/methods/ann/layer/constant.hpp +++ b/src/mlpack/methods/ann/layer/constant.hpp @@ -79,6 +79,12 @@ class Constant //! Get the output size. size_t OutSize() const { return outSize; } + //! Get the size of the weights. + size_t WeightSize() const + { + return 0; + } + /** * Serialize the layer. */ From 6e241b33617364876179951d888114a81396c5be Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 5 Mar 2021 00:09:59 -0500 Subject: [PATCH 058/729] Fix anchor links in generated Markdown documentation (#2856) * Use the correct binding name to generate the anchor link. * Fix compilation warnings. --- src/mlpack/bindings/go/print_type_doc_impl.hpp | 2 +- src/mlpack/bindings/markdown/print_docs.cpp | 14 ++++++++++++-- .../simple_residue_termination.hpp | 6 +++--- .../svd_complete_incremental_learning.hpp | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/mlpack/bindings/go/print_type_doc_impl.hpp b/src/mlpack/bindings/go/print_type_doc_impl.hpp index 0755f60b8a..d0a5fef659 100644 --- a/src/mlpack/bindings/go/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/go/print_type_doc_impl.hpp @@ -84,7 +84,7 @@ std::string PrintTypeDoc( */ template std::string PrintTypeDoc( - util::ParamData& data, + util::ParamData& /* data */, const typename std::enable_if::value>::type*) { if (T::is_col || T::is_row) diff --git a/src/mlpack/bindings/markdown/print_docs.cpp b/src/mlpack/bindings/markdown/print_docs.cpp index 45b9807afa..44adf69e93 100644 --- a/src/mlpack/bindings/markdown/print_docs.cpp +++ b/src/mlpack/bindings/markdown/print_docs.cpp @@ -36,8 +36,18 @@ void PrintHeaders(const std::string& bindingName, { BindingInfo::Language() = languages[i]; - cout << " - [" << GetBindingName(bindingName) << "](#" << languages[i] - << "_" << bindingName << "){: .language-link #" << languages[i] << " }" + // Get the name of the binding in the target language, and convert it to + // lowercase (since the anchor link will be in lowercase). + const std::string langBindingName = GetBindingName(bindingName); + std::string anchorName = langBindingName; + std::transform(anchorName.begin(), anchorName.end(), anchorName.begin(), + [](unsigned char c) { return std::tolower(c); }); + // Strip '()' from the end if needed. + if (anchorName.substr(anchorName.size() - 2, 2) == "()") + anchorName = anchorName.substr(0, anchorName.size() - 2); + + cout << " - [" << langBindingName << "](#" << languages[i] + << "_" << anchorName << "){: .language-link #" << languages[i] << " }" << endl; } } diff --git a/src/mlpack/methods/amf/termination_policies/simple_residue_termination.hpp b/src/mlpack/methods/amf/termination_policies/simple_residue_termination.hpp index 86631e32ce..6c214795c4 100644 --- a/src/mlpack/methods/amf/termination_policies/simple_residue_termination.hpp +++ b/src/mlpack/methods/amf/termination_policies/simple_residue_termination.hpp @@ -45,9 +45,9 @@ class SimpleResidueTermination maxIterations(maxIterations), residue(0.0), iteration(0), - nm(0), - normOld(0) - { + normOld(0), + nm(0) + { // Nothing to do here. } diff --git a/src/mlpack/methods/amf/update_rules/svd_complete_incremental_learning.hpp b/src/mlpack/methods/amf/update_rules/svd_complete_incremental_learning.hpp index 37b7ab8c0a..ab2e9d2503 100644 --- a/src/mlpack/methods/amf/update_rules/svd_complete_incremental_learning.hpp +++ b/src/mlpack/methods/amf/update_rules/svd_complete_incremental_learning.hpp @@ -172,7 +172,7 @@ class SVDCompleteIncrementalLearning SVDCompleteIncrementalLearning(double u = 0.01, double kw = 0, double kh = 0) - : u(u), kw(kw), kh(kh), it(NULL), m(0), n(0), isStart(false) + : u(u), kw(kw), kh(kh), n(0), m(0), it(NULL), isStart(false) {} ~SVDCompleteIncrementalLearning() From d53b08d936971531be77a8d3cca2737846d13692 Mon Sep 17 00:00:00 2001 From: Anush V Kini Date: Fri, 5 Mar 2021 13:17:05 +0530 Subject: [PATCH 059/729] Removed loop from bootstrap --- src/mlpack/methods/random_forest/bootstrap.hpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/mlpack/methods/random_forest/bootstrap.hpp b/src/mlpack/methods/random_forest/bootstrap.hpp index fa6e5af6be..abbbbbaa05 100644 --- a/src/mlpack/methods/random_forest/bootstrap.hpp +++ b/src/mlpack/methods/random_forest/bootstrap.hpp @@ -38,13 +38,10 @@ void Bootstrap(const MatType& dataset, // Random sampling with replacement. arma::uvec indices = arma::randi(dataset.n_cols, arma::distr_param(0, dataset.n_cols - 1)); - for (size_t i = 0; i < dataset.n_cols; ++i) - { - bootstrapDataset.col(i) = dataset.col(indices[i]); - bootstrapLabels[i] = labels[indices[i]]; - if (UseWeights) - bootstrapWeights[i] = weights[indices[i]]; - } + bootstrapDataset = dataset.cols(indices); + bootstrapLabels = labels.cols(indices); + if (UseWeights) + bootstrapWeights = weights.cols(indices); } } // namespace tree From 3bd4567bdfbbfe5cbb29bcb76d5c1ef88dc13d1a Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 5 Mar 2021 09:29:29 -0500 Subject: [PATCH 060/729] Add functions to access and modify parameters for training. --- src/mlpack/methods/lars/lars.cpp | 4 ++++ src/mlpack/methods/lars/lars.hpp | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/mlpack/methods/lars/lars.cpp b/src/mlpack/methods/lars/lars.cpp index 03612406fc..16bfa64124 100644 --- a/src/mlpack/methods/lars/lars.cpp +++ b/src/mlpack/methods/lars/lars.cpp @@ -178,6 +178,10 @@ double LARS::Train(const arma::mat& matX, isIgnored.clear(); matUtriCholFactor.reset(); + // Update values in case lambda1 or lambda2 changed. + lasso = (lambda1 != 0); + elasticNet = (lambda1 != 0 && lambda2 != 0); + // This matrix may end up holding the transpose -- if necessary. arma::mat dataTrans; // dataRef is row-major. diff --git a/src/mlpack/methods/lars/lars.hpp b/src/mlpack/methods/lars/lars.hpp index 8989d13e55..d019fec900 100644 --- a/src/mlpack/methods/lars/lars.hpp +++ b/src/mlpack/methods/lars/lars.hpp @@ -249,6 +249,26 @@ class LARS arma::rowvec& predictions, const bool rowMajor = false) const; + //! Get the L1 regularization coefficient. + double Lambda1() const { return lambda1; } + //! Modify the L1 regularization coefficient. + double& Lambda1() { return lambda1; } + + //! Get the L2 regularization coefficient. + double Lambda2() const { return lambda2; } + //! Modify the L2 regularization coefficient. + double& Lambda2() { return lambda2; } + + //! Get whether to use the Cholesky decomposition. + bool UseCholesky() const { return useCholesky; } + //! Modify whether to use the Cholesky decomposition. + bool& UseCholesky() { return useCholesky; } + + //! Get the tolerance for maximum correlation during training. + double Tolerance() const { return tolerance; } + //! Modify the tolerance for maximum correlation during training. + double& Tolerance() { return tolerance; } + //! Access the set of active dimensions. const std::vector& ActiveSet() const { return activeSet; } From b11720c4defe4af59764e5c7d0b768208bb910aa Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 5 Mar 2021 09:31:44 -0500 Subject: [PATCH 061/729] Update history. --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 12692b8308..f0b696d6ac 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -34,6 +34,9 @@ * `NegativeLogLikelihood<>` now expects classes in the range `0` to `numClasses - 1` (#2534). + * Add `Lambda1()`, `Lambda2()`, `UseCholesky()`, and `Tolerance()` members to + `LARS` so parameters for training can be modified (#2861). + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From 5d078b4e173a818e4393c26a73677fd12a63d288 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 5 Mar 2021 18:21:45 -0500 Subject: [PATCH 062/729] Loosen tolerances: AdaBoost does not guarantee better performance than a single weak learner. --- src/mlpack/tests/adaboost_test.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/mlpack/tests/adaboost_test.cpp b/src/mlpack/tests/adaboost_test.cpp index cccf6f42d8..6f584a0f04 100644 --- a/src/mlpack/tests/adaboost_test.cpp +++ b/src/mlpack/tests/adaboost_test.cpp @@ -67,7 +67,7 @@ TEST_CASE("HammingLossBoundIris", "[AdaBoostTest]") /** * This test case runs the AdaBoost.mh algorithm on the UCI Iris dataset. It * checks if the error returned by running a single instance of the weak learner - * is worse than running the boosted weak learner using adaboost. + * close to that of the boosted weak learner using adaboost. */ TEST_CASE("WeakLearnerErrorIris", "[AdaBoostTest]") { @@ -105,7 +105,7 @@ TEST_CASE("WeakLearnerErrorIris", "[AdaBoostTest]") size_t countError = arma::accu(labels != predictedLabels);; double error = (double) countError / labels.n_cols; - REQUIRE(error <= weakLearnerErrorRate); + REQUIRE(error <= weakLearnerErrorRate + 0.03); } /** @@ -151,7 +151,7 @@ TEST_CASE("HammingLossBoundVertebralColumn", "[AdaBoostTest]") /** * This test case runs the AdaBoost.mh algorithm on the UCI Vertebral Column * dataset. It checks if the error returned by running a single instance of the - * weak learner is worse than running the boosted weak learner using adaboost. + * weak learner is close to that of a boosted weak learner using adaboost. */ TEST_CASE("WeakLearnerErrorVertebralColumn", "[AdaBoostTest]") { @@ -187,7 +187,7 @@ TEST_CASE("WeakLearnerErrorVertebralColumn", "[AdaBoostTest]") size_t countError = arma::accu(labels != predictedLabels); double error = (double) countError / labels.n_cols; - REQUIRE(error <= weakLearnerErrorRate); + REQUIRE(error <= weakLearnerErrorRate + 0.03); } /** @@ -233,7 +233,7 @@ TEST_CASE("HammingLossBoundNonLinearSepData", "[AdaBoostTest]") /** * This test case runs the AdaBoost.mh algorithm on a non-linearly separable * dataset. It checks if the error returned by running a single instance of the - * weak learner is worse than running the boosted weak learner using AdaBoost. + * weak learner is close to that of a boosted weak learner using AdaBoost. */ TEST_CASE("WeakLearnerErrorNonLinearSepData", "[AdaBoostTest]") { @@ -269,7 +269,7 @@ TEST_CASE("WeakLearnerErrorNonLinearSepData", "[AdaBoostTest]") size_t countError = arma::accu(labels != predictedLabels); double error = (double) countError / labels.n_cols; - REQUIRE(error == weakLearnerErrorRate); + REQUIRE(error <= weakLearnerErrorRate + 0.03); } /** @@ -314,7 +314,7 @@ TEST_CASE("HammingLossIris_DS", "[AdaBoostTest]") /** * This test case runs the AdaBoost.mh algorithm on a non-linearly separable * dataset. It checks if the error returned by running a single instance of the - * weak learner is worse than running the boosted weak learner using adaboost. + * weak learner is close to that of a boosted weak learner using adaboost. * This is for the weak learner: decision stumps. */ TEST_CASE("WeakLearnerErrorIris_DS", "[AdaBoostTest]") @@ -355,13 +355,13 @@ TEST_CASE("WeakLearnerErrorIris_DS", "[AdaBoostTest]") size_t countError = arma::accu(labels != predictedLabels); double error = (double) countError / labels.n_cols; - REQUIRE(error <= weakLearnerErrorRate); + REQUIRE(error <= weakLearnerErrorRate + 0.03); } /** * This test case runs the AdaBoost.mh algorithm on the UCI Vertebral Column * dataset. It checks if the error returned by running a single instance of the - * weak learner is worse than running the boosted weak learner using adaboost. + * weak learner is close to that of a boosted weak learner using adaboost. * This is for the weak learner: decision stumps. */ TEST_CASE("HammingLossBoundVertebralColumn_DS", "[AdaBoostTest]") @@ -403,7 +403,7 @@ TEST_CASE("HammingLossBoundVertebralColumn_DS", "[AdaBoostTest]") /** * This test case runs the AdaBoost.mh algorithm on the UCI Vertebral Column * dataset. It checks if the error returned by running a single instance of the - * weak learner is worse than running the boosted weak learner using adaboost. + * weak learner is close to that of a boosted weak learner using adaboost. * This is for the weak learner: decision stumps. */ TEST_CASE("WeakLearnerErrorVertebralColumn_DS", "[AdaBoostTest]") @@ -440,7 +440,7 @@ TEST_CASE("WeakLearnerErrorVertebralColumn_DS", "[AdaBoostTest]") size_t countError = arma::accu(labels != predictedLabels); double error = (double) countError / labels.n_cols; - REQUIRE(error <= weakLearnerErrorRate); + REQUIRE(error <= weakLearnerErrorRate + 0.03); } /** @@ -487,7 +487,7 @@ TEST_CASE("HammingLossBoundNonLinearSepData_DS", "[AdaBoostTest]") /** * This test case runs the AdaBoost.mh algorithm on a non-linearly separable * dataset. It checks if the error returned by running a single instance of the - * weak learner is worse than running the boosted weak learner using adaboost. + * weak learner is close to that of a boosted weak learner using adaboost. * This for the weak learner: decision stumps. */ TEST_CASE("WeakLearnerErrorNonLinearSepData_DS", "[AdaBoostTest]") @@ -526,7 +526,7 @@ TEST_CASE("WeakLearnerErrorNonLinearSepData_DS", "[AdaBoostTest]") size_t countError = arma::accu(labels != predictedLabels); double error = (double) countError / labels.n_cols; - REQUIRE(error <= weakLearnerErrorRate); + REQUIRE(error <= weakLearnerErrorRate + 0.03); } /** From 4a4de532dc3a539a075e6d648ce3129b13cc544f Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 6 Mar 2021 17:56:00 -0500 Subject: [PATCH 063/729] Move initialization of static members into a cpp file. --- .../environment/CMakeLists.txt | 1 + .../environment/env_type.cpp | 27 +++++++++++++++++++ .../environment/env_type.hpp | 4 --- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/mlpack/methods/reinforcement_learning/environment/env_type.cpp diff --git a/src/mlpack/methods/reinforcement_learning/environment/CMakeLists.txt b/src/mlpack/methods/reinforcement_learning/environment/CMakeLists.txt index 04e5b8b2a8..f93995ab75 100644 --- a/src/mlpack/methods/reinforcement_learning/environment/CMakeLists.txt +++ b/src/mlpack/methods/reinforcement_learning/environment/CMakeLists.txt @@ -2,6 +2,7 @@ # Anything not in this list will not be compiled into mlpack. set(SOURCES env_type.hpp + env_type.cpp mountain_car.hpp cart_pole.hpp continuous_mountain_car.hpp diff --git a/src/mlpack/methods/reinforcement_learning/environment/env_type.cpp b/src/mlpack/methods/reinforcement_learning/environment/env_type.cpp new file mode 100644 index 0000000000..d5363b5501 --- /dev/null +++ b/src/mlpack/methods/reinforcement_learning/environment/env_type.cpp @@ -0,0 +1,27 @@ +/** + * @file methods/reinforcement_learning/environment/env_type.cpp + * @author Nishant Kumar + * + * This file defines the static variables used by the discrete and continuous + * environments. + * + * 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 "env_type.hpp" + +namespace mlpack { +namespace rl { + +// Instantiate static members. + +size_t DiscreteActionEnv::State::dimension = 0; +size_t DiscreteActionEnv::Action::size = 0; + +size_t ContinuousActionEnv::State::dimension = 0; +size_t ContinuousActionEnv::Action::size = 0; + +} // namespace rl +} // namespace mlpack diff --git a/src/mlpack/methods/reinforcement_learning/environment/env_type.hpp b/src/mlpack/methods/reinforcement_learning/environment/env_type.hpp index e8513e3bb9..4fcf797322 100644 --- a/src/mlpack/methods/reinforcement_learning/environment/env_type.hpp +++ b/src/mlpack/methods/reinforcement_learning/environment/env_type.hpp @@ -105,8 +105,6 @@ class DiscreteActionEnv */ bool IsTerminal(const State& /* state */) const { return false; } }; -size_t DiscreteActionEnv::State::dimension = 0; -size_t DiscreteActionEnv::Action::size = 0; /** * To use the dummy environment, one may start by specifying the state and @@ -201,8 +199,6 @@ class ContinuousActionEnv */ bool IsTerminal(const State& /* state */) const { return false; } }; -size_t ContinuousActionEnv::State::dimension = 0; -size_t ContinuousActionEnv::Action::size = 0; } // namespace rl } // namespace mlpack From e516f72472bd606fc2b1d46acca1285e60fe5781 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 7 Mar 2021 18:27:01 +0530 Subject: [PATCH 064/729] Added SplitHelper to remove redundant code --- src/mlpack/core/data/split_data.hpp | 256 ++++++++++++---------------- 1 file changed, 105 insertions(+), 151 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 61f9860f54..1fa9bab6db 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -18,6 +18,101 @@ namespace mlpack { namespace data { +template +void SplitHelper(const InputType& input, + const LabelsType& inputLabel, + InputType& trainData, + InputType& testData, + LabelsType& trainLabel, + LabelsType& testLabel, + const double testRatio, + const bool shuffleData = true) +{ + const size_t testSize = static_cast(input.n_cols * testRatio); + const size_t trainSize = input.n_cols - testSize; + + trainData.set_size(input.n_rows, trainSize); + testData.set_size(input.n_rows, testSize); + trainLabel.set_size(inputLabel.n_rows, trainSize); + testLabel.set_size(inputLabel.n_rows, testSize); + + if (shuffleData) + { + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + + if (trainSize > 0) + { + for (size_t i = 0; i < trainSize; ++i) + { + trainData.col(i) = input.col(order(i)); + trainLabel.col(i) = inputLabel.col(order(i)); + } + } + if (trainSize < input.n_cols) + { + for (size_t i = trainSize; i < input.n_cols; ++i) + { + testData.col(i - trainSize) = input.col(order(i)); + testLabel.col(i - trainSize) = inputLabel.col(order(i)); + } + } + } + else + { + if (trainSize > 0) + { + trainData = input.cols(0, trainSize - 1); + trainLabel = inputLabel.cols(0, trainSize - 1); + } + + if (trainSize < input.n_cols) + { + testData = input.cols(trainSize, input.n_cols - 1); + testLabel = inputLabel.cols(trainSize, inputLabel.n_cols - 1); + } + } +} + +template +void SplitHelper(const InputType& input, + InputType& trainData, + InputType& testData, + const double testRatio, + const bool shuffleData = true) +{ + const size_t testSize = static_cast(input.n_cols * testRatio); + const size_t trainSize = input.n_cols - testSize; + + trainData.set_size(input.n_rows, trainSize); + testData.set_size(input.n_rows, testSize); + + if (shuffleData) + { + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + + if (trainSize > 0) + { + for (size_t i = 0; i < trainSize; ++i) + trainData.col(i) = input.col(order(i)); + } + if (trainSize < input.n_cols) + { + for (size_t i = trainSize; i < input.n_cols; ++i) + testData.col(i - trainSize) = input.col(order(i)); + } + } + else + { + if (trainSize > 0) + trainData = input.cols(0, trainSize - 1); + + if (trainSize < input.n_cols) + testData = input.cols(trainSize, input.n_cols - 1); + } +} + /** * Given an input dataset and labels, stratify into a training set and test set. * It is recommended to have the input labels between the range [0, n) where n @@ -92,8 +187,8 @@ void StratifiedSplit(const arma::Mat& input, trainData.set_size(input.n_rows, trainSize); testData.set_size(input.n_rows, testSize); - trainLabel.set_size(trainSize); - testLabel.set_size(testSize); + trainLabel.set_size(inputLabel.n_rows, trainSize); + testLabel.set_size(inputLabel.n_rows, testSize); if (shuffleData) { @@ -184,44 +279,9 @@ void Split(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - const size_t testSize = static_cast(input.n_cols * testRatio); - const size_t trainSize = input.n_cols - testSize; - trainData.set_size(input.n_rows, trainSize); - testData.set_size(input.n_rows, testSize); - trainLabel.set_size(1, trainSize); - testLabel.set_size(1, testSize); - - if (shuffleData) - { - arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, - input.n_cols)); - - if (trainSize > 0) - { - trainData = input.cols(order.subvec(0, trainSize - 1)); - trainLabel = inputLabel.cols(order.subvec(0, trainSize - 1)); - } - - if (trainSize < input.n_cols) - { - testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); - testLabel = inputLabel.cols(order.subvec(trainSize, input.n_cols - 1)); - } - } - else - { - if (trainSize > 0) - { - trainData = input.cols(0, trainSize - 1); - trainLabel = inputLabel.cols(0, trainSize - 1); - } - - if (trainSize < input.n_cols) - { - testData = input.cols(trainSize, input.n_cols - 1); - testLabel = inputLabel.cols(trainSize, inputLabel.n_cols - 1); - } - } + SplitHelper(input, inputLabel, trainData, + testData, trainLabel, testLabel, testRatio, + shuffleData); } /** @@ -254,30 +314,7 @@ void Split(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - const size_t testSize = static_cast(input.n_cols * testRatio); - const size_t trainSize = input.n_cols - testSize; - trainData.set_size(input.n_rows, trainSize); - testData.set_size(input.n_rows, testSize); - - if (shuffleData) - { - arma::uvec order = arma::shuffle(arma::linspace( - 0, input.n_cols - 1, input.n_cols)); - - if (trainSize > 0) - trainData = input.cols(order.subvec(0, trainSize - 1)); - - if (trainSize < input.n_cols) - testData = input.cols(order.subvec(trainSize, input.n_cols - 1)); - } - else - { - if (trainSize > 0) - trainData = input.cols(0, trainSize - 1); - - if (trainSize < input.n_cols) - testData = input.cols(trainSize , input.n_cols - 1); - } + SplitHelper(input, trainData, testData, testRatio, shuffleData); } /** @@ -418,56 +455,9 @@ void Split(const FieldType& input, const double testRatio, const bool shuffleData = true) { - const size_t testSize = static_cast(input.n_cols * testRatio); - const size_t trainSize = input.n_cols - testSize; - - trainData.set_size(1, trainSize); - testData.set_size(1, testSize); - trainLabel.set_size(trainSize); - testLabel.set_size(testSize); - - if (shuffleData) - { - arma::uvec order = arma::shuffle(arma::linspace(0, - input.n_cols - 1, input.n_cols)); - - if (trainSize > 0) - { - for (size_t i = 0; i < trainSize; ++i) - { - trainData[i] = input(0, order(i)); - trainLabel[i] = inputLabel(0, order(i)); - } - } - if (trainSize < input.n_cols) - { - for (size_t i = trainSize; i < input.n_cols; ++i) - { - testData[i - trainSize] = input(0, order(i)); - testLabel[i - trainSize] = inputLabel(0, order(i)); - } - } - } - else - { - if (trainSize > 0) - { - for (size_t i = 0; i < trainSize; ++i) - { - trainData[i] = input(0, i); - trainLabel[i] = inputLabel(0, i); - } - } - - if (trainSize < input.n_cols) - { - for (size_t i = trainSize; i < input.n_cols; ++i) - { - testData[i - trainSize] = input(0, i); - testLabel[i - trainSize] = inputLabel(0, i); - } - } - } + SplitHelper(input, inputLabel, trainData, + testData, trainLabel, testLabel, testRatio, + shuffleData); } /** @@ -508,43 +498,7 @@ void Split(const FieldType& input, const double testRatio, const bool shuffleData = true) { - const size_t testSize = static_cast(input.n_cols * testRatio); - const size_t trainSize = input.n_cols - testSize; - - trainData.set_size(1, trainSize); - testData.set_size(1, testSize); - - if (shuffleData) - { - arma::uvec order = arma::shuffle(arma::linspace(0, - input.n_cols - 1, input.n_cols)); - - if (trainSize > 0) - { - for (size_t i = 0; i < trainSize; i++) - trainData[i] = input(0, order(i)); - } - - if (trainSize < input.n_cols) - { - for (size_t i = trainSize; i < input.n_cols - 1; ++i) - testData[i - trainSize] = input(0, order(i)); - } - } - else - { - if (trainSize > 0) - { - for (size_t i = 0; i < trainSize; i++) - trainData[i] = input(0, i); - } - - if (trainSize < input.n_cols) - { - for (size_t i = trainSize; i < input.n_cols - 1; ++i) - testData[i - trainSize] = input(0, i); - } - } + SplitHelper(input, trainData, testData, testRatio, shuffleData); } /** From 9ae544a31b1d16b535b4ea7067e53cd67e96fbe5 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 9 Mar 2021 19:15:32 +0100 Subject: [PATCH 065/729] Clean Coverage, no longer used Signed-off-by: Omar Shrit --- CMakeLists.txt | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ecd13769c..38785e0165 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,8 +80,6 @@ option(BUILD_R_BINDINGS "Build R bindings." OFF) # generation. option(BUILD_MARKDOWN_BINDINGS "Build Markdown bindings for website documentation." OFF) -option(BUILD_WITH_COVERAGE - "Build with support for code coverage tools (gcc only)." OFF) option(MATHJAX "Use MathJax for HTML Doxygen output (disabled by default)." OFF) option(FORCE_CXX11 @@ -196,38 +194,6 @@ if(CMAKE_COMPILER_IS_GNUCC) ${CMAKE_THREAD_LIBS_INIT}) endif() -# Setup build for test coverage -if(BUILD_WITH_COVERAGE) - # Currently coverage only works with GNU g++. - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # Find gcov and lcov - find_program(GCOV gcov) - find_program(LCOV lcov) - - if(NOT GCOV) - message(FATAL_ERROR - "gcov not found! gcov is required when BUILD_WITH_COVERAGE=ON.") - endif() - - set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} "supc++") - set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} "quadmath") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fno-inline -fno-inline-small-functions -fno-default-inline -fprofile-arcs -fkeep-inline-functions") - message(STATUS "Adding debug compile options for code coverage.") - # Remove optimizations for better line coverage - set(DEBUG ON) - - if(LCOV) - configure_file(CMake/mlpack_coverage.in mlpack_coverage @ONLY) - add_custom_target(mlpack_coverage DEPENDS mlpack_test COMMAND ${PROJECT_BINARY_DIR}/mlpack_coverage) - else() - message(WARNING "'lcov' not found; local coverage report is disabled. " - "Install 'lcov' and rerun cmake to generate local coverage report.") - endif() - else() - message(FATAL_ERROR "BUILD_WITH_COVERAGE can only work with GNU environment.") - endif() -endif() - # Debugging CFLAGS. Turn optimizations off; turn debugging symbols on. if(DEBUG) if (NOT MSVC) From 9a1a6e983e32a4dec741fd8fa02c6676fcb23249 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 10 Mar 2021 11:25:35 +0530 Subject: [PATCH 066/729] Update src/mlpack/core/data/split_data.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/data/split_data.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 1fa9bab6db..67f8491c68 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -20,13 +20,13 @@ namespace data { template void SplitHelper(const InputType& input, - const LabelsType& inputLabel, - InputType& trainData, - InputType& testData, - LabelsType& trainLabel, - LabelsType& testLabel, - const double testRatio, - const bool shuffleData = true) + const LabelsType& inputLabel, + InputType& trainData, + InputType& testData, + LabelsType& trainLabel, + LabelsType& testLabel, + const double testRatio, + const bool shuffleData = true) { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; From b39ef0f9a9cd09e94200aaac274300fa7c06a92c Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 10 Mar 2021 12:25:39 +0530 Subject: [PATCH 067/729] Removed un needed overload of SplitHelper --- src/mlpack/core/data/split_data.hpp | 125 ++++++++++++---------------- 1 file changed, 51 insertions(+), 74 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 67f8491c68..1dd1abc62c 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -18,68 +18,12 @@ namespace mlpack { namespace data { -template -void SplitHelper(const InputType& input, - const LabelsType& inputLabel, - InputType& trainData, - InputType& testData, - LabelsType& trainLabel, - LabelsType& testLabel, - const double testRatio, - const bool shuffleData = true) -{ - const size_t testSize = static_cast(input.n_cols * testRatio); - const size_t trainSize = input.n_cols - testSize; - - trainData.set_size(input.n_rows, trainSize); - testData.set_size(input.n_rows, testSize); - trainLabel.set_size(inputLabel.n_rows, trainSize); - testLabel.set_size(inputLabel.n_rows, testSize); - - if (shuffleData) - { - arma::uvec order = arma::shuffle(arma::linspace(0, - input.n_cols - 1, input.n_cols)); - - if (trainSize > 0) - { - for (size_t i = 0; i < trainSize; ++i) - { - trainData.col(i) = input.col(order(i)); - trainLabel.col(i) = inputLabel.col(order(i)); - } - } - if (trainSize < input.n_cols) - { - for (size_t i = trainSize; i < input.n_cols; ++i) - { - testData.col(i - trainSize) = input.col(order(i)); - testLabel.col(i - trainSize) = inputLabel.col(order(i)); - } - } - } - else - { - if (trainSize > 0) - { - trainData = input.cols(0, trainSize - 1); - trainLabel = inputLabel.cols(0, trainSize - 1); - } - - if (trainSize < input.n_cols) - { - testData = input.cols(trainSize, input.n_cols - 1); - testLabel = inputLabel.cols(trainSize, inputLabel.n_cols - 1); - } - } -} - template void SplitHelper(const InputType& input, - InputType& trainData, - InputType& testData, - const double testRatio, - const bool shuffleData = true) + InputType& trainData, + InputType& testData, + const double testRatio, + const arma::uvec* order = nullptr) { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; @@ -87,20 +31,17 @@ void SplitHelper(const InputType& input, trainData.set_size(input.n_rows, trainSize); testData.set_size(input.n_rows, testSize); - if (shuffleData) + if (order) { - arma::uvec order = arma::shuffle(arma::linspace(0, - input.n_cols - 1, input.n_cols)); - if (trainSize > 0) { for (size_t i = 0; i < trainSize; ++i) - trainData.col(i) = input.col(order(i)); + trainData.col(i) = input.col( (*order)(i) ); } if (trainSize < input.n_cols) { for (size_t i = trainSize; i < input.n_cols; ++i) - testData.col(i - trainSize) = input.col(order(i)); + testData.col(i - trainSize) = input.col( (*order)(i) ); } } else @@ -279,9 +220,18 @@ void Split(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - SplitHelper(input, inputLabel, trainData, - testData, trainLabel, testLabel, testRatio, - shuffleData); + if(shuffleData) + { + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + SplitHelper(input, trainData, testData, testRatio, &order); + SplitHelper(inputLabel, trainLabel, testLabel, testRatio, &order); + } + else + { + SplitHelper(input, trainData, testData, testRatio); + SplitHelper(inputLabel, trainLabel, testLabel, testRatio); + } } /** @@ -314,7 +264,16 @@ void Split(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - SplitHelper(input, trainData, testData, testRatio, shuffleData); + if(shuffleData) + { + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + SplitHelper(input, trainData, testData, testRatio, &order); + } + else + { + SplitHelper(input, trainData, testData, testRatio); + } } /** @@ -455,9 +414,18 @@ void Split(const FieldType& input, const double testRatio, const bool shuffleData = true) { - SplitHelper(input, inputLabel, trainData, - testData, trainLabel, testLabel, testRatio, - shuffleData); + if(shuffleData) + { + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + SplitHelper(input, trainData, testData, testRatio, &order); + SplitHelper(inputLabel, trainLabel, testLabel, testRatio, &order); + } + else + { + SplitHelper(input, trainData, testData, testRatio); + SplitHelper(inputLabel, trainLabel, testLabel, testRatio); + } } /** @@ -498,7 +466,16 @@ void Split(const FieldType& input, const double testRatio, const bool shuffleData = true) { - SplitHelper(input, trainData, testData, testRatio, shuffleData); + if(shuffleData) + { + arma::uvec order = arma::shuffle(arma::linspace(0, + input.n_cols - 1, input.n_cols)); + SplitHelper(input, trainData, testData, testRatio, &order); + } + else + { + SplitHelper(input, trainData, testData, testRatio); + } } /** From 0557f042bf80ffcac471cbb0f461fb1103ea3db5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 10 Mar 2021 12:26:59 +0530 Subject: [PATCH 068/729] Resurrected StratifiedSplit implementation explanation --- src/mlpack/core/data/split_data.hpp | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 1dd1abc62c..7d61e434ec 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -101,6 +101,39 @@ void StratifiedSplit(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { + /** + * Basic idea: + * Let us say we have to stratify a dataset based on labels: + * 0 0 0 0 0 (5 0s) + * 1 1 1 1 1 1 1 1 1 1 1 (11 1s) + * + * Let our test ratio be 0.2. + * Then, the number of 0 labels in our test set = floor(5 * 0.2) = 1. + * The number of 1 labels in our test set = floor(11 * 0.2) = 2. + * + * In our first pass over the dataset, + * We visit each label and keep count of each label in our 'labelCounts' uvec. + * + * We then take a second pass over the dataset. + * We now maintain an additional uvec 'testLabelCounts' to hold the label + * counts of our test set. + * + * In this pass, when we encounter a label we check the 'testLabelCounts' uvec + * for the count of this label in the test set. + * If this count is less than the required number of labels in the test set, + * we add the data to the test set and increment the label count in the uvec. + * If this count is equal to or more than the required count in the test set, + * we add this data to the train set. + * + * Based on the above steps, we get the following labels in the split set: + * Train set (4 0s, 9 1s) + * 0 0 0 0 + * 1 1 1 1 1 1 1 1 1 + * + * Test set (1 0s, 2 1s) + * 0 + * 1 1 + */ const bool typeCheck = (arma::is_Row::value) || (arma::is_Col::value); if (!typeCheck) From 1117300efb742cc1fe0cb53aba3d2ba5b1b2c8bb Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 10 Mar 2021 12:40:09 +0530 Subject: [PATCH 069/729] Added documentation --- src/mlpack/core/data/split_data.hpp | 32 ++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 7d61e434ec..a97058d29b 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -18,39 +18,47 @@ namespace mlpack { namespace data { +/** + * This helper function splits any `input` data into training and testing parts. + * In order to shuffle the input data before spliting, an array of shuffled + * indices of the input data is passed in the form of argument `order`. + */ template void SplitHelper(const InputType& input, - InputType& trainData, - InputType& testData, + InputType& train, + InputType& test, const double testRatio, const arma::uvec* order = nullptr) { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; - trainData.set_size(input.n_rows, trainSize); - testData.set_size(input.n_rows, testSize); + // Initialising the sizes of outputs if not already initialized. + train.set_size(input.n_rows, trainSize); + test.set_size(input.n_rows, testSize); + // Shuffling and spliting simultaneously. if (order) { if (trainSize > 0) { for (size_t i = 0; i < trainSize; ++i) - trainData.col(i) = input.col( (*order)(i) ); + train.col(i) = input.col( (*order)(i) ); } if (trainSize < input.n_cols) { for (size_t i = trainSize; i < input.n_cols; ++i) - testData.col(i - trainSize) = input.col( (*order)(i) ); + test.col(i - trainSize) = input.col( (*order)(i) ); } } + // Spliting only. else { if (trainSize > 0) - trainData = input.cols(0, trainSize - 1); + train = input.cols(0, trainSize - 1); if (trainSize < input.n_cols) - testData = input.cols(trainSize, input.n_cols - 1); + test = input.cols(trainSize, input.n_cols - 1); } } @@ -253,7 +261,7 @@ void Split(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - if(shuffleData) + if (shuffleData) { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); @@ -297,7 +305,7 @@ void Split(const arma::Mat& input, const double testRatio, const bool shuffleData = true) { - if(shuffleData) + if (shuffleData) { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); @@ -447,7 +455,7 @@ void Split(const FieldType& input, const double testRatio, const bool shuffleData = true) { - if(shuffleData) + if (shuffleData) { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); @@ -499,7 +507,7 @@ void Split(const FieldType& input, const double testRatio, const bool shuffleData = true) { - if(shuffleData) + if (shuffleData) { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); From 43760f7aa36163d11d90a623b61cd0a244de6f3c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 10 Mar 2021 11:43:45 +0100 Subject: [PATCH 070/729] Remove the coverage badge Signed-off-by: Omar Shrit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index bb8ba1be6c..84eb8260b4 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="

Jenkins - Coveralls License NumFOCUS

From fca53ed16d4ba590e503b3b56c60fb8813621ac8 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 10 Mar 2021 20:05:15 +0530 Subject: [PATCH 071/729] initial_commit --- .../bindings/python/mlpack/preprocess_json_params.py | 8 ++++++++ src/mlpack/bindings/python/mlpack/serialization.hpp | 12 ++++++++++++ src/mlpack/bindings/python/mlpack/serialization.pxd | 1 + src/mlpack/bindings/python/print_class_defn.hpp | 7 +++++++ src/mlpack/bindings/python/print_pyx.cpp | 2 +- 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/mlpack/bindings/python/mlpack/preprocess_json_params.py diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py new file mode 100644 index 0000000000..001591a02c --- /dev/null +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -0,0 +1,8 @@ +def preprocess_params(params, return_dic=False): + params_decoded = params.decode("utf-8").replace("true", "True")\ + .replace("false", "False") + if return_dic: + dic = eval(params_decoded) + return params_decoded, dic + else: + return params_decoded diff --git a/src/mlpack/bindings/python/mlpack/serialization.hpp b/src/mlpack/bindings/python/mlpack/serialization.hpp index 879e559d07..df85aa5a2c 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.hpp +++ b/src/mlpack/bindings/python/mlpack/serialization.hpp @@ -38,6 +38,18 @@ void SerializeIn(T* t, const std::string& str, const std::string& name) b(cereal::make_nvp(name.c_str(), *t)); } +template +std::string SerializeOutJSON(T* t, const std::string& name) +{ + std::ostringstream oss; + { + cereal::JSONOutputArchive b(oss); + + b(cereal::make_nvp(name.c_str(), *t)); + } + return oss.str(); +} + } // namespace python } // namespace bindings } // namespace mlpack diff --git a/src/mlpack/bindings/python/mlpack/serialization.pxd b/src/mlpack/bindings/python/mlpack/serialization.pxd index 3df3306467..a8d5298a90 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.pxd +++ b/src/mlpack/bindings/python/mlpack/serialization.pxd @@ -12,3 +12,4 @@ from libcpp.string cimport string cdef extern from "serialization.hpp" namespace "mlpack::bindings::python" nogil: string SerializeOut[T](T* t, string name) nogil void SerializeIn[T](T* t, string str, string name) nogil + string SerializeOutJSON[T](T* t, string name) nogil \ No newline at end of file diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 6ed4973951..cd2ee2c5c0 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -72,6 +72,9 @@ void PrintClassDefn( * def __getstate__(self): * return SerializeOut(self.modelptr, "") * + * def _params(self): + * return SerializeOutJSON(self.modelptr, "") + * * def __setstate__(self, state): * SerializeIn(self.modelptr, state, "") * @@ -92,6 +95,10 @@ void PrintClassDefn( std::cout << " return SerializeOut(self.modelptr, \"" << printedType << "\")" << std::endl; std::cout << std::endl; + std::cout << " def _params(self):" << std::endl; + std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType + << "\")" << std::endl; + std::cout << std::endl; std::cout << " def __setstate__(self, state):" << std::endl; std::cout << " SerializeIn(self.modelptr, state, \"" << printedType << "\")" << std::endl; diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 6853c969da..3b8ef867cc 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,7 +80,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, " << "ResetTimers, EnableTimers" << endl; cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl; - cout << "from serialization cimport SerializeIn, SerializeOut" << endl; + cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON" << endl; cout << endl; cout << "import numpy as np" << endl; cout << "cimport numpy as np" << endl; From c7c51a8dbecae63997ad98b7bd2e74fc8d340752 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 10 Mar 2021 21:21:16 +0530 Subject: [PATCH 072/729] added to cmakelist --- src/mlpack/bindings/python/CMakeLists.txt | 1 + .../bindings/python/mlpack/preprocess_json_params.py | 3 ++- src/mlpack/bindings/python/print_class_defn.hpp | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mlpack/bindings/python/CMakeLists.txt b/src/mlpack/bindings/python/CMakeLists.txt index c36a026590..c32edaaa24 100644 --- a/src/mlpack/bindings/python/CMakeLists.txt +++ b/src/mlpack/bindings/python/CMakeLists.txt @@ -132,6 +132,7 @@ set(CYTHON_SOURCES mlpack/matrix_utils.py mlpack/serialization.hpp mlpack/serialization.pxd + mlpack/preprocess_json_params.py ) set(TEST_SOURCES diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 001591a02c..2d5f764ae2 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,4 +1,5 @@ -def preprocess_params(params, return_dic=False): +def process_params(model, return_dic=False): + params = model.params() params_decoded = params.decode("utf-8").replace("true", "True")\ .replace("false", "False") if return_dic: diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index cd2ee2c5c0..5c436ff2ae 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -95,10 +95,6 @@ void PrintClassDefn( std::cout << " return SerializeOut(self.modelptr, \"" << printedType << "\")" << std::endl; std::cout << std::endl; - std::cout << " def _params(self):" << std::endl; - std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType - << "\")" << std::endl; - std::cout << std::endl; std::cout << " def __setstate__(self, state):" << std::endl; std::cout << " SerializeIn(self.modelptr, state, \"" << printedType << "\")" << std::endl; @@ -107,6 +103,10 @@ void PrintClassDefn( std::cout << " return (self.__class__, (), self.__getstate__())" << std::endl; std::cout << std::endl; + std::cout << " def params(self):" << std::endl; + std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType + << "\")" << std::endl; + std::cout << std::endl; } /** From bd8a5e44c08b6a7b68e79ab8d1155946ab69abfd Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 10 Mar 2021 22:35:39 +0100 Subject: [PATCH 073/729] Remove appveyor, no longer used Signed-off-by: Omar Shrit --- .appveyor.yml | 219 -------------------------------------------------- 1 file changed, 219 deletions(-) delete mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 722a597468..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,219 +0,0 @@ -clone_depth: 10 - -environment: - BOOST_MATH : "C:/projects/mlpack/\ - boost_math_c99-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*" - BOOST_RANDOM : "C:/projects/mlpack/\ - boost_random-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*" - ARMADILLO_DOWNLOAD : "https://data.kurg.org/armadillo-8.400.0.tar.xz" - ARMADILLO_LIBRARY : "C:/projects/mlpack/armadillo-8.400.0/\ - build/Debug/armadillo.lib" - BLAS_LIBRARY : "%APPVEYOR_BUILD_FOLDER%/OpenBLAS.0.2.14.1/lib/native/lib/x64/\ - libopenblas.dll.a" - BOOST_INCLUDE : "C:/projects/mlpack/boost.1.60.0.0/lib/native/include" - JENKINS_DOC_DOWNLOAD : "http://ci.mlpack.org/job/mlpack%20-%20doxygen%20\ - build/lastSuccessfulBuild/artifact/build/doc/html/*zip*/html.zip" - JENKINS_DOC : "C:/projects/mlpack/dist/win-installer/jenkinsdoc.zip" - GIT_VERSION_FILE : "C:/projects/mlpack/src/mlpack/core/util/gitversion.hpp" - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - VSVER: Visual Studio 16 2019 - MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe - -# We have removed the VS studio 15 2017 build since it is not possible to complete -# or finish the build due to the `compiler out of heap space issues`. -# Therefore, in the meanwhile, we are only doing the installation for VS 16 2019. - -configuration: Release - -os: Visual Studio 2019 - -install: - - ps: nuget install boost -o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0 - - ps: > - nuget install boost_random-vc140 - -o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0 - - ps: > - nuget install boost_math_c99-vc140 - -o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0 - - ps: > - nuget install unofficial-flayan-cereal - -o "${env:APPVEYOR_BUILD_FOLDER}" - - ps: nuget install OpenBLAS -o "${env:APPVEYOR_BUILD_FOLDER}" - - set path=C:\Program Files (x86)\WiX Toolset v3.11\bin;%path% - -build_script: - - mkdir boost_libs - - ps: cp ${env:BOOST_MATH} C:\projects\mlpack\boost_libs\ - - ps: cp ${env:BOOST_RANDOM} C:\projects\mlpack\boost_libs\ - - echo TEST_ARMA is %ARMADILLO_DOWNLOAD% - - > - appveyor DownloadFile %ARMADILLO_DOWNLOAD% - -FileName armadillo.tar.xz - - 7z x armadillo.tar.xz -so -txz | 7z x -si -ttar > nul - - cd armadillo-8.400.0 && mkdir build && cd build - - > - cmake -G "%VSVER%" - -DBLAS_LIBRARY:FILEPATH=%BLAS_LIBRARY% - -DLAPACK_LIBRARY:FILEPATH=%BLAS_LIBRARY% - -DCMAKE_PREFIX:FILEPATH="%APPVEYOR_BUILD_FOLDER%/armadillo" - -DBUILD_SHARED_LIBS=OFF - -DCMAKE_BUILD_TYPE=Release .. - - > - "%MSBUILD%" "C:\projects\mlpack\armadillo-8.400.0\build\armadillo.sln" - /m /verbosity:quiet /p:Configuration=Release;Platform=x64 - - cd C:\projects\mlpack && mkdir build && cd build - - > - cmake -G "%VSVER%" - -DBLAS_LIBRARIES:FILEPATH=%BLAS_LIBRARY% - -DLAPACK_LIBRARIES:FILEPATH=%BLAS_LIBRARY% - -DARMADILLO_INCLUDE_DIR="C:/projects/mlpack/armadillo-8.400.0/include" - -DARMADILLO_LIBRARY:FILEPATH=%ARMADILLO_LIBRARY% - -DCEREAL_INCLUDE_DIR="C:/projects/mlpack/unofficial-flayan-cereal.1.2.2/build/native/include" - -DBOOST_INCLUDEDIR:PATH=%BOOST_INCLUDE% - -DDEBUG=OFF - -DPROFILE=OFF - -DBUILD_PYTHON_BINDINGS=OFF - -DBUILD_GO_BINDINGS=OFF - -DBUILD_R_BINDINGS=OFF - -DBUILD_TESTS=OFF - -DCMAKE_BUILD_TYPE=Release .. - - > - "%MSBUILD%" "C:\projects\mlpack\build\mlpack.sln" - /m /verbosity:minimal /nologo /p:BuildInParallel=true - /p:Configuration=Release;Platform=x64 - - # Zip Artifacts. - - > - 7z a mlpack-windows-no-libs.zip - "%APPVEYOR_BUILD_FOLDER%\build\Release\*.exe" - - > - 7z a mlpack-windows.zip - "%APPVEYOR_BUILD_FOLDER%\build\Release\*.*" - "%APPVEYOR_BUILD_FOLDER%/OpenBLAS.0.2.14.1/lib/native/lib/x64/*.*" - - # Pulling documentation for the installer. - - ps: > - try{(new-object net.webclient).DownloadFile(${env:JENKINS_DOC_DOWNLOAD}, - 'C:\projects\mlpack\dist\win-installer\jenkinsdoc.zip')} - catch{Write-Output "Unable to pull jenkins doc, skipping!"} - - ps: > - try{(Add-Type -AssemblyName System.IO.Compression.FileSystem); - [System.IO.Compression.ZipFile]::ExtractToDirectory(${env:JENKINS_DOC}, - 'C:\projects\mlpack\dist\win-installer\staging\doc')} - catch{Write-Output "Unable to add doc to installer, skipping!"} - - # Preparing installer staging. - - cd C:\projects\mlpack\dist\win-installer\staging && mkdir lib - - ps: > - cp C:\projects\mlpack\build\Release\*.lib - C:\projects\mlpack\dist\win-installer\staging\lib\ - - ps: > - cp C:\projects\mlpack\build\Release\*.exp - C:\projects\mlpack\dist\win-installer\staging\lib\ - - ps: > - cp C:\projects\mlpack\build\Release\*.dll - C:\projects\mlpack\dist\win-installer\staging\ - - ps: > - cp C:\projects\mlpack\build\Release\*.exe - C:\projects\mlpack\dist\win-installer\staging\ - - ps: > - cp C:\projects\mlpack\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll - C:\projects\mlpack\dist\win-installer\staging\ - - ps: > - cp C:\projects\mlpack\build\include\mlpack - C:\projects\mlpack\dist\win-installer\staging -recurse - - ps: > - cp C:\projects\mlpack\doc\examples - C:\projects\mlpack\dist\win-installer\staging -recurse - - ps: > - cp C:\projects\mlpack\src\mlpack\tests\data\german.csv - C:\projects\mlpack\dist\win-installer\staging\examples\sample-ml-app\sample-ml-app\data\ - - # Checking current gitversion or mlpack version. - - ps: > - $ver = (Get-Content - "${env:APPVEYOR_BUILD_FOLDER}\src\mlpack\core\util\version.hpp" | - where {$_ -like "*MLPACK_VERSION*"}); - $env:MLPACK_VERSION += $ver[0].substring($ver[0].length - 1, 1) + '.'; - $env:MLPACK_VERSION += $ver[1].substring($ver[1].length - 1, 1) + '.'; - $env:MLPACK_VERSION += $ver[2].substring($ver[2].length - 1, 1); - - if (Test-Path ${env:GIT_VERSION_FILE}) - { - $ver = (Get-Content ${env:GIT_VERSION_FILE}); - $env:INSTALL_VERSION = $ver.Split('"')[1].Split(' ')[1]; - } - else - { - $env:INSTALL_VERSION = $env:MLPACK_VERSION; - } - - echo INSTALL_VERSION is %INSTALL_VERSION% - - # Building MSI installer. - - cd C:\projects\mlpack\dist\win-installer\mlpack-win-installer - - > - heat dir ..\staging - -cg HeatGenerated - -dr INSTALLFOLDER - -sreg - -srd - -var var.HarvestPath - -ag - -sfrag - -out HeatGeneratedFileList.wxs - - > - candle -dHarvestPath=..\staging - -dConfiguration=Release - -dOutDir=bin\x64\Release\ - -dPlatform=x64 - -dProjectDir=. - -dProjectExt=.wixproj - -dProjectFileName=mlpack-win-installer.wixproj - -dProjectName=mlpack-win-installer - -dProjectPath=mlpack-win-installer.wixproj - -dTargetDir=.\bin\x64\Release\ - -dTargetExt=.msi - -dTargetFileName=mlpack-windows.msi - -dTargetName=mlpack-windows - -dTargetPath=.\bin\x64\Release\mlpack-windows.msi - -out obj\x64\Release\ - -arch x64 - -ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUIExtension.dll" - Product.wxs HeatGeneratedFileList.wxs - - > - light -out .\bin\x64\Release\mlpack-%INSTALL_VERSION%.msi - -pdbout .\bin\x64\Release\mlpack-windows.wixpdb - -cultures:null - -loc mlpack-localization.wxl - -ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUIExtension.dll" - -contentsfile - obj\x64\Release\mlpack-win-installer.wixproj.BindContentsFileListnull.txt - -outputsfile - obj\x64\Release\mlpack-win-installer.wixproj.BindOutputsFileListnull.txt - -builtoutputsfile - obj\x64\Release\mlpack-win-installer.wixproj.BindBuiltOutputsFileListnull.txt - -wixprojectfile - mlpack-win-installer.wixproj - obj\x64\Release\Product.wixobj - obj\x64\Release\HeatGeneratedFileList.wixobj - -artifacts: - - path: 'build\*.zip' - name: mlpack-windows-zip - - - path: 'dist\win-installer\mlpack-win-installer\bin\x64\Release\*.msi' - name: mlpack-windows-installer - -notifications: -- provider: Email - to: - - mlpack-git@lists.mlpack.org - on_build_success: true - on_build_failure: true - on_build_status_changed: true - -cache: - - packages -> **\packages.config - - armadillo.tar.xz -> appveyor.yaml - From d384a83c3dbc6448320ba4ef5aa07d90ca356d67 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 11 Mar 2021 07:31:15 +0530 Subject: [PATCH 074/729] Update src/mlpack/tests/split_data_test.cpp Co-authored-by: Marcus Edel --- src/mlpack/tests/split_data_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 8d2b5e470e..075347bd3a 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -388,7 +388,7 @@ TEST_CASE("SplitMatrixLabeledData", "[SplitDataTest]") CheckMatrices(labels, labels_concat); } -/* +/** * Split with input of type field and label of type field. */ TEST_CASE("SplitLabeledDataResultField", "[SplitDataTest]") From 9339e42c1f51e3502a45c58b840890ab335c82a8 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 11 Mar 2021 07:31:33 +0530 Subject: [PATCH 075/729] Update src/mlpack/tests/test_catch_tools.hpp Co-authored-by: Marcus Edel --- src/mlpack/tests/test_catch_tools.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/test_catch_tools.hpp b/src/mlpack/tests/test_catch_tools.hpp index dfd0577b19..879cac8b49 100644 --- a/src/mlpack/tests/test_catch_tools.hpp +++ b/src/mlpack/tests/test_catch_tools.hpp @@ -53,7 +53,7 @@ inline void CheckMatrices(const arma::Mat& a, template ::value>> -// Check the values of two field types +// Check the values of two field types. inline void CheckFields(const FieldType& a, const FieldType& b) { From 2942737a8e35b9eab9e20d355c843411a99b775e Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 11 Mar 2021 19:06:31 -0500 Subject: [PATCH 076/729] Fix failing tests. --- src/mlpack/methods/hmm/hmm.hpp | 20 +++++++++++--------- src/mlpack/methods/hmm/hmm_impl.hpp | 19 +++++-------------- src/mlpack/tests/hmm_test.cpp | 5 +++-- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/mlpack/methods/hmm/hmm.hpp b/src/mlpack/methods/hmm/hmm.hpp index a92c3d14ea..932382f41e 100644 --- a/src/mlpack/methods/hmm/hmm.hpp +++ b/src/mlpack/methods/hmm/hmm.hpp @@ -316,8 +316,8 @@ class HMM * * @param emissionLogProb emission probability at time t. * @param logLikelihood Log-likelihood of the given sequence of emission - * probability up to time t-1. This will be overwritten with the log-likelihood - * of the given emission probability up to time t. + * probability up to time t-1. This will be overwritten with the + * log-likelihood of the given emission probability up to time t. * @param forwardLogProb Vector in which forward probabilities will be saved. * Passing forwardLogProb as an empty vector indicates the start of the * sequence (i.e. time t=0). @@ -441,27 +441,29 @@ class HMM protected: /** * Given emission probabilities, computes forward probabilities at time t=0. + * The template parameter allows passing an Armadillo subview without + * instantiating it. * * @param emissionLogProb Emission probability at time t=0. * @param logScales Vector in which the log of scaling factors will be saved. * @return Forward probabilities */ - arma::vec ForwardAtT0( - const arma::vec& emissionLogProb, - double& logScales) const; + arma::vec ForwardAtT0(const arma::vec& emissionLogProb, + double& logScales) const; /** * Given emission probabilities, computes forward probabilities for time t>0. + * The template parameter allows passing an Armadillo subview without + * instantiating it. * * @param emissionLogProb Emission probability at time t>0. * @param logScales Vector in which the log of scaling factors will be saved. * @param prevForwardLogProb Previous forward probabilities. * @return Forward probabilities */ - arma::vec ForwardAtTn( - const arma::vec& emissionLogProb, - double& logScales, - const arma::vec& prevForwardLogProb) const; + arma::vec ForwardAtTn(const arma::vec& emissionLogProb, + double& logScales, + const arma::vec& prevForwardLogProb) const; // Helper functions. /** diff --git a/src/mlpack/methods/hmm/hmm_impl.hpp b/src/mlpack/methods/hmm/hmm_impl.hpp index 31d253d23f..0449484250 100644 --- a/src/mlpack/methods/hmm/hmm_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_impl.hpp @@ -603,8 +603,7 @@ double HMM::EmissionLogLikelihood( arma::vec& forwardLogProb) const { bool isStartOfSeq = forwardLogProb.empty(); - double curLogScale = EmissionLogScaleFactor(emissionLogProb, - forwardLogProb); + double curLogScale = EmissionLogScaleFactor(emissionLogProb, forwardLogProb); logLikelihood = isStartOfSeq ? curLogScale : curLogScale + logLikelihood; return logLikelihood; } @@ -745,7 +744,8 @@ arma::vec HMM::ForwardAtTn(const arma::vec& emissionLogProb, arma::vec forwardLogProb(logTransition.n_rows); forwardLogProb.fill(-std::numeric_limits::infinity()); // Now compute the probabilities for each successive observation. - for (size_t state = 0; state < logTransition.n_rows; state++) { + for (size_t state = 0; state < logTransition.n_rows; state++) + { // The forward probability of state j at time t is the sum over all // states of the probability of the previous state transitioning to // the current state and emitting the given observation. @@ -782,21 +782,12 @@ void HMM::Forward(const arma::mat& dataSeq, // behavior, you could append a single starting state to every single data // sequence and that should produce results in line with MATLAB. - forwardLogProb.col(0) = ForwardAtT0(logProbs.unsafe_col(0), logScales(0)); + forwardLogProb.col(0) = ForwardAtT0(logProbs.row(0).t(), logScales(0)); // Now compute the probabilities for each successive observation. for (size_t t = 1; t < dataSeq.n_cols; t++) { - for (size_t state = 0; state < logTransition.n_rows; state++) - { - // The forward probability of state j at time t is the sum over all states - // of the probability of the previous state transitioning to the current - // state and emitting the given observation. - arma::vec tmp = forwardLogProb.col(t - 1) + logTransition.col(state); - forwardLogProb(state, t) = math::AccuLog(tmp) + logProbs(t, state); - } - - forwardLogProb.col(t) = ForwardAtTn(logProbs.unsafe_col(t), logScales(t), + forwardLogProb.col(t) = ForwardAtTn(logProbs.row(t).t(), logScales(t), forwardLogProb.col(t - 1)); } } diff --git a/src/mlpack/tests/hmm_test.cpp b/src/mlpack/tests/hmm_test.cpp index 03a22f31e6..394d1a688e 100644 --- a/src/mlpack/tests/hmm_test.cpp +++ b/src/mlpack/tests/hmm_test.cpp @@ -1079,10 +1079,11 @@ TEST_CASE("GaussianHMMPredictTest", "[HMMTest]") { double loglikelihood = 0; arma::vec forwardLogProb; - for (size_t t = 0; t Date: Fri, 12 Mar 2021 10:28:41 +0100 Subject: [PATCH 077/729] Remove doc and config related to coverage Signed-off-by: Omar Shrit --- CMake/mlpack_coverage.in | 135 --------------------------------------- doc/guide/build.hpp | 2 - 2 files changed, 137 deletions(-) delete mode 100755 CMake/mlpack_coverage.in diff --git a/CMake/mlpack_coverage.in b/CMake/mlpack_coverage.in deleted file mode 100755 index b67ecf3cc1..0000000000 --- a/CMake/mlpack_coverage.in +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash -# This script gets the test coverage for mlpack_test. -test_case="ALL" -gcov_loc="" -token="" -clean=true -current_log_file=`date +'%Y.%h.%d:%H:%M:%S-coverage.log'` -current_coverage_file=`date +'%Y.%h.%d:%H:%M:%S-coverage.info'` -max_cov_count=50000 - -# default directories -root_dir="../" - -# Extract arguments. -for i in "$@" -do -case $i in - -h|--help) - echo "Usage: mlpack_coverage --help|-h" - echo " mlpack_coverage [-r=test_suite] [-g=gcov_tool_location]" - echo " [--token=coveralls_token]" - echo "Optional parameters:" - echo " -n|--no_test Do not run test before coverage computation" - echo " -r|--run_test Run tests with specific test suite" - echo " --no_clean Do not remove existing gcda file" - echo " -g|--gcov_tool_location Gcov location if not default" - echo " -t|--token Upload to coveralls with given token" - echo " --max_cov_count Max line coverage count (default 50000)" - echo " --root_dir Set the root directory from which gcov will be called. (default ../)" - exit 0 - shift - ;; - -n|--no_test) - test_case="" - shift - ;; - -r=*|--run_test=*) - test_case="${i#*=}" - shift # past argument=value - ;; - --no_clean) - clean=false - shift - ;; - -g=*|--gcov_tool_location=*) - gcov_loc="${i#*=}" - shift # past argument=value - ;; - -t=*|--token=*) - token="${i#*=}" - shift # past argument=value - ;; - --max_cov_count) - max_cov_count="${i#*=}" - shift - ;; - --root_dir=*) - root_dir="${i#*=}" - shift - ;; - *) - # unknown option - ;; -esac -done - -if [ "$clean" = true ]; then - echo "Deleting existing coverage data..." - find ./ -name "*.gcda" -type f -delete -fi - -# Initial pass. -echo "Generating primary coverage report." -[[ -d ./coveragehistory/ ]] || mkdir coveragehistory -lcov -b . -c -i -d ./ -o .coverage.wtest.base > ./coveragehistory/$current_log_file - -# Run the tests. -if [ "$test_case" = "ALL" ]; then - echo "Running all the tests..." - "@CMAKE_BINARY_DIR@"/bin/mlpack_test -elif ! [ "$test_case" = "" ]; then - echo "Running test suite: $test_case" - "@CMAKE_BINARY_DIR@"/bin/mlpack_test --run_test=$test_case -fi - -# Generate coverage based on executed tests. -echo "Computing coverage..." -if [ "$gcov_loc" = "" ]; -then lcov -b . -c -d ./ -o .coverage.wtest.run >> ./coveragehistory/$current_log_file -else - lcov -b . -c -d ./ -o .coverage.wtest.run --gcov-tool=$gcov_loc >> ./coveragehistory/$current_log_file -fi - -echo "Filtering coverage files..." -# Clear negative entries in coverage file -sed -E 's/-([0-9]+)/$max_cov_count/g' -i .coverage.wtest.run -# Merge coverage tracefiles. -lcov -a .coverage.wtest.base -a .coverage.wtest.run -o .coverage.total >> ./coveragehistory/$current_log_file - -# Filtering, extracting project files. -lcov -e .coverage.total "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/*" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file - -# Filtering, removing test-files and main.cpp. -lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/*/*_main.cpp" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file -lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/tests/*" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file - -# Remove untestable files. -lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/core/util/gitversion.hpp" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file -lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/core/util/arma_config.hpp" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file - -# Extra: Replace /build/ with /src/ to unify directories. -cat .coverage.total.filtered > .coverage.total - -# Extra: Clear up previous data, create html folder. -if [[ -d ./coverage/ ]] ; then - rm -rf ./coverage/* -else - mkdir coverage -fi - -# Step 9: Generate webpage. -genhtml -o ./coverage/ .coverage.total - -# Extra: Preserve coverage file in coveragehistory folder. -coverage_file=$current_coverage_file -cp .coverage.total ./coveragehistory/$current_coverage_file - -# Clean temporary coverage files. -#rm .coverage.* - -# Upload the result to coveralls if token is provided. -if ! [ "$token" = "" ]; then - cpp-coveralls -n -r $root_dir -b $root_dir -l ./coveragehistory/$current_coverage_file -t "$token" --max-cov-count $max_cov_count -fi - diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index 9996f5132d..9356f725cc 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -191,8 +191,6 @@ The full list of options mlpack allows: - DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it (default ON) - DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it (default ON) - - BUILD_WITH_COVERAGE=(ON/OFF): Build with support for code coverage tools - (gcc only) (default OFF) - PYTHON_EXECUTABLE=(/path/to/python_version): Path to specific Python executable - PYTHON_INSTALL_PREFIX=(/path/to/python/): Path to root of Python installation - JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable From a41fc26651c2696ca75758ff186dc58ab006cff2 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 12 Mar 2021 11:13:32 +0100 Subject: [PATCH 078/729] Remove addition t from the word test I do think this is a typo, unless if this is intended Signed-off-by: Omar Shrit --- src/mlpack/tests/tree_traits_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/tests/tree_traits_test.cpp b/src/mlpack/tests/tree_traits_test.cpp index caa642c71f..e7c95d1cd4 100644 --- a/src/mlpack/tests/tree_traits_test.cpp +++ b/src/mlpack/tests/tree_traits_test.cpp @@ -31,7 +31,7 @@ using namespace mlpack::metric; // weird things and will cause bizarre problems. // Test the defaults. -TEST_CASE("DefaultsTraitsTest", "[TreeTraitsTestt]") +TEST_CASE("DefaultsTraitsTest", "[TreeTraitsTest]") { // An irrelevant non-tree type class is used here so that the default // implementation of TreeTraits is chosen. @@ -48,7 +48,7 @@ TEST_CASE("DefaultsTraitsTest", "[TreeTraitsTestt]") } // Test the binary space tree traits. -TEST_CASE("BinarySpaceTreeTraitsTest", "[TreeTraitsTestt]") +TEST_CASE("BinarySpaceTreeTraitsTest", "[TreeTraitsTest]") { typedef BinarySpaceTree> TreeType; @@ -74,7 +74,7 @@ TEST_CASE("BinarySpaceTreeTraitsTest", "[TreeTraitsTestt]") } // Test the cover tree traits. -TEST_CASE("CoverTreeTraitsTest", "[TreeTraitsTestt]") +TEST_CASE("CoverTreeTraitsTest", "[TreeTraitsTest]") { // Children may be overlapping. bool b = TreeTraits>::HasOverlappingChildren; From 10ea5a0706c6ddae4f55f30f7d93c216fe279f01 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Fri, 12 Mar 2021 19:40:24 +0530 Subject: [PATCH 079/729] remove_matlab_1 --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ecd13769c..1a6e1e5bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,6 @@ include(CMake/CheckHash.cmake) option(DEBUG "Compile with debugging information." OFF) option(PROFILE "Compile with profiling information." OFF) option(ARMA_EXTRA_DEBUG "Compile with extra Armadillo debugging symbols." OFF) -option(MATLAB_BINDINGS "Compile MATLAB bindings if MATLAB is found." OFF) option(TEST_VERBOSE "Run test cases with verbose output." OFF) option(BUILD_TESTS "Build tests." ON) option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON) From 14996379dbb4150d6e61824c03ce5f22865a109a Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Fri, 12 Mar 2021 19:49:53 +0530 Subject: [PATCH 080/729] removed_matlab_2 --- CMake/FindMatlabMex.cmake | 110 -------------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 CMake/FindMatlabMex.cmake diff --git a/CMake/FindMatlabMex.cmake b/CMake/FindMatlabMex.cmake deleted file mode 100644 index 43b342c4a5..0000000000 --- a/CMake/FindMatlabMex.cmake +++ /dev/null @@ -1,110 +0,0 @@ -# This module looks for mex, the MATLAB compiler. -# The following variables are defined when the script completes: -# MATLAB_MEX: location of mex compiler -# MATLAB_ROOT: root of MATLAB installation -# MATLABMEX_FOUND: 0 if not found, 1 if found - -set(MATLABMEX_FOUND 0) - -if(WIN32) - # This is untested but taken from the older FindMatlab.cmake script as well as - # the modifications by Ramon Casero and Tom Doel for Gerardus. - - # Search for a version of Matlab available, starting from the most modern one - # to older versions. - foreach(MATVER "7.20" "7.19" "7.18" "7.17" "7.16" "7.15" "7.14" "7.13" "7.12" -"7.11" "7.10" "7.9" "7.8" "7.7" "7.6" "7.5" "7.4") - if((NOT DEFINED MATLAB_ROOT) - OR ("${MATLAB_ROOT}" STREQUAL "") - OR ("${MATLAB_ROOT}" STREQUAL "/registry")) - get_filename_component(MATLAB_ROOT - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${MATVER};MATLABROOT]" - ABSOLUTE) - set(MATLAB_VERSION ${MATVER}) - endif() - OR ("${MATLAB_ROOT}" STREQUAL "") - OR ("${MATLAB_ROOT}" STREQUAL "/registry")) - endforeach() - - find_program(MATLAB_MEX - mex - ${MATLAB_ROOT}/bin - ) -else() - # Check if this is a Mac. - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # This code is untested but taken from the older FindMatlab.cmake script as - # well as the modifications by Ramon Casero and Tom Doel for Gerardus. - - set(LIBRARY_EXTENSION .dylib) - - # If this is a Mac and the attempts to find MATLAB_ROOT have so far failed,~ - # we look in the applications folder - if((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL "")) - - # Search for a version of Matlab available, starting from the most modern - # one to older versions - foreach(MATVER "R2013b" "R2013a" "R2012b" "R2012a" "R2011b" "R2011a" -"R2010b" "R2010a" "R2009b" "R2009a" "R2008b") - if((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL "")) - if(EXISTS /Applications/MATLAB_${MATVER}.app) - set(MATLAB_ROOT /Applications/MATLAB_${MATVER}.app) - - endif() - endif() - endforeach() - - endif() - - find_program(MATLAB_MEX - mex - PATHS - ${MATLAB_ROOT}/bin - ) - - else() - # On a Linux system. The goal is to find MATLAB_ROOT. - set(LIBRARY_EXTENSION .so) - - find_program(MATLAB_MEX_POSSIBLE_LINK - mex - PATHS - ${MATLAB_ROOT}/bin - /opt/matlab/bin - /usr/local/matlab/bin - $ENV{HOME}/matlab/bin - # Now all the versions - /opt/matlab/[rR]20[0-9][0-9][abAB]/bin - /usr/local/matlab/[rR]20[0-9][0-9][abAB]/bin - /opt/matlab-[rR]20[0-9][0-9][abAB]/bin - /opt/matlab_[rR]20[0-9][0-9][abAB]/bin - /usr/local/matlab-[rR]20[0-9][0-9][abAB]/bin - /usr/local/matlab_[rR]20[0-9][0-9][abAB]/bin - $ENV{HOME}/matlab/[rR]20[0-9][0-9][abAB]/bin - $ENV{HOME}/matlab-[rR]20[0-9][0-9][abAB]/bin - $ENV{HOME}/matlab_[rR]20[0-9][0-9][abAB]/bin - ) - - get_filename_component(MATLAB_MEX "${MATLAB_MEX_POSSIBLE_LINK}" REALPATH) - get_filename_component(MATLAB_BIN_ROOT "${MATLAB_MEX}" PATH) - # Strip ./bin/. - get_filename_component(MATLAB_ROOT "${MATLAB_BIN_ROOT}" PATH) - endif() -endif() - -if(NOT EXISTS "${MATLAB_MEX}" AND "${MatlabMex_FIND_REQUIRED}") - message(FATAL_ERROR "Could not find MATLAB mex compiler; try specifying MATLAB_ROOT.") -else() - if(EXISTS "${MATLAB_MEX}") - message(STATUS "Found MATLAB mex compiler: ${MATLAB_MEX}") - message(STATUS "MATLAB root: ${MATLAB_ROOT}") - set(MATLABMEX_FOUND 1) - endif() -endif() - -mark_as_advanced( - MATLAB_MEX - MATLABMEX_FOUND - MATLAB_ROOT -) - From 3801b16e13d1f8a503e2f618a9d0f317142e4e1f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 12 Mar 2021 22:19:43 +0530 Subject: [PATCH 081/729] Removed pointer from default function argument --- src/mlpack/core/data/split_data.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index a97058d29b..12f3b0efec 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -28,7 +28,7 @@ void SplitHelper(const InputType& input, InputType& train, InputType& test, const double testRatio, - const arma::uvec* order = nullptr) + const arma::uvec& order = arma::uvec()) { const size_t testSize = static_cast(input.n_cols * testRatio); const size_t trainSize = input.n_cols - testSize; @@ -38,17 +38,17 @@ void SplitHelper(const InputType& input, test.set_size(input.n_rows, testSize); // Shuffling and spliting simultaneously. - if (order) + if (!order.is_empty()) { if (trainSize > 0) { for (size_t i = 0; i < trainSize; ++i) - train.col(i) = input.col( (*order)(i) ); + train.col(i) = input.col(order(i)); } if (trainSize < input.n_cols) { for (size_t i = trainSize; i < input.n_cols; ++i) - test.col(i - trainSize) = input.col( (*order)(i) ); + test.col(i - trainSize) = input.col(order(i)); } } // Spliting only. @@ -265,8 +265,8 @@ void Split(const arma::Mat& input, { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); - SplitHelper(input, trainData, testData, testRatio, &order); - SplitHelper(inputLabel, trainLabel, testLabel, testRatio, &order); + SplitHelper(input, trainData, testData, testRatio, order); + SplitHelper(inputLabel, trainLabel, testLabel, testRatio, order); } else { @@ -309,7 +309,7 @@ void Split(const arma::Mat& input, { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); - SplitHelper(input, trainData, testData, testRatio, &order); + SplitHelper(input, trainData, testData, testRatio, order); } else { @@ -459,8 +459,8 @@ void Split(const FieldType& input, { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); - SplitHelper(input, trainData, testData, testRatio, &order); - SplitHelper(inputLabel, trainLabel, testLabel, testRatio, &order); + SplitHelper(input, trainData, testData, testRatio, order); + SplitHelper(inputLabel, trainLabel, testLabel, testRatio, order); } else { @@ -511,7 +511,7 @@ void Split(const FieldType& input, { arma::uvec order = arma::shuffle(arma::linspace(0, input.n_cols - 1, input.n_cols)); - SplitHelper(input, trainData, testData, testRatio, &order); + SplitHelper(input, trainData, testData, testRatio, order); } else { From 6ebe71864b46383a79fd46f4fbb194118e11d26d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 13 Mar 2021 08:55:30 +0530 Subject: [PATCH 082/729] Update src/mlpack/core/data/split_data.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/data/split_data.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 12f3b0efec..6347d68a98 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -414,7 +414,7 @@ Split(const arma::Mat& input, * output parameters given (trainData, testData, trainLabel, and testLabel). * * The input dataset must be of type arma::field. It should have the shape - - * (n_rows = 1, n_cols = Number of samples, n_slices = 1) + * (n_rows = 1, n_cols = Number of samples, n_slices = 1). * * NOTE: Here FieldType could be arma::field or arma::field * From 4dd32a662180ba1b6895dce01809c665dc64f104 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 13 Mar 2021 08:55:43 +0530 Subject: [PATCH 083/729] Update src/mlpack/core/data/split_data.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/data/split_data.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/data/split_data.hpp b/src/mlpack/core/data/split_data.hpp index 6347d68a98..f9b0c1558f 100644 --- a/src/mlpack/core/data/split_data.hpp +++ b/src/mlpack/core/data/split_data.hpp @@ -416,7 +416,7 @@ Split(const arma::Mat& input, * The input dataset must be of type arma::field. It should have the shape - * (n_rows = 1, n_cols = Number of samples, n_slices = 1). * - * NOTE: Here FieldType could be arma::field or arma::field + * NOTE: Here FieldType could be arma::field or arma::field. * * @code * arma::field input = loadData(); From 15a37141611a195d8934299b05e2b8ff637a847c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 13 Mar 2021 17:31:32 -0500 Subject: [PATCH 084/729] Remove ElemType template parameter from DecisionTree. --- .../decision_tree/all_categorical_split.hpp | 14 ++-- .../all_categorical_split_impl.hpp | 15 ++-- .../best_binary_numeric_split.hpp | 18 ++-- .../best_binary_numeric_split_impl.hpp | 8 +- .../methods/decision_tree/decision_tree.hpp | 21 +++-- .../decision_tree/decision_tree_impl.hpp | 54 ------------ .../methods/random_forest/random_forest.hpp | 22 ++++- .../random_forest/random_forest_impl.hpp | 84 +++++++------------ src/mlpack/tests/decision_tree_test.cpp | 72 ++++++++++++++-- 9 files changed, 150 insertions(+), 158 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index 2a9de942a9..faa8f16c6b 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -29,7 +29,6 @@ class AllCategoricalSplit { public: // No extra info needed for split. - template class AuxiliarySplitInfo { }; /** @@ -64,8 +63,8 @@ class AllCategoricalSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& aux); + arma::vec& classProbabilities, + AuxiliarySplitInfo& aux); /** * Return the number of children in the split. @@ -73,9 +72,8 @@ class AllCategoricalSplit * @param classProbabilities Auxiliary information for the split. * @param * (aux) Auxiliary information for the split (Unused). */ - template - static size_t NumChildren(const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */); + static size_t NumChildren(const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */); /** * Calculate the direction a point should percolate to. @@ -87,8 +85,8 @@ class AllCategoricalSplit template static size_t CalculateDirection( const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */); + const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */); }; } // namespace tree diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 12ac592ad4..00135625ab 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -26,8 +26,8 @@ double AllCategoricalSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& /* aux */) + arma::vec& classProbabilities, + AuxiliarySplitInfo& /* aux */) { // Count the number of elements in each potential child. const double epsilon = 1e-7; // Tolerance for floating-point errors. @@ -110,20 +110,19 @@ double AllCategoricalSplit::SplitIfBetter( } template -template size_t AllCategoricalSplit::NumChildren( - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */) + const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */) { - return classProbabilities[0]; + return size_t(classProbabilities[0]); } template template size_t AllCategoricalSplit::CalculateDirection( const ElemType& point, - const arma::Col& /* classProbabilities */, - const AuxiliarySplitInfo& /* aux */) + const arma::vec& /* classProbabilities */, + const AuxiliarySplitInfo& /* aux */) { return (size_t) point; } diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 976b810c63..ab081c84fc 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -28,7 +28,6 @@ class BestBinaryNumericSplit { public: // No extra info needed for split. - template class AuxiliarySplitInfo { }; /** @@ -37,6 +36,10 @@ class BestBinaryNumericSplit * return the value 'bestGain'. If a split is made, then classProbabilities * and aux may be modified. * + * It's not necessary that `ElemType` is the same as the type of the data in + * `VecType`---if they are different, casting will be done to store the + * auxiliary information. + * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). * @param data The dimension of data points to check for a split in. @@ -60,15 +63,14 @@ class BestBinaryNumericSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& aux); + arma::vec& classProbabilities, + AuxiliarySplitInfo& aux); /** * Returns 2, since the binary split always has two children. */ - template - static size_t NumChildren(const arma::Col& /* classProbabilities */, - const AuxiliarySplitInfo& /* aux */) + static size_t NumChildren(const arma::vec& /* classProbabilities */, + const AuxiliarySplitInfo& /* aux */) { return 2; } @@ -83,8 +85,8 @@ class BestBinaryNumericSplit template static size_t CalculateDirection( const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */); + const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */); }; } // namespace tree diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index f5b38220ca..14bd0e3fb9 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -25,8 +25,8 @@ double BestBinaryNumericSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& /* aux */) + arma::vec& classProbabilities, + AuxiliarySplitInfo& /* aux */) { // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) @@ -189,8 +189,8 @@ template template size_t BestBinaryNumericSplit::CalculateDirection( const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */) + const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */) { if (point <= classProbabilities[0]) return 0; // Go left. diff --git a/src/mlpack/methods/decision_tree/decision_tree.hpp b/src/mlpack/methods/decision_tree/decision_tree.hpp index 9ab8599aec..fee81909e3 100644 --- a/src/mlpack/methods/decision_tree/decision_tree.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree.hpp @@ -30,18 +30,20 @@ namespace tree { * * The class inherits from the auxiliary split information in order to prevent * an empty auxiliary split information struct from taking any extra size. + * + * Note that `ElemType` is a template parameter controlling the type that is + * used to store split information. In general, you would want to set this to + * be the same as the type of the data that you will be using, but it's not + * required to do that. */ template class NumericSplitType = BestBinaryNumericSplit, template class CategoricalSplitType = AllCategoricalSplit, typename DimensionSelectionType = AllDimensionSelect, - typename ElemType = double, bool NoRecursion = false> class DecisionTree : - public NumericSplitType::template - AuxiliarySplitInfo, - public CategoricalSplitType::template - AuxiliarySplitInfo + public NumericSplitType::AuxiliarySplitInfo, + public CategoricalSplitType::AuxiliarySplitInfo { public: //! Allow access to the numeric split type. @@ -500,9 +502,9 @@ class DecisionTree : //! Note that this class will also hold the members of the NumericSplit and //! CategoricalSplit AuxiliarySplitInfo classes, since it inherits from them. //! We'll define some convenience typedefs here. - typedef typename NumericSplit::template AuxiliarySplitInfo + typedef typename NumericSplit::AuxiliarySplitInfo NumericAuxiliarySplitInfo; - typedef typename CategoricalSplit::template AuxiliarySplitInfo + typedef typename CategoricalSplit::AuxiliarySplitInfo CategoricalAuxiliarySplitInfo; /** @@ -578,13 +580,11 @@ class DecisionTree : template class NumericSplitType = BestBinaryNumericSplit, template class CategoricalSplitType = AllCategoricalSplit, - typename DimensionSelectType = AllDimensionSelect, - typename ElemType = double> + typename DimensionSelectType = AllDimensionSelect> using DecisionStump = DecisionTree; /** @@ -595,7 +595,6 @@ typedef DecisionTree ID3DecisionStump; } // namespace tree } // namespace mlpack diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index b99075f5b2..e4cd77851b 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -22,14 +22,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template DecisionTree::DecisionTree( MatType data, const data::DatasetInfo& datasetInfo, @@ -62,14 +60,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template DecisionTree::DecisionTree( MatType data, LabelsType labels, @@ -100,14 +96,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template DecisionTree::DecisionTree( MatType data, const data::DatasetInfo& datasetInfo, @@ -144,14 +138,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template DecisionTree::DecisionTree( const DecisionTree& other, MatType data, @@ -185,14 +177,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template DecisionTree::DecisionTree( MatType data, LabelsType labels, @@ -229,14 +219,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template DecisionTree::DecisionTree( const DecisionTree& other, MatType data, @@ -275,13 +263,11 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> DecisionTree::DecisionTree(const size_t numClasses) : splitDimension(0), dimensionTypeOrMajorityClass(0), @@ -296,13 +282,11 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> DecisionTree::DecisionTree(const DecisionTree& other) : NumericAuxiliarySplitInfo(other), CategoricalAuxiliarySplitInfo(other), @@ -320,13 +304,11 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> DecisionTree::DecisionTree(DecisionTree&& other) : NumericAuxiliarySplitInfo(std::move(other)), CategoricalAuxiliarySplitInfo(std::move(other)), @@ -344,19 +326,16 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> DecisionTree& DecisionTree::operator=(const DecisionTree& other) { if (this == &other) @@ -388,19 +367,16 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> DecisionTree& DecisionTree::operator=(DecisionTree&& other) { if (this == &other) @@ -432,13 +408,11 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> DecisionTree::~DecisionTree() { for (size_t i = 0; i < children.size(); ++i) @@ -450,14 +424,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template double DecisionTree::Train( MatType data, const data::DatasetInfo& datasetInfo, @@ -493,14 +465,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template double DecisionTree::Train( MatType data, LabelsType labels, @@ -535,14 +505,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template double DecisionTree::Train( MatType data, const data::DatasetInfo& datasetInfo, @@ -584,14 +552,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template double DecisionTree::Train( MatType data, LabelsType labels, @@ -632,14 +598,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template double DecisionTree::Train( MatType& data, const size_t begin, @@ -818,14 +782,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template double DecisionTree::Train( MatType& data, const size_t begin, @@ -976,14 +938,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template size_t DecisionTree::Classify(const VecType& point) const { if (children.size() == 0) @@ -1000,14 +960,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template void DecisionTree::Classify(const VecType& point, size_t& prediction, arma::vec& probabilities) const @@ -1028,14 +986,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template void DecisionTree::Classify(const MatType& data, arma::Row& predictions) const { @@ -1056,14 +1012,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template void DecisionTree::Classify(const MatType& data, arma::Row& predictions, arma::mat& probabilities) const @@ -1095,14 +1049,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template void DecisionTree::serialize(Archive& ar, const uint32_t /* version */) { @@ -1126,14 +1078,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template size_t DecisionTree::CalculateDirection(const VecType& point) const { if ((data::Datatype) dimensionTypeOrMajorityClass == @@ -1150,13 +1100,11 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> size_t DecisionTree::NumClasses() const { // Recurse to the nearest child and return the number of elements in the @@ -1171,14 +1119,12 @@ template class NumericSplitType, template class CategoricalSplitType, typename DimensionSelectionType, - typename ElemType, bool NoRecursion> template void DecisionTree::CalculateClassProbabilities( const RowType& labels, const size_t numClasses, diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index b297f8a5ef..cd0592c675 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -19,17 +19,33 @@ namespace mlpack { namespace tree { +/** + * The RandomForest class provides an implementation of random forests, + * described in Breiman's seminal paper: + * + * @code + * @article{breiman2001random, + * title={Random forests}, + * author={Breiman, Leo}, + * journal={Machine Learning}, + * volume={45}, + * number={1}, + * pages={5--32}, + * year={2001}, + * publisher={Springer} + * } + * @endcode + */ template class NumericSplitType = BestBinaryNumericSplit, - template class CategoricalSplitType = AllCategoricalSplit, - typename ElemType = double> + template class CategoricalSplitType = AllCategoricalSplit> class RandomForest { public: //! Allow access to the underlying decision tree type. typedef DecisionTree DecisionTreeType; + DimensionSelectionType> DecisionTreeType; /** * Construct the random forest without any training or specifying the number diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 124199ee8a..6d5b8d1497 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -22,16 +22,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::RandomForest(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -52,16 +50,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::RandomForest(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -83,16 +79,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::RandomForest(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -113,16 +107,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::RandomForest(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -143,16 +135,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template double RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Train(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -174,16 +164,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template double RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Train(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -205,16 +193,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template double RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Train(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -236,16 +222,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template double RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Train(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -267,16 +251,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template size_t RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Classify(const VecType& point) const { // Pass off to another Classify() overload. @@ -291,16 +273,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template void RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Classify(const VecType& point, size_t& prediction, arma::vec& probabilities) const @@ -338,16 +318,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template void RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Classify(const MatType& data, arma::Row& predictions) const { @@ -373,16 +351,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template void RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Classify(const MatType& data, arma::Row& predictions, arma::mat& probabilities) const @@ -411,16 +387,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template void RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::serialize(Archive& ar, const uint32_t /* version */) { size_t numTrees; @@ -442,16 +416,14 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template double RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::Train(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 7722c54fe4..8956b41674 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -289,7 +289,7 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest", "[DecisionTreeTest]") weights.ones(); arma::vec classProbabilities; - BestBinaryNumericSplit::template AuxiliarySplitInfo aux; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); @@ -327,7 +327,7 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); arma::vec classProbabilities; - BestBinaryNumericSplit::template AuxiliarySplitInfo aux; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); @@ -363,7 +363,7 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") } arma::vec classProbabilities; - BestBinaryNumericSplit::template AuxiliarySplitInfo aux; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); @@ -388,7 +388,7 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest", "[DecisionTreeTest]") weights.ones(); arma::vec classProbabilities; - AllCategoricalSplit::template AuxiliarySplitInfo aux; + AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); @@ -424,7 +424,7 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest", "[DecisionTreeTest]") weights.ones(); arma::vec classProbabilities; - AllCategoricalSplit::template AuxiliarySplitInfo aux; + AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); @@ -457,7 +457,7 @@ TEST_CASE("AllCategoricalSplitNoGainTest", "[DecisionTreeTest]") } arma::vec classProbabilities; - AllCategoricalSplit::template AuxiliarySplitInfo aux; + AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); @@ -701,6 +701,66 @@ TEST_CASE("SimpleGeneralizationTest", "[DecisionTreeTest]") REQUIRE(wdcorrect > 0.75); } +/** + * Test that the decision tree generalizes reasonably when built on float data. + */ +TEST_CASE("SimpleGeneralizationFMatTest", "[DecisionTreeTest]") +{ + arma::fmat inputData; + if (!data::Load("vc2.csv", inputData)) + FAIL("Cannot load test dataset vc2.csv!"); + + arma::Row labels; + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load labels for vc2_labels.txt"); + + // Initialize an all-ones weight matrix. + arma::rowvec weights(labels.n_cols, arma::fill::ones); + + // Build decision tree. + DecisionTree<> d(inputData, labels, 3, 10); // Leaf size of 10. + DecisionTree<> wd(inputData, labels, 3, weights, 10); // Leaf size of 10. + + // Load testing data. + arma::mat testData; + if (!data::Load("vc2_test.csv", testData)) + FAIL("Cannot load test dataset vc2_test.csv!"); + + arma::Mat trueTestLabels; + if (!data::Load("vc2_test_labels.txt", trueTestLabels)) + FAIL("Cannot load labels for vc2_test_labels.txt"); + + // Get the predicted test labels. + arma::Row predictions; + d.Classify(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out the accuracy. + double correct = 0.0; + for (size_t i = 0; i < predictions.n_elem; ++i) + if (predictions[i] == trueTestLabels[i]) + ++correct; + correct /= predictions.n_elem; + + REQUIRE(correct > 0.75); + + // reset the prediction + predictions.zeros(); + wd.Classify(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out the accuracy. + double wdcorrect = 0.0; + for (size_t i = 0; i < predictions.n_elem; ++i) + if (predictions[i] == trueTestLabels[i]) + ++wdcorrect; + wdcorrect /= predictions.n_elem; + + REQUIRE(wdcorrect > 0.75); +} + /** * Test that we can build a decision tree on a simple categorical dataset. */ From 56e3364547af687b10f3fba33da190b7a5c53b3d Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 13 Mar 2021 17:33:48 -0500 Subject: [PATCH 085/729] Update history. --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index f0b696d6ac..cf915012f2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -37,6 +37,9 @@ * Add `Lambda1()`, `Lambda2()`, `UseCholesky()`, and `Tolerance()` members to `LARS` so parameters for training can be modified (#2861). + * Remove unused `ElemType` template parameter from `DecisionTree` and + `RandomForest` (#2874). + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From 0e81b16bdbf7dd172f44185cdf084afdbdd5e74e Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 14 Mar 2021 08:41:15 +0530 Subject: [PATCH 086/729] Changed variables to camel case --- src/mlpack/tests/split_data_test.cpp | 58 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/mlpack/tests/split_data_test.cpp b/src/mlpack/tests/split_data_test.cpp index 075347bd3a..4ef35924c0 100644 --- a/src/mlpack/tests/split_data_test.cpp +++ b/src/mlpack/tests/split_data_test.cpp @@ -223,9 +223,9 @@ TEST_CASE("ZeroRatioStratifiedSplitData", "[SplitDataTest]") // Set the labels to 5 0s and 10 1s. const Row labels = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - const double test_ratio = 0; + const double testRatio = 0; - const auto value = Split(input, labels, test_ratio, false, true); + const auto value = Split(input, labels, testRatio, false, true); REQUIRE(std::get<0>(value).n_cols == 15); REQUIRE(std::get<1>(value).n_cols == 0); REQUIRE(std::get<2>(value).n_cols == 15); @@ -242,9 +242,9 @@ TEST_CASE("TotalRatioStratifiedSplitData", "[SplitDataTest]") // Set the labels to 5 0s and 10 1s. const Row labels = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - const double test_ratio = 1; + const double testRatio = 1; - const auto value = Split(input, labels, test_ratio, false, true); + const auto value = Split(input, labels, testRatio, false, true); REQUIRE(std::get<0>(value).n_cols == 0); REQUIRE(std::get<1>(value).n_cols == 15); REQUIRE(std::get<2>(value).n_cols == 0); @@ -263,9 +263,9 @@ TEST_CASE("StratifiedSplitDataResultTest", "[SplitDataTest]") const Row labels = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; - const double test_ratio = 0.25; + const double testRatio = 0.25; - const auto value = Split(input, labels, test_ratio, true, true); + const auto value = Split(input, labels, testRatio, true, true); REQUIRE(static_cast(find(std::get<2>(value) == 0)).n_rows == 3); REQUIRE(static_cast(find(std::get<2>(value) == 1)).n_rows == 6); REQUIRE(static_cast(find(std::get<2>(value) == 2)).n_rows == 9); @@ -293,22 +293,22 @@ TEST_CASE("StratifiedSplitLargerDataResultTest", "[SplitDataTest]") input.randu(); // 256 0s, 128 1s, 64 2s and 32 3s. - Row zero_label(256); - Row one_label(128); - Row two_label(64); - Row three_label(32); + Row zeroLabel(256); + Row oneLabel(128); + Row twoLabel(64); + Row threeLabel(32); - zero_label.fill(0); - one_label.fill(1); - two_label.fill(2); - three_label.fill(3); + zeroLabel.fill(0); + oneLabel.fill(1); + twoLabel.fill(2); + threeLabel.fill(3); - Row labels = arma::join_rows(zero_label, one_label); - labels = arma::join_rows(labels, two_label); - labels = arma::join_rows(labels, three_label); - const double test_ratio = 0.3; + Row labels = arma::join_rows(zeroLabel, oneLabel); + labels = arma::join_rows(labels, twoLabel); + labels = arma::join_rows(labels, threeLabel); + const double testRatio = 0.3; - const auto value = Split(input, labels, test_ratio, false, true); + const auto value = Split(input, labels, testRatio, false, true); REQUIRE(static_cast(find(std::get<2>(value) == 0)).n_rows == 180); REQUIRE(static_cast(find(std::get<2>(value) == 1)).n_rows == 90); REQUIRE(static_cast(find(std::get<2>(value) == 2)).n_rows == 45); @@ -334,9 +334,9 @@ TEST_CASE("StratifiedSplitRunTimeErrorTest", "[SplitDataTest]") input.randu(); labels.randu(); - const double test_ratio = 0.3; + const double testRatio = 0.3; - REQUIRE_THROWS_AS(Split(input, labels, test_ratio, false, true), + REQUIRE_THROWS_AS(Split(input, labels, testRatio, false, true), std::runtime_error); } @@ -380,12 +380,12 @@ TEST_CASE("SplitMatrixLabeledData", "[SplitDataTest]") REQUIRE(std::get<2>(value).n_cols == 8); REQUIRE(std::get<3>(value).n_cols == 2); - mat input_concat = arma::join_rows(std::get<0>(value), std::get<1>(value)); - mat labels_concat = arma::join_rows(std::get<2>(value), std::get<3>(value)); + mat inputConcat = arma::join_rows(std::get<0>(value), std::get<1>(value)); + mat labelsConcat = arma::join_rows(std::get<2>(value), std::get<3>(value)); // Order matters here. - CheckMatrices(input, input_concat); - CheckMatrices(labels, labels_concat); + CheckMatrices(input, inputConcat); + CheckMatrices(labels, labelsConcat); } /** @@ -414,10 +414,10 @@ TEST_CASE("SplitLabeledDataResultField", "[SplitDataTest]") REQUIRE(std::get<2>(value).n_cols == 1); // Train label. REQUIRE(std::get<3>(value).n_cols == 1); // Test label. - field input_concat = {std::get<0>(value)(0), std::get<1>(value)(0)}; - field label_concat = {std::get<2>(value)(0), std::get<3>(value)(0)}; + field inputConcat = {std::get<0>(value)(0), std::get<1>(value)(0)}; + field labelConcat = {std::get<2>(value)(0), std::get<3>(value)(0)}; // Order matters here. - CheckFields(input, input_concat); - CheckFields(label, label_concat); + CheckFields(input, inputConcat); + CheckFields(label, labelConcat); } From 66fca128002e4eefe9f9239cd167b697159afcad Mon Sep 17 00:00:00 2001 From: Yashwant Date: Sun, 14 Mar 2021 10:02:17 +0530 Subject: [PATCH 087/729] Correction in configure file. --- src/mlpack/bindings/R/mlpack/configure | 4 ++-- src/mlpack/bindings/R/mlpack/src/rcpp_mlpack.h | 2 +- src/mlpack/core.hpp | 2 +- src/mlpack/core/math/random.hpp | 2 +- src/mlpack/core/util/timers.hpp | 18 +++++++++--------- src/mlpack/core/util/to_lower.hpp | 8 ++++---- .../methods/amf/update_rules/nmf_mult_div.hpp | 2 +- .../randomized_block_krylov_svd.cpp | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/mlpack/bindings/R/mlpack/configure b/src/mlpack/bindings/R/mlpack/configure index a571fb1119..fe98704ab8 100755 --- a/src/mlpack/bindings/R/mlpack/configure +++ b/src/mlpack/bindings/R/mlpack/configure @@ -1,8 +1,8 @@ #!/bin/sh -if [ $(uname) = "SunOS" ] +if test `uname` = "SunOS" ; then -sed -i '1 s/$/ -ftrack-macro-expansion=0/' ./src/Makevars +sed '1 s/$/ -ftrack-macro-expansion=0/' ./src/Makevars > ./src/Makevars.tmp && cat ./src/Makevars.tmp > ./src/Makevars && rm ./src/Makevars.tmp fi exit 0 diff --git a/src/mlpack/bindings/R/mlpack/src/rcpp_mlpack.h b/src/mlpack/bindings/R/mlpack/src/rcpp_mlpack.h index 8c285e2193..a66e7ed637 100644 --- a/src/mlpack/bindings/R/mlpack/src/rcpp_mlpack.h +++ b/src/mlpack/bindings/R/mlpack/src/rcpp_mlpack.h @@ -15,7 +15,7 @@ #include -// To suppress Found ‘__assert_fail’, possibly from ‘assert’ (C). +// To suppress Found '__assert_fail', possibly from 'assert' (C). #define BOOST_DISABLE_ASSERTS // Rcpp has its own stream object which cooperates more nicely with R's i/o diff --git a/src/mlpack/core.hpp b/src/mlpack/core.hpp index b4645d2b09..e53eae7e45 100644 --- a/src/mlpack/core.hpp +++ b/src/mlpack/core.hpp @@ -1,4 +1,4 @@ -/** +/** * @file core.hpp * * Include all of the base components required to write mlpack methods, and the diff --git a/src/mlpack/core/math/random.hpp b/src/mlpack/core/math/random.hpp index 738702f4b0..5091a08ff3 100644 --- a/src/mlpack/core/math/random.hpp +++ b/src/mlpack/core/math/random.hpp @@ -42,7 +42,7 @@ inline void RandomSeed(const size_t seed) #if (!defined(BINDING_TYPE) || BINDING_TYPE != BINDING_TYPE_TEST) randGen.seed((uint32_t) seed); #if (BINDING_TYPE == BINDING_TYPE_R) - // To suppress Found ‘srand’, possibly from ‘srand’ (C). + // To suppress Found 'srand', possibly from 'srand' (C). (void) seed; #else srand((unsigned int) seed); diff --git a/src/mlpack/core/util/timers.hpp b/src/mlpack/core/util/timers.hpp index fc83b4984a..8316695377 100644 --- a/src/mlpack/core/util/timers.hpp +++ b/src/mlpack/core/util/timers.hpp @@ -129,23 +129,23 @@ class Timers void PrintTimer(const std::string& timerName); /** -  * Initializes a timer, available like a normal value specified on -  * the command line.  Timers are of type timeval. If a timer is started, then + * Initializes a timer, available like a normal value specified on + * the command line. Timers are of type timeval. If a timer is started, then * stopped, then re-started, then stopped, the final timer value will be the * length of both runs of the timer. -  * -  * @param timerName The name of the timer in question. + * + * @param timerName The name of the timer in question. * @param threadId Id of the thread accessing the timer. -  */ + */ void StartTimer(const std::string& timerName, const std::thread::id& threadId = std::thread::id()); /** -  * Halts the timer, and replaces its value with the delta time from its start. -  * -  * @param timerName The name of the timer in question. + * Halts the timer, and replaces its value with the delta time from its start. + * + * @param timerName The name of the timer in question. * @param threadId Id of the thread accessing the timer. -  */ + */ void StopTimer(const std::string& timerName, const std::thread::id& threadId = std::thread::id()); diff --git a/src/mlpack/core/util/to_lower.hpp b/src/mlpack/core/util/to_lower.hpp index 866b160ffd..6107911e0e 100644 --- a/src/mlpack/core/util/to_lower.hpp +++ b/src/mlpack/core/util/to_lower.hpp @@ -16,11 +16,11 @@ namespace mlpack { namespace util { /** - * Convert a string to lowercase letters. - * - * @param input The string to convert. + * Convert a string to lowercase letters. + * + * @param input The string to convert. * @param output The string to be converted. - */ + */ inline void ToLower(const std::string& input, std::string& output) { std::transform(input.begin(), input.end(), output.begin(), diff --git a/src/mlpack/methods/amf/update_rules/nmf_mult_div.hpp b/src/mlpack/methods/amf/update_rules/nmf_mult_div.hpp index f744dd0b38..8a318a2ad1 100644 --- a/src/mlpack/methods/amf/update_rules/nmf_mult_div.hpp +++ b/src/mlpack/methods/amf/update_rules/nmf_mult_div.hpp @@ -31,7 +31,7 @@ namespace amf { * } * @endcode * - * This is a multiplicative rule that ensures that the Kullback–Leibler + * This is a multiplicative rule that ensures that the Kullback-Leibler * divergence * * \f[ diff --git a/src/mlpack/methods/block_krylov_svd/randomized_block_krylov_svd.cpp b/src/mlpack/methods/block_krylov_svd/randomized_block_krylov_svd.cpp index ff2377f312..101d7cd477 100644 --- a/src/mlpack/methods/block_krylov_svd/randomized_block_krylov_svd.cpp +++ b/src/mlpack/methods/block_krylov_svd/randomized_block_krylov_svd.cpp @@ -83,7 +83,7 @@ void RandomizedBlockKrylovSVD::Apply(const arma::mat& data, arma::qr_econ(Q, R, K); - // Approximate eigenvalues and eigenvectors using Rayleigh–Ritz method. + // Approximate eigenvalues and eigenvectors using Rayleigh-Ritz method. arma::svd_econ(u, s, v, Q.t() * data); // Do economical singular value decomposition and compute only the From c648805aee66773e63c7c287b47e4f5c436cf896 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Mon, 15 Mar 2021 11:28:46 +0530 Subject: [PATCH 088/729] Try some more flags. --- src/mlpack/bindings/R/mlpack/configure | 2 +- src/mlpack/bindings/R/mlpack/src/Makevars.win | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/bindings/R/mlpack/configure b/src/mlpack/bindings/R/mlpack/configure index fe98704ab8..5c0fe63b6a 100755 --- a/src/mlpack/bindings/R/mlpack/configure +++ b/src/mlpack/bindings/R/mlpack/configure @@ -2,7 +2,7 @@ if test `uname` = "SunOS" ; then -sed '1 s/$/ -ftrack-macro-expansion=0/' ./src/Makevars > ./src/Makevars.tmp && cat ./src/Makevars.tmp > ./src/Makevars && rm ./src/Makevars.tmp +sed '1 s/$/ -ftrack-macro-expansion=0 -save-temps/' ./src/Makevars > ./src/Makevars.tmp && cat ./src/Makevars.tmp > ./src/Makevars && rm ./src/Makevars.tmp fi exit 0 diff --git a/src/mlpack/bindings/R/mlpack/src/Makevars.win b/src/mlpack/bindings/R/mlpack/src/Makevars.win index 4cca03b1a5..19c20469e5 100644 --- a/src/mlpack/bindings/R/mlpack/src/Makevars.win +++ b/src/mlpack/bindings/R/mlpack/src/Makevars.win @@ -1,3 +1,3 @@ -PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 +PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 -save-temps PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) CXX_STD = CXX11 From b35386d1948a50d1f157fa4e210a01cb330c9c06 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 15 Mar 2021 12:50:49 -0400 Subject: [PATCH 089/729] Update src/mlpack/tests/decision_tree_test.cpp Co-authored-by: Marcus Edel --- src/mlpack/tests/decision_tree_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 8956b41674..a5c4fd8448 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -718,8 +718,8 @@ TEST_CASE("SimpleGeneralizationFMatTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_cols, arma::fill::ones); // Build decision tree. - DecisionTree<> d(inputData, labels, 3, 10); // Leaf size of 10. - DecisionTree<> wd(inputData, labels, 3, weights, 10); // Leaf size of 10. + DecisionTree<> d(inputData, labels, 3, 10 /* Leaf size of 10. */); + DecisionTree<> wd(inputData, labels, 3, weights, 10 /* Leaf size of 10. */); // Load testing data. arma::mat testData; From 978f6300f21bbc0ef38e7e4b32627872d224818f Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 15 Mar 2021 12:50:54 -0400 Subject: [PATCH 090/729] Update src/mlpack/tests/decision_tree_test.cpp Co-authored-by: Marcus Edel --- src/mlpack/tests/decision_tree_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index a5c4fd8448..f5ff789857 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -745,7 +745,7 @@ TEST_CASE("SimpleGeneralizationFMatTest", "[DecisionTreeTest]") REQUIRE(correct > 0.75); - // reset the prediction + // Reset the prediction. predictions.zeros(); wd.Classify(testData, predictions); From b009aad23dd00a5c6192c9099d4bb3ba5653fa5a Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 16 Mar 2021 22:13:18 +0530 Subject: [PATCH 091/729] Fixed documentation in information_gain.hpp. Fixed a small typo :) --- src/mlpack/methods/decision_tree/information_gain.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/information_gain.hpp b/src/mlpack/methods/decision_tree/information_gain.hpp index 6126a41918..cc48600fa6 100644 --- a/src/mlpack/methods/decision_tree/information_gain.hpp +++ b/src/mlpack/methods/decision_tree/information_gain.hpp @@ -26,7 +26,7 @@ class InformationGain { public: /** - * Evaluate the Gini impurity given a vector of class weight counts. + * Evaluate the information gain given a vector of class weight counts. */ template static double EvaluatePtr(const CountType* counts, From 085519be4f52856d06eb40422e2042a3af7f458d Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 16 Mar 2021 15:50:08 -0400 Subject: [PATCH 092/729] Prefer the batch implementation. --- .../core/dists/gaussian_distribution.hpp | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/mlpack/core/dists/gaussian_distribution.hpp b/src/mlpack/core/dists/gaussian_distribution.hpp index d7d3800c06..2d47f7d686 100644 --- a/src/mlpack/core/dists/gaussian_distribution.hpp +++ b/src/mlpack/core/dists/gaussian_distribution.hpp @@ -90,11 +90,11 @@ class GaussianDistribution */ void Probability(const arma::mat& x, arma::vec& probabilities) const { - probabilities.set_size(x.n_cols); - for (size_t i = 0; i < x.n_cols; ++i) - { - probabilities(i) = Probability(x.unsafe_col(i)); - } + // Use LogProbability(), then transform the log-probabilities out of + // logspace. + arma::vec logProbs; + LogProbability(x, logProbs); + probabilities = arma::exp(logProbs); } /** @@ -110,17 +110,11 @@ class GaussianDistribution // Column i of 'diffs' is the difference between x.col(i) and the mean. arma::mat diffs = x; diffs.each_col() -= mean; - // Now, we only want to calculate the diagonal elements of (diffs' * cov^-1 - // * diffs). We just don't need any of the other elements. We can - // calculate the right hand part of the equation (instead of the left side) - // so that later we are referencing columns, not rows -- that is faster. - const arma::mat rhs = -0.5 * invCov * diffs; - arma::vec logExponents(diffs.n_cols); // We will now fill this. - for (size_t i = 0; i < diffs.n_cols; ++i) - logExponents(i) = accu(diffs.unsafe_col(i) % rhs.unsafe_col(i)); + // Now, we only want to calculate the diagonal elements of (diffs' * cov^-1 + // * diffs). We just don't need any of the other elements. logProbabilities = -0.5 * x.n_rows * log2pi - 0.5 * logDetCov + - logExponents; + sum(diffs % (-0.5 * invCov * diffs), 0).t(); } /** From 204129d6a91c73190c840da76713c56a494a919a Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 16 Mar 2021 15:50:43 -0400 Subject: [PATCH 093/729] Slightly more efficient implementation of LogAdd(). --- src/mlpack/core/math/log_add_impl.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/math/log_add_impl.hpp b/src/mlpack/core/math/log_add_impl.hpp index f86dce4cd9..559c94149f 100644 --- a/src/mlpack/core/math/log_add_impl.hpp +++ b/src/mlpack/core/math/log_add_impl.hpp @@ -47,8 +47,10 @@ T LogAdd(T x, T y) r = y; } - return (r == -std::numeric_limits::infinity() || - d == -std::numeric_limits::infinity()) ? r : r + log(1 + exp(d)); + if (std::isinf(d) || std::isinf(r)) + return r; + + return r + log(1 + exp(d)); } /** From b3e23abf0fa1f149e7780bbf667532a0238e9628 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 16 Mar 2021 15:53:53 -0400 Subject: [PATCH 094/729] Better log-sum-exp utilities. --- src/mlpack/core/math/log_add.hpp | 34 ++++++++++++- src/mlpack/core/math/log_add_impl.hpp | 72 +++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/src/mlpack/core/math/log_add.hpp b/src/mlpack/core/math/log_add.hpp index 51497f8d0d..6613954f11 100644 --- a/src/mlpack/core/math/log_add.hpp +++ b/src/mlpack/core/math/log_add.hpp @@ -28,7 +28,7 @@ template T LogAdd(T x, T y); /** - * Sum a vector of log values. (T should be an Armadillo type.) + * Log-sum a vector of log values. (T should be an Armadillo type.) * * @param x vector of log values * @return log(e^x0 + e^x1 + ...) @@ -36,6 +36,38 @@ T LogAdd(T x, T y); template typename T::elem_type AccuLog(const T& x); +/** + * Compute the sum of exponentials of each element in each column, then compute + * the log of that. If InPlace is true, then the values of `y` will also be + * added to the sum. + * + * That is, if InPlace is false, then this method will set `y` such that: + * + * `y_i = log(sum(exp(x.col(i))))` + * + * and if InPlace is true, then `y` will be set such that: + * + * `y_i = log(sum(exp(x.col(i))) + exp(y_i))`. + */ +template +void LogSumExp(const T& x, arma::Col& y); + +/** + * Compute the sum of exponentials of each element in each row, then compute the + * log of that. If InPlace is true, then the values of `y` will also be added + * to the sum. + * + * That is, if InPlace is false, then this method will set `y` such that: + * + * `y_i = log(sum(exp(x.row(i))))` + * + * and if InPlace is true, then `y` will be set such that: + * + * `y_i = log(sum(exp(x.row(i))) + exp(y_i))`. + */ +template +void LogSumExpT(const T& x, arma::Col& y); + } // namespace math } // namespace mlpack diff --git a/src/mlpack/core/math/log_add_impl.hpp b/src/mlpack/core/math/log_add_impl.hpp index 559c94149f..17f93c0055 100644 --- a/src/mlpack/core/math/log_add_impl.hpp +++ b/src/mlpack/core/math/log_add_impl.hpp @@ -62,15 +62,77 @@ T LogAdd(T x, T y) template typename T::elem_type AccuLog(const T& x) { - typename T::elem_type sum = - -std::numeric_limits::infinity(); + typename T::elem_type maxVal = max(x); + if (maxVal == -std::numeric_limits::infinity()) + return maxVal; - for (size_t i = 0; i < x.n_elem; ++i) + return maxVal + log(sum(exp(x - maxVal)));; +} + +/** + * Compute the sum of exponentials of each element in each column, then compute + * the log of that. If InPlace is true, then the values of `y` will also be + * added to the sum. + */ +template +void LogSumExp(const T& x, arma::Col& y) +{ + arma::Col maxs; + + if (InPlace) { - sum = LogAdd(sum, x[i]); + // Compute the maximum in each column (treating y as a column too). + maxs = max(max(x, 1), y); + + y = maxs + log(sum(exp(x - repmat(maxs, 1, x.n_cols)), 1) + + exp(y - maxs)); + } + else + { + // Compute the maximum element in each column. + maxs = max(x, 1); + + y = maxs + log(sum(exp(x - repmat(maxs, 1, x.n_cols)), 1)); } - return sum; + if (maxs.has_inf()) + { + y.replace(-std::numeric_limits::quiet_NaN(), + -std::numeric_limits::infinity()); + } +} + +/** + * Compute the sum of exponentials of each element in each row, then compute the + * log of that. If InPlace is true, then the values of `y` will also be added + * to the sum. + */ +template +void LogSumExpT(const T& x, arma::Col& y) +{ + arma::Row maxs; + + if (InPlace) + { + // Compute the maximum element in each column. + maxs = max(max(x, 0), y.t()); + + y = maxs.t() + log(sum(exp(x - repmat(maxs, x.n_rows, 1)), 0) + + exp(y.t() - maxs)).t(); + } + else + { + // Compute the maximum element in each column. + arma::Row maxs = max(x, 0); + + y = (maxs + log(sum(exp(x - repmat(maxs, x.n_rows, 1)), 0))).t(); + } + + if (maxs.has_inf()) + { + y.replace(-std::numeric_limits::quiet_NaN(), + -std::numeric_limits::infinity()); + } } } // namespace math From b5f840834f5094aca663fb90472a0e1c95037061 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 16 Mar 2021 15:54:07 -0400 Subject: [PATCH 095/729] Use LogSumExp() computation in batch. --- src/mlpack/methods/gmm/diagonal_gmm.cpp | 11 +++-------- src/mlpack/methods/gmm/gmm.cpp | 11 +++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/mlpack/methods/gmm/diagonal_gmm.cpp b/src/mlpack/methods/gmm/diagonal_gmm.cpp index 065bf57adb..ab7c30e1ac 100644 --- a/src/mlpack/methods/gmm/diagonal_gmm.cpp +++ b/src/mlpack/methods/gmm/diagonal_gmm.cpp @@ -92,15 +92,10 @@ void DiagonalGMM::LogProbability(const arma::mat& observation, // Save log(weights) as a vector. arma::vec logWeights = arma::log(weights); - // Compute Log Probability. - logProb = logProb.t(); - - for (size_t j = 0; j < observation.n_cols; j++) - { - const arma::vec sumVec = logWeights + logProb.unsafe_col(j); - logProbs(j) = math::AccuLog(sumVec); - } + // Compute log-probability. + logProb += repmat(logWeights.t(), logProb.n_rows, 1); + math::LogSumExp(logProb, logProbs); } /** diff --git a/src/mlpack/methods/gmm/gmm.cpp b/src/mlpack/methods/gmm/gmm.cpp index 6ee2e7e85e..42603d45c7 100644 --- a/src/mlpack/methods/gmm/gmm.cpp +++ b/src/mlpack/methods/gmm/gmm.cpp @@ -93,15 +93,10 @@ void GMM::LogProbability(const arma::mat& observation, // Save log(weights) as a vector. arma::vec logWeights = arma::log(weights); - // Compute Log Probability. - logProb = logProb.t(); - - for (size_t j = 0; j < observation.n_cols; j++) - { - const arma::vec sumVec = logWeights + logProb.unsafe_col(j); - logProbs(j) = math::AccuLog(sumVec); - } + // Compute log-probability. + logProb += repmat(logWeights.t(), logProb.n_rows, 1); + math::LogSumExp(logProb, logProbs); } /** From bc338df4470fd554dffce6a8c7874bb36a345d98 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 16 Mar 2021 15:54:18 -0400 Subject: [PATCH 096/729] Use LogSumExp() computations throughout (where possible). --- src/mlpack/methods/hmm/hmm_impl.hpp | 96 ++++++++++++++--------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/mlpack/methods/hmm/hmm_impl.hpp b/src/mlpack/methods/hmm/hmm_impl.hpp index 0449484250..05b4de2e3f 100644 --- a/src/mlpack/methods/hmm/hmm_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_impl.hpp @@ -149,8 +149,8 @@ double HMM::Train(const std::vector& dataSeq) backwardLog, logScales); // Add to estimate of initial probability for state j. - for (size_t j = 0; j < logTransition.n_cols; ++j) - newLogInitial[j] = math::LogAdd(newLogInitial[j], stateLogProb(j, 0)); + math::LogSumExp(stateLogProb.unsafe_col(0), + newLogInitial); // Define a variable to store the value of log-probability for data. arma::mat logProbs(dataSeq[seq].n_cols, logTransition.n_rows); @@ -163,7 +163,6 @@ double HMM::Train(const std::vector& dataSeq) emission[i].LogProbability(dataSeq[seq], alias); } - // Now re-estimate the parameters. This is the M-step. // pi_i = sum_d ((1 / P(seq[d])) sum_t (f(i, 0) b(i, 0)) // T_ij = sum_d ((1 / P(seq[d])) sum_t (f(i, t) T_ij E_i(seq[d][t]) b(i, @@ -172,24 +171,31 @@ double HMM::Train(const std::vector& dataSeq) // We store the new estimates in a different matrix. for (size_t t = 0; t < dataSeq[seq].n_cols; ++t) { - for (size_t j = 0; j < logTransition.n_cols; ++j) + // Assemble temporary vector that's used in log-sum computation. + if (t < dataSeq[seq].n_cols - 1) { - if (t < dataSeq[seq].n_cols - 1) - { - // Estimate of T_ij (probability of transition from state j to state - // i). We postpone multiplication of the old T_ij until later. - for (size_t i = 0; i < logTransition.n_rows; i++) - { - newLogTransition(i, j) = math::LogAdd(newLogTransition(i, j), - forwardLog(j, t) + backwardLog(i, t + 1) + logProbs(t + 1, i) - - logScales[t + 1]); - } - } + // This term is the same across all states, so compute it once and + // cache it. + const arma::vec tmp = backwardLog.col(t + 1) + + logProbs.row(t + 1).t() - logScales[t + 1]; + arma::vec output; + math::LogSumExp(tmp, output); - // Add to list of emission observations, for Distribution::Train(). - emissionList.col(sumTime) = dataSeq[seq].col(t); - emissionProb[j][sumTime] = exp(stateLogProb(j, t)); + for (size_t j = 0; j < logTransition.n_cols; ++j) + { + // Compute the estimate of T_ij (probability of transition from + // state j to state i). We postpone multiplication of the old T_ij + // until later. + arma::vec tmp2 = output + forwardLog(j, t); + arma::vec alias = newLogTransition.unsafe_col(j); + math::LogSumExp(tmp2, alias); + } } + + // Add to list of emission observations, for Distribution::Train(). + for (size_t j = 0; j < logTransition.n_cols; ++j) + emissionProb[j][sumTime] = exp(stateLogProb(j, t)); + emissionList.col(sumTime) = dataSeq[seq].col(t); sumTime++; } } @@ -712,14 +718,12 @@ arma::vec HMM::ForwardAtT0(const arma::vec& emissionLogProb, // P(X_k | o_{1:k}) for all possible states X_k, for each time point k. ConvertToLogSpace(); - arma::vec forwardLogProb(logTransition.n_rows); - forwardLogProb.fill(-std::numeric_limits::infinity()); // The first entry in the forward algorithm uses the initial state // probabilities. Note that MATLAB assumes that the starting state (at // t = -1) is state 0; this is not our assumption here. To force that // behavior, you could append a single starting state to every single data // sequence and that should produce results in line with MATLAB. - forwardLogProb = logInitial + emissionLogProb; + arma::vec forwardLogProb = logInitial + emissionLogProb; // Normalize probability. logScales = math::AccuLog(forwardLogProb); @@ -741,17 +745,16 @@ arma::vec HMM::ForwardAtTn(const arma::vec& emissionLogProb, // Our goal is to calculate the forward probabilities: // P(X_k | o_{1:k}) for all possible states X_k, for each time point k. - arma::vec forwardLogProb(logTransition.n_rows); - forwardLogProb.fill(-std::numeric_limits::infinity()); - // Now compute the probabilities for each successive observation. - for (size_t state = 0; state < logTransition.n_rows; state++) - { - // The forward probability of state j at time t is the sum over all - // states of the probability of the previous state transitioning to - // the current state and emitting the given observation. - arma::vec tmp = prevForwardLogProb + logTransition.row(state).t(); - forwardLogProb(state) = math::AccuLog(tmp) + emissionLogProb(state); - } + // The forward probability of state j at time t is the sum over all states of + // the probability of the previous state transitioning to the current state + // and emitting the given observation. To do this computation in log-space, + // we can use LogSumExp(). + arma::vec forwardLogProb; + arma::mat tmp = logTransition + repmat(prevForwardLogProb.t(), + logTransition.n_rows, 1); + math::LogSumExp(tmp, forwardLogProb); + forwardLogProb += emissionLogProb; + // Normalize probability. logScales = math::AccuLog(forwardLogProb); if (std::isfinite(logScales)) @@ -809,23 +812,20 @@ void HMM::Backward(const arma::mat& dataSeq, // Now step backwards through all other observations. for (size_t t = dataSeq.n_cols - 2; t + 1 > 0; t--) { - for (size_t j = 0; j < logTransition.n_rows; j++) - { - // The backward probability of state j at time t is the sum over all state - // of the probability of the next state having been a transition from the - // current state multiplied by the probability of each of those states - // emitting the given observation. - for (size_t state = 0; state < logTransition.n_rows; state++) - { - backwardLogProb(j, t) = math::LogAdd(backwardLogProb(j, t), - logTransition(state, j) + backwardLogProb(state, t + 1) - + logProbs(t + 1, state)); - } + // The backward probability of state j at time t is the sum over all + // states of the probability of the next state having been a transition + // from the current state multiplied by the probability of each of those + // states emitting the given observation. To compute this in log-space, we + // can use LogSumExpT(). + const arma::mat tmp = logTransition + + repmat(backwardLogProb.col(t + 1), 1, logTransition.n_cols) + + repmat(logProbs.row(t + 1).t(), 1, logTransition.n_cols); + arma::vec alias = backwardLogProb.unsafe_col(t); + math::LogSumExpT(tmp, alias); - // Normalize by the weights from the forward algorithm. - if (std::isfinite(logScales[t + 1])) - backwardLogProb(j, t) -= logScales[t + 1]; - } + // Normalize by the weights from the forward algorithm. + if (std::isfinite(logScales[t + 1])) + backwardLogProb.col(t) -= logScales[t + 1]; } } From 00b157cd33bbf1f2bfd3ebaf952b5d8eedfbfbf8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 16 Mar 2021 16:15:14 -0400 Subject: [PATCH 097/729] Oops, remove doubly-specified default template argument. --- src/mlpack/core/math/log_add_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/math/log_add_impl.hpp b/src/mlpack/core/math/log_add_impl.hpp index 17f93c0055..6be66b91b9 100644 --- a/src/mlpack/core/math/log_add_impl.hpp +++ b/src/mlpack/core/math/log_add_impl.hpp @@ -74,7 +74,7 @@ typename T::elem_type AccuLog(const T& x) * the log of that. If InPlace is true, then the values of `y` will also be * added to the sum. */ -template +template void LogSumExp(const T& x, arma::Col& y) { arma::Col maxs; @@ -107,7 +107,7 @@ void LogSumExp(const T& x, arma::Col& y) * log of that. If InPlace is true, then the values of `y` will also be added * to the sum. */ -template +template void LogSumExpT(const T& x, arma::Col& y) { arma::Row maxs; From 2f0bf29667d2d1c536ab3a68e260b2c4964b0c4b Mon Sep 17 00:00:00 2001 From: Yashwant Date: Wed, 17 Mar 2021 12:56:23 +0530 Subject: [PATCH 098/729] Add flags as suggested by @rcurtin. --- src/mlpack/bindings/R/mlpack/configure | 2 +- src/mlpack/bindings/R/mlpack/src/Makevars.win | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/bindings/R/mlpack/configure b/src/mlpack/bindings/R/mlpack/configure index 5c0fe63b6a..608e27d17e 100755 --- a/src/mlpack/bindings/R/mlpack/configure +++ b/src/mlpack/bindings/R/mlpack/configure @@ -2,7 +2,7 @@ if test `uname` = "SunOS" ; then -sed '1 s/$/ -ftrack-macro-expansion=0 -save-temps/' ./src/Makevars > ./src/Makevars.tmp && cat ./src/Makevars.tmp > ./src/Makevars && rm ./src/Makevars.tmp +sed '1 s/$/ -ftrack-macro-expansion=0 -pipe --param ggc-min-expand=10 --param ggc-min-heapsize=8192/' ./src/Makevars > ./src/Makevars.tmp && cat ./src/Makevars.tmp > ./src/Makevars && rm ./src/Makevars.tmp fi exit 0 diff --git a/src/mlpack/bindings/R/mlpack/src/Makevars.win b/src/mlpack/bindings/R/mlpack/src/Makevars.win index 19c20469e5..12f71348e6 100644 --- a/src/mlpack/bindings/R/mlpack/src/Makevars.win +++ b/src/mlpack/bindings/R/mlpack/src/Makevars.win @@ -1,3 +1,3 @@ -PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 -save-temps +PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 -pipe --param ggc-min-expand=10 --param ggc-min-heapsize=8192 PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) CXX_STD = CXX11 From fd43668cdaffc1271063a5fa5ce3e17c673181b5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 18:43:20 +0530 Subject: [PATCH 099/729] Added WarmStart template parameter --- .../methods/random_forest/random_forest.hpp | 2 +- .../random_forest/random_forest_impl.hpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index b297f8a5ef..23673a9592 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -359,7 +359,7 @@ class RandomForest * @tparam MatType The type of data matrix (i.e. arma::mat). * @return The average entropy of all the decision trees trained under forest. */ - template + template double Train(const MatType& data, const data::DatasetInfo& datasetInfo, const arma::Row& labels, diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 124199ee8a..d79b252791 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -44,7 +44,7 @@ RandomForest< // Pass off work to the Train() method. data::DatasetInfo info; // Ignored. arma::rowvec weights; // Fake weights, not used. - Train(dataset, info, labels, numClasses, weights, numTrees, + Train(dataset, info, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -74,7 +74,7 @@ RandomForest< { // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. - Train(dataset, datasetInfo, labels, numClasses, weights, + Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -105,7 +105,7 @@ RandomForest< { // Pass off work to the Train() method. data::DatasetInfo info; // Ignored by Train(). - Train(dataset, info, labels, numClasses, weights, numTrees, + Train(dataset, info, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -135,7 +135,7 @@ RandomForest< DimensionSelectionType dimensionSelector) { // Pass off work to the Train() method. - Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, + Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -165,7 +165,7 @@ double RandomForest< // Pass off to Train(). data::DatasetInfo info; // Ignored by Train(). arma::rowvec weights; // Ignored by Train(). - return Train(dataset, info, labels, numClasses, weights, + return Train(dataset, info, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -196,7 +196,7 @@ double RandomForest< { // Pass off to Train(). arma::rowvec weights; // Ignored by Train(). - return Train(dataset, datasetInfo, labels, numClasses, weights, + return Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -227,7 +227,7 @@ double RandomForest< { // Pass off to Train(). data::DatasetInfo info; // Ignored by Train(). - return Train(dataset, info, labels, numClasses, weights, + return Train(dataset, info, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -258,7 +258,7 @@ double RandomForest< DimensionSelectionType dimensionSelector) { // Pass off to Train(). - return Train(dataset, datasetInfo, labels, numClasses, weights, + return Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -445,7 +445,7 @@ template< template class CategoricalSplitType, typename ElemType > -template +template double RandomForest< FitnessFunction, DimensionSelectionType, From e5935d4eb0d07ba9fd2e62c102e12c2fcafc28ff Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 18:51:00 +0530 Subject: [PATCH 100/729] Added warmStart to Train function definition --- src/mlpack/methods/random_forest/random_forest.hpp | 12 ++++++++---- .../methods/random_forest/random_forest_impl.hpp | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 23673a9592..f3aea15896 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -179,7 +179,8 @@ class RandomForest const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = - DimensionSelectionType()); + DimensionSelectionType(), + bool warmStart = false); /** * Train the random forest on the given labeled training data with the given @@ -211,7 +212,8 @@ class RandomForest const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = - DimensionSelectionType()); + DimensionSelectionType(), + bool warmStart = false); /** * Train the random forest on the given weighted labeled training data with @@ -241,7 +243,8 @@ class RandomForest const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = - DimensionSelectionType()); + DimensionSelectionType(), + bool warmStart = false); /** * Train the random forest on the given weighted labeled training data with @@ -274,7 +277,8 @@ class RandomForest const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = - DimensionSelectionType()); + DimensionSelectionType(), + bool warmStart = false); /** * Predict the class of the given point. If the random forest has not been diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index d79b252791..da2c6ef470 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -160,7 +160,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector, + bool warmStart) { // Pass off to Train(). data::DatasetInfo info; // Ignored by Train(). @@ -192,7 +193,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector, + bool warmStart) { // Pass off to Train(). arma::rowvec weights; // Ignored by Train(). @@ -223,7 +225,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector, + bool warmStart) { // Pass off to Train(). data::DatasetInfo info; // Ignored by Train(). @@ -255,7 +258,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector, + bool warmStart) { // Pass off to Train(). return Train(dataset, datasetInfo, labels, numClasses, weights, From 65578cbd2e68be1f75371392f805d0f4db38380c Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 19:11:39 +0530 Subject: [PATCH 101/729] Fixed template instantiation error --- .../random_forest/random_forest_impl.hpp | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index da2c6ef470..5044b0fd66 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -164,11 +164,16 @@ double RandomForest< bool warmStart) { // Pass off to Train(). - data::DatasetInfo info; // Ignored by Train(). + data::DatasetInfo datasetInfo; // Ignored by Train(). arma::rowvec weights; // Ignored by Train(). - return Train(dataset, info, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + if (warmStart) + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); + else + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } template< @@ -198,9 +203,14 @@ double RandomForest< { // Pass off to Train(). arma::rowvec weights; // Ignored by Train(). - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + if (warmStart) + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); + else + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } template< @@ -229,10 +239,15 @@ double RandomForest< bool warmStart) { // Pass off to Train(). - data::DatasetInfo info; // Ignored by Train(). - return Train(dataset, info, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + data::DatasetInfo datasetInfo; // Ignored by Train(). + if (warmStart) + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); + else + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } template< @@ -262,9 +277,14 @@ double RandomForest< bool warmStart) { // Pass off to Train(). - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + if (warmStart) + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); + else + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } template< From 552532c84ed68bfe12f89bfcd7ff0bfa745c0999 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 19:33:18 +0530 Subject: [PATCH 102/729] Added test for WarmStart --- .../random_forest/random_forest_impl.hpp | 4 +++ src/mlpack/tests/random_forest_test.cpp | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 5044b0fd66..c13526d005 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -488,6 +488,10 @@ double RandomForest< DimensionSelectionType& dimensionSelector) { // Train each tree individually. + if (WarmStart) + { + std::cout << "Warm start\n"; + } trees.resize(numTrees); // This will fill the vector with untrained trees. double avgGain = 0.0; diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 95d1f09a6a..f1974d4bd5 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -498,3 +498,28 @@ TEST_CASE("DifferentTreesTest", "[RandomForestTest]") REQUIRE(success == true); } + +/** + * Test that RandomForest::Train() when passed warmStart = True trains on top + * of exixting forest and adds the newly trained trees to the previously + * exixting forest. + */ +TEST_CASE("WarmStartTreesTest", "[RandomForestTest]") +{ + arma::mat trainingData; + arma::Row trainingLabels; + data::DatasetInfo di; + MockCategoricalData(trainingData, trainingLabels, di); + + // Train a random forest. + RandomForest<> rf(trainingData, di, trainingLabels, 5, 25 /* 25 trees */, 1, + 1e-7, 0, MultipleRandomDimensionSelect(4)); + + REQUIRE(rf.NumTrees() == 25); + + rf.Train(trainingData, di, trainingLabels, 5, 20 /* 20 trees */, 1, 1e-7, 0, + MultipleRandomDimensionSelect(4), true /* warmStart */); + + // TODO: It needs to be updated to 25 + 20 once implementation is ready. + REQUIRE(rf.NumTrees() == 20); +} \ No newline at end of file From 2af1cd9630edd845a467f5d2847599615b8b530e Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 20:36:10 +0530 Subject: [PATCH 103/729] Implemented the WarmStart functionality --- .../methods/random_forest/random_forest.hpp | 3 ++ .../random_forest/random_forest_impl.hpp | 37 ++++++++++++++----- src/mlpack/tests/random_forest_test.cpp | 3 +- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index f3aea15896..4dfc0504d9 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -377,6 +377,9 @@ class RandomForest //! The trees in the forest. std::vector trees; + + //! The average gain of the forest. + double avgGain = 0.0; }; } // namespace tree diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index c13526d005..abfa6bd270 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -460,6 +460,7 @@ void RandomForest< trees.resize(numTrees); ar(CEREAL_NVP(trees)); + ar(CEREAL_NVP(avgGain)); } template< @@ -487,14 +488,22 @@ double RandomForest< const size_t maximumDepth, DimensionSelectionType& dimensionSelector) { - // Train each tree individually. + size_t oldNumTrees = trees.size(); + // Convert avgGain to total gain. + avgGain *= oldNumTrees; + if (WarmStart) { - std::cout << "Warm start\n"; + // This will extend the vector with untrained trees. + trees.resize(trees.size() + numTrees); + } + else + { + // This will fill the vector with untrained trees. + trees.resize(numTrees); } - trees.resize(numTrees); // This will fill the vector with untrained trees. - double avgGain = 0.0; + // Train each tree individually. #pragma omp parallel for reduction( + : avgGain) for (omp_size_t i = 0; i < numTrees; ++i) { @@ -507,18 +516,19 @@ double RandomForest< Timer::Stop("bootstrap"); // Now build the decision tree. + DecisionTreeType tmpTree; Timer::Start("train_tree"); if (UseWeights) { if (UseDatasetInfo) { - avgGain += trees[i].Train(bootstrapDataset, datasetInfo, + avgGain += tmpTree.Train(bootstrapDataset, datasetInfo, bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } else { - avgGain += trees[i].Train(bootstrapDataset, bootstrapLabels, numClasses, + avgGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -527,19 +537,28 @@ double RandomForest< { if (UseDatasetInfo) { - avgGain += trees[i].Train(bootstrapDataset, datasetInfo, + avgGain += tmpTree.Train(bootstrapDataset, datasetInfo, bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } else { - avgGain += trees[i].Train(bootstrapDataset, bootstrapLabels, numClasses, + avgGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } } + + // Storing the trained tree at the desired index. + if (WarmStart) + trees[oldNumTrees + i] = tmpTree; + else + trees[i] = tmpTree; + Timer::Stop("train_tree"); } - return avgGain / numTrees; + + avgGain /= trees.size(); + return avgGain; } } // namespace tree diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index f1974d4bd5..44fec47f3d 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -520,6 +520,5 @@ TEST_CASE("WarmStartTreesTest", "[RandomForestTest]") rf.Train(trainingData, di, trainingLabels, 5, 20 /* 20 trees */, 1, 1e-7, 0, MultipleRandomDimensionSelect(4), true /* warmStart */); - // TODO: It needs to be updated to 25 + 20 once implementation is ready. - REQUIRE(rf.NumTrees() == 20); + REQUIRE(rf.NumTrees() == 25 + 20); } \ No newline at end of file From 4bad3a1e550c82aca93e0e3ca08b10716b737026 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 20:48:56 +0530 Subject: [PATCH 104/729] Added test for checking quality of predictions --- src/mlpack/tests/random_forest_test.cpp | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 44fec47f3d..2c3cc246d1 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -521,4 +521,40 @@ TEST_CASE("WarmStartTreesTest", "[RandomForestTest]") MultipleRandomDimensionSelect(4), true /* warmStart */); REQUIRE(rf.NumTrees() == 25 + 20); +} + +/** + * Test that RandomForest::Train() when passed warmStart = True does not drop + * prediction quality on train data. Note that prediction quality may drop due + * to overfitting in some cases. + */ +TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") +{ + arma::mat trainingData; + arma::Row trainingLabels; + data::DatasetInfo di; + MockCategoricalData(trainingData, trainingLabels, di); + + // Train a random forest. + RandomForest<> rf(trainingData, di, trainingLabels, 5, 25 /* 25 trees */, 1, + 1e-7, 0, MultipleRandomDimensionSelect(4)); + + // Get performance statistics on train data. + arma::Row oldPredictions; + rf.Classify(trainingData, oldPredictions); + + // Calculate the number of correct points. + size_t oldCorrect = arma::accu(oldPredictions == trainingLabels); + + rf.Train(trainingData, di, trainingLabels, 5, 20 /* 20 trees */, 1, 1e-7, 0, + MultipleRandomDimensionSelect(4), true /* warmStart */); + + // Get performance statistics on train data. + arma::Row newPredictions; + rf.Classify(trainingData, newPredictions); + + // Calculate the number of correct points. + size_t newCorrect = arma::accu(newPredictions == trainingLabels); + + REQUIRE(newCorrect - oldCorrect >= 0); } \ No newline at end of file From 2f4de23208eda8229a1ea0cc7c1564041b3f0a9c Mon Sep 17 00:00:00 2001 From: mayank raj Date: Wed, 17 Mar 2021 20:51:23 +0530 Subject: [PATCH 105/729] added tanh exponential activation function --- .../ann/activation_functions/CMakeLists.txt | 1 + .../tanh_exponential_function.hpp | 83 +++++++++++++++++++ src/mlpack/methods/ann/layer/base_layer.hpp | 13 +++ .../tests/activation_functions_test.cpp | 16 ++++ 4 files changed, 113 insertions(+) create mode 100644 src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp diff --git a/src/mlpack/methods/ann/activation_functions/CMakeLists.txt b/src/mlpack/methods/ann/activation_functions/CMakeLists.txt index d5c0868c1c..1639817716 100644 --- a/src/mlpack/methods/ann/activation_functions/CMakeLists.txt +++ b/src/mlpack/methods/ann/activation_functions/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCES poisson1_function.hpp gaussian_function.hpp hard_swish_function.hpp + tanh_exponential_function.hpp ) # Add directory name to sources. diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp new file mode 100644 index 0000000000..8bbc3c3771 --- /dev/null +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -0,0 +1,83 @@ +/** + * @file methods/ann/activation_functions/tanh_exponential_function.hpp + * @author Mayank Raj + * + * Definition and implementation of the Tanh exponential function. + * + * 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 TANH_EXPONENTIAL_FUNCTION_HPP_INCLUDED +#define TANH_EXPONENTIAL_FUNCTION_HPP_INCLUDED + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * The TanhExp function, defined by + * + * @f{eqnarray*}{ + * f(x) = x * tanh(e^x)\\ + * f'(x) = tanh(e^x) + x*e^x*(sech(e^x))^2\\ + * @f} + */ + class TanhExpFunction +{ + public: + /** + * Computes the TanhExp function. + * + * @param x Input data. + * @return f(x). + */ + static double Fn(const double x) + { + return x*std::tanh(std::exp(x)); + } + + /** + * Computes the TanhExp function. + * + * @param x Input data. + * @param y The resulting output activation. + */ + template + static void Fn(const InputVecType& x, OutputVecType& y) + { + y = x*arma::tanh(arma::exp(x)); + } + + /** + * Computes the first derivative of the TanhExp function. + * + * @param y Input activation. + * @return f'(x) + */ + static double Deriv(const double y) + { + return std::tanh(std::exp(y)) + + y*std::exp(y)*std::pow(std::sech(std::exp(y)),2); + } + + /** + * Computes the first derivatives of the tanh function. + * + * @param y Input activations. + * @param x The resulting derivatives. + */ + template + static void Deriv(const InputVecType& y, OutputVecType& x) + { + x = arma::tanh(arma::exp(y)) + + y*arma::exp(y)*arma::pow(arma::sech(arma::exp(y)),2); + } +}; // class TanhExpFunction + +} // namespace ann +} // namespace mlpack + +#endif // TANH_EXPONENTIAL_FUNCTION_HPP_INCLUDED diff --git a/src/mlpack/methods/ann/layer/base_layer.hpp b/src/mlpack/methods/ann/layer/base_layer.hpp index ae49f30fe6..a1dcca3e35 100644 --- a/src/mlpack/methods/ann/layer/base_layer.hpp +++ b/src/mlpack/methods/ann/layer/base_layer.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace mlpack { namespace ann /** Artificial Neural Network. */ { @@ -52,6 +53,7 @@ namespace ann /** Artificial Neural Network. */ { * - ElliotLayer * - GaussianLayer * - HardSwishLayer + * - TanhExpLayer * * @tparam ActivationFunction Activation function used for the embedding layer. * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, @@ -290,6 +292,17 @@ template < using HardSwishFunctionLayer = BaseLayer< ActivationFunction, InputDataType, OutputDataType>; + /** + * Standard TanhExp-Layer using the TanhExp activation function. + */ +template < + class ActivationFunction = TanhExpFunction, + typename InputDataType = arma::mat, + typename OutputDataType = arma::mat +> +using TanhExpFunctionLayer = BaseLayer< + ActivationFunction, InputDataType, OutputDataType>; + } // namespace ann } // namespace mlpack diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 85cc1f7608..b1359d60e1 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "catch.hpp" @@ -1220,3 +1221,18 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") CheckDerivativeCorrect (desiredActivations, desiredDerivatives); } + +/** + * Basic test of the TanhExp function. + */ +TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") +{ + const arma::colvec desiredActivations("-0.26903 0.3.20000 0.4.50000 0.0000 \ + 0.99133 -0.35214 2.0 0.0000"); + + const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 0 \ + 1.383 0.029873 1 0.76159"); + + CheckActivationCorrect(activationData, desiredActivations); + CheckDerivativeCorrect(desiredActivations, desiredDerivatives); +} From 41e23de5e5208c916c680cf1912c1d89c79806c9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 20:54:11 +0530 Subject: [PATCH 106/729] Added documentation for the warmStart parameter --- src/mlpack/methods/random_forest/random_forest.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 4dfc0504d9..e2a698c805 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -168,6 +168,8 @@ class RandomForest * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. + * @param warmStart When set to `true`, it fits new trees and add them to the + * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -200,6 +202,8 @@ class RandomForest * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. + * @param warmStart When set to `true`, it fits new trees and add them to the + * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -231,6 +235,8 @@ class RandomForest * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. + * @param warmStart When set to `true`, it fits new trees and add them to the + * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -264,6 +270,8 @@ class RandomForest * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. + * @param warmStart When set to `true`, it fits new trees and add them to the + * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -360,6 +368,7 @@ class RandomForest * @param dimensionSelector Instantiated dimension selection policy. * @tparam UseWeights Whether or not to use the weights parameter. * @tparam UseDatasetInfo Whether or not to use the datasetInfo parameter. + * @tparam WarmStart Whether or not train on top of exixting trained forest. * @tparam MatType The type of data matrix (i.e. arma::mat). * @return The average entropy of all the decision trees trained under forest. */ From b0ac4360a9a3e0569cc1235061e2b9ffe0d4d752 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 21:05:32 +0530 Subject: [PATCH 107/729] Changed warmStart from template variable to function argument --- .../methods/random_forest/random_forest.hpp | 8 ++- .../random_forest/random_forest_impl.hpp | 72 ++++++++----------- 2 files changed, 33 insertions(+), 47 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index e2a698c805..2f8d27135e 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -366,13 +366,14 @@ class RandomForest * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. + * @param warmStart When set to `true`, it fits new trees and add them to the + * previous forest else a new forest is trained from scratch. * @tparam UseWeights Whether or not to use the weights parameter. * @tparam UseDatasetInfo Whether or not to use the datasetInfo parameter. - * @tparam WarmStart Whether or not train on top of exixting trained forest. * @tparam MatType The type of data matrix (i.e. arma::mat). * @return The average entropy of all the decision trees trained under forest. */ - template + template double Train(const MatType& data, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -382,7 +383,8 @@ class RandomForest const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector); + DimensionSelectionType& dimensionSelector, + bool warmStart = false); //! The trees in the forest. std::vector trees; diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index abfa6bd270..b607b5ebc3 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -44,8 +44,9 @@ RandomForest< // Pass off work to the Train() method. data::DatasetInfo info; // Ignored. arma::rowvec weights; // Fake weights, not used. - Train(dataset, info, labels, numClasses, weights, numTrees, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + Train(dataset, info, labels, numClasses, weights, numTrees, + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, + false); } template< @@ -74,9 +75,9 @@ RandomForest< { // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. - Train(dataset, datasetInfo, labels, numClasses, weights, + Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, false); } template< @@ -105,8 +106,9 @@ RandomForest< { // Pass off work to the Train() method. data::DatasetInfo info; // Ignored by Train(). - Train(dataset, info, labels, numClasses, weights, numTrees, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + Train(dataset, info, labels, numClasses, weights, numTrees, + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, + false); } template< @@ -135,8 +137,9 @@ RandomForest< DimensionSelectionType dimensionSelector) { // Pass off work to the Train() method. - Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector, false); } template< @@ -166,14 +169,9 @@ double RandomForest< // Pass off to Train(). data::DatasetInfo datasetInfo; // Ignored by Train(). arma::rowvec weights; // Ignored by Train(). - if (warmStart) - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); - else - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector, warmStart); } template< @@ -203,14 +201,9 @@ double RandomForest< { // Pass off to Train(). arma::rowvec weights; // Ignored by Train(). - if (warmStart) - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); - else - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector, warmStart); } template< @@ -240,14 +233,9 @@ double RandomForest< { // Pass off to Train(). data::DatasetInfo datasetInfo; // Ignored by Train(). - if (warmStart) - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); - else - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector, warmStart); } template< @@ -277,14 +265,9 @@ double RandomForest< bool warmStart) { // Pass off to Train(). - if (warmStart) - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); - else - return Train(dataset, datasetInfo, labels, numClasses, weights, - numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + return Train(dataset, datasetInfo, labels, numClasses, weights, + numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector, warmStart); } template< @@ -470,7 +453,7 @@ template< template class CategoricalSplitType, typename ElemType > -template +template double RandomForest< FitnessFunction, DimensionSelectionType, @@ -486,13 +469,14 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector) + DimensionSelectionType& dimensionSelector, + bool warmStart) { size_t oldNumTrees = trees.size(); // Convert avgGain to total gain. avgGain *= oldNumTrees; - if (WarmStart) + if (warmStart) { // This will extend the vector with untrained trees. trees.resize(trees.size() + numTrees); @@ -549,7 +533,7 @@ double RandomForest< } // Storing the trained tree at the desired index. - if (WarmStart) + if (warmStart) trees[oldNumTrees + i] = tmpTree; else trees[i] = tmpTree; From 6af0387171c5179a14dc7946bc2e6626b978d4e6 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Wed, 17 Mar 2021 21:56:36 +0530 Subject: [PATCH 108/729] minor change --- .../activation_functions/tanh_exponential_function.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 8bbc3c3771..42576fc013 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -22,7 +22,7 @@ namespace ann /** Artificial Neural Network. */ { * * @f{eqnarray*}{ * f(x) = x * tanh(e^x)\\ - * f'(x) = tanh(e^x) + x*e^x*(sech(e^x))^2\\ + * f'(x) = tanh(e^x) - x*e^x*(tanh(e^x)^2 - 1)\\ * @f} */ class TanhExpFunction @@ -59,8 +59,8 @@ namespace ann /** Artificial Neural Network. */ { */ static double Deriv(const double y) { - return std::tanh(std::exp(y)) + - y*std::exp(y)*std::pow(std::sech(std::exp(y)),2); + return std::tanh(std::exp(y)) - + y*std::exp(y)*(std::pow(std::tanh(std::exp(y)),2) - 1); } /** @@ -72,8 +72,8 @@ namespace ann /** Artificial Neural Network. */ { template static void Deriv(const InputVecType& y, OutputVecType& x) { - x = arma::tanh(arma::exp(y)) + - y*arma::exp(y)*arma::pow(arma::sech(arma::exp(y)),2); + x = arma::tanh(arma::exp(y)) - + y*arma::exp(y)*(arma::pow(arma::tanh(arma::exp(y)),2) - 1); } }; // class TanhExpFunction From 9e4ca1b76b51a309b85e5d79a758a9184016dbb2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 17 Mar 2021 23:47:38 +0530 Subject: [PATCH 109/729] Added newline at EOF --- src/mlpack/tests/random_forest_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 2c3cc246d1..966af53e55 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -557,4 +557,4 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") size_t newCorrect = arma::accu(newPredictions == trainingLabels); REQUIRE(newCorrect - oldCorrect >= 0); -} \ No newline at end of file +} From b7f7a88572632be0bbdde5a4b0d3d681a594b02a Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 18 Mar 2021 00:22:13 +0530 Subject: [PATCH 110/729] Fixed OpenMP error --- .../methods/random_forest/random_forest_impl.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index b607b5ebc3..3599056729 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -474,7 +474,7 @@ double RandomForest< { size_t oldNumTrees = trees.size(); // Convert avgGain to total gain. - avgGain *= oldNumTrees; + double totalGain = avgGain * oldNumTrees; if (warmStart) { @@ -488,7 +488,7 @@ double RandomForest< } // Train each tree individually. - #pragma omp parallel for reduction( + : avgGain) + #pragma omp parallel for reduction( + : totalGain) for (omp_size_t i = 0; i < numTrees; ++i) { Timer::Start("bootstrap"); @@ -506,13 +506,13 @@ double RandomForest< { if (UseDatasetInfo) { - avgGain += tmpTree.Train(bootstrapDataset, datasetInfo, + totalGain += tmpTree.Train(bootstrapDataset, datasetInfo, bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } else { - avgGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, + totalGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -521,13 +521,13 @@ double RandomForest< { if (UseDatasetInfo) { - avgGain += tmpTree.Train(bootstrapDataset, datasetInfo, + totalGain += tmpTree.Train(bootstrapDataset, datasetInfo, bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } else { - avgGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, + totalGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } } @@ -541,7 +541,7 @@ double RandomForest< Timer::Stop("train_tree"); } - avgGain /= trees.size(); + avgGain = totalGain / trees.size(); return avgGain; } From 3d5bc06aa4ff6f962278e16e1f520919d627f243 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Thu, 18 Mar 2021 09:17:48 +0530 Subject: [PATCH 111/729] minor change --- src/mlpack/tests/activation_functions_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index b1359d60e1..225efb5bda 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1227,7 +1227,7 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") */ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") { - const arma::colvec desiredActivations("-0.26903 0.3.20000 0.4.50000 0.0000 \ + const arma::colvec desiredActivations("-0.26903 0.320000 0.4.50000 0.0000 \ 0.99133 -0.35214 2.0 0.0000"); const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 0 \ From d61e638611fd77d5a9b3764d5ec69641cf51c93a Mon Sep 17 00:00:00 2001 From: mayank raj Date: Thu, 18 Mar 2021 13:37:56 +0530 Subject: [PATCH 112/729] minor --- src/mlpack/tests/activation_functions_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 225efb5bda..fed997155d 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1227,7 +1227,7 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") */ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") { - const arma::colvec desiredActivations("-0.26903 0.320000 0.4.50000 0.0000 \ + const arma::colvec desiredActivations("-0.26903 3.20000 0.4.50000 0.0000 \ 0.99133 -0.35214 2.0 0.0000"); const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 0 \ From 2545cc806ac763d8194e6f595967b5f44dc67ca0 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Thu, 18 Mar 2021 14:43:04 +0530 Subject: [PATCH 113/729] minor change --- src/mlpack/tests/activation_functions_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index fed997155d..1345eff49b 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1227,7 +1227,7 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") */ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") { - const arma::colvec desiredActivations("-0.26903 3.20000 0.4.50000 0.0000 \ + const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 0.0000 \ 0.99133 -0.35214 2.0 0.0000"); const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 0 \ From 3c9a0e09a1243bf0115a2119235e57f1c2feb31f Mon Sep 17 00:00:00 2001 From: mayank raj Date: Thu, 18 Mar 2021 15:46:19 +0530 Subject: [PATCH 114/729] minor --- src/mlpack/tests/activation_functions_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 1345eff49b..b589be5f06 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1227,10 +1227,10 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") */ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") { - const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 0.0000 \ + const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 -0.0000 \ 0.99133 -0.35214 2.0 0.0000"); - const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 0 \ + const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 -0.0 \ 1.383 0.029873 1 0.76159"); CheckActivationCorrect(activationData, desiredActivations); From 960cdf7be99c8bfc373ce79b21a84eab235ebd11 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 18 Mar 2021 22:10:32 +0530 Subject: [PATCH 115/729] Added WarmStart to bindings --- .../random_forest/random_forest_main.cpp | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 9b0ab53ff3..6df3a923d6 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -130,6 +130,8 @@ PARAM_INT_IN("subspace_dim", "Dimensionality of random subspace to use for " "d", 0); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); +PARAM_FLAG("warm_start", "If true and passed along with `training` and " + "`input_model` then trains more trees on top of existing model.", "w"); /** * This is the class that we will serialize. It is a pretty simple wrapper @@ -167,7 +169,8 @@ static void mlpackMain() math::RandomSeed((size_t) std::time(NULL)); // Check for incompatible input parameters. - RequireOnlyOnePassed({ "training", "input_model" }, true); + if (!IO::HasParam("warm_start")) + RequireOnlyOnePassed({ "training", "input_model" }, true); ReportIgnoredParam({{ "training", false }}, "print_training_accuracy"); ReportIgnoredParam({{ "test", false }}, "test_labels"); @@ -201,10 +204,17 @@ static void mlpackMain() ReportIgnoredParam({{ "training", false }}, "minimum_leaf_size"); RandomForestModel* rfModel; + // Handles the case when we are either training on top of existing forest + // else we are making predictions only. + if (IO::HasParam("warm_start") or IO::HasParam("input_model")) + rfModel = IO::GetParam("input_model"); + // Handles the case when we are training new forest from scratch. + else + rfModel = new RandomForestModel(); + if (IO::HasParam("training")) { Timer::Start("rf_training"); - rfModel = new RandomForestModel(); // Train the model on the given input data. arma::mat data = std::move(IO::GetParam("training")); @@ -232,8 +242,15 @@ static void mlpackMain() const size_t numClasses = arma::max(labels) + 1; // Train the model. - rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, - minimumGainSplit, maxDepth, mrds); + if (IO::HasParam("warm_start")) + { + bool warmStart = IO::GetParam("warm_start"); + rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, + minimumGainSplit, maxDepth, mrds, warmStart); + } + else + rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, + minimumGainSplit, maxDepth, mrds); Timer::Stop("rf_training"); // Did we want training accuracy? @@ -251,11 +268,6 @@ static void mlpackMain() Timer::Stop("rf_prediction"); } } - else - { - // Then we must be loading a model. - rfModel = IO::GetParam("input_model"); - } if (IO::HasParam("test")) { From e533fb880840248567f2a46a15c6acc9bbcf9010 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 18 Mar 2021 22:31:25 +0530 Subject: [PATCH 116/729] Improved error handling in bindings --- src/mlpack/methods/random_forest/random_forest_main.cpp | 7 +++++++ src/mlpack/tests/main_tests/random_forest_test.cpp | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 6df3a923d6..80b932e833 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -171,6 +171,13 @@ static void mlpackMain() // Check for incompatible input parameters. if (!IO::HasParam("warm_start")) RequireOnlyOnePassed({ "training", "input_model" }, true); + else + { + // When warm_start is passed, training and input_model must also be passed. + std::vector params = {"warm_start", "training", + "input_model"}; + RequireNoneOrAllPassed(params, true); + } ReportIgnoredParam({{ "training", false }}, "print_training_accuracy"); ReportIgnoredParam({{ "test", false }}, "test_labels"); diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index 47a56170f9..df69379e08 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -204,7 +204,8 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestMaximumDepthTest", } /** - * Make sure only one of training data or pre-trained model is passed. + * Make sure only one of training data or pre-trained model is passed, when + * warm_start is not passed. */ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingVerTest", "[RandomForestMainTest][BindingTests]") From 8903d453a3acfc105bf03d13a92ed511c2a32de4 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 18 Mar 2021 23:17:11 +0530 Subject: [PATCH 117/729] Added tests for bindings of warmstart --- .../tests/main_tests/random_forest_test.cpp | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index df69379e08..75368946e8 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -454,3 +454,67 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMaxDepthTest", delete rf2; delete rf3; } + +/** + * Make sure that training and input_model are both passed when warm_start is + * false. + */ +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingModelWarmStart" + "[RandomForestMainTest][BindingTests]") +{ + arma::mat inputData; + if (!data::Load("vc2.csv", inputData)) + FAIL("Cannot load train dataset vc2.csv!"); + + arma::Row labels; + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load labels for vc2_labels.txt"); + + // Input training data. + SetInputParam("training", std::move(inputData)); + SetInputParam("labels", std::move(labels)); + + mlpackMain(); + + // Setting warm_start flag. + SetInputParam("warm_start", false); + + Log::Fatal.ignoreInput = true; + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + Log::Fatal.ignoreInput = false; +} + +/** + * Ensuring that model does gets trained on top of existing one when warm_start + * and input_model are both passed. + */ +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart" + "[RandomForestMainTest][BindingTests]") +{ + arma::mat inputData; + if (!data::Load("vc2.csv", inputData)) + FAIL("Cannot load train dataset vc2.csv!"); + + arma::Row labels; + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load labels for vc2_labels.txt"); + + // Input training data. + SetInputParam("training", std::move(inputData)); + SetInputParam("labels", std::move(labels)); + + mlpackMain(); + + // Old number of trees in the model. + size_t oldNumTrees = + IO::GetParam("output_model")->rf.NumTrees(); + + SetInputParam("warm_start", true); + + mlpackMain(); + + size_t newNumTrees = + IO::GetParam("output_model")->rf.NumTrees(); + + REQUIRE(oldNumTrees + 10 == newNumTrees); +} From 4d34889451c755034946f04a6fbc49ac46306c55 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 18 Mar 2021 23:31:38 +0530 Subject: [PATCH 118/729] Fixed a small typo :) --- src/mlpack/tests/main_tests/random_forest_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index 75368946e8..caa3ad7d8f 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -459,7 +459,7 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMaxDepthTest", * Make sure that training and input_model are both passed when warm_start is * false. */ -TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingModelWarmStart" +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingModelWarmStart", "[RandomForestMainTest][BindingTests]") { arma::mat inputData; @@ -488,7 +488,7 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingModelWarmStart" * Ensuring that model does gets trained on top of existing one when warm_start * and input_model are both passed. */ -TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart" +TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart", "[RandomForestMainTest][BindingTests]") { arma::mat inputData; From 45057987a80ef1008850fa5de6267c6ab26513dc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 18 Mar 2021 23:41:06 +0530 Subject: [PATCH 119/729] Fixed the testcase and shortened the input check --- src/mlpack/methods/random_forest/random_forest_main.cpp | 6 +----- src/mlpack/tests/main_tests/random_forest_test.cpp | 3 +++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 80b932e833..bdf94e1d4a 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -172,12 +172,8 @@ static void mlpackMain() if (!IO::HasParam("warm_start")) RequireOnlyOnePassed({ "training", "input_model" }, true); else - { // When warm_start is passed, training and input_model must also be passed. - std::vector params = {"warm_start", "training", - "input_model"}; - RequireNoneOrAllPassed(params, true); - } + RequireNoneOrAllPassed({"warm_start", "training", "input_model"}, true); ReportIgnoredParam({{ "training", false }}, "print_training_accuracy"); ReportIgnoredParam({{ "test", false }}, "test_labels"); diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index caa3ad7d8f..6f0c932ed9 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -510,6 +510,9 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart", IO::GetParam("output_model")->rf.NumTrees(); SetInputParam("warm_start", true); + // Input pre-trained model. + SetInputParam("input_model", + IO::GetParam("output_model")); mlpackMain(); From b013321520fa6681930e2bce4856c5045c8180db Mon Sep 17 00:00:00 2001 From: mayank <54908605+mayankray2020@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:21:12 +0530 Subject: [PATCH 120/729] Update src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp Co-authored-by: Marcus Edel --- .../ann/activation_functions/tanh_exponential_function.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 42576fc013..89c77d974b 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -36,7 +36,7 @@ namespace ann /** Artificial Neural Network. */ { */ static double Fn(const double x) { - return x*std::tanh(std::exp(x)); + return x * std::tanh(std::exp(x)); } /** From cf11826aca3edec078e55c834dea7b935c939ff0 Mon Sep 17 00:00:00 2001 From: mayank <54908605+mayankray2020@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:21:19 +0530 Subject: [PATCH 121/729] Update src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp Co-authored-by: Marcus Edel --- .../ann/activation_functions/tanh_exponential_function.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 89c77d974b..17a65152ce 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -48,7 +48,7 @@ namespace ann /** Artificial Neural Network. */ { template static void Fn(const InputVecType& x, OutputVecType& y) { - y = x*arma::tanh(arma::exp(x)); + y = x * arma::tanh(arma::exp(x)); } /** From c5904a0bbf712989f66ade9b2c85edd8675ee38e Mon Sep 17 00:00:00 2001 From: mayank <54908605+mayankray2020@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:21:26 +0530 Subject: [PATCH 122/729] Update src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp Co-authored-by: Marcus Edel --- .../ann/activation_functions/tanh_exponential_function.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 17a65152ce..d839dfafa7 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -59,8 +59,8 @@ namespace ann /** Artificial Neural Network. */ { */ static double Deriv(const double y) { - return std::tanh(std::exp(y)) - - y*std::exp(y)*(std::pow(std::tanh(std::exp(y)),2) - 1); + return std::tanh(std::exp(y)) - y * std::exp(y) * + (std::pow(std::tanh(std::exp(y)), 2) - 1); } /** From 89a1a411526007b3d1cbe90f33c7191e57d0557c Mon Sep 17 00:00:00 2001 From: mayank <54908605+mayankray2020@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:21:39 +0530 Subject: [PATCH 123/729] Update src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp Co-authored-by: Marcus Edel --- .../ann/activation_functions/tanh_exponential_function.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index d839dfafa7..6f9c8f803d 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -72,8 +72,8 @@ namespace ann /** Artificial Neural Network. */ { template static void Deriv(const InputVecType& y, OutputVecType& x) { - x = arma::tanh(arma::exp(y)) - - y*arma::exp(y)*(arma::pow(arma::tanh(arma::exp(y)),2) - 1); + x = arma::tanh(arma::exp(y)) - y * arma::exp(y) * + (arma::pow(arma::tanh(arma::exp(y)), 2) - 1); } }; // class TanhExpFunction From 7ab434112caa87db1a00279189101289419e10f0 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Fri, 19 Mar 2021 11:51:36 +0530 Subject: [PATCH 124/729] minor change --- .../ann/activation_functions/tanh_exponential_function.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 6f9c8f803d..2eb0ec22c1 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -9,8 +9,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef TANH_EXPONENTIAL_FUNCTION_HPP_INCLUDED -#define TANH_EXPONENTIAL_FUNCTION_HPP_INCLUDED +#ifndef MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_TANH_EXPONENTIAL_FUNCTION_HPP +#define MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_TANH_EXPONENTIAL_FUNCTION_HPP #include @@ -80,4 +80,4 @@ namespace ann /** Artificial Neural Network. */ { } // namespace ann } // namespace mlpack -#endif // TANH_EXPONENTIAL_FUNCTION_HPP_INCLUDED +#endif From 54f58bf5b1a385b03546884d5704ec2c064c97d0 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Fri, 19 Mar 2021 12:13:44 +0530 Subject: [PATCH 125/729] test values changed --- src/mlpack/tests/activation_functions_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index b589be5f06..88c45acd7e 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1230,8 +1230,8 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 -0.0000 \ 0.99133 -0.35214 2.0 0.0000"); - const arma::colvec desiredDerivatives("-0.13126 1.0000 1.0000 -0.0 \ - 1.383 0.029873 1 0.76159"); + const arma::colvec desiredDerivatives("0.52305 1.0000 1.0000 0.76159 \ + 1.03924 0.44982 1.00002 0.76159"); CheckActivationCorrect(activationData, desiredActivations); CheckDerivativeCorrect(desiredActivations, desiredDerivatives); From a84ba95ee89a49e608995a85be601cc3bfc6a1ea Mon Sep 17 00:00:00 2001 From: mayank raj Date: Fri, 19 Mar 2021 12:20:21 +0530 Subject: [PATCH 126/729] minor change --- src/mlpack/tests/activation_functions_test.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 88c45acd7e..30d24849e6 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1227,10 +1227,15 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") */ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") { - const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 -0.0000 \ + + const arma::colvec activationData("-2 3.2 4.5 1 -1 2 0"); + + // Hand-calculated values. + const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 \ 0.99133 -0.35214 2.0 0.0000"); - const arma::colvec desiredDerivatives("0.52305 1.0000 1.0000 0.76159 \ + // Hand-calculated values. + const arma::colvec desiredDerivatives("0.52305 1.0000 1.0000 \ 1.03924 0.44982 1.00002 0.76159"); CheckActivationCorrect(activationData, desiredActivations); From ccb43c7cc153f3bcd4bc77ec145554fa62cdec08 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Fri, 19 Mar 2021 14:04:21 +0530 Subject: [PATCH 127/729] test value changed --- src/mlpack/tests/activation_functions_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 30d24849e6..2ae2ea344d 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -1232,11 +1232,11 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") // Hand-calculated values. const arma::colvec desiredActivations("-0.26903 3.20000 4.50000 \ - 0.99133 -0.35214 2.0 0.0000"); + 0.991329 -0.352135 2.0 0.0000"); // Hand-calculated values. - const arma::colvec desiredDerivatives("0.52305 1.0000 1.0000 \ - 1.03924 0.44982 1.00002 0.76159"); + const arma::colvec desiredDerivatives("0.523051 1.0000 1.0000 \ + 1.03924 0.449818 1.00002 0.761594"); CheckActivationCorrect(activationData, desiredActivations); CheckDerivativeCorrect(desiredActivations, desiredDerivatives); From 4239e15d76f729883a24702b1458de61e2a11147 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Fri, 19 Mar 2021 15:29:42 +0530 Subject: [PATCH 128/729] fixed errors --- .../ann/activation_functions/tanh_exponential_function.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 2eb0ec22c1..97319d2bb6 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -48,7 +48,7 @@ namespace ann /** Artificial Neural Network. */ { template static void Fn(const InputVecType& x, OutputVecType& y) { - y = x * arma::tanh(arma::exp(x)); + y = x % arma::tanh(arma::exp(x)); } /** @@ -59,7 +59,7 @@ namespace ann /** Artificial Neural Network. */ { */ static double Deriv(const double y) { - return std::tanh(std::exp(y)) - y * std::exp(y) * + return std::tanh(std::exp(y)) - y % std::exp(y) % (std::pow(std::tanh(std::exp(y)), 2) - 1); } @@ -72,7 +72,7 @@ namespace ann /** Artificial Neural Network. */ { template static void Deriv(const InputVecType& y, OutputVecType& x) { - x = arma::tanh(arma::exp(y)) - y * arma::exp(y) * + x = arma::tanh(arma::exp(y)) - y % arma::exp(y) % (arma::pow(arma::tanh(arma::exp(y)), 2) - 1); } }; // class TanhExpFunction From 8de2d7fd3e0c4ed0e2a3063a673aafaa59b09230 Mon Sep 17 00:00:00 2001 From: mayank raj Date: Fri, 19 Mar 2021 19:49:20 +0530 Subject: [PATCH 129/729] minor --- .../ann/activation_functions/tanh_exponential_function.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 97319d2bb6..5e74b73342 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -59,7 +59,7 @@ namespace ann /** Artificial Neural Network. */ { */ static double Deriv(const double y) { - return std::tanh(std::exp(y)) - y % std::exp(y) % + return std::tanh(std::exp(y)) - y * std::exp(y) * (std::pow(std::tanh(std::exp(y)), 2) - 1); } From 6cd97a7a4baa300e5c83020aa7d2b1ba4a07af51 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 19 Mar 2021 23:41:50 +0530 Subject: [PATCH 130/729] Defined the random split class --- .../best_binary_numeric_split.hpp | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 976b810c63..9f41490086 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -87,6 +87,77 @@ class BestBinaryNumericSplit const AuxiliarySplitInfo& /* aux */); }; +/** + * The RandomBinaryNumericSplit is a splitting function for decision trees that + * will split based on a randomly selected point between the minimum + * and maximum value of the numerical dimension. + * + * @tparam FitnessFunction Fitness function to use to calculate gain. + */ +template +class RandomBinaryNumericSplit +{ + public: + // No extra info needed for split. + template + class AuxiliarySplitInfo { }; + + /** + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then classProbabilities + * and aux may be modified. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param labels Labels for each point. + * @param numClasses Number of classes in the dataset. + * @param weights Weights associated with labels. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param minimumGainSplit Minimum gain split. + * @param classProbabilities Class probabilities vector, which may be filled + * with split information a successful split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + */ + template + static double SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const size_t numClasses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + arma::Col& classProbabilities, + AuxiliarySplitInfo& aux); + + /** + * Returns 2, since the binary split always has two children. + */ + template + static size_t NumChildren(const arma::Col& /* classProbabilities */, + const AuxiliarySplitInfo& /* aux */) + { + return 2; + } + + /** + * Given a point, calculate which child it should go to (left or right). + * + * @param point Point to calculate direction of. + * @param classProbabilities Auxiliary information for the split. + * @param * (aux) Auxiliary information for the split (Unused). + */ + template + static size_t CalculateDirection( + const ElemType& point, + const arma::Col& classProbabilities, + const AuxiliarySplitInfo& /* aux */); +}; + } // namespace tree } // namespace mlpack From 0ad73bc2cbaff72e036b90b229d10a530e032a5f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 20 Mar 2021 18:51:31 +0530 Subject: [PATCH 131/729] Added implementation of random split --- .../best_binary_numeric_split_impl.hpp | 183 ++++++++++++++++-- 1 file changed, 162 insertions(+), 21 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index f5b38220ca..2fad09fb69 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -12,6 +12,8 @@ #ifndef MLPACK_METHODS_DECISION_TREE_BEST_BINARY_NUMERIC_SPLIT_IMPL_HPP #define MLPACK_METHODS_DECISION_TREE_BEST_BINARY_NUMERIC_SPLIT_IMPL_HPP +#include + namespace mlpack { namespace tree { @@ -39,11 +41,11 @@ double BestBinaryNumericSplit::SplitIfBetter( arma::Row sortedLabels(labels.n_elem); arma::rowvec sortedWeights; for (size_t i = 0; i < sortedLabels.n_elem; ++i) - sortedLabels[i] = labels[sortedIndices[i]]; + sortedLabels(i) = labels(sortedIndices(i)); // Sanity check: if the first element is the same as the last, we can't split // in this dimension. - if (data[sortedIndices[0]] == data[sortedIndices[sortedIndices.n_elem - 1]]) + if (data(sortedIndices(0)) == data(sortedIndices(sortedIndices.n_elem - 1))) return DBL_MAX; // Only initialize if we are using weights. @@ -52,7 +54,7 @@ double BestBinaryNumericSplit::SplitIfBetter( sortedWeights.set_size(sortedLabels.n_elem); // The weights must keep the same order as the labels. for (size_t i = 0; i < sortedLabels.n_elem; ++i) - sortedWeights[i] = weights[sortedIndices[i]]; + sortedWeights(i) = weights(sortedIndices(i)); } // Loop through all possible split points, choosing the best one. Also, force @@ -77,15 +79,15 @@ double BestBinaryNumericSplit::SplitIfBetter( // These points have to be on the left. for (size_t i = 0; i < minimum - 1; ++i) { - classWeightSums(sortedLabels[i], 0) += sortedWeights[i]; - totalLeftWeight += sortedWeights[i]; + classWeightSums(sortedLabels(i), 0) += sortedWeights(i); + totalLeftWeight += sortedWeights(i); } // These points have to be on the right. for (size_t i = minimum - 1; i < data.n_elem; ++i) { - classWeightSums(sortedLabels[i], 1) += sortedWeights[i]; - totalRightWeight += sortedWeights[i]; + classWeightSums(sortedLabels(i), 1) += sortedWeights(i); + totalRightWeight += sortedWeights(i); } } else @@ -96,11 +98,11 @@ double BestBinaryNumericSplit::SplitIfBetter( // Initialize the counts. // These points have to be on the left. for (size_t i = 0; i < minimum - 1; ++i) - ++classCounts(sortedLabels[i], 0); + ++classCounts(sortedLabels(i), 0); // These points have to be on the right. for (size_t i = minimum - 1; i < data.n_elem; ++i) - ++classCounts(sortedLabels[i], 1); + ++classCounts(sortedLabels(i), 1); } for (size_t index = minimum; index < data.n_elem - minimum; ++index) @@ -108,19 +110,19 @@ double BestBinaryNumericSplit::SplitIfBetter( // Update class weight sums or counts. if (UseWeights) { - classWeightSums(sortedLabels[index - 1], 1) -= sortedWeights[index - 1]; - classWeightSums(sortedLabels[index - 1], 0) += sortedWeights[index - 1]; - totalLeftWeight += sortedWeights[index - 1]; - totalRightWeight -= sortedWeights[index - 1]; + classWeightSums(sortedLabels(index - 1), 1) -= sortedWeights(index - 1); + classWeightSums(sortedLabels(index - 1), 0) += sortedWeights(index - 1); + totalLeftWeight += sortedWeights(index - 1); + totalRightWeight -= sortedWeights(index - 1); } else { - --classCounts(sortedLabels[index - 1], 1); - ++classCounts(sortedLabels[index - 1], 0); + --classCounts(sortedLabels(index - 1), 1); + ++classCounts(sortedLabels(index - 1), 0); } // Make sure that the value has changed. - if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) + if (data(sortedIndices(index)) == data(sortedIndices(index - 1))) continue; // Calculate the gain for the left and right child. Only use weights if @@ -156,8 +158,8 @@ double BestBinaryNumericSplit::SplitIfBetter( classProbabilities.set_size(1); // The actual split value will be halfway between the value at index - 1 // and index. - classProbabilities[0] = (data[sortedIndices[index - 1]] + - data[sortedIndices[index]]) / 2.0; + classProbabilities(0) = (data(sortedIndices(index - 1)) + + data(sortedIndices(index))) / 2.0; return gain; } @@ -166,8 +168,8 @@ double BestBinaryNumericSplit::SplitIfBetter( // We still have a better split. bestFoundGain = gain; classProbabilities.set_size(1); - classProbabilities[0] = (data[sortedIndices[index - 1]] + - data[sortedIndices[index]]) / 2.0; + classProbabilities(0) = (data(sortedIndices(index - 1)) + + data(sortedIndices(index))) / 2.0; improved = true; } } @@ -192,7 +194,146 @@ size_t BestBinaryNumericSplit::CalculateDirection( const arma::Col& classProbabilities, const AuxiliarySplitInfo& /* aux */) { - if (point <= classProbabilities[0]) + if (point <= classProbabilities(0)) + return 0; // Go left. + else + return 1; // Go right. +} + +template +template +double RandomBinaryNumericSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const size_t numClasses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + arma::Col& classProbabilities, + AuxiliarySplitInfo& /* aux */) +{ + double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); + // Forcing a minimum leaf size of 1 (empty children don't make sense). + const size_t minimum = std::max(minimumLeafSize, (size_t) 1); + + // First sanity check: if we don't have enough points, we can't split. + if (data.n_elem < (minimum * 2)) + return DBL_MAX; + if (bestGain == 0.0) + return DBL_MAX; // It can't be outperformed. + + typename VecType::elem_type maxValue = arma::max(data); + typename VecType::elem_type minValue = arma::min(data); + + // Sanity check: if the maximum element is the same as the mininimum, we + // can't split in this dimension. + if (maxValue == minValue) + return DBL_MAX; + + /* + Just for making review easy, the following bit of code is taken directly from + https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + to generate a random number. (To be removed before merge) + */ + // Picking a random pivot to split the dimension. + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> distribution(minValue, maxValue); + double randomPivot = distribution(gen); + + // We need to count the number of points for each class. + arma::Mat classCounts; + arma::mat classWeightSums; + double totalWeight = 0.0; + double totalLeftWeight = 0.0; + double totalRightWeight = 0.0; + size_t leftLeafSize = 0; + size_t rightLeafSize = 0; + if (UseWeights) + { + classWeightSums.zeros(numClasses, 2); + totalWeight = arma::accu(weights); + bestFoundGain *= totalWeight; + + for (size_t i = 0; i < data.n_elem; ++i) + { + if (data(i) < randomPivot) + { + ++leftLeafSize; + classWeightSums(labels(i), 0) += weights(i); + totalLeftWeight += weights(i); + } + else + { + ++rightLeafSize; + classWeightSums(labels(i), 1) += weights(i); + totalRightWeight += weights(i); + } + } + } + else + { + classCounts.zeros(numClasses, 2); + bestFoundGain *= data.n_elem; + + for (size_t i = 0; i < data.n_elem; i++) + { + if (data(i) < randomPivot) + { + ++leftLeafSize; + ++classCounts(labels(i), 0); + } + else + { + ++rightLeafSize; + ++classCounts(labels(i), 1); + } + } + } + + // Calculate the gain for the left and right child. Only use weights if + // needed. + const double leftGain = UseWeights ? + FitnessFunction::template EvaluatePtr(classWeightSums.colptr(0), + numClasses, totalLeftWeight) : + FitnessFunction::template EvaluatePtr(classCounts.colptr(0), + numClasses, leftLeafSize); + const double rightGain = UseWeights ? + FitnessFunction::template EvaluatePtr(classWeightSums.colptr(1), + numClasses, totalRightWeight) : + FitnessFunction::template EvaluatePtr(classCounts.colptr(1), + numClasses, rightLeafSize); + + double gain; + if (UseWeights) + gain = totalLeftWeight * leftGain + totalRightWeight * rightGain; + else + // Calculate the gain at this split point. + gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; + + if (gain < bestFoundGain) + return DBL_MAX; + + classProbabilities.set_size(1); + classProbabilities(0) = randomPivot; + + if (UseWeights) + gain /= totalWeight; + else + gain /= labels.n_elem; + + return gain; +} + +template +template +size_t RandomBinaryNumericSplit::CalculateDirection( + const ElemType& point, + const arma::Col& classProbabilities, + const AuxiliarySplitInfo& /* aux */) +{ + if (point <= classProbabilities(0)) return 0; // Go left. else return 1; // Go right. From a140aba3259518f4f38fefb8e799a43f4a6af6a9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 20 Mar 2021 21:24:20 +0530 Subject: [PATCH 132/729] Added tests --- src/mlpack/tests/decision_tree_test.cpp | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 7722c54fe4..f01ceefefa 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -376,6 +376,66 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") REQUIRE(classProbabilities.n_elem == 0); } +/** + * Check that the RandomBinaryNumericSplit won't split if not enough points are + * given. + */ +TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") +{ + arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); + arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); + arma::rowvec weights(labels.n_elem); + + arma::vec classProbabilities; + RandomBinaryNumericSplit::template AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = GiniGain::Evaluate(labels, 2, weights); + const double gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities, + aux); + // This should make no difference because it won't split at all. + const double weightedGain = + RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, + labels, 2, weights, 8, 1e-7, classProbabilities, aux); + + // Make sure that no split was made. + REQUIRE(gain == DBL_MAX); + REQUIRE(gain == weightedGain); + REQUIRE(classProbabilities.n_elem == 0); +} + +/** + * Check that the RandomBinaryNumericSplit doesn't split a dimension that gives + * no gain. + */ +TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") +{ + arma::vec values(100); + arma::Row labels(100); + arma::rowvec weights; + for (size_t i = 0; i < 100; i += 2) + { + values[i] = i; + labels[i] = 0; + values[i + 1] = i; + labels[i + 1] = 1; + } + + arma::vec classProbabilities; + RandomBinaryNumericSplit::template AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = GiniGain::Evaluate(labels, 2, weights); + const double gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, + aux); + + // Make sure there was no split. + REQUIRE(gain == DBL_MAX); + REQUIRE(classProbabilities.n_elem == 0); +} + /** * Check that the AllCategoricalSplit will split when the split is obviously * better. From dcd1b8ce50a09187383b930a40adf2c4f70f29a8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 20 Mar 2021 13:53:28 -0400 Subject: [PATCH 133/729] Handle empty OpenMP_CXX_FLAGS correctly. --- src/mlpack/bindings/python/setup.py.in | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/mlpack/bindings/python/setup.py.in b/src/mlpack/bindings/python/setup.py.in index 4762f3194b..f049f0e002 100644 --- a/src/mlpack/bindings/python/setup.py.in +++ b/src/mlpack/bindings/python/setup.py.in @@ -52,18 +52,15 @@ if os.getenv('NO_BUILD') == '1': else: cxx_flags = '${CMAKE_CXX_FLAGS}'.strip() cxx_flags = re.sub(' +', ' ', cxx_flags) + extra_args = ['-DBINDING_TYPE=BINDING_TYPE_PYX', '-std=c++11'] + if '${OpenMP_CXX_FLAGS}' != '': + extra_args.append('${OpenMP_CXX_FLAGS}') if cxx_flags: - extra_args = ['-DBINDING_TYPE=BINDING_TYPE_PYX', - '-std=c++11', - '${OpenMP_CXX_FLAGS}'] + cxx_flags.split(' ') - else: - extra_args = ['-DBINDING_TYPE=BINDING_TYPE_PYX', - '-std=c++11', - '${OpenMP_CXX_FLAGS}'] + extra_args.extend(cxx_flags.split(' ')) # Extra options for MSVC compiler. if platform.system() == 'Windows': - extra_args = extra_args + ['/MD', '/O2', '/Ob2', '/DNDEBUG'] + extra_args.extend(['/MD', '/O2', '/Ob2', '/DNDEBUG']) # This is used for parallel builds; CMake will set PYX_TO_BUILD accordingly. if module is not None: From ab182f9d0ca4dc8a6c7bdb4898ec974d12a2212c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 20 Mar 2021 13:56:15 -0400 Subject: [PATCH 134/729] Update HISTORY. --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index cf915012f2..bb9611b2ce 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -40,6 +40,9 @@ * Remove unused `ElemType` template parameter from `DecisionTree` and `RandomForest` (#2874). + * Fix Python binding build when the CMake variable `USE_OPENMP` is set to + `OFF` (#2884). + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From 418004adee1aa34b9c706bfcbd23a56876fbe6f6 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 21 Mar 2021 16:22:45 -0400 Subject: [PATCH 135/729] Add methods to change the parameters for training. --- .../bayesian_linear_regression.cpp | 10 +- .../bayesian_linear_regression.hpp | 107 +++++++++++------- .../bayesian_linear_regression_impl.hpp | 4 +- 3 files changed, 73 insertions(+), 48 deletions(-) diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp index 10a5f92bd5..c163d0d148 100644 --- a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp @@ -18,12 +18,12 @@ using namespace mlpack::regression; BayesianLinearRegression::BayesianLinearRegression(const bool centerData, const bool scaleData, - const size_t nIterMax, - const double tol) : + const size_t maxIterations, + const double tolerance) : centerData(centerData), scaleData(scaleData), - nIterMax(nIterMax), - tol(tol), + maxIterations(maxIterations), + tolerance(tolerance), responsesOffset(0.0), alpha(0.0), beta(0.0), @@ -60,7 +60,7 @@ double BayesianLinearRegression::Train(const arma::mat& data, unsigned short i = 0; double deltaAlpha = 1.0, deltaBeta = 1.0, crit = 1.0; - while ((crit > tol) && (i < nIterMax)) + while ((crit > tolerance) && (i < maxIterations)) { deltaAlpha = -alpha; deltaBeta = -beta; diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp index a15ce1ced1..417e795bff 100644 --- a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp @@ -21,30 +21,30 @@ namespace mlpack { namespace regression { /** - * A Bayesian approach to the maximum likelihood estimation of the parameters - * \f$ \omega \f$ of the linear regression model. The Complexity is governed by - * the addition of a gaussian isotropic prior of precision \f$ \alpha \f$ over - * \f$ \omega \f$: + * A Bayesian approach to the maximum likelihood estimation of the parameters + * \f$ \omega \f$ of the linear regression model. The Complexity is governed by + * the addition of a gaussian isotropic prior of precision \f$ \alpha \f$ over + * \f$ \omega \f$: * * \f[ * p(\omega|\alpha) = \mathcal{N}(\omega|0, \alpha^{-1}I) * \f] - * - * The optimization procedure calculates the posterior distribution of - * \f$ \omega \f$ knowing the data by maximizing an approximation of the log - * marginal likelihood derived from a type II maximum likelihood approximation. + * + * The optimization procedure calculates the posterior distribution of + * \f$ \omega \f$ knowing the data by maximizing an approximation of the log + * marginal likelihood derived from a type II maximum likelihood approximation. * The determination of \f$ alpha \f$ and of the noise precision \f$ beta \f$ - * is part of the optimization process, leading to an automatic determination of - * w. The model being entirely based on probabilty distributions, uncertainties + * is part of the optimization process, leading to an automatic determination of + * w. The model being entirely based on probabilty distributions, uncertainties * are available and easly computed for both the parameters and the predictions. * - * The advantage over linear regression and ridge regression is that the + * The advantage over linear regression and ridge regression is that the * regularization is determined from all the training data alone without any - * require to an hold out method. + * require to an hold out method. * - * The code below is an implementation of the maximization of the evidence + * The code below is an implementation of the maximization of the evidence * function described in the section 3.5.2 of the C.Bishop book, Pattern - * Recognition and Machine Learning. + * Recognition and Machine Learning. * * @code * @article{MacKay91bayesianinterpolation, @@ -60,36 +60,37 @@ namespace regression { * @code * @book{Bishop:2006:PRM:1162264, * author = {Bishop, Christopher M.}, - * title = {Pattern Recognition and Machine Learning (Information Science + * title = {Pattern Recognition and Machine Learning (Information Science * and Statistics)}, * chapter = {3} * year = {2006}, * isbn = {0387310738}, * publisher = {Springer-Verlag}, * address = {Berlin, Heidelberg}, - * } + * } * @endcode - * + * * Example of use: * * @code * arma::mat xTrain; // Train data matrix. Column-major. * arma::rowvec yTrain; // Train target values. - + * * // Train the model. Regularization strength is optimally tunned with the * // training data alone by applying the Train method. - * BayesianLinearRegression estimator(); // Instanciate the estimator with default option. + * // Instantiate the estimator with default option. + * BayesianLinearRegression estimator; * estimator.Train(xTrain, yTrain); - + * * // Prediction on test points. * arma::mat xTest; // Test data matrix. Column-major. * arma::rowvec predictions; - + * * estimator.Predict(xTest, prediction); - + * * arma::rowvec yTest; // Test target values. * estimator.RMSE(xTest, yTest); // Evaluate using the RMSE score. - + * * // Compute the standard deviations of the predictions. * arma::rowvec stds; * estimator.Predict(xTest, responses, stds) @@ -107,19 +108,20 @@ class BayesianLinearRegression * examples. * @param scaleData Whether or not scale the data according to the * standard deviation of each feature. - * @param nIterMax Maximum number of iterations for convergency. - * @param tol Level from which the solution is considered sufficientlly - * stable. + * @param maxIterations Maximum number of iterations for convergency. + * @param tolerance Level from which the solution is considered sufficientlly + * stable. */ BayesianLinearRegression(const bool centerData = true, const bool scaleData = false, - const size_t nIterMax = 50, - const double tol = 1e-4); + const size_t maxIterations = 50, + const double tolerance = 1e-4); /** - * Run BayesianLinearRegression. The input matrix (like all mlpack matrices) should be - * column-major -- each column is an observation and each row is a dimension. - * + * Run BayesianLinearRegression. The input matrix (like all mlpack matrices) + * should be column-major -- each column is an observation and each row is a + * dimension. + * * @param data Column-major input data, dim(P, N). * @param responses A vector of targets, dim(N). * @return Root mean squared error. @@ -139,12 +141,13 @@ class BayesianLinearRegression arma::rowvec& predictions) const; /** - * Predict \f$y_{i}\f$ and the standard deviation of the predictive posterior + * Predict \f$y_{i}\f$ and the standard deviation of the predictive posterior * distribution for each data point in the given data matrix, using the * currently-trained Bayesian Ridge estimator. * * @param points The data point to apply the model. - * @param predictions Vector which will contain calculated values on completion. + * @param predictions Vector which will contain calculated values on + * completion. * @param std Standard deviations of the predictions. */ void Predict(const arma::mat& points, @@ -163,7 +166,7 @@ class BayesianLinearRegression const arma::rowvec& responses) const; /** - * Get the solution vector. + * Get the solution vector. * * @return omega Solution vector. */ @@ -187,7 +190,7 @@ class BayesianLinearRegression /** * Get the estimated variance. Train() must be called before. - * + * * @return 1.0 / \f$ \beta \f$ */ double Variance() const { return 1.0 / Beta(); } @@ -200,7 +203,7 @@ class BayesianLinearRegression const arma::colvec& DataOffset() const { return dataOffset; } /** - * Get the vector of standard deviations computed on the features over the + * Get the vector of standard deviations computed on the features over the * training points. * * @return dataOffset @@ -214,9 +217,31 @@ class BayesianLinearRegression */ double ResponsesOffset() const { return responsesOffset; } + //! Get whether the data will be centered during training. + bool CenterData() const { return centerData; } + //! Modify whether the data will be centered during training. + bool& CenterData() { return centerData; } + + //! Get whether the data will be scaled by standard deviations during + //! training. + bool ScaleData() const { return scaleData; } + //! Modify whether the data will be scaled by standard deviations during + //! training. + bool& ScaleData() { return scaleData; } + + //! Get the maximum number of iterations for training. + size_t MaxIterations() const { return maxIterations; } + //! Modify the maximum number of iterations for training. + size_t& MaxIterations() { return maxIterations; } + + //! Get the tolerance for training to converge. + double Tolerance() const { return tolerance; } + //! Modify the tolerance for training to converge. + double& Tolerance() { return tolerance; } + /** * Serialize the BayesianLinearRegression model. - **/ + */ template void serialize(Archive& ar, const uint32_t version); @@ -227,11 +252,11 @@ class BayesianLinearRegression //! Scale the data by standard deviations if true. bool scaleData; - //! Maximum number of iterations for convergency. - size_t nIterMax; + //! Maximum number of iterations for convergence. + size_t maxIterations; //! Level from which the solution is considered sufficientlly stable. - double tol; + double tolerance; //! Mean vector computed over the points. arma::colvec dataOffset; @@ -251,7 +276,7 @@ class BayesianLinearRegression //! Effective number of parameters. double gamma; - //! Solution vector + //! Solution vector. arma::colvec omega; //! Covariance matrix of the solution vector omega. diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp index d0881dd06a..65a4d70998 100644 --- a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp @@ -26,8 +26,8 @@ void BayesianLinearRegression::serialize(Archive& ar, { ar(CEREAL_NVP(centerData)); ar(CEREAL_NVP(scaleData)); - ar(CEREAL_NVP(nIterMax)); - ar(CEREAL_NVP(tol)); + ar(CEREAL_NVP(maxIterations)); + ar(CEREAL_NVP(tolerance)); ar(CEREAL_NVP(dataOffset)); ar(CEREAL_NVP(dataScale)); ar(CEREAL_NVP(responsesOffset)); From 5fd2b9fb2292b4d11d91b7aa46aef1ccd8ae3f7f Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 22 Mar 2021 09:37:23 -0400 Subject: [PATCH 136/729] Remove unnecessary comments. --- src/mlpack/methods/hmm/hmm.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mlpack/methods/hmm/hmm.hpp b/src/mlpack/methods/hmm/hmm.hpp index 932382f41e..164a1390f4 100644 --- a/src/mlpack/methods/hmm/hmm.hpp +++ b/src/mlpack/methods/hmm/hmm.hpp @@ -441,8 +441,6 @@ class HMM protected: /** * Given emission probabilities, computes forward probabilities at time t=0. - * The template parameter allows passing an Armadillo subview without - * instantiating it. * * @param emissionLogProb Emission probability at time t=0. * @param logScales Vector in which the log of scaling factors will be saved. @@ -453,8 +451,6 @@ class HMM /** * Given emission probabilities, computes forward probabilities for time t>0. - * The template parameter allows passing an Armadillo subview without - * instantiating it. * * @param emissionLogProb Emission probability at time t>0. * @param logScales Vector in which the log of scaling factors will be saved. From f06cb9c9e382b91e10eb4862a98897afd296dbfe Mon Sep 17 00:00:00 2001 From: mayank raj Date: Wed, 24 Mar 2021 14:16:12 +0530 Subject: [PATCH 137/729] minor changes --- .../tanh_exponential_function.hpp | 13 +++++++++++++ src/mlpack/methods/ann/layer/base_layer.hpp | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index 5e74b73342..cabe427a88 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -4,6 +4,19 @@ * * Definition and implementation of the Tanh exponential function. * + * For more information see the following paper + * + * @code + * @misc{The Institution of Engineering and Technology 2015 , + * title = {TanhExp: A Smooth Activation Function with High Convergence Speed for Lightweight Neural Networks}, + * author = {Xinyu Liu and Xiaoguang Di}, + * year = {2020}, + * url = {https://arxiv.org/pdf/2003.09855v2.pdf}, + * eprint = {2003.09855v2}, + * archivePrefix = {arXiv}, + * primaryClass = {cs.LG} } + * @endcode + * * 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 diff --git a/src/mlpack/methods/ann/layer/base_layer.hpp b/src/mlpack/methods/ann/layer/base_layer.hpp index a1dcca3e35..7169d5f474 100644 --- a/src/mlpack/methods/ann/layer/base_layer.hpp +++ b/src/mlpack/methods/ann/layer/base_layer.hpp @@ -292,7 +292,7 @@ template < using HardSwishFunctionLayer = BaseLayer< ActivationFunction, InputDataType, OutputDataType>; - /** +/** * Standard TanhExp-Layer using the TanhExp activation function. */ template < From 0126e4efd58637ac0dd0685339d6a46784175fff Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 25 Mar 2021 10:20:46 -0400 Subject: [PATCH 138/729] Add code to check for a CSV header. --- .../bindings/cli/print_type_doc_impl.hpp | 12 +++-- src/mlpack/core/data/detect_file_type.cpp | 53 +++++++++++++++++-- src/mlpack/core/data/detect_file_type.hpp | 10 +++- src/mlpack/core/data/load.hpp | 4 ++ 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/mlpack/bindings/cli/print_type_doc_impl.hpp b/src/mlpack/bindings/cli/print_type_doc_impl.hpp index e6aa78d915..81edad4910 100644 --- a/src/mlpack/bindings/cli/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/cli/print_type_doc_impl.hpp @@ -98,8 +98,10 @@ std::string PrintTypeDoc( "of the data is detected by the extension of the filename. The storage" " should be such that one row corresponds to one point, and one column " "corresponds to one dimension (this is the typical storage format for " - "on-disk data). All values of the matrix will be loaded as double-" - "precision floating point data."; + "on-disk data). CSV files will be checked for a header; if no header " + "is found, the first row will be loaded as a data point. All values of" + " the matrix will be loaded as double-" "precision floating point " + "data."; } else if (std::is_same>::value) { @@ -111,8 +113,10 @@ std::string PrintTypeDoc( "compiled with HDF5 support. The type of the data is detected by the " "extension of the filename. The storage should be such that one row " "corresponds to one point, and one column corresponds to one dimension " - "(this is the typical storage format for on-disk data). All values of " - "the matrix will be loaded as unsigned integers."; + "(this is the typical storage format for on-disk data). CSV files will" + " be checked for a header; if no header is found, the first row will be" + " loaded as a data point. All values of the matrix will be loaded as " + "unsigned integers."; } else if (std::is_same::value || std::is_same::value) diff --git a/src/mlpack/core/data/detect_file_type.cpp b/src/mlpack/core/data/detect_file_type.cpp index 740ffabd93..4fb09661f9 100644 --- a/src/mlpack/core/data/detect_file_type.cpp +++ b/src/mlpack/core/data/detect_file_type.cpp @@ -47,9 +47,14 @@ std::string GetStringType(const arma::file_type& type) * from Armadillo's function guess_file_type_internal(), but we avoid using * internal Armadillo functionality. * + * If the file is detected as a CSV, and the CSV is detected to have a header + * row, the stream `f` will be fast-forwarded to point at the second line of the + * file. + * * @param f Opened istream to look into to guess the file type. + * @param filename Name of file, for output purposes. */ -arma::file_type GuessFileType(std::istream& f) +arma::file_type GuessFileType(std::istream& f, const std::string filename) { f.clear(); const std::fstream::pos_type pos1 = f.tellg(); @@ -114,6 +119,42 @@ arma::file_type GuessFileType(std::istream& f) } } + if (hasComma && (hasBracket == false)) + { + // If we believe we have a CSV file, then we want to try to skip any header + // row. We'll detect a header row by simply seeing if anything in the first + // line doesn't parse as a number. + // + // TODO: this is not a foolproof algorithm, so there should eventually be a + // way added for the user to explicitly indicate that there is or isn't a + // header. + std::string firstLine; + std::getline(f, firstLine); + + std::stringstream str(firstLine); + std::string token; + bool allNumeric = true; + // We'll abuse 'getline()' to split on commas. + while (std::getline(str, token, ',')) + { + // Let's see if we can parse the token into a number. + try + { + (void) std::stod(token); + } + catch (std::invalid_argument& s) + { + allNumeric = false; + break; + } + } + + // If we could parse everything into a number, then let's rewind `f` so that + // it's at the start of the file. + if (allNumeric) + f.seekg(pos1); + } + delete[] dataMem; if (hasBinary) @@ -131,12 +172,14 @@ arma::file_type GuessFileType(std::istream& f) * necessary. (For instance, a .csv file could be delimited by spaces, commas, * or tabs.) This is meant to be used during loading. * + * If the file is detected as a CSV, and the CSV is detected to have a header + * row, `stream` will be fast-forwarded to point at the second line of the file. + * * @param stream Opened file stream to look into for autodetection. * @param filename Name of the file. * @return The detected file type. */ -arma::file_type AutoDetect(std::fstream& stream, - const std::string& filename) +arma::file_type AutoDetect(std::fstream& stream, const std::string& filename) { // Get the extension. std::string extension = Extension(filename); @@ -144,7 +187,7 @@ arma::file_type AutoDetect(std::fstream& stream, if (extension == "csv" || extension == "tsv") { - detectedLoadType = GuessFileType(stream); + detectedLoadType = GuessFileType(stream, filename); if (detectedLoadType == arma::csv_ascii) { if (extension == "tsv") @@ -202,7 +245,7 @@ arma::file_type AutoDetect(std::fstream& stream, } else // It's not arma_ascii. Now we let Armadillo guess. { - detectedLoadType = GuessFileType(stream); + detectedLoadType = GuessFileType(stream, filename); if (detectedLoadType != arma::raw_ascii && detectedLoadType != arma::csv_ascii) diff --git a/src/mlpack/core/data/detect_file_type.hpp b/src/mlpack/core/data/detect_file_type.hpp index ab387ad0ba..7552664b85 100644 --- a/src/mlpack/core/data/detect_file_type.hpp +++ b/src/mlpack/core/data/detect_file_type.hpp @@ -30,9 +30,14 @@ std::string GetStringType(const arma::file_type& type); * from Armadillo's function guess_file_type_internal(), but we avoid using * internal Armadillo functionality. * + * If the file is detected as a CSV, and the CSV is detected to have a header + * row, the stream `f` will be fast-forwarded to point at the second line of the + * file. + * * @param f Opened istream to look into to guess the file type. + * @param filename Name of file, for output purposes. */ -arma::file_type GuessFileType(std::istream& f); +arma::file_type GuessFileType(std::istream& f, const std::string& filename); /** * Attempt to auto-detect the type of a file given its extension, and by @@ -40,6 +45,9 @@ arma::file_type GuessFileType(std::istream& f); * necessary. (For instance, a .csv file could be delimited by spaces, commas, * or tabs.) This is meant to be used during loading. * + * If the file is detected as a CSV, and the CSV is detected to have a header + * row, `stream` will be fast-forwarded to point at the second line of the file. + * * @param stream Opened file stream to look into for autodetection. * @param filename Name of the file. * @return The detected file type. arma::file_type_unknown if unknown. diff --git a/src/mlpack/core/data/load.hpp b/src/mlpack/core/data/load.hpp index d6681d5dce..9b54f43ce1 100644 --- a/src/mlpack/core/data/load.hpp +++ b/src/mlpack/core/data/load.hpp @@ -48,6 +48,10 @@ namespace data /** Functions to load and save matrices and models. */ { * `inputLoadType` parameter with the correct type above (e.g. * `arma::csv_ascii`.) * + * If the detected file type is CSV (`arma::csv_ascii`), the first row will be + * checked for a CSV header. If a CSV header is not detected, the first row + * will be treated as data; otherwise, the first row will be skipped. + * * If the parameter 'fatal' is set to true, a std::runtime_error exception will * be thrown if the matrix does not load successfully. The parameter * 'transpose' controls whether or not the matrix is transposed after loading. From 6dda52946b13ca8ce3cac7bb6459ec33a496f752 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 25 Mar 2021 11:00:43 -0400 Subject: [PATCH 139/729] Fix minor bugs. --- src/mlpack/core/data/detect_file_type.cpp | 6 +++--- src/mlpack/core/data/detect_file_type.hpp | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mlpack/core/data/detect_file_type.cpp b/src/mlpack/core/data/detect_file_type.cpp index 4fb09661f9..8f88188df6 100644 --- a/src/mlpack/core/data/detect_file_type.cpp +++ b/src/mlpack/core/data/detect_file_type.cpp @@ -54,7 +54,7 @@ std::string GetStringType(const arma::file_type& type) * @param f Opened istream to look into to guess the file type. * @param filename Name of file, for output purposes. */ -arma::file_type GuessFileType(std::istream& f, const std::string filename) +arma::file_type GuessFileType(std::istream& f) { f.clear(); const std::fstream::pos_type pos1 = f.tellg(); @@ -187,7 +187,7 @@ arma::file_type AutoDetect(std::fstream& stream, const std::string& filename) if (extension == "csv" || extension == "tsv") { - detectedLoadType = GuessFileType(stream, filename); + detectedLoadType = GuessFileType(stream); if (detectedLoadType == arma::csv_ascii) { if (extension == "tsv") @@ -245,7 +245,7 @@ arma::file_type AutoDetect(std::fstream& stream, const std::string& filename) } else // It's not arma_ascii. Now we let Armadillo guess. { - detectedLoadType = GuessFileType(stream, filename); + detectedLoadType = GuessFileType(stream); if (detectedLoadType != arma::raw_ascii && detectedLoadType != arma::csv_ascii) diff --git a/src/mlpack/core/data/detect_file_type.hpp b/src/mlpack/core/data/detect_file_type.hpp index 7552664b85..8856de29fe 100644 --- a/src/mlpack/core/data/detect_file_type.hpp +++ b/src/mlpack/core/data/detect_file_type.hpp @@ -35,9 +35,8 @@ std::string GetStringType(const arma::file_type& type); * file. * * @param f Opened istream to look into to guess the file type. - * @param filename Name of file, for output purposes. */ -arma::file_type GuessFileType(std::istream& f, const std::string& filename); +arma::file_type GuessFileType(std::istream& f); /** * Attempt to auto-detect the type of a file given its extension, and by From 7bb314b0041fbddd213c6d5b81f9615d88b9f249 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 25 Mar 2021 11:00:49 -0400 Subject: [PATCH 140/729] Add test for detecting CSV header. --- src/mlpack/tests/load_save_test.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/mlpack/tests/load_save_test.cpp b/src/mlpack/tests/load_save_test.cpp index 602533a84b..44e48e338e 100644 --- a/src/mlpack/tests/load_save_test.cpp +++ b/src/mlpack/tests/load_save_test.cpp @@ -2485,3 +2485,22 @@ TEST_CASE("DatasetMapperNonUniqueTest", "[LoadSaveTest]") REQUIRE(dm.UnmapString(nan, 0, 1) == "goodbye"); REQUIRE(dm.UnmapString(nan, 0, 2) == "cheese"); } + +/** + * Make sure if we load a CSV with a header, that that header doesn't get loaded + * as a point. + */ +TEST_CASE("LoadCSVHeaderTest", "[LoadSaveTest]") +{ + fstream f; + f.open("test.csv", fstream::out); + f << "a, b, c, d" << endl; + f << "1, 2, 3, 4" << endl; + f << "5, 6, 7, 8" << endl; + + arma::mat dataset; + data::Load("test.csv", dataset); + + REQUIRE(dataset.n_rows == 4); + REQUIRE(dataset.n_cols == 2); +} From 64d6402fa0b2cbc8dd57d15889ff1223915f85ac Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 25 Mar 2021 13:09:26 -0400 Subject: [PATCH 141/729] Update src/mlpack/bindings/cli/print_type_doc_impl.hpp Co-authored-by: Anush Kini <33577829+Abilityguy@users.noreply.github.com> --- src/mlpack/bindings/cli/print_type_doc_impl.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mlpack/bindings/cli/print_type_doc_impl.hpp b/src/mlpack/bindings/cli/print_type_doc_impl.hpp index 81edad4910..51e3106de5 100644 --- a/src/mlpack/bindings/cli/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/cli/print_type_doc_impl.hpp @@ -100,8 +100,7 @@ std::string PrintTypeDoc( "corresponds to one dimension (this is the typical storage format for " "on-disk data). CSV files will be checked for a header; if no header " "is found, the first row will be loaded as a data point. All values of" - " the matrix will be loaded as double-" "precision floating point " - "data."; + " the matrix will be loaded as double-precision floating point data."; } else if (std::is_same>::value) { From be0e152f396d8c5a6b1634d6495f42a212be8446 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 26 Mar 2021 11:57:09 +0530 Subject: [PATCH 142/729] Changed warmStart position in signature of train --- .../methods/random_forest/random_forest.hpp | 34 +++++++++---------- .../random_forest/random_forest_impl.hpp | 20 +++++------ .../random_forest/random_forest_main.cpp | 4 +-- src/mlpack/tests/random_forest_test.cpp | 8 ++--- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 2f8d27135e..503eada9c0 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -167,9 +167,9 @@ class RandomForest * @param minimumLeafSize Minimum number of points in each tree's leaf nodes. * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. + * @param warmStart When set to `true`, it adds `numTrees` new trees to the + * existing random forest else a new forest is trained from scratch. * @param dimensionSelector Instantiated dimension selection policy. - * @param warmStart When set to `true`, it fits new trees and add them to the - * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -180,9 +180,9 @@ class RandomForest const size_t minimumLeafSize = 1, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, + const bool warmStart = false, DimensionSelectionType dimensionSelector = - DimensionSelectionType(), - bool warmStart = false); + DimensionSelectionType()); /** * Train the random forest on the given labeled training data with the given @@ -201,9 +201,9 @@ class RandomForest * @param minimumLeafSize Minimum number of points in each tree's leaf nodes. * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. + * @param warmStart When set to `true`, it adds `numTrees` new trees to the + * existing random forest else a new forest is trained from scratch. * @param dimensionSelector Instantiated dimension selection policy. - * @param warmStart When set to `true`, it fits new trees and add them to the - * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -215,9 +215,9 @@ class RandomForest const size_t minimumLeafSize = 1, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, + const bool warmStart = false, DimensionSelectionType dimensionSelector = - DimensionSelectionType(), - bool warmStart = false); + DimensionSelectionType()); /** * Train the random forest on the given weighted labeled training data with @@ -234,9 +234,9 @@ class RandomForest * @param minimumLeafSize Minimum number of points in each tree's leaf nodes. * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. + * @param warmStart When set to `true`, it adds `numTrees` new trees to the + * existing random forest else a new forest is trained from scratch. * @param dimensionSelector Instantiated dimension selection policy. - * @param warmStart When set to `true`, it fits new trees and add them to the - * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -248,9 +248,9 @@ class RandomForest const size_t minimumLeafSize = 1, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, + const bool warmStart = false, DimensionSelectionType dimensionSelector = - DimensionSelectionType(), - bool warmStart = false); + DimensionSelectionType()); /** * Train the random forest on the given weighted labeled training data with @@ -269,9 +269,9 @@ class RandomForest * @param minimumLeafSize Minimum number of points in each tree's leaf nodes. * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. + * @param warmStart When set to `true`, it adds `numTrees` new trees to the + * existing random forest else a new forest is trained from scratch. * @param dimensionSelector Instantiated dimension selection policy. - * @param warmStart When set to `true`, it fits new trees and add them to the - * previous forest else a new forest is trained from scratch. * @return The average entropy of all the decision trees trained under forest. */ template @@ -284,9 +284,9 @@ class RandomForest const size_t minimumLeafSize = 1, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, + const bool warmStart = false, DimensionSelectionType dimensionSelector = - DimensionSelectionType(), - bool warmStart = false); + DimensionSelectionType()); /** * Predict the class of the given point. If the random forest has not been @@ -384,7 +384,7 @@ class RandomForest const double minimumGainSplit, const size_t maximumDepth, DimensionSelectionType& dimensionSelector, - bool warmStart = false); + const bool warmStart = false); //! The trees in the forest. std::vector trees; diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 3599056729..c19ee5d98f 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -163,8 +163,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector, - bool warmStart) + const bool warmStart, + DimensionSelectionType dimensionSelector) { // Pass off to Train(). data::DatasetInfo datasetInfo; // Ignored by Train(). @@ -196,12 +196,12 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector, - bool warmStart) + const bool warmStart, + DimensionSelectionType dimensionSelector) { // Pass off to Train(). arma::rowvec weights; // Ignored by Train(). - return Train(dataset, datasetInfo, labels, numClasses, weights, + return Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, warmStart); } @@ -228,8 +228,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector, - bool warmStart) + const bool warmStart, + DimensionSelectionType dimensionSelector) { // Pass off to Train(). data::DatasetInfo datasetInfo; // Ignored by Train(). @@ -261,8 +261,8 @@ double RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector, - bool warmStart) + const bool warmStart, + DimensionSelectionType dimensionSelector) { // Pass off to Train(). return Train(dataset, datasetInfo, labels, numClasses, weights, @@ -470,7 +470,7 @@ double RandomForest< const double minimumGainSplit, const size_t maximumDepth, DimensionSelectionType& dimensionSelector, - bool warmStart) + const bool warmStart) { size_t oldNumTrees = trees.size(); // Convert avgGain to total gain. diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index bdf94e1d4a..5edfe2d1e1 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -249,11 +249,11 @@ static void mlpackMain() { bool warmStart = IO::GetParam("warm_start"); rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, - minimumGainSplit, maxDepth, mrds, warmStart); + minimumGainSplit, maxDepth, warmStart, mrds); } else rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, - minimumGainSplit, maxDepth, mrds); + minimumGainSplit, maxDepth, false, mrds); Timer::Stop("rf_training"); // Did we want training accuracy? diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 966af53e55..b6e615e761 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -457,14 +457,14 @@ TEST_CASE("RandomForestCategoricalTrainReturnEntropy", "[RandomForestTest]") // Test random forest on unweighted categorical dataset. RandomForest<> rf; double entropy = rf.Train(fullData, di, fullLabels, 5, 15 /* 15 trees */, 1, - 1e-7, 0, MultipleRandomDimensionSelect(3)); + 1e-7, 0, false, MultipleRandomDimensionSelect(3)); REQUIRE(std::isfinite(entropy) == true); // Test random forest on weighted categorical dataset. RandomForest<> wrf; entropy = wrf.Train(fullData, di, fullLabels, 5, weights, 15 /* 15 trees */, - 1, 1e-7, 0, MultipleRandomDimensionSelect(3)); + 1, 1e-7, 0, false, MultipleRandomDimensionSelect(3)); REQUIRE(std::isfinite(entropy) == true); } @@ -518,7 +518,7 @@ TEST_CASE("WarmStartTreesTest", "[RandomForestTest]") REQUIRE(rf.NumTrees() == 25); rf.Train(trainingData, di, trainingLabels, 5, 20 /* 20 trees */, 1, 1e-7, 0, - MultipleRandomDimensionSelect(4), true /* warmStart */); + true /* warmStart */, MultipleRandomDimensionSelect(4)); REQUIRE(rf.NumTrees() == 25 + 20); } @@ -547,7 +547,7 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") size_t oldCorrect = arma::accu(oldPredictions == trainingLabels); rf.Train(trainingData, di, trainingLabels, 5, 20 /* 20 trees */, 1, 1e-7, 0, - MultipleRandomDimensionSelect(4), true /* warmStart */); + true /* warmStart */, MultipleRandomDimensionSelect(4)); // Get performance statistics on train data. arma::Row newPredictions; From b3de3ceb398faad76988ca5ac911a8e1c5b0bb98 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 26 Mar 2021 11:58:44 +0530 Subject: [PATCH 143/729] Initialised avgGain in ctors --- src/mlpack/methods/random_forest/random_forest.hpp | 2 +- .../methods/random_forest/random_forest_impl.hpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 503eada9c0..aa9ebc9b93 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -390,7 +390,7 @@ class RandomForest std::vector trees; //! The average gain of the forest. - double avgGain = 0.0; + double avgGain; }; } // namespace tree diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index c19ee5d98f..0277f71ece 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -39,7 +39,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector): + avgGain(0.0) { // Pass off work to the Train() method. data::DatasetInfo info; // Ignored. @@ -71,7 +72,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector): + avgGain(0.0) { // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. @@ -102,7 +104,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector): + avgGain(0.0) { // Pass off work to the Train() method. data::DatasetInfo info; // Ignored by Train(). @@ -134,7 +137,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector) + DimensionSelectionType dimensionSelector): + avgGain(0.0) { // Pass off work to the Train() method. Train(dataset, datasetInfo, labels, numClasses, weights, From ff3a35bdef569941cc7d313f4a6a39048f970394 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 26 Mar 2021 12:07:28 +0530 Subject: [PATCH 144/729] Reduced number of old trees in test --- src/mlpack/tests/random_forest_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index b6e615e761..62592c0907 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -536,7 +536,7 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") MockCategoricalData(trainingData, trainingLabels, di); // Train a random forest. - RandomForest<> rf(trainingData, di, trainingLabels, 5, 25 /* 25 trees */, 1, + RandomForest<> rf(trainingData, di, trainingLabels, 5, 3 /* 3 trees */, 1, 1e-7, 0, MultipleRandomDimensionSelect(4)); // Get performance statistics on train data. From d90069be5d7ea8c2c541a2a58d024dcc486cef32 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 26 Mar 2021 12:54:13 +0530 Subject: [PATCH 145/729] Fixed unnecessary copying of trees --- .../random_forest/random_forest_impl.hpp | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 0277f71ece..106072c8f2 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -476,21 +476,15 @@ double RandomForest< DimensionSelectionType& dimensionSelector, const bool warmStart) { - size_t oldNumTrees = trees.size(); + // Reset the forest if we are not doing a warm-start. + if (!warmStart) + trees.clear(); + const size_t oldNumTrees = trees.size(); + trees.resize(trees.size() + numTrees); + // Convert avgGain to total gain. double totalGain = avgGain * oldNumTrees; - if (warmStart) - { - // This will extend the vector with untrained trees. - trees.resize(trees.size() + numTrees); - } - else - { - // This will fill the vector with untrained trees. - trees.resize(numTrees); - } - // Train each tree individually. #pragma omp parallel for reduction( + : totalGain) for (omp_size_t i = 0; i < numTrees; ++i) @@ -503,45 +497,39 @@ double RandomForest< bootstrapLabels, bootstrapWeights); Timer::Stop("bootstrap"); - // Now build the decision tree. - DecisionTreeType tmpTree; Timer::Start("train_tree"); if (UseWeights) { if (UseDatasetInfo) { - totalGain += tmpTree.Train(bootstrapDataset, datasetInfo, - bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, - minimumGainSplit, maximumDepth, dimensionSelector); + totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, + datasetInfo, bootstrapLabels, numClasses, bootstrapWeights, + minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } else { - totalGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, - bootstrapWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, + bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, + minimumGainSplit, maximumDepth, dimensionSelector); } } else { if (UseDatasetInfo) { - totalGain += tmpTree.Train(bootstrapDataset, datasetInfo, - bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, - maximumDepth, dimensionSelector); + totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, + datasetInfo, bootstrapLabels, numClasses, minimumLeafSize, + minimumGainSplit, maximumDepth, dimensionSelector); } else { - totalGain += tmpTree.Train(bootstrapDataset, bootstrapLabels, numClasses, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, + bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, + maximumDepth, dimensionSelector); } } - // Storing the trained tree at the desired index. - if (warmStart) - trees[oldNumTrees + i] = tmpTree; - else - trees[i] = tmpTree; - Timer::Stop("train_tree"); } From af79e1c02d618f326fb1f91188eb991ce1f70b1a Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 21:09:46 +0530 Subject: [PATCH 146/729] Simplified code to train in bindings. --- .../methods/random_forest/random_forest_main.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 5edfe2d1e1..f64fdc8c07 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -245,15 +245,9 @@ static void mlpackMain() const size_t numClasses = arma::max(labels) + 1; // Train the model. - if (IO::HasParam("warm_start")) - { - bool warmStart = IO::GetParam("warm_start"); - rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, - minimumGainSplit, maxDepth, warmStart, mrds); - } - else - rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, - minimumGainSplit, maxDepth, false, mrds); + rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, + minimumGainSplit, maxDepth, IO::HasParam("warm_start"), mrds); + Timer::Stop("rf_training"); // Did we want training accuracy? From ef52e858ae6eaf9d290adfa747735ccb80a68678 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 21:24:05 +0530 Subject: [PATCH 147/729] Added suggestion --- src/mlpack/methods/random_forest/random_forest_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index f64fdc8c07..c73385a709 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -207,9 +207,9 @@ static void mlpackMain() ReportIgnoredParam({{ "training", false }}, "minimum_leaf_size"); RandomForestModel* rfModel; - // Handles the case when we are either training on top of existing forest - // else we are making predictions only. - if (IO::HasParam("warm_start") or IO::HasParam("input_model")) + // Input model is loaded when we are either doing warm-started training or + // else we are making predictions only or both. + if (IO::HasParam("input_model")) rfModel = IO::GetParam("input_model"); // Handles the case when we are training new forest from scratch. else From 0f65b18e6d5fb2b80cd953726acd9359ff0394b4 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 21:33:42 +0530 Subject: [PATCH 148/729] Fixed failing tests --- src/mlpack/tests/main_tests/random_forest_test.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index 6f0c932ed9..eea8d696bb 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -500,8 +500,8 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart", FAIL("Cannot load labels for vc2_labels.txt"); // Input training data. - SetInputParam("training", std::move(inputData)); - SetInputParam("labels", std::move(labels)); + SetInputParam("training", inputData); + SetInputParam("labels", labels); mlpackMain(); @@ -509,7 +509,11 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart", size_t oldNumTrees = IO::GetParam("output_model")->rf.NumTrees(); + // Input training data. + SetInputParam("training", std::move(inputData)); + SetInputParam("labels", std::move(labels)); SetInputParam("warm_start", true); + // Input pre-trained model. SetInputParam("input_model", IO::GetParam("output_model")); From fb928ae37f3ae29fc4597af17a8e7ae343545412 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 21:40:04 +0530 Subject: [PATCH 149/729] Added to `HISTORY.md` --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index f0b696d6ac..ac338a6036 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,6 @@ ### mlpack ?.?.? ###### ????-??-?? + * Added warm start feature to Random Forest (#2881). * Added Pixel Shuffle layer (#2563). * Add "check_input_matrices" option to python bindings that checks From 416cd7cf8c62387439abbbe04e0878c4b82619d5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 21:48:04 +0530 Subject: [PATCH 150/729] Added a missing newline --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index ac338a6036..c40cf9ea18 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? * Added warm start feature to Random Forest (#2881). + * Added Pixel Shuffle layer (#2563). * Add "check_input_matrices" option to python bindings that checks From bc4307d37ecfbef9f4efb3c8387b1327a948a77f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 22:42:58 +0530 Subject: [PATCH 151/729] Undo unwanted changes --- src/mlpack/methods/random_forest/random_forest_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 106072c8f2..7bd7d2d878 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -269,7 +269,7 @@ double RandomForest< DimensionSelectionType dimensionSelector) { // Pass off to Train(). - return Train(dataset, datasetInfo, labels, numClasses, weights, + return Train(dataset, datasetInfo, labels, numClasses, weights, numTrees, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, warmStart); } From 5d3d81de288b88160bd72b6d9fa6ad520a11ee55 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 27 Mar 2021 22:43:09 +0530 Subject: [PATCH 152/729] Update HISTORY.md Co-authored-by: Ryan Curtin --- HISTORY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index c40cf9ea18..31ffa70b83 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? - * Added warm start feature to Random Forest (#2881). + * Added warm start feature to Random Forest (#2881); this feature is + accessible from mlpack's bindings to different languages. * Added Pixel Shuffle layer (#2563). From abe7ecc2edcadb5755adcc1cf8acd38b4f5c88f2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 28 Mar 2021 12:31:53 +0530 Subject: [PATCH 153/729] Minor fix in documentation --- src/mlpack/methods/random_forest/random_forest.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index aa9ebc9b93..746547697e 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -168,7 +168,7 @@ class RandomForest * @param minimumGainSplit Minimum gain for splitting a decision tree node. * @param maximumDepth Maximum depth for the tree. * @param warmStart When set to `true`, it adds `numTrees` new trees to the - * existing random forest else a new forest is trained from scratch. + * existing random forest otherwise a new forest is trained from scratch. * @param dimensionSelector Instantiated dimension selection policy. * @return The average entropy of all the decision trees trained under forest. */ From 73bc5b11f7533c8f87daf0510c46645825914c3c Mon Sep 17 00:00:00 2001 From: gunnxx Date: Sun, 28 Mar 2021 15:49:56 +0700 Subject: [PATCH 154/729] edit RL tutorial for custom DQN network --- .../reinforcement_learning.txt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/doc/tutorials/reinforcement_learning/reinforcement_learning.txt b/doc/tutorials/reinforcement_learning/reinforcement_learning.txt index d8fb6cec58..ef5a3b9f41 100644 --- a/doc/tutorials/reinforcement_learning/reinforcement_learning.txt +++ b/doc/tutorials/reinforcement_learning/reinforcement_learning.txt @@ -153,19 +153,22 @@ the output shape is represented by the number of possible actions, which in this (`foward` and `backward`). We can also use mlpack's ann module to setup a custom FFN network. For example, here we use a single -hidden layer. +hidden layer. However, Q-learning agent expect an object to have `ResetNoise` method which `SimpleDQN` has. +We can't pass mlpack's FFN network directly. Instead, we have to wrap it into `SimpleDQN` object. @code int main() { // Set up the network. - FFN, GaussianInitialization> model(MeanSquaredError<>(), + FFN, GaussianInitialization> network(MeanSquaredError<>(), GaussianInitialization(0, 0.001)); - model.Add>(4, 128); - model.Add>(); - model.Add>(128, 128); - model.Add>(); - model.Add>(128, 2); + network.Add>(4, 128); + network.Add>(); + network.Add>(128, 128); + network.Add>(); + network.Add>(128, 2); + + SimpleDQN<> model(network); @endcode From 487ab565c6ee0ffa3e9096543acae3a9e893f575 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 28 Mar 2021 14:37:35 -0400 Subject: [PATCH 155/729] Remove inaccurate comment. --- src/mlpack/core/data/detect_file_type.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/core/data/detect_file_type.cpp b/src/mlpack/core/data/detect_file_type.cpp index 8f88188df6..3cf990f715 100644 --- a/src/mlpack/core/data/detect_file_type.cpp +++ b/src/mlpack/core/data/detect_file_type.cpp @@ -52,7 +52,6 @@ std::string GetStringType(const arma::file_type& type) * file. * * @param f Opened istream to look into to guess the file type. - * @param filename Name of file, for output purposes. */ arma::file_type GuessFileType(std::istream& f) { From bea27ff487a6f43df67b232539da8814a0ab868c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 28 Mar 2021 15:14:56 -0400 Subject: [PATCH 156/729] Better strategy for finding invalid numbers. --- src/mlpack/core/data/detect_file_type.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/mlpack/core/data/detect_file_type.cpp b/src/mlpack/core/data/detect_file_type.cpp index 3cf990f715..c00954f1c0 100644 --- a/src/mlpack/core/data/detect_file_type.cpp +++ b/src/mlpack/core/data/detect_file_type.cpp @@ -137,11 +137,22 @@ arma::file_type GuessFileType(std::istream& f) while (std::getline(str, token, ',')) { // Let's see if we can parse the token into a number. - try + double num; + std::string rest; + + // Try to parse into a number. + std::stringstream s(token); + s >> num; + if (s.fail()) { - (void) std::stod(token); + allNumeric = false; + break; } - catch (std::invalid_argument& s) + + // Now check to see there isn't anything else. (This catches cases like, + // e.g., "1a".) + s >> rest; + if (rest.length() > 0) { allNumeric = false; break; From 40698325b693fb183011a18b74f22ee23509a316 Mon Sep 17 00:00:00 2001 From: Tri Wahyu Guntara <31506965+gunnxx@users.noreply.github.com> Date: Mon, 29 Mar 2021 12:49:53 +0700 Subject: [PATCH 157/729] edit RL tutorial for custom DQN network Co-authored-by: Marcus Edel --- doc/tutorials/reinforcement_learning/reinforcement_learning.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorials/reinforcement_learning/reinforcement_learning.txt b/doc/tutorials/reinforcement_learning/reinforcement_learning.txt index ef5a3b9f41..34edf931da 100644 --- a/doc/tutorials/reinforcement_learning/reinforcement_learning.txt +++ b/doc/tutorials/reinforcement_learning/reinforcement_learning.txt @@ -153,7 +153,7 @@ the output shape is represented by the number of possible actions, which in this (`foward` and `backward`). We can also use mlpack's ann module to setup a custom FFN network. For example, here we use a single -hidden layer. However, Q-learning agent expect an object to have `ResetNoise` method which `SimpleDQN` has. +hidden layer. However, the Q-Learning agent expects the object to have a `ResetNoise` method which `SimpleDQN` has. We can't pass mlpack's FFN network directly. Instead, we have to wrap it into `SimpleDQN` object. @code From ecde617cff45b204e2d96f5c9cbe2902d441baa9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 29 Mar 2021 17:14:58 +0530 Subject: [PATCH 158/729] Fixed static code analysis error --- .../methods/random_forest/random_forest.hpp | 2 +- .../random_forest/random_forest_impl.hpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 746547697e..3ad85106ce 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -35,7 +35,7 @@ class RandomForest * Construct the random forest without any training or specifying the number * of trees. Predict() will throw an exception until Train() is called. */ - RandomForest() { } + RandomForest(); /** * Create a random forest, training on the given labeled training data with diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 7bd7d2d878..32a380be61 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -18,6 +18,25 @@ namespace mlpack { namespace tree { +template< + typename FitnessFunction, + typename DimensionSelectionType, + template class NumericSplitType, + template class CategoricalSplitType, + typename ElemType +> +RandomForest< + FitnessFunction, + DimensionSelectionType, + NumericSplitType, + CategoricalSplitType, + ElemType +>::RandomForest(): + avgGain(0.0) +{ + // Nothing to do here. +} + template< typename FitnessFunction, typename DimensionSelectionType, From 240463c1da7fdddc5ef7895dce15bd84d0f6f7fc Mon Sep 17 00:00:00 2001 From: FawwazMayda <33770567+FawwazMayda@users.noreply.github.com> Date: Wed, 31 Mar 2021 00:05:41 +0800 Subject: [PATCH 159/729] Improve Linear Regression Docs. (#2890) * adding multivariate examples * editing some typo in file * edit some typo and modify the section * Update linear_regression.txt * Update linear_regression.txt --- .../linear_regression/linear_regression.txt | 215 ++++++++++++------ 1 file changed, 142 insertions(+), 73 deletions(-) diff --git a/doc/tutorials/linear_regression/linear_regression.txt b/doc/tutorials/linear_regression/linear_regression.txt index a0baec8ec3..751ff0c935 100644 --- a/doc/tutorials/linear_regression/linear_regression.txt +++ b/doc/tutorials/linear_regression/linear_regression.txt @@ -46,6 +46,7 @@ A list of all the sections this tutorial contains. - \ref cli_ex2_lrtut - \ref cli_ex3_lrtut - \ref cli_ex4_lrtut + - \ref cli_ex5_lrtut - \ref linreg_lrtut - \ref linreg_ex1_lrtut - \ref linreg_ex2_lrtut @@ -113,22 +114,23 @@ $ cat dataset.csv 4,4 $ cat lr.xml - - - - - - 2 - 1 - 2 - 1 - -3.97205464519563669e-16 - 1.00000000000000022e+00 - - 0.00000000000000000e+00 - 1 - - + + + + 0 + + 2 + 1 + 1 + 0 + 1 + + 0 + true + + + + @endcode As you can see, the function for this input is \f$f(y)=0+1x_1\f$. We can see @@ -141,36 +143,102 @@ dataset is one dimensional, and the last column has the \f$y\f$ values, or responses, for each row. You can specify these responses in a separate file if you want, using the \c --input_responses, or \c -r, option. -@subsection cli_ex2_lrtut Compute model and predict at the same time +@subsection cli_ex2_lrtut Train a multivariate linear regression model + +Multivariate linear regression means that the response variable is predicted by +more than just one input variable. In this example we will try to fit a +multivariate linear regression model to data that contains four variables, stored in +\c dataset_2.csv. @code -$ mlpack_linear_regression --training_file dataset.csv --test_file predict.csv \ +$ cat dataset_2.csv +0,0,0,0,14 +1,1,1,1,24 +2,1,0,2,27 +1,2,2,2,32 +-1,-3,0,2,17 +@endcode + +Now let's run \c mlpack_linear_regression as usual: + +@code +$ mlpack_linear_regression --training_file dataset_2.csv -v -M lr.xml +[INFO ] Loading 'dataset_2.csv' as CSV data. Size is 5 x 5. +[INFO ] +[INFO ] Execution parameters: +[INFO ] help: 0 +[INFO ] info: +[INFO ] input_model_file: +[INFO ] lambda: 0 +[INFO ] output_model_file: lr.xml +[INFO ] output_predictions_file: +[INFO ] test_file: +[INFO ] training_file: dataset_2.csv +[INFO ] training_responses_file: +[INFO ] verbose: 1 +[INFO ] version: 0 +[INFO ] Program timers: +[INFO ] load_regressors: 0.000060s +[INFO ] loading_data: 0.000050s +[INFO ] regression: 0.000049s +[INFO ] total_time: 0.000118s + +$ cat lr.xml + + + + 0 + + 5 + 1 + 1 + 14.00000000000002 + 1.9999999999999447 + 1.0000000000000431 + 2.9999999999999516 + 4.0000000000000249 + + 0 + true + + +@endcode + +If we take a look at the \c lr.xml output we can see the \c \ part has five elements which +the first corresponds to \f$\beta_0\f$ , the second corresponds to \f$\beta_1\f$ , and so on. This is equivalent +to \f$f(y) = \beta_0 + \beta_1x_1 + \beta_2x_2 + \beta_3x_3 + \beta_4x_4\f$ or \f$f(y)=14+2x_1+1x_2+3x_3+4x_4\f$. + +@subsection cli_ex3_lrtut Compute model and predict at the same time + +@code +$ mlpack_linear_regression --training_file dataset.csv --test_file predict.csv --output_predictions_file predictions.csv \ > -v +[WARN ] '--output_predictions_file (-o)' ignored because '--test_file (-T)' is specified! [INFO ] Loading 'dataset.csv' as CSV data. Size is 2 x 5. [INFO ] Loading 'predict.csv' as raw ASCII formatted data. Size is 1 x 3. [INFO ] Saving CSV data to 'predictions.csv'. -[INFO ] +[INFO ] [INFO ] Execution parameters: -[INFO ] help: false -[INFO ] info: "" -[INFO ] input_model_file: "" +[INFO ] help: 0 +[INFO ] info: +[INFO ] input_model_file: [INFO ] lambda: 0 -[INFO ] output_model_file: "" -[INFO ] output_predictions: predictions.csv -[INFO ] test_file: predict.csv -[INFO ] training_file: dataset.csv -[INFO ] training_responses: "" -[INFO ] verbose: true -[INFO ] version: false -[INFO ] +[INFO ] output_model_file: +[INFO ] output_predictions_file: 'predictions.csv' (1x3 matrix) +[INFO ] test_file: 'predict.csv' (0x0 matrix) +[INFO ] training_file: 'dataset.csv' (0x0 matrix) +[INFO ] training_responses_file: '' +[INFO ] verbose: 1 +[INFO ] version: 0 [INFO ] Program timers: -[INFO ] load_regressors: 0.000371s -[INFO ] load_test_points: 0.000229s -[INFO ] loading_data: 0.000491s -[INFO ] prediction: 0.000075s -[INFO ] regression: 0.000449s -[INFO ] saving_data: 0.000186s -[INFO ] total_time: 0.002731s +[INFO ] load_regressors: 0.000069s +[INFO ] load_test_points: 0.000031s +[INFO ] loading_data: 0.000079s +[INFO ] prediction: 0.000001s +[INFO ] regression: 0.000054s +[INFO ] saving_data: 0.000055s +[INFO ] total_time: 0.000203s + $ cat dataset.csv 0,0 @@ -195,51 +263,52 @@ about the \c predict.csv dataset is that it has the same dimensionality as the dataset used to create the model, one. If the model generating dataset has \f$d\f$ dimensions, so must the dataset we want to predict for. -@subsection cli_ex3_lrtut Prediction using a precomputed model +@subsection cli_ex4_lrtut Prediction using a precomputed model @code -$ mlpack_linear_regression --input_model_file lr.xml --test_file predict.csv -v +$ mlpack_linear_regression --input_model_file lr.xml --test_file predict.csv --output_predictions_file predictions.csv -v +[WARN ] '--output_predictions_file (-o)' ignored because '--test_file (-T)' is specified! [INFO ] Loading 'predict.csv' as raw ASCII formatted data. Size is 1 x 3. [INFO ] Saving CSV data to 'predictions.csv'. -[INFO ] +[INFO ] [INFO ] Execution parameters: -[INFO ] help: false -[INFO ] info: "" +[INFO ] help: 0 +[INFO ] info: [INFO ] input_model_file: lr.xml [INFO ] lambda: 0 -[INFO ] output_model_file: "" -[INFO ] output_predictions: predictions.csv -[INFO ] test_file: predict.csv -[INFO ] training_file: "" -[INFO ] training_responses: "" -[INFO ] verbose: true -[INFO ] version: false -[INFO ] +[INFO ] output_model_file: +[INFO ] output_predictions_file: 'predictions.csv' (1x3 matrix) +[INFO ] test_file: 'predict.csv' (0x0 matrix) +[INFO ] training_file: '' +[INFO ] training_responses_file: '' +[INFO ] verbose: 1 +[INFO ] version: 0 [INFO ] Program timers: -[INFO ] load_model: 0.000264s -[INFO ] load_test_points: 0.000186s -[INFO ] loading_data: 0.000157s -[INFO ] prediction: 0.000098s -[INFO ] saving_data: 0.000157s -[INFO ] total_time: 0.001688s +[INFO ] load_model: 0.000051s +[INFO ] load_test_points: 0.000052s +[INFO ] loading_data: 0.000044s +[INFO ] prediction: 0.000010s +[INFO ] saving_data: 0.000079s +[INFO ] total_time: 0.000160s + $ cat lr.xml - - - - - - 2 - 1 - 2 - 1 - -3.97205464519563669e-16 - 1.00000000000000022e+00 - - 0.00000000000000000e+00 - 1 - - + + + + 0 + + 2 + 1 + 1 + 0 + 1 + + 0 + true + + + $ cat predict.csv 2 @@ -252,7 +321,7 @@ $ cat predictions.csv 4.0000000000e+00 @endcode -@subsection cli_ex4_lrtut Using ridge regression +@subsection cli_ex5_lrtut Using ridge regression Sometimes, the input matrix of predictors has a covariance matrix that is not invertible, or the system is overdetermined. In this case, ridge regression is From bea72a12aaff9724dfda08a8e28817f3b96c1e42 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Wed, 31 Mar 2021 09:15:40 +0530 Subject: [PATCH 160/729] Fix LazyData Note in R-bindings. --- src/mlpack/bindings/R/mlpack/DESCRIPTION.in | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/bindings/R/mlpack/DESCRIPTION.in b/src/mlpack/bindings/R/mlpack/DESCRIPTION.in index dc583f0dd9..1c64a50a72 100644 --- a/src/mlpack/bindings/R/mlpack/DESCRIPTION.in +++ b/src/mlpack/bindings/R/mlpack/DESCRIPTION.in @@ -20,6 +20,5 @@ Suggests: testthat (>= 2.1.0) URL: https://www.mlpack.org/doc/mlpack-@PACKAGE_VERSION@/r_documentation.html, https://github.com/mlpack/mlpack BugReports: https://github.com/mlpack/mlpack/issues -LazyData: true RoxygenNote: 7.1.0 Encoding: UTF-8 From 91db8fc3d960069043ae54c7070e8dcf8ab655b5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 1 Apr 2021 09:35:47 +0530 Subject: [PATCH 161/729] Fixed ElemType --- src/mlpack/methods/random_forest/random_forest_impl.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 5402c16abf..e0b1ef9a6a 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -28,8 +28,7 @@ RandomForest< FitnessFunction, DimensionSelectionType, NumericSplitType, - CategoricalSplitType, - ElemType + CategoricalSplitType >::RandomForest(): avgGain(0.0) { @@ -40,8 +39,7 @@ template< typename FitnessFunction, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType, - typename ElemType + template class CategoricalSplitType > template RandomForest< From 65d333377aff8a8f1c9bd02048734e5452db6a92 Mon Sep 17 00:00:00 2001 From: Roshan Swain Date: Fri, 2 Apr 2021 12:51:49 +0530 Subject: [PATCH 162/729] refactor tests by changing with approx_value --- mlpack | 1 + src/mlpack/tests/ann_dist_test.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) create mode 160000 mlpack diff --git a/mlpack b/mlpack new file mode 160000 index 0000000000..240463c1da --- /dev/null +++ b/mlpack @@ -0,0 +1 @@ +Subproject commit 240463c1da7fdddc5ef7895dce15bd84d0f6f7fc diff --git a/src/mlpack/tests/ann_dist_test.cpp b/src/mlpack/tests/ann_dist_test.cpp index ea1d8605a1..8f2e69ebf7 100644 --- a/src/mlpack/tests/ann_dist_test.cpp +++ b/src/mlpack/tests/ann_dist_test.cpp @@ -76,7 +76,8 @@ TEST_CASE("JacobianBernoulliDistributionTest", "[ANNDistTest]") } module.LogProbBackward(target, jacobianB); - REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 1e-5); + REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 1e-5,1e-5)); + } } @@ -121,7 +122,7 @@ TEST_CASE("JacobianBernoulliDistributionLogisticTest", "[ANNDistTest]") } module.LogProbBackward(target, jacobianB); - REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 3e-5); + REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 5e-3,5e-3)); } } @@ -222,7 +223,7 @@ TEST_CASE("JacobianNormalDistributionMeanTest", "[ANNDistTest]") jacobianB.col(k) = deltaMu % deriv; } - REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 5e-3); + REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 5e-3,5e-3)); } } @@ -288,6 +289,6 @@ TEST_CASE("JacobianNormalDistributionStandardDeviationTest", "[ANNDistTest]") jacobianB.col(k) = deltaSigma % deriv; } - REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 5e-3); + REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 5e-3,5e-3)); } } From 52e123e56792638c957d0229b001ae14a9e94a75 Mon Sep 17 00:00:00 2001 From: Yashwant Date: Thu, 1 Apr 2021 10:38:19 +0530 Subject: [PATCH 163/729] Fix Go-bindings flow control. --- CMake/go/AppendModel.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMake/go/AppendModel.cmake b/CMake/go/AppendModel.cmake index eeb28f7ada..ec85510239 100644 --- a/CMake/go/AppendModel.cmake +++ b/CMake/go/AppendModel.cmake @@ -44,8 +44,8 @@ function(append_model SERIALIZATION_FILE PROGRAM_MAIN_FILE) else () string(APPEND GOMODEL_SAFE_TYPE ${MODEL_CHAR}) endif() - endif() - endforeach() + endforeach() + endif() # See if the model type already exists. file(READ "${SERIALIZATION_FILE}" SERIALIZATION_FILE_CONTENTS) @@ -77,7 +77,7 @@ function(append_model SERIALIZATION_FILE PROGRAM_MAIN_FILE) " C.mlpackSet${MODEL_SAFE_TYPE}" "Ptr(C.CString(identifier), (unsafe.Pointer)(ptr.mem))\n" "}\n\n") - endif () + endif() endforeach () endif() endfunction() From 53c663ac2453f3c2552b5646a1fb7f58ba933283 Mon Sep 17 00:00:00 2001 From: Roshan Swain Date: Sat, 3 Apr 2021 10:36:02 +0530 Subject: [PATCH 164/729] fixed few butgs in ann_dist and ann_layer test --- src/mlpack/tests/ann_dist_test.cpp | 8 ++++---- src/mlpack/tests/ann_layer_test.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/mlpack/tests/ann_dist_test.cpp b/src/mlpack/tests/ann_dist_test.cpp index 8f2e69ebf7..a3930a0b4d 100644 --- a/src/mlpack/tests/ann_dist_test.cpp +++ b/src/mlpack/tests/ann_dist_test.cpp @@ -76,7 +76,7 @@ TEST_CASE("JacobianBernoulliDistributionTest", "[ANNDistTest]") } module.LogProbBackward(target, jacobianB); - REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 1e-5,1e-5)); + REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 1e-5); } } @@ -122,7 +122,7 @@ TEST_CASE("JacobianBernoulliDistributionLogisticTest", "[ANNDistTest]") } module.LogProbBackward(target, jacobianB); - REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 5e-3,5e-3)); + REQUIRE(arma::approx_equal(jacobianA, jacobianB, "both", 5e-3, 5e-3)); } } @@ -223,7 +223,7 @@ TEST_CASE("JacobianNormalDistributionMeanTest", "[ANNDistTest]") jacobianB.col(k) = deltaMu % deriv; } - REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 5e-3,5e-3)); + REQUIRE(arma::approx_equal(jacobianA, jacobianB, "both", 5e-3, 5e-3)); } } @@ -289,6 +289,6 @@ TEST_CASE("JacobianNormalDistributionStandardDeviationTest", "[ANNDistTest]") jacobianB.col(k) = deltaSigma % deriv; } - REQUIRE(arma::approx_equal(jacobianA, jacobianB,"both", 5e-3,5e-3)); + REQUIRE(arma::approx_equal(jacobianA, jacobianB, "both", 5e-3, 5e-3)); } } diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 54105b1f9e..e7ca2ce190 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -256,7 +256,8 @@ TEST_CASE("SimpleDropoutLayerTest", "[ANNLayerTest]") // Test the Forward function. arma::mat output; module.Forward(input, output); - REQUIRE(arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))) <= 0.05); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))) <= 0.05); + // REQUIRE(arma::as_scalar(arma::approx_equal(mean(output), (1-p), "both", 0.05, 0.05 ))); // Test the Backward function. arma::mat delta; @@ -349,7 +350,8 @@ TEST_CASE("SimpleAlphaDropoutLayerTest", "[ANNLayerTest]") // Test the Backward function when training phase. arma::mat delta; module.Backward(input, input, delta); - REQUIRE(arma::as_scalar(arma::abs(arma::mean(delta) - 0)) <= 0.05); + REQUIRE(arma::as_scalar(arma::max(arma::abs(arma::mean(delta) - 0) <= 0.05))); + // Test the Forward function when testing phase. module.Deterministic() = true; From 1f90c54237bf6b63e2f35421dc7f7cd6e403e298 Mon Sep 17 00:00:00 2001 From: Roshan Swain Date: Sat, 3 Apr 2021 10:40:19 +0530 Subject: [PATCH 165/729] removed unnecessary comment --- src/mlpack/tests/ann_layer_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index e7ca2ce190..ac9e6b9891 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -257,7 +257,6 @@ TEST_CASE("SimpleDropoutLayerTest", "[ANNLayerTest]") arma::mat output; module.Forward(input, output); REQUIRE(arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))) <= 0.05); - // REQUIRE(arma::as_scalar(arma::approx_equal(mean(output), (1-p), "both", 0.05, 0.05 ))); // Test the Backward function. arma::mat delta; From cb9ba56a75a925a6a6568bb98339677db8241a7b Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Tue, 6 Apr 2021 06:48:40 +0530 Subject: [PATCH 166/729] Fixed mean poolinglayer for correct ceil_mode (#2887) Redesigned poolinglayer for correct ceil_mode. --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 51 +++++++++++------ .../methods/ann/layer/mean_pooling_impl.hpp | 5 -- src/mlpack/tests/ann_layer_test.cpp | 57 ++++++++++++++++++- 3 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 4840592dc4..80daaa9951 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -166,9 +166,17 @@ class MeanPooling for (size_t i = 0, rowidx = 0; i < output.n_rows; ++i, rowidx += strideWidth) { + size_t rowEnd = rowidx + kernelWidth - 1; + size_t colEnd = colidx + kernelHeight - 1; + + if (rowEnd > input.n_rows - 1) + rowEnd = input.n_rows - 1; + if (colEnd > input.n_cols - 1) + colEnd = input.n_cols - 1; + arma::mat subInput = input( - arma::span(rowidx, rowidx + kernelWidth - 1 - offset), - arma::span(colidx, colidx + kernelHeight - 1 - offset)); + arma::span(rowidx, rowEnd), + arma::span(colidx, colEnd)); output(i, j) = arma::mean(arma::mean(subInput)); } @@ -186,22 +194,36 @@ class MeanPooling const arma::Mat& error, arma::Mat& output) { - const size_t rStep = input.n_rows / error.n_rows - offset; - const size_t cStep = input.n_cols / error.n_cols - offset; arma::Mat unpooledError; - for (size_t j = 0; j < input.n_cols - cStep; j += cStep) + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) { - for (size_t i = 0; i < input.n_rows - rStep; i += rStep) - { - const arma::Mat& inputArea = input(arma::span(i, i + rStep - 1), - arma::span(j, j + cStep - 1)); + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) + { + size_t rowEnd = i + kernelWidth - 1; + size_t colEnd = j + kernelHeight - 1; - unpooledError = arma::Mat(inputArea.n_rows, inputArea.n_cols); - unpooledError.fill(error(i / rStep, j / cStep) / inputArea.n_elem); + if (rowEnd > input.n_rows - 1) + { + if (floor) + continue; + rowEnd = input.n_rows - 1; + } - output(arma::span(i, i + rStep - 1 - offset), - arma::span(j, j + cStep - 1 - offset)) += unpooledError; + if (colEnd > input.n_cols - 1) + { + if (floor) + continue; + colEnd = input.n_cols - 1; + } + + arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); + + unpooledError = arma::Mat(InputArea.n_rows, InputArea.n_cols); + unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem); + + output(arma::span(i, i + InputArea.n_rows - 1), + arma::span(j, j + InputArea.n_cols - 1)) += unpooledError; } } } @@ -245,9 +267,6 @@ class MeanPooling //! If true use maximum a posteriori during the forward pass. bool deterministic; - //! Locally-stored stored rounding offset. - size_t offset; - //! Locally-stored number of input units. size_t batchSize; diff --git a/src/mlpack/methods/ann/layer/mean_pooling_impl.hpp b/src/mlpack/methods/ann/layer/mean_pooling_impl.hpp index ce4e6c7895..ad4a8e6943 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling_impl.hpp @@ -45,7 +45,6 @@ MeanPooling::MeanPooling( outputHeight(0), reset(false), deterministic(false), - offset(0), batchSize(0) { // Nothing to do here. @@ -67,8 +66,6 @@ void MeanPooling::Forward( (double) kernelWidth) / (double) strideWidth + 1); outputHeight = std::floor((inputHeight - (double) kernelHeight) / (double) strideHeight + 1); - - offset = 0; } else { @@ -76,8 +73,6 @@ void MeanPooling::Forward( (double) kernelWidth) / (double) strideWidth + 1); outputHeight = std::ceil((inputHeight - (double) kernelHeight) / (double) strideHeight + 1); - - offset = 1; } outputTemp = arma::zeros >(outputWidth, outputHeight, diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 54105b1f9e..13576eb11a 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -3883,6 +3883,57 @@ TEST_CASE("LpMaxPoolingTestCase", "[ANNLayerTest]") REQUIRE(output.n_elem == 4); } +/** + * Simple test for Mean Pooling layer. + */ +TEST_CASE("MeanPoolingTestCase", "[ANNLayerTest]") +{ + // For rectangular input to pooling layers. + arma::mat input = arma::mat(28, 1); + input.zeros(); + input(0) = input(16) = 1; + input(1) = input(17) = 2; + input(2) = input(18) = 3; + input(3) = input(19) = 4; + input(4) = input(20) = 5; + input(5) = input(23) = 6; + input(6) = input(24) = 7; + input(14) = input(25) = 8; + input(15) = input(26) = 9; + + MeanPooling<> module1(2, 2, 2, 2, false); + MeanPooling<> module2(2, 2, 2, 2, true); + module1.InputWidth() = 7; + module1.InputHeight() = 4; + module2.InputWidth() = 7; + module2.InputHeight() = 4; + + // Calculated using torch.nn.MeanPool2d(). + arma::mat result1, result2; + result1 << 0.7500 << 4.2500 << arma::endr + << 1.7500 << 4.0000 << arma::endr + << 2.7500 << 6.0000 << arma::endr + << 3.5000 << 2.5000 << arma::endr; + + result2 << 0.7500 << 4.2500 << arma::endr + << 1.7500 << 4.0000 << arma::endr + << 2.7500 << 6.0000 << arma::endr; + + arma::mat output1, output2; + module1.Forward(input, output1); + module2.Forward(input, output2); + output1.reshape(4, 2); + output2.reshape(3, 2); + CheckMatrices(output1, result1, 1e-1); + CheckMatrices(output2, result2, 1e-1); + + arma::mat delta1, delta2; + module1.Backward(input, output1, delta1); + REQUIRE(arma::accu(delta1) == 25.5); + module2.Backward(input, output2, delta2); + REQUIRE(arma::accu(delta2) == 19.5); +} + /** * Simple test for Max Pooling layer. */ @@ -4155,7 +4206,7 @@ TEST_CASE("AdaptiveMeanPoolingTestCase", "[ANNLayerTest]") REQUIRE(output.n_cols == 1); // Test the Backward Function. module1.Backward(input, output, delta); - REQUIRE(arma::accu(delta) == 7.0); + REQUIRE(arma::accu(delta) == 19.75); // For Square input. input = arma::mat(9, 1); @@ -4177,7 +4228,7 @@ TEST_CASE("AdaptiveMeanPoolingTestCase", "[ANNLayerTest]") REQUIRE(output.n_cols == 1); // Test the Backward Function. module2.Backward(input, output, delta); - REQUIRE(arma::accu(delta) == 0.0); + REQUIRE(arma::accu(delta) == 4.50); // For Square input. input = arma::mat(16, 1); @@ -4219,7 +4270,7 @@ TEST_CASE("AdaptiveMeanPoolingTestCase", "[ANNLayerTest]") REQUIRE(output.n_cols == 1); // Test the Backward Function. module4.Backward(input, output, delta); - REQUIRE(arma::accu(delta) == 1.5); + REQUIRE(arma::accu(delta) == 2.25); } TEST_CASE("TransposedConvolutionalLayerOptionalParameterTest", "[ANNLayerTest]") From 5f2a184faedf33b95753e14580c0db0ae2c5af18 Mon Sep 17 00:00:00 2001 From: Roshan Swain Date: Wed, 7 Apr 2021 13:09:13 +0530 Subject: [PATCH 167/729] fixed styling --- src/mlpack/tests/ann_dist_test.cpp | 3 +-- src/mlpack/tests/ann_layer_test.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mlpack/tests/ann_dist_test.cpp b/src/mlpack/tests/ann_dist_test.cpp index a3930a0b4d..4232c0042d 100644 --- a/src/mlpack/tests/ann_dist_test.cpp +++ b/src/mlpack/tests/ann_dist_test.cpp @@ -77,7 +77,6 @@ TEST_CASE("JacobianBernoulliDistributionTest", "[ANNDistTest]") module.LogProbBackward(target, jacobianB); REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 1e-5); - } } @@ -122,7 +121,7 @@ TEST_CASE("JacobianBernoulliDistributionLogisticTest", "[ANNDistTest]") } module.LogProbBackward(target, jacobianB); - REQUIRE(arma::approx_equal(jacobianA, jacobianB, "both", 5e-3, 5e-3)); + REQUIRE(arma::approx_equal(jacobianA, jacobianB, "both", 3e-5, 3e-5)); } } diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index ac9e6b9891..beb1339f56 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -351,7 +351,6 @@ TEST_CASE("SimpleAlphaDropoutLayerTest", "[ANNLayerTest]") module.Backward(input, input, delta); REQUIRE(arma::as_scalar(arma::max(arma::abs(arma::mean(delta) - 0) <= 0.05))); - // Test the Forward function when testing phase. module.Deterministic() = true; module.Forward(input, output); From ee34576c07b9ed6fa09bf80f0e1c94064a6e06f6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 09:09:46 +0530 Subject: [PATCH 168/729] Apply suggestions from code review Co-authored-by: Ryan Curtin --- .../methods/random_forest/random_forest_impl.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index e0b1ef9a6a..32152d2c91 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -29,7 +29,7 @@ RandomForest< DimensionSelectionType, NumericSplitType, CategoricalSplitType ->::RandomForest(): +>::RandomForest() : avgGain(0.0) { // Nothing to do here. @@ -54,8 +54,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector): - avgGain(0.0) + DimensionSelectionType dimensionSelector) : + avgGain(0.0) { // Pass off work to the Train() method. data::DatasetInfo info; // Ignored. @@ -115,8 +115,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector): - avgGain(0.0) + DimensionSelectionType dimensionSelector) : + avgGain(0.0) { // Pass off work to the Train() method. data::DatasetInfo info; // Ignored by Train(). @@ -146,8 +146,8 @@ RandomForest< const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType dimensionSelector): - avgGain(0.0) + DimensionSelectionType dimensionSelector) : + avgGain(0.0) { // Pass off work to the Train() method. Train(dataset, datasetInfo, labels, numClasses, weights, From bf5fce877c3db4312eeb2a425df860107ee4fd7a Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 05:06:30 +0200 Subject: [PATCH 169/729] Remove unused vector. --- src/mlpack/bindings/go/print_doc_functions_impl.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/mlpack/bindings/go/print_doc_functions_impl.hpp b/src/mlpack/bindings/go/print_doc_functions_impl.hpp index 3f1dcd9a5e..1f250aafb5 100644 --- a/src/mlpack/bindings/go/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/go/print_doc_functions_impl.hpp @@ -432,13 +432,6 @@ inline std::string ProgramCall(const std::string& programName) std::ostringstream ossOptions; ossOptions << "param := mlpack." << goProgramName << "Options()\n"; oss << util::HyphenateString(ossOptions.str(), 4); - std::vector outputOptions; - for (auto it = parameters.begin(); it != parameters.end(); ++it) - { - util::ParamData& d = it->second; - if (!d.input) - outputOptions.push_back(it->first); - } std::string result = oss.str(); oss.str(""); std::ostringstream ossInputs; From b11f9995e28f3b58c891a60999e2d3d8b379e3d1 Mon Sep 17 00:00:00 2001 From: Roshan Swain Date: Sat, 10 Apr 2021 12:59:15 +0530 Subject: [PATCH 170/729] removed the submodule --- mlpack | 1 - 1 file changed, 1 deletion(-) delete mode 160000 mlpack diff --git a/mlpack b/mlpack deleted file mode 160000 index 240463c1da..0000000000 --- a/mlpack +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 240463c1da7fdddc5ef7895dce15bd84d0f6f7fc From 748b33b99725a2339589110d96211947759fbe13 Mon Sep 17 00:00:00 2001 From: FawwazMayda <33770567+FawwazMayda@users.noreply.github.com> Date: Sat, 10 Apr 2021 18:16:48 +0800 Subject: [PATCH 171/729] add missing std:: --- .../reinforcement_learning/reinforcement_learning.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorials/reinforcement_learning/reinforcement_learning.txt b/doc/tutorials/reinforcement_learning/reinforcement_learning.txt index 34edf931da..e53edd0c74 100644 --- a/doc/tutorials/reinforcement_learning/reinforcement_learning.txt +++ b/doc/tutorials/reinforcement_learning/reinforcement_learning.txt @@ -326,7 +326,7 @@ auto measure = [&returns, &position, &episode](double episodeReturn) std::cout << "Episode No.: " << episode << "; Episode Return: " << episodeReturn - << "; Average Return: " << arma::mean(returns) << endl; + << "; Average Return: " << arma::mean(returns) << std::endl; }; @endcode @@ -392,7 +392,7 @@ int main() std::cout << "Episode No.: " << episode << "; Episode Return: " << episodeReturn - << "; Average Return: " << arma::mean(returns) << endl; + << "; Average Return: " << arma::mean(returns) << std::endl; }; for (int i = 0; i < 100; i++) From f7c87020aae2f7ae91adaaa2b9ce56def661fdcb Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 19:14:09 +0200 Subject: [PATCH 172/729] Remove unreachable code. --- src/mlpack/methods/det/dtree_impl.hpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/mlpack/methods/det/dtree_impl.hpp b/src/mlpack/methods/det/dtree_impl.hpp index 7df858e4d2..dfdb994049 100644 --- a/src/mlpack/methods/det/dtree_impl.hpp +++ b/src/mlpack/methods/det/dtree_impl.hpp @@ -874,19 +874,13 @@ double DTree::ComputeValue(const VecType& query) const } if (subtreeLeaves == 1) // If we are a leaf... - { return std::exp(std::log(ratio) - logVolume); - } - else - { - // Return either of the two children - left or right, depending on the - // splitValue - return (query[splitDim] <= splitValue) ? + + // Return either of the two children - left or right, depending on the + // splitValue. + return (query[splitDim] <= splitValue) ? left->ComputeValue(query) : right->ComputeValue(query); - } - - return 0.0; } // Index the buckets for possible usage later. From 4437b6b4d14e2c5d2fc8f04c566f12462ac0a4bb Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 19:15:47 +0200 Subject: [PATCH 173/729] Remove unreachable cf code. --- src/mlpack/methods/cf/cf_model.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/mlpack/methods/cf/cf_model.cpp b/src/mlpack/methods/cf/cf_model.cpp index 226edcf1be..424726953e 100644 --- a/src/mlpack/methods/cf/cf_model.cpp +++ b/src/mlpack/methods/cf/cf_model.cpp @@ -89,31 +89,26 @@ CFWrapperBase* TrainHelper(const DecompositionPolicy& decomposition, return new CFWrapper(data, decomposition, numUsersForSimilarity, rank, maxIterations, minResidue, mit); - break; case CFModel::ITEM_MEAN_NORMALIZATION: return new CFWrapper(data, decomposition, numUsersForSimilarity, rank, maxIterations, minResidue, mit); - break; case CFModel::USER_MEAN_NORMALIZATION: return new CFWrapper(data, decomposition, numUsersForSimilarity, rank, maxIterations, minResidue, mit); - break; case CFModel::OVERALL_MEAN_NORMALIZATION: return new CFWrapper(data, decomposition, numUsersForSimilarity, rank, maxIterations, minResidue, mit); - break; case CFModel::Z_SCORE_NORMALIZATION: return new CFWrapper(data, decomposition, numUsersForSimilarity, rank, maxIterations, minResidue, mit); - break; } // This shouldn't ever happen. From 14427fd2f42af2ff5498dc9e17579e32c0ddc1bd Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 19:17:49 +0200 Subject: [PATCH 174/729] Remove unreachable epanechnikov kernel code. --- src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp index 15c65ebb7b..eee34daaee 100644 --- a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp +++ b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp @@ -58,7 +58,6 @@ double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a, (3.0 * bandwidth) + 2.0 * distance * distance * distance / (3.0 * bandwidth * bandwidth) - std::pow(distance, 5.0) / (30.0 * std::pow(bandwidth, 4.0))); - break; case 2: return 1.0 / volumeSquared * ((2.0 / 3.0 * bandwidth * bandwidth - distance * distance) * @@ -67,12 +66,10 @@ double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a, (distance / 6.0 + 2.0 / 9.0 * distance * std::pow(distance / bandwidth, 2.0) - distance / 72.0 * std::pow(distance / bandwidth, 4.0))); - break; default: Log::Fatal << "EpanechnikovKernel::ConvolutionIntegral(): dimension " << a.n_rows << " not supported."; return -1.0; // This line will not execute. - break; } } From 5c6723a5c6fc437aa7b4cb5057803134c97f4b77 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 19:19:44 +0200 Subject: [PATCH 175/729] Remove unreachable spherical kernel code. --- src/mlpack/core/kernels/spherical_kernel.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mlpack/core/kernels/spherical_kernel.hpp b/src/mlpack/core/kernels/spherical_kernel.hpp index 13fc549f49..48fd9365a9 100644 --- a/src/mlpack/core/kernels/spherical_kernel.hpp +++ b/src/mlpack/core/kernels/spherical_kernel.hpp @@ -56,7 +56,7 @@ class SphericalKernel * @tparam VecTypeB Type of second vector. * @param a First vector. * @param b Second vector. - * @return the convolution integral value. + * @return The convolution integral value. */ template double ConvolutionIntegral(const VecTypeA& a, const VecTypeB& b) const @@ -72,17 +72,14 @@ class SphericalKernel { case 1: return 1.0 / volumeSquared * (2.0 * bandwidth - distance); - break; case 2: return 1.0 / volumeSquared * (2.0 * bandwidth * bandwidth * acos(distance/(2.0 * bandwidth)) - distance / 4.0 * sqrt(4.0*bandwidth*bandwidth-distance*distance)); - break; default: Log::Fatal << "The spherical kernel does not support convolution\ integrals above dimension two, yet..." << std::endl; return -1.0; - break; } } double Normalizer(size_t dimension) const From 01e522906681de578ade4bba84c3cd9a822411b2 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 19:27:59 +0200 Subject: [PATCH 176/729] Handle potential division by zero issue and minor style fixes. --- .../simple_tolerance_termination.hpp | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/mlpack/methods/amf/termination_policies/simple_tolerance_termination.hpp b/src/mlpack/methods/amf/termination_policies/simple_tolerance_termination.hpp index 81630e14bf..191278bf7f 100644 --- a/src/mlpack/methods/amf/termination_policies/simple_tolerance_termination.hpp +++ b/src/mlpack/methods/amf/termination_policies/simple_tolerance_termination.hpp @@ -79,7 +79,7 @@ class SimpleToleranceTermination WH = W * H; - // compute residue + // Compute residue. residueOld = residue; size_t n = V->n_rows; size_t m = V->n_cols; @@ -99,48 +99,51 @@ class SimpleToleranceTermination } } } - residue = sum / count; + + residue = sum; + if (count > 0) + residue /= count; residue = sqrt(residue); - // increment iteration count + // Increment iteration count. iteration++; Log::Info << "Iteration " << iteration << "; residue " << ((residueOld - residue) / residueOld) << ".\n"; - // if residue tolerance is not satisfied + // If residue tolerance is not satisfied. if ((residueOld - residue) / residueOld < tolerance && iteration > 4) { - // check if this is a first of successive drops + // Check if this is a first of successive drops. if (reverseStepCount == 0 && isCopy == false) { - // store a copy of W and H matrix + // Store a copy of W and H matrix. isCopy = true; this->W = W; this->H = H; - // store residue values + // Store residue values. c_index = residue; c_indexOld = residueOld; } - // increase successive drop count + // Increase successive drop count. reverseStepCount++; } - // if tolerance is satisfied + // If tolerance is satisfied. else { - // initialize successive drop count + // Initialize successive drop count. reverseStepCount = 0; - // if residue is droped below minimum scrap stored values + // If residue is droped below minimum scrap stored values. if (residue <= c_indexOld && isCopy == true) { isCopy = false; } } - // check if termination criterion is met + // Check if termination criterion is met. if (reverseStepCount == reverseStepTolerance || iteration > maxIterations) { - // if stored values are present replace them with current value as they - // represent the minimum residue point + // If stored values are present replace them with current value as they + // represent the minimum residue point. if (isCopy) { W = this->W; @@ -149,49 +152,50 @@ class SimpleToleranceTermination } return true; } - else return false; + + return false; } - //! Get current value of residue + //! Get current value of residue. const double& Index() const { return residue; } - //! Get current iteration count + //! Get current iteration count. const size_t& Iteration() const { return iteration; } - //! Access upper limit of iteration count + //! Access upper limit of iteration count. const size_t& MaxIterations() const { return maxIterations; } size_t& MaxIterations() { return maxIterations; } - //! Access tolerance value + //! Access tolerance value. const double& Tolerance() const { return tolerance; } double& Tolerance() { return tolerance; } private: - //! tolerance + //! Locally-stored tolerance. double tolerance; - //! iteration threshold + //! Locally-stored iteration threshold. size_t maxIterations; - //! pointer to matrix being factorized + //! Pointer to matrix being factorized. const MatType* V; - //! current iteration count + //! Current iteration count. size_t iteration; - //! residue values + //! Locally-stored residue values. double residueOld; double residue; - //! tolerance on successive residue drops + //! Tolerance on successive residue drops. size_t reverseStepTolerance; - //! successive residue drops + //! Successive residue drops. size_t reverseStepCount; - //! indicates whether a copy of information is available which corresponds to - //! minimum residue point + //! Indicates whether a copy of information is available which corresponds to + //! minimum residue point. bool isCopy; - //! variables to store information of minimum residue poi + //! Variables to store information of minimum residue poi. arma::mat W; arma::mat H; double c_indexOld; From 1cda50f3275d51182098460d06b222b1bb2f874d Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 19:30:42 +0200 Subject: [PATCH 177/729] Handle potential division by zero issue. --- src/mlpack/core/metrics/bleu_impl.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mlpack/core/metrics/bleu_impl.hpp b/src/mlpack/core/metrics/bleu_impl.hpp index 38e9b29437..27119bef1e 100644 --- a/src/mlpack/core/metrics/bleu_impl.hpp +++ b/src/mlpack/core/metrics/bleu_impl.hpp @@ -178,7 +178,10 @@ ElemType BLEU::Evaluate( else geometricMean = 0.0; - ratio = ElemType(translationLength) / referenceLength; + ratio = ElemType(translationLength); + if (referenceLength > 0) + ration /= referenceLength; + brevityPenalty = (ratio > 1.0) ? 1.0 : std::exp(1.0 - 1.0 / ratio); bleuScore = geometricMean * brevityPenalty; From cf9bd906dcfcff9115812e3d3e0b0be554cb38f9 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 20:28:36 +0200 Subject: [PATCH 178/729] Fix parameter name. --- src/mlpack/core/metrics/bleu_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/metrics/bleu_impl.hpp b/src/mlpack/core/metrics/bleu_impl.hpp index 27119bef1e..f81d62c69a 100644 --- a/src/mlpack/core/metrics/bleu_impl.hpp +++ b/src/mlpack/core/metrics/bleu_impl.hpp @@ -180,7 +180,7 @@ ElemType BLEU::Evaluate( ratio = ElemType(translationLength); if (referenceLength > 0) - ration /= referenceLength; + ratio /= referenceLength; brevityPenalty = (ratio > 1.0) ? 1.0 : std::exp(1.0 - 1.0 / ratio); bleuScore = geometricMean * brevityPenalty; From ff5a86d08787ca15d477ffb1aca9bc3f0f9a425b Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sat, 10 Apr 2021 20:43:57 +0200 Subject: [PATCH 179/729] Rethrow the original exception object using an empty throw. --- src/mlpack/methods/fastmks/fastmks_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/fastmks/fastmks_main.cpp b/src/mlpack/methods/fastmks/fastmks_main.cpp index 3b784f6d04..1638f64922 100644 --- a/src/mlpack/methods/fastmks/fastmks_main.cpp +++ b/src/mlpack/methods/fastmks/fastmks_main.cpp @@ -262,7 +262,7 @@ static void mlpackMain() // Delete the memory, if needed. if (IO::HasParam("reference")) delete model; - throw e; + throw; } } From e52217ee8bafb1e00cfc33262ad698b2d69b2a71 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Sun, 11 Apr 2021 18:04:31 +0200 Subject: [PATCH 180/729] Use Azure build as badge source. --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 84eb8260b4..21b9e09e7e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="

- Jenkins + Azure DevOps builds (job) License NumFOCUS

@@ -141,10 +141,10 @@ If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled. ### 4. Building mlpack from source -This document discusses how to build mlpack from source. These build directions +This document discusses how to build mlpack from source. These build directions will work for any Linux-like shell environment (for example Ubuntu, macOS, -FreeBSD etc). However, mlpack is in the repositories of many Linux distributions -and so it may be easier to use the package manager for your system. For example, +FreeBSD etc). However, mlpack is in the repositories of many Linux distributions +and so it may be easier to use the package manager for your system. For example, on Ubuntu, you can install the mlpack library and command-line executables (e.g. mlpack_pca, mlpack_kmeans etc.) with the following command: @@ -182,7 +182,7 @@ sufficient. The next step is to run CMake to configure the project. Running CMake is the equivalent to running `./configure` with autotools. If you run CMake with no -options, it will configure the project to build with no debugging symbols and +options, it will configure the project to build with no debugging symbols and no profiling information: $ cmake ../ @@ -238,7 +238,7 @@ This will build all library components as well as 'mlpack_test'. $ make -If you do not want to build everything in the library, individual components +If you do not want to build everything in the library, individual components of the build can be specified: $ make mlpack_pca mlpack_knn mlpack_kfn @@ -251,7 +251,7 @@ and submit an issue. The mlpack developers will quickly help you figure it out: Alternately, mlpack help can be found in IRC at `#mlpack` on chat.freenode.net. If you wish to install mlpack to `/usr/local/include/mlpack/`, `/usr/local/lib/`, -and `/usr/local/bin/`, make sure you have root privileges (or write permissions +and `/usr/local/bin/`, make sure you have root privileges (or write permissions to those three directories), and simply type $ make install From 270dec8fb4eabdcb6bc2639d908d5948c991ce5a Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 12 Apr 2021 03:48:35 +0200 Subject: [PATCH 181/729] Catch2 will mark the test as failed if an exception is thrown. --- src/mlpack/tests/serialization.hpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/mlpack/tests/serialization.hpp b/src/mlpack/tests/serialization.hpp index b88ff5e957..93b293b451 100644 --- a/src/mlpack/tests/serialization.hpp +++ b/src/mlpack/tests/serialization.hpp @@ -29,14 +29,12 @@ void TestArmadilloSerialization(arma::Cube& x) // Use type_info name to get unique file name for serialization test files. std::string fileName = FilterFileName(typeid(IArchiveType).name()); std::ofstream ofs(fileName, std::ios::binary); - bool success = true; { OArchiveType o(ofs); o(CEREAL_NVP(x)); } - REQUIRE(success == true); ofs.close(); // Now load it. @@ -52,8 +50,6 @@ void TestArmadilloSerialization(arma::Cube& x) remove(fileName.c_str()); - REQUIRE(success == true); - REQUIRE(x.n_rows == orig.n_rows); REQUIRE(x.n_cols == orig.n_cols); REQUIRE(x.n_elem_slice == orig.n_elem_slice); @@ -99,19 +95,16 @@ void TestArmadilloSerialization(MatType& x) // First save it. std::string fileName = FilterFileName(typeid(IArchiveType).name()); std::ofstream ofs(fileName, std::ios::binary); - bool success = true; { OArchiveType o(ofs); o(CEREAL_NVP(x)); } - REQUIRE(success == true); ofs.close(); // Now load it. MatType orig(x); - success = true; std::ifstream ifs(fileName, std::ios::binary); { @@ -122,8 +115,6 @@ void TestArmadilloSerialization(MatType& x) remove(fileName.c_str()); - REQUIRE(success == true); - REQUIRE(x.n_rows == orig.n_rows); REQUIRE(x.n_cols == orig.n_cols); REQUIRE(x.n_elem == orig.n_elem); @@ -156,7 +147,6 @@ void SerializeObject(T& t, T& newT) { std::string fileName = FilterFileName(typeid(T).name()); std::ofstream ofs(fileName, std::ios::binary); - bool success = true; { OArchiveType o(ofs); @@ -166,8 +156,6 @@ void SerializeObject(T& t, T& newT) } ofs.close(); - REQUIRE(success == true); - std::ifstream ifs(fileName, std::ios::binary); { @@ -178,8 +166,6 @@ void SerializeObject(T& t, T& newT) ifs.close(); remove(fileName.c_str()); - - REQUIRE(success == true); } // Test mlpack serialization with all three archive types. @@ -200,7 +186,6 @@ void SerializePointerObject(T* t, T*& newT) { std::string fileName = FilterFileName(typeid(T).name()); std::ofstream ofs(fileName, std::ios::binary); - bool success = true; { OArchiveType o(ofs); @@ -208,8 +193,6 @@ void SerializePointerObject(T* t, T*& newT) } ofs.close(); - REQUIRE(success == true); - std::ifstream ifs(fileName, std::ios::binary); { @@ -218,8 +201,6 @@ void SerializePointerObject(T* t, T*& newT) } ifs.close(); remove(fileName.c_str()); - - REQUIRE(success == true); } template From 044c2a4fbdd05afa38f0efa364b5c8fdf9fbe879 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 12 Apr 2021 03:48:53 +0200 Subject: [PATCH 182/729] Catch potential division by zero. --- src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp b/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp index c977f0fecb..cc1119a845 100644 --- a/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp @@ -435,7 +435,8 @@ bool XTreeSplit::SplitNonLeafNode(TreeType *tree, std::vector& relevels) bool useMinOverlapSplit = false; if (tiedOnOverlap) { - if (overlapBestAreaAxis / areaBestAreaAxis < MAX_OVERLAP) + if (MAX_OVERLAP > 0 && + overlapBestAreaAxis / areaBestAreaAxis < MAX_OVERLAP) { tree->numDescendants = 0; tree->bound.Clear(); From caae33a7970969f94b1ac573c1f17046e6fd5d97 Mon Sep 17 00:00:00 2001 From: Yashwants19 Date: Mon, 12 Apr 2021 04:56:35 +0000 Subject: [PATCH 183/729] Upgrade Catch to 2.13.5 --- src/mlpack/tests/catch.hpp | 388 +++++++++++++++++++++---------------- 1 file changed, 222 insertions(+), 166 deletions(-) diff --git a/src/mlpack/tests/catch.hpp b/src/mlpack/tests/catch.hpp index 0384171ae4..9c1c854fd5 100644 --- a/src/mlpack/tests/catch.hpp +++ b/src/mlpack/tests/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.13.4 - * Generated: 2020-12-29 14:48:00.116107 + * Catch v2.13.5 + * Generated: 2021-04-10 23:43:17.560525 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 4 +#define CATCH_VERSION_PATCH 5 #ifdef __clang__ # pragma clang system_header @@ -66,13 +66,16 @@ #if !defined(CATCH_CONFIG_IMPL_ONLY) // start catch_platform.h +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html #ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX @@ -132,9 +135,9 @@ namespace Catch { #endif -// We have to avoid both ICC and Clang, because they try to mask themselves -// as gcc, and we want only GCC in this block -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) @@ -7054,8 +7057,8 @@ namespace Catch { double b2 = bias - z1; double a1 = a(b1); double a2 = a(b2); - auto lo = std::max(cumn(a1), 0); - auto hi = std::min(cumn(a2), n - 1); + auto lo = (std::max)(cumn(a1), 0); + auto hi = (std::min)(cumn(a2), n - 1); return { point, resample[lo], resample[hi], confidence_level }; } @@ -7124,7 +7127,9 @@ namespace Catch { } template EnvironmentEstimate> estimate_clock_cost(FloatDuration resolution) { - auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration(clock_cost_estimation_time_limit)); + auto time_limit = (std::min)( + resolution * clock_cost_estimation_tick_limit, + FloatDuration(clock_cost_estimation_time_limit)); auto time_clock = [](int k) { return Detail::measure([k] { for (int i = 0; i < k; ++i) { @@ -7771,7 +7776,7 @@ namespace Catch { double sb = stddev.point; double mn = mean.point / n; double mg_min = mn / 2.; - double sg = std::min(mg_min / 4., sb / std::sqrt(n)); + double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); double sg2 = sg * sg; double sb2 = sb * sb; @@ -7790,7 +7795,7 @@ namespace Catch { return (nc / n) * (sb2 - nc * sg2); }; - return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2; + return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2; } bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector::iterator first, std::vector::iterator last) { @@ -7980,86 +7985,58 @@ namespace Catch { // start catch_fatal_condition.h -// start catch_windows_h_proxy.h - - -#if defined(CATCH_PLATFORM_WINDOWS) - -#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX -#endif -#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINED_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -#endif // defined(CATCH_PLATFORM_WINDOWS) - -// end catch_windows_h_proxy.h -#if defined( CATCH_CONFIG_WINDOWS_SEH ) +#include namespace Catch { - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); - FatalConditionHandler(); - static void reset(); - ~FatalConditionHandler(); - - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - -} // namespace Catch - -#elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) - -#include - -namespace Catch { - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions[]; - static stack_t oldSigStack; - static char altStackMem[]; - - static void handleSignal( int sig ); + // Wrapper for platform-specific fatal error (signals/SEH) handlers + // + // Tries to be cooperative with other handlers, and not step over + // other handlers. This means that unknown structured exceptions + // are passed on, previous signal handlers are called, and so on. + // + // Can only be instantiated once, and assumes that once a signal + // is caught, the binary will end up terminating. Thus, there + class FatalConditionHandler { + bool m_started = false; + // Install/disengage implementation for specific platform. + // Should be if-defed to work on current platform, can assume + // engage-disengage 1:1 pairing. + void engage_platform(); + void disengage_platform(); + public: + // Should also have platform-specific implementations as needed FatalConditionHandler(); ~FatalConditionHandler(); - static void reset(); + + void engage() { + assert(!m_started && "Handler cannot be installed twice."); + m_started = true; + engage_platform(); + } + + void disengage() { + assert(m_started && "Handler cannot be uninstalled without being installed first"); + m_started = false; + disengage_platform(); + } }; -} // namespace Catch - -#else - -namespace Catch { - struct FatalConditionHandler { - void reset(); + //! Simple RAII guard for (dis)engaging the FatalConditionHandler + class FatalConditionHandlerGuard { + FatalConditionHandler* m_handler; + public: + FatalConditionHandlerGuard(FatalConditionHandler* handler): + m_handler(handler) { + m_handler->engage(); + } + ~FatalConditionHandlerGuard() { + m_handler->disengage(); + } }; -} -#endif +} // end namespace Catch // end catch_fatal_condition.h #include @@ -8185,6 +8162,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; + FatalConditionHandler m_fatalConditionhandler; bool m_lastAssertionPassed = false; bool m_shouldReportUnexpected = true; bool m_includeSuccessfulResults; @@ -10057,6 +10035,36 @@ namespace Catch { } // end catch_errno_guard.h +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +#endif +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +#endif // defined(CATCH_PLATFORM_WINDOWS) + +// end catch_windows_h_proxy.h #include namespace Catch { @@ -10573,7 +10581,7 @@ namespace Catch { // Extracts the actual name part of an enum instance // In other words, it returns the Blue part of Bikeshed::Colour::Blue StringRef extractInstanceName(StringRef enumInstance) { - // Find last occurence of ":" + // Find last occurrence of ":" size_t name_start = enumInstance.size(); while (name_start > 0 && enumInstance[name_start - 1] != ':') { --name_start; @@ -10735,25 +10743,47 @@ namespace Catch { // end catch_exception_translator_registry.cpp // start catch_fatal_condition.cpp -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif +#include + +#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS ) + +namespace Catch { + + // If neither SEH nor signal handling is required, the handler impls + // do not have to do anything, and can be empty. + FatalConditionHandler::engage_platform() {} + FatalConditionHandler::disengage_platform() {} + FatalConditionHandler::FatalConditionHandler() = default; + FatalConditionHandler::~FatalConditionHandler() = default; + +} // end namespace Catch + +#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS + +#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS ) +#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time" +#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) namespace { - // Report the error condition + //! Signals fatal error message to the run context void reportFatal( char const * const message ) { Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); } -} -#endif // signals/SEH handling + //! Minimal size Catch2 needs for its own fatal error handling. + //! Picked anecdotally, so it might not be sufficient on all + //! platforms, and for all configurations. + constexpr std::size_t minStackSizeForErrors = 32 * 1024; +} // end unnamed namespace + +#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS #if defined( CATCH_CONFIG_WINDOWS_SEH ) namespace Catch { + struct SignalDefs { DWORD id; const char* name; }; // There is no 1-1 mapping between signals and windows exceptions. @@ -10766,7 +10796,7 @@ namespace Catch { { static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, }; - LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { for (auto const& def : signalDefs) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { reportFatal(def.name); @@ -10777,38 +10807,50 @@ namespace Catch { return EXCEPTION_CONTINUE_SEARCH; } - FatalConditionHandler::FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = nullptr; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } + // Since we do not support multiple instantiations, we put these + // into global variables and rely on cleaning them up in outlined + // constructors/destructors + static PVOID exceptionHandlerHandle = nullptr; - void FatalConditionHandler::reset() { - if (isSet) { - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = nullptr; - isSet = false; + // For MSVC, we reserve part of the stack memory for handling + // memory overflow structured exception. + FatalConditionHandler::FatalConditionHandler() { + ULONG guaranteeSize = static_cast(minStackSizeForErrors); + if (!SetThreadStackGuarantee(&guaranteeSize)) { + // We do not want to fully error out, because needing + // the stack reserve should be rare enough anyway. + Catch::cerr() + << "Failed to reserve piece of stack." + << " Stack overflows will not be reported successfully."; } } - FatalConditionHandler::~FatalConditionHandler() { - reset(); + // We do not attempt to unset the stack guarantee, because + // Windows does not support lowering the stack size guarantee. + FatalConditionHandler::~FatalConditionHandler() = default; + + void FatalConditionHandler::engage_platform() { + // Register as first handler in current chain + exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + if (!exceptionHandlerHandle) { + CATCH_RUNTIME_ERROR("Could not register vectored exception handler"); + } } -bool FatalConditionHandler::isSet = false; -ULONG FatalConditionHandler::guaranteeSize = 0; -PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; + void FatalConditionHandler::disengage_platform() { + if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { + CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); + } + exceptionHandlerHandle = nullptr; + } -} // namespace Catch +} // end namespace Catch -#elif defined( CATCH_CONFIG_POSIX_SIGNALS ) +#endif // CATCH_CONFIG_WINDOWS_SEH + +#if defined( CATCH_CONFIG_POSIX_SIGNALS ) + +#include namespace Catch { @@ -10817,10 +10859,6 @@ namespace Catch { const char* name; }; - // 32kb for the alternate stack seems to be sufficient. However, this value - // is experimentally determined, so that's not guaranteed. - static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; - static SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGILL, "SIGILL - Illegal instruction signal" }, @@ -10830,7 +10868,32 @@ namespace Catch { { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } }; - void FatalConditionHandler::handleSignal( int sig ) { +// Older GCCs trigger -Wmissing-field-initializers for T foo = {} +// which is zero initialization, but not explicit. We want to avoid +// that. +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + + static char* altStackMem = nullptr; + static std::size_t altStackSize = 0; + static stack_t oldSigStack{}; + static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{}; + + static void restorePreviousSignalHandlers() { + // We set signal handlers back to the previous ones. Hopefully + // nobody overwrote them in the meantime, and doesn't expect + // their signal handlers to live past ours given that they + // installed them after ours.. + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + } + + static void handleSignal( int sig ) { char const * name = ""; for (auto const& def : signalDefs) { if (sig == def.id) { @@ -10838,16 +10901,33 @@ namespace Catch { break; } } - reset(); - reportFatal(name); + // We need to restore previous signal handlers and let them do + // their thing, so that the users can have the debugger break + // when a signal is raised, and so on. + restorePreviousSignalHandlers(); + reportFatal( name ); raise( sig ); } FatalConditionHandler::FatalConditionHandler() { - isSet = true; + assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists"); + if (altStackSize == 0) { + altStackSize = std::max(static_cast(SIGSTKSZ), minStackSizeForErrors); + } + altStackMem = new char[altStackSize](); + } + + FatalConditionHandler::~FatalConditionHandler() { + delete[] altStackMem; + // We signal that another instance can be constructed by zeroing + // out the pointer. + altStackMem = nullptr; + } + + void FatalConditionHandler::engage_platform() { stack_t sigStack; sigStack.ss_sp = altStackMem; - sigStack.ss_size = sigStackSize; + sigStack.ss_size = altStackSize; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = { }; @@ -10859,40 +10939,17 @@ namespace Catch { } } - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } - - void FatalConditionHandler::reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[sigStackSize] = {}; - -} // namespace Catch - -#else - -namespace Catch { - void FatalConditionHandler::reset() {} -} - -#endif // signals/SEH handling - #if defined(__GNUC__) # pragma GCC diagnostic pop #endif + + void FatalConditionHandler::disengage_platform() { + restorePreviousSignalHandlers(); + } + +} // end namespace Catch + +#endif // CATCH_CONFIG_POSIX_SIGNALS // end catch_fatal_condition.cpp // start catch_generators.cpp @@ -11447,7 +11504,8 @@ namespace { return lhs == rhs; } - auto ulpDiff = std::abs(lc - rc); + // static cast as a workaround for IBM XLC + auto ulpDiff = std::abs(static_cast(lc - rc)); return static_cast(ulpDiff) <= maxUlpDiff; } @@ -11621,7 +11679,6 @@ Floating::WithinRelMatcher WithinRel(float target) { } // namespace Matchers } // namespace Catch - // end catch_matchers_floating.cpp // start catch_matchers_generic.cpp @@ -12955,9 +13012,8 @@ namespace Catch { } void RunContext::invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals + FatalConditionHandlerGuard _(&m_fatalConditionhandler); m_activeTestCase->invoke(); - fatalConditionHandler.reset(); } void RunContext::handleUnfinishedSections() { @@ -15320,7 +15376,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 13, 4, "", 0 ); + static Version version( 2, 13, 5, "", 0 ); return version; } From 70c966f4778a4d1d81edd0eb6940baf0b353d8c8 Mon Sep 17 00:00:00 2001 From: Mark <64029109+MarkFischinger@users.noreply.github.com> Date: Mon, 12 Apr 2021 21:57:08 +0200 Subject: [PATCH 184/729] Check whether existing weights are loaded If no weights are loaded, the network is empty and new weights are generated. If not, the already loaded weights will be used. --- src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp index 68b150bc9d..864b3ac58e 100644 --- a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp @@ -52,7 +52,9 @@ QLearning< targetNetwork = learningNetwork; // Set up q-learning network. - learningNetwork.ResetParameters(); + if(leaningNetwork.Parameters().is_empty()) + learningNetwork.ResetParameters(); + targetNetwork.ResetParameters(); #if ENS_VERSION_MAJOR == 1 From 1980e1492ed3aa14290669f540af591e00b11aa2 Mon Sep 17 00:00:00 2001 From: Mark <64029109+MarkFischinger@users.noreply.github.com> Date: Tue, 13 Apr 2021 02:22:46 +0200 Subject: [PATCH 185/729] Update q_learning_impl.hpp --- src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp index 864b3ac58e..1aa84d3822 100644 --- a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp @@ -52,7 +52,7 @@ QLearning< targetNetwork = learningNetwork; // Set up q-learning network. - if(leaningNetwork.Parameters().is_empty()) + if (leaningNetwork.Parameters().is_empty()) learningNetwork.ResetParameters(); targetNetwork.ResetParameters(); From 08f0ad96d988d756f990579d0af6ddedf6615678 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Tue, 13 Apr 2021 03:48:58 +0200 Subject: [PATCH 186/729] Remove remaining success parameter. --- src/mlpack/tests/serialization.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/tests/serialization.hpp b/src/mlpack/tests/serialization.hpp index 93b293b451..361523f701 100644 --- a/src/mlpack/tests/serialization.hpp +++ b/src/mlpack/tests/serialization.hpp @@ -39,7 +39,6 @@ void TestArmadilloSerialization(arma::Cube& x) // Now load it. arma::Cube orig(x); - success = true; std::ifstream ifs(fileName, std::ios::binary); { From e89e39d06de442153c3d2577197be36cd2616eab Mon Sep 17 00:00:00 2001 From: Mark <64029109+MarkFischinger@users.noreply.github.com> Date: Tue, 13 Apr 2021 11:42:11 +0200 Subject: [PATCH 187/729] Update q_learning_impl.hpp --- src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp index 1aa84d3822..9fe689aa26 100644 --- a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp @@ -52,7 +52,7 @@ QLearning< targetNetwork = learningNetwork; // Set up q-learning network. - if (leaningNetwork.Parameters().is_empty()) + if (learningNetwork.Parameters().is_empty()) learningNetwork.ResetParameters(); targetNetwork.ResetParameters(); From 17b05d054d15684f155edeed32f5c84addac371e Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Wed, 14 Apr 2021 04:33:52 +0200 Subject: [PATCH 188/729] Catch potential division by zero. --- src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp b/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp index cc1119a845..73a532b03e 100644 --- a/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/x_tree_split_impl.hpp @@ -435,7 +435,7 @@ bool XTreeSplit::SplitNonLeafNode(TreeType *tree, std::vector& relevels) bool useMinOverlapSplit = false; if (tiedOnOverlap) { - if (MAX_OVERLAP > 0 && + if (areaBestAreaAxis > 0 && overlapBestAreaAxis / areaBestAreaAxis < MAX_OVERLAP) { tree->numDescendants = 0; From 53402fdbc37a8a3c882be40b12de071f20b13363 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Thu, 15 Apr 2021 11:05:33 +0530 Subject: [PATCH 189/729] added preprocessing --- .../python/mlpack/preprocess_json_params.py | 111 +++++++++++++++++- 1 file changed, 106 insertions(+), 5 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 2d5f764ae2..1fb7227499 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,9 +1,110 @@ -def process_params(model, return_dic=False): +from random import randint +import numpy as np +import pprint + +def process_params(model, return_str=False, pretty_print=False): params = model.params() params_decoded = params.decode("utf-8").replace("true", "True")\ .replace("false", "False") - if return_dic: - dic = eval(params_decoded) - return params_decoded, dic + + # this is to handle same key names of "elem". + # same key values cannot exist in python dictionary, + # so I am replacing "elem" with random numbers. + str_to_find = '"elem":' + res = [i for i in range(len(params_decoded)) if\ + params_decoded.startswith(str_to_find, i)] + + # this variable keeps track of what random numbers are generated, + # to avoid same random numbers generated for two "elem" keys. + gen_nums = [] + + for i in range(len(res)): + random_num = random_with_N_digits(4) + + # keep generating until unique number is not found. + while(random_num in gen_nums): + random_num = random_with_N_digits(4) + + params_decoded = params_decoded[:res[i]] + '"{}":'.format(random_num) +\ + params_decoded[res[i]+len(str_to_find):] + + # now we can convert it to a python dictionary. + params_dic = eval(params_decoded) + + # remove "cereal_class_version". + scrub(params_dic, "cereal_class_version") + + # convert armadillo dictionary to numpy array + arma_to_np(params_dic) + + pp = pprint.PrettyPrinter() + + if pretty_print: + pp.pprint(params_dic) + + if return_str: + return params_dic, pp.pformat(params_dic) else: - return params_decoded + return params_dic + +def arma_to_np(obj): + """ + This function replaces the armadillo dictionary vector to + numpy array in the given dictionary. + """ + if isinstance(obj, dict): + for key in obj.keys(): + if isinstance(obj[key], dict): + # if "vec_state" is present in dictionary, then + # it must be armadillo vector. + if "vec_state" in obj[key].keys(): + n_rows = int(obj[key]["n_rows"]) + n_cols = int(obj[key]["n_cols"]) + elem_keys = list(set(obj[key].keys()).difference(set(["n_rows", "n_cols", "vec_state"]))) + elems = [] + for elem in elem_keys: + elems.append(obj[key][elem]) + + if n_rows*n_cols != len(elems): + raise RuntimeError("Shape {}x{} not valid with number of elements {}" + .format(n_rows, n_cols, len(elems))) + + elems = np.array(elems).reshape(n_cols, n_rows).astype(float) + obj[key] = elems + else: + arma_to_np(obj[key]) + else: + arma_to_np(obj[key]) + elif isinstance(obj, list): + for i in range(len(obj)): + arma_to_np(obj[i]) + else: + pass + +def scrub(obj, bad_key): + """ + This function removes a certain key-value pair from the + given dictionary. + """ + if isinstance(obj, dict): + for key in list(obj.keys()): + if key == bad_key: + del obj[key] + else: + scrub(obj[key], bad_key) + elif isinstance(obj, list): + for i in range(len(obj)): + if obj[i] == bad_key: + del obj[i] + else: + scrub(obj[i], bad_key) + else: + pass + +def random_with_N_digits(n): + """ + Generates random N digit numbers. + """ + range_start = 10**(n-1) + range_end = (10**n)-1 + return randint(range_start, range_end) \ No newline at end of file From 049dfc180b2f7831f29933ac3cc12e1331549471 Mon Sep 17 00:00:00 2001 From: Mark <64029109+MarkFischinger@users.noreply.github.com> Date: Thu, 15 Apr 2021 11:04:22 +0200 Subject: [PATCH 190/729] Update COPYRIGHT.txt --- COPYRIGHT.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index a3c8f90f38..b7e9d6cf15 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -142,6 +142,7 @@ Copyright: Copyright 2020, Gaurav Ghati Copyright 2020, Anmolpreet Singh Copyright 2021, Tru Hoang + Copyright 2021, Mark Fischinger License: BSD-3-clause All rights reserved. From 2e0eb7882f0bc32f5a4f6bcf354f015ef5a91cce Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Fri, 16 Apr 2021 21:26:45 +0200 Subject: [PATCH 191/729] Include string header to resolve undefined type error. --- src/mlpack/tests/main_tests/gmm_generate_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/tests/main_tests/gmm_generate_test.cpp b/src/mlpack/tests/main_tests/gmm_generate_test.cpp index 7a40e87f98..fe41ded07e 100644 --- a/src/mlpack/tests/main_tests/gmm_generate_test.cpp +++ b/src/mlpack/tests/main_tests/gmm_generate_test.cpp @@ -9,6 +9,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ +#include + #define BINDING_TYPE BINDING_TYPE_TEST static const std::string testName = "GmmGenerate"; From 0bd163d4a42effd7657eaeca14e9f899efa7df53 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Fri, 16 Apr 2021 22:28:31 +0200 Subject: [PATCH 192/729] Include string header to resolve undefined type error. --- src/mlpack/tests/main_tests/gmm_probability_test.cpp | 2 +- src/mlpack/tests/main_tests/range_search_test.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/main_tests/gmm_probability_test.cpp b/src/mlpack/tests/main_tests/gmm_probability_test.cpp index 0f5b9160c5..c4949b484a 100644 --- a/src/mlpack/tests/main_tests/gmm_probability_test.cpp +++ b/src/mlpack/tests/main_tests/gmm_probability_test.cpp @@ -9,9 +9,9 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ +#include #define BINDING_TYPE BINDING_TYPE_TEST - static const std::string testName = "GmmProbability"; #include diff --git a/src/mlpack/tests/main_tests/range_search_test.cpp b/src/mlpack/tests/main_tests/range_search_test.cpp index 3d9fd08bb5..c7c6ce9596 100644 --- a/src/mlpack/tests/main_tests/range_search_test.cpp +++ b/src/mlpack/tests/main_tests/range_search_test.cpp @@ -9,6 +9,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ +#include + #define BINDING_TYPE BINDING_TYPE_TEST static const std::string testName = "RangeSearchMain"; From df03ef559865662159df311b5c5f83976c14cd9b Mon Sep 17 00:00:00 2001 From: Yashwants19 Date: Sat, 17 Apr 2021 04:42:00 +0000 Subject: [PATCH 193/729] Upgrade Boost Version in CMake script. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73937c2a4b..0aa70cb74a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,7 @@ set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${CEREAL_INCLUDE_DIR}) # Unfortunately this configuration variable is necessary and will need to be # updated as time goes on and new versions are released. set(Boost_ADDITIONAL_VERSIONS + "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" From ad790e71e651638a70ef08141f595954d79ab3a1 Mon Sep 17 00:00:00 2001 From: Yashwants19 Date: Sat, 17 Apr 2021 10:03:34 +0000 Subject: [PATCH 194/729] Upgrade Catch to 2.13.6 --- src/mlpack/tests/catch.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mlpack/tests/catch.hpp b/src/mlpack/tests/catch.hpp index 9c1c854fd5..36eaeb27f7 100644 --- a/src/mlpack/tests/catch.hpp +++ b/src/mlpack/tests/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.13.5 - * Generated: 2021-04-10 23:43:17.560525 + * Catch v2.13.6 + * Generated: 2021-04-16 18:23:38.044268 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 5 +#define CATCH_VERSION_PATCH 6 #ifdef __clang__ # pragma clang system_header @@ -10751,8 +10751,8 @@ namespace Catch { // If neither SEH nor signal handling is required, the handler impls // do not have to do anything, and can be empty. - FatalConditionHandler::engage_platform() {} - FatalConditionHandler::disengage_platform() {} + void FatalConditionHandler::engage_platform() {} + void FatalConditionHandler::disengage_platform() {} FatalConditionHandler::FatalConditionHandler() = default; FatalConditionHandler::~FatalConditionHandler() = default; @@ -15376,7 +15376,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 13, 5, "", 0 ); + static Version version( 2, 13, 6, "", 0 ); return version; } From ed0e2e2b5f2d258132ee0ae5156e1843b7cb0b40 Mon Sep 17 00:00:00 2001 From: Roshan Swain Date: Sat, 17 Apr 2021 19:30:05 +0530 Subject: [PATCH 195/729] removed max from abs mod in ann_layer_test --- src/mlpack/tests/ann_layer_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index beb1339f56..54105b1f9e 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -256,7 +256,7 @@ TEST_CASE("SimpleDropoutLayerTest", "[ANNLayerTest]") // Test the Forward function. arma::mat output; module.Forward(input, output); - REQUIRE(arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))) <= 0.05); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))) <= 0.05); // Test the Backward function. arma::mat delta; @@ -349,7 +349,7 @@ TEST_CASE("SimpleAlphaDropoutLayerTest", "[ANNLayerTest]") // Test the Backward function when training phase. arma::mat delta; module.Backward(input, input, delta); - REQUIRE(arma::as_scalar(arma::max(arma::abs(arma::mean(delta) - 0) <= 0.05))); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(delta) - 0)) <= 0.05); // Test the Forward function when testing phase. module.Deterministic() = true; From 9c5da70aa033b0c0e43f57ee52824e4cde425212 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Sat, 17 Apr 2021 21:08:29 +0530 Subject: [PATCH 196/729] added reversed processing --- .../python/mlpack/preprocess_json_params.py | 82 ++++++++++++++++++- .../bindings/python/mlpack/serialization.hpp | 8 ++ .../bindings/python/mlpack/serialization.pxd | 3 +- .../bindings/python/print_class_defn.hpp | 14 +++- src/mlpack/bindings/python/print_pyx.cpp | 2 +- 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 1fb7227499..209f817838 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,9 +1,11 @@ from random import randint import numpy as np +import json import pprint +from copy import deepcopy -def process_params(model, return_str=False, pretty_print=False): - params = model.params() +def process_params(model, return_str=False, pretty_print=False, remove_version=False): + params = model.get_params() params_decoded = params.decode("utf-8").replace("true", "True")\ .replace("false", "False") @@ -32,7 +34,8 @@ def process_params(model, return_str=False, pretty_print=False): params_dic = eval(params_decoded) # remove "cereal_class_version". - scrub(params_dic, "cereal_class_version") + if remove_version: + scrub(params_dic, "cereal_class_version") # convert armadillo dictionary to numpy array arma_to_np(params_dic) @@ -47,9 +50,80 @@ def process_params(model, return_str=False, pretty_print=False): else: return params_dic +def feed_params(model, params_dic): + """ + This function takes in a model and the parameters dictionary, + and sets the parameters of the model as the given parameters. + """ + # deepcopy to prevent changes to the user dictionary. + params_dic_copy = deepcopy(params_dic) + + # this list for keeping track of the random numbers generated to replace + # '"elem":' string, because python dictionaries cannot hold same keys. + rand_gen = [] + np_to_arma(params_dic_copy, rand_gen) + + # dumping to string. + params_str = json.dumps(params_dic_copy) + + # replacing random numbers with '"elem":' to match JSON given by cereal. + for rand_num in rand_gen: + params_str = params_str.replace('"{}":'.format(rand_num), '"elem":') + + # setting parameters to the model. + model.set_params(params_str.encode("utf-8")) + +def np_to_arma(obj, rand_gen): + """ + This function replaces a numpy array to json representation + of armadillo vector. This is reverse of "arma_to_np(obj)". + """ + if isinstance(obj, dict): + for key in obj.keys(): + """ + Checking if this is a numpy array. + """ + if isinstance(obj[key], np.ndarray): + # n_rows, n_cols have to be strings. + n_rows, n_cols = str(1),str(1) + + dic = dict() + + if len(obj[key].shape) == 1: + n_rows = obj[key].shape[0] + dic["vec_state"] = str(1) + elif len(obj[key].shape) == 2: + n_rows, n_cols = obj[key].shape + dic["vec_state"] = str(2) + else: + raise RuntimeError("Invalid number of dimensions in array {}".format(len(onj[key].shape))) + + dic["n_rows"] = str(n_cols) # implicit transpose + dic["n_cols"] = str(n_rows) # implicit transpose + + elems = obj[key].flatten().astype(float) + + # writing elements of vector with random generated keys, + # these keys will be replaced by '"elem":' in "feed_params()" function. + for elem in elems: + random_key = random_with_N_digits(4) + while(random_key in rand_gen): + random_key = random_with_N_digits(4) + rand_gen.append(random_key) + dic[str(random_key)] = elem + + obj[key] = dic + else: + np_to_arma(obj[key], rand_gen) + elif isinstance(obj, list): + for i in range(len(obj)): + np_to_arma(obj[i], rand_gen) + else: + pass + def arma_to_np(obj): """ - This function replaces the armadillo dictionary vector to + This function replaces the JSON representation of armadillo vector to numpy array in the given dictionary. """ if isinstance(obj, dict): diff --git a/src/mlpack/bindings/python/mlpack/serialization.hpp b/src/mlpack/bindings/python/mlpack/serialization.hpp index df85aa5a2c..15f837a2de 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.hpp +++ b/src/mlpack/bindings/python/mlpack/serialization.hpp @@ -50,6 +50,14 @@ std::string SerializeOutJSON(T* t, const std::string& name) return oss.str(); } +template +void SerializeInJSON(T* t, const std::string& str, const std::string& name) +{ + std::istringstream iss(str); + cereal::JSONInputArchive b(iss); + b(cereal::make_nvp(name.c_str(), *t)); +} + } // namespace python } // namespace bindings } // namespace mlpack diff --git a/src/mlpack/bindings/python/mlpack/serialization.pxd b/src/mlpack/bindings/python/mlpack/serialization.pxd index a8d5298a90..dc3998fb70 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.pxd +++ b/src/mlpack/bindings/python/mlpack/serialization.pxd @@ -12,4 +12,5 @@ from libcpp.string cimport string cdef extern from "serialization.hpp" namespace "mlpack::bindings::python" nogil: string SerializeOut[T](T* t, string name) nogil void SerializeIn[T](T* t, string str, string name) nogil - string SerializeOutJSON[T](T* t, string name) nogil \ No newline at end of file + string SerializeOutJSON[T](T* t, string name) nogil + void SerializeInJSON[T](T* t, string str, string name) nogil \ No newline at end of file diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 5c436ff2ae..2f66adc241 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -72,14 +72,17 @@ void PrintClassDefn( * def __getstate__(self): * return SerializeOut(self.modelptr, "") * - * def _params(self): - * return SerializeOutJSON(self.modelptr, "") - * * def __setstate__(self, state): * SerializeIn(self.modelptr, state, "") * * def __reduce_ex__(self): * return (self.__class__, (), self.__getstate__()) + * + * def get_params(self): + * return SerializeOutJSON(self.modelptr, "") + * + * def set_params(self, state): + * SerializeInJSON(seld.modelptr, state, "") * @endcode */ std::cout << "cdef class " << strippedType << "Type:" << std::endl; @@ -103,9 +106,12 @@ void PrintClassDefn( std::cout << " return (self.__class__, (), self.__getstate__())" << std::endl; std::cout << std::endl; - std::cout << " def params(self):" << std::endl; + std::cout << " def get_params(self):" << std::endl; std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType << "\")" << std::endl; + std::cout << " def set_params(self, state):" << std::endl; + std::cout << " SerializeInJSON(self.modelptr, state, \"" << printedType + << "\")" << std::endl; std::cout << std::endl; } diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 3b8ef867cc..edcdb66ac1 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,7 +80,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, " << "ResetTimers, EnableTimers" << endl; cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl; - cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON" << endl; + cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON, SerializeInJSON" << endl; cout << endl; cout << "import numpy as np" << endl; cout << "cimport numpy as np" << endl; From d8ca63f576f1e46cfd5cfd7303554e1c08f6c1c9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 20 Apr 2021 07:08:01 +0530 Subject: [PATCH 197/729] Make new file for random split. --- .../best_binary_numeric_split.hpp | 71 -------- .../best_binary_numeric_split_impl.hpp | 139 --------------- .../random_binary_numeric_split.hpp | 97 +++++++++++ .../random_binary_numeric_split_impl.hpp | 162 ++++++++++++++++++ 4 files changed, 259 insertions(+), 210 deletions(-) create mode 100644 src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp create mode 100644 src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 9f41490086..976b810c63 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -87,77 +87,6 @@ class BestBinaryNumericSplit const AuxiliarySplitInfo& /* aux */); }; -/** - * The RandomBinaryNumericSplit is a splitting function for decision trees that - * will split based on a randomly selected point between the minimum - * and maximum value of the numerical dimension. - * - * @tparam FitnessFunction Fitness function to use to calculate gain. - */ -template -class RandomBinaryNumericSplit -{ - public: - // No extra info needed for split. - template - class AuxiliarySplitInfo { }; - - /** - * Check if we can split a node. If we can split a node in a way that - * improves on 'bestGain', then we return the improved gain. Otherwise we - * return the value 'bestGain'. If a split is made, then classProbabilities - * and aux may be modified. - * - * @param bestGain Best gain seen so far (we'll only split if we find gain - * better than this). - * @param data The dimension of data points to check for a split in. - * @param labels Labels for each point. - * @param numClasses Number of classes in the dataset. - * @param weights Weights associated with labels. - * @param minimumLeafSize Minimum number of points in a leaf node for - * splitting. - * @param minimumGainSplit Minimum gain split. - * @param classProbabilities Class probabilities vector, which may be filled - * with split information a successful split. - * @param aux Auxiliary split information, which may be modified on a - * successful split. - */ - template - static double SplitIfBetter( - const double bestGain, - const VecType& data, - const arma::Row& labels, - const size_t numClasses, - const WeightVecType& weights, - const size_t minimumLeafSize, - const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& aux); - - /** - * Returns 2, since the binary split always has two children. - */ - template - static size_t NumChildren(const arma::Col& /* classProbabilities */, - const AuxiliarySplitInfo& /* aux */) - { - return 2; - } - - /** - * Given a point, calculate which child it should go to (left or right). - * - * @param point Point to calculate direction of. - * @param classProbabilities Auxiliary information for the split. - * @param * (aux) Auxiliary information for the split (Unused). - */ - template - static size_t CalculateDirection( - const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */); -}; - } // namespace tree } // namespace mlpack diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 2fad09fb69..e611038e79 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -200,145 +200,6 @@ size_t BestBinaryNumericSplit::CalculateDirection( return 1; // Go right. } -template -template -double RandomBinaryNumericSplit::SplitIfBetter( - const double bestGain, - const VecType& data, - const arma::Row& labels, - const size_t numClasses, - const WeightVecType& weights, - const size_t minimumLeafSize, - const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& /* aux */) -{ - double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); - // Forcing a minimum leaf size of 1 (empty children don't make sense). - const size_t minimum = std::max(minimumLeafSize, (size_t) 1); - - // First sanity check: if we don't have enough points, we can't split. - if (data.n_elem < (minimum * 2)) - return DBL_MAX; - if (bestGain == 0.0) - return DBL_MAX; // It can't be outperformed. - - typename VecType::elem_type maxValue = arma::max(data); - typename VecType::elem_type minValue = arma::min(data); - - // Sanity check: if the maximum element is the same as the mininimum, we - // can't split in this dimension. - if (maxValue == minValue) - return DBL_MAX; - - /* - Just for making review easy, the following bit of code is taken directly from - https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution - to generate a random number. (To be removed before merge) - */ - // Picking a random pivot to split the dimension. - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_real_distribution<> distribution(minValue, maxValue); - double randomPivot = distribution(gen); - - // We need to count the number of points for each class. - arma::Mat classCounts; - arma::mat classWeightSums; - double totalWeight = 0.0; - double totalLeftWeight = 0.0; - double totalRightWeight = 0.0; - size_t leftLeafSize = 0; - size_t rightLeafSize = 0; - if (UseWeights) - { - classWeightSums.zeros(numClasses, 2); - totalWeight = arma::accu(weights); - bestFoundGain *= totalWeight; - - for (size_t i = 0; i < data.n_elem; ++i) - { - if (data(i) < randomPivot) - { - ++leftLeafSize; - classWeightSums(labels(i), 0) += weights(i); - totalLeftWeight += weights(i); - } - else - { - ++rightLeafSize; - classWeightSums(labels(i), 1) += weights(i); - totalRightWeight += weights(i); - } - } - } - else - { - classCounts.zeros(numClasses, 2); - bestFoundGain *= data.n_elem; - - for (size_t i = 0; i < data.n_elem; i++) - { - if (data(i) < randomPivot) - { - ++leftLeafSize; - ++classCounts(labels(i), 0); - } - else - { - ++rightLeafSize; - ++classCounts(labels(i), 1); - } - } - } - - // Calculate the gain for the left and right child. Only use weights if - // needed. - const double leftGain = UseWeights ? - FitnessFunction::template EvaluatePtr(classWeightSums.colptr(0), - numClasses, totalLeftWeight) : - FitnessFunction::template EvaluatePtr(classCounts.colptr(0), - numClasses, leftLeafSize); - const double rightGain = UseWeights ? - FitnessFunction::template EvaluatePtr(classWeightSums.colptr(1), - numClasses, totalRightWeight) : - FitnessFunction::template EvaluatePtr(classCounts.colptr(1), - numClasses, rightLeafSize); - - double gain; - if (UseWeights) - gain = totalLeftWeight * leftGain + totalRightWeight * rightGain; - else - // Calculate the gain at this split point. - gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; - - if (gain < bestFoundGain) - return DBL_MAX; - - classProbabilities.set_size(1); - classProbabilities(0) = randomPivot; - - if (UseWeights) - gain /= totalWeight; - else - gain /= labels.n_elem; - - return gain; -} - -template -template -size_t RandomBinaryNumericSplit::CalculateDirection( - const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */) -{ - if (point <= classProbabilities(0)) - return 0; // Go left. - else - return 1; // Go right. -} - } // namespace tree } // namespace mlpack diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp new file mode 100644 index 0000000000..944bf82809 --- /dev/null +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -0,0 +1,97 @@ +/** + * @file methods/decision_tree/random_binary_numeric_split.hpp + * @author Rishabh Garg + * + * A tree splitter that finds a random binary numeric split. + * + * 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_DECISION_TREE_RANDOM_BINARY_NUMERIC_SPLIT_HPP +#define MLPACK_METHODS_DECISION_TREE_RANDOM_BINARY_NUMERIC_SPLIT_HPP + +#include + +namespace mlpack { +namespace tree { + +/** + * The RandomBinaryNumericSplit is a splitting function for decision trees that + * will split based on a randomly selected point between the minimum + * and maximum value of the numerical dimension. + * + * @tparam FitnessFunction Fitness function to use to calculate gain. + */ +template +class RandomBinaryNumericSplit +{ + public: + // No extra info needed for split. + template + class AuxiliarySplitInfo { }; + + /** + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then classProbabilities + * and aux may be modified. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param labels Labels for each point. + * @param numClasses Number of classes in the dataset. + * @param weights Weights associated with labels. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param minimumGainSplit Minimum gain split. + * @param classProbabilities Class probabilities vector, which may be filled + * with split information a successful split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + */ + template + static double SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const size_t numClasses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + arma::Col& classProbabilities, + AuxiliarySplitInfo& aux); + + /** + * Returns 2, since the binary split always has two children. + */ + template + static size_t NumChildren(const arma::Col& /* classProbabilities */, + const AuxiliarySplitInfo& /* aux */) + { + return 2; + } + + /** + * Given a point, calculate which child it should go to (left or right). + * + * @param point Point to calculate direction of. + * @param classProbabilities Auxiliary information for the split. + * @param * (aux) Auxiliary information for the split (Unused). + */ + template + static size_t CalculateDirection( + const ElemType& point, + const arma::Col& classProbabilities, + const AuxiliarySplitInfo& /* aux */); +}; + +} // namespace tree +} // namespace mlpack + +// Include implementation. +#include "best_binary_numeric_split_impl.hpp" + +#endif \ No newline at end of file diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp new file mode 100644 index 0000000000..44edfda841 --- /dev/null +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -0,0 +1,162 @@ +/** + * @file methods/decision_tree/random_binary_numeric_split_impl.hpp + * @author Rishabh Garg + * + * Implementation of strategy that finds the random binary numeric split. + * + * 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_DECISION_TREE_RANDOM_BINARY_NUMERIC_SPLIT_IMPL_HPP +#define MLPACK_METHODS_DECISION_TREE_RANDOM_BINARY_NUMERIC_SPLIT_IMPL_HPP + +#include + +namespace mlpack { +namespace tree { + +template +template +double RandomBinaryNumericSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const size_t numClasses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + arma::Col& classProbabilities, + AuxiliarySplitInfo& /* aux */) +{ + double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); + // Forcing a minimum leaf size of 1 (empty children don't make sense). + const size_t minimum = std::max(minimumLeafSize, (size_t) 1); + + // First sanity check: if we don't have enough points, we can't split. + if (data.n_elem < (minimum * 2)) + return DBL_MAX; + if (bestGain == 0.0) + return DBL_MAX; // It can't be outperformed. + + typename VecType::elem_type maxValue = arma::max(data); + typename VecType::elem_type minValue = arma::min(data); + + // Sanity check: if the maximum element is the same as the mininimum, we + // can't split in this dimension. + if (maxValue == minValue) + return DBL_MAX; + + /* + Just for making review easy, the following bit of code is taken directly from + https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + to generate a random number. (To be removed before merge) + */ + // Picking a random pivot to split the dimension. + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> distribution(minValue, maxValue); + double randomPivot = distribution(gen); + + // We need to count the number of points for each class. + arma::Mat classCounts; + arma::mat classWeightSums; + double totalWeight = 0.0; + double totalLeftWeight = 0.0; + double totalRightWeight = 0.0; + size_t leftLeafSize = 0; + size_t rightLeafSize = 0; + if (UseWeights) + { + classWeightSums.zeros(numClasses, 2); + totalWeight = arma::accu(weights); + bestFoundGain *= totalWeight; + + for (size_t i = 0; i < data.n_elem; ++i) + { + if (data(i) < randomPivot) + { + ++leftLeafSize; + classWeightSums(labels(i), 0) += weights(i); + totalLeftWeight += weights(i); + } + else + { + ++rightLeafSize; + classWeightSums(labels(i), 1) += weights(i); + totalRightWeight += weights(i); + } + } + } + else + { + classCounts.zeros(numClasses, 2); + bestFoundGain *= data.n_elem; + + for (size_t i = 0; i < data.n_elem; i++) + { + if (data(i) < randomPivot) + { + ++leftLeafSize; + ++classCounts(labels(i), 0); + } + else + { + ++rightLeafSize; + ++classCounts(labels(i), 1); + } + } + } + + // Calculate the gain for the left and right child. Only use weights if + // needed. + const double leftGain = UseWeights ? + FitnessFunction::template EvaluatePtr(classWeightSums.colptr(0), + numClasses, totalLeftWeight) : + FitnessFunction::template EvaluatePtr(classCounts.colptr(0), + numClasses, leftLeafSize); + const double rightGain = UseWeights ? + FitnessFunction::template EvaluatePtr(classWeightSums.colptr(1), + numClasses, totalRightWeight) : + FitnessFunction::template EvaluatePtr(classCounts.colptr(1), + numClasses, rightLeafSize); + + double gain; + if (UseWeights) + gain = totalLeftWeight * leftGain + totalRightWeight * rightGain; + else + // Calculate the gain at this split point. + gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; + + if (gain < bestFoundGain) + return DBL_MAX; + + classProbabilities.set_size(1); + classProbabilities(0) = randomPivot; + + if (UseWeights) + gain /= totalWeight; + else + gain /= labels.n_elem; + + return gain; +} + +template +template +size_t RandomBinaryNumericSplit::CalculateDirection( + const ElemType& point, + const arma::Col& classProbabilities, + const AuxiliarySplitInfo& /* aux */) +{ + if (point <= classProbabilities(0)) + return 0; // Go left. + else + return 1; // Go right. +} + +} // namespace tree +} // namespace mlpack + +#endif From ccebfcbe634823e77ada8c940925901fd6a23fdc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 20 Apr 2021 07:29:40 +0530 Subject: [PATCH 198/729] Changed imports --- src/mlpack/methods/decision_tree/decision_tree.hpp | 1 + .../methods/decision_tree/random_binary_numeric_split.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree.hpp b/src/mlpack/methods/decision_tree/decision_tree.hpp index 9ab8599aec..2d9c5c92c4 100644 --- a/src/mlpack/methods/decision_tree/decision_tree.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree.hpp @@ -17,6 +17,7 @@ #include "gini_gain.hpp" #include "information_gain.hpp" #include "best_binary_numeric_split.hpp" +#include "random_binary_numeric_split.hpp" #include "all_categorical_split.hpp" #include "all_dimension_select.hpp" #include diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 944bf82809..4733c6d84b 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -92,6 +92,6 @@ class RandomBinaryNumericSplit } // namespace mlpack // Include implementation. -#include "best_binary_numeric_split_impl.hpp" +#include "random_binary_numeric_split_impl.hpp" #endif \ No newline at end of file From 25ce2155540beba2f9e210d1dd8ba65f06567d81 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 20 Apr 2021 07:41:45 +0530 Subject: [PATCH 199/729] Use math::Random which essentially does the same thing --- .../random_binary_numeric_split_impl.hpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 44edfda841..99656601d0 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -12,7 +12,7 @@ #ifndef MLPACK_METHODS_DECISION_TREE_RANDOM_BINARY_NUMERIC_SPLIT_IMPL_HPP #define MLPACK_METHODS_DECISION_TREE_RANDOM_BINARY_NUMERIC_SPLIT_IMPL_HPP -#include +#include namespace mlpack { namespace tree { @@ -48,16 +48,8 @@ double RandomBinaryNumericSplit::SplitIfBetter( if (maxValue == minValue) return DBL_MAX; - /* - Just for making review easy, the following bit of code is taken directly from - https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution - to generate a random number. (To be removed before merge) - */ // Picking a random pivot to split the dimension. - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_real_distribution<> distribution(minValue, maxValue); - double randomPivot = distribution(gen); + double randomPivot = math::Random(minValue, maxValue); // We need to count the number of points for each class. arma::Mat classCounts; From 374cb2db9ad9c975379aaaf00090ab87223ec022 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 20 Apr 2021 07:44:41 +0530 Subject: [PATCH 200/729] Fixed typo --- .../methods/decision_tree/random_binary_numeric_split_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 99656601d0..1b11bcb57c 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -43,7 +43,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( typename VecType::elem_type maxValue = arma::max(data); typename VecType::elem_type minValue = arma::min(data); - // Sanity check: if the maximum element is the same as the mininimum, we + // Sanity check: if the maximum element is the same as the minimum, we // can't split in this dimension. if (maxValue == minValue) return DBL_MAX; From 8d63ae35f3a62db88c33eef02d96101a12715475 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 20 Apr 2021 07:52:53 +0530 Subject: [PATCH 201/729] Add citation. --- .../random_binary_numeric_split.hpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 4733c6d84b..0a94d2db22 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -4,6 +4,26 @@ * * A tree splitter that finds a random binary numeric split. * + * @code + * @article{10.1007/s10994-006-6226-1, + * author = {Geurts, Pierre and Ernst, Damien and Wehenkel, Louis}, + * title = {Extremely Randomized Trees}, + * year = {2006}, + * issue_date = {April 2006}, + * publisher = {Kluwer Academic Publishers}, + * address = {USA}, + * volume = {63}, + * number = {1}, + * issn = {0885-6125}, + * url = {https://doi.org/10.1007/s10994-006-6226-1}, + * doi = {10.1007/s10994-006-6226-1}, + * journal = {Mach. Learn.}, + * month = apr, + * pages = {3–42}, + * numpages = {40}, + * } + * @endcode + * * 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 From a5b632c761c92e59cd7ac0e2ec7785df12cbaa9f Mon Sep 17 00:00:00 2001 From: Aakash Kaushik Date: Thu, 22 Apr 2021 00:11:32 +0530 Subject: [PATCH 202/729] tests/cmake config --- src/mlpack/tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index de0f56d8df..9761cd6df1 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -1,3 +1,5 @@ +include(CTest) + # mlpack test executable. add_executable(mlpack_test activation_functions_test.cpp From f2bc627d75eea094d71cac21d533b7ca96ce183b Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 06:24:42 +0530 Subject: [PATCH 203/729] Move citation into class and added newline at EOF --- .../random_binary_numeric_split.hpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 0a94d2db22..5d3f99ba21 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -4,26 +4,6 @@ * * A tree splitter that finds a random binary numeric split. * - * @code - * @article{10.1007/s10994-006-6226-1, - * author = {Geurts, Pierre and Ernst, Damien and Wehenkel, Louis}, - * title = {Extremely Randomized Trees}, - * year = {2006}, - * issue_date = {April 2006}, - * publisher = {Kluwer Academic Publishers}, - * address = {USA}, - * volume = {63}, - * number = {1}, - * issn = {0885-6125}, - * url = {https://doi.org/10.1007/s10994-006-6226-1}, - * doi = {10.1007/s10994-006-6226-1}, - * journal = {Mach. Learn.}, - * month = apr, - * pages = {3–42}, - * numpages = {40}, - * } - * @endcode - * * 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 @@ -58,6 +38,26 @@ class RandomBinaryNumericSplit * return the value 'bestGain'. If a split is made, then classProbabilities * and aux may be modified. * + * @code + * @article{10.1007/s10994-006-6226-1, + * author = {Geurts, Pierre and Ernst, Damien and Wehenkel, Louis}, + * title = {Extremely Randomized Trees}, + * year = {2006}, + * issue_date = {April 2006}, + * publisher = {Kluwer Academic Publishers}, + * address = {USA}, + * volume = {63}, + * number = {1}, + * issn = {0885-6125}, + * url = {https://doi.org/10.1007/s10994-006-6226-1}, + * doi = {10.1007/s10994-006-6226-1}, + * journal = {Mach. Learn.}, + * month = apr, + * pages = {3–42}, + * numpages = {40}, + * } + * @endcode + * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). * @param data The dimension of data points to check for a split in. @@ -114,4 +114,4 @@ class RandomBinaryNumericSplit // Include implementation. #include "random_binary_numeric_split_impl.hpp" -#endif \ No newline at end of file +#endif From ab6ae18801954aed12fd8c4f1d994e88dfd454ac Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 06:34:39 +0530 Subject: [PATCH 204/729] Removed best found gain check, as discussed with @rcurtin --- .../methods/decision_tree/random_binary_numeric_split_impl.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 1b11bcb57c..231827deac 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -121,9 +121,6 @@ double RandomBinaryNumericSplit::SplitIfBetter( // Calculate the gain at this split point. gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; - if (gain < bestFoundGain) - return DBL_MAX; - classProbabilities.set_size(1); classProbabilities(0) = randomPivot; From 4704a25da533469a3436adde9c78d2cabb608acb Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 06:37:09 +0530 Subject: [PATCH 205/729] Removed test where no split was made if there was no gain. --- src/mlpack/tests/decision_tree_test.cpp | 31 ------------------------- 1 file changed, 31 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index f01ceefefa..f9bc70c956 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -405,37 +405,6 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") REQUIRE(classProbabilities.n_elem == 0); } -/** - * Check that the RandomBinaryNumericSplit doesn't split a dimension that gives - * no gain. - */ -TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") -{ - arma::vec values(100); - arma::Row labels(100); - arma::rowvec weights; - for (size_t i = 0; i < 100; i += 2) - { - values[i] = i; - labels[i] = 0; - values[i + 1] = i; - labels[i + 1] = 1; - } - - arma::vec classProbabilities; - RandomBinaryNumericSplit::template AuxiliarySplitInfo aux; - - // Call the method to do the splitting. - const double bestGain = GiniGain::Evaluate(labels, 2, weights); - const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, - aux); - - // Make sure there was no split. - REQUIRE(gain == DBL_MAX); - REQUIRE(classProbabilities.n_elem == 0); -} - /** * Check that the AllCategoricalSplit will split when the split is obviously * better. From bf98ea52bf67249f25faf9dbd6db1b5416fcebca Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 09:23:45 +0530 Subject: [PATCH 206/729] Add test for different splits under best and random settings. --- src/mlpack/tests/decision_tree_test.cpp | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index f9bc70c956..8337486e84 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -405,6 +405,48 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") REQUIRE(classProbabilities.n_elem == 0); } +/** + * Check that RandomBinaryNumericSplit generally gives a split different than + * the BestBinaryNumericSplit. + */ + TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") + { + arma::vec values(1000); + arma::Row labels(1000); + arma::rowvec weights; + for (size_t i = 0; i < 1000; i += 2) + { + values[i] = math::Random(0, 5); + labels[i] = 0; + values[i + 1] = math::Random(0, 5); + labels[i + 1] = 1; + } + + arma::vec classProbabilities, classProbabilities1; + BestBinaryNumericSplit::template AuxiliarySplitInfo aux; + RandomBinaryNumericSplit::template AuxiliarySplitInfo aux1; + + const double bestGain = GiniGain::Evaluate(labels, 2, weights); + + for(int i = 0; i < 5; i++) + { + // Call BestBinaryNumericSplit to do the splitting. + double gain = BestBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities, + aux); + + // Call RandomBinaryNumericSplit to do the splitting. + gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1, + aux1); + + if (classProbabilities[0] == classProbabilities1[0]) + break; + } + + REQUIRE(classProbabilities[0] != classProbabilities1[0]); + } + /** * Check that the AllCategoricalSplit will split when the split is obviously * better. From 43097c96f765663f194372b18a82d07f20f18af6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:03:53 +0530 Subject: [PATCH 207/729] Add UseBootstrap template parameter to random forest --- .../methods/random_forest/random_forest.hpp | 1 + .../random_forest/random_forest_impl.hpp | 30 +++++++++++++++++++ src/mlpack/tests/random_forest_test.cpp | 6 ++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 3790f1a725..fa91edd1ef 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -37,6 +37,7 @@ namespace tree { * @endcode */ template class NumericSplitType = BestBinaryNumericSplit, template class CategoricalSplitType = AllCategoricalSplit> diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 32152d2c91..46bedddd15 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -20,12 +20,14 @@ namespace tree { template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType > RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -37,6 +39,7 @@ RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -44,6 +47,7 @@ template< template RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -67,6 +71,7 @@ RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -74,6 +79,7 @@ template< template RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -97,6 +103,7 @@ RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -104,6 +111,7 @@ template< template RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -127,6 +135,7 @@ RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -134,6 +143,7 @@ template< template RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -157,6 +167,7 @@ RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -164,6 +175,7 @@ template< template double RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -187,6 +199,7 @@ double RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -194,6 +207,7 @@ template< template double RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -217,6 +231,7 @@ double RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -224,6 +239,7 @@ template< template double RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -247,6 +263,7 @@ double RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -254,6 +271,7 @@ template< template double RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -277,6 +295,7 @@ double RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -284,6 +303,7 @@ template< template size_t RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -299,6 +319,7 @@ size_t RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -306,6 +327,7 @@ template< template void RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -344,6 +366,7 @@ void RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -351,6 +374,7 @@ template< template void RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -377,6 +401,7 @@ void RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -384,6 +409,7 @@ template< template void RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -413,6 +439,7 @@ void RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -420,6 +447,7 @@ template< template void RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType @@ -443,6 +471,7 @@ void RandomForest< template< typename FitnessFunction, + bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, template class CategoricalSplitType @@ -450,6 +479,7 @@ template< template double RandomForest< FitnessFunction, + UseBootstrap, DimensionSelectionType, NumericSplitType, CategoricalSplitType diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 62592c0907..e5c6b10004 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -409,13 +409,13 @@ TEST_CASE("RandomForestNumericTrainReturnEntropy", "[RandomForestTest]") weights[i] = math::Random(0.0, 0.01); // Low weights for false points. // Test random forest on unweighted numeric dataset. - RandomForest rf; + RandomForest rf; double entropy = rf.Train(dataset, labels, 3, 10, 1); REQUIRE(std::isfinite(entropy) == true); // Test random forest on weighted numeric dataset. - RandomForest wrf; + RandomForest wrf; entropy = wrf.Train(dataset, labels, 3, weights, 10, 1); REQUIRE(std::isfinite(entropy) == true); @@ -488,7 +488,7 @@ TEST_CASE("DifferentTreesTest", "[RandomForestTest]") // multiple trials. while (!success && trial < 5) { - RandomForest rf; + RandomForest rf; rf.Train(d, l, 2, 2, 5); success = (rf.Tree(0).SplitDimension() != rf.Tree(1).SplitDimension()); From 1ff5e61103d3d77ae5c5cab79c52f347b15d9745 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:24:49 +0530 Subject: [PATCH 208/729] Changed train function to use UseBootstrap --- .../random_forest/random_forest_impl.hpp | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 46bedddd15..970c57d3c0 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -508,44 +508,62 @@ double RandomForest< #pragma omp parallel for reduction( + : totalGain) for (omp_size_t i = 0; i < numTrees; ++i) { - Timer::Start("bootstrap"); MatType bootstrapDataset; arma::Row bootstrapLabels; arma::rowvec bootstrapWeights; - Bootstrap(dataset, labels, weights, bootstrapDataset, - bootstrapLabels, bootstrapWeights); - Timer::Stop("bootstrap"); + if (UseBootstrap) + { + Timer::Start("bootstrap"); + Bootstrap(dataset, labels, weights, bootstrapDataset, + bootstrapLabels, bootstrapWeights); + Timer::Stop("bootstrap"); + } Timer::Start("train_tree"); if (UseWeights) { if (UseDatasetInfo) { - totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, - datasetInfo, bootstrapLabels, numClasses, bootstrapWeights, - minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + totalGain += UseBootstrap ? + trees[oldNumTrees + i].Train(bootstrapDataset, datasetInfo, + bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, + minimumGainSplit, maximumDepth, dimensionSelector) : + trees[oldNumTrees + i].Train(dataset, datasetInfo, labels, + numClasses, weights, minimumLeafSize, minimumGainSplit, + maximumDepth, dimensionSelector); } else { - totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, - bootstrapLabels, numClasses, bootstrapWeights, minimumLeafSize, - minimumGainSplit, maximumDepth, dimensionSelector); + totalGain += UseBootstrap ? + trees[oldNumTrees + i].Train(bootstrapDataset, bootstrapLabels, + numClasses, bootstrapWeights, minimumLeafSize, + minimumGainSplit, maximumDepth, dimensionSelector) : + trees[oldNumTrees + i].Train(dataset, labels, numClasses, + weights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } } else { if (UseDatasetInfo) { - totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, - datasetInfo, bootstrapLabels, numClasses, minimumLeafSize, - minimumGainSplit, maximumDepth, dimensionSelector); + totalGain += UseBootstrap ? + trees[oldNumTrees + i].Train(bootstrapDataset, datasetInfo, + bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, + maximumDepth, dimensionSelector) : + trees[oldNumTrees + i].Train(dataset, datasetInfo, labels, + numClasses, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } else { - totalGain += trees[oldNumTrees + i].Train(bootstrapDataset, - bootstrapLabels, numClasses, minimumLeafSize, minimumGainSplit, - maximumDepth, dimensionSelector); + totalGain += UseBootstrap ? + trees[oldNumTrees + i].Train(bootstrapDataset, bootstrapLabels, + numClasses, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector) : + trees[oldNumTrees + i].Train(dataset, labels, numClasses, + minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); } } From c049d49ebd8bce51abe1eade47dfd322b662bd7c Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:38:35 +0530 Subject: [PATCH 209/729] Removed ElemType from RandomBinaryNumericSplit --- .../decision_tree/random_binary_numeric_split.hpp | 14 ++++++-------- .../random_binary_numeric_split_impl.hpp | 8 ++++---- src/mlpack/tests/decision_tree_test.cpp | 6 +++--- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 5d3f99ba21..6297b20727 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -29,7 +29,6 @@ class RandomBinaryNumericSplit { public: // No extra info needed for split. - template class AuxiliarySplitInfo { }; /** @@ -81,15 +80,14 @@ class RandomBinaryNumericSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& aux); + arma::vec& classProbabilities, + AuxiliarySplitInfo& aux); /** * Returns 2, since the binary split always has two children. */ - template - static size_t NumChildren(const arma::Col& /* classProbabilities */, - const AuxiliarySplitInfo& /* aux */) + static size_t NumChildren(const arma::vec& /* classProbabilities */, + const AuxiliarySplitInfo& /* aux */) { return 2; } @@ -104,8 +102,8 @@ class RandomBinaryNumericSplit template static size_t CalculateDirection( const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */); + const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */); }; } // namespace tree diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 231827deac..a6bd966ecd 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -27,8 +27,8 @@ double RandomBinaryNumericSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::Col& classProbabilities, - AuxiliarySplitInfo& /* aux */) + arma::vec& classProbabilities, + AuxiliarySplitInfo& /* aux */) { double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); // Forcing a minimum leaf size of 1 (empty children don't make sense). @@ -136,8 +136,8 @@ template template size_t RandomBinaryNumericSplit::CalculateDirection( const ElemType& point, - const arma::Col& classProbabilities, - const AuxiliarySplitInfo& /* aux */) + const arma::vec& classProbabilities, + const AuxiliarySplitInfo& /* aux */) { if (point <= classProbabilities(0)) return 0; // Go left. diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 19cf0ca930..d45e413835 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -387,7 +387,7 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); arma::vec classProbabilities; - RandomBinaryNumericSplit::template AuxiliarySplitInfo aux; + RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); @@ -423,8 +423,8 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") } arma::vec classProbabilities, classProbabilities1; - BestBinaryNumericSplit::template AuxiliarySplitInfo aux; - RandomBinaryNumericSplit::template AuxiliarySplitInfo aux1; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; + RandomBinaryNumericSplit::AuxiliarySplitInfo aux1; const double bestGain = GiniGain::Evaluate(labels, 2, weights); From 5c3b60ea0ba86251bf018784ed1725a32bdb2cb5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 24 Apr 2021 06:41:55 +0530 Subject: [PATCH 210/729] Add splitIfBetterGain to RandomBinaryNumericSplit --- .../random_binary_numeric_split.hpp | 3 +- .../random_binary_numeric_split_impl.hpp | 6 +++- src/mlpack/tests/decision_tree_test.cpp | 31 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 6297b20727..8a530a651f 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -81,7 +81,8 @@ class RandomBinaryNumericSplit const size_t minimumLeafSize, const double minimumGainSplit, arma::vec& classProbabilities, - AuxiliarySplitInfo& aux); + AuxiliarySplitInfo& aux, + const bool splitIfBetterGain = false); /** * Returns 2, since the binary split always has two children. diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index a6bd966ecd..ed4f6f0e45 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -28,7 +28,8 @@ double RandomBinaryNumericSplit::SplitIfBetter( const size_t minimumLeafSize, const double minimumGainSplit, arma::vec& classProbabilities, - AuxiliarySplitInfo& /* aux */) + AuxiliarySplitInfo& /* aux */, + const bool splitIfBetterGain) { double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); // Forcing a minimum leaf size of 1 (empty children don't make sense). @@ -121,6 +122,9 @@ double RandomBinaryNumericSplit::SplitIfBetter( // Calculate the gain at this split point. gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; + if (gain < bestFoundGain and splitIfBetterGain) + return DBL_MAX; + classProbabilities.set_size(1); classProbabilities(0) = randomPivot; diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index d45e413835..52730c5c28 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -405,6 +405,37 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") REQUIRE(classProbabilities.n_elem == 0); } +/** + * Check that the RandomBinaryNumericSplit doesn't split a dimension that gives + * no gain when splitIfBetterGain is true. + */ +TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") +{ + arma::vec values(100); + arma::Row labels(100); + arma::rowvec weights; + for (size_t i = 0; i < 100; i += 2) + { + values[i] = i; + labels[i] = 0; + values[i + 1] = i; + labels[i + 1] = 1; + } + + arma::vec classProbabilities; + RandomBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = GiniGain::Evaluate(labels, 2, weights); + const double gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, + aux, true); + + // Make sure there was no split. + REQUIRE(gain == DBL_MAX); + REQUIRE(classProbabilities.n_elem == 0); +} + /** * Check that RandomBinaryNumericSplit generally gives a split different than * the BestBinaryNumericSplit. From fdfdc925705127b49d7e76582de523f8a419b3bf Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 24 Apr 2021 06:46:39 +0530 Subject: [PATCH 211/729] Shifter UseBootstrap to end of template list --- .../methods/random_forest/random_forest.hpp | 4 +- .../random_forest/random_forest_impl.hpp | 120 +++++++++--------- src/mlpack/tests/random_forest_test.cpp | 6 +- 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index fa91edd1ef..8d9ff4669b 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -37,10 +37,10 @@ namespace tree { * @endcode */ template class NumericSplitType = BestBinaryNumericSplit, - template class CategoricalSplitType = AllCategoricalSplit> + template class CategoricalSplitType = AllCategoricalSplit, + bool UseBootstrap = true> class RandomForest { public: diff --git a/src/mlpack/methods/random_forest/random_forest_impl.hpp b/src/mlpack/methods/random_forest/random_forest_impl.hpp index 970c57d3c0..e3ff9fb61d 100644 --- a/src/mlpack/methods/random_forest/random_forest_impl.hpp +++ b/src/mlpack/methods/random_forest/random_forest_impl.hpp @@ -20,17 +20,17 @@ namespace tree { template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::RandomForest() : avgGain(0.0) { @@ -39,18 +39,18 @@ RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::RandomForest(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -71,18 +71,18 @@ RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::RandomForest(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -103,18 +103,18 @@ RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::RandomForest(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -135,18 +135,18 @@ RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::RandomForest(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -167,18 +167,18 @@ RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template double RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Train(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -199,18 +199,18 @@ double RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template double RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Train(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -231,18 +231,18 @@ double RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template double RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Train(const MatType& dataset, const arma::Row& labels, const size_t numClasses, @@ -263,18 +263,18 @@ double RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template double RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Train(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, @@ -295,18 +295,18 @@ double RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template size_t RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Classify(const VecType& point) const { // Pass off to another Classify() overload. @@ -319,18 +319,18 @@ size_t RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template void RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Classify(const VecType& point, size_t& prediction, arma::vec& probabilities) const @@ -366,18 +366,18 @@ void RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template void RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Classify(const MatType& data, arma::Row& predictions) const { @@ -401,18 +401,18 @@ void RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template void RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Classify(const MatType& data, arma::Row& predictions, arma::mat& probabilities) const @@ -439,18 +439,18 @@ void RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template void RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::serialize(Archive& ar, const uint32_t /* version */) { size_t numTrees; @@ -471,18 +471,18 @@ void RandomForest< template< typename FitnessFunction, - bool UseBootstrap, typename DimensionSelectionType, template class NumericSplitType, - template class CategoricalSplitType + template class CategoricalSplitType, + bool UseBootstrap > template double RandomForest< FitnessFunction, - UseBootstrap, DimensionSelectionType, NumericSplitType, - CategoricalSplitType + CategoricalSplitType, + UseBootstrap >::Train(const MatType& dataset, const data::DatasetInfo& datasetInfo, const arma::Row& labels, diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index e5c6b10004..62592c0907 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -409,13 +409,13 @@ TEST_CASE("RandomForestNumericTrainReturnEntropy", "[RandomForestTest]") weights[i] = math::Random(0.0, 0.01); // Low weights for false points. // Test random forest on unweighted numeric dataset. - RandomForest rf; + RandomForest rf; double entropy = rf.Train(dataset, labels, 3, 10, 1); REQUIRE(std::isfinite(entropy) == true); // Test random forest on weighted numeric dataset. - RandomForest wrf; + RandomForest wrf; entropy = wrf.Train(dataset, labels, 3, weights, 10, 1); REQUIRE(std::isfinite(entropy) == true); @@ -488,7 +488,7 @@ TEST_CASE("DifferentTreesTest", "[RandomForestTest]") // multiple trials. while (!success && trial < 5) { - RandomForest rf; + RandomForest rf; rf.Train(d, l, 2, 2, 5); success = (rf.Tree(0).SplitDimension() != rf.Tree(1).SplitDimension()); From 22eb09e5d4811b34b57f61e6feb23b8d3c50b6fc Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 23 Apr 2021 22:10:38 -0400 Subject: [PATCH 212/729] Don't build mlpack_test as part of make. --- HISTORY.md | 3 +++ README.md | 8 +++++++- doc/guide/build.hpp | 24 ++++++++++++++---------- src/mlpack/tests/CMakeLists.txt | 1 + 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 2f7aab9538..528c1746f5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -46,6 +46,9 @@ * Fix Python binding build when the CMake variable `USE_OPENMP` is set to `OFF` (#2884). + * The `mlpack_test` target is no longer built as part of `make all`. Use + `make mlpack_test` to build the tests. + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. diff --git a/README.md b/README.md index 21b9e09e7e..b8fffc8ca8 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,7 @@ also be built. OpenMP will be used for parallelization when possible by default. Once CMake is configured, building the library is as simple as typing 'make'. -This will build all library components as well as 'mlpack_test'. +This will build all library components and bindings. $ make @@ -243,6 +243,12 @@ of the build can be specified: $ make mlpack_pca mlpack_knn mlpack_kfn +If you want to build the tests, just make the `mlpack_test` target, and use +`ctest` to run the tests: + + $ make mlpack_test + $ ctest . + If the build fails and you cannot figure out why, register an account on Github and submit an issue. The mlpack developers will quickly help you figure it out: diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index 9356f725cc..a87fe8fe1f 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -170,7 +170,8 @@ The full list of options mlpack allows: - PROFILE=(ON/OFF): compile with profiling symbols (default OFF) - ARMA_EXTRA_DEBUG=(ON/OFF): compile with extra Armadillo debugging symbols (default OFF) - - BUILD_TESTS=(ON/OFF): compile the \c mlpack_test program (default ON) + - BUILD_TESTS=(ON/OFF): compile the \c mlpack_test program when `make` is run + (default ON) - BUILD_CLI_EXECUTABLES=(ON/OFF): compile the mlpack command-line executables (i.e. \c mlpack_knn, \c mlpack_kfn, \c mlpack_logistic_regression, etc.) (default ON) @@ -225,14 +226,10 @@ and libraries. These also use the '-D' flag. @section build_build Building mlpack Once CMake is configured, building the library is as simple as typing 'make'. -This will build all library components as well as 'mlpack_test'. +This will build all library components. @code $ make -Scanning dependencies of target mlpack -[ 1%] Building CXX object -src/mlpack/CMakeFiles/mlpack.dir/core/optimizers/aug_lagrangian/aug_lagrangian_test_functions.cpp.o -<...> @endcode It's often useful to specify \c -jN to the \c make command, which will build on @@ -247,17 +244,24 @@ $ make mlpack_pca mlpack_knn mlpack_kfn @endcode One particular component of interest is mlpack_test, which runs the mlpack test -suite. You can build this component with +suite. This is not built when @c make is run. You can build this component +with @code $ make mlpack_test @endcode We use Catch2 to write our tests. -To run all tests, you can simply run: +To run all tests, you can simply use CTest: @code -$ ./bin/mlpack_test +$ ctest . +@endcode + +Or, you can run the test suite manually: + +@code +$ bin/mlpack_test @endcode To run all tests in a particular file you can run: @@ -266,7 +270,7 @@ To run all tests in a particular file you can run: $ ./bin/mlpack_test "[testname]" @endcode -where testname is the name of the test suite. +where testname is the name of the test suite. For example to run all collaborative filtering tests implemented in cf_test.cpp you can run: @code diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index de0f56d8df..b6d4b937cc 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -1,5 +1,6 @@ # mlpack test executable. add_executable(mlpack_test + EXCLUDE_FROM_ALL activation_functions_test.cpp adaboost_test.cpp akfn_test.cpp From 6ed9384746fee65de718fb1cbfe8303d10889ba3 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 24 Apr 2021 11:57:01 +0530 Subject: [PATCH 213/729] Add typedef for ExtraTrees --- .../methods/random_forest/random_forest.hpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 8d9ff4669b..9eaa4a5429 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -410,6 +410,38 @@ class RandomForest double avgGain; }; +/** + * Convenience typedef for Extra Trees. (Extremely Randomised Trees Forest) + * + * @code + * @article{10.1007/s10994-006-6226-1, + * author = {Geurts, Pierre and Ernst, Damien and Wehenkel, Louis}, + * title = {Extremely Randomized Trees}, + * year = {2006}, + * issue_date = {April 2006}, + * publisher = {Kluwer Academic Publishers}, + * address = {USA}, + * volume = {63}, + * number = {1}, + * issn = {0885-6125}, + * url = {https://doi.org/10.1007/s10994-006-6226-1}, + * doi = {10.1007/s10994-006-6226-1}, + * journal = {Mach. Learn.}, + * month = apr, + * pages = {3–42}, + * numpages = {40}, + * } + * @endcode + */ +template class CategoricalSplitType = AllCategoricalSplit> +using ExtraTrees = RandomForest; + } // namespace tree } // namespace mlpack From 185d79568039720a3e662b902829d337cdcfb5e7 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 24 Apr 2021 11:57:43 +0530 Subject: [PATCH 214/729] Add test ensuring high accuracy on iris classification task. --- src/mlpack/tests/random_forest_test.cpp | 51 +++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 62592c0907..6ec820777c 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -558,3 +558,54 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") REQUIRE(newCorrect - oldCorrect >= 0); } + +/** + * Ensure that the Extra Trees algorithm gives decent accuracy. + */ +TEST_CASE("ExtraTreesAccuracyTest", "[RandomForestTest]") +{ + // Load the vc2 dataset. + arma::mat dataset; + if (!data::Load("iris_train.csv", dataset)) + FAIL("Cannot load dataset iris_train.csv"); + arma::Row labels; + if (!data::Load("iris_train_labels.csv", labels)) + FAIL("Cannot load dataset iris_train_labels.csv"); + + // Add some noise. + arma::mat noise(dataset.n_rows, 1000, arma::fill::randu); + arma::Row noiseLabels(1000); + for (size_t i = 0; i < noiseLabels.n_elem; ++i) + noiseLabels[i] = math::RandInt(3); // Random label. + + // Concatenate data matrices. + arma::mat data = arma::join_rows(dataset, noise); + arma::Row fullLabels = arma::join_rows(labels, noiseLabels); + + // Now set weights. + arma::rowvec weights(dataset.n_cols + 1000); + for (size_t i = 0; i < dataset.n_cols; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = dataset.n_cols; i < dataset.n_cols + 1000; ++i) + weights[i] = math::Random(0.0, 0.01); // Low weights for false points. + + // Train extra tree. + ExtraTrees<> et(data, fullLabels, 3, weights, 20, 1); + + // Get performance statistics on test data. + arma::mat testDataset; + if (!data::Load("iris_test.csv", testDataset)) + FAIL("Cannot load dataset iris_test.csv"); + arma::Row testLabels; + if (!data::Load("iris_test_labels.csv", testLabels)) + FAIL("Cannot load dataset iris_test_labels.csv"); + + arma::Row predictions; + et.Classify(testDataset, predictions); + + // Calculate the prediction accuracy. + double accuracy = arma::accu(predictions == testLabels); + accuracy /= predictions.n_elem; + + REQUIRE(accuracy >= 0.94); +} From eb80b2da5ed340464d89690ab89c7d83bb5b0782 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 24 Apr 2021 14:27:52 +0200 Subject: [PATCH 215/729] The Autodownloader. This pull request provides the Autodownloader for mlpack dependencies. It can be used with current and future dependencies. This one is born from working with #2531, with help from @rcurtin and @zoq. It is ready to merge, with minor reviews are always welcome. Signed-off-by: Omar Shrit --- CMake/Autodownload.cmake | 56 ++++++++++ CMakeLists.txt | 220 +++++++++++++++------------------------ 2 files changed, 140 insertions(+), 136 deletions(-) create mode 100644 CMake/Autodownload.cmake diff --git a/CMake/Autodownload.cmake b/CMake/Autodownload.cmake new file mode 100644 index 0000000000..b82ab001b9 --- /dev/null +++ b/CMake/Autodownload.cmake @@ -0,0 +1,56 @@ +## This function auto-downloads mlpack dependencies. +## You need to pass the LINK to download from, the name of +## the dependency, and the name of the compressed package such as +## armadillo.tar.gz +## At each download, this module sets a GENERIC_INCLUDE_DIR path, +## which means that you need to set the main path for the include +## directories for each package. +## Note that, the package should be compressed only as .tar.gz + +macro(get_deps LINK DEPS_NAME PACKAGE) + if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/${PACKAGE}") + file(DOWNLOAD ${LINK} + "${CMAKE_BINARY_DIR}/deps/${PACKAGE}" + STATUS DOWNLOAD_STATUS_LIST LOG DOWNLOAD_LOG + SHOW_PROGRESS) + list(GET DOWNLOAD_STATUS_LIST 0 DOWNLOAD_STATUS) + if (DOWNLOAD_STATUS EQUAL 0) + execute_process(COMMAND ${CMAKE_COMMAND} -E + tar xf "${CMAKE_BINARY_DIR}/deps/${PACKAGE}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps/") + else () + list(GET DOWNLOAD_STATUS_LIST 1 DOWNLOAD_ERROR) + message(FATAL_ERROR + "Could not download ${DEPS_NAME}! Error code ${DOWNLOAD_STATUS}: ${DOWNLOAD_ERROR}! Error log: ${DOWNLOAD_LOG}") + endif() + endif() + # Get the name of the directory. + file (GLOB DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/" + "${CMAKE_BINARY_DIR}/deps/${DEPS_NAME}*.*") + # Clean this line when boost is removed. + if (${DEPS_NAME} MATCHES "boost") + file (GLOB DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/" + "${CMAKE_BINARY_DIR}/deps/${DEPS_NAME}*_*") + elseif(${DEPS_NAME} MATCHES "stb") + file (GLOB DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/" + "${CMAKE_BINARY_DIR}/deps/${DEPS_NAME}") + endif() + # list(FILTER) is not available on 3.5 or older, but try to keep + # configuring without filtering the list anyway + # (it works only if the file is present as .tar.gz). + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.6.0") + list(FILTER DIRECTORIES EXCLUDE REGEX ".*\.tar\.gz") + endif () + list(LENGTH DIRECTORIES DIRECTORIES_LEN) + if (DIRECTORIES_LEN GREATER 0) + list(GET DIRECTORIES 0 DEPENDENCY_DIR) + set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") + # Clean this line when boost is removed. + if (${DEPS_NAME} MATCHES "boost") + set(Boost_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/") + endif() + else () + message(FATAL_ERROR + "Problem unpacking ${DEPS_NAME}! Expected only one directory ${DEPS_NAME};. Try to remove the directory ${CMAKE_BINARY_DIR}/deps and reconfigure.") + endif () +endmacro() diff --git a/CMakeLists.txt b/CMakeLists.txt index 0aa70cb74a..588952a236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(mlpack C CXX) include(CMake/cotire.cmake) include(CMake/CheckHash.cmake) +include(CMake/Autodownload.cmake) # First, define all the compilation options. # We default to debugging mode for developers. @@ -24,15 +25,26 @@ set(ENSMALLEN_VERSION "2.10.0") set(BOOST_VERSION "1.58") set(CEREAL_VERSION "1.1.2") +# If BUILD_SHARED_LIBS is OFF then the mlpack library will be built statically. +# In addition, all mlpack CLI bindings will be linked statically as well. if (WIN32) option(BUILD_SHARED_LIBS - "Compile shared libraries (if OFF, static libraries are compiled)." OFF) + "Compile shared libraries (if OFF, static libraries and binaries are compiled)." OFF) set(DLL_COPY_DIRS "" CACHE STRING "List of directories (separated by ';') containing DLLs to copy for runtime.") set(DLL_COPY_LIBS "" CACHE STRING "List of DLLs (separated by ';') that should be copied for runtime.") -else () +else() option(BUILD_SHARED_LIBS - "Compile shared libraries (if OFF, static libraries are compiled)." ON) + "Compile shared libraries (if OFF, static libraries and binaries are compiled)." ON) +endif() + +# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES. +if (NOT BUILD_SHARED_LIBS) + if(WIN32) + list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + endif() endif() # Detect whether the user passed BUILD_PYTHON_BINDINGS in order to determine if @@ -93,12 +105,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # Include modules in the CMake directory. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake") -# Disable any downloads if needed. -if (DISABLE_DOWNLOADS) - set(DOWNLOAD_ENSMALLEN OFF) - set(DOWNLOAD_STB_IMAGE OFF) -endif () - # If we are on a Unix-like system, use the GNU install directories module. # Otherwise set the values manually. if (UNIX) @@ -112,12 +118,12 @@ else () endif () # This is as of yet unused. -#option(PGO "Use profile-guided optimization if not a debug build" ON) +# option(PGO "Use profile-guided optimization if not a debug build" ON) # Set the CFLAGS and CXXFLAGS depending on the options the user specified. # Only GCC-like compilers support -Wextra, and other compilers give tons of # output for -Wall, so only -Wall and -Wextra on GCC. -if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") +if (CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # Ensure that we can't compile with clang 3.4, since this causes strange # issues. if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) @@ -144,7 +150,7 @@ endif () # If we are using MINGW, we need sections and big-obj, otherwise we create too # many sections. -if(CMAKE_COMPILER_IS_GNUCC AND WIN32) +if (CMAKE_COMPILER_IS_GNUCC AND WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections -Wa,-mbig-obj") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wa,-mbig-obj") endif() @@ -153,7 +159,7 @@ endif() # OS (at least on some systems). Further, gcc sometimes optimizes calls to # math.h functions, making -lm unnecessary with gcc, but it may still be # necessary with clang. -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if (APPLE) # Detect OS X version. Use '/usr/bin/sw_vers -productVersion' to # extract V from '10.V.x'. @@ -166,7 +172,7 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # OSX Lion (10.7) and OS X Mountain Lion (10.8) doesn't automatically # select the right stdlib. - if(${MACOSX_VERSION} LESS 9) + if (${MACOSX_VERSION} LESS 9) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++") @@ -187,14 +193,14 @@ endif() # If we're using gcc, then we need to link against pthreads to use std::thread, # which we do in the tests. -if(CMAKE_COMPILER_IS_GNUCC) +if (CMAKE_COMPILER_IS_GNUCC) find_package(Threads) set(COMPILER_SUPPORT_LIBRARIES ${COMPILER_SUPPORT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) endif() # Debugging CFLAGS. Turn optimizations off; turn debugging symbols on. -if(DEBUG) +if (DEBUG) if (NOT MSVC) add_definitions(-DDEBUG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -ftemplate-backtrace-limit=0") @@ -203,10 +209,10 @@ if(DEBUG) # mlpack uses it's own mlpack::backtrace class based on Binary File Descriptor # and linux Dynamic Loader and more portable version in future - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") find_package(Bfd) find_package(LibDL) - if(LIBBFD_FOUND AND LIBDL_FOUND) + if (LIBBFD_FOUND AND LIBDL_FOUND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic") set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${LIBBFD_INCLUDE_DIRS} ${LIBDL_INCLUDE_DIRS}) @@ -230,19 +236,19 @@ else() endif() # Profiling CFLAGS. Turn profiling information on. -if(CMAKE_COMPILER_IS_GNUCC AND PROFILE) +if (CMAKE_COMPILER_IS_GNUCC AND PROFILE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") endif() # If the user asked for running test cases with verbose output, turn that on. -if(TEST_VERBOSE) +if (TEST_VERBOSE) add_definitions(-DTEST_VERBOSE) endif() # If the user asked for extra Armadillo debugging output, turn that on. -if(ARMA_EXTRA_DEBUG) +if (ARMA_EXTRA_DEBUG) add_definitions(-DARMA_EXTRA_DEBUG) endif() @@ -254,137 +260,72 @@ endif() # ARMADILLO_INCLUDE_DIRS - directories necessary for Armadillo includes # BOOST_ROOT - root of Boost installation # BOOST_INCLUDEDIR - include directory for Boost +# CEREAL_INCLUDE_DIR - include directory for cereal # ENSMALLEN_INCLUDE_DIR - include directory for ensmallen # STB_IMAGE_INCLUDE_DIR - include directory for STB image library # MATHJAX_ROOT - root of MathJax installation -find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED) +if (DISABLE_DOWNLOADS) + find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED) +else() + find_package(Armadillo "${ARMADILLO_VERSION}") + if (NOT ARMADILLO_FOUND) + get_deps(http://files.mlpack.org/armadillo-10.3.0.tar.gz armadillo armadillo-10.3.0.tar.gz) + set(ARMADILLO_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) + find_package(Armadillo REQUIRED) + endif() +endif() # Include directories for the previous dependencies. set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS}) set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${ARMADILLO_LIBRARIES}) # Find stb_image.h and stb_image_write.h. -find_package(StbImage) -# Download stb_image for image loading. -if (NOT STB_IMAGE_FOUND) - if (DOWNLOAD_STB_IMAGE) - set(STB_DIR "stb") - install(DIRECTORY DESTINATION "${CMAKE_BINARY_DIR}/deps/${STB_DIR}") - file(DOWNLOAD http://mlpack.org/files/stb-2.22/stb_image.h - "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image.h" - STATUS STB_IMAGE_DOWNLOAD_STATUS_LIST LOG STB_IMAGE_DOWNLOAD_LOG - SHOW_PROGRESS) - list(GET STB_IMAGE_DOWNLOAD_STATUS_LIST 0 STB_IMAGE_DOWNLOAD_STATUS) - file(DOWNLOAD http://mlpack.org/files/stb-1.13/stb_image_write.h - "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image_write.h" - STATUS STB_IMAGE_WRITE_DOWNLOAD_STATUS_LIST - LOG STB_IMAGE_WRITE_DOWNLOAD_LOG - SHOW_PROGRESS) - list(GET STB_IMAGE_WRITE_DOWNLOAD_STATUS_LIST 0 - STB_IMAGE_WRITE_DOWNLOAD_STATUS) - if (STB_IMAGE_DOWNLOAD_STATUS EQUAL 0 AND - STB_IMAGE_WRITE_DOWNLOAD_STATUS EQUAL 0) - check_hash (http://mlpack.org/files/stb/hash.md5 "${CMAKE_BINARY_DIR}/deps/${STB_DIR}" - HASH_CHECK_FAIL) - if (HASH_CHECK_FAIL EQUAL 0) - set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} - "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/") - message(STATUS - "Successfully downloaded stb into ${CMAKE_BINARY_DIR}/deps/${STB_DIR}/") - # Now we have to also ensure these header files get installed. - install(FILES "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") - install(FILES "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image_write.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") - add_definitions(-DHAS_STB) - set(STB_AVAILABLE "1") - else () - message(WARNING - "stb/stb_image.h is not installed. Image utilities will not be available!") - endif () - else () - file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/") - list(GET STB_IMAGE_DOWNLOAD_STATUS_LIST 1 STB_DOWNLOAD_ERROR) - message(WARNING - "Could not download stb! Error code ${STB_DOWNLOAD_STATUS}: ${STB_DOWNLOAD_ERROR}! Error log: ${STB_DOWNLOAD_LOG}") - message(WARNING - "stb/stb_image.h is not installed. Image utilities will not be available!") - endif () - else () - message(WARNING - "stb/stb_image.h is not installed. Image utilities will not be available!") - endif () -else () - # Already has STB installed. +if (DISABLE_DOWNLOADS) + find_package(StbImage) +else() + find_package(StbImage) + if (NOT STB_IMAGE_FOUND) + get_deps(http://mlpack.org/files/stb.tar.gz stb stb.tar.gz) + set(STB_IMAGE_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) + find_package(StbImage REQUIRED) + endif() +endif() + +if (STB_IMAGE_FOUND) add_definitions(-DHAS_STB) - set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${STB_IMAGE_INCLUDE_DIR}) set(STB_AVAILABLE "1") -endif () +endif() +set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${STB_IMAGE_INCLUDE_DIR}") # Find ensmallen. -# Once ensmallen is readily available in package repos, the automatic downloader -# here can be removed. -find_package(Ensmallen "${ENSMALLEN_VERSION}") -if (NOT ENSMALLEN_FOUND) - if (DOWNLOAD_ENSMALLEN) - file(DOWNLOAD http://www.ensmallen.org/files/ensmallen-latest.tar.gz - "${CMAKE_BINARY_DIR}/deps/ensmallen-latest.tar.gz" - STATUS ENS_DOWNLOAD_STATUS_LIST LOG ENS_DOWNLOAD_LOG - SHOW_PROGRESS) - list(GET ENS_DOWNLOAD_STATUS_LIST 0 ENS_DOWNLOAD_STATUS) - if (ENS_DOWNLOAD_STATUS EQUAL 0) - execute_process(COMMAND ${CMAKE_COMMAND} -E - tar xzf "${CMAKE_BINARY_DIR}/deps/ensmallen-latest.tar.gz" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps/") +if (DISABLE_DOWNLOADS) + find_package(Ensmallen "${ENSMALLEN_VERSION}" REQUIRED) +else() + find_package(Ensmallen "${ENSMALLEN_VERSION}") + if (NOT ENSMALLEN_FOUND) + get_deps(http://www.ensmallen.org/files/ensmallen-latest.tar.gz ensmallen ensmallen-latest.tar.gz) + set(ENSMALLEN_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) + find_package(Ensmallen REQUIRED) + endif() +endif() +set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${ENSMALLEN_INCLUDE_DIR}") - # Get the name of the directory. - file (GLOB ENS_DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/" - "${CMAKE_BINARY_DIR}/deps/ensmallen-[0-9]*.[0-9]*.[0-9]*") - # list(FILTER) is not available on 3.5 or older, but try to keep - # configuring without filtering the list anyway (it might work if only - # the file ensmallen-latest.tar.gz is present. - if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.6.0") - list(FILTER ENS_DIRECTORIES EXCLUDE REGEX "ensmallen-.*\.tar\.gz") - endif () - list(LENGTH ENS_DIRECTORIES ENS_DIRECTORIES_LEN) - if (ENS_DIRECTORIES_LEN EQUAL 1) - list(GET ENS_DIRECTORIES 0 ENSMALLEN_INCLUDE_DIR) - set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} - "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include") - message(STATUS - "Successfully downloaded ensmallen into ${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/") - - # Now we have to also ensure these header files get installed. - install(DIRECTORY "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen_bits/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ensmallen_bits") - install(FILES "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") - else () - message(FATAL_ERROR "Problem unpacking ensmallen! Expected only one directory ensmallen-x.y.z/; found ${ENS_DIRECTORIES}. Try removing the directory ${CMAKE_BINARY_DIR}/deps and reconfiguring.") - endif () - else () - list(GET ENS_DOWNLOAD_STATUS_LIST 1 ENS_DOWNLOAD_ERROR) - message(FATAL_ERROR - "Could not download ensmallen! Error code ${ENS_DOWNLOAD_STATUS}: ${ENS_DOWNLOAD_ERROR}! Error log: ${ENS_DOWNLOAD_LOG}") - endif () - else () - # Release versions will have ensmallen packaged with the release so we can - # just reference that. - if (EXISTS "${CMAKE_SOURCE_DIR}/src/mlpack/core/optimizers/ensmallen/ensmallen.hpp") - set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS} - "${CMAKE_SOURCE_DIR}/src/mlpack/core/optimizers/ensmallen") - else () - message(FATAL_ERROR - "Cannot find ensmallen headers! Try setting ENSMALLEN_INCLUDE_DIR!") - endif () - endif () -else () - set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${ENSMALLEN_INCLUDE_DIR}") -endif () - -find_package(cereal "${CEREAL_VERSION}" REQUIRED) +# Find cereal. +if (DISABLE_DOWNLOADS) + find_package(cereal "${CEREAL_VERSION}" REQUIRED) +else() + find_package(cereal "${CEREAL_VERSION}") + if (NOT CEREAL_FOUND) + get_deps(https://github.com/USCiLab/cereal/archive/refs/tags/v1.3.0.tar.gz cereal cereal-1.3.0.tar.gz) + set(CEREAL_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) + find_package(cereal REQUIRED) + endif() +endif() set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${CEREAL_INCLUDE_DIR}) # Unfortunately this configuration variable is necessary and will need to be # updated as time goes on and new versions are released. set(Boost_ADDITIONAL_VERSIONS - "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" @@ -409,8 +350,15 @@ set(Boost_ADDITIONAL_VERSIONS # TODO for the brave: transition all mlpack's CMake to 'target-based modern # CMake'. Good luck! You'll need it. set(Boost_NO_BOOST_CMAKE 1) -find_package(Boost "${BOOST_VERSION}") - +if (DISABLE_DOWNLOADS) + find_package(Boost "${BOOST_VERSION}" REQUIRED) +else() + find_package(Boost "${BOOST_VERSION}") + if (NOT Boost_FOUND) + get_deps(https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.gz boost boost_1_75_0.tar.gz) + find_package(Boost REQUIRED) + endif() +endif() set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES}) set(MLPACK_LIBRARY_DIRS ${MLPACK_LIBRARY_DIRS}) @@ -433,7 +381,7 @@ if (OPENMP_FOUND) add_definitions(-DHAS_OPENMP) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - if(OpenMP_CXX_FOUND) + if (OpenMP_CXX_FOUND) set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${OpenMP_CXX_LIBRARIES}) endif () else () From 0020da5715e51b65be9b58a620a736c6c2e61a2d Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 24 Apr 2021 14:31:37 +0200 Subject: [PATCH 216/729] Update boost version oops. Signed-off-by: Omar Shrit --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 588952a236..9a2c55aaa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,7 @@ set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${CEREAL_INCLUDE_DIR}) # Unfortunately this configuration variable is necessary and will need to be # updated as time goes on and new versions are released. set(Boost_ADDITIONAL_VERSIONS + "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" From fb2bdbe15938ae43239e674bc495b62988d34aaf Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 24 Apr 2021 14:48:21 +0200 Subject: [PATCH 217/729] Download all boost instead of a specific version. Signed-off-by: Omar Shrit --- .ci/linux-steps.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/linux-steps.yaml b/.ci/linux-steps.yaml index f695c14fe1..18cd645043 100644 --- a/.ci/linux-steps.yaml +++ b/.ci/linux-steps.yaml @@ -21,7 +21,7 @@ steps: unset BOOST_ROOT echo "##vso[task.setvariable variable=BOOST_ROOT]"$BOOST_ROOT - sudo apt-get install -y --allow-unauthenticated libopenblas-dev g++ libboost1.70-dev xz-utils + sudo apt-get install -y --allow-unauthenticated libopenblas-dev g++ libboost-all-dev xz-utils if [ "$(binding)" == "python" ]; then export PYBIN=$(which python) @@ -41,7 +41,7 @@ steps: # Install cereal. wget https://github.com/USCiLab/cereal/archive/v1.3.0.tar.gz tar -xvzpf v1.3.0.tar.gz # Unpack into cereal-1.3.0/. - cd cereal-1.3.0/ + displayName: 'Install Build Dependencies' # Configure mlpack (CMake) From e89909cd6c695f5bf7dbe6b9ee23d0ac2ad528b5 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 24 Apr 2021 10:56:19 -0400 Subject: [PATCH 218/729] Explicitly build the tests. --- .ci/linux-steps.yaml | 4 ++-- .ci/macos-steps.yaml | 4 ++-- .ci/windows-steps.yaml | 1 + .github/workflows/main.yml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.ci/linux-steps.yaml b/.ci/linux-steps.yaml index f695c14fe1..9cec6f41ee 100644 --- a/.ci/linux-steps.yaml +++ b/.ci/linux-steps.yaml @@ -56,12 +56,12 @@ steps: displayName: 'CMake' # Build mlpack -- script: cd build && make +- script: cd build && make && make mlpack_test condition: eq(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF') displayName: 'Build' # Build mlpack -- script: cd build && make -j2 +- script: cd build && make -j2 && make -j2 mlpack_test condition: ne(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF') displayName: 'Build' diff --git a/.ci/macos-steps.yaml b/.ci/macos-steps.yaml index ce3c7796f5..48b15863a9 100644 --- a/.ci/macos-steps.yaml +++ b/.ci/macos-steps.yaml @@ -45,7 +45,7 @@ steps: displayName: 'CMake' # Build mlpack -- script: cd build && make -j2 +- script: cd build && make -j2 && make -j2 mlpack_test displayName: 'Build' # Run tests via ctest. @@ -65,4 +65,4 @@ steps: inputs: pathtoPublish: 'build/Testing/' artifactName: 'Tests' - displayName: 'Publish artifacts test results' \ No newline at end of file + displayName: 'Publish artifacts test results' diff --git a/.ci/windows-steps.yaml b/.ci/windows-steps.yaml index e2a9ed38e0..a6793997e6 100644 --- a/.ci/windows-steps.yaml +++ b/.ci/windows-steps.yaml @@ -88,6 +88,7 @@ steps: # Run tests via ctest. - bash: | cd build + cmake --build . --target mlpack_test -C Release CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test -C Release . -j1 displayName: 'Run tests via ctest' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9fa25191a6..a9a2574072 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -68,7 +68,7 @@ jobs: - name: Build run: | - cd build && make -j2 + cd build && make -j2 && make -j2 mlpack_test - name: Run tests via ctest run: | From f1a01df3001ddbda146efb5047b9079894940fb7 Mon Sep 17 00:00:00 2001 From: fawwazmayda Date: Sun, 25 Apr 2021 00:29:31 +0800 Subject: [PATCH 219/729] adding new silu function fixing indentation fixing style error Update silu_function.hpp --- .../ann/activation_functions/CMakeLists.txt | 1 + .../activation_functions/silu_function.hpp | 96 +++++++++++++++++++ src/mlpack/methods/ann/layer/base_layer.hpp | 14 +++ .../tests/activation_functions_test.cpp | 23 +++++ 4 files changed, 134 insertions(+) create mode 100644 src/mlpack/methods/ann/activation_functions/silu_function.hpp diff --git a/src/mlpack/methods/ann/activation_functions/CMakeLists.txt b/src/mlpack/methods/ann/activation_functions/CMakeLists.txt index 1639817716..98b03e0a91 100644 --- a/src/mlpack/methods/ann/activation_functions/CMakeLists.txt +++ b/src/mlpack/methods/ann/activation_functions/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES gaussian_function.hpp hard_swish_function.hpp tanh_exponential_function.hpp + silu_function.hpp ) # Add directory name to sources. diff --git a/src/mlpack/methods/ann/activation_functions/silu_function.hpp b/src/mlpack/methods/ann/activation_functions/silu_function.hpp new file mode 100644 index 0000000000..0c063a5b59 --- /dev/null +++ b/src/mlpack/methods/ann/activation_functions/silu_function.hpp @@ -0,0 +1,96 @@ +/** + * @file methods/ann/activation_functions/silu_function.hpp + * @author Fawwaz Mayda + * + * Definition and implementation of the Sigmoid Weighted Linear Unit function (SILU). + * + * For more information see the following paper + * + * @code + * @misc{elfwing2017sigmoidweighted , + * title = {Sigmoid-Weighted Linear Units for Neural Network Function Approximation in Reinforcement Learning}, + * author = {Stefan Elfwing and Eiji Uchibe and Kenji Doya}, + * year = {2017}, + * url = {https://arxiv.org/pdf/1702.03118.pdf}, + * eprint = {1702.03118}, + * archivePrefix = {arXiv}, + * primaryClass = {cs.LG} } + * @endcode + * + * 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_ACTIVATION_FUNCTIONS_SILU_FUNCTION_HPP +#define MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_SILU_FUNCTION_HPP + +#include + +namespace mlpack { +namespace ann /* Artificial Neural Network */ { + +/** + * The SILU function, defined by + * + * @f{eqnarray*}{ + * f(x) &=& x * \frac{1}{1 + e^{-x}}\\ + * f'(x) &=& \frac{1}{1 + e^{-x}} * (1 + x * (1-\frac{1}{1 + e^{-x}}))\\ + * @f} + */ +class SILUFunction +{ + public: + /** + * Computes the SILU function. + * + * @param x Input data. + * @return f(x). + */ + static double Fn(const double x) + { + return x / (1.0 + std::exp(-x)); + } + + /** + * Computes the SILU function. + * + * @param x Input data. + * @param y The resulting output activation. + */ + template + static void Fn(const InputVecType &x, OutputVecType &y) + { + y = x / (1.0 + arma::exp(-x)); + } + + /** + * Computes the first derivative of the SILU function. + * + * @param y Input activation. + * @return f'(x) + */ + static double Deriv(const double x) + { + double sigmoid = 1.0 / (1.0 + std::exp(-x)); + return sigmoid * (1.0 + x * (1.0 - sigmoid)); + } + + /** + * Computes the first derivatives of the SILU function. + * + * @param y Input activations. + * @param x The resulting derivatives. + */ + template + static void Deriv(const InputVecType &x, OutputVecType &y) + { + OutputVecType sigmoid = 1.0 / (1.0 + arma::exp(-x)); + y = sigmoid % (1.0 + x % (1.0 - sigmoid)); + } +}; // class SILUFunction + +} // namespace ann +} // namespace mlpack + +#endif \ No newline at end of file diff --git a/src/mlpack/methods/ann/layer/base_layer.hpp b/src/mlpack/methods/ann/layer/base_layer.hpp index 7169d5f474..9c6bd19478 100644 --- a/src/mlpack/methods/ann/layer/base_layer.hpp +++ b/src/mlpack/methods/ann/layer/base_layer.hpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace mlpack { namespace ann /** Artificial Neural Network. */ { @@ -54,6 +55,7 @@ namespace ann /** Artificial Neural Network. */ { * - GaussianLayer * - HardSwishLayer * - TanhExpLayer + * - SILULayer * * @tparam ActivationFunction Activation function used for the embedding layer. * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, @@ -303,6 +305,18 @@ template < using TanhExpFunctionLayer = BaseLayer< ActivationFunction, InputDataType, OutputDataType>; +/** + * Standard SILU-Layer using the SILU activation function. + */ +template < + class ActivationFunction = SILUFunction, + typename InputDataType = arma::mat, + typename OutputDataType = arma::mat +> +using SILUFunctionLayer = BaseLayer< + ActivationFunction, InputDataType,OutputDataType +>; + } // namespace ann } // namespace mlpack diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index 2ae2ea344d..a20b95c039 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include "catch.hpp" @@ -1241,3 +1242,25 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") CheckActivationCorrect(activationData, desiredActivations); CheckDerivativeCorrect(desiredActivations, desiredDerivatives); } + +/** + * Basic test of the SILU(Sigmoid Weighted Linear Unit) Function + */ +TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") +{ + // Random generated values. + const arma::colvec activationData("-2 2 4.5 -5.7 -1 1 0 10"); + + // Calculated with PyTorch. + arma::colvec desiredActivation("-0.23840583860874176 1.7615940570831299 4.450558662414551 \ + -0.01900840364396572 -0.2689414322376251 0.7310585975646973 \ + 0.0 9.99954605102539"); + + // Calculated with PyTorch. + arma::colvec desiredDerivate("0.38191673159599304 1.073788046836853 1.0392179489135742 \ + 0.49049633741378784 0.36713290214538574 0.8354039788246155 \ + 0.5 1.0004087686538696"); + + CheckActivationCorrect(activationData,desiredActivation); + CheckDerivativeCorrect(desiredActivation,desiredDerivate); +} From 06678129052afa1a91aa510949f8ba5536873d2e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 24 Apr 2021 18:41:59 +0200 Subject: [PATCH 220/729] Fix find armadillo by rcurtin. Authored-by: Ryan Curtin Signed-off-by: Omar Shrit --- CMake/FindArmadillo.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CMake/FindArmadillo.cmake b/CMake/FindArmadillo.cmake index c684963f70..3d696b0abb 100644 --- a/CMake/FindArmadillo.cmake +++ b/CMake/FindArmadillo.cmake @@ -77,13 +77,14 @@ else() # don't link to armadillo in this case set(ARMADILLO_LIBRARY "") endif() + # Link to support libraries in either case on MSVC. if(NOT _ARMA_USE_WRAPPER OR MSVC) if(_ARMA_USE_LAPACK) if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED) find_package(LAPACK QUIET) else() - find_package(LAPCK REQUIRED) + find_package(LAPACK REQUIRED) endif() if(LAPACK_FOUND) set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${LAPACK_LIBRARIES}") @@ -154,5 +155,6 @@ unset(__ARMA_SUPPORT_INCLUDE_DIRS) # Hide internal variables mark_as_advanced( - ARMADILLO_INCLUDE_DIR - ARMADILLO_LIBRARY) + ARMADILLO_INCLUDE_DIR + ARMADILLO_LIBRARY + ARMADILLO_LIBRARIES) From 74878b783ed963d2e96397cddfead26dea7acb05 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 24 Apr 2021 19:06:14 +0200 Subject: [PATCH 221/729] Fix cover tree issues by @rcurtin fixes #2869 This pull request closes #2869 and fixes all errors from cover tree when trying to put mlpack on arm64 devices. Thanks to @rcurtin to put all effort to resolve this one. Authored-by: Ryan Curtin Signed-off-by: Omar Shrit --- .../tree/cover_tree/dual_tree_traverser.hpp | 20 +++--- .../cover_tree/dual_tree_traverser_impl.hpp | 62 +++++++++---------- .../cover_tree/single_tree_traverser_impl.hpp | 18 +++--- src/mlpack/tests/akfn_test.cpp | 1 - src/mlpack/tests/krann_search_test.cpp | 3 +- 5 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index 804c647e58..ebc6729fdc 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -87,19 +87,23 @@ class CoverTree:: * Helper function for traversal of the two trees. */ void Traverse(CoverTree& queryNode, - std::map >& - referenceMap); + std::map, + std::greater>& referenceMap); //! Prepare map for recursion. void PruneMap(CoverTree& queryNode, - std::map >& - referenceMap, - std::map >& - childMap); + std::map, + std::greater>& referenceMap, + std::map, + std::greater>& childMap); void ReferenceRecursion(CoverTree& queryNode, - std::map >& - referenceMap); + std::map, + std::greater>& referenceMap); }; } // namespace tree diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp index 5e29d09fca..cde21d8a75 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp @@ -43,7 +43,7 @@ DualTreeTraverser::Traverse(CoverTree& queryNode, CoverTree& referenceNode) { // Start by creating a map and adding the reference root node to it. - std::map > refMap; + std::map, std::greater> refMap; DualCoverTreeMapEntry rootRefEntry; @@ -70,7 +70,8 @@ template void CoverTree:: DualTreeTraverser::Traverse( CoverTree& queryNode, - std::map >& referenceMap) + std::map, std::greater>& + referenceMap) { if (referenceMap.size() == 0) return; // Nothing to do! @@ -85,7 +86,7 @@ DualTreeTraverser::Traverse( // Now, reduce the scale of the query node by recursing. But we can't recurse // if the query node is a leaf node. if ((queryNode.Scale() != INT_MIN) && - (queryNode.Scale() >= (*referenceMap.rbegin()).first)) + (queryNode.Scale() >= (*referenceMap.begin()).first)) { // Recurse into the non-self-children first. The recursion order cannot // affect the runtime of the algorithm, because each query child recursion's @@ -95,11 +96,15 @@ DualTreeTraverser::Traverse( for (size_t i = 1; i < queryNode.NumChildren(); ++i) { // We need a copy of the map for this child. - std::map > childMap; + std::map, std::greater> + childMap; + PruneMap(queryNode.Child(i), referenceMap, childMap); Traverse(queryNode.Child(i), childMap); } - std::map > selfChildMap; + std::map, std::greater> + selfChildMap; + PruneMap(queryNode.Child(0), referenceMap, selfChildMap); Traverse(queryNode.Child(0), selfChildMap); } @@ -111,8 +116,7 @@ DualTreeTraverser::Traverse( // evaluations to do. Log::Assert((*referenceMap.begin()).first == INT_MIN); Log::Assert(queryNode.Scale() == INT_MIN); - std::vector& pointVector = - (*referenceMap.begin()).second; + std::vector& pointVector = referenceMap[INT_MIN]; for (size_t i = 0; i < pointVector.size(); ++i) { @@ -156,25 +160,25 @@ template void CoverTree:: DualTreeTraverser::PruneMap( CoverTree& queryNode, - std::map >& referenceMap, - std::map >& childMap) + std::map, std::greater>& + referenceMap, + std::map, std::greater>& + childMap) { if (referenceMap.empty()) return; // Nothing to do. // Copy the zero set first. - if ((*referenceMap.begin()).first == INT_MIN) + if (referenceMap.count(INT_MIN) == 1) { // Get a reference to the vector representing the entries at this scale. - std::vector& scaleVector = - (*referenceMap.begin()).second; + std::vector& scaleVector = referenceMap[INT_MIN]; // Before traversing all the points in this scale, sort by score. std::sort(scaleVector.begin(), scaleVector.end()); - const int thisScale = (*referenceMap.begin()).first; - childMap[thisScale].reserve(scaleVector.size()); - std::vector& newScaleVector = childMap[thisScale]; + childMap[INT_MIN].reserve(scaleVector.size()); + std::vector& newScaleVector = childMap[INT_MIN]; // Loop over each entry in the vector. for (size_t j = 0; j < scaleVector.size(); ++j) @@ -208,13 +212,13 @@ DualTreeTraverser::PruneMap( // If we didn't add anything, then strike this vector from the map. if (newScaleVector.size() == 0) - childMap.erase((*referenceMap.begin()).first); + childMap.erase(INT_MIN); } - typename std::map >::reverse_iterator - it = referenceMap.rbegin(); + typename std::map, + std::greater>::iterator it = referenceMap.begin(); - while ((it != referenceMap.rend())) + while ((it != referenceMap.end())) { const int thisScale = (*it).first; if (thisScale == INT_MIN) // We already did it. @@ -277,28 +281,26 @@ template void CoverTree:: DualTreeTraverser::ReferenceRecursion( CoverTree& queryNode, - std::map >& referenceMap) + std::map, std::greater>& + referenceMap) { // First, reduce the maximum scale in the reference map down to the scale of // the query node. while (!referenceMap.empty()) { + const int maxScale = ((*referenceMap.begin()).first); // Hacky bullshit to imitate jl cover tree. - if (queryNode.Parent() == NULL && (*referenceMap.rbegin()).first < - queryNode.Scale()) + if (queryNode.Parent() == NULL && maxScale < queryNode.Scale()) break; - if (queryNode.Parent() != NULL && (*referenceMap.rbegin()).first <= - queryNode.Scale()) + if (queryNode.Parent() != NULL && maxScale <= queryNode.Scale()) break; // If the query node's scale is INT_MIN and the reference map's maximum // scale is INT_MIN, don't try to recurse... - if ((queryNode.Scale() == INT_MIN) && - ((*referenceMap.rbegin()).first == INT_MIN)) + if (queryNode.Scale() == INT_MIN && maxScale == INT_MIN) break; // Get a reference to the current largest scale. - std::vector& scaleVector = - (*referenceMap.rbegin()).second; + std::vector& scaleVector = referenceMap[maxScale]; // Before traversing all the points in this scale, sort by score. std::sort(scaleVector.begin(), scaleVector.end()); @@ -308,7 +310,6 @@ DualTreeTraverser::ReferenceRecursion( { // Get a reference to the current element. const DualCoverTreeMapEntry& frame = scaleVector.at(i); - CoverTree* refNode = frame.referenceNode; // Create the score for the children. @@ -344,13 +345,12 @@ DualTreeTraverser::ReferenceRecursion( newFrame.score = childScore; // Use the score of the parent. newFrame.baseCase = baseCase; newFrame.traversalInfo = rule.TraversalInfo(); - referenceMap[newFrame.referenceNode->Scale()].push_back(newFrame); } } // Now clear the memory for this scale; it isn't needed anymore. - referenceMap.erase((*referenceMap.rbegin()).first); + referenceMap.erase(maxScale); } } diff --git a/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp b/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp index 728e64f39d..0721c4e090 100644 --- a/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp @@ -80,9 +80,9 @@ SingleTreeTraverser::Traverse( // and then the vector is all the nodes in that scale which need to be // investigated. Because no point in a scale can add a point in its own // scale, we know that the vector for each scale is final when we get to it. - // In addition, map is organized in such a way that rbegin() will return the - // largest scale. - std::map > mapQueue; + // In addition, the map is organized in such a way that begin() will return + // the largest scale. + std::map, std::greater> mapQueue; // Create the score for the children. double rootChildScore = rule.Score(queryIndex, referenceNode); @@ -123,14 +123,13 @@ SingleTreeTraverser::Traverse( // Now begin the iteration through the map, but only if it has anything in it. if (mapQueue.empty()) return; - typename std::map >::reverse_iterator rit = - mapQueue.rbegin(); + int maxScale = mapQueue.cbegin()->first; // We will treat the leaves differently (below). - while ((*rit).first != INT_MIN) + while (maxScale != INT_MIN) { // Get a reference to the current scale. - std::vector& scaleVector = (*rit).second; + std::vector& scaleVector = mapQueue[maxScale]; // Before traversing all the points in this scale, sort by score. std::sort(scaleVector.begin(), scaleVector.end()); @@ -170,7 +169,9 @@ SingleTreeTraverser::Traverse( // trees using TreeTraits::FirstPointIsCentroid; this is an optimization // that (theoretically) the compiler should get right. if (point != parent) + { baseCase = rule.BaseCase(queryIndex, point); + } // Don't add the self-leaf. size_t j = 0; @@ -193,7 +194,8 @@ SingleTreeTraverser::Traverse( } // Now clear the memory for this scale; it isn't needed anymore. - mapQueue.erase((*rit).first); + mapQueue.erase(maxScale); + maxScale = mapQueue.begin()->first; } // Now deal with the leaves. diff --git a/src/mlpack/tests/akfn_test.cpp b/src/mlpack/tests/akfn_test.cpp index a5f802cd7e..1808190fbb 100644 --- a/src/mlpack/tests/akfn_test.cpp +++ b/src/mlpack/tests/akfn_test.cpp @@ -241,4 +241,3 @@ TEST_CASE("AKFNDualBallTreeTest", "[AKFNTest]") for (size_t i = 0; i < neighborsBallTree.n_elem; ++i) REQUIRE_RELATIVE_ERR(distancesBallTree(i), distancesExact(i), 0.05); } - diff --git a/src/mlpack/tests/krann_search_test.cpp b/src/mlpack/tests/krann_search_test.cpp index 68214b4a25..a548b30438 100644 --- a/src/mlpack/tests/krann_search_test.cpp +++ b/src/mlpack/tests/krann_search_test.cpp @@ -368,7 +368,8 @@ TEST_CASE("DualCoverTreeTest", "[KRANNTest]") RACoverTreeSearch tsdRann(&refTree, false, 1.0, 0.95, false, false, 5); arma::Mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 100; From 54267705ed3c7ad595bfdb7ef48cfd8dd4e4cff3 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 24 Apr 2021 19:24:32 +0200 Subject: [PATCH 222/729] If we are building mlpack statically then build executable statically too This pull request is not related to cross-compilation. Signed-off-by: Omar Shrit --- src/mlpack/bindings/cli/CMakeLists.txt | 20 +++++++++++++++----- src/mlpack/tests/CMakeLists.txt | 21 +++++++++++++++------ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/mlpack/bindings/cli/CMakeLists.txt b/src/mlpack/bindings/cli/CMakeLists.txt index 4b94805fe5..8ebc20583a 100644 --- a/src/mlpack/bindings/cli/CMakeLists.txt +++ b/src/mlpack/bindings/cli/CMakeLists.txt @@ -50,11 +50,21 @@ if (BUILD_CLI_EXECUTABLES) add_executable(mlpack_${name} ${name}_main.cpp ) - target_link_libraries(mlpack_${name} - mlpack - ${ARMADILLO_LIBRARIES} - ${COMPILER_SUPPORT_LIBRARIES} - ) + # Build mlpack CLI binding binaries statically. + if(NOT BUILD_SHARED_LIBS) + target_link_libraries(mlpack_${name} -static + mlpack + ${ARMADILLO_LIBRARIES} + ${COMPILER_SUPPORT_LIBRARIES} + ) + else() + # Build mlpack CLI binding binaries dynamically. + target_link_libraries(mlpack_${name} + mlpack + ${ARMADILLO_LIBRARIES} + ${COMPILER_SUPPORT_LIBRARIES} + ) + endif() # Make sure that we set BINDING_TYPE to cli so the command-line program is # compiled with the correct int main() call. set_target_properties(mlpack_${name} PROPERTIES COMPILE_FLAGS diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index de0f56d8df..0695ccb7b7 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -175,12 +175,21 @@ add_executable(mlpack_test main_tests/test_helper.hpp ) -# Link dependencies of test executable. -target_link_libraries(mlpack_test - mlpack - ${ARMADILLO_LIBRARIES} - ${COMPILER_SUPPORT_LIBRARIES} -) +if(NOT BUILD_SHARED_LIBS) +# Build mlpack test executable statically. + target_link_libraries(mlpack_test -static + mlpack + ${ARMADILLO_LIBRARIES} + ${COMPILER_SUPPORT_LIBRARIES} + ) +else() + # Build mlpack test executable dynamically. + target_link_libraries(mlpack_test + mlpack + ${ARMADILLO_LIBRARIES} + ${COMPILER_SUPPORT_LIBRARIES} + ) +endif() set_target_properties(mlpack_test PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "../core.hpp") cotire(mlpack_test) From 9102ac8ef7b37cacf52b52484732a961d82637ca Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 25 Apr 2021 05:19:43 +0530 Subject: [PATCH 223/729] Lined up spacing in ExtraTrees typedef --- src/mlpack/methods/random_forest/random_forest.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 9eaa4a5429..1bfac12e6f 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -437,10 +437,10 @@ template class CategoricalSplitType = AllCategoricalSplit> using ExtraTrees = RandomForest; + DimensionSelectionType, + RandomBinaryNumericSplit, + CategoricalSplitType, + false>; } // namespace tree } // namespace mlpack From be8893dd9ac822a9c1b345faa0d7a2e9c61407c9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 25 Apr 2021 05:21:09 +0530 Subject: [PATCH 224/729] Removed include from BestBinaryNumericSplit --- .../methods/decision_tree/best_binary_numeric_split_impl.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 0d8858581c..098f0ab252 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -12,8 +12,6 @@ #ifndef MLPACK_METHODS_DECISION_TREE_BEST_BINARY_NUMERIC_SPLIT_IMPL_HPP #define MLPACK_METHODS_DECISION_TREE_BEST_BINARY_NUMERIC_SPLIT_IMPL_HPP -#include - namespace mlpack { namespace tree { From 89843155ee62621857c6cd09323d6d2c6d531a91 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 25 Apr 2021 05:54:52 +0530 Subject: [PATCH 225/729] Reduced min accurary to 91% --- src/mlpack/tests/random_forest_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 6ec820777c..37f331f34c 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -607,5 +607,5 @@ TEST_CASE("ExtraTreesAccuracyTest", "[RandomForestTest]") double accuracy = arma::accu(predictions == testLabels); accuracy /= predictions.n_elem; - REQUIRE(accuracy >= 0.94); + REQUIRE(accuracy >= 0.91); } From 82be58a30557ba902d39e734f4fb0fd37cd7675c Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 25 Apr 2021 06:07:59 +0530 Subject: [PATCH 226/729] Added to HISTORY.md --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 2f7aab9538..48873c0115 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? + * Added Extra Trees Algorithm (#2883). + * Added warm start feature to Random Forest (#2881); this feature is accessible from mlpack's bindings to different languages. From 38b1907784a9299a02de6bf57b5c2b14ccb70e64 Mon Sep 17 00:00:00 2001 From: Aakash kaushik Date: Mon, 26 Apr 2021 00:19:35 +0530 Subject: [PATCH 227/729] Set test timeout for mlpack_test to zero. --- src/mlpack/tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 9761cd6df1..aa5a156411 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -205,3 +205,5 @@ add_custom_command(TARGET mlpack_test ) add_test(NAME "catch_test" COMMAND mlpack_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + +set_tests_properties(mlpack_test PROPERTIES TIMEOUT 0) From 1ed810d15128636cb0558b9c14ed1733e764d794 Mon Sep 17 00:00:00 2001 From: Aakash kaushik Date: Mon, 26 Apr 2021 00:22:06 +0530 Subject: [PATCH 228/729] Removed extra space --- src/mlpack/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index aa5a156411..094ea41196 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -206,4 +206,4 @@ add_custom_command(TARGET mlpack_test add_test(NAME "catch_test" COMMAND mlpack_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -set_tests_properties(mlpack_test PROPERTIES TIMEOUT 0) +set_tests_properties(mlpack_test PROPERTIES TIMEOUT 0) From 95fca84588c128081d9ab2ccdebfe451d8ee0a0f Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 26 Apr 2021 02:05:08 +0200 Subject: [PATCH 229/729] Remove redundant numClasses assignment. --- src/mlpack/methods/linear_svm/linear_svm_main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mlpack/methods/linear_svm/linear_svm_main.cpp b/src/mlpack/methods/linear_svm/linear_svm_main.cpp index f72b7c1b6f..ce645e964b 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_main.cpp +++ b/src/mlpack/methods/linear_svm/linear_svm_main.cpp @@ -373,10 +373,6 @@ static void mlpackMain() oss << IO::GetPrintableParam("test"); std::string testOutput = oss.str(); - if (!IO::HasParam("training")) - { - numClasses = model->svm.NumClasses(); - } // Get the test dataset, and get predictions. testSet = std::move(IO::GetParam("test")); arma::Row predictions; From 03a10c2618748e1b7e43d4205d6deb5cbf1400d3 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 26 Apr 2021 02:15:35 +0200 Subject: [PATCH 230/729] Initalize bestDistance at a later stage. --- .../methods/neighbor_search/neighbor_search_rules_impl.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp index 74d3c490cd..d9c5d2bba3 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp @@ -397,7 +397,6 @@ inline double NeighborSearchRules:: // take the better of the two. double worstDistance = SortPolicy::BestDistance(); - double bestDistance = SortPolicy::WorstDistance(); double bestPointDistance = SortPolicy::WorstDistance(); double auxDistance = SortPolicy::WorstDistance(); @@ -428,7 +427,7 @@ inline double NeighborSearchRules:: // Add triangle inequality adjustment to best distance. It is possible this // could be tighter for some certain types of trees. - bestDistance = SortPolicy::CombineWorst(auxDistance, + double bestDistance = SortPolicy::CombineWorst(auxDistance, 2 * queryNode.FurthestDescendantDistance()); // Add triangle inequality adjustment to best distance of points in node. From 73fec171ec66c85382f5f2f8b79539d1e3d355f5 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 26 Apr 2021 02:17:05 +0200 Subject: [PATCH 231/729] Initalize auxDistance at a later stage. --- .../methods/neighbor_search/neighbor_search_rules_impl.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp index d9c5d2bba3..6bf8055efd 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp @@ -398,7 +398,6 @@ inline double NeighborSearchRules:: double worstDistance = SortPolicy::BestDistance(); double bestPointDistance = SortPolicy::WorstDistance(); - double auxDistance = SortPolicy::WorstDistance(); // Loop over points held in the node. for (size_t i = 0; i < queryNode.NumPoints(); ++i) @@ -410,7 +409,7 @@ inline double NeighborSearchRules:: bestPointDistance = distance; } - auxDistance = bestPointDistance; + double auxDistance = bestPointDistance; // Loop over children of the node, and use their cached information to // assemble bounds. From 25fea7c3612d22daa25ed99b5f6a480695e9bc75 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 26 Apr 2021 02:39:19 +0200 Subject: [PATCH 232/729] Remove unused parameter (alpha). --- src/mlpack/tests/det_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/det_test.cpp b/src/mlpack/tests/det_test.cpp index ab55a541cd..92e2ca00a5 100644 --- a/src/mlpack/tests/det_test.cpp +++ b/src/mlpack/tests/det_test.cpp @@ -341,7 +341,7 @@ TEST_CASE("TestComputeValue", "[DETTest]") 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); + testDTree.PruneAndUpdate(alpha, testData.n_cols, false); double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0)); From 0c4ff06969a024f5b30459e1f4e4ee44d2cced27 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 26 Apr 2021 02:39:48 +0200 Subject: [PATCH 233/729] Remove unused parameter (alpha). --- src/mlpack/tests/det_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/det_test.cpp b/src/mlpack/tests/det_test.cpp index 92e2ca00a5..8f49d39fca 100644 --- a/src/mlpack/tests/det_test.cpp +++ b/src/mlpack/tests/det_test.cpp @@ -448,7 +448,7 @@ TEST_CASE("TestSparseComputeValue", "[DETTest]") 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); + testDTree.PruneAndUpdate(alpha, testData.n_cols, false); double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0)); From b2ad544a16c0c9165c24746b313787ede6800217 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Mon, 26 Apr 2021 04:36:52 +0200 Subject: [PATCH 234/729] Move deltaBeta into the loop. --- .../bayesian_linear_regression.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp index c163d0d148..92b01d80c8 100644 --- a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp @@ -1,6 +1,6 @@ /** * @file methods/bayesian_linear_regression/bayesian_linear_regression.cpp - * @author Clement Mercier + * @author Clement Mercier * * Implementation of Bayesian linear regression. * @@ -58,12 +58,12 @@ double BayesianLinearRegression::Train(const arma::mat& data, beta = 1 / (var(t, 1) * 0.1); unsigned short i = 0; - double deltaAlpha = 1.0, deltaBeta = 1.0, crit = 1.0; + double deltaAlpha = 1.0, crit = 1.0; while ((crit > tolerance) && (i < maxIterations)) { deltaAlpha = -alpha; - deltaBeta = -beta; + double deltaBeta = -beta; // Update the solution. omega = eigVec * diagmat(1 / (eigVal + (alpha / beta))) * eigVecInvPhitT; From 3d24936f5894efb8f00e37fdfc3acf70b2a80ece Mon Sep 17 00:00:00 2001 From: Aakash Kaushik Date: Mon, 26 Apr 2021 09:50:46 +0530 Subject: [PATCH 235/729] catch_test instead of mlpack_test --- src/mlpack/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 094ea41196..e05cf135a1 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -206,4 +206,4 @@ add_custom_command(TARGET mlpack_test add_test(NAME "catch_test" COMMAND mlpack_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -set_tests_properties(mlpack_test PROPERTIES TIMEOUT 0) +set_tests_properties("catch_test" PROPERTIES TIMEOUT 0) From da5862bcd010b17838bdf2be9be665c403570530 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 13:01:44 +0200 Subject: [PATCH 236/729] Add a use case for BUILD_SHARED_LIBS in docs Signed-off-by: Omar Shrit --- doc/guide/build.hpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index 9356f725cc..21b22fd238 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -209,6 +209,14 @@ The full list of options mlpack allows: Each option can be specified to CMake with the '-D' flag. Other tools can also be used to configure CMake, but those are not documented here. +For example, if you would like to build mlpack and its CLI binding statically, then +you need to execute the following commands: + +@code +$ cd build +$ cmake -D BUILD_SHARED_LIBS=OFF ../ +@endcode + In addition, the following directories may be specified, to find include files and libraries. These also use the '-D' flag. @@ -216,10 +224,12 @@ and libraries. These also use the '-D' flag. - ARMADILLO_LIBRARY=(/path/to/armadillo/libarmadillo.so): location of Armadillo library - BOOST_ROOT=(/path/to/boost/): path to root of boost installation + - CEREAL_INCLUDE_DIR=(/path/to/cereal/include): path to include directory for + cereal - ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory for ensmallen - STB_IMAGE_INCLUDE_DIR=(/path/to/stb/include): path to include directory for - STB image library + STB image library - MATHJAX_ROOT=(/path/to/mathjax): path to root of MathJax installation @section build_build Building mlpack From dd9383d2269f19e1e8dd38c5f7e8708d654d1c01 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 26 Apr 2021 20:14:49 +0530 Subject: [PATCH 237/729] Update HISTORY.md --- HISTORY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 48873c0115..e3c253ec35 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? - * Added Extra Trees Algorithm (#2883). + * Added Extra Trees Algorithm (#2883). Currently, it can be used using the + * class `mlpack::tree::ExtraTrees`, but only through C++. * Added warm start feature to Random Forest (#2881); this feature is accessible from mlpack's bindings to different languages. From 921a30ce21ea0117d795667ddc96a58790fe23ed Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 16:45:18 +0200 Subject: [PATCH 238/729] Update indentation in src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index ebc6729fdc..a3cf53645d 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -101,9 +101,8 @@ class CoverTree:: std::greater>& childMap); void ReferenceRecursion(CoverTree& queryNode, - std::map, - std::greater>& referenceMap); + std::map, + std::greater>& referenceMap); }; } // namespace tree From 993d3b040f537880b72cd808a503d2435138f58a Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 16:45:30 +0200 Subject: [PATCH 239/729] Update indentation in src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index a3cf53645d..d4611accd6 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -100,7 +100,8 @@ class CoverTree:: std::vector, std::greater>& childMap); - void ReferenceRecursion(CoverTree& queryNode, + void ReferenceRecursion( + CoverTree& queryNode, std::map, std::greater>& referenceMap); }; From 1b0e7b44db4fbe9070ecc3b29cc550b0b32cc16b Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 16:45:44 +0200 Subject: [PATCH 240/729] Update indentation in src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp Co-authored-by: Ryan Curtin --- .../core/tree/cover_tree/dual_tree_traverser.hpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index d4611accd6..65ae0c8219 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -93,12 +93,10 @@ class CoverTree:: //! Prepare map for recursion. void PruneMap(CoverTree& queryNode, - std::map, - std::greater>& referenceMap, - std::map, - std::greater>& childMap); + std::map, + std::greater>& referenceMap, + std::map, + std::greater>& childMap); void ReferenceRecursion( CoverTree& queryNode, From abbc179220799fc022c5fb45b22e183a6c1e7a0b Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 16:45:59 +0200 Subject: [PATCH 241/729] Update indentation in src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index 65ae0c8219..2a901ef5b7 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -92,7 +92,8 @@ class CoverTree:: std::greater>& referenceMap); //! Prepare map for recursion. - void PruneMap(CoverTree& queryNode, + void PruneMap( + CoverTree& queryNode, std::map, std::greater>& referenceMap, std::map, From d7fa52cc4f46e6d0cc0d6f58f4127666c5cbf906 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 16:46:14 +0200 Subject: [PATCH 242/729] Update indentation in src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index 2a901ef5b7..9ddda38b98 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -87,9 +87,8 @@ class CoverTree:: * Helper function for traversal of the two trees. */ void Traverse(CoverTree& queryNode, - std::map, - std::greater>& referenceMap); + std::map, + std::greater>& referenceMap); //! Prepare map for recursion. void PruneMap( From bb4e3770733f30c625bd6eed97bac807c8285a61 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 26 Apr 2021 16:46:26 +0200 Subject: [PATCH 243/729] Update indentation in src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp Co-authored-by: Ryan Curtin --- src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index 9ddda38b98..2b7a8ae378 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -86,7 +86,8 @@ class CoverTree:: /** * Helper function for traversal of the two trees. */ - void Traverse(CoverTree& queryNode, + void Traverse( + CoverTree& queryNode, std::map, std::greater>& referenceMap); From cefa6ab75006195b8f2352e6d1c947812532bc25 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Tue, 27 Apr 2021 16:04:06 +0530 Subject: [PATCH 244/729] initial commit --- src/mlpack/bindings/cli/add_to_cli11.hpp | 4 +-- src/mlpack/bindings/cli/cli_option.hpp | 5 ++- src/mlpack/bindings/cli/get_param.hpp | 12 +++++-- .../bindings/cli/get_printable_param_impl.hpp | 8 ++--- src/mlpack/bindings/cli/get_raw_param.hpp | 2 +- src/mlpack/bindings/cli/in_place_copy.hpp | 34 +++++++++++++++---- src/mlpack/bindings/cli/output_param_impl.hpp | 4 +-- src/mlpack/bindings/cli/set_param.hpp | 2 +- 8 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/mlpack/bindings/cli/add_to_cli11.hpp b/src/mlpack/bindings/cli/add_to_cli11.hpp index f4ae48a608..0e2c93ea0e 100644 --- a/src/mlpack/bindings/cli/add_to_cli11.hpp +++ b/src/mlpack/bindings/cli/add_to_cli11.hpp @@ -46,7 +46,7 @@ void AddToCLI11(const std::string& cliName, app.add_option_function(cliName.c_str(), [¶m](const std::string& value) { - using TupleType = std::tuple::type>; + using TupleType = std::tuple::type, size_t, size_t>; TupleType& tuple = *boost::any_cast(¶m.value); std::get<1>(tuple) = boost::any_cast(value); param.wasPassed = true; @@ -108,7 +108,7 @@ void AddToCLI11(const std::string& cliName, app.add_option_function(cliName.c_str(), [¶m](const std::string& value) { - using TupleType = std::tuple::type>; + using TupleType = std::tuple::type, size_t, size_t>; TupleType& tuple = *boost::any_cast(¶m.value); std::get<1>(tuple) = boost::any_cast(value); param.wasPassed = true; diff --git a/src/mlpack/bindings/cli/cli_option.hpp b/src/mlpack/bindings/cli/cli_option.hpp index eeebc2d7cc..37339cf979 100644 --- a/src/mlpack/bindings/cli/cli_option.hpp +++ b/src/mlpack/bindings/cli/cli_option.hpp @@ -100,7 +100,10 @@ class CLIOption else { typename ParameterType::type>::type tmp; - data.value = boost::any(std::tuple(defaultValue, tmp)); + if(arma::is_arma_type::value) + data.value = boost::any(std::tuple(defaultValue, tmp, 0, 0)); + else + data.value = boost::any(std::tuple(defaultValue, tmp)); } const std::string tname = data.tname; diff --git a/src/mlpack/bindings/cli/get_param.hpp b/src/mlpack/bindings/cli/get_param.hpp index eaaa813d61..b5b23f65ee 100644 --- a/src/mlpack/bindings/cli/get_param.hpp +++ b/src/mlpack/bindings/cli/get_param.hpp @@ -51,10 +51,12 @@ T& GetParam( // contains the filename. It's possible we could load empty matrices many // times, but I am not bothered by that---it shouldn't be something that // happens. - typedef std::tuple::type> TupleType; + typedef std::tuple::type, size_t, size_t> TupleType; TupleType& tuple = *boost::any_cast(&d.value); const std::string& value = std::get<1>(tuple); T& matrix = std::get<0>(tuple); + size_t& n_rows = std::get<2>(tuple); + size_t& n_cols = std::get<3>(tuple); if (d.input && !d.loaded) { // Call correct data::Load() function. @@ -62,6 +64,8 @@ T& GetParam( data::Load(value, matrix, true); else data::Load(value, matrix, true, !d.noTranspose); + n_rows = matrix.n_rows; + n_cols = matrix.n_cols; d.loaded = true; } @@ -81,13 +85,17 @@ T& GetParam( { // If this is an input parameter, we need to load both the matrix and the // dataset info. - typedef std::tuple TupleType; + typedef std::tuple TupleType; TupleType* tuple = boost::any_cast(&d.value); const std::string& value = std::get<1>(*tuple); T& t = std::get<0>(*tuple); + size_t& n_rows = std::get<2>(*tuple); + size_t& n_cols = std::get<3>(*tuple); if (d.input && !d.loaded) { data::Load(value, std::get<1>(t), std::get<0>(t), true, !d.noTranspose); + n_rows = std::get<1>(t).n_rows; + n_cols = std::get<1>(t).n_cols; d.loaded = true; } diff --git a/src/mlpack/bindings/cli/get_printable_param_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_impl.hpp index 9e2584f6b5..b679b2afdf 100644 --- a/src/mlpack/bindings/cli/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_impl.hpp @@ -79,7 +79,7 @@ std::string GetPrintableParam( std::tuple>::value>::type* /* junk */) { // Extract the string from the tuple that's being held. - typedef std::tuple::type> TupleType; + typedef std::tuple::type, size_t, size_t> TupleType; const TupleType* tuple = boost::any_cast(&data.value); std::ostringstream oss; @@ -87,10 +87,8 @@ std::string GetPrintableParam( if (std::get<1>(*tuple) != "") { - // Make sure the matrix is loaded so that we can print its size. - T& mat = GetParam(const_cast(data)); - std::string matDescription = GetMatrixSize(mat); - + std::string matDescription = std::to_string(std::get<2>(*tuple)) + "x"; + matDescription += std::to_string(std::get<3>(*tuple)) + " matrix"; oss << " (" << matDescription << ")"; } diff --git a/src/mlpack/bindings/cli/get_raw_param.hpp b/src/mlpack/bindings/cli/get_raw_param.hpp index 35d544f08b..a0305df23c 100644 --- a/src/mlpack/bindings/cli/get_raw_param.hpp +++ b/src/mlpack/bindings/cli/get_raw_param.hpp @@ -48,7 +48,7 @@ T& GetRawParam( arma::mat>>::value>::type* = 0) { // Don't load the matrix. - typedef std::tuple TupleType; + typedef std::tuple TupleType; T& value = std::get<0>(*boost::any_cast(&d.value)); return value; } diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index ca0d7667f5..97ce2430b9 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -41,7 +41,7 @@ void InPlaceCopyInternal( /** * Modify the filename for any type that needs to be loaded from disk to match - * the filename of the input parameter. + * the filename of the input parameter. For matrix/dataset info. * * @param d ParamData object we want to make into an in-place copy. * @param input ParamData object whose filename we should copy. @@ -50,14 +50,34 @@ template void InPlaceCopyInternal( util::ParamData& d, util::ParamData& input, - const typename std::enable_if< - arma::is_arma_type::value || - std::is_same>::value || - data::HasSerialize::value>::type* = 0) + const typename std::enable_if::value || + std::is_same>::value>::type* = 0) { // Make the output filename the same as the input filename. - typedef std::tuple::type> TupleType; + typedef std::tuple::type, size_t, size_t> TupleType; + TupleType& tuple = *boost::any_cast(&d.value); + std::string& value = std::get<1>(tuple); + + const TupleType& inputTuple = *boost::any_cast(&input.value); + value = std::get<1>(inputTuple); +} + +/** + * Modify the filename for any type that needs to be loaded from disk to match + * the filename of the input parameter. For serializable object. + * + * @param d ParamData object we want to make into an in-place copy. + * @param input ParamData object whose filename we should copy. + */ +template +void InPlaceCopyInternal( + util::ParamData& d, + util::ParamData& input, + const typename std::enable_if::value>::type* = 0) +{ + // Make the output filename the same as the input filename. + typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); std::string& value = std::get<1>(tuple); diff --git a/src/mlpack/bindings/cli/output_param_impl.hpp b/src/mlpack/bindings/cli/output_param_impl.hpp index c4dcfddbf4..0bc0a5a75c 100644 --- a/src/mlpack/bindings/cli/output_param_impl.hpp +++ b/src/mlpack/bindings/cli/output_param_impl.hpp @@ -53,7 +53,7 @@ void OutputParamImpl( util::ParamData& data, const typename boost::enable_if>::type* /* junk */) { - typedef std::tuple TupleType; + typedef std::tuple TupleType; const T& output = std::get<0>(*boost::any_cast(&data.value)); const std::string& filename = std::get<1>(*boost::any_cast(&data.value)); @@ -95,7 +95,7 @@ void OutputParamImpl( std::tuple>>::type* /* junk */) { // Output the matrix with the mappings. - typedef std::tuple TupleType; + typedef std::tuple TupleType; const T& tuple = std::get<0>(*boost::any_cast(&data.value)); const std::string& filename = std::get<1>(*boost::any_cast(&data.value)); diff --git a/src/mlpack/bindings/cli/set_param.hpp b/src/mlpack/bindings/cli/set_param.hpp index 8295b51242..8a7695e6a9 100644 --- a/src/mlpack/bindings/cli/set_param.hpp +++ b/src/mlpack/bindings/cli/set_param.hpp @@ -63,7 +63,7 @@ void SetParam( std::tuple>::value>::type* = 0) { // We're setting the string filename. - typedef std::tuple::type> TupleType; + typedef std::tuple::type, size_t, size_t> TupleType; TupleType& tuple = *boost::any_cast(&d.value); std::get<1>(tuple) = boost::any_cast(value); } From 46982228b962bacafec244b4eec38afd5aa391bb Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Tue, 27 Apr 2021 21:15:32 +0530 Subject: [PATCH 245/729] fixing tests --- src/mlpack/bindings/cli/set_param.hpp | 4 +-- src/mlpack/tests/cli_binding_test.cpp | 36 +++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/mlpack/bindings/cli/set_param.hpp b/src/mlpack/bindings/cli/set_param.hpp index 8a7695e6a9..10e265d52d 100644 --- a/src/mlpack/bindings/cli/set_param.hpp +++ b/src/mlpack/bindings/cli/set_param.hpp @@ -51,8 +51,8 @@ void SetParam( } /** - * Set a matrix parameter, a matrix/dataset info parameter, or a serializable - * object. These set the filename referring to the parameter. + * Set a matrix parameter, a matrix/dataset info parameter. + * These set the filename referring to the parameter. */ template void SetParam( diff --git a/src/mlpack/tests/cli_binding_test.cpp b/src/mlpack/tests/cli_binding_test.cpp index 391a0bfe1a..10532572a0 100644 --- a/src/mlpack/tests/cli_binding_test.cpp +++ b/src/mlpack/tests/cli_binding_test.cpp @@ -82,7 +82,7 @@ TEST_CASE("GetParamLoadedMatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::ones); - tuple tuple = make_tuple(m, filename); + tuple tuple = make_tuple(m, filename, 0, 0); d.value = boost::any(tuple); // Mark it as already loaded. d.input = true; @@ -106,7 +106,7 @@ TEST_CASE("GetParamUnloadedMatTest", "[CLIOptionTest]") arma::mat test(5, 5, arma::fill::ones); data::Save("test.csv", test); arma::mat m; - tuple tuple = make_tuple(m, filename); + tuple tuple = make_tuple(m, filename, 0, 0); d.value = boost::any(tuple); // Make sure it is not loaded yet. d.input = true; @@ -132,7 +132,7 @@ TEST_CASE("GetParamUmatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::Mat m(5, 5, arma::fill::ones); - tuple, string> tuple = make_tuple(m, filename); + tuple, string, size_t, size_t> tuple = make_tuple(m, filename, 0, 0); d.value = boost::any(tuple); // Mark it as already loaded. d.input = true; @@ -157,7 +157,7 @@ TEST_CASE("GetParamUnloadedUmatTest", "[CLIOptionTest]") arma::Mat test(5, 5, arma::fill::ones); data::Save("test.csv", test); arma::Mat m; - tuple, string> tuple = make_tuple(m, filename); + tuple, string, size_t, size_t> tuple = make_tuple(m, filename, 0, 0); d.value = boost::any(tuple); // Make sure it is not loaded yet. d.input = true; @@ -200,7 +200,7 @@ TEST_CASE("GetParamDatasetInfoMatTest", "[CLIOptionTest]") arma::mat m; tuple tuple1 = make_tuple(dd, m); - tuple tuple2 = make_tuple(tuple1, filename); + tuple tuple2 = make_tuple(tuple1, filename, 0, 0); d.value = boost::any(tuple2); // Make sure it is not loaded yet. @@ -274,7 +274,7 @@ TEST_CASE("RawParamMatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::ones); - tuple tuple = make_tuple(m, filename); + tuple tuple = make_tuple(m, filename, 0, 0); d.value = boost::any(tuple); d.input = true; d.loaded = false; @@ -324,7 +324,7 @@ TEST_CASE("GetRawParamDatasetInfoTest", "[CLIOptionTest]") arma::mat m(3, 3, arma::fill::randu); tuple tuple1 = make_tuple(dd, m); - tuple tuple2 = make_tuple(tuple1, filename); + tuple tuple2 = make_tuple(tuple1, filename, 0, 0); d.value = boost::any(tuple2); // Make sure it is not loaded yet. @@ -350,7 +350,7 @@ TEST_CASE("OutputParamMatTest", "[CLIOptionTest]") // Create value. string filename = "test.csv"; arma::mat m(3, 3, arma::fill::randu); - tuple t = make_tuple(m, filename); + tuple t = make_tuple(m, filename, 0, 0); d.value = boost::any(t); d.input = false; @@ -376,7 +376,7 @@ TEST_CASE("OutputParamUmatTest", "[CLIOptionTest]") // Create value. string filename = "test.csv"; arma::Mat m(3, 3, arma::fill::randu); - tuple, string> t = make_tuple(m, filename); + tuple, string, size_t, size_t> t = make_tuple(m, filename, 0, 0); d.value = boost::any(t); d.input = false; @@ -467,7 +467,7 @@ TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]") // Create initial value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::randu); - d.value = boost::any(make_tuple(m, filename)); + d.value = boost::any(make_tuple(m, filename, size_t(0), size_t(0))); // Get a new string. string newFilename = "new.csv"; @@ -475,10 +475,9 @@ TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]") SetParam((util::ParamData&) d, (const void*) &a2, (void*) NULL); - // Make sure the change went through. - tuple& t = - *boost::any_cast>(&d.value); + tuple& t = + *boost::any_cast>(&d.value); REQUIRE(get<1>(t) == "new.csv"); } @@ -518,7 +517,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") arma::mat m(3, 3, arma::fill::randu); DatasetInfo di(3); tuple t1 = make_tuple(di, m); - tuple, string> t2 = make_tuple(t1, filename); + tuple, string, size_t, size_t> t2 = make_tuple(t1, filename, + size_t(0), size_t(0)); d.value = boost::any(t2); d.noTranspose = false; @@ -530,8 +530,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") (const void*) &a2, (void*) NULL); // Check that the name is right. - tuple, string>& t3 = - *boost::any_cast, string>>(&d.value); + tuple, string, size_t, size_t>& t3 = + *boost::any_cast, string, size_t, size_t>>(&d.value); REQUIRE(get<1>(t3) == "new_filename.csv"); } @@ -556,7 +556,7 @@ TEST_CASE("GetAllocatedMemoryNonModelTest", "[CLIOptionTest]") // Also test with a matrix type. arma::mat test(10, 10, arma::fill::ones); string filename = "test.csv"; - tuple t = make_tuple(test, filename); + tuple t = make_tuple(test, filename, 0, 0); d.value = boost::any(t); result = (void*) 1; @@ -602,7 +602,7 @@ TEST_CASE("DeleteAllocatedMemoryNonModelTest", "[CLIOptionTest]") arma::mat test(10, 10, arma::fill::ones); string filename = "test.csv"; - tuple t = make_tuple(test, filename); + tuple t = make_tuple(test, filename, 0, 0); d.value = boost::any(t); DeleteAllocatedMemory((util::ParamData&) d, From 7cfff7d5aad7e2e0dc27ede874922ed8192c90c3 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 28 Apr 2021 00:09:57 +0530 Subject: [PATCH 246/729] fixing tests 2 --- src/mlpack/bindings/cli/cli_option.hpp | 3 ++- src/mlpack/bindings/cli/get_printable_param_impl.hpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mlpack/bindings/cli/cli_option.hpp b/src/mlpack/bindings/cli/cli_option.hpp index 37339cf979..10ae7ddc1b 100644 --- a/src/mlpack/bindings/cli/cli_option.hpp +++ b/src/mlpack/bindings/cli/cli_option.hpp @@ -100,7 +100,8 @@ class CLIOption else { typename ParameterType::type>::type tmp; - if(arma::is_arma_type::value) + if(arma::is_arma_type::value || + std::is_same>::value) data.value = boost::any(std::tuple(defaultValue, tmp, 0, 0)); else data.value = boost::any(std::tuple(defaultValue, tmp)); diff --git a/src/mlpack/bindings/cli/get_printable_param_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_impl.hpp index b679b2afdf..89e0c75fe7 100644 --- a/src/mlpack/bindings/cli/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_impl.hpp @@ -87,6 +87,8 @@ std::string GetPrintableParam( if (std::get<1>(*tuple) != "") { + // make sure that the matrix is loaded, so that we can print its size. + GetParam(const_cast(data)); std::string matDescription = std::to_string(std::get<2>(*tuple)) + "x"; matDescription += std::to_string(std::get<3>(*tuple)) + " matrix"; oss << " (" << matDescription << ")"; From b980f1617967fedfb0517e85ca219fc1196c1547 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 28 Apr 2021 17:20:35 -0400 Subject: [PATCH 247/729] Add a link to the vision document in the readme. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b8fffc8ca8..98c908fc7d 100644 --- a/README.md +++ b/README.md @@ -361,6 +361,9 @@ older versions of mlpack: - [Development Site (Github)](https://www.github.com/mlpack/mlpack/) - [API documentation (Doxygen)](https://www.mlpack.org/doc/mlpack-git/doxygen/index.html) +To learn about the development goals of mlpack in the short- and medium-term +future, see the [vision document](https://www.mlpack.org/papers/vision.pdf). + ### 8. Bug reporting (see also [mlpack help](https://www.mlpack.org/questions.html)) From e8fa7b0cb8b26c83401ddf1b39a90535f84d49af Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 29 Apr 2021 21:42:45 +0530 Subject: [PATCH 248/729] Fixed ceil parameter in max and lp pooling layer --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 46 +++++++++++++------ .../methods/ann/layer/lp_pooling_impl.hpp | 5 -- src/mlpack/methods/ann/layer/max_pooling.hpp | 14 ++++-- .../methods/ann/layer/max_pooling_impl.hpp | 3 -- 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 8423dda79f..40296acad1 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -167,9 +167,17 @@ class LpPooling for (size_t i = 0, rowidx = 0; i < output.n_rows; ++i, rowidx += strideWidth) { + size_t rowEnd = rowidx + kernelWidth - 1; + size_t colEnd = colidx + kernelHeight - 1; + + if (rowEnd > input.n_rows - 1) + rowEnd = input.n_rows - 1; + if (colEnd > input.n_cols - 1) + colEnd = input.n_cols - 1; + arma::mat subInput = input( - arma::span(rowidx, rowidx + kernelWidth - 1 - offset), - arma::span(colidx, colidx + kernelHeight - 1 - offset)); + arma::span(rowidx, rowEnd), + arma::span(colidx, colEnd)); output(i, j) = pow(arma::accu(arma::pow(subInput, normType)), 1.0 / normType); @@ -188,24 +196,39 @@ class LpPooling const arma::Mat& error, arma::Mat& output) { - const size_t rStep = input.n_rows / error.n_rows - offset; - const size_t cStep = input.n_cols / error.n_cols - offset; arma::Mat unpooledError; - for (size_t j = 0; j < input.n_cols - cStep; j += cStep) + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) { - for (size_t i = 0; i < input.n_rows - rStep; i += rStep) + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) { - const arma::Mat& inputArea = input(arma::span(i, i + rStep - 1), - arma::span(j, j + cStep - 1)); + size_t rowEnd = i + kernelWidth - 1; + size_t colEnd = j + kernelHeight - 1; + + if (rowEnd > input.n_rows - 1) + { + if (floor) + continue; + rowEnd = input.n_rows - 1; + } + + if (colEnd > input.n_cols - 1) + { + if (floor) + continue; + colEnd = input.n_cols - 1; + } + + arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); + size_t sum = pow(arma::accu(arma::pow(inputArea, normType)), (normType - 1) / normType); unpooledError = arma::Mat(inputArea.n_rows, inputArea.n_cols); unpooledError.fill(error(i / rStep, j / cStep)); unpooledError %= arma::pow(inputArea, normType - 1); unpooledError /= sum; - output(arma::span(i, i + rStep - 1 - offset), - arma::span(j, j + cStep - 1 - offset)) += unpooledError; + output(arma::span(i, i + InputArea.n_rows - 1), + arma::span(j, j + InputArea.n_cols - 1)) += unpooledError; } } } @@ -249,9 +272,6 @@ class LpPooling //! Locally-stored reset parameter used to initialize the module once. bool reset; - //! Locally-stored stored rounding offset. - size_t offset; - //! Locally-stored number of input units. size_t batchSize; diff --git a/src/mlpack/methods/ann/layer/lp_pooling_impl.hpp b/src/mlpack/methods/ann/layer/lp_pooling_impl.hpp index 0abe08ada6..525789fe07 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling_impl.hpp @@ -46,7 +46,6 @@ LpPooling::LpPooling( outputWidth(0), outputHeight(0), reset(false), - offset(0), batchSize(0) { // Nothing to do here. @@ -68,8 +67,6 @@ void LpPooling::Forward( (double) kernelWidth) / (double) strideWidth + 1); outputHeight = std::floor((inputHeight - (double) kernelHeight) / (double) strideHeight + 1); - - offset = 0; } else { @@ -77,8 +74,6 @@ void LpPooling::Forward( (double) kernelWidth) / (double) strideWidth + 1); outputHeight = std::ceil((inputHeight - (double) kernelHeight) / (double) strideHeight + 1); - - offset = 1; } outputTemp = arma::zeros >(outputWidth, outputHeight, diff --git a/src/mlpack/methods/ann/layer/max_pooling.hpp b/src/mlpack/methods/ann/layer/max_pooling.hpp index 098a9d100a..81488597f7 100644 --- a/src/mlpack/methods/ann/layer/max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/max_pooling.hpp @@ -188,9 +188,17 @@ class MaxPooling for (size_t i = 0, rowidx = 0; i < output.n_rows; ++i, rowidx += strideWidth) { + size_t rowEnd = rowidx + kernelWidth - 1; + size_t colEnd = colidx + kernelHeight - 1; + + if (rowEnd > input.n_rows - 1) + rowEnd = input.n_rows - 1; + if (colEnd > input.n_cols - 1) + colEnd = input.n_cols - 1; + arma::mat subInput = input( - arma::span(rowidx, rowidx + kernelWidth - 1 - offset), - arma::span(colidx, colidx + kernelHeight - 1 - offset)); + arma::span(rowidx, rowEnd), + arma::span(colidx, colEnd)); const size_t idx = pooling.Pooling(subInput); output(i, j) = subInput(idx); @@ -264,8 +272,6 @@ class MaxPooling //! If true use maximum a posteriori during the forward pass. bool deterministic; - //! Locally-stored stored rounding offset. - size_t offset; //! Locally-stored number of input units. size_t batchSize; diff --git a/src/mlpack/methods/ann/layer/max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/max_pooling_impl.hpp index cbc17904c4..9650a5f2c3 100644 --- a/src/mlpack/methods/ann/layer/max_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/max_pooling_impl.hpp @@ -45,7 +45,6 @@ MaxPooling::MaxPooling( outputWidth(0), outputHeight(0), deterministic(false), - offset(0), batchSize(0) { // Nothing to do here. @@ -67,7 +66,6 @@ void MaxPooling::Forward( (double) kernelWidth) / (double) strideWidth + 1); outputHeight = std::floor((inputHeight - (double) kernelHeight) / (double) strideHeight + 1); - offset = 0; } else { @@ -75,7 +73,6 @@ void MaxPooling::Forward( (double) kernelWidth) / (double) strideWidth + 1); outputHeight = std::ceil((inputHeight - (double) kernelHeight) / (double) strideHeight + 1); - offset = 1; } outputTemp = arma::zeros >(outputWidth, outputHeight, From 1def9db61db2bd463d92559134a02cb240894299 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 29 Apr 2021 22:41:05 +0530 Subject: [PATCH 249/729] minor change --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 8 ++++---- src/mlpack/methods/ann/layer/max_pooling.hpp | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 40296acad1..03ef9f540e 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -221,11 +221,11 @@ class LpPooling arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); - size_t sum = pow(arma::accu(arma::pow(inputArea, normType)), + size_t sum = pow(arma::accu(arma::pow(InputArea, normType)), (normType - 1) / normType); - unpooledError = arma::Mat(inputArea.n_rows, inputArea.n_cols); - unpooledError.fill(error(i / rStep, j / cStep)); - unpooledError %= arma::pow(inputArea, normType - 1); + unpooledError = arma::Mat(InputArea.n_rows, InputArea.n_cols); + unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem); + unpooledError %= arma::pow(InputArea, normType - 1); unpooledError /= sum; output(arma::span(i, i + InputArea.n_rows - 1), arma::span(j, j + InputArea.n_cols - 1)) += unpooledError; diff --git a/src/mlpack/methods/ann/layer/max_pooling.hpp b/src/mlpack/methods/ann/layer/max_pooling.hpp index 81488597f7..2547c5596a 100644 --- a/src/mlpack/methods/ann/layer/max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/max_pooling.hpp @@ -205,9 +205,8 @@ class MaxPooling if (!deterministic) { - arma::Mat subIndices = indices(arma::span(rowidx, - rowidx + kernelWidth - 1 - offset), - arma::span(colidx, colidx + kernelHeight - 1 - offset)); + arma::Mat subIndices = indices(arma::span(rowidx, rowEnd), + arma::span(colidx, colEnd)); poolingIndices(i, j) = subIndices(idx); } From e441e906de3cfa1101f65f1a89bc05c1d804caa8 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 29 Apr 2021 23:08:36 +0200 Subject: [PATCH 250/729] Update doc/guide/build.hpp Co-authored-by: Ryan Curtin --- doc/guide/build.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index 21b22fd238..e107edb7a2 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -209,7 +209,7 @@ The full list of options mlpack allows: Each option can be specified to CMake with the '-D' flag. Other tools can also be used to configure CMake, but those are not documented here. -For example, if you would like to build mlpack and its CLI binding statically, then +For example, if you would like to build mlpack and its CLI bindings statically, then you need to execute the following commands: @code From ab7fffb8bac12013b5f445fddff57ef448d27b48 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 29 Apr 2021 23:08:51 +0200 Subject: [PATCH 251/729] Fix indentation in src/mlpack/bindings/cli/CMakeLists.txt Co-authored-by: Ryan Curtin --- src/mlpack/bindings/cli/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/cli/CMakeLists.txt b/src/mlpack/bindings/cli/CMakeLists.txt index 8ebc20583a..40f8ac6d75 100644 --- a/src/mlpack/bindings/cli/CMakeLists.txt +++ b/src/mlpack/bindings/cli/CMakeLists.txt @@ -53,9 +53,9 @@ if (BUILD_CLI_EXECUTABLES) # Build mlpack CLI binding binaries statically. if(NOT BUILD_SHARED_LIBS) target_link_libraries(mlpack_${name} -static - mlpack - ${ARMADILLO_LIBRARIES} - ${COMPILER_SUPPORT_LIBRARIES} + mlpack + ${ARMADILLO_LIBRARIES} + ${COMPILER_SUPPORT_LIBRARIES} ) else() # Build mlpack CLI binding binaries dynamically. From 0830bbc6d617d15fa5539d971b9549f63a9312b7 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 29 Apr 2021 23:23:57 +0200 Subject: [PATCH 252/729] Fix documentation Signed-off-by: Omar Shrit --- README.md | 7 ++++++- doc/guide/build.hpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 21b9e09e7e..9d0e549f87 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ Options are specified with the -D flag. The allowed options include: BUILD_R_BINDINGS=(ON/OFF): whether or not to build R bindings R_EXECUTABLE=(/path/to/R): Path to specific R executable BUILD_TESTS=(ON/OFF): whether or not to build tests - BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to + BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as opposed to static libraries DISABLE_DOWNLOADS=(ON/OFF): whether to disable all downloads during build DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it @@ -224,6 +224,11 @@ Options are specified with the -D flag. The allowed options include: BUILD_DOCS=(ON/OFF): build Doxygen documentation, if Doxygen is available (default ON) +For example, to build mlpack library and CLI bindings statically the following +command can be used: + + $ cmake -D BUILD_SHARED_LIBS=OFF ../ + Other tools can also be used to configure CMake, but those are not documented here. See [this section of the build guide](https://www.mlpack.org/doc/mlpack-git/doxygen/build.html#build_config) for more details, including a full list of options, and their default values. diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index e107edb7a2..76b7682b6f 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -182,7 +182,7 @@ The full list of options mlpack allows: and Gonum exist. (default OFF) - BUILD_JULIA_BINDINGS=(ON/OFF): compile Julia bindings, if Julia is found (default OFF) - - BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to + - BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as opposed to static libraries (default ON) - TEST_VERBOSE=(ON/OFF): run test cases in \c mlpack_test with verbose output (default OFF) From 9613dab9e6640b478900d111ecec0d83b2a764e4 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 30 Apr 2021 02:10:47 +0200 Subject: [PATCH 253/729] Update README.md Co-authored-by: Ryan Curtin --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d0e549f87..7f7f861e43 100644 --- a/README.md +++ b/README.md @@ -211,8 +211,8 @@ Options are specified with the -D flag. The allowed options include: BUILD_R_BINDINGS=(ON/OFF): whether or not to build R bindings R_EXECUTABLE=(/path/to/R): Path to specific R executable BUILD_TESTS=(ON/OFF): whether or not to build tests - BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as opposed to - static libraries + BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as + opposed to static libraries DISABLE_DOWNLOADS=(ON/OFF): whether to disable all downloads during build DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory From 2349dfad81c2514fe06a2049295de824f9535e66 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 30 Apr 2021 02:10:59 +0200 Subject: [PATCH 254/729] Fix indentation in src/mlpack/bindings/cli/CMakeLists.txt Co-authored-by: Ryan Curtin --- src/mlpack/bindings/cli/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/cli/CMakeLists.txt b/src/mlpack/bindings/cli/CMakeLists.txt index 40f8ac6d75..ee64bcf331 100644 --- a/src/mlpack/bindings/cli/CMakeLists.txt +++ b/src/mlpack/bindings/cli/CMakeLists.txt @@ -56,7 +56,7 @@ if (BUILD_CLI_EXECUTABLES) mlpack ${ARMADILLO_LIBRARIES} ${COMPILER_SUPPORT_LIBRARIES} - ) + ) else() # Build mlpack CLI binding binaries dynamically. target_link_libraries(mlpack_${name} From bff45dce934ba891b10d07373b682aae3b15685f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 1 May 2021 07:08:29 +0530 Subject: [PATCH 255/729] Add documentation for parameters of NumChildren --- .../methods/decision_tree/random_binary_numeric_split.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 8a530a651f..a7caa9cc24 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -86,6 +86,11 @@ class RandomBinaryNumericSplit /** * Returns 2, since the binary split always has two children. + * + * @param classProbabilities Class probabilities vector, which may be filled + * with split information a successful split. (Not used here.) + * @param aux Auxiliary split information, which may be modified on a + * successful split. (Not used here.) */ static size_t NumChildren(const arma::vec& /* classProbabilities */, const AuxiliarySplitInfo& /* aux */) From f4e5bf7e60a0594e72cb22807edb5c6016ab44a6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 1 May 2021 07:12:04 +0530 Subject: [PATCH 256/729] Add documentation for splitIfBetterGain --- .../methods/decision_tree/random_binary_numeric_split.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index a7caa9cc24..d7ab4732f8 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -70,6 +70,9 @@ class RandomBinaryNumericSplit * with split information a successful split. * @param aux Auxiliary split information, which may be modified on a * successful split. + * @param splitIfBetterGain When set to true, it will split only when gain is + * better than the current best gain. Otherwise, it always makes a + * split regardless of gain. */ template static double SplitIfBetter( From 0eefde31443dbfceab0c6800dc86cd807ca73d54 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 1 May 2021 07:16:08 +0530 Subject: [PATCH 257/729] Fixed dataset name in test file --- src/mlpack/tests/random_forest_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 37f331f34c..3b51db9542 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -564,7 +564,7 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") */ TEST_CASE("ExtraTreesAccuracyTest", "[RandomForestTest]") { - // Load the vc2 dataset. + // Load the iris dataset. arma::mat dataset; if (!data::Load("iris_train.csv", dataset)) FAIL("Cannot load dataset iris_train.csv"); From 5aece9bdb4a9dcb8918d930cb2497ece3945b5f5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 1 May 2021 09:47:26 +0530 Subject: [PATCH 258/729] Changed and to && to fix windows build --- .../methods/decision_tree/random_binary_numeric_split_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index ed4f6f0e45..aec26637a3 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -122,7 +122,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( // Calculate the gain at this split point. gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; - if (gain < bestFoundGain and splitIfBetterGain) + if (gain < bestFoundGain && splitIfBetterGain) return DBL_MAX; classProbabilities.set_size(1); From 6ce53a9fb1ef132e258a9db92f3bd2d47e5c2ad8 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 1 May 2021 14:17:39 +0200 Subject: [PATCH 259/729] Find blas, refactor OpenBLAS. Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 33 +++++++++++++++++++++++++++++++ CMake/FindArmadillo.cmake | 11 ++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 CMake/ConfigureCrossCompile.cmake diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake new file mode 100644 index 0000000000..023efc121b --- /dev/null +++ b/CMake/ConfigureCrossCompile.cmake @@ -0,0 +1,33 @@ +if (CMAKE_CROSSCOMPILING) + include(board/flags-config.cmake) + if(NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX)) + message(FATAL_ERROR "Neither of CMAKE_SYSROOT or TOOLCHAIN_PREFIX is set, please set both of them and try again") + elseif(NOT CMAKE_SYSROOT) + message(FATAL_ERROR "Can not proceed CMAKE_SYSROOT is not set") + elseif(NOT TOOLCHAIN_PREFIX) + message(FATAL_ERROR "Cant not proceed TOOLCHAIN_PREFIXN is not set") + elseif(NOT OPENBLAS_TARGET) + message(FATAL_ERROR "Cant not proceed, board name is not set, please refer to documentation") + endif() +endif() + +macro(search_openblas version) + set(BLA_STATIC ON) + find_package(BLAS) + if (NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) + get_deps(https://github.com/xianyi/OpenBLAS/releases/download/v${version}/OpenBLAS-${version}.tar.gz OpenBLAS OpenBLAS-${version}.tar.gz) + if (NOT MSVC) + if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") + execute_process(COMMAND make TARGET=${OPENBLAS_TARGET} BINARY=${OPENBLAS_BINARY} HOSTCC=gcc CC=${CMAKE_C_COMPILER} FC=${CMAKE_FORTRAN_COMPILER} NO_SHARED=1 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}) + endif() + file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") + set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) + set(BLA_VENDOR OpenBLAS) + set(BLAS_FOUND ON) + endif() + endif() + find_library(GFORTRAN NAMES libgfortran.a) + find_library(PTHREAD NAMES libpthread.a) + set(COMPILER_SUPPORT_LIBRARIES ${COMPILER_SUPPORT_LIBRARIES} ${GFORTRAN} ${PTHREAD}) +endmacro() diff --git a/CMake/FindArmadillo.cmake b/CMake/FindArmadillo.cmake index 3d696b0abb..d0b5921684 100644 --- a/CMake/FindArmadillo.cmake +++ b/CMake/FindArmadillo.cmake @@ -91,12 +91,13 @@ if(NOT _ARMA_USE_WRAPPER OR MSVC) endif() endif() if(_ARMA_USE_BLAS) - if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED) - find_package(BLAS QUIET) + if(NOT BLAS_FOUND) + if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED) + find_package(BLAS QUIET) + else() + find_package(BLAS REQUIRED) + endif() else() - find_package(BLAS REQUIRED) - endif() - if(BLAS_FOUND) set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${BLAS_LIBRARIES}") endif() endif() From f717bd62c7e58918b598a3a21cc263e7b9c98b1e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 1 May 2021 14:18:39 +0200 Subject: [PATCH 260/729] Add crosscompile files, add flags for several architectures Signed-off-by: Omar Shrit --- board/crosscompile-toolchain.cmake | 41 +++++++++++++++++ board/flags-config.cmake | 74 ++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 board/crosscompile-toolchain.cmake create mode 100644 board/flags-config.cmake diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake new file mode 100644 index 0000000000..5bd40d5f6b --- /dev/null +++ b/board/crosscompile-toolchain.cmake @@ -0,0 +1,41 @@ +## This file handles cross-compilation configurations for aarch64, +## known as arm64. The objective of this file is to find and assign +## cross-compiler and the entire toolchain. +## It works best with buildroot toolchain, when using it the user +## needs to set the: TOOLCHAIN_PREFIX and CMAKE_SYSROOT from the +## command line. + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSROOT "" CACHE STRING "CMAKE_SYSROOT") +set(TOOLCHAIN_PREFIX "" CACHE STRING "TOOLCHAIN_PREFIX") + +## In some distribution, a dynamic link for aarch64-linux-gnu-gcc may not be +## found or created, instead it might be labeled with the version at the end +## For instance: aarch64-linux-gnu-gcc-5 +## Therefore, if dynamic link exists, you do not have to specify the version +set(VERSION_NUMBER "" CACHE STRING "Enter the version number of the compiler") + +# Without that flag CMake is not able to pass test compilation check +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_AR "${TOOLCHAIN_PREFIX}gcc-ar${VERSION_NUMBER}" CACHE FILEPATH "" FORCE) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc${VERSION_NUMBER}) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++${VERSION_NUMBER}) +set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}ld${VERSION_NUMBER}) +set(CMAKE_C_ARCHIVE_CREATE " qcs ") +set(CMAKE_C_ARCHIVE_FINISH true) +set(CMAKE_FORTRAN_COMPILER ${TOOLCHAIN_PREFIX}gfortran) +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy${VERSION_NUMBER} CACHE INTERNAL "objcopy tool") +set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size${VERSION_NUMBER} CACHE INTERNAL "size tool") + +## Here are the standard ROOT_PATH if you are using the standard toolchain +## if you are using a different toolchain you have to specify that too +set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}") + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${CMAKE_SYSROOT}" CACHE INTERNAL "" FORCE) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/board/flags-config.cmake b/board/flags-config.cmake new file mode 100644 index 0000000000..5e7eb0af59 --- /dev/null +++ b/board/flags-config.cmake @@ -0,0 +1,74 @@ +# This function provides a set of specific flags for each supported board +# Depending on the processor type. The objective is to optimize for size. +# Thus, all of the fllowing flags are chosen carefully to reduce binary +# footprints. + +# Set generic minimization flags for all platforms. +# These flags are the same for all cross-compilation cases. +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -fdata-sections -ffunction-sections") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer -fno-unwind-tables") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-asynchronous-unwind-tables -fvisibility=hidden") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fshort-enums -finline-small-functions") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -findirect-inlining -fno-common") +#-flto -fuse-ld=gold # There is an issue with gold link when compiling on +# Ubuntu 16. At that point gcc linker did not integrate the flto support +# inside and it was a separate plugin that need to be added. Therefore, +# this can be added when mlpack Azure CI moves toward Ubuntu 20. + +option(RPI0 "Optimize compiler flags for Raspberry PI 0." OFF) +option(RPI1 "Optimize compiler flags for Raspberry PI 1." OFF) +option(RPI2 "Optimize compiler flags for Raspberry PI 2." OFF) +option(RPI3 "Optimize compiler flags for Raspberry PI 3." OFF) +option(RPI4 "Optimize compiler flags for Raspberry PI 4." OFF) +option(BV "Optimize compiler flags for Beagleboard V." OFF) +option(JETSONAGX "Optimize compiler flags for Nvidia Jetson AGX Xavier." OFF) +option(KATAMI "Optimize compiler flags for Pentium 3 Katami processors." OFF) +option(COPPERMINE "Optimize compiler flags for Pentium 3 Coppermine processors." OFF) +option(NORTHWOOD "Optimize compiler flags for Pentium 4 Northwood processors." OFF) + +# Set specific platforms CMAKE CXX flags. +if(RPI0 OR RPI1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=arm1176jzf-s") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "ARMV6") + set(OPENBLAS_BINARY "32") +elseif(RPI2) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a7") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "ARMV7") + set(OPENBLAS_BINARY "32") +elseif(RPI3) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a53") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "CORTEXA53") + set(OPENBLAS_BINARY "64") +elseif(RPI4) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a72") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "CORTEXA72") + set(OPENBLAS_BINARY "64") +elseif(BV) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "RISCV64_GENERIC") + set(OPENBLAS_BINARY "64") +elseif(JETSONAGX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -matune=cortex-a76") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "ARM8") + set(OPENBLAS_BINARY "64") +elseif(KATAMI) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "KATAMI") + set(OPENBLAS_BINARY "32") +elseif(COPPERMINE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "COPPERMINE") + set(OPENBLAS_BINARY "32") +elseif(NORTHWOOD) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium4") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set(OPENBLAS_TARGET "NORTHWOOD") + set(OPENBLAS_BINARY "32") +endif() From 5eec177b74486c11744789b397f51b9cf5a8ee2b Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 1 May 2021 14:20:56 +0200 Subject: [PATCH 261/729] Add minor Cmake configuration to adapt crosscompilation Signed-off-by: Omar Shrit --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a2c55aaa0..ccba88c7f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(mlpack C CXX) include(CMake/cotire.cmake) include(CMake/CheckHash.cmake) include(CMake/Autodownload.cmake) +include(CMake/ConfigureCrossCompile.cmake) # First, define all the compilation options. # We default to debugging mode for developers. @@ -33,6 +34,9 @@ if (WIN32) set(DLL_COPY_DIRS "" CACHE STRING "List of directories (separated by ';') containing DLLs to copy for runtime.") set(DLL_COPY_LIBS "" CACHE STRING "List of DLLs (separated by ';') that should be copied for runtime.") +elseif(CMAKE_CROSSCOMPILING) + option(BUILD_SHARED_LIBS + "Compile shared libraries (if OFF, static libraries and binaries are compiled)." OFF) else() option(BUILD_SHARED_LIBS "Compile shared libraries (if OFF, static libraries and binaries are compiled)." ON) @@ -265,6 +269,10 @@ endif() # STB_IMAGE_INCLUDE_DIR - include directory for STB image library # MATHJAX_ROOT - root of MathJax installation +if (CMAKE_CROSSCOMPILING) + search_openblas(0.3.13) +endif() + if (DISABLE_DOWNLOADS) find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED) else() From 945346968168e49a4415e8205da74a6d7b6edeb4 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 3 May 2021 21:28:44 +0530 Subject: [PATCH 262/729] Changed Randomised -> Randomized --- src/mlpack/methods/random_forest/random_forest.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/random_forest/random_forest.hpp b/src/mlpack/methods/random_forest/random_forest.hpp index 1bfac12e6f..47c706392c 100644 --- a/src/mlpack/methods/random_forest/random_forest.hpp +++ b/src/mlpack/methods/random_forest/random_forest.hpp @@ -411,7 +411,7 @@ class RandomForest }; /** - * Convenience typedef for Extra Trees. (Extremely Randomised Trees Forest) + * Convenience typedef for Extra Trees. (Extremely Randomized Trees Forest) * * @code * @article{10.1007/s10994-006-6226-1, From 27227f553b234ebd2025fae497e66693e13edeb1 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 3 May 2021 21:32:37 +0530 Subject: [PATCH 263/729] Add random_split to CMakeLists.txt --- src/mlpack/methods/decision_tree/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/methods/decision_tree/CMakeLists.txt b/src/mlpack/methods/decision_tree/CMakeLists.txt index 68f5a2ef41..4072a5097d 100644 --- a/src/mlpack/methods/decision_tree/CMakeLists.txt +++ b/src/mlpack/methods/decision_tree/CMakeLists.txt @@ -11,6 +11,8 @@ set(SOURCES gini_gain.hpp information_gain.hpp multiple_random_dimension_select.hpp + random_binary_numeric_split.hpp + random_binary_numeric_split_impl.hpp random_dimension_select.hpp ) From a9b27768af16fc86a315279287fc24aabe62f28a Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 20:17:54 +0200 Subject: [PATCH 264/729] Add comments, set BLAS_openblas_LIBRARIES, reset FindArmadillo changes Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 9 +++++++++ CMake/FindArmadillo.cmake | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 023efc121b..58757da1b2 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -1,3 +1,10 @@ +# This file adds the necessary configurations to cross compile +# mlpack for embedde system. You need to set the following variables +# from the command line: the CMAKE_SYSROOT, TOOLCHAIN_PREFIX and the +# board type. +# This file will compile OpenBLAS if it is downloaded and it is not +# available on you system in order to find the BLAS library. + if (CMAKE_CROSSCOMPILING) include(board/flags-config.cmake) if(NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX)) @@ -23,6 +30,8 @@ macro(search_openblas version) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) + set(BLAS_openblas_LIBRARIES ${OPENBLAS_LIBRARIES}) + message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) endif() diff --git a/CMake/FindArmadillo.cmake b/CMake/FindArmadillo.cmake index d0b5921684..e1ba5b2221 100644 --- a/CMake/FindArmadillo.cmake +++ b/CMake/FindArmadillo.cmake @@ -91,13 +91,13 @@ if(NOT _ARMA_USE_WRAPPER OR MSVC) endif() endif() if(_ARMA_USE_BLAS) - if(NOT BLAS_FOUND) +# if(NOT BLAS_FOUND) if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED) find_package(BLAS QUIET) else() find_package(BLAS REQUIRED) endif() - else() + if(BLAS_FOUND) set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${BLAS_LIBRARIES}") endif() endif() From f877c57fbc4c50950a79bd4f4f51a427e6b05ed7 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 22:43:14 +0200 Subject: [PATCH 265/729] Update ConfigureCrossCompile.cmake --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 58757da1b2..77f73478f6 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -1,5 +1,5 @@ # This file adds the necessary configurations to cross compile -# mlpack for embedde system. You need to set the following variables +# mlpack for embedded systems. You need to set the following variables # from the command line: the CMAKE_SYSROOT, TOOLCHAIN_PREFIX and the # board type. # This file will compile OpenBLAS if it is downloaded and it is not From 921ec4fe72ce7d5e7533df93216796bdfe02702a Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:21:37 +0200 Subject: [PATCH 266/729] Print another message to see on CI Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 58757da1b2..1943f4a2bc 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -39,4 +39,5 @@ macro(search_openblas version) find_library(GFORTRAN NAMES libgfortran.a) find_library(PTHREAD NAMES libpthread.a) set(COMPILER_SUPPORT_LIBRARIES ${COMPILER_SUPPORT_LIBRARIES} ${GFORTRAN} ${PTHREAD}) + message(STATUS "SHOW BLAS libraries 2: ${BLAS_LIBRARIES}") endmacro() From 52330fe587c7950c4adb065d626ee7ecb4e0b416 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:25:50 +0200 Subject: [PATCH 267/729] Add dot in board/crosscompile-toolchain.cmake Co-authored-by: Marcus Edel --- board/crosscompile-toolchain.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index 5bd40d5f6b..ce65a4e089 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -12,7 +12,7 @@ set(TOOLCHAIN_PREFIX "" CACHE STRING "TOOLCHAIN_PREFIX") ## In some distribution, a dynamic link for aarch64-linux-gnu-gcc may not be ## found or created, instead it might be labeled with the version at the end ## For instance: aarch64-linux-gnu-gcc-5 -## Therefore, if dynamic link exists, you do not have to specify the version +## Therefore, if dynamic link exists, you do not have to specify the version. set(VERSION_NUMBER "" CACHE STRING "Enter the version number of the compiler") # Without that flag CMake is not able to pass test compilation check From 5889fa3cef38292f4d09cd6ee817bd9ead523955 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:26:23 +0200 Subject: [PATCH 268/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Marcus Edel --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index f20d168604..feaac23b33 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -3,7 +3,7 @@ # from the command line: the CMAKE_SYSROOT, TOOLCHAIN_PREFIX and the # board type. # This file will compile OpenBLAS if it is downloaded and it is not -# available on you system in order to find the BLAS library. +# available on your system in order to find the BLAS library. if (CMAKE_CROSSCOMPILING) include(board/flags-config.cmake) From b9bc2399e4897af2c10d28d520702296b72feb44 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:26:32 +0200 Subject: [PATCH 269/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Marcus Edel --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index feaac23b33..540f041a4b 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -12,7 +12,7 @@ if (CMAKE_CROSSCOMPILING) elseif(NOT CMAKE_SYSROOT) message(FATAL_ERROR "Can not proceed CMAKE_SYSROOT is not set") elseif(NOT TOOLCHAIN_PREFIX) - message(FATAL_ERROR "Cant not proceed TOOLCHAIN_PREFIXN is not set") + message(FATAL_ERROR "Cant not proceed TOOLCHAIN_PREFIX is not set") elseif(NOT OPENBLAS_TARGET) message(FATAL_ERROR "Cant not proceed, board name is not set, please refer to documentation") endif() From 09324718c160150395edfa3fa2d2d17db673de44 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:27:07 +0200 Subject: [PATCH 270/729] Fix style in CMake/ConfigureCrossCompile.cmake Co-authored-by: Marcus Edel --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 540f041a4b..bb813754a7 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -21,7 +21,7 @@ endif() macro(search_openblas version) set(BLA_STATIC ON) find_package(BLAS) - if (NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) + if(NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) get_deps(https://github.com/xianyi/OpenBLAS/releases/download/v${version}/OpenBLAS-${version}.tar.gz OpenBLAS OpenBLAS-${version}.tar.gz) if (NOT MSVC) if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") From 4ad7db5a30dac398bd9d8b6e774dc98f83db02b7 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:27:25 +0200 Subject: [PATCH 271/729] Add dot in board/crosscompile-toolchain.cmake Co-authored-by: Marcus Edel --- board/crosscompile-toolchain.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index ce65a4e089..7dd36333cf 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -15,7 +15,7 @@ set(TOOLCHAIN_PREFIX "" CACHE STRING "TOOLCHAIN_PREFIX") ## Therefore, if dynamic link exists, you do not have to specify the version. set(VERSION_NUMBER "" CACHE STRING "Enter the version number of the compiler") -# Without that flag CMake is not able to pass test compilation check +# Without that flag CMake is not able to pass test compilation check. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_AR "${TOOLCHAIN_PREFIX}gcc-ar${VERSION_NUMBER}" CACHE FILEPATH "" FORCE) From 9f56f2c94f5f120b12f8151bce18c436bba27a6e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:27:42 +0200 Subject: [PATCH 272/729] Add missing period in board/crosscompile-toolchain.cmake Co-authored-by: Marcus Edel --- board/crosscompile-toolchain.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index 7dd36333cf..bcbe612af4 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -30,7 +30,7 @@ set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy${VERSION_NUMBER} CACHE INTERNAL "ob set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size${VERSION_NUMBER} CACHE INTERNAL "size tool") ## Here are the standard ROOT_PATH if you are using the standard toolchain -## if you are using a different toolchain you have to specify that too +## if you are using a different toolchain you have to specify that too. set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${CMAKE_SYSROOT}" CACHE INTERNAL "" FORCE) From ae5db236072a7f17a3bec2e399ff68e26121e99b Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:37:46 +0200 Subject: [PATCH 273/729] Change back to board_name Signed-off-by: Omar Shrit --- board/flags-config.cmake | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 5e7eb0af59..ae65619e45 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -15,58 +15,49 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -findirect-inlining -fno-common") # inside and it was a separate plugin that need to be added. Therefore, # this can be added when mlpack Azure CI moves toward Ubuntu 20. -option(RPI0 "Optimize compiler flags for Raspberry PI 0." OFF) -option(RPI1 "Optimize compiler flags for Raspberry PI 1." OFF) -option(RPI2 "Optimize compiler flags for Raspberry PI 2." OFF) -option(RPI3 "Optimize compiler flags for Raspberry PI 3." OFF) -option(RPI4 "Optimize compiler flags for Raspberry PI 4." OFF) -option(BV "Optimize compiler flags for Beagleboard V." OFF) -option(JETSONAGX "Optimize compiler flags for Nvidia Jetson AGX Xavier." OFF) -option(KATAMI "Optimize compiler flags for Pentium 3 Katami processors." OFF) -option(COPPERMINE "Optimize compiler flags for Pentium 3 Coppermine processors." OFF) -option(NORTHWOOD "Optimize compiler flags for Pentium 4 Northwood processors." OFF) +set(BOARD_NAME "Optimize compiler flags for a specific board.") # Set specific platforms CMAKE CXX flags. -if(RPI0 OR RPI1) +if(BOARD_NAME MATCHES "RPI0" OR BOARD_NAME MATCHES "RPI1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=arm1176jzf-s") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "ARMV6") set(OPENBLAS_BINARY "32") -elseif(RPI2) +elseif(BOARD_NAME MATCHES "RPI2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a7") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "ARMV7") set(OPENBLAS_BINARY "32") -elseif(RPI3) +elseif(BOARD_NAME MATCHES "RPI3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a53") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "CORTEXA53") set(OPENBLAS_BINARY "64") -elseif(RPI4) +elseif(BOARD_NAME MATCHES "RPI4") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a72") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "CORTEXA72") set(OPENBLAS_BINARY "64") -elseif(BV) +elseif(BOARD_NAME MATCHES "BV") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "RISCV64_GENERIC") set(OPENBLAS_BINARY "64") -elseif(JETSONAGX) +elseif(BOARD_NAME MATCHES "JETSONAGX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -matune=cortex-a76") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "ARM8") set(OPENBLAS_BINARY "64") -elseif(KATAMI) +elseif(BOARD_NAME MATCHES "KATAMI") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "KATAMI") set(OPENBLAS_BINARY "32") -elseif(COPPERMINE) +elseif(BOARD_NAME MATCHES "COPPERMINE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "COPPERMINE") set(OPENBLAS_BINARY "32") -elseif(NORTHWOOD) +elseif(BOARD_NAME MATCHES "NORTHWOOD") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium4") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "NORTHWOOD") From aa989db797b146995b37d352597bf19574eedc5f Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 3 May 2021 23:51:15 +0200 Subject: [PATCH 274/729] Set up the variable correctly Signed-off-by: Omar Shrit --- board/flags-config.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index ae65619e45..83cf7ac46d 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -15,7 +15,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -findirect-inlining -fno-common") # inside and it was a separate plugin that need to be added. Therefore, # this can be added when mlpack Azure CI moves toward Ubuntu 20. -set(BOARD_NAME "Optimize compiler flags for a specific board.") +set(BOARD_NAME "" CACHE STRING "Specify Board name to optimize for.") # Set specific platforms CMAKE CXX flags. if(BOARD_NAME MATCHES "RPI0" OR BOARD_NAME MATCHES "RPI1") From ea5a69f4d1a0080bb54a97c4a73dc75a84baae3f Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 00:32:43 +0200 Subject: [PATCH 275/729] Set BLAS_openblas_LIBRARY instead of LIBRARIES Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index bb813754a7..45fb984acf 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -7,7 +7,7 @@ if (CMAKE_CROSSCOMPILING) include(board/flags-config.cmake) - if(NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX)) + if (NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX)) message(FATAL_ERROR "Neither of CMAKE_SYSROOT or TOOLCHAIN_PREFIX is set, please set both of them and try again") elseif(NOT CMAKE_SYSROOT) message(FATAL_ERROR "Can not proceed CMAKE_SYSROOT is not set") @@ -21,7 +21,7 @@ endif() macro(search_openblas version) set(BLA_STATIC ON) find_package(BLAS) - if(NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) + if (NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) get_deps(https://github.com/xianyi/OpenBLAS/releases/download/v${version}/OpenBLAS-${version}.tar.gz OpenBLAS OpenBLAS-${version}.tar.gz) if (NOT MSVC) if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") @@ -30,7 +30,7 @@ macro(search_openblas version) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) - set(BLAS_openblas_LIBRARIES ${OPENBLAS_LIBRARIES}) + set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) From f47788e3902e33562d682663659acadf525531a0 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 00:51:07 +0200 Subject: [PATCH 276/729] Remove BLAS_LIBRARIES and test without it Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 45fb984acf..87e47a6472 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -29,7 +29,7 @@ macro(search_openblas version) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") - set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) + # set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) From 45a531ccbbf2a46657301285fb4f84ec6ef63f1c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 01:09:45 +0200 Subject: [PATCH 277/729] Set LAPACK_openblas_LIBRARY ONLY Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 87e47a6472..498f71962a 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -30,7 +30,8 @@ macro(search_openblas version) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") # set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) - set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + # set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) From 2014891496bcd9bbbd3a62d4c120bc6c24a3962f Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 01:34:14 +0200 Subject: [PATCH 278/729] Try both lapack and blas for openblas Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 498f71962a..91b61b9bfb 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -30,7 +30,7 @@ macro(search_openblas version) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") # set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) - # set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) From f6ae407829f26bf43b323cabbd8e080097c8ab2c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 01:45:27 +0200 Subject: [PATCH 279/729] Test LAPACK and BLAS LIBRARIES Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 91b61b9bfb..3078d400db 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -29,9 +29,10 @@ macro(search_openblas version) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") - # set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) - set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) - set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) + set(LAPACK_LIBRARIES ${OPENBLAS_LIBRARIES}) + # set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + # set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) From 98413832a2f814e0b4569822adf0298a5ad2eb9d Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 15:42:14 +0200 Subject: [PATCH 280/729] Let us recheck LAPACK and BLAS Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 3078d400db..dea8e6e139 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -29,10 +29,10 @@ macro(search_openblas version) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") - set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) - set(LAPACK_LIBRARIES ${OPENBLAS_LIBRARIES}) - # set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) - # set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + # set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) + # set(LAPACK_LIBRARIES ${OPENBLAS_LIBRARIES}) + set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) From aeb09ea5af9c10eec1325c29e99f817ab99d47c9 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 15:49:50 +0200 Subject: [PATCH 281/729] Add comment for crosscompiling in CMakeLists Signed-off-by: Omar Shrit --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ccba88c7f8..749b1dea72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,6 +269,8 @@ endif() # STB_IMAGE_INCLUDE_DIR - include directory for STB image library # MATHJAX_ROOT - root of MathJax installation +# Download and compile OpenBLAS if we are cross compiling mlpack for a specific +# architecture. The function takes the version of OpenBLAS as variable. if (CMAKE_CROSSCOMPILING) search_openblas(0.3.13) endif() From 9e7902b18df5e4ffacf10727d6cbff68dd252305 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 16:01:58 +0200 Subject: [PATCH 282/729] TOUPPER string, add comments for buildroot Signed-off-by: Omar Shrit --- board/crosscompile-toolchain.cmake | 3 +++ board/flags-config.cmake | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index bcbe612af4..dc001ab6e8 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -4,6 +4,9 @@ ## It works best with buildroot toolchain, when using it the user ## needs to set the: TOOLCHAIN_PREFIX and CMAKE_SYSROOT from the ## command line. +## Currently, we recommend using buildroot toolchain for +## cross-compilation. Here is the link to download the toolchains: +## https://toolchains.bootlin.com/ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSROOT "" CACHE STRING "CMAKE_SYSROOT") diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 83cf7ac46d..5b0972f7c5 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -16,48 +16,49 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -findirect-inlining -fno-common") # this can be added when mlpack Azure CI moves toward Ubuntu 20. set(BOARD_NAME "" CACHE STRING "Specify Board name to optimize for.") +string(TOUPPER BOARD_NAME BOARD) # Set specific platforms CMAKE CXX flags. -if(BOARD_NAME MATCHES "RPI0" OR BOARD_NAME MATCHES "RPI1") +if(BOARD MATCHES "RPI0" OR BOARD MATCHES "RPI1") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=arm1176jzf-s") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "ARMV6") set(OPENBLAS_BINARY "32") -elseif(BOARD_NAME MATCHES "RPI2") +elseif(BOARD MATCHES "RPI2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a7") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "ARMV7") set(OPENBLAS_BINARY "32") -elseif(BOARD_NAME MATCHES "RPI3") +elseif(BOARD MATCHES "RPI3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a53") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "CORTEXA53") set(OPENBLAS_BINARY "64") -elseif(BOARD_NAME MATCHES "RPI4") +elseif(BOARD MATCHES "RPI4") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a72") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "CORTEXA72") set(OPENBLAS_BINARY "64") -elseif(BOARD_NAME MATCHES "BV") +elseif(BOARD MATCHES "BV") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "RISCV64_GENERIC") set(OPENBLAS_BINARY "64") -elseif(BOARD_NAME MATCHES "JETSONAGX") +elseif(BOARD MATCHES "JETSONAGX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -matune=cortex-a76") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "ARM8") set(OPENBLAS_BINARY "64") -elseif(BOARD_NAME MATCHES "KATAMI") +elseif(BOARD MATCHES "KATAMI") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "KATAMI") set(OPENBLAS_BINARY "32") -elseif(BOARD_NAME MATCHES "COPPERMINE") +elseif(BOARD MATCHES "COPPERMINE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "COPPERMINE") set(OPENBLAS_BINARY "32") -elseif(BOARD_NAME MATCHES "NORTHWOOD") +elseif(BOARD MATCHES "NORTHWOOD") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium4") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "NORTHWOOD") From 256e81d80b4cca8d27fb56473e0478d874299ee2 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 16:10:21 +0200 Subject: [PATCH 283/729] Move openblas check Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index dea8e6e139..41e8954802 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -13,8 +13,6 @@ if (CMAKE_CROSSCOMPILING) message(FATAL_ERROR "Can not proceed CMAKE_SYSROOT is not set") elseif(NOT TOOLCHAIN_PREFIX) message(FATAL_ERROR "Cant not proceed TOOLCHAIN_PREFIX is not set") - elseif(NOT OPENBLAS_TARGET) - message(FATAL_ERROR "Cant not proceed, board name is not set, please refer to documentation") endif() endif() @@ -22,6 +20,9 @@ macro(search_openblas version) set(BLA_STATIC ON) find_package(BLAS) if (NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) + if(NOT OPENBLAS_TARGET) + message(FATAL_ERROR "Cant not proceed, OPENBLAS_TARGET is not set, and to either set that or BOARD_NAME") + endif() get_deps(https://github.com/xianyi/OpenBLAS/releases/download/v${version}/OpenBLAS-${version}.tar.gz OpenBLAS OpenBLAS-${version}.tar.gz) if (NOT MSVC) if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") From 40472cf7b688c4f587b6e8eb186aff6507b63a98 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 16:28:21 +0200 Subject: [PATCH 284/729] Update boost link Signed-off-by: Omar Shrit --- CMakeLists.txt | 2 +- board/flags-config.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 749b1dea72..daf416f5e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -366,7 +366,7 @@ if (DISABLE_DOWNLOADS) else() find_package(Boost "${BOOST_VERSION}") if (NOT Boost_FOUND) - get_deps(https://dl.bintray.com/boostorg/release/1.75.0/source/boost_1_75_0.tar.gz boost boost_1_75_0.tar.gz) + get_deps(https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz boost boost_1_76_0.tar.gz) find_package(Boost REQUIRED) endif() endif() diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 5b0972f7c5..3c19e4a17b 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -16,7 +16,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -findirect-inlining -fno-common") # this can be added when mlpack Azure CI moves toward Ubuntu 20. set(BOARD_NAME "" CACHE STRING "Specify Board name to optimize for.") -string(TOUPPER BOARD_NAME BOARD) +string(TOUPPER ${BOARD_NAME} BOARD) # Set specific platforms CMAKE CXX flags. if(BOARD MATCHES "RPI0" OR BOARD MATCHES "RPI1") From 5c6533533a67a305d116c1e76be21e57341d9eca Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 4 May 2021 18:04:45 +0200 Subject: [PATCH 285/729] Cleaning, removing debugging symbols Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 4 ---- board/crosscompile-toolchain.cmake | 22 ++++++++-------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 41e8954802..92f305394b 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -30,11 +30,8 @@ macro(search_openblas version) WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") - # set(BLAS_LIBRARIES ${OPENBLAS_LIBRARIES}) - # set(LAPACK_LIBRARIES ${OPENBLAS_LIBRARIES}) set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) - message(STATUS "SHOW BLAS libraries: ${BLAS_LIBRARIES}") set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) endif() @@ -42,5 +39,4 @@ macro(search_openblas version) find_library(GFORTRAN NAMES libgfortran.a) find_library(PTHREAD NAMES libpthread.a) set(COMPILER_SUPPORT_LIBRARIES ${COMPILER_SUPPORT_LIBRARIES} ${GFORTRAN} ${PTHREAD}) - message(STATUS "SHOW BLAS libraries 2: ${BLAS_LIBRARIES}") endmacro() diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index dc001ab6e8..dfa8165492 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -9,28 +9,22 @@ ## https://toolchains.bootlin.com/ set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSROOT "" CACHE STRING "CMAKE_SYSROOT") -set(TOOLCHAIN_PREFIX "" CACHE STRING "TOOLCHAIN_PREFIX") - -## In some distribution, a dynamic link for aarch64-linux-gnu-gcc may not be -## found or created, instead it might be labeled with the version at the end -## For instance: aarch64-linux-gnu-gcc-5 -## Therefore, if dynamic link exists, you do not have to specify the version. -set(VERSION_NUMBER "" CACHE STRING "Enter the version number of the compiler") +set(CMAKE_SYSROOT) +set(TOOLCHAIN_PREFIX "" CACHE STRING "Path for Toolchain for cross compiler and other compilation tools.") # Without that flag CMake is not able to pass test compilation check. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -set(CMAKE_AR "${TOOLCHAIN_PREFIX}gcc-ar${VERSION_NUMBER}" CACHE FILEPATH "" FORCE) -set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc${VERSION_NUMBER}) -set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++${VERSION_NUMBER}) -set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}ld${VERSION_NUMBER}) +set(CMAKE_AR "${TOOLCHAIN_PREFIX}gcc-ar" CACHE FILEPATH "" FORCE) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++) +set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}ld) set(CMAKE_C_ARCHIVE_CREATE " qcs ") set(CMAKE_C_ARCHIVE_FINISH true) set(CMAKE_FORTRAN_COMPILER ${TOOLCHAIN_PREFIX}gfortran) set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) -set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy${VERSION_NUMBER} CACHE INTERNAL "objcopy tool") -set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size${VERSION_NUMBER} CACHE INTERNAL "size tool") +set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool") +set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool") ## Here are the standard ROOT_PATH if you are using the standard toolchain ## if you are using a different toolchain you have to specify that too. From e8bfd4a346edc13716d718fc22394627086874f4 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:06:31 +0200 Subject: [PATCH 286/729] Update board/flags-config.cmake Co-authored-by: Ryan Curtin --- board/flags-config.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 3c19e4a17b..67608d25b5 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -1,6 +1,6 @@ # This function provides a set of specific flags for each supported board # Depending on the processor type. The objective is to optimize for size. -# Thus, all of the fllowing flags are chosen carefully to reduce binary +# Thus, all of the following flags are chosen carefully to reduce binary # footprints. # Set generic minimization flags for all platforms. From 25314fdb4a8d8463bfea544890472e783ffa8e57 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:06:55 +0200 Subject: [PATCH 287/729] Update board/flags-config.cmake Co-authored-by: Ryan Curtin --- board/flags-config.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 67608d25b5..d3e2d981bf 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -1,5 +1,5 @@ # This function provides a set of specific flags for each supported board -# Depending on the processor type. The objective is to optimize for size. +# depending on the processor type. The objective is to optimize for size. # Thus, all of the following flags are chosen carefully to reduce binary # footprints. From 27d8752d9019e0ccc8f81c640afc15e396ddcece Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:07:30 +0200 Subject: [PATCH 288/729] Update board/crosscompile-toolchain.cmake Co-authored-by: Ryan Curtin --- board/crosscompile-toolchain.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index dfa8165492..2cf60770c1 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -12,7 +12,7 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSROOT) set(TOOLCHAIN_PREFIX "" CACHE STRING "Path for Toolchain for cross compiler and other compilation tools.") -# Without that flag CMake is not able to pass test compilation check. +# Ensure that CMake tries to build static libraries when testing the compiler. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_AR "${TOOLCHAIN_PREFIX}gcc-ar" CACHE FILEPATH "" FORCE) From da96df8762d732105e593443722c946c2c319afe Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:08:17 +0200 Subject: [PATCH 289/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Ryan Curtin --- CMake/ConfigureCrossCompile.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 92f305394b..b9927a5e66 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -1,7 +1,6 @@ # This file adds the necessary configurations to cross compile # mlpack for embedded systems. You need to set the following variables -# from the command line: the CMAKE_SYSROOT, TOOLCHAIN_PREFIX and the -# board type. +# from the command line: CMAKE_SYSROOT and TOOLCHAIN_PREFIX. # This file will compile OpenBLAS if it is downloaded and it is not # available on your system in order to find the BLAS library. From 860db2558499f2f485c20c281178159f95adf9b4 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:09:04 +0200 Subject: [PATCH 290/729] Correct comments in CMake/ConfigureCrossCompile.cmake Co-authored-by: Ryan Curtin --- CMake/ConfigureCrossCompile.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index b9927a5e66..2d29ec80a8 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -2,7 +2,10 @@ # mlpack for embedded systems. You need to set the following variables # from the command line: CMAKE_SYSROOT and TOOLCHAIN_PREFIX. # This file will compile OpenBLAS if it is downloaded and it is not -# available on your system in order to find the BLAS library. +# available on your system in order to find the BLAS library. If OpenBLAS will +# be compiled, the OPENBLAS_TARGET variable must be set. This can be done +# by, e.g., setting BOARD_NAME (which will set OPENBLAS_TARGET in +# `board/flags-config.cmake`). if (CMAKE_CROSSCOMPILING) include(board/flags-config.cmake) From 188cc167a26223ab0f960b48ffaf235861669b21 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:09:42 +0200 Subject: [PATCH 291/729] Update board/crosscompile-toolchain.cmake Co-authored-by: Ryan Curtin --- board/crosscompile-toolchain.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index 2cf60770c1..2adb64152c 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -1,9 +1,11 @@ ## This file handles cross-compilation configurations for aarch64, ## known as arm64. The objective of this file is to find and assign ## cross-compiler and the entire toolchain. -## It works best with buildroot toolchain, when using it the user -## needs to set the: TOOLCHAIN_PREFIX and CMAKE_SYSROOT from the -## command line. +## +## This configuration works best with the buildroot toolchain. When using this +## file, be sure to set the TOOLCHAIN_PREFIX and CMAKE_SYSROOT variables, +## preferably via the CMake configuration command (e.g. `-DCMAKE_SYSROOT=<...>`). +## ## Currently, we recommend using buildroot toolchain for ## cross-compilation. Here is the link to download the toolchains: ## https://toolchains.bootlin.com/ From 786636b1114caebd44da3d37596c7630aa3341e5 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:17:58 +0200 Subject: [PATCH 292/729] Revert changes in FindArmadillo Signed-off-by: Omar Shrit --- CMake/FindArmadillo.cmake | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CMake/FindArmadillo.cmake b/CMake/FindArmadillo.cmake index e1ba5b2221..3d696b0abb 100644 --- a/CMake/FindArmadillo.cmake +++ b/CMake/FindArmadillo.cmake @@ -91,12 +91,11 @@ if(NOT _ARMA_USE_WRAPPER OR MSVC) endif() endif() if(_ARMA_USE_BLAS) -# if(NOT BLAS_FOUND) - if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED) - find_package(BLAS QUIET) - else() - find_package(BLAS REQUIRED) - endif() + if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED) + find_package(BLAS QUIET) + else() + find_package(BLAS REQUIRED) + endif() if(BLAS_FOUND) set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${BLAS_LIBRARIES}") endif() From 6564c8ec97742a2e8643b10d43f8309f3006c7d9 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 5 May 2021 00:22:24 +0200 Subject: [PATCH 293/729] Add an elseif(board) if the board is not known Signed-off-by: Omar Shrit --- board/flags-config.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index d3e2d981bf..349c55068d 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -63,4 +63,6 @@ elseif(BOARD MATCHES "NORTHWOOD") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(OPENBLAS_TARGET "NORTHWOOD") set(OPENBLAS_BINARY "32") +elseif(BOARD) + message(FATAL_ERROR "Board type is not known, please choose a supported board from the list") endif() From dbd882707b2d880429b89abf80ce4b0bded08192 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 5 May 2021 09:50:30 +0530 Subject: [PATCH 294/729] undo changes --- src/mlpack/bindings/cli/add_to_cli11.hpp | 4 +-- src/mlpack/bindings/cli/cli_option.hpp | 6 +--- src/mlpack/bindings/cli/get_param.hpp | 12 ++----- .../bindings/cli/get_printable_param_impl.hpp | 10 +++--- src/mlpack/bindings/cli/get_raw_param.hpp | 2 +- src/mlpack/bindings/cli/in_place_copy.hpp | 34 ++++-------------- src/mlpack/bindings/cli/output_param_impl.hpp | 4 +-- src/mlpack/bindings/cli/set_param.hpp | 6 ++-- src/mlpack/tests/cli_binding_test.cpp | 36 +++++++++---------- 9 files changed, 41 insertions(+), 73 deletions(-) diff --git a/src/mlpack/bindings/cli/add_to_cli11.hpp b/src/mlpack/bindings/cli/add_to_cli11.hpp index 0e2c93ea0e..f4ae48a608 100644 --- a/src/mlpack/bindings/cli/add_to_cli11.hpp +++ b/src/mlpack/bindings/cli/add_to_cli11.hpp @@ -46,7 +46,7 @@ void AddToCLI11(const std::string& cliName, app.add_option_function(cliName.c_str(), [¶m](const std::string& value) { - using TupleType = std::tuple::type, size_t, size_t>; + using TupleType = std::tuple::type>; TupleType& tuple = *boost::any_cast(¶m.value); std::get<1>(tuple) = boost::any_cast(value); param.wasPassed = true; @@ -108,7 +108,7 @@ void AddToCLI11(const std::string& cliName, app.add_option_function(cliName.c_str(), [¶m](const std::string& value) { - using TupleType = std::tuple::type, size_t, size_t>; + using TupleType = std::tuple::type>; TupleType& tuple = *boost::any_cast(¶m.value); std::get<1>(tuple) = boost::any_cast(value); param.wasPassed = true; diff --git a/src/mlpack/bindings/cli/cli_option.hpp b/src/mlpack/bindings/cli/cli_option.hpp index 10ae7ddc1b..eeebc2d7cc 100644 --- a/src/mlpack/bindings/cli/cli_option.hpp +++ b/src/mlpack/bindings/cli/cli_option.hpp @@ -100,11 +100,7 @@ class CLIOption else { typename ParameterType::type>::type tmp; - if(arma::is_arma_type::value || - std::is_same>::value) - data.value = boost::any(std::tuple(defaultValue, tmp, 0, 0)); - else - data.value = boost::any(std::tuple(defaultValue, tmp)); + data.value = boost::any(std::tuple(defaultValue, tmp)); } const std::string tname = data.tname; diff --git a/src/mlpack/bindings/cli/get_param.hpp b/src/mlpack/bindings/cli/get_param.hpp index b5b23f65ee..eaaa813d61 100644 --- a/src/mlpack/bindings/cli/get_param.hpp +++ b/src/mlpack/bindings/cli/get_param.hpp @@ -51,12 +51,10 @@ T& GetParam( // contains the filename. It's possible we could load empty matrices many // times, but I am not bothered by that---it shouldn't be something that // happens. - typedef std::tuple::type, size_t, size_t> TupleType; + typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); const std::string& value = std::get<1>(tuple); T& matrix = std::get<0>(tuple); - size_t& n_rows = std::get<2>(tuple); - size_t& n_cols = std::get<3>(tuple); if (d.input && !d.loaded) { // Call correct data::Load() function. @@ -64,8 +62,6 @@ T& GetParam( data::Load(value, matrix, true); else data::Load(value, matrix, true, !d.noTranspose); - n_rows = matrix.n_rows; - n_cols = matrix.n_cols; d.loaded = true; } @@ -85,17 +81,13 @@ T& GetParam( { // If this is an input parameter, we need to load both the matrix and the // dataset info. - typedef std::tuple TupleType; + typedef std::tuple TupleType; TupleType* tuple = boost::any_cast(&d.value); const std::string& value = std::get<1>(*tuple); T& t = std::get<0>(*tuple); - size_t& n_rows = std::get<2>(*tuple); - size_t& n_cols = std::get<3>(*tuple); if (d.input && !d.loaded) { data::Load(value, std::get<1>(t), std::get<0>(t), true, !d.noTranspose); - n_rows = std::get<1>(t).n_rows; - n_cols = std::get<1>(t).n_cols; d.loaded = true; } diff --git a/src/mlpack/bindings/cli/get_printable_param_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_impl.hpp index 89e0c75fe7..9e2584f6b5 100644 --- a/src/mlpack/bindings/cli/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_impl.hpp @@ -79,7 +79,7 @@ std::string GetPrintableParam( std::tuple>::value>::type* /* junk */) { // Extract the string from the tuple that's being held. - typedef std::tuple::type, size_t, size_t> TupleType; + typedef std::tuple::type> TupleType; const TupleType* tuple = boost::any_cast(&data.value); std::ostringstream oss; @@ -87,10 +87,10 @@ std::string GetPrintableParam( if (std::get<1>(*tuple) != "") { - // make sure that the matrix is loaded, so that we can print its size. - GetParam(const_cast(data)); - std::string matDescription = std::to_string(std::get<2>(*tuple)) + "x"; - matDescription += std::to_string(std::get<3>(*tuple)) + " matrix"; + // Make sure the matrix is loaded so that we can print its size. + T& mat = GetParam(const_cast(data)); + std::string matDescription = GetMatrixSize(mat); + oss << " (" << matDescription << ")"; } diff --git a/src/mlpack/bindings/cli/get_raw_param.hpp b/src/mlpack/bindings/cli/get_raw_param.hpp index a0305df23c..35d544f08b 100644 --- a/src/mlpack/bindings/cli/get_raw_param.hpp +++ b/src/mlpack/bindings/cli/get_raw_param.hpp @@ -48,7 +48,7 @@ T& GetRawParam( arma::mat>>::value>::type* = 0) { // Don't load the matrix. - typedef std::tuple TupleType; + typedef std::tuple TupleType; T& value = std::get<0>(*boost::any_cast(&d.value)); return value; } diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index 97ce2430b9..ca0d7667f5 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -41,7 +41,7 @@ void InPlaceCopyInternal( /** * Modify the filename for any type that needs to be loaded from disk to match - * the filename of the input parameter. For matrix/dataset info. + * the filename of the input parameter. * * @param d ParamData object we want to make into an in-place copy. * @param input ParamData object whose filename we should copy. @@ -50,34 +50,14 @@ template void InPlaceCopyInternal( util::ParamData& d, util::ParamData& input, - const typename std::enable_if::value || - std::is_same>::value>::type* = 0) + const typename std::enable_if< + arma::is_arma_type::value || + std::is_same>::value || + data::HasSerialize::value>::type* = 0) { // Make the output filename the same as the input filename. - typedef std::tuple::type, size_t, size_t> TupleType; - TupleType& tuple = *boost::any_cast(&d.value); - std::string& value = std::get<1>(tuple); - - const TupleType& inputTuple = *boost::any_cast(&input.value); - value = std::get<1>(inputTuple); -} - -/** - * Modify the filename for any type that needs to be loaded from disk to match - * the filename of the input parameter. For serializable object. - * - * @param d ParamData object we want to make into an in-place copy. - * @param input ParamData object whose filename we should copy. - */ -template -void InPlaceCopyInternal( - util::ParamData& d, - util::ParamData& input, - const typename std::enable_if::value>::type* = 0) -{ - // Make the output filename the same as the input filename. - typedef std::tuple::type> TupleType; + typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); std::string& value = std::get<1>(tuple); diff --git a/src/mlpack/bindings/cli/output_param_impl.hpp b/src/mlpack/bindings/cli/output_param_impl.hpp index 0bc0a5a75c..c4dcfddbf4 100644 --- a/src/mlpack/bindings/cli/output_param_impl.hpp +++ b/src/mlpack/bindings/cli/output_param_impl.hpp @@ -53,7 +53,7 @@ void OutputParamImpl( util::ParamData& data, const typename boost::enable_if>::type* /* junk */) { - typedef std::tuple TupleType; + typedef std::tuple TupleType; const T& output = std::get<0>(*boost::any_cast(&data.value)); const std::string& filename = std::get<1>(*boost::any_cast(&data.value)); @@ -95,7 +95,7 @@ void OutputParamImpl( std::tuple>>::type* /* junk */) { // Output the matrix with the mappings. - typedef std::tuple TupleType; + typedef std::tuple TupleType; const T& tuple = std::get<0>(*boost::any_cast(&data.value)); const std::string& filename = std::get<1>(*boost::any_cast(&data.value)); diff --git a/src/mlpack/bindings/cli/set_param.hpp b/src/mlpack/bindings/cli/set_param.hpp index 10e265d52d..8295b51242 100644 --- a/src/mlpack/bindings/cli/set_param.hpp +++ b/src/mlpack/bindings/cli/set_param.hpp @@ -51,8 +51,8 @@ void SetParam( } /** - * Set a matrix parameter, a matrix/dataset info parameter. - * These set the filename referring to the parameter. + * Set a matrix parameter, a matrix/dataset info parameter, or a serializable + * object. These set the filename referring to the parameter. */ template void SetParam( @@ -63,7 +63,7 @@ void SetParam( std::tuple>::value>::type* = 0) { // We're setting the string filename. - typedef std::tuple::type, size_t, size_t> TupleType; + typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); std::get<1>(tuple) = boost::any_cast(value); } diff --git a/src/mlpack/tests/cli_binding_test.cpp b/src/mlpack/tests/cli_binding_test.cpp index 10532572a0..391a0bfe1a 100644 --- a/src/mlpack/tests/cli_binding_test.cpp +++ b/src/mlpack/tests/cli_binding_test.cpp @@ -82,7 +82,7 @@ TEST_CASE("GetParamLoadedMatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::ones); - tuple tuple = make_tuple(m, filename, 0, 0); + tuple tuple = make_tuple(m, filename); d.value = boost::any(tuple); // Mark it as already loaded. d.input = true; @@ -106,7 +106,7 @@ TEST_CASE("GetParamUnloadedMatTest", "[CLIOptionTest]") arma::mat test(5, 5, arma::fill::ones); data::Save("test.csv", test); arma::mat m; - tuple tuple = make_tuple(m, filename, 0, 0); + tuple tuple = make_tuple(m, filename); d.value = boost::any(tuple); // Make sure it is not loaded yet. d.input = true; @@ -132,7 +132,7 @@ TEST_CASE("GetParamUmatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::Mat m(5, 5, arma::fill::ones); - tuple, string, size_t, size_t> tuple = make_tuple(m, filename, 0, 0); + tuple, string> tuple = make_tuple(m, filename); d.value = boost::any(tuple); // Mark it as already loaded. d.input = true; @@ -157,7 +157,7 @@ TEST_CASE("GetParamUnloadedUmatTest", "[CLIOptionTest]") arma::Mat test(5, 5, arma::fill::ones); data::Save("test.csv", test); arma::Mat m; - tuple, string, size_t, size_t> tuple = make_tuple(m, filename, 0, 0); + tuple, string> tuple = make_tuple(m, filename); d.value = boost::any(tuple); // Make sure it is not loaded yet. d.input = true; @@ -200,7 +200,7 @@ TEST_CASE("GetParamDatasetInfoMatTest", "[CLIOptionTest]") arma::mat m; tuple tuple1 = make_tuple(dd, m); - tuple tuple2 = make_tuple(tuple1, filename, 0, 0); + tuple tuple2 = make_tuple(tuple1, filename); d.value = boost::any(tuple2); // Make sure it is not loaded yet. @@ -274,7 +274,7 @@ TEST_CASE("RawParamMatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::ones); - tuple tuple = make_tuple(m, filename, 0, 0); + tuple tuple = make_tuple(m, filename); d.value = boost::any(tuple); d.input = true; d.loaded = false; @@ -324,7 +324,7 @@ TEST_CASE("GetRawParamDatasetInfoTest", "[CLIOptionTest]") arma::mat m(3, 3, arma::fill::randu); tuple tuple1 = make_tuple(dd, m); - tuple tuple2 = make_tuple(tuple1, filename, 0, 0); + tuple tuple2 = make_tuple(tuple1, filename); d.value = boost::any(tuple2); // Make sure it is not loaded yet. @@ -350,7 +350,7 @@ TEST_CASE("OutputParamMatTest", "[CLIOptionTest]") // Create value. string filename = "test.csv"; arma::mat m(3, 3, arma::fill::randu); - tuple t = make_tuple(m, filename, 0, 0); + tuple t = make_tuple(m, filename); d.value = boost::any(t); d.input = false; @@ -376,7 +376,7 @@ TEST_CASE("OutputParamUmatTest", "[CLIOptionTest]") // Create value. string filename = "test.csv"; arma::Mat m(3, 3, arma::fill::randu); - tuple, string, size_t, size_t> t = make_tuple(m, filename, 0, 0); + tuple, string> t = make_tuple(m, filename); d.value = boost::any(t); d.input = false; @@ -467,7 +467,7 @@ TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]") // Create initial value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::randu); - d.value = boost::any(make_tuple(m, filename, size_t(0), size_t(0))); + d.value = boost::any(make_tuple(m, filename)); // Get a new string. string newFilename = "new.csv"; @@ -475,9 +475,10 @@ TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]") SetParam((util::ParamData&) d, (const void*) &a2, (void*) NULL); + // Make sure the change went through. - tuple& t = - *boost::any_cast>(&d.value); + tuple& t = + *boost::any_cast>(&d.value); REQUIRE(get<1>(t) == "new.csv"); } @@ -517,8 +518,7 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") arma::mat m(3, 3, arma::fill::randu); DatasetInfo di(3); tuple t1 = make_tuple(di, m); - tuple, string, size_t, size_t> t2 = make_tuple(t1, filename, - size_t(0), size_t(0)); + tuple, string> t2 = make_tuple(t1, filename); d.value = boost::any(t2); d.noTranspose = false; @@ -530,8 +530,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") (const void*) &a2, (void*) NULL); // Check that the name is right. - tuple, string, size_t, size_t>& t3 = - *boost::any_cast, string, size_t, size_t>>(&d.value); + tuple, string>& t3 = + *boost::any_cast, string>>(&d.value); REQUIRE(get<1>(t3) == "new_filename.csv"); } @@ -556,7 +556,7 @@ TEST_CASE("GetAllocatedMemoryNonModelTest", "[CLIOptionTest]") // Also test with a matrix type. arma::mat test(10, 10, arma::fill::ones); string filename = "test.csv"; - tuple t = make_tuple(test, filename, 0, 0); + tuple t = make_tuple(test, filename); d.value = boost::any(t); result = (void*) 1; @@ -602,7 +602,7 @@ TEST_CASE("DeleteAllocatedMemoryNonModelTest", "[CLIOptionTest]") arma::mat test(10, 10, arma::fill::ones); string filename = "test.csv"; - tuple t = make_tuple(test, filename, 0, 0); + tuple t = make_tuple(test, filename); d.value = boost::any(t); DeleteAllocatedMemory((util::ParamData&) d, From c53ab383487d893629ebf2c8e27074ea0df3e927 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 5 May 2021 19:00:16 +0530 Subject: [PATCH 295/729] made recommended changes --- src/mlpack/bindings/cli/add_to_cli11.hpp | 4 +-- src/mlpack/bindings/cli/get_param.hpp | 14 ++++++++-- .../bindings/cli/get_printable_param_impl.hpp | 9 +++--- src/mlpack/bindings/cli/get_raw_param.hpp | 2 +- src/mlpack/bindings/cli/in_place_copy.hpp | 28 +++++++++++++++++-- src/mlpack/bindings/cli/output_param_impl.hpp | 8 +++--- src/mlpack/bindings/cli/parameter_type.hpp | 8 +++--- src/mlpack/bindings/cli/set_param.hpp | 6 ++-- 8 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/mlpack/bindings/cli/add_to_cli11.hpp b/src/mlpack/bindings/cli/add_to_cli11.hpp index f4ae48a608..ceb03c64e2 100644 --- a/src/mlpack/bindings/cli/add_to_cli11.hpp +++ b/src/mlpack/bindings/cli/add_to_cli11.hpp @@ -48,7 +48,7 @@ void AddToCLI11(const std::string& cliName, { using TupleType = std::tuple::type>; TupleType& tuple = *boost::any_cast(¶m.value); - std::get<1>(tuple) = boost::any_cast(value); + std::get<0>(std::get<1>(tuple)) = boost::any_cast(value); param.wasPassed = true; }, param.desc.c_str()); @@ -110,7 +110,7 @@ void AddToCLI11(const std::string& cliName, { using TupleType = std::tuple::type>; TupleType& tuple = *boost::any_cast(¶m.value); - std::get<1>(tuple) = boost::any_cast(value); + std::get<0>(std::get<1>(tuple)) = boost::any_cast(value); param.wasPassed = true; }, param.desc.c_str()); diff --git a/src/mlpack/bindings/cli/get_param.hpp b/src/mlpack/bindings/cli/get_param.hpp index eaaa813d61..d401e0e554 100644 --- a/src/mlpack/bindings/cli/get_param.hpp +++ b/src/mlpack/bindings/cli/get_param.hpp @@ -53,8 +53,10 @@ T& GetParam( // happens. typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); - const std::string& value = std::get<1>(tuple); + const std::string& value = std::get<0>(std::get<1>(tuple)); T& matrix = std::get<0>(tuple); + size_t& n_rows = std::get<1>(std::get<1>(tuple)); + size_t& n_cols = std::get<2>(std::get<1>(tuple)); if (d.input && !d.loaded) { // Call correct data::Load() function. @@ -62,6 +64,8 @@ T& GetParam( data::Load(value, matrix, true); else data::Load(value, matrix, true, !d.noTranspose); + n_rows = matrix.n_rows; + n_cols = matrix.n_cols; d.loaded = true; } @@ -81,13 +85,17 @@ T& GetParam( { // If this is an input parameter, we need to load both the matrix and the // dataset info. - typedef std::tuple TupleType; + typedef std::tuple> TupleType; TupleType* tuple = boost::any_cast(&d.value); - const std::string& value = std::get<1>(*tuple); + const std::string& value = std::get<0>(std::get<1>(*tuple)); T& t = std::get<0>(*tuple); + size_t& n_rows = std::get<1>(std::get<1>(*tuple)); + size_t& n_cols = std::get<2>(std::get<1>(*tuple)); if (d.input && !d.loaded) { data::Load(value, std::get<1>(t), std::get<0>(t), true, !d.noTranspose); + n_rows = std::get<1>(t).n_rows; + n_cols = std::get<1>(t).n_cols; d.loaded = true; } diff --git a/src/mlpack/bindings/cli/get_printable_param_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_impl.hpp index 9e2584f6b5..8a3cb211cb 100644 --- a/src/mlpack/bindings/cli/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_impl.hpp @@ -83,13 +83,14 @@ std::string GetPrintableParam( const TupleType* tuple = boost::any_cast(&data.value); std::ostringstream oss; - oss << "'" << std::get<1>(*tuple) << "'"; + oss << "'" << std::get<0>(std::get<1>(*tuple)) << "'"; - if (std::get<1>(*tuple) != "") + if (std::get<0>(std::get<1>(*tuple)) != "") { // Make sure the matrix is loaded so that we can print its size. - T& mat = GetParam(const_cast(data)); - std::string matDescription = GetMatrixSize(mat); + GetParam(const_cast(data)); + std::string matDescription = std::to_string(std::get<1>(std::get<1>(*tuple))) + "x"; + matDescription += std::to_string(std::get<2>(std::get<1>(*tuple))) + " matrix"; oss << " (" << matDescription << ")"; } diff --git a/src/mlpack/bindings/cli/get_raw_param.hpp b/src/mlpack/bindings/cli/get_raw_param.hpp index 35d544f08b..46c3956a1f 100644 --- a/src/mlpack/bindings/cli/get_raw_param.hpp +++ b/src/mlpack/bindings/cli/get_raw_param.hpp @@ -48,7 +48,7 @@ T& GetRawParam( arma::mat>>::value>::type* = 0) { // Don't load the matrix. - typedef std::tuple TupleType; + typedef std::tuple> TupleType; T& value = std::get<0>(*boost::any_cast(&d.value)); return value; } diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index ca0d7667f5..e2094e53d4 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -41,7 +41,7 @@ void InPlaceCopyInternal( /** * Modify the filename for any type that needs to be loaded from disk to match - * the filename of the input parameter. + * the filename of the input parameter. For matrix/datasetinfo parameter. * * @param d ParamData object we want to make into an in-place copy. * @param input ParamData object whose filename we should copy. @@ -53,12 +53,34 @@ void InPlaceCopyInternal( const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value || - data::HasSerialize::value>::type* = 0) + std::tuple>::value>::type* = 0) { // Make the output filename the same as the input filename. typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); + std::string& value = std::get<0>(std::get<1>(tuple)); + + const TupleType& inputTuple = *boost::any_cast(&input.value); + value = std::get<0>(std::get<1>(inputTuple)); +} + +/** + * Modify the filename for any type that needs to be loaded from disk to match + * the filename of the input parameter. For Serializable object. + * + * @param d ParamData object we want to make into an in-place copy. + * @param input ParamData object whose filename we should copy. + */ +template +void InPlaceCopyInternal( + util::ParamData& d, + util::ParamData& input, + const typename std::enable_if< + data::HasSerialize::value>::type* = 0) +{ + // Make the output filename the same as the input filename. + typedef std::tuple::type> TupleType; + TupleType& tuple = *boost::any_cast(&d.value); std::string& value = std::get<1>(tuple); const TupleType& inputTuple = *boost::any_cast(&input.value); diff --git a/src/mlpack/bindings/cli/output_param_impl.hpp b/src/mlpack/bindings/cli/output_param_impl.hpp index c4dcfddbf4..ab2f1e8822 100644 --- a/src/mlpack/bindings/cli/output_param_impl.hpp +++ b/src/mlpack/bindings/cli/output_param_impl.hpp @@ -53,10 +53,10 @@ void OutputParamImpl( util::ParamData& data, const typename boost::enable_if>::type* /* junk */) { - typedef std::tuple TupleType; + typedef std::tuple> TupleType; const T& output = std::get<0>(*boost::any_cast(&data.value)); const std::string& filename = - std::get<1>(*boost::any_cast(&data.value)); + std::get<0>(std::get<1>(*boost::any_cast(&data.value))); if (output.n_elem > 0 && filename != "") { @@ -95,10 +95,10 @@ void OutputParamImpl( std::tuple>>::type* /* junk */) { // Output the matrix with the mappings. - typedef std::tuple TupleType; + typedef std::tuple> TupleType; const T& tuple = std::get<0>(*boost::any_cast(&data.value)); const std::string& filename = - std::get<1>(*boost::any_cast(&data.value)); + std::get<0>(std::get<1>(*boost::any_cast(&data.value))); const arma::mat& matrix = std::get<1>(tuple); // The mapping isn't taken into account. We should write a data::Save() diff --git a/src/mlpack/bindings/cli/parameter_type.hpp b/src/mlpack/bindings/cli/parameter_type.hpp index ddc289ae32..036240b375 100644 --- a/src/mlpack/bindings/cli/parameter_type.hpp +++ b/src/mlpack/bindings/cli/parameter_type.hpp @@ -53,7 +53,7 @@ struct ParameterType template struct ParameterType> { - typedef std::string type; + typedef std::tuple type; }; /** @@ -65,7 +65,7 @@ struct ParameterType> template struct ParameterType> { - typedef std::string type; + typedef std::tuple type; }; /** @@ -76,7 +76,7 @@ struct ParameterType> template struct ParameterType> { - typedef std::string type; + typedef std::tuple type; }; /** @@ -86,7 +86,7 @@ template struct ParameterType, arma::Mat>> { - typedef std::string type; + typedef std::tuple type; }; } // namespace cli diff --git a/src/mlpack/bindings/cli/set_param.hpp b/src/mlpack/bindings/cli/set_param.hpp index 8295b51242..f800fe0553 100644 --- a/src/mlpack/bindings/cli/set_param.hpp +++ b/src/mlpack/bindings/cli/set_param.hpp @@ -51,8 +51,8 @@ void SetParam( } /** - * Set a matrix parameter, a matrix/dataset info parameter, or a serializable - * object. These set the filename referring to the parameter. + * Set a matrix parameter, a matrix/dataset info parameter. + * These set the filename referring to the parameter. */ template void SetParam( @@ -65,7 +65,7 @@ void SetParam( // We're setting the string filename. typedef std::tuple::type> TupleType; TupleType& tuple = *boost::any_cast(&d.value); - std::get<1>(tuple) = boost::any_cast(value); + std::get<0>(std::get<1>(tuple)) = boost::any_cast(value); } /** From e1713a4dbc5d233a0b16df173f39e8cbcfec1f66 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 5 May 2021 23:21:37 +0530 Subject: [PATCH 296/729] fixing tests 3 --- src/mlpack/tests/cli_binding_test.cpp | 65 ++++++++++++++++++--------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/src/mlpack/tests/cli_binding_test.cpp b/src/mlpack/tests/cli_binding_test.cpp index 391a0bfe1a..76cf6a652d 100644 --- a/src/mlpack/tests/cli_binding_test.cpp +++ b/src/mlpack/tests/cli_binding_test.cpp @@ -82,7 +82,9 @@ TEST_CASE("GetParamLoadedMatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::ones); - tuple tuple = make_tuple(m, filename); + typedef std::tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple tuple = make_tuple(m, testTuple); d.value = boost::any(tuple); // Mark it as already loaded. d.input = true; @@ -106,7 +108,9 @@ TEST_CASE("GetParamUnloadedMatTest", "[CLIOptionTest]") arma::mat test(5, 5, arma::fill::ones); data::Save("test.csv", test); arma::mat m; - tuple tuple = make_tuple(m, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple tuple = make_tuple(m, testTuple); d.value = boost::any(tuple); // Make sure it is not loaded yet. d.input = true; @@ -132,7 +136,9 @@ TEST_CASE("GetParamUmatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::Mat m(5, 5, arma::fill::ones); - tuple, string> tuple = make_tuple(m, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple, TupleType> tuple = make_tuple(m, testTuple); d.value = boost::any(tuple); // Mark it as already loaded. d.input = true; @@ -157,7 +163,9 @@ TEST_CASE("GetParamUnloadedUmatTest", "[CLIOptionTest]") arma::Mat test(5, 5, arma::fill::ones); data::Save("test.csv", test); arma::Mat m; - tuple, string> tuple = make_tuple(m, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple, TupleType> tuple = make_tuple(m, testTuple); d.value = boost::any(tuple); // Make sure it is not loaded yet. d.input = true; @@ -199,8 +207,10 @@ TEST_CASE("GetParamDatasetInfoMatTest", "[CLIOptionTest]") data::DatasetInfo dd; arma::mat m; + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; tuple tuple1 = make_tuple(dd, m); - tuple tuple2 = make_tuple(tuple1, filename); + tuple tuple2 = make_tuple(tuple1, testTuple); d.value = boost::any(tuple2); // Make sure it is not loaded yet. @@ -274,7 +284,9 @@ TEST_CASE("RawParamMatTest", "[CLIOptionTest]") // Create value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::ones); - tuple tuple = make_tuple(m, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple tuple = make_tuple(m, testTuple); d.value = boost::any(tuple); d.input = true; d.loaded = false; @@ -322,9 +334,10 @@ TEST_CASE("GetRawParamDatasetInfoTest", "[CLIOptionTest]") // Create tuples. data::DatasetInfo dd(3); arma::mat m(3, 3, arma::fill::randu); - + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; tuple tuple1 = make_tuple(dd, m); - tuple tuple2 = make_tuple(tuple1, filename); + tuple tuple2 = make_tuple(tuple1, testTuple); d.value = boost::any(tuple2); // Make sure it is not loaded yet. @@ -350,7 +363,9 @@ TEST_CASE("OutputParamMatTest", "[CLIOptionTest]") // Create value. string filename = "test.csv"; arma::mat m(3, 3, arma::fill::randu); - tuple t = make_tuple(m, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple t = make_tuple(m, testTuple); d.value = boost::any(t); d.input = false; @@ -376,7 +391,9 @@ TEST_CASE("OutputParamUmatTest", "[CLIOptionTest]") // Create value. string filename = "test.csv"; arma::Mat m(3, 3, arma::fill::randu); - tuple, string> t = make_tuple(m, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple, TupleType> t = make_tuple(m, testTuple); d.value = boost::any(t); d.input = false; @@ -467,7 +484,9 @@ TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]") // Create initial value. string filename = "hello.csv"; arma::mat m(5, 5, arma::fill::randu); - d.value = boost::any(make_tuple(m, filename)); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + d.value = boost::any(make_tuple(m, testTuple)); // Get a new string. string newFilename = "new.csv"; @@ -477,9 +496,9 @@ TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]") (void*) NULL); // Make sure the change went through. - tuple& t = - *boost::any_cast>(&d.value); - REQUIRE(get<1>(t) == "new.csv"); + tuple& t = + *boost::any_cast>(&d.value); + REQUIRE(get<0>(get<1>(t)) == "new.csv"); } // Test that calling SetParam on a model sets the string correctly. @@ -517,8 +536,10 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") string filename = "test.csv"; arma::mat m(3, 3, arma::fill::randu); DatasetInfo di(3); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; tuple t1 = make_tuple(di, m); - tuple, string> t2 = make_tuple(t1, filename); + tuple, TupleType> t2 = make_tuple(t1, testTuple); d.value = boost::any(t2); d.noTranspose = false; @@ -530,10 +551,10 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") (const void*) &a2, (void*) NULL); // Check that the name is right. - tuple, string>& t3 = - *boost::any_cast, string>>(&d.value); + tuple, TupleType>& t3 = + *boost::any_cast, TupleType>>(&d.value); - REQUIRE(get<1>(t3) == "new_filename.csv"); + REQUIRE(get<0>(get<1>(t3)) == "new_filename.csv"); } // Test that GetAllocatedMemory() will properly return NULL for a non-model @@ -556,7 +577,9 @@ TEST_CASE("GetAllocatedMemoryNonModelTest", "[CLIOptionTest]") // Also test with a matrix type. arma::mat test(10, 10, arma::fill::ones); string filename = "test.csv"; - tuple t = make_tuple(test, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple t = make_tuple(test, testTuple); d.value = boost::any(t); result = (void*) 1; @@ -602,7 +625,9 @@ TEST_CASE("DeleteAllocatedMemoryNonModelTest", "[CLIOptionTest]") arma::mat test(10, 10, arma::fill::ones); string filename = "test.csv"; - tuple t = make_tuple(test, filename); + typedef tuple TupleType; + TupleType testTuple{filename, 0, 0}; + tuple t = make_tuple(test, testTuple); d.value = boost::any(t); DeleteAllocatedMemory((util::ParamData&) d, From 6fe628f49fc7f3a4ae874b68627452bb00a78e98 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:29:14 +0200 Subject: [PATCH 297/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Ryan Curtin --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 2d29ec80a8..49eec75b68 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -14,7 +14,7 @@ if (CMAKE_CROSSCOMPILING) elseif(NOT CMAKE_SYSROOT) message(FATAL_ERROR "Can not proceed CMAKE_SYSROOT is not set") elseif(NOT TOOLCHAIN_PREFIX) - message(FATAL_ERROR "Cant not proceed TOOLCHAIN_PREFIX is not set") + message(FATAL_ERROR "Cannot configure: TOOLCHAIN_PREFIX must be set when performing cross-compiling!") endif() endif() From 55bac6d763a60866b84b4f8e2794e7bec8c30845 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:29:29 +0200 Subject: [PATCH 298/729] Update board/crosscompile-toolchain.cmake Co-authored-by: Ryan Curtin --- board/crosscompile-toolchain.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/crosscompile-toolchain.cmake b/board/crosscompile-toolchain.cmake index 2adb64152c..2b586e1113 100644 --- a/board/crosscompile-toolchain.cmake +++ b/board/crosscompile-toolchain.cmake @@ -12,7 +12,7 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSROOT) -set(TOOLCHAIN_PREFIX "" CACHE STRING "Path for Toolchain for cross compiler and other compilation tools.") +set(TOOLCHAIN_PREFIX "" CACHE STRING "Path for toolchain for cross compiler and other compilation tools.") # Ensure that CMake tries to build static libraries when testing the compiler. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) From 9d29409ba279e384b215d4d8d7cbfd369f2d7721 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:29:37 +0200 Subject: [PATCH 299/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Ryan Curtin --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 49eec75b68..93fb7e4ab4 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -12,7 +12,7 @@ if (CMAKE_CROSSCOMPILING) if (NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX)) message(FATAL_ERROR "Neither of CMAKE_SYSROOT or TOOLCHAIN_PREFIX is set, please set both of them and try again") elseif(NOT CMAKE_SYSROOT) - message(FATAL_ERROR "Can not proceed CMAKE_SYSROOT is not set") + message(FATAL_ERROR "Cannot configure: CMAKE_SYSROOT must be set when performing cross-compiling!") elseif(NOT TOOLCHAIN_PREFIX) message(FATAL_ERROR "Cannot configure: TOOLCHAIN_PREFIX must be set when performing cross-compiling!") endif() From 17cd0a89480b337e86155b89abd945deacf022f2 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:30:10 +0200 Subject: [PATCH 300/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Ryan Curtin --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 93fb7e4ab4..89610df001 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -23,7 +23,7 @@ macro(search_openblas version) find_package(BLAS) if (NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES)) if(NOT OPENBLAS_TARGET) - message(FATAL_ERROR "Cant not proceed, OPENBLAS_TARGET is not set, and to either set that or BOARD_NAME") + message(FATAL_ERROR "Cannot compile OpenBLAS: OPENBLAS_TARGET is not set. Either set that variable, or set BOARD_NAME correctly!") endif() get_deps(https://github.com/xianyi/OpenBLAS/releases/download/v${version}/OpenBLAS-${version}.tar.gz OpenBLAS OpenBLAS-${version}.tar.gz) if (NOT MSVC) From 31c3cf227d29badccf50183051a48d231cf507e9 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:31:42 +0200 Subject: [PATCH 301/729] Update CMake/ConfigureCrossCompile.cmake Co-authored-by: Ryan Curtin --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 89610df001..75e28bc453 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -10,7 +10,7 @@ if (CMAKE_CROSSCOMPILING) include(board/flags-config.cmake) if (NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX)) - message(FATAL_ERROR "Neither of CMAKE_SYSROOT or TOOLCHAIN_PREFIX is set, please set both of them and try again") + message(FATAL_ERROR "Neither CMAKE_SYSROOT nor TOOLCHAIN_PREFIX are set; please set both of them and try again.") elseif(NOT CMAKE_SYSROOT) message(FATAL_ERROR "Cannot configure: CMAKE_SYSROOT must be set when performing cross-compiling!") elseif(NOT TOOLCHAIN_PREFIX) From 4b90d92145346e3421e6ba9444fd95ab87914688 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:33:10 +0200 Subject: [PATCH 302/729] Update board/flags-config.cmake Co-authored-by: Ryan Curtin --- board/flags-config.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 349c55068d..154cba387b 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -64,5 +64,5 @@ elseif(BOARD MATCHES "NORTHWOOD") set(OPENBLAS_TARGET "NORTHWOOD") set(OPENBLAS_BINARY "32") elseif(BOARD) - message(FATAL_ERROR "Board type is not known, please choose a supported board from the list") + message(FATAL_ERROR "Given BOARD_TYPE is not known; please choose a supported board from the list") endif() From 48daf7ca59e75ed1633610e8c9cf02d84140b522 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 00:57:20 +0200 Subject: [PATCH 303/729] Update board/flags-config.cmake Co-authored-by: Ryan Curtin --- board/flags-config.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index 154cba387b..aa7704a710 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -64,5 +64,5 @@ elseif(BOARD MATCHES "NORTHWOOD") set(OPENBLAS_TARGET "NORTHWOOD") set(OPENBLAS_BINARY "32") elseif(BOARD) - message(FATAL_ERROR "Given BOARD_TYPE is not known; please choose a supported board from the list") + message(FATAL_ERROR "Given BOARD_NAME is not known; please choose a supported board from the list") endif() From 8a9f9b4b2cc9cdf6543a711394d1e2f673bf5b20 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 6 May 2021 01:03:35 +0200 Subject: [PATCH 304/729] Add TODO message to update documentation Signed-off-by: Omar Shrit --- board/flags-config.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/board/flags-config.cmake b/board/flags-config.cmake index aa7704a710..06dfecd5cf 100644 --- a/board/flags-config.cmake +++ b/board/flags-config.cmake @@ -64,5 +64,6 @@ elseif(BOARD MATCHES "NORTHWOOD") set(OPENBLAS_TARGET "NORTHWOOD") set(OPENBLAS_BINARY "32") elseif(BOARD) + ## TODO: update documentation with a list of the supported boards. message(FATAL_ERROR "Given BOARD_NAME is not known; please choose a supported board from the list") endif() From 0cb6a13c066eaa77a170e7d772e92d71556ea8ff Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 7 May 2021 10:33:05 +0530 Subject: [PATCH 305/729] Reverted unnecessary bracket changes --- .../best_binary_numeric_split_impl.hpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 098f0ab252..14bd0e3fb9 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -39,11 +39,11 @@ double BestBinaryNumericSplit::SplitIfBetter( arma::Row sortedLabels(labels.n_elem); arma::rowvec sortedWeights; for (size_t i = 0; i < sortedLabels.n_elem; ++i) - sortedLabels(i) = labels(sortedIndices(i)); + sortedLabels[i] = labels[sortedIndices[i]]; // Sanity check: if the first element is the same as the last, we can't split // in this dimension. - if (data(sortedIndices(0)) == data(sortedIndices(sortedIndices.n_elem - 1))) + if (data[sortedIndices[0]] == data[sortedIndices[sortedIndices.n_elem - 1]]) return DBL_MAX; // Only initialize if we are using weights. @@ -52,7 +52,7 @@ double BestBinaryNumericSplit::SplitIfBetter( sortedWeights.set_size(sortedLabels.n_elem); // The weights must keep the same order as the labels. for (size_t i = 0; i < sortedLabels.n_elem; ++i) - sortedWeights(i) = weights(sortedIndices(i)); + sortedWeights[i] = weights[sortedIndices[i]]; } // Loop through all possible split points, choosing the best one. Also, force @@ -77,15 +77,15 @@ double BestBinaryNumericSplit::SplitIfBetter( // These points have to be on the left. for (size_t i = 0; i < minimum - 1; ++i) { - classWeightSums(sortedLabels(i), 0) += sortedWeights(i); - totalLeftWeight += sortedWeights(i); + classWeightSums(sortedLabels[i], 0) += sortedWeights[i]; + totalLeftWeight += sortedWeights[i]; } // These points have to be on the right. for (size_t i = minimum - 1; i < data.n_elem; ++i) { - classWeightSums(sortedLabels(i), 1) += sortedWeights(i); - totalRightWeight += sortedWeights(i); + classWeightSums(sortedLabels[i], 1) += sortedWeights[i]; + totalRightWeight += sortedWeights[i]; } } else @@ -96,11 +96,11 @@ double BestBinaryNumericSplit::SplitIfBetter( // Initialize the counts. // These points have to be on the left. for (size_t i = 0; i < minimum - 1; ++i) - ++classCounts(sortedLabels(i), 0); + ++classCounts(sortedLabels[i], 0); // These points have to be on the right. for (size_t i = minimum - 1; i < data.n_elem; ++i) - ++classCounts(sortedLabels(i), 1); + ++classCounts(sortedLabels[i], 1); } for (size_t index = minimum; index < data.n_elem - minimum; ++index) @@ -108,19 +108,19 @@ double BestBinaryNumericSplit::SplitIfBetter( // Update class weight sums or counts. if (UseWeights) { - classWeightSums(sortedLabels(index - 1), 1) -= sortedWeights(index - 1); - classWeightSums(sortedLabels(index - 1), 0) += sortedWeights(index - 1); - totalLeftWeight += sortedWeights(index - 1); - totalRightWeight -= sortedWeights(index - 1); + classWeightSums(sortedLabels[index - 1], 1) -= sortedWeights[index - 1]; + classWeightSums(sortedLabels[index - 1], 0) += sortedWeights[index - 1]; + totalLeftWeight += sortedWeights[index - 1]; + totalRightWeight -= sortedWeights[index - 1]; } else { - --classCounts(sortedLabels(index - 1), 1); - ++classCounts(sortedLabels(index - 1), 0); + --classCounts(sortedLabels[index - 1], 1); + ++classCounts(sortedLabels[index - 1], 0); } // Make sure that the value has changed. - if (data(sortedIndices(index)) == data(sortedIndices(index - 1))) + if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) continue; // Calculate the gain for the left and right child. Only use weights if @@ -156,8 +156,8 @@ double BestBinaryNumericSplit::SplitIfBetter( classProbabilities.set_size(1); // The actual split value will be halfway between the value at index - 1 // and index. - classProbabilities(0) = (data(sortedIndices(index - 1)) + - data(sortedIndices(index))) / 2.0; + classProbabilities[0] = (data[sortedIndices[index - 1]] + + data[sortedIndices[index]]) / 2.0; return gain; } @@ -166,8 +166,8 @@ double BestBinaryNumericSplit::SplitIfBetter( // We still have a better split. bestFoundGain = gain; classProbabilities.set_size(1); - classProbabilities(0) = (data(sortedIndices(index - 1)) + - data(sortedIndices(index))) / 2.0; + classProbabilities[0] = (data[sortedIndices[index - 1]] + + data[sortedIndices[index]]) / 2.0; improved = true; } } @@ -192,7 +192,7 @@ size_t BestBinaryNumericSplit::CalculateDirection( const arma::vec& classProbabilities, const AuxiliarySplitInfo& /* aux */) { - if (point <= classProbabilities(0)) + if (point <= classProbabilities[0]) return 0; // Go left. else return 1; // Go right. From 594c002f4f64e78890192e8abf55f16d8560424b Mon Sep 17 00:00:00 2001 From: fawwazmayda Date: Sat, 8 May 2021 13:16:02 +0800 Subject: [PATCH 306/729] adding flatten_t_swish adding test adding Flatten T Swish Update activation_functions_test.cpp Update flatten_t_swish.hpp fixing mistype fixing style improve styling Update flatten_t_swish_impl.hpp Update flatten_t_swish.hpp Update flatten_t_swish_impl.hpp Update COPYRIGHT.txt Update activation_functions_test.cpp Update activation_functions_test.cpp fix style Update flatten_t_swish_impl.hpp Update flatten_t_swish_impl.hpp Update flatten_t_swish_impl.hpp Update history.md --- COPYRIGHT.txt | 1 + HISTORY.md | 2 + src/mlpack/methods/ann/layer/CMakeLists.txt | 2 + .../methods/ann/layer/flatten_t_swish.hpp | 124 ++++++++++++++++++ .../ann/layer/flatten_t_swish_impl.hpp | 80 +++++++++++ src/mlpack/methods/ann/layer/layer.hpp | 1 + .../tests/activation_functions_test.cpp | 62 +++++++++ 7 files changed, 272 insertions(+) create mode 100644 src/mlpack/methods/ann/layer/flatten_t_swish.hpp create mode 100644 src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index b7e9d6cf15..db89c05176 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -143,6 +143,7 @@ Copyright: Copyright 2020, Anmolpreet Singh Copyright 2021, Tru Hoang Copyright 2021, Mark Fischinger + Copyright 2021, Muhammad Fawwaz Mayda License: BSD-3-clause All rights reserved. diff --git a/HISTORY.md b/HISTORY.md index 528c1746f5..5e758fb023 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? + * Add Flatten T Swish activation function (`flatten-t-swish.hpp`) + * Added warm start feature to Random Forest (#2881); this feature is accessible from mlpack's bindings to different languages. diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index 2b181012c7..52dbebec75 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -36,6 +36,8 @@ set(SOURCES elu_impl.hpp fast_lstm.hpp fast_lstm_impl.hpp + flatten_t_swish.hpp + flatten_t_swish_impl.hpp flexible_relu.hpp flexible_relu_impl.hpp glimpse.hpp diff --git a/src/mlpack/methods/ann/layer/flatten_t_swish.hpp b/src/mlpack/methods/ann/layer/flatten_t_swish.hpp new file mode 100644 index 0000000000..3d891b3363 --- /dev/null +++ b/src/mlpack/methods/ann/layer/flatten_t_swish.hpp @@ -0,0 +1,124 @@ +/** + * @file methods/ann/layer/flatten_t_swish.hpp + * @author Fawwaz Mayda + * + * Definition of Flatten T Swish layer first introduced in the acoustic model, + * Hock Hung Chieng, Noorhaniza Wahid, Pauline Ong, Sai Raj Kishore Perla, + * "Flatten-T Swish: a thresholded ReLU-Swish-like activation function for deep learning", 2018 + * + * 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_FLATTEN_T_SWISH_HPP +#define MLPACK_METHODS_ANN_LAYER_FLATTEN_T_SWISH_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * The Flatten T Swish activation function, defined by + * + * @f{eqnarray*}{ + * f'(x) &=& \left\{ + * \begin{array}{lr} + * frac{x}{1+exp(-x)} + T & : x \ge 0 \\ + * T & : x < 0 + * \end{array} + * \right. \\ + * f'(x) &=& \left\{ + * \begin{array}{lr} + * \sigma(x)(1 - f(x)) + f(x) & : x > 0 \\ + * 0 & : x \le 0 + * \end{array} + * \right. + * @f} + * + * @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 FlattenTSwish +{ + public: + /** + * Create the Flatten T Swish object using the specified parameters. + * The thresholded value T can be adjusted via T paramaters. + * When the x is < 0, T will be used instead of 0. + * The default value of T is -0.20 as suggested in the paper. + * @param T + */ + FlattenTSwish(const double T = -0.20); + + /** + * 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 + 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 + void Backward(const DataType& input, const DataType& gy, DataType& g); + + //! Get the output parameter. + OutputDataType const& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const& Delta() const { return delta; } + //! Modify the delta. + OutputDataType& Delta() { return delta; } + + //! Get the T parameter. + double const& T() const { return t; } + //! Modify the T parameter. + double& T() { return t; } + + //! Get size of weights. + size_t WeightSize() const { return 0; } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& ar, const uint32_t /* version */); + + private: + //! Locally-stored delta object. + OutputDataType delta; + + //! Locally-stored output parameter object. + OutputDataType outputParameter; + + //! T Parameter from paper. + double t; +}; // class FlattenTSwish + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "flatten_t_swish_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp new file mode 100644 index 0000000000..1ce5364da8 --- /dev/null +++ b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp @@ -0,0 +1,80 @@ +/** + * @file methods/ann/layer/flatten_t_swish_impl.hpp + * @author Fawwaz Mayda + * + * Definition of Flatten T Swish layer first introduced in the acoustic model, + * Hock Hung Chieng, Noorhaniza Wahid, Pauline Ong, Sai Raj Kishore Perla, + * "Flatten-T Swish: a thresholded ReLU-Swish-like activation function for deep learning", 2018 + * + * 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_FLATTEN_T_SWISH_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_FLATTEN_T_SWISH_IMPL_HPP + +// In case it hasn't yet been included. +#include "flatten_t_swish.hpp" +#include +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +template +FlattenTSwish::FlattenTSwish( + const double T) : t(T) +{ + // Nothing to do here. +} + +template +template +void FlattenTSwish::Forward( + const InputType& input, OutputType& output) +{ + // Placeholder for Relu values. + OutputDataType relu; + RectifierFunction::Fn(input, relu); + LogisticFunction::Fn(input, output); + // F(x) = relu * sigmoid + t. + output = relu % output + t; +} + +template +template +void FlattenTSwish::Backward( + const DataType& input, const DataType& gy, DataType& g) +{ + DataType derivate, sigmoid; + LogisticFunction::Fn(input,sigmoid); + derivate.set_size(arma::size(input)); + for(size_t i = 0; i < input.n_elem; ++i) + { + if (input(i) >= 0) + { + // F(x) = x * sigmoid(x). + // We don't put '+ t' here because this is a derivate. + derivate(i) = input(i) * sigmoid(i); + derivate(i) = sigmoid(i) * (1.0 - derivate(i)) + derivate(i); + } + else + derivate(i) = 0; + } + g = gy % derivate; +} + +template +template +void FlattenTSwish::serialize( + Archive& ar, + const uint32_t /* version */) +{ + ar(CEREAL_NVP(t)); +} + +} // namespace ann +} // namespace mlpack + +#endif \ No newline at end of file diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index 6d13a26772..b2f598b985 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -32,6 +32,7 @@ #include "dropout.hpp" #include "elu.hpp" #include "fast_lstm.hpp" +#include "flatten_t_swish.hpp" #include "flexible_relu.hpp" #include "glimpse.hpp" #include "gru.hpp" diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index a20b95c039..fcca17d2c0 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -660,6 +660,48 @@ void CheckSoftminDerivativeCorrect(const arma::colvec input, } } +/** + * Implementation of the Flatten T Swish activation function test. The function is + * implemented as Flatten T Swish layer in the file flatten_t_swish.hpp. + * + * @param input Input data used for evaluating the Flatten T Swish activation function. + * @param target Target data used to evaluate the Flatten T Swish activation. + */ +void CheckFlattenTSwishActivationCorrect(const arma::colvec input, const arma::colvec target) +{ + FlattenTSwish<> fts(0.4); + arma::colvec activations; + + fts.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 CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::colvec target) +{ + FlattenTSwish<> fts; + + // Set the error to 1 to get the actual derivative. + arma::colvec error = arma::ones(input.n_elem); + + arma::colvec derivate; + fts.Backward(input,error,derivate); + for(size_t i = 0; i < derivate.n_elem; ++i) + { + REQUIRE(derivate.at(i) == Approx(target.at(i)).epsilon(1e-5)); + } +} + /** * Basic test of the tanh function. */ @@ -1264,3 +1306,23 @@ TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") CheckActivationCorrect(activationData,desiredActivation); CheckDerivativeCorrect(desiredActivation,desiredDerivate); } + +/** + * Basic test of Flatten T Swish function. + */ +TEST_CASE("FlattenTSwishFunctionTest","[ActivationFunctionsTest]") +{ + // Random Value. + arma::colvec input("-4.0 -1.0 2 3 4 5 6"); + + // Hand Calculated and using PyTorch. + arma::colvec desiredActivation("0.4000000059604645 0.4000000059604645 2.1615941524505615 \ + 3.2577223777770996 4.328054904937744 5.3665361404418945 6.385164737701416"); + + // Hand Calculated and using PyTorch. + arma::colvec desiredDerivation("0.694792 0.694792 1.096893 1.079178 1.042602 \ + 1.020182 1.009048"); + + CheckFlattenTSwishActivationCorrect(input,desiredActivation); + CheckFlattenTSwishDerivateCorrect(desiredActivation,desiredDerivation); +} \ No newline at end of file From 145c259182304ff8a99445e3e395b1551aba0a83 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 8 May 2021 23:06:15 +0200 Subject: [PATCH 307/729] Download old boost version if the compiler is tooo.. old This pull request fixes #2939 Signed-off-by: Omar Shrit --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index daf416f5e2..89418e9394 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -366,7 +366,11 @@ if (DISABLE_DOWNLOADS) else() find_package(Boost "${BOOST_VERSION}") if (NOT Boost_FOUND) - get_deps(https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz boost boost_1_76_0.tar.gz) + if (CMAKE_COMPILER_IS_GNUCC AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) + get_deps(http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.gz boost boost_1_58_0.tar.gz) + else() + get_deps(https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz boost boost_1_76_0.tar.gz) + endif() find_package(Boost REQUIRED) endif() endif() From 047577852b33a51d84cdd7ea87c1baa91de61762 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 9 May 2021 06:51:12 +0530 Subject: [PATCH 308/729] Apply suggestions from code review Co-authored-by: Marcus Edel --- .../methods/decision_tree/random_binary_numeric_split_impl.hpp | 2 +- src/mlpack/tests/decision_tree_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index aec26637a3..555113970c 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -87,7 +87,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( classCounts.zeros(numClasses, 2); bestFoundGain *= data.n_elem; - for (size_t i = 0; i < data.n_elem; i++) + for (size_t i = 0; i < data.n_elem; ++i) { if (data(i) < randomPivot) { diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 52730c5c28..6541069879 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -459,7 +459,7 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") const double bestGain = GiniGain::Evaluate(labels, 2, weights); - for(int i = 0; i < 5; i++) + for (int i = 0; i < 5; ++i) { // Call BestBinaryNumericSplit to do the splitting. double gain = BestBinaryNumericSplit::SplitIfBetter( From 2a6152dfcdd9b22ad2fc7693448304d774a8e738 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 9 May 2021 06:54:09 +0530 Subject: [PATCH 309/729] Update HISTORY.md --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index f8eb50f377..9eec0b93e5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,7 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? * Added Extra Trees Algorithm (#2883). Currently, it can be used using the - * class `mlpack::tree::ExtraTrees`, but only through C++. + class `mlpack::tree::ExtraTrees`, but only through C++. * Add Flatten T Swish activation function (`flatten-t-swish.hpp`) From 9930308e007d6ff90c7d8106277bf4e39bf07f18 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 9 May 2021 21:05:12 +0530 Subject: [PATCH 310/729] Update src/mlpack/bindings/cli/get_printable_param_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/cli/get_printable_param_impl.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mlpack/bindings/cli/get_printable_param_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_impl.hpp index 8a3cb211cb..9898c49ee6 100644 --- a/src/mlpack/bindings/cli/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_impl.hpp @@ -89,8 +89,9 @@ std::string GetPrintableParam( { // Make sure the matrix is loaded so that we can print its size. GetParam(const_cast(data)); - std::string matDescription = std::to_string(std::get<1>(std::get<1>(*tuple))) + "x"; - matDescription += std::to_string(std::get<2>(std::get<1>(*tuple))) + " matrix"; + std::string matDescription = + std::to_string(std::get<2>(std::get<1>(*tuple))) + "x" + + std::to_string(std::get<1>(std::get<1>(*tuple))) + " matrix"; oss << " (" << matDescription << ")"; } From 0a22827b41c1ed784dc817368293d1009415fa5d Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 9 May 2021 21:05:20 +0530 Subject: [PATCH 311/729] Update src/mlpack/bindings/cli/in_place_copy.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/cli/in_place_copy.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index e2094e53d4..4112c8a5a5 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -41,7 +41,7 @@ void InPlaceCopyInternal( /** * Modify the filename for any type that needs to be loaded from disk to match - * the filename of the input parameter. For matrix/datasetinfo parameter. + * the filename of the input parameter, for a matrix/DatasetInfo parameter. * * @param d ParamData object we want to make into an in-place copy. * @param input ParamData object whose filename we should copy. From 92f568f3b785562c0b809c3138aa1d7e25b6fa95 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 9 May 2021 21:05:28 +0530 Subject: [PATCH 312/729] Update src/mlpack/bindings/cli/in_place_copy.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/cli/in_place_copy.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index 4112c8a5a5..c8de4c81c8 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -53,7 +53,8 @@ void InPlaceCopyInternal( const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* = 0) + std::tuple>::value + >::type* = 0) { // Make the output filename the same as the input filename. typedef std::tuple::type> TupleType; From ebc61b761533d13d9c48552f083df7712c5e585c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 9 May 2021 21:05:34 +0530 Subject: [PATCH 313/729] Update src/mlpack/bindings/cli/in_place_copy.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/cli/in_place_copy.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index c8de4c81c8..d3ed1c9521 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -67,7 +67,7 @@ void InPlaceCopyInternal( /** * Modify the filename for any type that needs to be loaded from disk to match - * the filename of the input parameter. For Serializable object. + * the filename of the input parameter. For serializable objects. * * @param d ParamData object we want to make into an in-place copy. * @param input ParamData object whose filename we should copy. From 7b7119fd8b6079c12cca1eba429a702b6bc2fb39 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 9 May 2021 23:27:49 +0530 Subject: [PATCH 314/729] updated UnmappedParamTest --- src/mlpack/tests/io_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/io_test.cpp b/src/mlpack/tests/io_test.cpp index 26319a8d79..725ea25222 100644 --- a/src/mlpack/tests/io_test.cpp +++ b/src/mlpack/tests/io_test.cpp @@ -974,7 +974,7 @@ TEST_CASE_METHOD(IOTestDestroyer, "UnmappedParamTest", // Now check that we can get unmapped parameters. REQUIRE(IO::GetPrintableParam("matrix") == - "'test_data_3_1000.csv' (3x1000 matrix)"); + "'test_data_3_1000.csv' (1000x3 matrix)"); // This will have size 0x0 since it's an output parameter, and it hasn't been // set since ParseCommandLine() was called. REQUIRE(IO::GetPrintableParam("matrix2") == From 1f088abb6109eb9b7743d5b130278c316c1bfb14 Mon Sep 17 00:00:00 2001 From: JackBoosY Date: Tue, 18 May 2021 20:05:05 -0700 Subject: [PATCH 315/729] Fix uwp build error C4146 --- src/mlpack/core/data/is_naninf.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/data/is_naninf.hpp b/src/mlpack/core/data/is_naninf.hpp index 9462cdbae8..ac06b491f2 100644 --- a/src/mlpack/core/data/is_naninf.hpp +++ b/src/mlpack/core/data/is_naninf.hpp @@ -41,12 +41,12 @@ inline bool IsNaNInf(T& val, const std::string& token) if (std::numeric_limits::has_infinity) { val = (!neg) ? std::numeric_limits::infinity() : - -std::numeric_limits::infinity(); + -1 * std::numeric_limits::infinity(); } else { val = (!neg) ? std::numeric_limits::max() : - -std::numeric_limits::max(); + -1 * std::numeric_limits::max(); } return true; From b26d120a79aa6d4807b893d74cc51d5306630b9e Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 19 May 2021 16:55:59 -0400 Subject: [PATCH 316/729] Try to fix the static code analysis issue. --- src/mlpack/tests/decision_tree_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 6541069879..40ccbec8ae 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -471,6 +471,9 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1, aux1); + // The variable is not used; suppress warnings. + (void) gain; + if (classProbabilities[0] == classProbabilities1[0]) break; } From b5c2961965a5a3bac7986d68a1e52f75e25109ae Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 19 May 2021 17:51:55 -0400 Subject: [PATCH 317/729] Another solution... and also fix a bunch of warnings. --- .../ann/layer/recurrent_attention_impl.hpp | 4 ++-- .../q_networks/categorical_dqn.hpp | 8 +++++--- src/mlpack/tests/decision_tree_test.cpp | 7 ++----- src/mlpack/tests/lsh_test.cpp | 1 - .../tests/main_tests/hoeffding_tree_test.cpp | 10 +++++----- src/mlpack/tests/main_tests/kmeans_test.cpp | 4 ++-- .../local_coordinate_coding_test.cpp | 8 ++++---- .../tests/main_tests/mean_shift_test.cpp | 5 +++-- .../main_tests/preprocess_split_test.cpp | 20 +++++++++++-------- src/mlpack/tests/random_forest_test.cpp | 6 +++--- src/mlpack/tests/rectangle_tree_test.cpp | 8 ++++---- 11 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/mlpack/methods/ann/layer/recurrent_attention_impl.hpp b/src/mlpack/methods/ann/layer/recurrent_attention_impl.hpp index dcc60055d5..abc3da7727 100644 --- a/src/mlpack/methods/ann/layer/recurrent_attention_impl.hpp +++ b/src/mlpack/methods/ann/layer/recurrent_attention_impl.hpp @@ -28,11 +28,11 @@ namespace ann /** Artificial Neural Network. */ { template RecurrentAttention::RecurrentAttention() : + outSize(0), rho(0), forwardStep(0), backwardStep(0), - deterministic(false), - outSize(0) + deterministic(false) { // Nothing to do. } diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp index 82ce15e77e..aab2c4bc1b 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp @@ -37,7 +37,7 @@ using namespace mlpack::ann; * url = {http://arxiv.org/abs/1707.06887} * } * @endcode - * + * * @tparam OutputLayerType The output layer type of the network. * @tparam InitType The initialization type used for the network. * @tparam NetworkType The type of network used for simple dqn. @@ -53,7 +53,8 @@ class CategoricalDQN /** * Default constructor. */ - CategoricalDQN() : network(), isNoisy(false), atomSize(0), vMin(0.0), vMax(0.0) + CategoricalDQN() : + network(), atomSize(0), vMin(0.0), vMax(0.0), isNoisy(false) { /* Nothing to do here. */ } /** @@ -101,7 +102,8 @@ class CategoricalDQN } /** - * Construct an instance of CategoricalDQN class from a pre-constructed network. + * Construct an instance of CategoricalDQN class from a pre-constructed + * network. * * @param network The network to be used by CategoricalDQN class. * @param config Hyper-parameters for categorical dqn. diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 40ccbec8ae..8fcf6b1e95 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -462,18 +462,15 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") for (int i = 0; i < 5; ++i) { // Call BestBinaryNumericSplit to do the splitting. - double gain = BestBinaryNumericSplit::SplitIfBetter( + (void) BestBinaryNumericSplit::SplitIfBetter( bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities, aux); // Call RandomBinaryNumericSplit to do the splitting. - gain = RandomBinaryNumericSplit::SplitIfBetter( + (void) RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1, aux1); - // The variable is not used; suppress warnings. - (void) gain; - if (classProbabilities[0] == classProbabilities1[0]) break; } diff --git a/src/mlpack/tests/lsh_test.cpp b/src/mlpack/tests/lsh_test.cpp index 1d445192b5..5328609dab 100644 --- a/src/mlpack/tests/lsh_test.cpp +++ b/src/mlpack/tests/lsh_test.cpp @@ -985,7 +985,6 @@ TEST_CASE("SparseLSHTest", "[LSHTest]") // Make sure that sparse LSH distances aren't garbage. for (size_t i = 0; i < sparseNeighbors.n_elem; ++i) { - REQUIRE(sparseNeighbors[i] >= 0); REQUIRE(sparseNeighbors[i] < rdata.n_cols); REQUIRE(sparseDistances[i] >= 0.0); REQUIRE(!std::isinf(sparseDistances[i])); diff --git a/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp b/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp index af4373fb66..16ae37175b 100644 --- a/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp +++ b/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp @@ -398,7 +398,7 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMinSamplesTest", // Check that small min_samples creates larger model. REQUIRE((IO::GetParam("output_model"))->NumNodes() < - nodes); + (size_t) nodes); } /** @@ -466,7 +466,7 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMaxSamplesTest", mlpackMain(); // Check that large max_samples creates smaller model. - REQUIRE(nodes < + REQUIRE((size_t) nodes < (IO::GetParam("output_model"))->NumNodes()); } @@ -533,7 +533,7 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingConfidenceTest", mlpackMain(); // Check that higher confidence creates smaller tree. - REQUIRE(nodes < + REQUIRE((size_t) nodes < (IO::GetParam("output_model"))->NumNodes()); } @@ -601,7 +601,7 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingPassesTest", mlpackMain(); // Check that model with larger number of passes has greater number of nodes. - REQUIRE(nodes < + REQUIRE((size_t) nodes < (IO::GetParam("output_model"))->NumNodes()); } @@ -715,7 +715,7 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, // Check that both models have different number of nodes. CHECK((IO::GetParam("output_model"))->NumNodes() != - nodes); + (size_t) nodes); } /** diff --git a/src/mlpack/tests/main_tests/kmeans_test.cpp b/src/mlpack/tests/main_tests/kmeans_test.cpp index 6db26d1fcb..f1d4b5882d 100644 --- a/src/mlpack/tests/main_tests/kmeans_test.cpp +++ b/src/mlpack/tests/main_tests/kmeans_test.cpp @@ -153,7 +153,7 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringSizeCheck", REQUIRE(IO::GetParam("output").n_rows == row+1); REQUIRE(IO::GetParam("output").n_cols == col); REQUIRE(IO::GetParam("centroid").n_rows == row); - REQUIRE(IO::GetParam("centroid").n_cols == c); + REQUIRE(IO::GetParam("centroid").n_cols == (arma::uword) c); } /** @@ -179,7 +179,7 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringSizeCheckLabelOnly", REQUIRE(IO::GetParam("output").n_rows == 1); REQUIRE(IO::GetParam("output").n_cols == col); REQUIRE(IO::GetParam("centroid").n_rows == row); - REQUIRE(IO::GetParam("centroid").n_cols == c); + REQUIRE(IO::GetParam("centroid").n_cols == (arma::uword) c); } diff --git a/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp b/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp index 9ea8d90511..31b24013db 100644 --- a/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp +++ b/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp @@ -62,10 +62,10 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCDimensionsTest", mlpackMain(); // Check that the output has correct dimensions. - REQUIRE(IO::GetParam("codes").n_rows == atoms); - REQUIRE(IO::GetParam("codes").n_cols == cols); - REQUIRE(IO::GetParam("dictionary").n_rows == rows); - REQUIRE(IO::GetParam("dictionary").n_cols == atoms); + REQUIRE(IO::GetParam("codes").n_rows == (arma::uword) atoms); + REQUIRE(IO::GetParam("codes").n_cols == (arma::uword) cols); + REQUIRE(IO::GetParam("dictionary").n_rows == (arma::uword) rows); + REQUIRE(IO::GetParam("dictionary").n_cols == (arma::uword) atoms); } /** diff --git a/src/mlpack/tests/main_tests/mean_shift_test.cpp b/src/mlpack/tests/main_tests/mean_shift_test.cpp index 5da1c28b95..867eb4ec1e 100644 --- a/src/mlpack/tests/main_tests/mean_shift_test.cpp +++ b/src/mlpack/tests/main_tests/mean_shift_test.cpp @@ -118,9 +118,10 @@ TEST_CASE_METHOD( mlpackMain(); // Now check that the output has 1 extra row for labels. - REQUIRE(IO::GetParam("output").n_rows == numRows + 1); + REQUIRE(IO::GetParam("output").n_rows == + (arma::uword) (numRows + 1)); // Check number of output points are the same. - REQUIRE(IO::GetParam("output").n_cols == numCols); + REQUIRE(IO::GetParam("output").n_cols == (arma::uword) numCols); } /** diff --git a/src/mlpack/tests/main_tests/preprocess_split_test.cpp b/src/mlpack/tests/main_tests/preprocess_split_test.cpp index 16dc039157..40e6296197 100644 --- a/src/mlpack/tests/main_tests/preprocess_split_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_split_test.cpp @@ -168,11 +168,12 @@ TEST_CASE_METHOD( mlpackMain(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == inputSize); + REQUIRE(IO::GetParam("training").n_cols == + (arma::uword) inputSize); REQUIRE(IO::GetParam("test").n_cols == 0); REQUIRE(IO::GetParam>("training_labels").n_cols == - labelSize); + (arma::uword) labelSize); REQUIRE(IO::GetParam>("test_labels").n_cols == 0); } @@ -205,10 +206,11 @@ TEST_CASE_METHOD( // Now check that the output has desired dimensions. REQUIRE(IO::GetParam("training").n_cols == 0); - REQUIRE(IO::GetParam("test").n_cols == inputSize); + REQUIRE(IO::GetParam("test").n_cols == (arma::uword) inputSize); REQUIRE(IO::GetParam>("training_labels").n_cols == 0); - REQUIRE(IO::GetParam>("test_labels").n_cols == labelSize); + REQUIRE(IO::GetParam>("test_labels").n_cols == + (arma::uword) labelSize); } /** @@ -275,11 +277,12 @@ TEST_CASE_METHOD( mlpackMain(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == inputSize); + REQUIRE(IO::GetParam("training").n_cols == + (arma::uword) inputSize); REQUIRE(IO::GetParam("test").n_cols == 0); REQUIRE(IO::GetParam>("training_labels").n_cols == - labelSize); + (arma::uword) labelSize); REQUIRE(IO::GetParam>("test_labels").n_cols == 0); } @@ -314,10 +317,11 @@ TEST_CASE_METHOD( // Now check that the output has desired dimensions. REQUIRE(IO::GetParam("training").n_cols == 0); - REQUIRE(IO::GetParam("test").n_cols == inputSize); + REQUIRE(IO::GetParam("test").n_cols == (arma::uword) inputSize); REQUIRE(IO::GetParam>("training_labels").n_cols == 0); - REQUIRE(IO::GetParam>("test_labels").n_cols == labelSize); + REQUIRE(IO::GetParam>("test_labels").n_cols == + (arma::uword) labelSize); } /** diff --git a/src/mlpack/tests/random_forest_test.cpp b/src/mlpack/tests/random_forest_test.cpp index 3b51db9542..7b86eb2c34 100644 --- a/src/mlpack/tests/random_forest_test.cpp +++ b/src/mlpack/tests/random_forest_test.cpp @@ -514,7 +514,7 @@ TEST_CASE("WarmStartTreesTest", "[RandomForestTest]") // Train a random forest. RandomForest<> rf(trainingData, di, trainingLabels, 5, 25 /* 25 trees */, 1, 1e-7, 0, MultipleRandomDimensionSelect(4)); - + REQUIRE(rf.NumTrees() == 25); rf.Train(trainingData, di, trainingLabels, 5, 20 /* 20 trees */, 1, 1e-7, 0, @@ -538,7 +538,7 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") // Train a random forest. RandomForest<> rf(trainingData, di, trainingLabels, 5, 3 /* 3 trees */, 1, 1e-7, 0, MultipleRandomDimensionSelect(4)); - + // Get performance statistics on train data. arma::Row oldPredictions; rf.Classify(trainingData, oldPredictions); @@ -556,7 +556,7 @@ TEST_CASE("WarmStartTreesPredictionsQualityTest", "[RandomForestTest]") // Calculate the number of correct points. size_t newCorrect = arma::accu(newPredictions == trainingLabels); - REQUIRE(newCorrect - oldCorrect >= 0); + REQUIRE(newCorrect >= oldCorrect); } /** diff --git a/src/mlpack/tests/rectangle_tree_test.cpp b/src/mlpack/tests/rectangle_tree_test.cpp index aa487df94f..4d5b9e60bd 100644 --- a/src/mlpack/tests/rectangle_tree_test.cpp +++ b/src/mlpack/tests/rectangle_tree_test.cpp @@ -364,7 +364,7 @@ TEST_CASE("TreeBalance", "[RectangleTreeTraitsTest]") TreeType tree(dataset, 20, 6, 5, 2, 0); REQUIRE(GetMinLevel(tree) == GetMaxLevel(tree)); - REQUIRE(tree.TreeDepth() == GetMinLevel(tree)); + REQUIRE((int) tree.TreeDepth() == GetMinLevel(tree)); } // A test to see if point deletion is working correctly. We build a tree, then @@ -982,7 +982,7 @@ TEST_CASE("RPlusTreeOverlapTest", "[RectangleTreeTraitsTest]") // Ensure that all leaf nodes are at the same level. REQUIRE(GetMinLevel(rPlusTree) == GetMaxLevel(rPlusTree)); - REQUIRE(rPlusTree.TreeDepth() == GetMinLevel(rPlusTree)); + REQUIRE((int) rPlusTree.TreeDepth() == GetMinLevel(rPlusTree)); } @@ -1099,7 +1099,7 @@ TEST_CASE("RPlusPlusTreeBoundTest", "[RectangleTreeTraitsTest]") REQUIRE(b == false); REQUIRE(GetMinLevel(rPlusPlusTree) == GetMaxLevel(rPlusPlusTree)); - REQUIRE(rPlusPlusTree.TreeDepth() == GetMinLevel(rPlusPlusTree)); + REQUIRE((int) rPlusPlusTree.TreeDepth() == GetMinLevel(rPlusPlusTree)); // Check the MinimalSplitsNumberSweep. typedef RectangleTree Date: Mon, 24 May 2021 14:59:40 +0530 Subject: [PATCH 318/729] changed way to handle same key values --- src/mlpack/bindings/python/CMakeLists.txt | 1 + .../python/mlpack/preprocess_json_params.py | 271 +++++++++++------- .../bindings/python/print_class_defn.hpp | 36 ++- src/mlpack/bindings/python/print_pyx.cpp | 1 + 4 files changed, 198 insertions(+), 111 deletions(-) diff --git a/src/mlpack/bindings/python/CMakeLists.txt b/src/mlpack/bindings/python/CMakeLists.txt index c32edaaa24..cf0066a132 100644 --- a/src/mlpack/bindings/python/CMakeLists.txt +++ b/src/mlpack/bindings/python/CMakeLists.txt @@ -203,6 +203,7 @@ add_custom_command(TARGET python POST_BUILD mlpack/io.pxd mlpack/io_util.hpp mlpack/matrix_utils.py + mlpack/preprocess_json_params.py mlpack WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 209f817838..dc42876223 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,124 +1,105 @@ +#!/usr/bin/env python + from random import randint import numpy as np import json import pprint from copy import deepcopy +from collections import OrderedDict -def process_params(model, return_str=False, pretty_print=False, remove_version=False): - params = model.get_params() - params_decoded = params.decode("utf-8").replace("true", "True")\ - .replace("false", "False") - - # this is to handle same key names of "elem". - # same key values cannot exist in python dictionary, - # so I am replacing "elem" with random numbers. - str_to_find = '"elem":' - res = [i for i in range(len(params_decoded)) if\ - params_decoded.startswith(str_to_find, i)] - - # this variable keeps track of what random numbers are generated, - # to avoid same random numbers generated for two "elem" keys. - gen_nums = [] - - for i in range(len(res)): - random_num = random_with_N_digits(4) - - # keep generating until unique number is not found. - while(random_num in gen_nums): - random_num = random_with_N_digits(4) - - params_decoded = params_decoded[:res[i]] + '"{}":'.format(random_num) +\ - params_decoded[res[i]+len(str_to_find):] - - # now we can convert it to a python dictionary. - params_dic = eval(params_decoded) - - # remove "cereal_class_version". - if remove_version: - scrub(params_dic, "cereal_class_version") - - # convert armadillo dictionary to numpy array - arma_to_np(params_dic) +def process_params_out(model, params, return_str=False): + ''' + This method processes the parameters obtained from the model. + params: + 1) model - the model to process params. + 2) params - json parameters of the model (which we get through cereal). + 3) return_str (bool) - if True then a pretty string version of the params is returned. + ''' + # for pretty printing. pp = pprint.PrettyPrinter() - if pretty_print: - pp.pprint(params_dic) + params_dic = json.loads(params, object_pairs_hook=value_resolver) + + # remove "cereal_class_version". + cereal_class_version = [] # this stores the cereal_class_version value for all deleted pairs. + ref_path = [] + # 'full_paths' will store the complete path in the dictionary for all occurrences. + # this will be used during the reversed process, to insert 'cereal_class_version' + # at the correct places to avoid any errors. + full_paths = [] + + scrub(params_dic, "cereal_class_version", cereal_class_version, full_paths, ref_path) + + # storing 'cereal_class_version' occurrences paths and values. + model.scrubbed_params["cereal_class_version"] = { + "values": cereal_class_version, + "full_paths": full_paths, + } + + # convert armadillo dictionary to numpy array. + arma_to_np(params_dic) if return_str: return params_dic, pp.pformat(params_dic) else: return params_dic -def feed_params(model, params_dic): +def process_params_in(model, params_dic): """ This function takes in a model and the parameters dictionary, - and sets the parameters of the model as the given parameters. + and returns a string that can be ingested back into the model. """ # deepcopy to prevent changes to the user dictionary. params_dic_copy = deepcopy(params_dic) - # this list for keeping track of the random numbers generated to replace - # '"elem":' string, because python dictionaries cannot hold same keys. - rand_gen = [] - np_to_arma(params_dic_copy, rand_gen) + # convert numpy to armadillo. + np_to_arma(params_dic_copy) + + for param_name, details in model.scrubbed_params.items(): + for val, path in zip(details["values"], details["full_paths"]): + insert_in_dic(params_dic_copy, path, param_name, val) # dumping to string. - params_str = json.dumps(params_dic_copy) + params_str = json.dumps(params_dic_copy, cls=restore_value) + return params_str - # replacing random numbers with '"elem":' to match JSON given by cereal. - for rand_num in rand_gen: - params_str = params_str.replace('"{}":'.format(rand_num), '"elem":') - - # setting parameters to the model. - model.set_params(params_str.encode("utf-8")) - -def np_to_arma(obj, rand_gen): +def np_to_arma(obj): """ This function replaces a numpy array to json representation of armadillo vector. This is reverse of "arma_to_np(obj)". """ - if isinstance(obj, dict): + if isinstance(obj, OrderedDict): for key in obj.keys(): """ Checking if this is a numpy array. """ if isinstance(obj[key], np.ndarray): # n_rows, n_cols have to be strings. - n_rows, n_cols = str(1),str(1) - - dic = dict() - - if len(obj[key].shape) == 1: - n_rows = obj[key].shape[0] - dic["vec_state"] = str(1) - elif len(obj[key].shape) == 2: - n_rows, n_cols = obj[key].shape - dic["vec_state"] = str(2) - else: - raise RuntimeError("Invalid number of dimensions in array {}".format(len(onj[key].shape))) + n_rows, n_cols = obj[key].shape + dic = OrderedDict() + dic["n_rows"] = str(n_cols) # implicit transpose dic["n_cols"] = str(n_rows) # implicit transpose - elems = obj[key].flatten().astype(float) - - # writing elements of vector with random generated keys, - # these keys will be replaced by '"elem":' in "feed_params()" function. - for elem in elems: - random_key = random_with_N_digits(4) - while(random_key in rand_gen): - random_key = random_with_N_digits(4) - rand_gen.append(random_key) - dic[str(random_key)] = elem + if n_cols != 1 and n_rows != 1: + dic["vec_state"] = "0" + elif n_rows == 1: + dic["vec_state"] = "1" + elif n_cols == 1: + dic["vec_state"] = "2" + elems = obj[key].flatten() + dic["elem"] = list(elems) obj[key] = dic else: - np_to_arma(obj[key], rand_gen) + np_to_arma(obj[key]) elif isinstance(obj, list): for i in range(len(obj)): - np_to_arma(obj[i], rand_gen) + np_to_arma(obj[i]) else: + # we cannot recurse further if we do not have a dictionary or list object, so just pass. pass def arma_to_np(obj): @@ -126,25 +107,15 @@ def arma_to_np(obj): This function replaces the JSON representation of armadillo vector to numpy array in the given dictionary. """ - if isinstance(obj, dict): + if isinstance(obj, OrderedDict): for key in obj.keys(): - if isinstance(obj[key], dict): + if isinstance(obj[key], OrderedDict): # if "vec_state" is present in dictionary, then # it must be armadillo vector. if "vec_state" in obj[key].keys(): n_rows = int(obj[key]["n_rows"]) n_cols = int(obj[key]["n_cols"]) - elem_keys = list(set(obj[key].keys()).difference(set(["n_rows", "n_cols", "vec_state"]))) - elems = [] - for elem in elem_keys: - elems.append(obj[key][elem]) - - if n_rows*n_cols != len(elems): - raise RuntimeError("Shape {}x{} not valid with number of elements {}" - .format(n_rows, n_cols, len(elems))) - - elems = np.array(elems).reshape(n_cols, n_rows).astype(float) - obj[key] = elems + obj[key] = np.array(obj[key]["elem"]).reshape(n_cols, n_rows).astype(type(obj[key]["elem"][0])) # implicit transpose else: arma_to_np(obj[key]) else: @@ -153,32 +124,124 @@ def arma_to_np(obj): for i in range(len(obj)): arma_to_np(obj[i]) else: + # we cannot recurse further if we do not have a dictionary or list object, so just pass. pass -def scrub(obj, bad_key): +def scrub(obj, bad_key, values, full_paths, ref_path): """ This function removes a certain key-value pair from the given dictionary. + params: + 1) obj (dict) - dictionary to traverse. + 2) bad_key (str) - key to remove. + 3) values (list) - list of values of all occurrences of bad_key + (this will be used to insert bad_key back into dictionary). + 4) full_paths (list) - this is a list that contains full path to all occurrences of + bad_key (used to insert bad_key back into dictionary). + 5) ref_path (list) - this for keeping track of the current path in the dictionary. """ - if isinstance(obj, dict): + if isinstance(obj, OrderedDict): for key in list(obj.keys()): + ref_path.append(key) if key == bad_key: + ref_path.pop() + ref_path_copy = deepcopy(ref_path) + full_paths.append(ref_path_copy) + values.append(obj[key]) del obj[key] else: - scrub(obj[key], bad_key) + scrub(obj[key], bad_key, values, full_paths, ref_path) + if ref_path != []: + ref_path.pop() elif isinstance(obj, list): for i in range(len(obj)): - if obj[i] == bad_key: - del obj[i] - else: - scrub(obj[i], bad_key) + ref_path.append(f"listidx_{i}") + scrub(obj[i], bad_key, values, full_paths, ref_path) + if ref_path != []: + ref_path.pop() else: + ref_path.pop() pass -def random_with_N_digits(n): - """ - Generates random N digit numbers. - """ - range_start = 10**(n-1) - range_end = (10**n)-1 - return randint(range_start, range_end) \ No newline at end of file +def value_resolver(pairs): + ''' + This function converts multiple "elem" occurences to a list. + Eg: + str({ + vec_state: 1, + n_rows: 2, + n_cols: 1, + elem: 1, + elem: 2 + }) + + will be converted to + + dict({ + vec_state: 1, + n_rows: 2, + n_cols: 1, + elem: [1,2] + }) + This is done to handle same keys in the json while converting to python + dictionary. + ''' + has_elem = False + for key,val in pairs: + if key == "elem": + has_elem = True + break + if has_elem: + val_list = [val for (key,val) in pairs if key == "elem"] + pairs = [(key,val) for (key,val) in pairs if key != "elem"] + pairs.append(("elem", val_list)) + return OrderedDict(pairs) + +class restore_value(json.JSONEncoder): + ''' + This is a custom encoder. + Eg: + dict({ + vec_state: 1, + n_rows: 2, + n_cols: 1, + elem: [1,2] + }) + + will be converted into + + str({ + vec_state: 1, + n_rows: 2, + n_cols: 1, + elem: 1, + elem: 2 + }) + while encoding. + This is used to create a json that can be ingested to cereal. + ''' + def encode(self, o): + if isinstance(o, dict): + if "elem" in o.keys(): + to_return = '{%s' % ', '.join(': '.join((json.encoder.py_encode_basestring(k), self.encode(v))) for k, v in o.items() if k != "elem") + for val in o["elem"]: + to_return += ', ' + json.encoder.py_encode_basestring("elem") + f': {val}' + to_return += "}" + return to_return + else: + to_return = '{%s}' % ', '.join(': '.join((json.encoder.py_encode_basestring(k), self.encode(v))) for k, v in o.items()) + return to_return + if isinstance(o, list): + to_return = '[%s]' % ', '.join((self.encode(k) for k in o)) + return to_return + return super().encode(o) + +def insert_in_dic(dic, path, key, val): + temp = dic[path[0]] + for idx in range(1,len(path)): + if "listidx_" in path[idx]: + temp = temp[int(path[idx].replace("listidx_", ""))] + else: + temp = temp[path[idx]] + temp[key] = val + temp.move_to_end(key, last=False) diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 2f66adc241..ff1de4b26e 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -62,10 +62,12 @@ void PrintClassDefn( * @code * cdef class Type: * cdef * modelptr - * + * cdef public dict scrubbed_params + * * def __cinit__(self): * self.modelptr = new () - * + * self.scrubbed_params = dict() + * * def __dealloc__(self): * del self.modelptr * @@ -78,18 +80,29 @@ void PrintClassDefn( * def __reduce_ex__(self): * return (self.__class__, (), self.__getstate__()) * - * def get_params(self): + * def _get_cpp_params(self): * return SerializeOutJSON(self.modelptr, "") * - * def set_params(self, state): - * SerializeInJSON(seld.modelptr, state, "") + * def _set_cpp_params(self, state): + * SerializeInJSON(self.modelptr, state, "") + * + * def get_cpp_params(self, return_str=False): + * params = self._get_cpp_params() + * return process_params_out(self, params, return_str=return_str) + * + * def set_cpp_params(self, params_dic): + * params_str = process_params_in(self, params_dic) + * self._set_cpp_params(params_str) + * * @endcode */ std::cout << "cdef class " << strippedType << "Type:" << std::endl; std::cout << " cdef " << printedType << "* modelptr" << std::endl; + std::cout << " cdef public dict scrubbed_params" << std::endl; std::cout << std::endl; std::cout << " def __cinit__(self):" << std::endl; std::cout << " self.modelptr = new " << printedType << "()" << std::endl; + std::cout << " self.scrubbed_params = dict()" << std::endl; std::cout << std::endl; std::cout << " def __dealloc__(self):" << std::endl; std::cout << " del self.modelptr" << std::endl; @@ -106,13 +119,22 @@ void PrintClassDefn( std::cout << " return (self.__class__, (), self.__getstate__())" << std::endl; std::cout << std::endl; - std::cout << " def get_params(self):" << std::endl; + std::cout << " def _get_cpp_params(self):" << std::endl; std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType << "\")" << std::endl; - std::cout << " def set_params(self, state):" << std::endl; + std::cout << std::endl; + std::cout << " def _set_cpp_params(self, state):" << std::endl; std::cout << " SerializeInJSON(self.modelptr, state, \"" << printedType << "\")" << std::endl; std::cout << std::endl; + std::cout << " def get_cpp_params(self, return_str=False):" << std::endl; + std::cout << " params = self._get_cpp_params()" << std::endl; + std::cout << " return process_params_out(self, params, return_str=return_str)" << std::endl; + std::cout << std::endl; + std::cout << " def set_cpp_params(self, params_dic):" << std::endl; + std::cout << " params_str = process_params_in(self, params_dic)" << std::endl; + std::cout << " self._set_cpp_params(params_str.encode(\"utf-8\"))" << std::endl; + std::cout << std::endl; } /** diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index edcdb66ac1..1878b68d20 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,6 +80,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, " << "ResetTimers, EnableTimers" << endl; cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl; + cout << "from preprocess_json_params import process_params_out, process_params_in" << endl; cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON, SerializeInJSON" << endl; cout << endl; cout << "import numpy as np" << endl; From 9f80053f5d6c1a1bdc5e7decbe701afc5eb6f83f Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 15:05:02 +0530 Subject: [PATCH 319/729] added license and added description --- .../python/mlpack/preprocess_json_params.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index dc42876223..f83996b59c 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,5 +1,18 @@ #!/usr/bin/env python +""" +preprocess_json_params.py: utility functions for json paramter preprocessing + (see set_cpp_param() and get_cpp_param() methods + in print_class_defn.hpp) +This file defines the to_matrix() function, which can be used to convert Pandas +dataframes or other types of array-like objects to numpy ndarrays for use in +mlpack bindings. + +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. +""" from random import randint import numpy as np import json From 719f23ee71764d4ab56d27f71cef6fd40066626b Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 15:13:07 +0530 Subject: [PATCH 320/729] removed unused imports --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index f83996b59c..10f2a90dda 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -13,7 +13,6 @@ 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. """ -from random import randint import numpy as np import json import pprint From 3307cf1921df875727dc6ac8b6ee7d27df0ce905 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 18:44:22 +0530 Subject: [PATCH 321/729] added comments --- .../python/mlpack/preprocess_json_params.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 10f2a90dda..8128762959 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -31,6 +31,7 @@ def process_params_out(model, params, return_str=False): # for pretty printing. pp = pprint.PrettyPrinter() + # value_resolver defined later. params_dic = json.loads(params, object_pairs_hook=value_resolver) # remove "cereal_class_version". @@ -68,11 +69,12 @@ def process_params_in(model, params_dic): # convert numpy to armadillo. np_to_arma(params_dic_copy) + # inserting scrubbed parameters back into dictionary. for param_name, details in model.scrubbed_params.items(): for val, path in zip(details["values"], details["full_paths"]): insert_in_dic(params_dic_copy, path, param_name, val) - # dumping to string. + # dumping to string. restore_value defined later. params_str = json.dumps(params_dic_copy, cls=restore_value) return params_str @@ -177,7 +179,8 @@ def scrub(obj, bad_key, values, full_paths, ref_path): def value_resolver(pairs): ''' - This function converts multiple "elem" occurences to a list. + This function converts multiple "elem" occurences to a list when + used with json.loads(). Eg: str({ vec_state: 1, @@ -211,7 +214,8 @@ def value_resolver(pairs): class restore_value(json.JSONEncoder): ''' - This is a custom encoder. + This is a custom encoder that converts a dictionary to + correct json format for ingesting in cereal. Eg: dict({ vec_state: 1, @@ -249,6 +253,10 @@ class restore_value(json.JSONEncoder): return super().encode(o) def insert_in_dic(dic, path, key, val): + ''' + This function inserts a particluar key-value pair in a dictionray + after following a particular path. + ''' temp = dic[path[0]] for idx in range(1,len(path)): if "listidx_" in path[idx]: @@ -256,4 +264,5 @@ def insert_in_dic(dic, path, key, val): else: temp = temp[path[idx]] temp[key] = val + # moving key-value pair to the start. temp.move_to_end(key, last=False) From 872f868eb312591e24d7b470040e1cddf8b8183e Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 19:10:02 +0530 Subject: [PATCH 322/729] updated comment --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 8128762959..0b929c9387 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -4,9 +4,8 @@ preprocess_json_params.py: utility functions for json paramter preprocessing (see set_cpp_param() and get_cpp_param() methods in print_class_defn.hpp) -This file defines the to_matrix() function, which can be used to convert Pandas -dataframes or other types of array-like objects to numpy ndarrays for use in -mlpack bindings. +The "process_params_out" and "process_params_in" utilities are used to handle +interconversion between the output json from cereal and python dictionary. 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 From a759382e5853696154dc48acc98c10dfab9d87fb Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 24 May 2021 17:55:08 +0200 Subject: [PATCH 323/729] Check for blas and Lapack before downloading armadillo Signed-off-by: Omar Shrit --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index daf416f5e2..e2bd365156 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,6 +280,11 @@ if (DISABLE_DOWNLOADS) else() find_package(Armadillo "${ARMADILLO_VERSION}") if (NOT ARMADILLO_FOUND) + find_package(BLAS QUIET) + find_package(LAPACK QUIET) + if (NOT BLAS_FOUND AND NOT LAPACK_FOUND) + message(FATAL_ERROR "Can not find BLAS or LAPACK, please install one of them before installing mlpack") + endif() get_deps(http://files.mlpack.org/armadillo-10.3.0.tar.gz armadillo armadillo-10.3.0.tar.gz) set(ARMADILLO_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) find_package(Armadillo REQUIRED) From 32444d2336bf5dfc0f7c984385047ec904b83899 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 24 May 2021 18:18:21 +0200 Subject: [PATCH 324/729] Adding the missing installation step for the Autodownloader Signed-off-by: Omar Shrit --- CMake/Autodownload.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMake/Autodownload.cmake b/CMake/Autodownload.cmake index b82ab001b9..9339dcc9bf 100644 --- a/CMake/Autodownload.cmake +++ b/CMake/Autodownload.cmake @@ -45,9 +45,11 @@ macro(get_deps LINK DEPS_NAME PACKAGE) if (DIRECTORIES_LEN GREATER 0) list(GET DIRECTORIES 0 DEPENDENCY_DIR) set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") - # Clean this line when boost is removed. + install(DIRECTORY "${GENERIC_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + # Clean these lines when boost is removed. if (${DEPS_NAME} MATCHES "boost") set(Boost_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/") + install(DIRECTORY "${Boost_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") endif() else () message(FATAL_ERROR From de040a0e70837e13ab628e920dce26ed43f27ce2 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 24 May 2021 18:20:29 +0200 Subject: [PATCH 325/729] Add missing period --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2bd365156..6445bf7847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,7 +283,7 @@ else() find_package(BLAS QUIET) find_package(LAPACK QUIET) if (NOT BLAS_FOUND AND NOT LAPACK_FOUND) - message(FATAL_ERROR "Can not find BLAS or LAPACK, please install one of them before installing mlpack") + message(FATAL_ERROR "Can not find BLAS or LAPACK, please install one of them before installing mlpack.") endif() get_deps(http://files.mlpack.org/armadillo-10.3.0.tar.gz armadillo armadillo-10.3.0.tar.gz) set(ARMADILLO_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) From acc845683048f5ea762b618c2ceb12a11cbad4f2 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 25 May 2021 14:53:20 +0200 Subject: [PATCH 326/729] Update CMakeLists.txt Co-authored-by: Ryan Curtin --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6445bf7847..1b6729d10b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,7 +283,7 @@ else() find_package(BLAS QUIET) find_package(LAPACK QUIET) if (NOT BLAS_FOUND AND NOT LAPACK_FOUND) - message(FATAL_ERROR "Can not find BLAS or LAPACK, please install one of them before installing mlpack.") + message(FATAL_ERROR "Can not find BLAS or LAPACK! These are required for Armadillo. Please install one of them---or install Armadillo---before installing mlpack.") endif() get_deps(http://files.mlpack.org/armadillo-10.3.0.tar.gz armadillo armadillo-10.3.0.tar.gz) set(ARMADILLO_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) From 2436606a5056c8cbccbd45193e9b5e1e5c5e84b9 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 25 May 2021 11:47:37 -0400 Subject: [PATCH 327/729] Add some notes for usage on RHEL7. --- CMakeLists.txt | 5 +++++ README.md | 7 ++++++- doc/guide/build.hpp | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89418e9394..b314b0f5ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,11 @@ enable_testing() set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Ensure that GCC is new enough, if the compiler is GCC. +if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5) + message(FATAL_ERROR "GCC version (${CMAKE_CXX_COMPILER_VERSION}) is too old! 5.x or newer is required.") +endif () + # Include modules in the CMake directory. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake") diff --git a/README.md b/README.md index 10f82a2c12..16d6e5a4ab 100644 --- a/README.md +++ b/README.md @@ -153,11 +153,16 @@ mlpack_pca, mlpack_kmeans etc.) with the following command: On Fedora or Red Hat (EPEL): $ sudo dnf install mlpack-devel mlpack-bin -Note: Older Ubuntu versions may not have the most recent version of mlpack +*Note*: Older Ubuntu versions may not have the most recent version of mlpack available---for instance, at the time of this writing, Ubuntu 16.04 only has mlpack 3.4.2 available. Options include upgrading your Ubuntu version, finding a PPA or other non-official sources, or installing with a manual build. +*Note*: If you are using RHEL7/CentOS 7, gcc 4.8 is too old to compile mlpack. +One option is to use `devtoolset-8`; see +[here](https://www.softwarecollections.org/en/scls/rhscl/devtoolset-8/) for more +information. + There are some useful pages to consult in addition to this section: - [Building mlpack From Source](https://www.mlpack.org/doc/mlpack-git/doxygen/build.html) diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index c35582b667..a1ce7dfe31 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -63,6 +63,10 @@ $ sudo make install If the \c cmake \c .. command fails, you are probably missing a dependency, so check the output and install any necessary libraries. (See \ref build_dep.) +@note If you are using RHEL7/CentOS 7, the default version of gcc is too old. +One solution is to use \c devtoolset-8; more information is available at +https://www.softwarecollections.org/en/scls/rhscl/devtoolset-8/ . + On many Linux systems, mlpack will install by default to @c /usr/local/lib and you may need to set the @c LD_LIBRARY_PATH environment variable: From 39b814887bad244c8855ffe19a74030bdcf5d944 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Wed, 26 May 2021 13:22:44 +0530 Subject: [PATCH 328/729] faster forward pass of mean pool layer --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 80daaa9951..57f621f682 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -160,12 +160,23 @@ class MeanPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { + arma::mat inputPre = input; + size_t inRow = input.n_rows; + size_t inCol = input.n_cols; + + for(int i = 1; i < inCol; i++) + inputPre.col(i) += inputPre.col(i - 1); + + for(int i = 1; i < inRow; i++) + inputPre.row(i) += inputPre.row(i - 1); + for (size_t j = 0, colidx = 0; j < output.n_cols; ++j, colidx += strideHeight) { for (size_t i = 0, rowidx = 0; i < output.n_rows; ++i, rowidx += strideWidth) { + double val = 0.0; size_t rowEnd = rowidx + kernelWidth - 1; size_t colEnd = colidx + kernelHeight - 1; @@ -174,11 +185,17 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; - arma::mat subInput = input( - arma::span(rowidx, rowEnd), - arma::span(colidx, colEnd)); + val += inputPre(rowEnd, colEnd); + if(rowidx >= 1) + { + if(colidx >= 1) + val += inputPre(rowidx - 1, colidx - 1); + val -= inputPre(rowidx - 1, colEnd); + } + if(colidx >= 1) + val -= inputPre(rowEnd, colidx - 1); - output(i, j) = arma::mean(arma::mean(subInput)); + output(i, j) = val / input.n_elem; } } } From 8b6bdfb5fcbdcf6ac29983764a6e8ba3a16042ff Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Wed, 26 May 2021 20:08:03 +0530 Subject: [PATCH 329/729] Fixed kernalArea --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 57f621f682..8b066c6d3c 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -163,6 +163,7 @@ class MeanPooling arma::mat inputPre = input; size_t inRow = input.n_rows; size_t inCol = input.n_cols; + size_t kernalArea = kernelWidth * kernelHeight; for(int i = 1; i < inCol; i++) inputPre.col(i) += inputPre.col(i - 1); @@ -195,7 +196,7 @@ class MeanPooling if(colidx >= 1) val -= inputPre(rowEnd, colidx - 1); - output(i, j) = val / input.n_elem; + output(i, j) = val / kernalArea; } } } From bd95076c4e2295da009544c58a973abb3edbdc22 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Wed, 26 May 2021 20:10:52 +0530 Subject: [PATCH 330/729] Fixed kernal area if ceil = true --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 8b066c6d3c..ce9252bc29 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -163,7 +163,6 @@ class MeanPooling arma::mat inputPre = input; size_t inRow = input.n_rows; size_t inCol = input.n_cols; - size_t kernalArea = kernelWidth * kernelHeight; for(int i = 1; i < inCol; i++) inputPre.col(i) += inputPre.col(i - 1); @@ -186,6 +185,7 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; + size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); val += inputPre(rowEnd, colEnd); if(rowidx >= 1) { From 20a17d32fa07a669feba8818e0985c1f074836d6 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 27 May 2021 08:23:52 +0530 Subject: [PATCH 331/729] Style Fixes. --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index ce9252bc29..31e12a1541 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -160,14 +160,12 @@ class MeanPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { - arma::mat inputPre = input; - size_t inRow = input.n_rows; - size_t inCol = input.n_cols; + arma::Mt inputPre = input; - for(int i = 1; i < inCol; i++) + for(size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); - for(int i = 1; i < inRow; i++) + for(size_t i = 1; i < input.n_rows; ++i) inputPre.row(i) += inputPre.row(i - 1); for (size_t j = 0, colidx = 0; j < output.n_cols; @@ -185,15 +183,15 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; - size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); + const kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); val += inputPre(rowEnd, colEnd); - if(rowidx >= 1) + if (rowidx >= 1) { - if(colidx >= 1) + if (colidx >= 1) val += inputPre(rowidx - 1, colidx - 1); val -= inputPre(rowidx - 1, colEnd); } - if(colidx >= 1) + if (colidx >= 1) val -= inputPre(rowEnd, colidx - 1); output(i, j) = val / kernalArea; From c884d1538e57f3407a2d6e6a1e3990c87d8b2d37 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 27 May 2021 08:58:04 +0530 Subject: [PATCH 332/729] Minor fix --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 31e12a1541..eeb380f206 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -183,7 +183,7 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; - const kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); + const size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); val += inputPre(rowEnd, colEnd); if (rowidx >= 1) { From ac122a9ab73e9690faf4b9a696f725bead1e3836 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Wed, 26 May 2021 13:49:48 +0530 Subject: [PATCH 333/729] improved speed of mean_backward under certain condition --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 85 ++++++++++++++----- 1 file changed, 62 insertions(+), 23 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 80daaa9951..312388eab1 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -195,35 +195,74 @@ class MeanPooling arma::Mat& output) { - arma::Mat unpooledError; - for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + size_t condition = kernelHeight * kernelWidth - strideHeight * strideWidth - + kernelWidth - kernelHeight; + size_t kernalArea = kernelHeight * kernelWidth; + if (condition > 0) { - for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) - { - size_t rowEnd = i + kernelWidth - 1; - size_t colEnd = j + kernelHeight - 1; - - if (rowEnd > input.n_rows - 1) + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + { + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) { - if (floor) - continue; - rowEnd = input.n_rows - 1; + size_t rowEnd = i + kernelWidth - 1; + size_t colEnd = j + kernelHeight - 1; + + if (rowEnd >= input.n_rows || colEnd >= input.n_cols) + break; + + output(i, j) += error(rowidx, colidx) / kernalArea; + + if (rowEnd + 1 < input.n_rows) + { + output(rowEnd + 1, j) -= error(rowidx, colidx) / kernalArea; + + if (colEnd + 1 < input.n_cols) + output(rowEnd + 1, colEnd + 1) += error(rowidx, colidx) / kernalArea; + } } - if (colEnd > input.n_cols - 1) + if (colEnd + 1 < input.n_cols) + output(i, colEnd + 1) -= error(rowidx, colidx) / kernalArea; + } + + for (size_t i = 1; i < input.n_rows; ++i) + output.row(i) += output.row(i - 1); + + for (size_t j = 1; j < input.n_cols; ++j) + output.col(j) += output.col(j - 1); + } + else + { + arma::Mat unpooledError; + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + { + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) { - if (floor) - continue; - colEnd = input.n_cols - 1; + size_t rowEnd = i + kernelWidth - 1; + size_t colEnd = j + kernelHeight - 1; + + if (rowEnd > input.n_rows - 1) + { + if (floor) + continue; + rowEnd = input.n_rows - 1; + } + + if (colEnd > input.n_cols - 1) + { + if (floor) + continue; + colEnd = input.n_cols - 1; + } + + arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); + + unpooledError = arma::Mat(InputArea.n_rows, InputArea.n_cols); + unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem); + + output(arma::span(i, i + InputArea.n_rows - 1), + arma::span(j, j + InputArea.n_cols - 1)) += unpooledError; } - - arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); - - unpooledError = arma::Mat(InputArea.n_rows, InputArea.n_cols); - unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem); - - output(arma::span(i, i + InputArea.n_rows - 1), - arma::span(j, j + InputArea.n_cols - 1)) += unpooledError; } } } From b18199899b34ef5a5d76a986e9b9dfad26e5c193 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Wed, 26 May 2021 14:21:31 +0530 Subject: [PATCH 334/729] minor fix --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 312388eab1..bde20c3c6a 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -219,10 +219,10 @@ class MeanPooling if (colEnd + 1 < input.n_cols) output(rowEnd + 1, colEnd + 1) += error(rowidx, colidx) / kernalArea; } - } - if (colEnd + 1 < input.n_cols) - output(i, colEnd + 1) -= error(rowidx, colidx) / kernalArea; + if (colEnd + 1 < input.n_cols) + output(i, colEnd + 1) -= error(rowidx, colidx) / kernalArea; + } } for (size_t i = 1; i < input.n_rows; ++i) From 21744a71fd0bf9667baf7e697f0ae8ad71956645 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Wed, 26 May 2021 20:16:18 +0530 Subject: [PATCH 335/729] When ceil = true the kernal size will change. --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index bde20c3c6a..1df12e5bc5 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -197,7 +197,7 @@ class MeanPooling size_t condition = kernelHeight * kernelWidth - strideHeight * strideWidth - kernelWidth - kernelHeight; - size_t kernalArea = kernelHeight * kernelWidth; + if (condition > 0) { for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) @@ -207,9 +207,21 @@ class MeanPooling size_t rowEnd = i + kernelWidth - 1; size_t colEnd = j + kernelHeight - 1; - if (rowEnd >= input.n_rows || colEnd >= input.n_cols) - break; + if (rowEnd > input.n_rows - 1) + { + if (floor) + continue; + rowEnd = input.n_rows - 1; + } + if (colEnd > input.n_cols - 1) + { + if (floor) + continue; + colEnd = input.n_cols - 1; + } + + size_t kernalArea = (rowEnd - i + 1) * (colEnd - j + 1); output(i, j) += error(rowidx, colidx) / kernalArea; if (rowEnd + 1 < input.n_rows) From b3a691c3ab197458d0aa63f9c18064576e0324bb Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 27 May 2021 11:58:25 +0530 Subject: [PATCH 336/729] Update mean_pooling.hpp --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index eeb380f206..799f729884 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -160,7 +160,7 @@ class MeanPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { - arma::Mt inputPre = input; + arma::Mat inputPre = input; for(size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); From caa4246531079f343e857b6f826bd87c0fe66de6 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 16:19:16 +0530 Subject: [PATCH 337/729] implemented channel shuffle --- src/mlpack/methods/ann/layer/CMakeLists.txt | 2 + .../methods/ann/layer/channel_shuffle.hpp | 140 ++++++++++++++++++ .../ann/layer/channel_shuffle_impl.hpp | 137 +++++++++++++++++ src/mlpack/methods/ann/layer/layer_types.hpp | 2 + src/mlpack/tests/ann_layer_test.cpp | 39 +++++ 5 files changed, 320 insertions(+) create mode 100644 src/mlpack/methods/ann/layer/channel_shuffle.hpp create mode 100644 src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index 52dbebec75..d1eb91ff55 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -18,6 +18,8 @@ set(SOURCES batch_norm_impl.hpp bilinear_interpolation.hpp bilinear_interpolation_impl.hpp + channel_shuffle.hpp + channel_shuffle_impl.hpp concat.hpp concat_impl.hpp concat_performance.hpp diff --git a/src/mlpack/methods/ann/layer/channel_shuffle.hpp b/src/mlpack/methods/ann/layer/channel_shuffle.hpp new file mode 100644 index 0000000000..a9b3e2ec37 --- /dev/null +++ b/src/mlpack/methods/ann/layer/channel_shuffle.hpp @@ -0,0 +1,140 @@ +/** + * @file methods/ann/layer/channel_shuffle.hpp + * @author Abhinav Anand + * + * 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_CHANNEL_SHUFFLE_HPP +#define MLPACK_METHODS_ANN_LAYER_CHANNEL_SHUFFLE_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Definition and Implementation of the Channel Shuffle Layer. + * + * Channel Shuffle divide the channels/units in a tensor into groups + * and rearrange while keeping the original tensor shape. + * + * @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 ChannelShuffle +{ + public: + //! Create the Channel Shuffle object. + ChannelShuffle(); + + /** + * The constructor for the Channel Shuffle. + * + * @param depth Number of input slices. + * @param group Number of groups for shuffling channels. + */ + ChannelShuffle(const size_t inRowSize, + const size_t inColSize, + const size_t depth, + const size_t group); + + /** + * Forward pass through the layer. + * + * @param input The input matrix. + * @param output The resulting interpolated output matrix. + */ + template + void Forward(const arma::Mat& input, arma::Mat& 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. Since the layer does not have any learn-able parameters, + * we just have to down-sample the gradient to make its size compatible with + * the input size. + * + * @param * (input) The input matrix. + * @param gradient The computed backward gradient. + * @param output The resulting down-sampled output. + */ + template + void Backward(const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output); + + //! Get the output parameter. + OutputDataType const& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const& Delta() const { return delta; } + //! Modify the delta. + OutputDataType& Delta() { return delta; } + + //! Get the row size of the input. + size_t const& InRowSize() const { return inRowSize; } + //! Modify the row size of the input. + size_t& InRowSize() { return inRowSize; } + + //! Get the column size of the input. + size_t const& InColSize() const { return inColSize; } + //! Modify the column size of the input. + size_t& InColSize() { return inColSize; } + + //! Get the depth of the input. + size_t const& InDepth() const { return depth; } + //! Modify the depth of the input. + size_t& InDepth() { return depth; } + + //! Get the number of groups the channels is divided into. + size_t const& InGroup() const { return group; } + //! Modify the number of groups the channels is divided into. + size_t& InGroup() { return group; } + + //! Get the shape of the input. + size_t InputShape() const + { + return inRowSize; + } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& ar, const uint32_t /* version */); + + private: + //! Locally stored row size of the input. + size_t inRowSize; + //! Locally stored column size of the input. + size_t inColSize; + //! Locally stored depth of the input. + size_t depth; + //! Locally stored the number of groups the channels is divided into. + size_t group; + //! Locally stored number of input points. + size_t batchSize; + //! Locally-stored delta object. + OutputDataType delta; + //! Locally-stored output parameter object. + OutputDataType outputParameter; +}; // class ChannelShuffle + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "channel_shuffle_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp new file mode 100644 index 0000000000..96ee7eb76e --- /dev/null +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -0,0 +1,137 @@ +/** + * @file methods/ann/layer/channe_shuffle_impl.hpp + * @author Abhinav Anand + * + * Implementation of the channel shuffle function as an individual layer. + * + * 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_CHANNEL_SHUFFLE_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_CHANNEL_SHUFFLE_IMPL_HPP + +// In case it hasn't yet been included. +#include "channel_shuffle.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + + +template +ChannelShuffle:: +ChannelShuffle(): + inRowSize(0), + inColSize(0), + depth(0), + groupCount(0), + batchSize(0) +{ + // Nothing to do here. +} + +template +ChannelShuffle:: +ChannelShuffle( + const size_t inRowSize, + const size_t inColSize, + const size_t depth, + const size_t groupCount): + depth(depth), + groupCount(groupCount), + batchSize(0) +{ + if (depth % groupCount != 0) + { + Log::Fatal << "Number of channels must be divisible by groupCount.!" << std::endl; + } +} + +template +template +void ChannelShuffle::Forward( + const arma::Mat& input, arma::Mat& output) +{ + batchSize = input.n_cols; + cons + if (output.is_empty()) + output.set_size(inRowSize * inColSize * depth, batchSize); + else + { + assert(output.n_rows == inRowSize * inColSize * depth); + assert(output.n_cols == batchSize); + } + + + arma::cube inputAsCube(const_cast&>(input).memptr(), + inRowSize, inColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, + depth * batchSize, false, true); + + const size_t groupSize= depth / groupCount; + size_t outChannelIdx = 0; + for (int k = 0; k < batchSize; ++k) + { + for (int i = 0; i < groupSize; ++i) + { + for (int g = 0; g < groupCount; ++g, ++outChannelIdx) + { + size_t inChannelIdx = k * batchSize + g * groupSize + i; + outputAsCube.slice(outChannelIdx) = inputAsCube.slice(inChannelIdx); + } + } + } + +} + +template +template +void ChannelShuffle::Backward( + const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output) +{ + if (output.is_empty()) + output.set_size(inRowSize * inColSize * depth, batchSize); + else + { + assert(output.n_rows == inRowSize * inColSize * depth); + assert(output.n_cols == batchSize); + } + + arma::cube gradientAsCube(((arma::Mat&) gradient).memptr(), inColSize, + inColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, + depth * batchSize, false, true); + + const size_t groupSize= depth / groupCount; + size_t outChannelIdx = 0; + for (int k = 0; k < batchSize; ++k) + { + for (int i = 0; i < groupSize; ++i) + { + for (int g = 0; g < groupCount; ++g, ++outChannelIdx) + { + size_t gradientChannelIdx = k * batchSize + g * groupSize + i; + outputAsCube.slice(outChannelIdx) = inputAsCube.slice(gradientChannelIdx); + } + } + } + +} + +template +template +void ChannelShuffle::serialize( + Archive& ar, const uint32_t /* version */) +{ + ar(CEREAL_NVP(inRowSize)); + ar(CEREAL_NVP(inColSize)); + ar(CEREAL_NVP(depth)); +} + +} // namespace ann +} // namespace mlpack + +#endif diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index 2532efecfe..dfcf7a0645 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,7 @@ using MoreTypes = boost::variant< Linear3D*, LpPooling*, PixelShuffle*, + Channel_Shuffle*, Glimpse*, Highway*, MultiheadAttention*, diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 13576eb11a..74c158dc0d 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -4656,6 +4656,45 @@ TEST_CASE("TransposedConvolutionWeightInitializationTest", "[ANNLayerTest]") == (outSize * inSize * kernelWidth * kernelHeight) + outSize); } +/** + * Simple Test for ChannelShuffle layer. + */ +TEST_CASE("ChannelShuffleLayerTest", "[ANNLayerTest]") +{ + arma::mat input1, output1, outputExpected1; + ChannelShuffle<> module1(2, 2, 6, 2); + + input1 << 1 << 2 << arma::endr + << 3 << 4 << arma::endr + << 5 << 6 << arma::endr + << 7 << 8 << arma::endr + << 9 << 10 << arma::endr + << 11 << 12 << arma::endr + << 13 << 14 << arma::endr + << 15 << 16 << arma::endr + << 17 << 18 << arma::endr + << 19 << 20 << arma::endr + << 21 << 22 << arma::endr + << 23 << 24 << arma::endr; + input1.reshape(24, 1); + outputExpected1 << 1 << 2 << arma::endr + << 3 << 4 << arma::endr + << 13 << 14 << arma::endr + << 15 << 16 << arma::endr + << 5 << 6 << arma::endr + << 7 << 8 << arma::endr + << 17 << 18 << arma::endr + << 19 << 20 << arma::endr + << 9 << 10 << arma::endr + << 11 << 12 << arma::endr + << 21 << 22 << arma::endr + << 23 << 24 << arma::endr; + // Check the Forward pass of the layer. + module1.Forward(input1, output1); + CheckMatrices(output1, outputExpected1); + +} + /** * Simple Test for PixelShuffle layer. */ From c37e16331e250d414751cf88587940c2bc76b47f Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 16:28:24 +0530 Subject: [PATCH 338/729] fixed backwawrd function --- src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp index 96ee7eb76e..7ff3fbcb81 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -106,15 +106,15 @@ void ChannelShuffle::Backward( depth * batchSize, false, true); const size_t groupSize= depth / groupCount; - size_t outChannelIdx = 0; + size_t gradientChannelIdx = 0; for (int k = 0; k < batchSize; ++k) { for (int i = 0; i < groupSize; ++i) { - for (int g = 0; g < groupCount; ++g, ++outChannelIdx) + for (int g = 0; g < groupCount; ++g, ++gradientChannelIdx) { - size_t gradientChannelIdx = k * batchSize + g * groupSize + i; - outputAsCube.slice(outChannelIdx) = inputAsCube.slice(gradientChannelIdx); + size_t outChannelIdx = k * batchSize + g * groupSize + i; + outputAsCube.slice(outChannelIdx) = gradientAsCube.slice(gradientChannelIdx); } } } From 181f1807283a60392ccab2171155e90670d7c2a9 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 17:33:23 +0530 Subject: [PATCH 339/729] minor fix --- src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp | 4 +++- src/mlpack/methods/ann/layer/layer_types.hpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp index 7ff3fbcb81..32c9001b15 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -38,6 +38,8 @@ ChannelShuffle( const size_t inColSize, const size_t depth, const size_t groupCount): + inRowSize(inRowSize), + inColSize(inColSize), depth(depth), groupCount(groupCount), batchSize(0) @@ -54,7 +56,7 @@ void ChannelShuffle::Forward( const arma::Mat& input, arma::Mat& output) { batchSize = input.n_cols; - cons + if (output.is_empty()) output.set_size(inRowSize * inColSize * depth, batchSize); else diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index dfcf7a0645..d72cd1fa33 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -225,7 +225,7 @@ using MoreTypes = boost::variant< Linear3D*, LpPooling*, PixelShuffle*, - Channel_Shuffle*, + ChannelShuffle*, Glimpse*, Highway*, MultiheadAttention*, From b29c92b154a8eea64b187905f21b6dd671b4535c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:06:09 +0530 Subject: [PATCH 340/729] added doc --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 9648d9f580..a154e7eee9 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -155,9 +155,13 @@ std::string PrintTypeDoc( { return "An mlpack model pointer. This type can be pickled to or from disk, " "and internally holds a pointer to C++ memory containing the mlpack " - "model. Note that this means that the mlpack model itself cannot be " - "easily inspected in Python; however, the pickled model can be loaded " - "in C++ and inspected there."; + "model. This model pointer has 2 methods using which the parameters " + "of the model can be inspected as well as changed through Python. " + "The get_cpp_params() method returns a python ordered dictionary that " + "contains all the parameters of the model. The user can inspect the " + "parameters as well change the parameter values in the dictionary " + "(without deleting any keys) and pass that back into the model " + "using the set_cpp_params() method."; } } // namespace python From 00e70ca799e3c667d66c2bd00a016386b39cae1a Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:06:33 +0530 Subject: [PATCH 341/729] Update src/mlpack/bindings/python/mlpack/preprocess_json_params.py Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 0b929c9387..5ce0e3887d 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -257,7 +257,7 @@ def insert_in_dic(dic, path, key, val): after following a particular path. ''' temp = dic[path[0]] - for idx in range(1,len(path)): + for idx in range(1, len(path)): if "listidx_" in path[idx]: temp = temp[int(path[idx].replace("listidx_", ""))] else: From c054b86486a4e4e24a31869b55ecbf3f19736a2c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:06:42 +0530 Subject: [PATCH 342/729] Update src/mlpack/bindings/python/mlpack/preprocess_json_params.py Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 5ce0e3887d..5504940d21 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -74,7 +74,7 @@ def process_params_in(model, params_dic): insert_in_dic(params_dic_copy, path, param_name, val) # dumping to string. restore_value defined later. - params_str = json.dumps(params_dic_copy, cls=restore_value) + params_str = json.dumps(params_dic_copy, cls=restore_value) return params_str def np_to_arma(obj): From 8779900b6ebbfb0229568a0df189c8b5c535fc17 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:07:09 +0530 Subject: [PATCH 343/729] added new line --- src/mlpack/bindings/python/mlpack/serialization.pxd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/serialization.pxd b/src/mlpack/bindings/python/mlpack/serialization.pxd index dc3998fb70..b82c9e73a5 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.pxd +++ b/src/mlpack/bindings/python/mlpack/serialization.pxd @@ -13,4 +13,5 @@ cdef extern from "serialization.hpp" namespace "mlpack::bindings::python" nogil: string SerializeOut[T](T* t, string name) nogil void SerializeIn[T](T* t, string str, string name) nogil string SerializeOutJSON[T](T* t, string name) nogil - void SerializeInJSON[T](T* t, string str, string name) nogil \ No newline at end of file + void SerializeInJSON[T](T* t, string str, string name) nogil + From 210c1dc7d96fde8361c20b28fcbe78c7bcb533dc Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 18:11:05 +0530 Subject: [PATCH 344/729] minor fix --- src/mlpack/methods/ann/layer/channel_shuffle.hpp | 10 ++++++---- .../methods/ann/layer/channel_shuffle_impl.hpp | 12 ++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle.hpp b/src/mlpack/methods/ann/layer/channel_shuffle.hpp index a9b3e2ec37..dca7f45a1f 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle.hpp @@ -39,13 +39,15 @@ class ChannelShuffle /** * The constructor for the Channel Shuffle. * + * @param inRowSize Number of input rows. + * @param inColSize Number of input columns. * @param depth Number of input slices. * @param group Number of groups for shuffling channels. */ ChannelShuffle(const size_t inRowSize, const size_t inColSize, const size_t depth, - const size_t group); + const size_t groupCount); /** * Forward pass through the layer. @@ -98,9 +100,9 @@ class ChannelShuffle size_t& InDepth() { return depth; } //! Get the number of groups the channels is divided into. - size_t const& InGroup() const { return group; } + size_t const& InGroupCount() const { return groupCount; } //! Modify the number of groups the channels is divided into. - size_t& InGroup() { return group; } + size_t& InGroupCount() { return groupCount; } //! Get the shape of the input. size_t InputShape() const @@ -122,7 +124,7 @@ class ChannelShuffle //! Locally stored depth of the input. size_t depth; //! Locally stored the number of groups the channels is divided into. - size_t group; + size_t groupCount; //! Locally stored number of input points. size_t batchSize; //! Locally-stored delta object. diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp index 32c9001b15..5a4c2886ed 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -73,11 +73,11 @@ void ChannelShuffle::Forward( const size_t groupSize= depth / groupCount; size_t outChannelIdx = 0; - for (int k = 0; k < batchSize; ++k) + for (size_t k = 0; k < batchSize; ++k) { - for (int i = 0; i < groupSize; ++i) + for (size_t i = 0; i < groupSize; ++i) { - for (int g = 0; g < groupCount; ++g, ++outChannelIdx) + for (size_t g = 0; g < groupCount; ++g, ++outChannelIdx) { size_t inChannelIdx = k * batchSize + g * groupSize + i; outputAsCube.slice(outChannelIdx) = inputAsCube.slice(inChannelIdx); @@ -109,11 +109,11 @@ void ChannelShuffle::Backward( const size_t groupSize= depth / groupCount; size_t gradientChannelIdx = 0; - for (int k = 0; k < batchSize; ++k) + for (size_t k = 0; k < batchSize; ++k) { - for (int i = 0; i < groupSize; ++i) + for (size_t i = 0; i < groupSize; ++i) { - for (int g = 0; g < groupCount; ++g, ++gradientChannelIdx) + for (size_t g = 0; g < groupCount; ++g, ++gradientChannelIdx) { size_t outChannelIdx = k * batchSize + g * groupSize + i; outputAsCube.slice(outChannelIdx) = gradientAsCube.slice(gradientChannelIdx); From 99c2d40a6ab7b4aacf3cf237f7624867aad4fcd2 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:17:59 +0530 Subject: [PATCH 345/729] wrapped lines to 80 chars --- .../python/mlpack/preprocess_json_params.py | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 5504940d21..cd87ae4bc7 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -25,7 +25,8 @@ def process_params_out(model, params, return_str=False): params: 1) model - the model to process params. 2) params - json parameters of the model (which we get through cereal). - 3) return_str (bool) - if True then a pretty string version of the params is returned. + 3) return_str (bool) - if True then a pretty string version of the + params is returned. ''' # for pretty printing. pp = pprint.PrettyPrinter() @@ -34,14 +35,16 @@ def process_params_out(model, params, return_str=False): params_dic = json.loads(params, object_pairs_hook=value_resolver) # remove "cereal_class_version". - cereal_class_version = [] # this stores the cereal_class_version value for all deleted pairs. + # this stores the cereal_class_version value for all deleted pairs. + cereal_class_version = [] ref_path = [] - # 'full_paths' will store the complete path in the dictionary for all occurrences. - # this will be used during the reversed process, to insert 'cereal_class_version' - # at the correct places to avoid any errors. + # 'full_paths' will store the complete path in the dictionary for all + # occurrences. This will be used during the reversed process, to insert + # 'cereal_class_version' at the correct places to avoid any errors. full_paths = [] - scrub(params_dic, "cereal_class_version", cereal_class_version, full_paths, ref_path) + scrub(params_dic, "cereal_class_version", cereal_class_version, full_paths, + ref_path) # storing 'cereal_class_version' occurrences paths and values. model.scrubbed_params["cereal_class_version"] = { @@ -112,7 +115,8 @@ def np_to_arma(obj): for i in range(len(obj)): np_to_arma(obj[i]) else: - # we cannot recurse further if we do not have a dictionary or list object, so just pass. + # we cannot recurse further if we do not have a + # dictionary or list object, so just pass. pass def arma_to_np(obj): @@ -128,7 +132,9 @@ def arma_to_np(obj): if "vec_state" in obj[key].keys(): n_rows = int(obj[key]["n_rows"]) n_cols = int(obj[key]["n_cols"]) - obj[key] = np.array(obj[key]["elem"]).reshape(n_cols, n_rows).astype(type(obj[key]["elem"][0])) # implicit transpose + # implicit transpose + obj[key] = np.array(obj[key]["elem"])\ + .reshape(n_cols, n_rows).astype(type(obj[key]["elem"][0])) else: arma_to_np(obj[key]) else: @@ -137,7 +143,8 @@ def arma_to_np(obj): for i in range(len(obj)): arma_to_np(obj[i]) else: - # we cannot recurse further if we do not have a dictionary or list object, so just pass. + # we cannot recurse further if we do not have a + # dictionary or list object, so just pass. pass def scrub(obj, bad_key, values, full_paths, ref_path): @@ -148,10 +155,12 @@ def scrub(obj, bad_key, values, full_paths, ref_path): 1) obj (dict) - dictionary to traverse. 2) bad_key (str) - key to remove. 3) values (list) - list of values of all occurrences of bad_key - (this will be used to insert bad_key back into dictionary). - 4) full_paths (list) - this is a list that contains full path to all occurrences of - bad_key (used to insert bad_key back into dictionary). - 5) ref_path (list) - this for keeping track of the current path in the dictionary. + (this will be used to insert bad_key back into dictionary). + 4) full_paths (list) - this is a list that contains full path to all + occurrences of bad_key (used to insert bad_key back + into dictionary). + 5) ref_path (list) - this for keeping track of the current path in the + dictionary. """ if isinstance(obj, OrderedDict): for key in list(obj.keys()): @@ -238,13 +247,18 @@ class restore_value(json.JSONEncoder): def encode(self, o): if isinstance(o, dict): if "elem" in o.keys(): - to_return = '{%s' % ', '.join(': '.join((json.encoder.py_encode_basestring(k), self.encode(v))) for k, v in o.items() if k != "elem") + to_return = '{%s' % ', '.join( + ': '.join((json.encoder.py_encode_basestring(k), self.encode(v)))\ + for k, v in o.items() if k != "elem") for val in o["elem"]: - to_return += ', ' + json.encoder.py_encode_basestring("elem") + f': {val}' + to_return += ', ' + json.encoder.py_encode_basestring("elem") +\ + f': {val}' to_return += "}" return to_return else: - to_return = '{%s}' % ', '.join(': '.join((json.encoder.py_encode_basestring(k), self.encode(v))) for k, v in o.items()) + to_return = '{%s}' % ', '.join( + ': '.join((json.encoder.py_encode_basestring(k), self.encode(v)))\ + for k, v in o.items()) return to_return if isinstance(o, list): to_return = '[%s]' % ', '.join((self.encode(k) for k in o)) From 5ceb8daf1611b94f47a809ce8626d42e28cb01a8 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 27 May 2021 16:15:06 +0200 Subject: [PATCH 346/729] Check of the deps name is not equal boost Signed-off-by: Omar Shrit --- CMake/Autodownload.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMake/Autodownload.cmake b/CMake/Autodownload.cmake index 9339dcc9bf..ce23e32909 100644 --- a/CMake/Autodownload.cmake +++ b/CMake/Autodownload.cmake @@ -44,12 +44,13 @@ macro(get_deps LINK DEPS_NAME PACKAGE) list(LENGTH DIRECTORIES DIRECTORIES_LEN) if (DIRECTORIES_LEN GREATER 0) list(GET DIRECTORIES 0 DEPENDENCY_DIR) - set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") - install(DIRECTORY "${GENERIC_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") # Clean these lines when boost is removed. if (${DEPS_NAME} MATCHES "boost") set(Boost_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/") install(DIRECTORY "${Boost_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + else() + set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") + install(DIRECTORY "${GENERIC_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") endif() else () message(FATAL_ERROR From a0ae1ae7e0c8537be301d82d2d7341990fe3bf27 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 27 May 2021 16:51:42 +0200 Subject: [PATCH 347/729] Clean old no longer used download var for ensmallen and stb Signed-off-by: Omar Shrit --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b314b0f5ce..71b5c0d8d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,6 @@ option(TEST_VERBOSE "Run test cases with verbose output." OFF) option(BUILD_TESTS "Build tests." ON) option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON) option(DISABLE_DOWNLOADS "Disable downloads of dependencies during build." OFF) -option(DOWNLOAD_ENSMALLEN "If ensmallen is not found, download it." ON) -option(DOWNLOAD_STB_IMAGE "Download stb_image for image loading." ON) option(BUILD_GO_SHLIB "Build Go shared library." OFF) option(BUILD_DOCS "Build doxygen documentation (if doxygen is available)." ON) From d2114617ae6bfd0b066c3673eb848eacf2f14ff6 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 21:06:03 +0530 Subject: [PATCH 348/729] fixed test case --- src/mlpack/tests/ann_layer_test.cpp | 54 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 74c158dc0d..3a444947e8 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -4661,38 +4661,42 @@ TEST_CASE("TransposedConvolutionWeightInitializationTest", "[ANNLayerTest]") */ TEST_CASE("ChannelShuffleLayerTest", "[ANNLayerTest]") { - arma::mat input1, output1, outputExpected1; + arma::mat input1, output1, outputExpected1, outputBackward1; ChannelShuffle<> module1(2, 2, 6, 2); - input1 << 1 << 2 << arma::endr - << 3 << 4 << arma::endr - << 5 << 6 << arma::endr - << 7 << 8 << arma::endr - << 9 << 10 << arma::endr - << 11 << 12 << arma::endr - << 13 << 14 << arma::endr - << 15 << 16 << arma::endr - << 17 << 18 << arma::endr - << 19 << 20 << arma::endr - << 21 << 22 << arma::endr - << 23 << 24 << arma::endr; + input1 << 1 << 13 << arma::endr + << 2 << 14 << arma::endr + << 3 << 15 << arma::endr + << 4 << 16 << arma::endr + << 5 << 17 << arma::endr + << 6 << 18 << arma::endr + << 7 << 19 << arma::endr + << 8 << 20 << arma::endr + << 9 << 21 << arma::endr + << 10 << 22 << arma::endr + << 11 << 23 << arma::endr + << 12 << 24 << arma::endr; input1.reshape(24, 1); - outputExpected1 << 1 << 2 << arma::endr - << 3 << 4 << arma::endr - << 13 << 14 << arma::endr - << 15 << 16 << arma::endr - << 5 << 6 << arma::endr - << 7 << 8 << arma::endr - << 17 << 18 << arma::endr - << 19 << 20 << arma::endr - << 9 << 10 << arma::endr - << 11 << 12 << arma::endr - << 21 << 22 << arma::endr - << 23 << 24 << arma::endr; + outputExpected1 << 1 << 17 << arma::endr + << 2 << 18 << arma::endr + << 3 << 19 << arma::endr + << 4 << 20 << arma::endr + << 13 << 9 << arma::endr + << 14 << 10 << arma::endr + << 15 << 11 << arma::endr + << 16 << 12 << arma::endr + << 5 << 21 << arma::endr + << 6 << 22 << arma::endr + << 7 << 23 << arma::endr + << 8 << 24 << arma::endr; // Check the Forward pass of the layer. module1.Forward(input1, output1); CheckMatrices(output1, outputExpected1); + // Check the Backward pass of the layer. + module1.backward(output1, output1, outputBackward1); + CheckMatrices(input1, outputBackward1); + } /** From 5c1600c112785d85091a110ffa8f8594c680faeb Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 21:42:04 +0530 Subject: [PATCH 349/729] fixed test case --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 3a444947e8..2bc3eff890 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -4694,7 +4694,7 @@ TEST_CASE("ChannelShuffleLayerTest", "[ANNLayerTest]") CheckMatrices(output1, outputExpected1); // Check the Backward pass of the layer. - module1.backward(output1, output1, outputBackward1); + module1.Backward(output1, output1, outputBackward1); CheckMatrices(input1, outputBackward1); } From d8d6de550bbbe7647a29e3186fb9a8c8bbbbabe4 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Thu, 27 May 2021 22:48:07 +0530 Subject: [PATCH 350/729] fixed test case --- src/mlpack/tests/ann_layer_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 2bc3eff890..63c82f3b4a 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -4693,6 +4693,7 @@ TEST_CASE("ChannelShuffleLayerTest", "[ANNLayerTest]") module1.Forward(input1, output1); CheckMatrices(output1, outputExpected1); + outputExpected1.reshape(24, 1); // Check the Backward pass of the layer. module1.Backward(output1, output1, outputBackward1); CheckMatrices(input1, outputBackward1); From 86123a1e751d516e9b9c2d8a46af406df7e586be Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Fri, 28 May 2021 00:04:25 +0530 Subject: [PATCH 351/729] Fix test case --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 63c82f3b4a..a8d7c4605a 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -4689,11 +4689,11 @@ TEST_CASE("ChannelShuffleLayerTest", "[ANNLayerTest]") << 6 << 22 << arma::endr << 7 << 23 << arma::endr << 8 << 24 << arma::endr; + outputExpected1.reshape(24, 1); // Check the Forward pass of the layer. module1.Forward(input1, output1); CheckMatrices(output1, outputExpected1); - outputExpected1.reshape(24, 1); // Check the Backward pass of the layer. module1.Backward(output1, output1, outputBackward1); CheckMatrices(input1, outputBackward1); From a916ac4d45c53665529c5e592827f53760ad129e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 27 May 2021 23:23:23 +0200 Subject: [PATCH 352/729] Remove the variables from documenatations and README Signed-off-by: Omar Shrit --- README.md | 2 -- doc/guide/build.hpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/README.md b/README.md index 16d6e5a4ab..f7000edef0 100644 --- a/README.md +++ b/README.md @@ -219,10 +219,8 @@ Options are specified with the -D flag. The allowed options include: BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as opposed to static libraries DISABLE_DOWNLOADS=(ON/OFF): whether to disable all downloads during build - DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory for ensmallen - DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it STB_IMAGE_INCLUDE_DIR=(/path/to/stb/include): path to include directory for STB image library USE_OPENMP=(ON/OFF): whether or not to use OpenMP if available diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index a1ce7dfe31..ca48677cf0 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -193,9 +193,6 @@ The full list of options mlpack allows: (default OFF) - DISABLE_DOWNLOADS=(ON/OFF): Disable downloads of dependencies during build (default OFF) - - DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it - (default ON) - - DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it (default ON) - PYTHON_EXECUTABLE=(/path/to/python_version): Path to specific Python executable - PYTHON_INSTALL_PREFIX=(/path/to/python/): Path to root of Python installation - JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable From d3952325128ef892c91c2bfd525993346dc63387 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Fri, 28 May 2021 08:37:47 +0530 Subject: [PATCH 353/729] Added comments to explain the method and minor style fix --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 1df12e5bc5..57c00b3f35 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -195,15 +195,60 @@ class MeanPooling arma::Mat& output) { - size_t condition = kernelHeight * kernelWidth - strideHeight * strideWidth - + const size_t condition = kernelHeight * kernelWidth - strideHeight * strideWidth - kernelWidth - kernelHeight; if (condition > 0) { - for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + // If this condition is true then theoritically the prefix sum method of + // unpooling is faster. The aim of unpooling is to add + // `error(i, j) / kernalArea` to `inputArea(kernal)`. This requires + // inputArea.n_elem additions. So, total operations required will be + // `error.n_elem * inputArea.n_elem` operations. + // To improve this method we will use an idea of prefix sums. Let's see + // this method in 1-D matrix then we will extend it to 2-D matrix. + // Let the input be a 1-D matrix input = `[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]` of size 10 + // and we want to add `10` to idx = 1 to idx = 5. In brute force method we can run + // a loop from idx = 1 to idx = 5 and add `10` to each element. In prefix method + // We will add `+10` to idx = 1 and `-10` to idx = (5 + 1). Now the input will look + // like `[0, +10, 0, 0, 0, 0, -10, 0, 0, 0]`. After that we can just do prefix + // sum `input[i] += input[i - 1]`. Then the input becomes + // `[0, +10, +10, +10, +10, +10, 0, 0, 0, 0]`. So the total computation require + // by this method is (2 additions + Prefix operations). + // Note that if there are `k` such operation of adding a number of some + // continuous subarray. Then the brute force method will require + // `k * size(subarray)` operations. But the prefix method will require + // `2 * k + Prefix` operations, because the Prefix can be performed once at + // the end. + // Now for 2-D matrix. Lets say we want to add `e` to all elements from + // input(x1 : x2, y1 : y2). So the inputArea = (x2 - x1 + 1) * (y2 - y1 + 1). + // In prefix method the following operations will be performed: + // 1. Add `+e` to input(x1, y1). + // 2. Add `-e` to input(x1 + 1, y1). + // 3. Add `-e` to input(x1, y1 + 1). + // 4. Add `+e` to input(x1 + 1, y1 + 1). + // 5. Perform Prefix sum over columns i.e input(i, j) += input(i, j - 1) + // 6. Perform Prefix sum over rows i.e input(i, j) += input(i - 1, j) + // So lets say if we had `k` number of such operations. The brute force + // method will require `kernalArea * k` operations. + // The prefix method will require `4 * k + Prefix operation`. + + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, ++colidx) { - for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, ++rowidx) { + // We have to add error(i, j) to output(span(rowidx, rowEnd), span(colidx, colEnd)). + // The steps of prefix sum method: + // + // 1. For each (i, j) perform: + // 1.1 Add +error(i, j) to output(rowidx, colidx) + // 1.2 Add -error(i, j) to output(rowidx, colidx + 1) + // 1.3 Add -error(i, j) to output(rowidx + 1, colidx) + // 1.4 Add +error(i, j) to output(rowidx + 1, colidx + 1) + // + // 2. Do prefix sum column wise i.e output(i, j) += output(i, j - 1) + // 2. Do prefix sum row wise i.e output(i, j) += output(i - 1, j) + size_t rowEnd = i + kernelWidth - 1; size_t colEnd = j + kernelHeight - 1; @@ -246,9 +291,9 @@ class MeanPooling else { arma::Mat unpooledError; - for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, ++colidx) { - for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, ++rowidx) { size_t rowEnd = i + kernelWidth - 1; size_t colEnd = j + kernelHeight - 1; From 0bed1fec961b047d315c690d46ea52deddc1afff Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Fri, 28 May 2021 08:46:31 +0530 Subject: [PATCH 354/729] Apply suggestions from code review Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 799f729884..2480a9525f 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -162,10 +162,10 @@ class MeanPooling { arma::Mat inputPre = input; - for(size_t i = 1; i < input.n_cols; ++i) + for (size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); - for(size_t i = 1; i < input.n_rows; ++i) + for (size_t i = 1; i < input.n_rows; ++i) inputPre.row(i) += inputPre.row(i - 1); for (size_t j = 0, colidx = 0; j < output.n_cols; From 2ca058b3a73acd5c2f5f10448bb6a7b6060f5f78 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Fri, 28 May 2021 09:59:14 +0530 Subject: [PATCH 355/729] added to history --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 2f7aab9538..51583448ac 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? + * Added dict-style inspection of mlpack models in python bindings (#2868). + * Added warm start feature to Random Forest (#2881); this feature is accessible from mlpack's bindings to different languages. From ae4104b0d85409da6eeb7bf4234d793688dc20a2 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Tue, 1 Jun 2021 20:14:42 +0530 Subject: [PATCH 356/729] Apply suggestions from code review Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/channel_shuffle.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle.hpp b/src/mlpack/methods/ann/layer/channel_shuffle.hpp index dca7f45a1f..27c747e84a 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle.hpp @@ -16,9 +16,9 @@ namespace mlpack { namespace ann /** Artificial Neural Network. */ { /** - * Definition and Implementation of the Channel Shuffle Layer. + * Definition and implementation of the Channel Shuffle Layer. * - * Channel Shuffle divide the channels/units in a tensor into groups + * Channel Shuffle divides the channels/units in a tensor into groups * and rearrange while keeping the original tensor shape. * * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, From b190489ede4ae531ab0596bb76858fc5d0befbde Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:14:25 +0530 Subject: [PATCH 357/729] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index a154e7eee9..cbcb129246 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -157,7 +157,7 @@ std::string PrintTypeDoc( "and internally holds a pointer to C++ memory containing the mlpack " "model. This model pointer has 2 methods using which the parameters " "of the model can be inspected as well as changed through Python. " - "The get_cpp_params() method returns a python ordered dictionary that " + "The `get_cpp_params()` method returns a python ordered dictionary that " "contains all the parameters of the model. The user can inspect the " "parameters as well change the parameter values in the dictionary " "(without deleting any keys) and pass that back into the model " From d26b744ed56ff56f54a6d3c896ef2f32c6c88669 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:14:34 +0530 Subject: [PATCH 358/729] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index cbcb129246..767947807b 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -161,7 +161,6 @@ std::string PrintTypeDoc( "contains all the parameters of the model. The user can inspect the " "parameters as well change the parameter values in the dictionary " "(without deleting any keys) and pass that back into the model " - "using the set_cpp_params() method."; } } // namespace python From 297961a78c859ed05d9b5419a49ac0aad58b96fa Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:14:52 +0530 Subject: [PATCH 359/729] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 767947807b..0c52f1d481 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -155,7 +155,7 @@ std::string PrintTypeDoc( { return "An mlpack model pointer. This type can be pickled to or from disk, " "and internally holds a pointer to C++ memory containing the mlpack " - "model. This model pointer has 2 methods using which the parameters " + "model. This model pointer has 2 methods with which the parameters " "of the model can be inspected as well as changed through Python. " "The `get_cpp_params()` method returns a python ordered dictionary that " "contains all the parameters of the model. The user can inspect the " From 41024f6f7f188cf53854b574cc8b0db02d6e8f0c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:15:11 +0530 Subject: [PATCH 360/729] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 0c52f1d481..c062e9c7e1 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -158,9 +158,10 @@ std::string PrintTypeDoc( "model. This model pointer has 2 methods with which the parameters " "of the model can be inspected as well as changed through Python. " "The `get_cpp_params()` method returns a python ordered dictionary that " - "contains all the parameters of the model. The user can inspect the " - "parameters as well change the parameter values in the dictionary " - "(without deleting any keys) and pass that back into the model " + "contains all the parameters of the model. These parameters can " + "be inspected and changed. To set new parameters for a model, " + "pass the modified dictionary (without deleting any keys) to the " + "`set_cpp_params()` method." } } // namespace python From aaa1a47259f08b5cff4c9fdae82d95e7bff1e501 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 1 Jun 2021 19:15:10 -0400 Subject: [PATCH 361/729] Better handling of tree resetting for HoeffdingTree. --- .../hoeffding_trees/hoeffding_tree.hpp | 42 ++- .../hoeffding_trees/hoeffding_tree_impl.hpp | 291 ++++++++++-------- 2 files changed, 196 insertions(+), 137 deletions(-) diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp index b58d97a423..546d573d34 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp @@ -164,14 +164,14 @@ class HoeffdingTree /** * Copy assignment operator. - * + * * @param other Tree to copy. */ HoeffdingTree& operator=(const HoeffdingTree& other); /** * Move assignment operator. - * + * * @param other Tree to move. */ HoeffdingTree& operator=(HoeffdingTree&& other); @@ -183,20 +183,31 @@ class HoeffdingTree /** * Train on a set of points, either in streaming mode or in batch mode, with - * the given labels. + * the given labels. If `resetTree` is set to `true`, then reset the state of + * the tree to an empty tree before training. + * + * Note that the tree will be automatically reset if the dimensionality of + * `data` does not match the dimensionality that the tree was currently + * trained with. * * @param data Data points to train on. * @param labels Labels of data points. * @param batchTraining If true, perform training in batch. + * @param resetTree If true, reset the tree to an empty tree before training. */ template void Train(const MatType& data, const arma::Row& labels, - const bool batchTraining = true); + const bool batchTraining = true, + const bool resetTree = false); /** * Train on a set of points, either in streaming mode or in batch mode, with - * the given labels and the given DatasetInfo. This will reset the tree. + * the given labels and the given `DatasetInfo`. This will reset the tree. + * This only needs to be called when the `DatasetInfo` has changed---if you + * are training incrementally but have already passed the DatasetInfo once, + * use the overload of `Train()` that does not take a `DatasetInfo` and make + * sure `resetTree` is set to `false`. */ template void Train(const MatType& data, @@ -205,7 +216,8 @@ class HoeffdingTree const bool batchTraining = true); /** - * Train on a single point in streaming mode, with the given label. + * Train on a single point in streaming mode, with the given label. The tree + * will not be reset before training. * * @param point Point to train on. * @param label Label of point to train on. @@ -379,6 +391,24 @@ class HoeffdingTree typename NumericSplitType::SplitInfo numericSplit; //! If the split has occurred, these are the children. std::vector children; + + /** + * Perform training (typically after a reset, but not necessarily). This + * assumes datasetInfo and dimensionMappings are set correctly. + */ + template + void TrainInternal(const MatType& data, + const arma::Row& labels, + const bool batchTraining); + + /** + * Reset the tree. This assumes datasetInfo is set correctly. + */ + void ResetTree( + const CategoricalSplitType& categoricalSplitIn = + CategoricalSplitType(0, 0), + const NumericSplitType& numericSplitIn = + NumericSplitType(0)); }; } // namespace tree diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp index f79b0eb027..848824c15b 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp @@ -28,7 +28,7 @@ HoeffdingTree< NumericSplitType, CategoricalSplitType >::HoeffdingTree(const MatType& data, - const data::DatasetInfo& datasetInfo, + const data::DatasetInfo& datasetInfoIn, const arma::Row& labels, const size_t numClasses, const bool batchTraining, @@ -39,15 +39,14 @@ HoeffdingTree< const CategoricalSplitType& categoricalSplitIn, const NumericSplitType& numericSplitIn) : - dimensionMappings(new std::unordered_map>()), - ownsMappings(true), + dimensionMappings(NULL), + ownsMappings(false), numSamples(0), numClasses(numClasses), maxSamples((maxSamples == 0) ? size_t(-1) : maxSamples), checkInterval(checkInterval), minSamples(minSamples), - datasetInfo(new data::DatasetInfo(datasetInfo)), + datasetInfo(new data::DatasetInfo(datasetInfoIn)), ownsInfo(true), successProbability(successProbability), splitDimension(size_t(-1)), @@ -56,24 +55,8 @@ HoeffdingTree< categoricalSplit(0), numericSplit() { - // Generate dimension mappings and create split objects. - for (size_t i = 0; i < datasetInfo.Dimensionality(); ++i) - { - if (datasetInfo.Type(i) == data::Datatype::categorical) - { - categoricalSplits.push_back(CategoricalSplitType( - datasetInfo.NumMappings(i), numClasses, categoricalSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, - categoricalSplits.size() - 1); - } - else - { - numericSplits.push_back(NumericSplitType(numClasses, - numericSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric, - numericSplits.size() - 1); - } - } + // Reset the tree. + ResetTree(categoricalSplitIn, numericSplitIn); // Now train. Train(data, labels, batchTraining); @@ -119,23 +102,7 @@ HoeffdingTree< // Do we need to generate the mappings too? if (ownsMappings) { - for (size_t i = 0; i < datasetInfo.Dimensionality(); ++i) - { - if (datasetInfo.Type(i) == data::Datatype::categorical) - { - categoricalSplits.push_back(CategoricalSplitType( - datasetInfo.NumMappings(i), numClasses, categoricalSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, - categoricalSplits.size() - 1); - } - else - { - numericSplits.push_back(NumericSplitType(numClasses, - numericSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric, - numericSplits.size() - 1); - } - } + ResetTree(categoricalSplitIn, numericSplitIn); } else { @@ -381,71 +348,26 @@ void HoeffdingTree< CategoricalSplitType >::Train(const MatType& data, const arma::Row& labels, - const bool batchTraining) + const bool batchTraining, + const bool resetTree) { - if (batchTraining) + // We need to reset the tree either if the user asked for it, or if they + // passed data whose dimensionality is different than our datasetInfo object. + if (resetTree || data.n_rows != datasetInfo->Dimensionality()) { - // Pass all the points through the nodes, and then split only after that. - checkInterval = data.n_cols; // Only split on the last sample. - // Don't split if there are fewer than five points. - size_t oldMaxSamples = maxSamples; - maxSamples = std::max(size_t(data.n_cols - 1), size_t(5)); - for (size_t i = 0; i < data.n_cols; ++i) - Train(data.col(i), labels[i]); - maxSamples = oldMaxSamples; + // Create a new datasetInfo, which assumes that all features are numeric. + if (ownsInfo) + delete datasetInfo; + datasetInfo = new data::DatasetInfo(data.n_rows); + ownsInfo = true; - // Now, if we did split, find out which points go to which child, and - // perform the same batch training. - if (children.size() > 0) - { - // We need to create a vector of indices that represent the points that - // must go to each child, so we need children.size() vectors, but we don't - // know how long they will be. Therefore, we will create vectors each of - // size data.n_cols, but will probably not use all the memory we - // allocated, and then pass subvectors to the submat() function. - std::vector indices(children.size(), arma::uvec(data.n_cols)); - arma::Col counts = - arma::zeros>(children.size()); + // Set the number of classes correctly. + numClasses = arma::max(labels) + 1; - for (size_t i = 0; i < data.n_cols; ++i) - { - size_t direction = CalculateDirection(data.col(i)); - size_t currentIndex = counts[direction]; - indices[direction][currentIndex] = i; - counts[direction]++; - } - - // Now pass each of these submatrices to the children to perform - // batch-mode training. - for (size_t i = 0; i < children.size(); ++i) - { - // If we don't have any points that go to the child in question, don't - // train that child. - if (counts[i] == 0) - continue; - - // The submatrix here is non-contiguous, but I think this will be faster - // than copying the points to an ordered state. We still have to - // assemble the labels vector, though. - arma::Row childLabels = labels.cols( - indices[i].subvec(0, counts[i] - 1)); - - // Unfortunately, limitations of Armadillo's non-contiguous subviews - // prohibits us from successfully passing the non-contiguous subview to - // Train(), since the col() function is not provided. So, - // unfortunately, instead, we'll just extract the non-contiguous - // submatrix. - MatType childData = data.cols(indices[i].subvec(0, counts[i] - 1)); - children[i]->Train(childData, childLabels, true); - } - } - } - else - { - // We aren't training in batch mode; loop through the points. - for (size_t i = 0; i < data.n_cols; ++i) - Train(data.col(i), labels[i]); + ResetTree(); } + + TrainInternal(data, labels, batchTraining); } //! Train on a set of points. @@ -468,40 +390,13 @@ void HoeffdingTree< datasetInfo = &info; ownsInfo = false; - // Generate mappings. - if (ownsMappings) - delete dimensionMappings; + // Set the number of classes correctly. + numClasses = arma::max(labels) + 1; - const CategoricalSplitType categoricalSplitIn(0, 0); - const NumericSplitType numericSplitIn(0); - - dimensionMappings = - new std::unordered_map>(); - for (size_t i = 0; i < datasetInfo->Dimensionality(); ++i) - { - if (datasetInfo->Type(i) == data::Datatype::categorical) - { - categoricalSplits.push_back(CategoricalSplitType( - datasetInfo->NumMappings(i), numClasses, categoricalSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, - categoricalSplits.size() - 1); - } - else - { - numericSplits.push_back(NumericSplitType(numClasses, - numericSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric, - numericSplits.size() - 1); - } - } - - // Remove any old children. - for (size_t i = 0; i < children.size(); ++i) - delete children[i]; - children.clear(); + ResetTree(); // Now train. - Train(data, labels, batchTraining); + TrainInternal(data, labels, batchTraining); } //! Train on one point. @@ -1036,6 +931,140 @@ void HoeffdingTree< } } +template< + typename FitnessFunction, + template class NumericSplitType, + template class CategoricalSplitType +> +template +void HoeffdingTree< + FitnessFunction, + NumericSplitType, + CategoricalSplitType +>::TrainInternal(const MatType& data, + const arma::Row& labels, + const bool batchTraining) +{ + if (batchTraining) + { + // Pass all the points through the nodes, and then split only after that. + checkInterval = data.n_cols; // Only split on the last sample. + // Don't split if there are fewer than five points. + size_t oldMaxSamples = maxSamples; + maxSamples = std::max(size_t(data.n_cols - 1), size_t(5)); + for (size_t i = 0; i < data.n_cols; ++i) + Train(data.col(i), labels[i]); + maxSamples = oldMaxSamples; + + // Now, if we did split, find out which points go to which child, and + // perform the same batch training. + if (children.size() > 0) + { + // We need to create a vector of indices that represent the points that + // must go to each child, so we need children.size() vectors, but we don't + // know how long they will be. Therefore, we will create vectors each of + // size data.n_cols, but will probably not use all the memory we + // allocated, and then pass subvectors to the submat() function. + std::vector indices(children.size(), arma::uvec(data.n_cols)); + arma::Col counts = + arma::zeros>(children.size()); + + for (size_t i = 0; i < data.n_cols; ++i) + { + size_t direction = CalculateDirection(data.col(i)); + size_t currentIndex = counts[direction]; + indices[direction][currentIndex] = i; + counts[direction]++; + } + + // Now pass each of these submatrices to the children to perform + // batch-mode training. + for (size_t i = 0; i < children.size(); ++i) + { + // If we don't have any points that go to the child in question, don't + // train that child. + if (counts[i] == 0) + continue; + + // The submatrix here is non-contiguous, but I think this will be faster + // than copying the points to an ordered state. We still have to + // assemble the labels vector, though. + arma::Row childLabels = labels.cols( + indices[i].subvec(0, counts[i] - 1)); + + // Unfortunately, limitations of Armadillo's non-contiguous subviews + // prohibits us from successfully passing the non-contiguous subview to + // Train(), since the col() function is not provided. So, + // unfortunately, instead, we'll just extract the non-contiguous + // submatrix. + MatType childData = data.cols(indices[i].subvec(0, counts[i] - 1)); + children[i]->Train(childData, childLabels, true); + } + } + } + else + { + // We aren't training in batch mode; loop through the points. + for (size_t i = 0; i < data.n_cols; ++i) + Train(data.col(i), labels[i]); + } +} + +template< + typename FitnessFunction, + template class NumericSplitType, + template class CategoricalSplitType +> +void HoeffdingTree< + FitnessFunction, + NumericSplitType, + CategoricalSplitType +>::ResetTree(const CategoricalSplitType& categoricalSplitIn, + const NumericSplitType& numericSplitIn) +{ + // Generate mappings. + if (ownsMappings) + delete dimensionMappings; + + categoricalSplits.clear(); + numericSplits.clear(); + + dimensionMappings = + new std::unordered_map>(); + ownsMappings = true; + for (size_t i = 0; i < datasetInfo->Dimensionality(); ++i) + { + if (datasetInfo->Type(i) == data::Datatype::categorical) + { + categoricalSplits.push_back(CategoricalSplitType( + datasetInfo->NumMappings(i), numClasses, categoricalSplitIn)); + (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, + categoricalSplits.size() - 1); + } + else + { + numericSplits.push_back(NumericSplitType(numClasses, + numericSplitIn)); + (*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric, + numericSplits.size() - 1); + } + } + + // Clear children. + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; + children.clear(); + + // Reset statistics. + numSamples = 0; + splitDimension = size_t(-1); + majorityClass = 0; + majorityProbability = 0.0; + categoricalSplit = + typename CategoricalSplitType::SplitInfo(0); + numericSplit = typename NumericSplitType::SplitInfo(); +} + } // namespace tree } // namespace mlpack From 6461067aacfecd8c7d8d85f861ea2ccdb186deb7 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 1 Jun 2021 19:15:45 -0400 Subject: [PATCH 362/729] Add tests for using HoeffdingTrees with an empty constructor. --- src/mlpack/tests/hoeffding_tree_test.cpp | 49 +++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/hoeffding_tree_test.cpp b/src/mlpack/tests/hoeffding_tree_test.cpp index de7db90443..3b3a7c902f 100644 --- a/src/mlpack/tests/hoeffding_tree_test.cpp +++ b/src/mlpack/tests/hoeffding_tree_test.cpp @@ -1044,7 +1044,7 @@ TEST_CASE("BatchTrainingTest", "[HoeffdingTreeTest]") // able to have enough samples to build to the same leaves. HoeffdingTree<> batchTree(trainingData, info, trainingLabels, 5, true, 0.99999999); - HoeffdingTree<> streamTree(trainingLabels, info, trainingLabels, 5, false, + HoeffdingTree<> streamTree(trainingData, info, trainingLabels, 5, false, 0.99999999); // Ensure that the performance of the batch tree is better. @@ -1475,3 +1475,50 @@ TEST_CASE("HoeffdingTreeModelSerializationTest", "[HoeffdingTreeTest]") } } } + +TEST_CASE("HoeffdingTreeEmptyConstructorTrainTest", "[HoeffdingTreeTest]") +{ + // Generate data. + arma::mat data(5, 1000, arma::fill::randu); + // Generate labels. + arma::Row labels(1000); + for (size_t i = 0; i < 500; ++i) + labels[i] = 0; + for (size_t i = 500; i < 1000; ++i) + labels[i] = 1; + + // Create an empty tree. + HoeffdingTree<> ht; + + // Just ensure that we can train without throwing an exception. + REQUIRE_NOTHROW(ht.Train(data, labels)); + + // Now, create a categorical dataset and retrain. + data = arma::mat(4, 3000); + labels.set_size(3000); + data::DatasetInfo info(4); // All features are numeric, except the fourth. + info.MapString("0", 3); + for (size_t i = 0; i < 3000; i += 3) + { + data(0, i) = mlpack::math::Random(); + data(1, i) = mlpack::math::Random(); + data(2, i) = mlpack::math::Random(); + data(3, i) = 0.0; + labels[i] = 0; + + data(0, i + 1) = mlpack::math::Random(); + data(1, i + 1) = mlpack::math::Random() - 1.0; + data(2, i + 1) = mlpack::math::Random() + 0.5; + data(3, i + 1) = 0.0; + labels[i + 1] = 2; + + data(0, i + 2) = mlpack::math::Random(); + data(1, i + 2) = mlpack::math::Random() + 1.0; + data(2, i + 2) = mlpack::math::Random() + 0.8; + data(3, i + 2) = 0.0; + labels[i + 2] = 1; + } + + // Ensure we can train without throwing an exception. + REQUIRE_NOTHROW(ht.Train(data, info, labels)); +} From 052a0216d9da9bb17d190e92e2c6234d33e15851 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 1 Jun 2021 19:15:56 -0400 Subject: [PATCH 363/729] Update HISTORY. --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 9eec0b93e5..b4b523a3a6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -54,6 +54,9 @@ * The `mlpack_test` target is no longer built as part of `make all`. Use `make mlpack_test` to build the tests. + * Fixes to `HoeffdingTree`: ensure that training still works when empty + constructor is used. + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From 54402ee5ac9bf2588b6a1218be752fe2ecf0aa09 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 17:53:49 -0400 Subject: [PATCH 364/729] Add numClasses argument to HoeffdingTree training methods. --- .../methods/decision_tree/decision_tree.hpp | 8 ++-- .../hoeffding_trees/hoeffding_tree.hpp | 18 +++++++-- .../hoeffding_trees/hoeffding_tree_impl.hpp | 13 +++--- src/mlpack/tests/hoeffding_tree_test.cpp | 40 ++++++++++--------- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree.hpp b/src/mlpack/methods/decision_tree/decision_tree.hpp index 9afc4191b8..df81dc61ad 100644 --- a/src/mlpack/methods/decision_tree/decision_tree.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree.hpp @@ -203,10 +203,10 @@ class DecisionTree : typename std::remove_reference::type>::value>* = 0); /** - * Take ownership of another decision tree and train on the given data and labels - * with weights, assuming that the data is all of the numeric type. Setting - * minimumLeafSize and minimumGainSplit too small may cause the tree to - * overfit, but setting them too large may cause it to underfit. + * Take ownership of another decision tree and train on the given data and + * labels with weights, assuming that the data is all of the numeric type. + * Setting minimumLeafSize and minimumGainSplit too small may cause the tree + * to overfit, but setting them too large may cause it to underfit. * * Use std::move if data, labels or weights are no longer needed to avoid * copies. diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp index 546d573d34..2c58dfa787 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp @@ -188,18 +188,22 @@ class HoeffdingTree * * Note that the tree will be automatically reset if the dimensionality of * `data` does not match the dimensionality that the tree was currently - * trained with. + * trained with. The tree will also be reset if `numClasses` is passed. * * @param data Data points to train on. * @param labels Labels of data points. * @param batchTraining If true, perform training in batch. * @param resetTree If true, reset the tree to an empty tree before training. + * @param numClasses The number of classes in `labels`. Passing this will + * reset the tree. If not given and `resetTree` is `true`, then the + * number of classes will be computed from `labels`. */ template void Train(const MatType& data, const arma::Row& labels, const bool batchTraining = true, - const bool resetTree = false); + const bool resetTree = false, + const size_t numClasses = 0); /** * Train on a set of points, either in streaming mode or in batch mode, with @@ -208,12 +212,20 @@ class HoeffdingTree * are training incrementally but have already passed the DatasetInfo once, * use the overload of `Train()` that does not take a `DatasetInfo` and make * sure `resetTree` is set to `false`. + * + * @param data Data points to train on. + * @param info DatasetInfo object with information about each dimension. + * @param labels Labels of data points. + * @param batchTraining If true, perform training in batch. + * @param numClasses Number of classes in `labels`. If not specified, it is + * computed from `labels`. */ template void Train(const MatType& data, const data::DatasetInfo& info, const arma::Row& labels, - const bool batchTraining = true); + const bool batchTraining = true, + const size_t numClasses = 0); /** * Train on a single point in streaming mode, with the given label. The tree diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp index 848824c15b..77d6dc5b3c 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp @@ -349,11 +349,13 @@ void HoeffdingTree< >::Train(const MatType& data, const arma::Row& labels, const bool batchTraining, - const bool resetTree) + const bool resetTree, + const size_t numClassesIn) { // We need to reset the tree either if the user asked for it, or if they // passed data whose dimensionality is different than our datasetInfo object. - if (resetTree || data.n_rows != datasetInfo->Dimensionality()) + if (resetTree || data.n_rows != datasetInfo->Dimensionality() || + numClassesIn != 0) { // Create a new datasetInfo, which assumes that all features are numeric. if (ownsInfo) @@ -362,7 +364,7 @@ void HoeffdingTree< ownsInfo = true; // Set the number of classes correctly. - numClasses = arma::max(labels) + 1; + numClasses = (numClassesIn != 0) ? numClassesIn : arma::max(labels) + 1; ResetTree(); } @@ -382,7 +384,8 @@ void HoeffdingTree< >::Train(const MatType& data, const data::DatasetInfo& info, const arma::Row& labels, - const bool batchTraining) + const bool batchTraining, + const size_t numClassesIn) { // Take over new DatasetInfo. if (ownsInfo) @@ -391,7 +394,7 @@ void HoeffdingTree< ownsInfo = false; // Set the number of classes correctly. - numClasses = arma::max(labels) + 1; + numClasses = (numClassesIn != 0) ? numClassesIn : arma::max(labels) + 1; ResetTree(); diff --git a/src/mlpack/tests/hoeffding_tree_test.cpp b/src/mlpack/tests/hoeffding_tree_test.cpp index 3b3a7c902f..02db5e5c24 100644 --- a/src/mlpack/tests/hoeffding_tree_test.cpp +++ b/src/mlpack/tests/hoeffding_tree_test.cpp @@ -1494,31 +1494,35 @@ TEST_CASE("HoeffdingTreeEmptyConstructorTrainTest", "[HoeffdingTreeTest]") REQUIRE_NOTHROW(ht.Train(data, labels)); // Now, create a categorical dataset and retrain. - data = arma::mat(4, 3000); - labels.set_size(3000); + arma::mat data2 = arma::mat(4, 3000); + arma::Row labels2(3000); data::DatasetInfo info(4); // All features are numeric, except the fourth. info.MapString("0", 3); for (size_t i = 0; i < 3000; i += 3) { - data(0, i) = mlpack::math::Random(); - data(1, i) = mlpack::math::Random(); - data(2, i) = mlpack::math::Random(); - data(3, i) = 0.0; - labels[i] = 0; + data2(0, i) = mlpack::math::Random(); + data2(1, i) = mlpack::math::Random(); + data2(2, i) = mlpack::math::Random(); + data2(3, i) = 0.0; + labels2[i] = 0; - data(0, i + 1) = mlpack::math::Random(); - data(1, i + 1) = mlpack::math::Random() - 1.0; - data(2, i + 1) = mlpack::math::Random() + 0.5; - data(3, i + 1) = 0.0; - labels[i + 1] = 2; + data2(0, i + 1) = mlpack::math::Random(); + data2(1, i + 1) = mlpack::math::Random() - 1.0; + data2(2, i + 1) = mlpack::math::Random() + 0.5; + data2(3, i + 1) = 0.0; + labels2[i + 1] = 2; - data(0, i + 2) = mlpack::math::Random(); - data(1, i + 2) = mlpack::math::Random() + 1.0; - data(2, i + 2) = mlpack::math::Random() + 0.8; - data(3, i + 2) = 0.0; - labels[i + 2] = 1; + data2(0, i + 2) = mlpack::math::Random(); + data2(1, i + 2) = mlpack::math::Random() + 1.0; + data2(2, i + 2) = mlpack::math::Random() + 0.8; + data2(3, i + 2) = 0.0; + labels2[i + 2] = 1; } // Ensure we can train without throwing an exception. - REQUIRE_NOTHROW(ht.Train(data, info, labels)); + REQUIRE_NOTHROW(ht.Train(data2, info, labels2)); + + // Train while specifying the number of classes. + REQUIRE_NOTHROW(ht.Train(data, labels, false, true, 2)); + REQUIRE_NOTHROW(ht.Train(data2, info, labels2, false, 3)); } From 639f1d3e4e84d3e515354a448291e453b0b7a585 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 17:54:09 -0400 Subject: [PATCH 365/729] Update HISTORY. --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index b4b523a3a6..4409dbcfb2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -55,7 +55,7 @@ `make mlpack_test` to build the tests. * Fixes to `HoeffdingTree`: ensure that training still works when empty - constructor is used. + constructor is used (#2964). ### mlpack 3.4.2 ###### 2020-10-26 From bfde132ca75044fdcf01c0c5f4c8b39fcbbb26b5 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 18:08:49 -0400 Subject: [PATCH 366/729] Fix style issues (hopefully). --- src/mlpack/bindings/python/print_pyx.cpp | 3 +- src/mlpack/core/cv/cv_base_impl.hpp | 4 +-- src/mlpack/core/util/mlpack_main.hpp | 4 +-- src/mlpack/core/util/size_checks.hpp | 4 +-- .../simple_residue_termination.hpp | 2 +- .../activation_functions/silu_function.hpp | 30 ++++++++++--------- .../tanh_exponential_function.hpp | 5 ++-- src/mlpack/methods/ann/ffn_impl.hpp | 18 +++++------ .../methods/ann/layer/atrous_convolution.hpp | 10 ++++--- src/mlpack/methods/ann/layer/base_layer.hpp | 4 +-- .../methods/ann/layer/concatenate_impl.hpp | 8 ++--- .../ann/layer/flatten_t_swish_impl.hpp | 12 ++++---- src/mlpack/methods/ann/layer/gru.hpp | 2 +- src/mlpack/methods/ann/layer/isrlu.hpp | 1 - src/mlpack/methods/ann/layer/linear.hpp | 2 +- src/mlpack/methods/ann/layer/lp_pooling.hpp | 10 ++++--- src/mlpack/methods/ann/layer/lstm.hpp | 5 +++- src/mlpack/methods/ann/layer/lstm_impl.hpp | 12 ++++---- src/mlpack/methods/ann/layer/mean_pooling.hpp | 14 +++++---- .../methods/ann/layer/pixel_shuffle_impl.hpp | 10 +++---- .../methods/ann/layer/recurrent_impl.hpp | 29 ++++++++++-------- .../methods/ann/layer/reparametrization.hpp | 8 ++--- .../ann/layer/reparametrization_impl.hpp | 18 +++++------ .../binary_cross_entropy_loss_impl.hpp | 2 +- .../ann/loss_functions/huber_loss_impl.hpp | 14 +++++---- .../ann/loss_functions/kl_divergence_impl.hpp | 8 +++-- .../sigmoid_cross_entropy_error.hpp | 6 ++-- .../loss_functions/triplet_margin_loss.hpp | 2 +- .../triplet_margin_loss_impl.hpp | 9 ++++-- src/mlpack/methods/ann/rnn_impl.hpp | 15 ++++------ 30 files changed, 145 insertions(+), 126 deletions(-) diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 6853c969da..d2f03a8f4c 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -230,7 +230,8 @@ void PrintPYX(const util::BindingDetails& doc, << "\'bool'!\")" << endl; cout << endl; - // Before calling mlpackMain(), we check input matrices for NaN values if needed. + // Before calling mlpackMain(), we check input matrices for NaN values if + // needed. cout << " if check_input_matrices:" << endl; cout << " IO.CheckInputMatrices()" << endl; diff --git a/src/mlpack/core/cv/cv_base_impl.hpp b/src/mlpack/core/cv/cv_base_impl.hpp index 0da9f8f4fa..0a3d01e511 100644 --- a/src/mlpack/core/cv/cv_base_impl.hpp +++ b/src/mlpack/core/cv/cv_base_impl.hpp @@ -108,8 +108,8 @@ void CVBase::AssertDataConsistency(const MatType& xs, const PredictionsType& ys) { - util::CheckSameSizes(xs, (size_t) ys.n_cols, "CVBase::AssertDataConsistency()", - "predictions"); + util::CheckSameSizes(xs, (size_t) ys.n_cols, + "CVBase::AssertDataConsistency()", "predictions"); } template - static void Fn(const InputVecType &x, OutputVecType &y) + static void Fn(const InputVecType &x, OutputVecType &y) { - y = x / (1.0 + arma::exp(-x)); + y = x / (1.0 + arma::exp(-x)); } /** @@ -70,10 +72,10 @@ class SILUFunction * @param y Input activation. * @return f'(x) */ - static double Deriv(const double x) + static double Deriv(const double x) { - double sigmoid = 1.0 / (1.0 + std::exp(-x)); - return sigmoid * (1.0 + x * (1.0 - sigmoid)); + double sigmoid = 1.0 / (1.0 + std::exp(-x)); + return sigmoid * (1.0 + x * (1.0 - sigmoid)); } /** @@ -83,14 +85,14 @@ class SILUFunction * @param x The resulting derivatives. */ template - static void Deriv(const InputVecType &x, OutputVecType &y) + static void Deriv(const InputVecType &x, OutputVecType &y) { - OutputVecType sigmoid = 1.0 / (1.0 + arma::exp(-x)); - y = sigmoid % (1.0 + x % (1.0 - sigmoid)); + OutputVecType sigmoid = 1.0 / (1.0 + arma::exp(-x)); + y = sigmoid % (1.0 + x % (1.0 - sigmoid)); } }; // class SILUFunction } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index cabe427a88..536e42f94c 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -8,7 +8,8 @@ * * @code * @misc{The Institution of Engineering and Technology 2015 , - * title = {TanhExp: A Smooth Activation Function with High Convergence Speed for Lightweight Neural Networks}, + * title = {TanhExp: A Smooth Activation Function with High Convergence Speed + * for Lightweight Neural Networks}, * author = {Xinyu Liu and Xiaoguang Di}, * year = {2020}, * url = {https://arxiv.org/pdf/2003.09855v2.pdf}, @@ -38,7 +39,7 @@ namespace ann /** Artificial Neural Network. */ { * f'(x) = tanh(e^x) - x*e^x*(tanh(e^x)^2 - 1)\\ * @f} */ - class TanhExpFunction +class TanhExpFunction { public: /** diff --git a/src/mlpack/methods/ann/ffn_impl.hpp b/src/mlpack/methods/ann/ffn_impl.hpp index 401c094ca6..921ded0bd7 100644 --- a/src/mlpack/methods/ann/ffn_impl.hpp +++ b/src/mlpack/methods/ann/ffn_impl.hpp @@ -111,8 +111,8 @@ double FFN::Train( OptimizerType& optimizer, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, + CheckInputShape > >(network, + predictors.n_rows, "FFN<>::Train()"); ResetData(std::move(predictors), std::move(responses)); @@ -137,8 +137,8 @@ double FFN::Train( arma::mat responses, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, + CheckInputShape > >(network, + predictors.n_rows, "FFN<>::Train()"); ResetData(std::move(predictors), std::move(responses)); @@ -227,9 +227,8 @@ template::Predict( arma::mat predictors, arma::mat& results) { - CheckInputShape > >(network, - predictors.n_rows, - "FFN<>::Predict()"); + CheckInputShape > >( + network, predictors.n_rows, "FFN<>::Predict()"); if (parameter.is_empty()) ResetParameters(); @@ -264,9 +263,8 @@ template double FFN::Evaluate( const PredictorsType& predictors, const ResponsesType& responses) { - CheckInputShape > >(network, - predictors.n_rows, - "FFN<>::Evaluate()"); + CheckInputShape > >( + network, predictors.n_rows, "FFN<>::Evaluate()"); if (parameter.is_empty()) ResetParameters(); diff --git a/src/mlpack/methods/ann/layer/atrous_convolution.hpp b/src/mlpack/methods/ann/layer/atrous_convolution.hpp index daddab76f2..d6086de86f 100644 --- a/src/mlpack/methods/ann/layer/atrous_convolution.hpp +++ b/src/mlpack/methods/ann/layer/atrous_convolution.hpp @@ -71,7 +71,8 @@ class AtrousConvolution * @param inputWidth The widht of the input data. * @param inputHeight The height of the input data. * @param dilationWidth The space between the cells of filters in x direction. - * @param dilationHeight The space between the cells of filters in y direction. + * @param dilationHeight The space between the cells of filters in y + * direction. * @param paddingType The type of padding (Valid or Same). Defaults to None. */ AtrousConvolution(const size_t inSize, @@ -108,7 +109,8 @@ class AtrousConvolution * @param inputWidth The widht of the input data. * @param inputHeight The height of the input data. * @param dilationWidth The space between the cells of filters in x direction. - * @param dilationHeight The space between the cells of filters in y direction. + * @param dilationHeight The space between the cells of filters in y + * direction. * @param paddingType The type of padding (Valid/Same/None). Defaults to None. */ AtrousConvolution(const size_t inSize, @@ -266,8 +268,8 @@ class AtrousConvolution //! Get the shape of the input. size_t InputShape() const { - return inputHeight * inputWidth * inSize; - } + return inputHeight * inputWidth * inSize; + } /** * Serialize the layer. diff --git a/src/mlpack/methods/ann/layer/base_layer.hpp b/src/mlpack/methods/ann/layer/base_layer.hpp index 9c6bd19478..e2d7aaf809 100644 --- a/src/mlpack/methods/ann/layer/base_layer.hpp +++ b/src/mlpack/methods/ann/layer/base_layer.hpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace mlpack { namespace ann /** Artificial Neural Network. */ { @@ -314,7 +314,7 @@ template < typename OutputDataType = arma::mat > using SILUFunctionLayer = BaseLayer< - ActivationFunction, InputDataType,OutputDataType + ActivationFunction, InputDataType, OutputDataType >; } // namespace ann diff --git a/src/mlpack/methods/ann/layer/concatenate_impl.hpp b/src/mlpack/methods/ann/layer/concatenate_impl.hpp index bfede6c162..cf85443cf6 100644 --- a/src/mlpack/methods/ann/layer/concatenate_impl.hpp +++ b/src/mlpack/methods/ann/layer/concatenate_impl.hpp @@ -27,7 +27,7 @@ Concatenate::Concatenate() : } template -Concatenate::Concatenate(const Concatenate& layer) : +Concatenate::Concatenate(const Concatenate& layer) : inRows(layer.inRows), weights(layer.weights), delta(layer.delta), @@ -37,7 +37,7 @@ Concatenate::Concatenate(const Concatenate& layer } template -Concatenate::Concatenate(Concatenate&& layer) : +Concatenate::Concatenate(Concatenate&& layer) : inRows(layer.inRows), weights(std::move(layer.weights)), delta(std::move(layer.delta)), @@ -51,7 +51,7 @@ Concatenate& Concatenate:: operator=(const Concatenate& layer) { - if (this != &layer) + if (this != &layer) { inRows = layer.inRows; weights = layer.weights; @@ -67,7 +67,7 @@ Concatenate& Concatenate:: operator=(Concatenate&& layer) { - if (this != &layer) + if (this != &layer) { inRows = layer.inRows; weights = std::move(layer.weights); diff --git a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp index 1ce5364da8..edc616ac3c 100644 --- a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp +++ b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp @@ -48,9 +48,9 @@ void FlattenTSwish::Backward( const DataType& input, const DataType& gy, DataType& g) { DataType derivate, sigmoid; - LogisticFunction::Fn(input,sigmoid); + LogisticFunction::Fn(input, sigmoid); derivate.set_size(arma::size(input)); - for(size_t i = 0; i < input.n_elem; ++i) + for(size_t i = 0; i < input.n_elem; ++i) { if (input(i) >= 0) { @@ -58,9 +58,11 @@ void FlattenTSwish::Backward( // We don't put '+ t' here because this is a derivate. derivate(i) = input(i) * sigmoid(i); derivate(i) = sigmoid(i) * (1.0 - derivate(i)) + derivate(i); - } - else + } + else + { derivate(i) = 0; + } } g = gy % derivate; } @@ -77,4 +79,4 @@ void FlattenTSwish::serialize( } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/layer/gru.hpp b/src/mlpack/methods/ann/layer/gru.hpp index 3d98a712d8..c895ee7f81 100644 --- a/src/mlpack/methods/ann/layer/gru.hpp +++ b/src/mlpack/methods/ann/layer/gru.hpp @@ -156,7 +156,7 @@ class GRU size_t OutSize() const { return outSize; } //! Get the shape of the input. - size_t InputShape() const + size_t InputShape() const { return inSize; } diff --git a/src/mlpack/methods/ann/layer/isrlu.hpp b/src/mlpack/methods/ann/layer/isrlu.hpp index b0a786c6ba..36722b91c3 100644 --- a/src/mlpack/methods/ann/layer/isrlu.hpp +++ b/src/mlpack/methods/ann/layer/isrlu.hpp @@ -126,7 +126,6 @@ class ISRLU //! ISRLU Hyperparameter (alpha > 0). double alpha; - }; // class ISRLU } // namespace ann diff --git a/src/mlpack/methods/ann/layer/linear.hpp b/src/mlpack/methods/ann/layer/linear.hpp index cc31117c53..5b9d23bd87 100644 --- a/src/mlpack/methods/ann/layer/linear.hpp +++ b/src/mlpack/methods/ann/layer/linear.hpp @@ -152,7 +152,7 @@ class Linear return (inSize * outSize) + outSize; } - //! Get the shape of the input. + //! Get the shape of the input. size_t InputShape() const { return inSize; diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 03ef9f540e..1c2b841e24 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -196,11 +196,12 @@ class LpPooling const arma::Mat& error, arma::Mat& output) { - arma::Mat unpooledError; - for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, + colidx++) { - for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, + rowidx++) { size_t rowEnd = i + kernelWidth - 1; size_t colEnd = j + kernelHeight - 1; @@ -219,7 +220,8 @@ class LpPooling colEnd = input.n_cols - 1; } - arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); + arma::mat InputArea = input(arma::span(i, rowEnd), + arma::span(j, colEnd)); size_t sum = pow(arma::accu(arma::pow(InputArea, normType)), (normType - 1) / normType); diff --git a/src/mlpack/methods/ann/layer/lstm.hpp b/src/mlpack/methods/ann/layer/lstm.hpp index 98be4b500f..effca7328e 100644 --- a/src/mlpack/methods/ann/layer/lstm.hpp +++ b/src/mlpack/methods/ann/layer/lstm.hpp @@ -184,7 +184,10 @@ class LSTM size_t OutSize() const { return outSize; } //! Get the size of the weights. - size_t WeightSize() const { return (4 * outSize * inSize + 7 * outSize + 4 * outSize * outSize); } + size_t WeightSize() const + { + return (4 * outSize * inSize + 7 * outSize + 4 * outSize * outSize); + } //! Get the shape of the input. size_t InputShape() const diff --git a/src/mlpack/methods/ann/layer/lstm_impl.hpp b/src/mlpack/methods/ann/layer/lstm_impl.hpp index 9d720732c4..2b298d18aa 100644 --- a/src/mlpack/methods/ann/layer/lstm_impl.hpp +++ b/src/mlpack/methods/ann/layer/lstm_impl.hpp @@ -26,7 +26,7 @@ LSTM::LSTM() template LSTM::LSTM( - const LSTM& layer) : + const LSTM& layer) : inSize(layer.inSize), outSize(layer.outSize), rho(layer.rho), @@ -45,7 +45,7 @@ LSTM::LSTM( template LSTM::LSTM( - LSTM&& layer) : + LSTM&& layer) : inSize(std::move(layer.inSize)), outSize(std::move(layer.outSize)), rho(std::move(layer.rho)), @@ -63,7 +63,7 @@ LSTM::LSTM( } template -LSTM& +LSTM& LSTM :: operator=(const LSTM& layer) { if (this != &layer) @@ -82,11 +82,11 @@ LSTM :: operator=(const LSTM& layer) rhoSize = layer.rho; bpttSteps = layer.bpttSteps; } - return *this; + return *this; } template -LSTM& +LSTM& LSTM :: operator=(LSTM&& layer) { if (this != &layer) @@ -105,7 +105,7 @@ LSTM :: operator=(LSTM&& layer) rhoSize = std::move(layer.rho); bpttSteps = std::move(layer.bpttSteps); } - return *this; + return *this; } template diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 2480a9525f..afba6470c7 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -164,7 +164,7 @@ class MeanPooling for (size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); - + for (size_t i = 1; i < input.n_rows; ++i) inputPre.row(i) += inputPre.row(i - 1); @@ -210,12 +210,13 @@ class MeanPooling const arma::Mat& error, arma::Mat& output) { - arma::Mat unpooledError; - for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++) + for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, + colidx++) { - for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++) - { + for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, + rowidx++) + { size_t rowEnd = i + kernelWidth - 1; size_t colEnd = j + kernelHeight - 1; @@ -233,7 +234,8 @@ class MeanPooling colEnd = input.n_cols - 1; } - arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd)); + arma::mat InputArea = input(arma::span(i, rowEnd), + arma::span(j, colEnd)); unpooledError = arma::Mat(InputArea.n_rows, InputArea.n_cols); unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem); diff --git a/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp index f56f708981..4de0816990 100644 --- a/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp @@ -77,12 +77,11 @@ void PixelShuffle::Forward( size_t width_index = w / upscaleFactor; size_t channel_index = (upscaleFactor * (h % upscaleFactor)) + (w % upscaleFactor) + (c * std::pow(upscaleFactor, 2)); - outputTemp(w, h, c + n * sizeOut) = inputTemp(width_index, height_index, - channel_index + n * size); + outputTemp(w, h, c + n * sizeOut) = inputTemp(width_index, + height_index, channel_index + n * size); } } } - } } @@ -109,12 +108,11 @@ void PixelShuffle::Backward( size_t width_index = w / upscaleFactor; size_t channel_index = (upscaleFactor * (h % upscaleFactor)) + (w % upscaleFactor) + (c * std::pow(upscaleFactor, 2)); - gTemp(width_index, height_index, channel_index + n * size) = gyTemp(w, h, - c + n * sizeOut); + gTemp(width_index, height_index, channel_index + n * size) = + gyTemp(w, h, c + n * sizeOut); } } } - } } diff --git a/src/mlpack/methods/ann/layer/recurrent_impl.hpp b/src/mlpack/methods/ann/layer/recurrent_impl.hpp index e6b933bd20..046c48fa0f 100644 --- a/src/mlpack/methods/ann/layer/recurrent_impl.hpp +++ b/src/mlpack/methods/ann/layer/recurrent_impl.hpp @@ -128,9 +128,12 @@ Recurrent::Recurrent( template -size_t Recurrent::InputShape() const +size_t +Recurrent::InputShape() const { - const size_t inputShapeStartModule = boost::apply_visitor(InShapeVisitor(), startModule); + const size_t inputShapeStartModule = boost::apply_visitor(InShapeVisitor(), + startModule); + // Return the input shape of the first module that we have. if (inputShapeStartModule != 0) { @@ -140,34 +143,34 @@ size_t Recurrent::InputShape() c else { // Return input shape of the second module that we have. - const size_t inputShapeInputModule = boost::apply_visitor(InShapeVisitor(), inputModule); + const size_t inputShapeInputModule = boost::apply_visitor(InShapeVisitor(), + inputModule); if (inputShapeInputModule != 0) { return inputShapeInputModule; - // If the input shape of second module is 0. } - else + else // If the input shape of second module is 0. { // Return input shape of the third module that we have. - const size_t inputShapeFeedbackModule = boost::apply_visitor(InShapeVisitor(), - feedbackModule); + const size_t inputShapeFeedbackModule = boost::apply_visitor( + InShapeVisitor(), feedbackModule); if (inputShapeFeedbackModule != 0) { return inputShapeFeedbackModule; - // If the input shape of the third module is 0. } - else + else // If the input shape of the third module is 0. { // Return the shape of the fourth module that we have. - const size_t inputShapeTransferModule = boost::apply_visitor(InShapeVisitor(), - transferModule); + const size_t inputShapeTransferModule = boost::apply_visitor( + InShapeVisitor(), transferModule); if (inputShapeTransferModule != 0) { return inputShapeTransferModule; } - // If the input shape of the fourth module is 0. - else + else // If the input shape of the fourth module is 0. + { return 0; + } } } } diff --git a/src/mlpack/methods/ann/layer/reparametrization.hpp b/src/mlpack/methods/ann/layer/reparametrization.hpp index a526d746bf..d3a183b9fd 100644 --- a/src/mlpack/methods/ann/layer/reparametrization.hpp +++ b/src/mlpack/methods/ann/layer/reparametrization.hpp @@ -71,16 +71,16 @@ class Reparametrization const bool stochastic = true, const bool includeKl = true, const double beta = 1); - + //! Copy Constructor. Reparametrization(const Reparametrization& layer); - + //! Move Constructor. Reparametrization(Reparametrization&& layer); - + //! Copy assignment operator. Reparametrization& operator=(const Reparametrization& layer); - + //! Move assignment operator. Reparametrization& operator=(Reparametrization&& layer); diff --git a/src/mlpack/methods/ann/layer/reparametrization_impl.hpp b/src/mlpack/methods/ann/layer/reparametrization_impl.hpp index cef6a32b0d..117e67a620 100644 --- a/src/mlpack/methods/ann/layer/reparametrization_impl.hpp +++ b/src/mlpack/methods/ann/layer/reparametrization_impl.hpp @@ -46,7 +46,7 @@ Reparametrization::Reparametrization( << "included." << std::endl; } } - + template Reparametrization::Reparametrization( const Reparametrization& layer) : @@ -55,7 +55,7 @@ Reparametrization::Reparametrization( includeKl(layer.includeKl), beta(layer.beta) { - // Nothing to do here. + // Nothing to do here. } template @@ -66,13 +66,13 @@ Reparametrization::Reparametrization( includeKl(std::move(layer.includeKl)), beta(std::move(layer.beta)) { - // Nothing to do here. + // Nothing to do here. } - + template Reparametrization& Reparametrization:: -operator=(const Reparametrization& layer) +operator=(const Reparametrization& layer) { if (this != &layer) { @@ -83,11 +83,11 @@ operator=(const Reparametrization& layer) } return *this; } - + template Reparametrization& Reparametrization:: -operator=(Reparametrization&& layer) +operator=(Reparametrization&& layer) { if (this != &layer) { @@ -98,8 +98,8 @@ operator=(Reparametrization&& layer) } return *this; } - - + + template template void Reparametrization::Forward( diff --git a/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp index 89e7aaf1c2..4555240b88 100644 --- a/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp @@ -34,7 +34,7 @@ BCELoss::Forward( { typedef typename PredictionType::elem_type ElemType; - ElemType loss = -arma::accu(target % arma::log(prediction + eps) + + ElemType loss = -arma::accu(target % arma::log(prediction + eps) + (1. - target) % arma::log(1. - prediction + eps)); if (reduction) loss /= prediction.n_elem; diff --git a/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp index d692734754..50b2c61858 100644 --- a/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp @@ -31,16 +31,17 @@ HuberLoss::HuberLoss( template template typename PredictionType::elem_type -HuberLoss::Forward(const PredictionType& prediction, - const TargetType& target) +HuberLoss::Forward( + const PredictionType& prediction, + const TargetType& target) { typedef typename PredictionType::elem_type ElemType; ElemType loss = 0; for (size_t i = 0; i < prediction.n_elem; ++i) { const ElemType absError = std::abs(target[i] - prediction[i]); - loss += absError > delta - ? delta * (absError - 0.5 * delta) : 0.5 * std::pow(absError, 2); + loss += absError > delta ? + delta * (absError - 0.5 * delta) : 0.5 * std::pow(absError, 2); } return mean ? loss / prediction.n_elem : loss; } @@ -58,8 +59,9 @@ void HuberLoss::Backward( for (size_t i = 0; i < loss.n_elem; ++i) { const ElemType absError = std::abs(target[i] - prediction[i]); - loss[i] = absError > delta - ? - delta * (target[i] - prediction[i]) / absError : prediction[i] - target[i]; + loss[i] = absError > delta ? + -delta * (target[i] - prediction[i]) / absError : + prediction[i] - target[i]; if (mean) loss[i] /= loss.n_elem; } diff --git a/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp b/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp index aa1a5c1b62..9c74453a21 100644 --- a/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp @@ -29,8 +29,9 @@ KLDivergence::KLDivergence(const bool takeMean) : template template typename PredictionType::elem_type -KLDivergence::Forward(const PredictionType& prediction, - const TargetType& target) +KLDivergence::Forward( + const PredictionType& prediction, + const TargetType& target) { if (takeMean) { @@ -52,7 +53,8 @@ void KLDivergence::Backward( { if (takeMean) { - loss = arma::mean(arma::mean(arma::log(prediction) - arma::log(target) + 1)); + loss = arma::mean(arma::mean( + arma::log(prediction) - arma::log(target) + 1)); } else { diff --git a/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp b/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp index 2d0bed9721..a1f4384e7f 100644 --- a/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp +++ b/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp @@ -65,8 +65,10 @@ class SigmoidCrossEntropyError * @param target The target vector. */ template - inline typename PredictionType::elem_type Forward(const PredictionType& prediction, - const TargetType& target); + inline typename PredictionType::elem_type Forward( + const PredictionType& prediction, + const TargetType& target); + /** * Ordinary feed backward pass of a neural network. * diff --git a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp index fba54973f0..980d863d17 100644 --- a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp +++ b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp @@ -108,4 +108,4 @@ class TripletMarginLoss // include implementation. #include "triplet_margin_loss_impl.hpp" -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp index a007490be0..2a43bc4ac4 100644 --- a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp @@ -33,8 +33,10 @@ TripletMarginLoss::Forward( const PredictionType& prediction, const TargetType& target) { - PredictionType anchor = prediction.submat(0, 0, prediction.n_rows / 2 - 1, prediction.n_cols - 1); - PredictionType positive = prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1, + PredictionType anchor = + prediction.submat(0, 0, prediction.n_rows / 2 - 1, prediction.n_cols - 1); + PredictionType positive = + prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1, prediction.n_cols - 1); return std::max(0.0, arma::accu(arma::pow(anchor - positive, 2)) - arma::accu(arma::pow(anchor - target, 2)) + margin) / anchor.n_cols; @@ -51,7 +53,8 @@ void TripletMarginLoss::Backward( const TargetType& target, LossType& loss) { - PredictionType positive = prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1, + PredictionType positive = + prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1, prediction.n_cols - 1); loss = 2 * (target - positive) / target.n_cols; } diff --git a/src/mlpack/methods/ann/rnn_impl.hpp b/src/mlpack/methods/ann/rnn_impl.hpp index 5077eb9896..3e7d6d0323 100644 --- a/src/mlpack/methods/ann/rnn_impl.hpp +++ b/src/mlpack/methods/ann/rnn_impl.hpp @@ -149,9 +149,8 @@ double RNN::Train( OptimizerType& optimizer, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, - "RNN<>::Train()"); + CheckInputShape > >( + network, predictors.n_rows, "RNN<>::Train()"); numFunctions = responses.n_cols; @@ -197,9 +196,8 @@ double RNN::Train( arma::cube responses, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, - "RNN<>::Train()"); + CheckInputShape > >( + network, predictors.n_rows, "RNN<>::Train()"); numFunctions = responses.n_cols; @@ -233,9 +231,8 @@ template::Predict( arma::cube predictors, arma::cube& results, const size_t batchSize) { - CheckInputShape > >(network, - predictors.n_rows, - "RNN<>::Predict()"); + CheckInputShape > >( + network, predictors.n_rows, "RNN<>::Predict()"); ResetCells(); From 963139172bc09bf24d02ee6d860e37e07d5226a0 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 21:21:28 -0400 Subject: [PATCH 367/729] Some more style fixes. --- .../methods/ann/layer/concatenate_impl.hpp | 21 ++++---- .../ann/layer/flatten_t_swish_impl.hpp | 2 +- .../methods/ann/util/check_input_shape.hpp | 3 +- src/mlpack/methods/kde/kde_impl.hpp | 2 - .../methods/neighbor_search/ns_model.hpp | 2 +- .../methods/neighbor_search/ns_model_impl.hpp | 1 - src/mlpack/methods/pca/pca_impl.hpp | 2 +- .../range_search/range_search_impl.hpp | 4 +- src/mlpack/methods/rann/ra_model.hpp | 2 +- .../q_learning_impl.hpp | 2 +- .../tests/activation_functions_test.cpp | 52 +++++++++++-------- src/mlpack/tests/ann_layer_test.cpp | 2 +- src/mlpack/tests/ann_visitor_test.cpp | 4 +- src/mlpack/tests/cli_binding_test.cpp | 6 ++- src/mlpack/tests/decision_tree_test.cpp | 6 +-- src/mlpack/tests/feedforward_network_test.cpp | 12 +++-- src/mlpack/tests/hmm_test.cpp | 8 +-- src/mlpack/tests/krann_search_test.cpp | 10 ++-- src/mlpack/tests/recurrent_network_test.cpp | 6 +-- src/mlpack/tests/size_checks_test.cpp | 3 +- 20 files changed, 80 insertions(+), 70 deletions(-) diff --git a/src/mlpack/methods/ann/layer/concatenate_impl.hpp b/src/mlpack/methods/ann/layer/concatenate_impl.hpp index cf85443cf6..54b53471c8 100644 --- a/src/mlpack/methods/ann/layer/concatenate_impl.hpp +++ b/src/mlpack/methods/ann/layer/concatenate_impl.hpp @@ -21,27 +21,28 @@ namespace ann /** Artificial Neural Network. */ { template Concatenate::Concatenate() : - inRows(0) + inRows(0) { // Nothing to do here. } template -Concatenate::Concatenate(const Concatenate& layer) : - inRows(layer.inRows), - weights(layer.weights), - delta(layer.delta), - concat(layer.concat) +Concatenate::Concatenate( + const Concatenate& layer) : + inRows(layer.inRows), + weights(layer.weights), + delta(layer.delta), + concat(layer.concat) { // Nothing to to here. } template Concatenate::Concatenate(Concatenate&& layer) : - inRows(layer.inRows), - weights(std::move(layer.weights)), - delta(std::move(layer.delta)), - concat(std::move(layer.concat)) + inRows(layer.inRows), + weights(std::move(layer.weights)), + delta(std::move(layer.delta)), + concat(std::move(layer.concat)) { // Nothing to do here. } diff --git a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp index edc616ac3c..41410a544f 100644 --- a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp +++ b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp @@ -50,7 +50,7 @@ void FlattenTSwish::Backward( DataType derivate, sigmoid; LogisticFunction::Fn(input, sigmoid); derivate.set_size(arma::size(input)); - for(size_t i = 0; i < input.n_elem; ++i) + for (size_t i = 0; i < input.n_elem; ++i) { if (input(i) >= 0) { diff --git a/src/mlpack/methods/ann/util/check_input_shape.hpp b/src/mlpack/methods/ann/util/check_input_shape.hpp index 566c363e3f..59f2c72da2 100644 --- a/src/mlpack/methods/ann/util/check_input_shape.hpp +++ b/src/mlpack/methods/ann/util/check_input_shape.hpp @@ -22,7 +22,8 @@ namespace mlpack { namespace ann /** Artificial Neural Network. */{ template -void CheckInputShape(const T& network, const size_t inputShape, +void CheckInputShape(const T& network, + const size_t inputShape, const std::string& functionName) { for (size_t l = 0; l < network.size(); ++l) diff --git a/src/mlpack/methods/kde/kde_impl.hpp b/src/mlpack/methods/kde/kde_impl.hpp index 054c02119d..9fdadd2e3e 100644 --- a/src/mlpack/methods/kde/kde_impl.hpp +++ b/src/mlpack/methods/kde/kde_impl.hpp @@ -264,9 +264,7 @@ operator=(KDE&& other) // Move the other object. this->kernel = std::move(other.kernel); this->metric = std::move(other.metric); - // TODO: This should be: this->referenceTree = other.referenceTree; this->referenceTree = std::move(other.referenceTree); - // TODO: This should be: this->oldFromNewReferences = other.oldFromNewReferences; this->oldFromNewReferences = std::move(other.oldFromNewReferences); this->relError = other.relError; this->absError = other.absError; diff --git a/src/mlpack/methods/neighbor_search/ns_model.hpp b/src/mlpack/methods/neighbor_search/ns_model.hpp index b13918fa7d..e09fd6489c 100644 --- a/src/mlpack/methods/neighbor_search/ns_model.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model.hpp @@ -44,7 +44,7 @@ class NSWrapperBase virtual NSWrapperBase* Clone() const = 0; //! Destruct the NSWrapperBase (nothing to do). - virtual ~NSWrapperBase() { }; + virtual ~NSWrapperBase() {}; //! Return a reference to the dataset. virtual const arma::mat& Dataset() const = 0; diff --git a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp index 319fb652af..050398089a 100644 --- a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp @@ -516,7 +516,6 @@ void NSModel::InitializeModel(const NeighborSearchMode searchMode, epsilon); break; } - } //! Build the reference tree. diff --git a/src/mlpack/methods/pca/pca_impl.hpp b/src/mlpack/methods/pca/pca_impl.hpp index f469933c14..e1b6fe1958 100644 --- a/src/mlpack/methods/pca/pca_impl.hpp +++ b/src/mlpack/methods/pca/pca_impl.hpp @@ -74,7 +74,7 @@ void PCA::Apply(const arma::mat& data, arma::mat eigvec; Apply(data, transformedData, eigVal, eigvec); } - + /** * Apply Principal Component Analysis to the provided data set. * diff --git a/src/mlpack/methods/range_search/range_search_impl.hpp b/src/mlpack/methods/range_search/range_search_impl.hpp index cce20339a3..37b86baf61 100644 --- a/src/mlpack/methods/range_search/range_search_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_impl.hpp @@ -174,7 +174,8 @@ RangeSearch::operator=(const RangeSearch& other) if (this != &other) { oldFromNewReferences = other.oldFromNewReferences; - referenceTree = other.referenceTree ? new Tree(*other.referenceTree) : nullptr; + referenceTree = other.referenceTree ? new Tree(*other.referenceTree) : + nullptr; referenceSet = other.referenceTree ? &referenceTree->Dataset() : new MatType(*other.referenceSet); treeOwner = other.referenceTree; @@ -222,7 +223,6 @@ RangeSearch::operator=(RangeSearch&& other) other.singleMode = false; other.baseCases = 0; other.scores = 0; - } return *this; } diff --git a/src/mlpack/methods/rann/ra_model.hpp b/src/mlpack/methods/rann/ra_model.hpp index 572d599a0d..32ff60af07 100644 --- a/src/mlpack/methods/rann/ra_model.hpp +++ b/src/mlpack/methods/rann/ra_model.hpp @@ -41,7 +41,7 @@ class RAWrapperBase virtual RAWrapperBase* Clone() const = 0; //! Destruct the RAWrapperBase (nothing to do). - virtual ~RAWrapperBase() { }; + virtual ~RAWrapperBase() {}; //! Return a reference to the dataset. virtual const arma::mat& Dataset() const = 0; diff --git a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp index 9fe689aa26..de28d05e74 100644 --- a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp @@ -54,7 +54,7 @@ QLearning< // Set up q-learning network. if (learningNetwork.Parameters().is_empty()) learningNetwork.ResetParameters(); - + targetNetwork.ResetParameters(); #if ENS_VERSION_MAJOR == 1 diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index fcca17d2c0..cd4f7d4711 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -664,16 +664,18 @@ void CheckSoftminDerivativeCorrect(const arma::colvec input, * Implementation of the Flatten T Swish activation function test. The function is * implemented as Flatten T Swish layer in the file flatten_t_swish.hpp. * - * @param input Input data used for evaluating the Flatten T Swish activation function. + * @param input Input data used for evaluating the Flatten T Swish activation + * function. * @param target Target data used to evaluate the Flatten T Swish activation. */ -void CheckFlattenTSwishActivationCorrect(const arma::colvec input, const arma::colvec target) +void CheckFlattenTSwishActivationCorrect(const arma::colvec input, + const arma::colvec target) { FlattenTSwish<> fts(0.4); arma::colvec activations; fts.Forward(input,activations); - for(size_t i = 0; i < activations.n_elem; ++i) + for (size_t i = 0; i < activations.n_elem; ++i) { REQUIRE(activations.at(i) == Approx(target.at(i)).epsilon(1e-5)); } @@ -686,8 +688,8 @@ void CheckFlattenTSwishActivationCorrect(const arma::colvec input, const arma::c * @param input Input data used for evaluating the Softmin activation function. * @param target Target data used to evaluate the Softmin activation. */ - -void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::colvec target) +void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, + const arma::colvec target) { FlattenTSwish<> fts; @@ -696,7 +698,7 @@ void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::col arma::colvec derivate; fts.Backward(input,error,derivate); - for(size_t i = 0; i < derivate.n_elem; ++i) + for (size_t i = 0; i < derivate.n_elem; ++i) { REQUIRE(derivate.at(i) == Approx(target.at(i)).epsilon(1e-5)); } @@ -1270,7 +1272,6 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]") */ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") { - const arma::colvec activationData("-2 3.2 4.5 1 -1 2 0"); // Hand-calculated values. @@ -1282,29 +1283,32 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") 1.03924 0.449818 1.00002 0.761594"); CheckActivationCorrect(activationData, desiredActivations); - CheckDerivativeCorrect(desiredActivations, desiredDerivatives); + CheckDerivativeCorrect(desiredActivations, + desiredDerivatives); } /** * Basic test of the SILU(Sigmoid Weighted Linear Unit) Function */ -TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") +TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") { // Random generated values. const arma::colvec activationData("-2 2 4.5 -5.7 -1 1 0 10"); // Calculated with PyTorch. - arma::colvec desiredActivation("-0.23840583860874176 1.7615940570831299 4.450558662414551 \ - -0.01900840364396572 -0.2689414322376251 0.7310585975646973 \ - 0.0 9.99954605102539"); + arma::colvec desiredActivation( + "-0.23840583860874176 1.7615940570831299 4.450558662414551 \ + -0.01900840364396572 -0.2689414322376251 0.7310585975646973 \ + 0.0 9.99954605102539"); // Calculated with PyTorch. - arma::colvec desiredDerivate("0.38191673159599304 1.073788046836853 1.0392179489135742 \ - 0.49049633741378784 0.36713290214538574 0.8354039788246155 \ - 0.5 1.0004087686538696"); - - CheckActivationCorrect(activationData,desiredActivation); - CheckDerivativeCorrect(desiredActivation,desiredDerivate); + arma::colvec desiredDerivate( + "0.38191673159599304 1.073788046836853 1.0392179489135742 \ + 0.49049633741378784 0.36713290214538574 0.8354039788246155 \ + 0.5 1.0004087686538696"); + + CheckActivationCorrect(activationData, desiredActivation); + CheckDerivativeCorrect(desiredActivation, desiredDerivate); } /** @@ -1316,13 +1320,15 @@ TEST_CASE("FlattenTSwishFunctionTest","[ActivationFunctionsTest]") arma::colvec input("-4.0 -1.0 2 3 4 5 6"); // Hand Calculated and using PyTorch. - arma::colvec desiredActivation("0.4000000059604645 0.4000000059604645 2.1615941524505615 \ - 3.2577223777770996 4.328054904937744 5.3665361404418945 6.385164737701416"); + arma::colvec desiredActivation( + "0.4000000059604645 0.4000000059604645 2.1615941524505615 \ + 3.2577223777770996 4.328054904937744 5.3665361404418945 \ + 6.385164737701416"); // Hand Calculated and using PyTorch. arma::colvec desiredDerivation("0.694792 0.694792 1.096893 1.079178 1.042602 \ 1.020182 1.009048"); - CheckFlattenTSwishActivationCorrect(input,desiredActivation); - CheckFlattenTSwishDerivateCorrect(desiredActivation,desiredDerivation); -} \ No newline at end of file + CheckFlattenTSwishActivationCorrect(input, desiredActivation); + CheckFlattenTSwishDerivateCorrect(desiredActivation, desiredDerivation); +} diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 13576eb11a..1d94b16560 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -3927,7 +3927,7 @@ TEST_CASE("MeanPoolingTestCase", "[ANNLayerTest]") CheckMatrices(output1, result1, 1e-1); CheckMatrices(output2, result2, 1e-1); - arma::mat delta1, delta2; + arma::mat delta1, delta2; module1.Backward(input, output1, delta1); REQUIRE(arma::accu(delta1) == 25.5); module2.Backward(input, output2, delta2); diff --git a/src/mlpack/tests/ann_visitor_test.cpp b/src/mlpack/tests/ann_visitor_test.cpp index b9316e8f0f..29f376611e 100644 --- a/src/mlpack/tests/ann_visitor_test.cpp +++ b/src/mlpack/tests/ann_visitor_test.cpp @@ -228,8 +228,8 @@ TEST_CASE("WeightSizeVisitorTestForMultiheadAttentionLayer", "[ANNVisitorTest]") size_t randomembedDim = 768; size_t randomnumHeads = 12; - LayerTypes<> MultiheadAttentionLayer = new MultiheadAttention<>(randomtgtSeqLen, - randomsrcSeqLen, randomembedDim, randomnumHeads); + LayerTypes<> MultiheadAttentionLayer = new MultiheadAttention<>( + randomtgtSeqLen, randomsrcSeqLen, randomembedDim, randomnumHeads); CheckCorrectnessOfWeightSize(MultiheadAttentionLayer); } diff --git a/src/mlpack/tests/cli_binding_test.cpp b/src/mlpack/tests/cli_binding_test.cpp index 76cf6a652d..342323b504 100644 --- a/src/mlpack/tests/cli_binding_test.cpp +++ b/src/mlpack/tests/cli_binding_test.cpp @@ -539,7 +539,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") typedef tuple TupleType; TupleType testTuple{filename, 0, 0}; tuple t1 = make_tuple(di, m); - tuple, TupleType> t2 = make_tuple(t1, testTuple); + tuple, TupleType> t2 = make_tuple(t1, + testTuple); d.value = boost::any(t2); d.noTranspose = false; @@ -552,7 +553,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") // Check that the name is right. tuple, TupleType>& t3 = - *boost::any_cast, TupleType>>(&d.value); + *boost::any_cast, TupleType>>( + &d.value); REQUIRE(get<0>(get<1>(t3)) == "new_filename.csv"); } diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 8fcf6b1e95..d0bc624ca3 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -440,8 +440,8 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") * Check that RandomBinaryNumericSplit generally gives a split different than * the BestBinaryNumericSplit. */ - TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") - { +TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") +{ arma::vec values(1000); arma::Row labels(1000); arma::rowvec weights; @@ -476,7 +476,7 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") } REQUIRE(classProbabilities[0] != classProbabilities1[0]); - } +} /** * Check that the AllCategoricalSplit will split when the split is obviously diff --git a/src/mlpack/tests/feedforward_network_test.cpp b/src/mlpack/tests/feedforward_network_test.cpp index a41d745676..d802092158 100644 --- a/src/mlpack/tests/feedforward_network_test.cpp +++ b/src/mlpack/tests/feedforward_network_test.cpp @@ -158,7 +158,8 @@ TEST_CASE("CheckCopyMovingVanillaNetworkTest", "[FeedForwardNetworkTest]") /** * Check whether copying and moving network with Reparametrization is working or not. */ -TEST_CASE("CheckCopyMovingReparametrizationNetworkTest", "[FeedForwardNetworkTest]") +TEST_CASE("CheckCopyMovingReparametrizationNetworkTest", + "[FeedForwardNetworkTest]") { // Load the dataset. arma::mat trainData; @@ -285,7 +286,7 @@ TEST_CASE("CheckCopyMovingNoisyLinearTest", "[FeedForwardNetworkTest]") TEST_CASE("CheckCopyMovingConcatenateTest", "[FeedForwardNetworkTest]") { // Create training input by 5x5 matrix. - arma::mat input = arma::randu(10,1); + arma::mat input = arma::randu(10, 1); // Create training output by 1 matrix. arma::mat output = arma::mat("1"); @@ -1000,9 +1001,10 @@ TEST_CASE("FFNCheckInputShapeTest", "[FeedForwardNetworkTest]") model.Add >(); std::string expectedMsg = "FFN<>::Train(): "; - expectedMsg += "the first layer of the network expects "; - expectedMsg += std::to_string(trainData.n_rows - 3) + " elements, "; - expectedMsg += "but the input has " + std::to_string(trainData.n_rows) + " dimensions! "; + expectedMsg += "the first layer of the network expects "; + expectedMsg += std::to_string(trainData.n_rows - 3) + " elements, "; + expectedMsg += "but the input has " + std::to_string(trainData.n_rows) + + " dimensions! "; ens::DE opt(200, 1000, 0.6, 0.8, 1e-5); diff --git a/src/mlpack/tests/hmm_test.cpp b/src/mlpack/tests/hmm_test.cpp index 394d1a688e..de78b48d8e 100644 --- a/src/mlpack/tests/hmm_test.cpp +++ b/src/mlpack/tests/hmm_test.cpp @@ -833,10 +833,10 @@ TEST_CASE("GaussianHMMPredictTest", "[HMMTest]") 0.0521, 0.0313, 0.0188, 0.0113, 0.0068, 0.0042, 0.0026, 0.0018, 0.0014 } }; - - //100 pre-calculated emission probabilities each for 10 states + + // 100 pre-calculated emission probabilities each for 10 states. std::vector emissionProb = { - { -2.7301e+03, 1.7874e+00, -1.9428e+00, -3.6365e+00, -4.0397e-01, + { -2.7301e+03, 1.7874e+00, -1.9428e+00, -3.6365e+00, -4.0397e-01, -1.5115e-01, -1.0328e+00, -1.1071e+00, 5.2876e-01, -1.0643e-01 }, { -2.3684e+03, 1.8059e+00, -2.2058e+00, -4.0514e+00, -5.0935e-01, -2.1126e-01, -1.1962e+00, -1.2567e+00, 4.1247e-01, -3.0199e-01 }, @@ -1037,7 +1037,7 @@ TEST_CASE("GaussianHMMPredictTest", "[HMMTest]") { -1.5426e+05, -5.8691e-01, -2.8121e-01, -1.2660e+00, -4.9111e-01, -1.8141e-01, -5.7387e-02, -8.0842e-01, -2.9317e-01, 6.1601e-01 }, }; - + const double loglikelihoodRef = -2734.43; // Test log-likelihood calculation for the whole data. diff --git a/src/mlpack/tests/krann_search_test.cpp b/src/mlpack/tests/krann_search_test.cpp index a548b30438..5e6bff9446 100644 --- a/src/mlpack/tests/krann_search_test.cpp +++ b/src/mlpack/tests/krann_search_test.cpp @@ -43,7 +43,7 @@ TEST_CASE("NaiveGuaranteeTest", "[KRANNTest]") RASearch<> rsRann(refData, true, false, 1.0); arma::mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; @@ -105,7 +105,7 @@ TEST_CASE("SingleTreeSearch", "[KRANNTest]") // The relative ranks for the given query reference pair arma::Mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; @@ -166,7 +166,7 @@ TEST_CASE("DualTreeSearch", "[KRANNTest]") RASearch<> tsdRann(refData, false, false, 1.0, 0.95, false, false, 5); arma::Mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 1000; @@ -300,7 +300,7 @@ TEST_CASE("SingleCoverTreeTest", "[KRANNTest]") // The relative ranks for the given query reference pair. arma::Mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) FAIL("Cannot load dataset rann_test_qr_ranks.csv"); size_t numRounds = 100; @@ -666,7 +666,7 @@ TEST_CASE("RAModelTest", "[KRANNTest]") models[19] = RAModel(RAModel::TreeTypes::OCTREE, true); arma::Mat qrRanks; - if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose. + if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) FAIL("Cannot load dataset rann_test_qr_ranks.csv"); for (size_t j = 0; j < 3; ++j) diff --git a/src/mlpack/tests/recurrent_network_test.cpp b/src/mlpack/tests/recurrent_network_test.cpp index 7781b6c50c..4b5aca4afb 100644 --- a/src/mlpack/tests/recurrent_network_test.cpp +++ b/src/mlpack/tests/recurrent_network_test.cpp @@ -923,9 +923,9 @@ TEST_CASE("RNNCheckInputShapeTest", "[RecurrentNetworkTest]") model.Add >(); std::string expectedMsg = "RNN<>::Train(): "; - expectedMsg += "the first layer of the network expects "; - expectedMsg += std::to_string(3) + " elements, "; - expectedMsg += "but the input has " + std::to_string(1) + " dimensions! "; + expectedMsg += "the first layer of the network expects "; + expectedMsg += std::to_string(3) + " elements, "; + expectedMsg += "but the input has " + std::to_string(1) + " dimensions! "; StandardSGD opt(0.1, 1, input.n_cols /* 1 epoch */, -100); diff --git a/src/mlpack/tests/size_checks_test.cpp b/src/mlpack/tests/size_checks_test.cpp index d5c7f22e46..0e22a4aab7 100644 --- a/src/mlpack/tests/size_checks_test.cpp +++ b/src/mlpack/tests/size_checks_test.cpp @@ -32,7 +32,8 @@ TEST_CASE("CheckSizeTest", "[SizeCheckTest]") REQUIRE_NOTHROW(CheckSameSizes(data, secondLabels, "TestChecking")); REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) 30, "TestChecking")); - REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) thirdLabels.n_cols, "TestChecking")); + REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) thirdLabels.n_cols, + "TestChecking")); } /** From a392d2f9b84537f3bacbdd012f95631ec30e4dba Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 22:01:37 -0400 Subject: [PATCH 368/729] Some more style fixes. --- src/mlpack/methods/neighbor_search/ns_model.hpp | 2 +- src/mlpack/methods/rann/ra_model.hpp | 2 +- src/mlpack/tests/activation_functions_test.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/ns_model.hpp b/src/mlpack/methods/neighbor_search/ns_model.hpp index e09fd6489c..6d9fba3670 100644 --- a/src/mlpack/methods/neighbor_search/ns_model.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model.hpp @@ -44,7 +44,7 @@ class NSWrapperBase virtual NSWrapperBase* Clone() const = 0; //! Destruct the NSWrapperBase (nothing to do). - virtual ~NSWrapperBase() {}; + virtual ~NSWrapperBase() { } //! Return a reference to the dataset. virtual const arma::mat& Dataset() const = 0; diff --git a/src/mlpack/methods/rann/ra_model.hpp b/src/mlpack/methods/rann/ra_model.hpp index 32ff60af07..2223f05ebe 100644 --- a/src/mlpack/methods/rann/ra_model.hpp +++ b/src/mlpack/methods/rann/ra_model.hpp @@ -41,7 +41,7 @@ class RAWrapperBase virtual RAWrapperBase* Clone() const = 0; //! Destruct the RAWrapperBase (nothing to do). - virtual ~RAWrapperBase() {}; + virtual ~RAWrapperBase() { } //! Return a reference to the dataset. virtual const arma::mat& Dataset() const = 0; diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index cd4f7d4711..b60855d9b4 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -674,7 +674,7 @@ void CheckFlattenTSwishActivationCorrect(const arma::colvec input, FlattenTSwish<> fts(0.4); arma::colvec activations; - fts.Forward(input,activations); + fts.Forward(input, activations); for (size_t i = 0; i < activations.n_elem; ++i) { REQUIRE(activations.at(i) == Approx(target.at(i)).epsilon(1e-5)); @@ -697,7 +697,7 @@ void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, arma::colvec error = arma::ones(input.n_elem); arma::colvec derivate; - fts.Backward(input,error,derivate); + fts.Backward(input, error, derivate); for (size_t i = 0; i < derivate.n_elem; ++i) { REQUIRE(derivate.at(i) == Approx(target.at(i)).epsilon(1e-5)); @@ -1290,7 +1290,7 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") /** * Basic test of the SILU(Sigmoid Weighted Linear Unit) Function */ -TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") +TEST_CASE("SILUFunctionTest", "[ActivationFunctionsTest]") { // Random generated values. const arma::colvec activationData("-2 2 4.5 -5.7 -1 1 0 10"); @@ -1314,7 +1314,7 @@ TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") /** * Basic test of Flatten T Swish function. */ -TEST_CASE("FlattenTSwishFunctionTest","[ActivationFunctionsTest]") +TEST_CASE("FlattenTSwishFunctionTest", "[ActivationFunctionsTest]") { // Random Value. arma::colvec input("-4.0 -1.0 2 3 4 5 6"); From ec58b6dd7b912fe9b81e744e021258d6f8885f00 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 4 Jun 2021 19:45:53 -0400 Subject: [PATCH 369/729] Fix missing semicolon. --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index c062e9c7e1..8ab5986721 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -161,7 +161,7 @@ std::string PrintTypeDoc( "contains all the parameters of the model. These parameters can " "be inspected and changed. To set new parameters for a model, " "pass the modified dictionary (without deleting any keys) to the " - "`set_cpp_params()` method." + "`set_cpp_params()` method."; } } // namespace python From d063002f1f3c56998803052b4b51f7a345d9944c Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 6 Jun 2021 15:41:52 +0530 Subject: [PATCH 370/729] Got a better condition expression and gave its explanation --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index a5e97c9585..3d7b0716b4 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -210,10 +210,18 @@ class MeanPooling const arma::Mat& error, arma::Mat& output) { - const size_t condition = kernelHeight * kernelWidth - strideHeight * strideWidth - - kernelWidth - kernelHeight; + // This condition comes by comparing the number of operations involved in the brute + // force method and the prefix method. Let the area of error be errorArea and area + // of kernal be kernalArea. Total number of operations in brute force method will be + // `errorArea * kernalArea` and for each element in error we are doing kernalArea + // number of operations. Whereas in the prefix method the total number of operations + // will be `4 * errorArea + 2 * inputArea`. The term `2 * inputArea` comes from + // prefix sums performed (col-wise and row-wise). + // We can use this to determine which method to use. + const bool condition = (error.n_elem * kernalHeight * kernalWidth) > + (4 * error.n_elem + 2 * input.n_elem); - if (condition > 0) + if (condition) { // If this condition is true then theoritically the prefix sum method of // unpooling is faster. The aim of unpooling is to add From 01cb4b92b755fa881f3f4acfaf090c0870b7b14b Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 6 Jun 2021 20:28:33 +0530 Subject: [PATCH 371/729] typo fix. --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 3d7b0716b4..ef0150653f 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -218,7 +218,7 @@ class MeanPooling // will be `4 * errorArea + 2 * inputArea`. The term `2 * inputArea` comes from // prefix sums performed (col-wise and row-wise). // We can use this to determine which method to use. - const bool condition = (error.n_elem * kernalHeight * kernalWidth) > + const bool condition = (error.n_elem * kernelHeight * kernelWidth) > (4 * error.n_elem + 2 * input.n_elem); if (condition) From c0d5fef5472ff72a9ac8a174f27a712d9e328d97 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Mon, 7 Jun 2021 09:25:58 +0530 Subject: [PATCH 372/729] Apply suggestions from code review Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index ef0150653f..7789247018 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -213,7 +213,7 @@ class MeanPooling // This condition comes by comparing the number of operations involved in the brute // force method and the prefix method. Let the area of error be errorArea and area // of kernal be kernalArea. Total number of operations in brute force method will be - // `errorArea * kernalArea` and for each element in error we are doing kernalArea + // `errorArea * kernalArea` and for each element in error we are doing `kernalArea` // number of operations. Whereas in the prefix method the total number of operations // will be `4 * errorArea + 2 * inputArea`. The term `2 * inputArea` comes from // prefix sums performed (col-wise and row-wise). @@ -226,7 +226,7 @@ class MeanPooling // If this condition is true then theoritically the prefix sum method of // unpooling is faster. The aim of unpooling is to add // `error(i, j) / kernalArea` to `inputArea(kernal)`. This requires - // inputArea.n_elem additions. So, total operations required will be + // `inputArea.n_elem` additions. So, total operations required will be // `error.n_elem * inputArea.n_elem` operations. // To improve this method we will use an idea of prefix sums. Let's see // this method in 1-D matrix then we will extend it to 2-D matrix. From 82fc7550cd92a1de88fdfa5e7409b6934bee8ae1 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 7 Jun 2021 13:07:50 -0400 Subject: [PATCH 373/729] Make sure that the length of the model is serialized too. --- .../bindings/julia/print_param_defn.hpp | 10 ++++++--- src/mlpack/bindings/julia/tests/runtests.jl | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/julia/print_param_defn.hpp b/src/mlpack/bindings/julia/print_param_defn.hpp index 1ee6d7d164..6e5d152770 100644 --- a/src/mlpack/bindings/julia/print_param_defn.hpp +++ b/src/mlpack/bindings/julia/print_param_defn.hpp @@ -79,12 +79,14 @@ void PrintParamDefn( // buffer = ccall((:SerializePtr, Library), // Vector{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), model.ptr, // Base.pointer(buf_len)) - // buf = Base.unsafe_wrap(buf_ptr, buf_len[0]; own=true) + // buf = Base.unsafe_wrap(buf_ptr, buf_len[1]; own=true) + // write(stream, buf_len[1]) // write(stream, buf) // end // // function deserialize(stream::IO):: - // buffer = read(stream) + // buf_len = read(stream, UInt) + // buffer = read(stream, buf_len) // (ccall((:DeserializePtr, Library), // Ptr{Nothing}, (Vector{UInt8}, UInt), buffer, length(buffer))) // end @@ -138,6 +140,7 @@ void PrintParamDefn( << "Base.pointer(buf_len))" << std::endl; std::cout << " buf = Base.unsafe_wrap(Vector{UInt8}, buf_ptr, buf_len[1]; " << "own=true)" << std::endl; + std::cout << " write(stream, buf_len[1])" << std::endl; std::cout << " write(stream, buf)" << std::endl; std::cout << "end" << std::endl; @@ -145,7 +148,8 @@ void PrintParamDefn( std::cout << "# Deserialize a model from the given stream." << std::endl; std::cout << "function deserialize" << type << "(stream::IO)::" << type << std::endl; - std::cout << " buffer = read(stream)" << std::endl; + std::cout << " buf_len = read(stream, UInt)" << std::endl; + std::cout << " buffer = read(stream, buf_len)" << std::endl; std::cout << " " << type << "(ccall((:Deserialize" << type << "Ptr, " << programName << "Library), Ptr{Nothing}, (Ptr{UInt8}, UInt), " << "Base.pointer(buffer), length(buffer)))" << std::endl; diff --git a/src/mlpack/bindings/julia/tests/runtests.jl b/src/mlpack/bindings/julia/tests/runtests.jl index bb98c54435..57a6f548e0 100644 --- a/src/mlpack/bindings/julia/tests/runtests.jl +++ b/src/mlpack/bindings/julia/tests/runtests.jl @@ -342,6 +342,27 @@ end model_in=newModel) end +# Test that we can serialize a model as part of a larger tuple. +@testset "TestStreamTupleSerialization" begin + _, _, _, _, _, _, modelOut, _, _, _, _, _, _, _ = + test_julia_binding(4.0, 12, "hello", + build_model=true) + + stream = IOBuffer() + serialize(stream, (modelOut, 3, 4, 5)) + + newStream = IOBuffer(copy(stream.data)) + (newModel, a, b, c) = deserialize(newStream) + + _, _, _, _, _, bwOut, _, _, _, _, _, _, _, _ = + test_julia_binding(4.0, 12, "hello", + model_in=newModel) + + @test a == 3 + @test b == 4 + @test c == 5 +end + @testset "TestFileSerialization" begin _, _, _, _, _, _, modelOut, _, _, _, _, _, _, _ = test_julia_binding(4.0, 12, "hello", From d0e8351126ae1ba9d0a40991ba206f7dea5870c9 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 7 Jun 2021 13:13:04 -0400 Subject: [PATCH 374/729] Update history. --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index b08af6106e..d048cbdae1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -59,6 +59,8 @@ * Fixes to `HoeffdingTree`: ensure that training still works when empty constructor is used (#2964). + * Fix Julia model serialization bug (#2970). + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From 3a35be6d83b8c8ebb29d3928c3f0d0c32262aa40 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 7 Jun 2021 18:56:07 -0400 Subject: [PATCH 375/729] Maybe disable the cache? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a9a2574072..96f285ccb9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,7 +41,7 @@ jobs: Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps(dependencies = TRUE), 'depends.Rds')" - name: Cache R packages - if: runner.os != 'Windows' + if: runner.os != 'Windows' && runner.os != 'macOS' uses: actions/cache@v1 with: path: ${{ env.R_LIBS_USER }} From b2581bdd653575ba4b6c7d7d62972ed24c0e54ce Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 7 Jun 2021 22:09:50 -0400 Subject: [PATCH 376/729] Just disable the cache entirely because I failed to do it right last try... --- .github/workflows/main.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 96f285ccb9..4d3ab17447 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,13 +40,13 @@ jobs: 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' && runner.os != 'macOS' - 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: Cache R packages +# if: runner.os != 'Windows' && runner.os != 'macOS' +# 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: | From a51db0bce302bd532cd92bfab14239cbf8f7134e Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 8 Jun 2021 10:18:18 -0400 Subject: [PATCH 377/729] I wonder if this will do anything? --- .github/workflows/main.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4d3ab17447..c2bac7f193 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,13 +40,13 @@ jobs: 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' && runner.os != 'macOS' -# 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: 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: | @@ -59,6 +59,7 @@ jobs: run: | remotes::install_deps(dependencies = TRUE) remotes::install_cran("roxygen2") + remotes::install_cran("processx") shell: Rscript {0} - name: CMake From e9467cee01aca484ca75a1c166f0436164f11d60 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 8 Jun 2021 19:56:21 -0400 Subject: [PATCH 378/729] Some more attempts to get more output. --- .github/workflows/main.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c2bac7f193..aa76d54489 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,7 +38,7 @@ jobs: - 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')" + Rscript --verbose -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps(dependencies = TRUE), 'depends.Rds')" - name: Cache R packages if: runner.os != 'Windows' @@ -132,10 +132,11 @@ jobs: run: | remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) remotes::install_cran("rcmdcheck") + remotes::install_cran("processx") 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')" + run: Rscript --verbose -e "rcmdcheck::rcmdcheck('${{ needs.jobR.outputs.r_bindings }}', args = c('--no-manual','--as-cran'), error_on = 'warning', check_dir = 'check')" - name: Upload check results if: failure() From 7957eac1b8c10f6c4202f05bf0e6bf4390e4a6f8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 9 Jun 2021 17:48:21 -0400 Subject: [PATCH 379/729] I wonder if this will fix the issue? --- src/mlpack/methods/ann/gan/metrics/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/gan/metrics/CMakeLists.txt b/src/mlpack/methods/ann/gan/metrics/CMakeLists.txt index c93ed9d492..0600b603fa 100644 --- a/src/mlpack/methods/ann/gan/metrics/CMakeLists.txt +++ b/src/mlpack/methods/ann/gan/metrics/CMakeLists.txt @@ -1,8 +1,8 @@ # Define the files we need to compile. # Anything not in this list will not be compiled into mlpack. set(SOURCES - inception_score - inception_score_impl + inception_score.hpp + inception_score_impl.hpp ) # Add directory name to sources. From 1325745fecb2d4e84ba7468be25143c23787cd02 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 10 Jun 2021 17:11:24 +0200 Subject: [PATCH 380/729] Try to fix the installation dir, do not push Signed-off-by: Omar Shrit --- CMake/Autodownload.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/Autodownload.cmake b/CMake/Autodownload.cmake index ce23e32909..9d93704801 100644 --- a/CMake/Autodownload.cmake +++ b/CMake/Autodownload.cmake @@ -47,7 +47,7 @@ macro(get_deps LINK DEPS_NAME PACKAGE) # Clean these lines when boost is removed. if (${DEPS_NAME} MATCHES "boost") set(Boost_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/") - install(DIRECTORY "${Boost_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(DIRECTORY "${Boost_INCLUDE_DIR}/boost" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") else() set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") install(DIRECTORY "${GENERIC_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") From 8d67c9dad47085ad117f056bc648bb9e8fd5ddb2 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 10 Jun 2021 11:41:48 -0400 Subject: [PATCH 381/729] Safer unpacking of Armadillo sources. --- .ci/linux-steps.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.ci/linux-steps.yaml b/.ci/linux-steps.yaml index cab07dc8bb..228c404583 100644 --- a/.ci/linux-steps.yaml +++ b/.ci/linux-steps.yaml @@ -35,8 +35,12 @@ steps: fi # Install armadillo. - curl https://data.kurg.org/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo* - cmake . && make && sudo make install && cd .. + curl https://data.kurg.org/armadillo-8.400.0.tar.xz | tar -xvJ && \ + cd armadillo* && \ + cmake . && \ + make && \ + sudo make install && \ + cd .. # Install cereal. wget https://github.com/USCiLab/cereal/archive/v1.3.0.tar.gz From 220fc370b1d81bbe5d115309893ae0b9d9580778 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 11 Jun 2021 14:54:49 -0400 Subject: [PATCH 382/729] What if we force reinstallation? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aa76d54489..4b3f6da009 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -59,7 +59,7 @@ jobs: run: | remotes::install_deps(dependencies = TRUE) remotes::install_cran("roxygen2") - remotes::install_cran("processx") + remotes::install_cran("processx", force = TRUE) shell: Rscript {0} - name: CMake From 10cd2157692ef57d16b20060b6d1d446134eb9f4 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 11 Jun 2021 17:08:11 -0400 Subject: [PATCH 383/729] Oops, I forced in the wrong place. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4b3f6da009..d21ca98d10 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -132,7 +132,7 @@ jobs: run: | remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) remotes::install_cran("rcmdcheck") - remotes::install_cran("processx") + remotes::install_cran("processx", force=TRUE) shell: Rscript {0} - name: Check From c4ab2c8dac63702234582bef2c6e2aa3fa82ff7a Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 11 Jun 2021 20:11:20 -0400 Subject: [PATCH 384/729] Maybe reinstalling the ps package will help. --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d21ca98d10..92fd4a037f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -132,6 +132,7 @@ jobs: run: | remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) remotes::install_cran("rcmdcheck") + remotes::install_cran("ps", force=TRUE) remotes::install_cran("processx", force=TRUE) shell: Rscript {0} From 11e387881b5b7d257bfdedd5a1f9834b1bbace42 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 12 Jun 2021 08:30:02 -0400 Subject: [PATCH 385/729] Well it seems like maybe this strategy is working. --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 92fd4a037f..6ca32904e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -132,6 +132,7 @@ jobs: run: | remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) remotes::install_cran("rcmdcheck") + remotes::install_cran("digest", force=TRUE) remotes::install_cran("ps", force=TRUE) remotes::install_cran("processx", force=TRUE) shell: Rscript {0} From 303b3100b6155587c97c5cfc0bebbf61ef97d8a7 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 13 Jun 2021 08:36:20 -0400 Subject: [PATCH 386/729] Actually I think I am getting close now... --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6ca32904e6..d74b979875 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -135,6 +135,7 @@ jobs: remotes::install_cran("digest", force=TRUE) remotes::install_cran("ps", force=TRUE) remotes::install_cran("processx", force=TRUE) + remotes::install_cran("Rcpp", force=TRUE) shell: Rscript {0} - name: Check From d3c7522f2ca0387951de3827d7687f4be3fd1d7e Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 13 Jun 2021 11:07:25 -0400 Subject: [PATCH 387/729] Another package to reinstall... --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d74b979875..cc888925b4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -136,6 +136,7 @@ jobs: remotes::install_cran("ps", force=TRUE) remotes::install_cran("processx", force=TRUE) remotes::install_cran("Rcpp", force=TRUE) + remotes::install_cran("testthat", force=TRUE) shell: Rscript {0} - name: Check From 0c6418b5cc88075f2a9276340a48030ebc477153 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 13 Jun 2021 13:14:20 -0400 Subject: [PATCH 388/729] Not sure about this one... --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cc888925b4..352df21a31 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -136,6 +136,7 @@ jobs: remotes::install_cran("ps", force=TRUE) remotes::install_cran("processx", force=TRUE) remotes::install_cran("Rcpp", force=TRUE) + remotes::install_cran("rlang", force=TRUE) remotes::install_cran("testthat", force=TRUE) shell: Rscript {0} From ca188e2d4fcc1bee3897dab7737d9cac00bda489 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sun, 13 Jun 2021 19:05:08 -0400 Subject: [PATCH 389/729] Okay, another package... --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 352df21a31..5f347a4082 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -137,6 +137,7 @@ jobs: remotes::install_cran("processx", force=TRUE) remotes::install_cran("Rcpp", force=TRUE) remotes::install_cran("rlang", force=TRUE) + remotes::install_cran("magrittr", force=TRUE) remotes::install_cran("testthat", force=TRUE) shell: Rscript {0} From 62f7db4f2632fa42f55d920c0f8fbe6702f0cde4 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 14 Jun 2021 08:04:44 -0400 Subject: [PATCH 390/729] Another package... --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5f347a4082..e43652b442 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -139,6 +139,7 @@ jobs: remotes::install_cran("rlang", force=TRUE) remotes::install_cran("magrittr", force=TRUE) remotes::install_cran("testthat", force=TRUE) + remotes::install_cran("glue", force=TRUE) shell: Rscript {0} - name: Check From 0de456e90ecf9dd777154d12fbd45de6b1b09984 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 14 Jun 2021 14:46:32 -0400 Subject: [PATCH 391/729] Only reset the DatasetMapper if the dimensionality is wrong. --- src/mlpack/core/data/load_csv.hpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/mlpack/core/data/load_csv.hpp b/src/mlpack/core/data/load_csv.hpp index e6e6569ea4..845d3f076f 100644 --- a/src/mlpack/core/data/load_csv.hpp +++ b/src/mlpack/core/data/load_csv.hpp @@ -96,7 +96,20 @@ class LoadCSV { ++rows; } - info = DatasetMapper(rows); + + // Reset the DatasetInfo object, if needed. + if (info.Dimensionality() == 0) + { + info = DatasetMapper(rows); + } + else if (info.Dimensionality() != rows) + { + std::ostringstream oss; + oss << "data::LoadCSV(): given DatasetInfo has dimensionality " + << info.Dimensionality() << ", but data has dimensionality " + << rows; + throw std::invalid_argument(oss.str()); + } // Now, jump back to the beginning of the file. inFile.clear(); @@ -179,8 +192,19 @@ class LoadCSV qi::parse(line.begin(), line.end(), stringRule[findRowSize] % delimiterRule); - // Now that we know the dimensionality, initialize the DatasetMapper. - info.SetDimensionality(rows); + // Reset the DatasetInfo object, if needed. + if (info.Dimensionality() == 0) + { + info = DatasetMapper(rows); + } + else if (info.Dimensionality() != rows) + { + std::ostringstream oss; + oss << "data::LoadCSV(): given DatasetInfo has dimensionality " + << info.Dimensionality() << ", but data has dimensionality " + << rows; + throw std::invalid_argument(oss.str()); + } } // If we need to do a first pass for the DatasetMapper, do it. From 7d416ed4a34213462e25bfd3d8bc9f7003f0a682 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 14 Jun 2021 14:51:56 -0400 Subject: [PATCH 392/729] Update documentation so it is correct. --- src/mlpack/core/data/load.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/data/load.hpp b/src/mlpack/core/data/load.hpp index 9b54f43ce1..03766d8eeb 100644 --- a/src/mlpack/core/data/load.hpp +++ b/src/mlpack/core/data/load.hpp @@ -273,8 +273,12 @@ bool Load(const std::string& filename, * mlpack requires column-major matrices, this should be left at its default * value of 'true'. * - * The DatasetMapper object passed to this function will be re-created, so any - * mappings from previous loads will be lost. + * If the given `info` has already been used with a different `data::Load()` + * call where the dataset has the same dimensionality, then the mappings and + * dimension types inside of `info` will be *re-used*. If the given `info` is a + * new `DatasetMapper` object (e.g. its dimensionality is 0), then new mappings + * will be created. If the given `info` has a different dimensionality of data + * than what is present in `filename`, an exception will be thrown. * * @param filename Name of file to load. * @param matrix Matrix to load contents of file into. From 2fc791085f3148b21ce3bc16cecc9882eda58ea4 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 14 Jun 2021 14:53:44 -0400 Subject: [PATCH 393/729] Update history. --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index d048cbdae1..1c1c157cf8 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -61,6 +61,8 @@ * Fix Julia model serialization bug (#2970). + * Fix `LoadCSV()` to use pre-populated `DatasetInfo` objects (#2980). + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From f6f59726a30bfe23136f0f960e1ea899ee16e58d Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 14 Jun 2021 14:54:39 -0400 Subject: [PATCH 394/729] Another one... --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e43652b442..99aa5dcb41 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -140,6 +140,7 @@ jobs: remotes::install_cran("magrittr", force=TRUE) remotes::install_cran("testthat", force=TRUE) remotes::install_cran("glue", force=TRUE) + remotes::install_cran("diffobj", force=TRUE) shell: Rscript {0} - name: Check From b4592ac4483030b12d7edffa7e7af5ea44c63e46 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 14 Jun 2021 17:17:32 -0400 Subject: [PATCH 395/729] I wonder what will happen if I do this? --- .github/workflows/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99aa5dcb41..2cca708c0b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -128,6 +128,11 @@ jobs: key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('depends.Rds') }} restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}- + - name: Annihilate R environment + if: runner.os == 'macOS' + run: | + ls /Users/runner/work/_temp/Library/* && rm -rf /Users/runner/work/_temp/Library/* + - name: Install dependencies run: | remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) From d9bc6c8f307ed57adfbba2ff450c848bb0c546ef Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:25:56 +0530 Subject: [PATCH 396/729] added author link --- src/mlpack/methods/ann/layer/channel_shuffle.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle.hpp b/src/mlpack/methods/ann/layer/channel_shuffle.hpp index 27c747e84a..5e3eb273cb 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle.hpp @@ -21,6 +21,19 @@ namespace ann /** Artificial Neural Network. */ { * Channel Shuffle divides the channels/units in a tensor into groups * and rearrange while keeping the original tensor shape. * + * For more information, refer to the following paper, + * + * @code + * @article{zhang2018shufflenet, + * author = {Xiangyu Zhang, Xinyu Zhou, Mengxiao Lin, Jian Sun and + * Megvii Inc}, + * title = {Shufflenet: An extremely efficient convolutional neural + * network for mobile devices}, + * year = {2018}, + * url = {https://arxiv.org/pdf/1707.01083}, + * } + * @endcode + * * @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, From 832c1a3a3c5a07225824d4eadf0710b7dd3acb45 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:26:42 +0530 Subject: [PATCH 397/729] Apply suggestions from code review Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp index 5a4c2886ed..0ebfe134d7 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -46,7 +46,7 @@ ChannelShuffle( { if (depth % groupCount != 0) { - Log::Fatal << "Number of channels must be divisible by groupCount.!" << std::endl; + Log::Fatal << "Number of channels must be divisible by groupCount!" << std::endl; } } @@ -69,7 +69,7 @@ void ChannelShuffle::Forward( arma::cube inputAsCube(const_cast&>(input).memptr(), inRowSize, inColSize, depth * batchSize, false, false); arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, - depth * batchSize, false, true); + depth * batchSize, false, true); const size_t groupSize= depth / groupCount; size_t outChannelIdx = 0; @@ -105,7 +105,7 @@ void ChannelShuffle::Backward( arma::cube gradientAsCube(((arma::Mat&) gradient).memptr(), inColSize, inColSize, depth * batchSize, false, false); arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, - depth * batchSize, false, true); + depth * batchSize, false, true); const size_t groupSize= depth / groupCount; size_t gradientChannelIdx = 0; From 537df20aa3510cd9b8f83c586c47f75b840b84db Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:28:44 +0530 Subject: [PATCH 398/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index a8d7c4605a..137ea28aa9 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -4677,6 +4677,7 @@ TEST_CASE("ChannelShuffleLayerTest", "[ANNLayerTest]") << 11 << 23 << arma::endr << 12 << 24 << arma::endr; input1.reshape(24, 1); + // Value calculated using torch.nn.ChannelShuffle(). outputExpected1 << 1 << 17 << arma::endr << 2 << 18 << arma::endr << 3 << 19 << arma::endr From 12ecedfeb9f9c9b6f6332e9c6488a2bb7e42bcc5 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 15 Jun 2021 08:24:45 -0400 Subject: [PATCH 399/729] Reinstall remotes. --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2cca708c0b..2a25279601 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,10 +131,12 @@ jobs: - name: Annihilate R environment if: runner.os == 'macOS' run: | - ls /Users/runner/work/_temp/Library/* && rm -rf /Users/runner/work/_temp/Library/* + ls /Users/runner/work/_temp/Library/* && find +/Users/runner/work/_temp/Library/* ! -name 'remotes' -maxdepth=1 -type d -delete - name: Install dependencies run: | + install.packages("remotes") remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) remotes::install_cran("rcmdcheck") remotes::install_cran("digest", force=TRUE) From 464b31d6ed372c5e1e61c69e0d144380e088605c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 15 Jun 2021 11:35:35 -0400 Subject: [PATCH 400/729] Try to fix syntax. --- .github/workflows/main.yml | 4 ++-- src/mlpack/core/data/load.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2a25279601..7b80b5fa95 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -132,11 +132,11 @@ jobs: if: runner.os == 'macOS' run: | ls /Users/runner/work/_temp/Library/* && find -/Users/runner/work/_temp/Library/* ! -name 'remotes' -maxdepth=1 -type d -delete +/Users/runner/work/_temp/Library/* \! -name 'remotes' -maxdepth=1 -type d -delete - name: Install dependencies run: | - install.packages("remotes") + install.packages('remotes') remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) remotes::install_cran("rcmdcheck") remotes::install_cran("digest", force=TRUE) diff --git a/src/mlpack/core/data/load.hpp b/src/mlpack/core/data/load.hpp index 9b54f43ce1..50ee8cdaf2 100644 --- a/src/mlpack/core/data/load.hpp +++ b/src/mlpack/core/data/load.hpp @@ -34,7 +34,7 @@ namespace data /** Functions to load and save matrices and models. */ { * * - CSV (arma::csv_ascii), denoted by .csv, or optionally .txt * - TSV (arma::raw_ascii), denoted by .tsv, .csv, or .txt - * - ASCII (arma::raw_ascii), denoted by .json + * - ASCII (arma::raw_ascii), denoted by .txt * - Armadillo ASCII (arma::arma_ascii), also denoted by .txt * - PGM (arma::pgm_binary), denoted by .pgm * - PPM (arma::ppm_binary), denoted by .ppm From 5c21ce9d02b7302e20d484b9107bf94b91f891c6 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 15 Jun 2021 11:37:28 -0400 Subject: [PATCH 401/729] Another attempt at a syntax fix. --- .github/workflows/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b80b5fa95..b0a42bc408 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,8 +131,7 @@ jobs: - name: Annihilate R environment if: runner.os == 'macOS' run: | - ls /Users/runner/work/_temp/Library/* && find -/Users/runner/work/_temp/Library/* \! -name 'remotes' -maxdepth=1 -type d -delete + ls /Users/runner/work/_temp/Library/* && rm -rf /Users/runner/work/_temp/Library/* - name: Install dependencies run: | From a6c0087fcc464c6f091f69bdb677a3ddbb10448d Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 15 Jun 2021 18:49:54 +0200 Subject: [PATCH 402/729] I do think these headers are useless here in this file. Let us see if the CI agrees with me. Signed-off-by: Omar Shrit --- src/mlpack/core/data/load_model_impl.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/mlpack/core/data/load_model_impl.hpp b/src/mlpack/core/data/load_model_impl.hpp index ae5396b4fb..c62bad2673 100644 --- a/src/mlpack/core/data/load_model_impl.hpp +++ b/src/mlpack/core/data/load_model_impl.hpp @@ -15,15 +15,8 @@ // In case it hasn't already been included. #include "load.hpp" -#include -#include - #include "extension.hpp" -#include -#include -#include - #include #include #include From b4dd229c948d4c0e09c2f6e7fccb0ec9ad95f7a7 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 15 Jun 2021 13:50:42 -0400 Subject: [PATCH 403/729] Wow! It worked! Now can I simplify it? --- .github/workflows/main.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b0a42bc408..b461400b7f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,10 +38,10 @@ jobs: - name: Query dependencies run: | cp src/mlpack/bindings/R/mlpack/DESCRIPTION.in DESCRIPTION - Rscript --verbose -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps(dependencies = TRUE), 'depends.Rds')" + Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps(dependencies = TRUE), 'depends.Rds')" - name: Cache R packages - if: runner.os != 'Windows' + if: runner.os != 'Windows' && runner.os != 'macOS' uses: actions/cache@v1 with: path: ${{ env.R_LIBS_USER }} @@ -59,7 +59,6 @@ jobs: run: | remotes::install_deps(dependencies = TRUE) remotes::install_cran("roxygen2") - remotes::install_cran("processx", force = TRUE) shell: Rscript {0} - name: CMake @@ -121,17 +120,17 @@ jobs: 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' + if: runner.os != 'Windows' && runner.os != 'macOS' 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: Annihilate R environment - if: runner.os == 'macOS' - run: | - ls /Users/runner/work/_temp/Library/* && rm -rf /Users/runner/work/_temp/Library/* +# - name: Annihilate R environment +# if: runner.os == 'macOS' +# run: | +# ls /Users/runner/work/_temp/Library/* && rm -rf /Users/runner/work/_temp/Library/* - name: Install dependencies run: | @@ -150,7 +149,7 @@ jobs: shell: Rscript {0} - name: Check - run: Rscript --verbose -e "rcmdcheck::rcmdcheck('${{ needs.jobR.outputs.r_bindings }}', args = c('--no-manual','--as-cran'), error_on = 'warning', check_dir = 'check')" + run: Rscript -e "rcmdcheck::rcmdcheck('${{ needs.jobR.outputs.r_bindings }}', args = c('--no-manual','--as-cran'), error_on = 'warning', check_dir = 'check')" - name: Upload check results if: failure() From 4fc6a91d10b0bc572a8ff360d1a3e2208226f1e5 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 15 Jun 2021 17:37:08 -0400 Subject: [PATCH 404/729] What if all I needed to do was disable the cache? --- .github/workflows/main.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b461400b7f..68da47424e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -127,25 +127,10 @@ jobs: key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('depends.Rds') }} restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}- -# - name: Annihilate R environment -# if: runner.os == 'macOS' -# run: | -# ls /Users/runner/work/_temp/Library/* && rm -rf /Users/runner/work/_temp/Library/* - - name: Install dependencies run: | install.packages('remotes') remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) - remotes::install_cran("rcmdcheck") - remotes::install_cran("digest", force=TRUE) - remotes::install_cran("ps", force=TRUE) - remotes::install_cran("processx", force=TRUE) - remotes::install_cran("Rcpp", force=TRUE) - remotes::install_cran("rlang", force=TRUE) - remotes::install_cran("magrittr", force=TRUE) - remotes::install_cran("testthat", force=TRUE) - remotes::install_cran("glue", force=TRUE) - remotes::install_cran("diffobj", force=TRUE) shell: Rscript {0} - name: Check From 346b0c893a903db216839d6cf21a754dbf99ef2c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 15 Jun 2021 17:37:56 -0400 Subject: [PATCH 405/729] Oops, don't remove rcmdcheck. --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68da47424e..d53a06fa41 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,6 +131,7 @@ jobs: run: | install.packages('remotes') remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE) + remotes::install_cran("rcmdcheck") shell: Rscript {0} - name: Check From ad2c512be224cef38f28e854ab95ed5e44305dc9 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 16 Jun 2021 14:32:17 +0200 Subject: [PATCH 406/729] Adding the missing boost headers. Still surprised were the headers removal hits. Signed-off-by: Omar Shrit --- src/mlpack/bindings/markdown/print_docs.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mlpack/bindings/markdown/print_docs.cpp b/src/mlpack/bindings/markdown/print_docs.cpp index 44adf69e93..636b203ee4 100644 --- a/src/mlpack/bindings/markdown/print_docs.cpp +++ b/src/mlpack/bindings/markdown/print_docs.cpp @@ -9,12 +9,14 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ +#include "binding_info.hpp" #include "print_docs.hpp" +#include "print_doc_functions.hpp" #include #include -#include "binding_info.hpp" -#include "print_doc_functions.hpp" + +#include // Make sure that this is defined. #ifndef DOXYGEN_PREFIX From 218e13843f10929588ef08714711e0464aad6c57 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 16 Jun 2021 16:14:41 +0200 Subject: [PATCH 407/729] Re-organize header, I am confused now Signed-off-by: Omar Shrit --- src/mlpack/bindings/markdown/print_docs.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/bindings/markdown/print_docs.cpp b/src/mlpack/bindings/markdown/print_docs.cpp index 636b203ee4..e103437f80 100644 --- a/src/mlpack/bindings/markdown/print_docs.cpp +++ b/src/mlpack/bindings/markdown/print_docs.cpp @@ -9,15 +9,15 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#include "binding_info.hpp" -#include "print_docs.hpp" -#include "print_doc_functions.hpp" - #include #include #include +#include "binding_info.hpp" +#include "print_docs.hpp" +#include "print_doc_functions.hpp" + // Make sure that this is defined. #ifndef DOXYGEN_PREFIX #define DOXYGEN_PREFIX "https://mlpack.org/doc/mlpack-git/doxygen/" From ae0f0124c8928e8336082f194cca010692ba4d88 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Wed, 16 Jun 2021 16:17:57 +0200 Subject: [PATCH 408/729] Increase the minimum required cmake version to compile mlpack Signed-off-by: Omar Shrit --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2bd365156..10b0e26225 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.3.2) +cmake_minimum_required(VERSION 3.6) project(mlpack C CXX) include(CMake/cotire.cmake) From e48e4b7e810dc644759d19543974717759cb2f57 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 16 Jun 2021 14:24:42 -0400 Subject: [PATCH 409/729] Use SetDimensionality(); the constructor will lose the policy. --- src/mlpack/core/data/load_csv.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/data/load_csv.hpp b/src/mlpack/core/data/load_csv.hpp index 845d3f076f..ce7d0bb9b1 100644 --- a/src/mlpack/core/data/load_csv.hpp +++ b/src/mlpack/core/data/load_csv.hpp @@ -100,7 +100,7 @@ class LoadCSV // Reset the DatasetInfo object, if needed. if (info.Dimensionality() == 0) { - info = DatasetMapper(rows); + info.SetDimensionality(rows); } else if (info.Dimensionality() != rows) { @@ -195,7 +195,7 @@ class LoadCSV // Reset the DatasetInfo object, if needed. if (info.Dimensionality() == 0) { - info = DatasetMapper(rows); + info.SetDimensionality(rows); } else if (info.Dimensionality() != rows) { From aa6d55582622d3427b21ebfa0a630843eaadacf5 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 17 Jun 2021 10:00:20 +0530 Subject: [PATCH 410/729] Update src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp index 0ebfe134d7..6fda08704d 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -65,7 +65,6 @@ void ChannelShuffle::Forward( assert(output.n_cols == batchSize); } - arma::cube inputAsCube(const_cast&>(input).memptr(), inRowSize, inColSize, depth * batchSize, false, false); arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, From 64b9d63f02156e75b79723d485402ba721edea83 Mon Sep 17 00:00:00 2001 From: Aakash kaushik Date: Thu, 17 Jun 2021 15:38:54 +0530 Subject: [PATCH 411/729] Padding layer fix for multiple filters (#2985) * padding fix for multiple filters * padding for single and multiple layers * add tests and comments * zero output fix(forgot to assign to subcube) * fixed the implementation * applying suggestions * tests failed because of wronginputdims that i gave * correct outputHeight and width * fix failing test * final test fix * tests pass --- src/mlpack/methods/ann/layer/padding.hpp | 47 ++++++++++++++++++- src/mlpack/methods/ann/layer/padding_impl.hpp | 42 ++++++++++++++--- src/mlpack/tests/ann_layer_test.cpp | 22 ++++++++- 3 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/mlpack/methods/ann/layer/padding.hpp b/src/mlpack/methods/ann/layer/padding.hpp index 7d8bf72d0d..eab4bb0f05 100644 --- a/src/mlpack/methods/ann/layer/padding.hpp +++ b/src/mlpack/methods/ann/layer/padding.hpp @@ -41,11 +41,15 @@ class Padding * @param padWRight Right padding width of the input. * @param padHTop Top padding height of the input. * @param padHBottom Bottom padding height of the input. + * @param inputWidth Width of the input. + * @param inputHeight Height of the input. */ Padding(const size_t padWLeft = 0, const size_t padWRight = 0, const size_t padHTop = 0, - const size_t padHBottom = 0); + const size_t padHBottom = 0, + const size_t inputWidth = 0, + const size_t inputHeight = 0); /** * Ordinary feed forward pass of a neural network, evaluating the function @@ -101,6 +105,26 @@ class Padding //! Modify the bottom padding width. size_t& PadHBottom() { return padHBottom; } + //! Get the input width. + size_t InputWidth() const { return inputWidth; } + //! Modify the input width. + size_t& InputWidth() { return inputWidth; } + + //! Get the input height. + size_t InputHeight() const { return inputHeight; } + //! Modify the input height. + size_t& InputHeight() { return inputHeight; } + + //! Get the output width. + size_t OutputWidth() const { return outputWidth; } + //! Modify the output width. + size_t& OutputWidth() { return outputWidth; } + + //! Get the output height. + size_t OutputHeight() const { return outputHeight; } + //! Modify the output height. + size_t& OutputHeight() { return outputHeight; } + /** * Serialize the layer. */ @@ -123,6 +147,27 @@ class Padding //! Locally-stored number of rows and columns of input. size_t nRows, nCols; + //! Locally-stored input height. + size_t inputHeight; + + //! Locally-stored input width. + size_t inputWidth; + + //! Locally-stored output height. + size_t outputHeight; + + //! Locally-stored output width. + size_t outputWidth; + + //! Locally-stored number of input channels. + size_t inSize; + + //! Locally-stored cube input parameter. + arma::cube inputTemp; + + //! Locally-stored output parameter. + arma::cube outputTemp; + //! Locally-stored delta object. OutputDataType delta; diff --git a/src/mlpack/methods/ann/layer/padding_impl.hpp b/src/mlpack/methods/ann/layer/padding_impl.hpp index 93936b5e69..29eabd1645 100644 --- a/src/mlpack/methods/ann/layer/padding_impl.hpp +++ b/src/mlpack/methods/ann/layer/padding_impl.hpp @@ -24,13 +24,17 @@ Padding::Padding( const size_t padWLeft, const size_t padWRight, const size_t padHTop, - const size_t padHBottom) : + const size_t padHBottom, + const size_t inputWidth, + const size_t inputHeight) : padWLeft(padWLeft), padWRight(padWRight), padHTop(padHTop), padHBottom(padHBottom), nRows(0), - nCols(0) + nCols(0), + inputHeight(inputWidth), + inputWidth(inputHeight) { // Nothing to do here. } @@ -42,10 +46,33 @@ void Padding::Forward( { nRows = input.n_rows; nCols = input.n_cols; - output = arma::zeros(nRows + padWLeft + padWRight, - nCols + padHTop + padHBottom); - output.submat(padWLeft, padHTop, padWLeft + nRows - 1, - padHTop + nCols - 1) = input; + + if (inputWidth == 0 || inputHeight == 0) + { + output = arma::zeros(nRows + padWLeft + padWRight, + nCols + padHTop + padHBottom); + output.submat(padWLeft, padHTop, padWLeft + nRows - 1, + padHTop + nCols - 1) = input; + } + else + { + inSize = input.n_elem / (inputWidth * inputHeight * nCols); + inputTemp = arma::Cube(const_cast&>(input).memptr(), + inputWidth, inputHeight, inSize * nCols, false, false); + outputTemp = arma::zeros>(inputWidth + padWLeft + padWRight, + inputHeight + padHTop + padHBottom, inSize * nCols); + for (size_t i = 0; i < inputTemp.n_slices; ++i) + { + outputTemp.slice(i).submat(padWLeft, padHTop, padWLeft + inputWidth - 1, + padHTop + inputHeight - 1) = inputTemp.slice(i); + } + + output = arma::Mat(outputTemp.memptr(), outputTemp.n_elem / nCols, + nCols); + } + + outputWidth = inputWidth + padWLeft + padWRight; + outputHeight = inputHeight + padHTop + padHBottom; } template @@ -68,9 +95,12 @@ void Padding::serialize( ar(CEREAL_NVP(padWRight)); ar(CEREAL_NVP(padHTop)); ar(CEREAL_NVP(padHBottom)); + ar(CEREAL_NVP(inputWidth)); + ar(CEREAL_NVP(inputHeight)); } } // namespace ann } // namespace mlpack #endif + \ No newline at end of file diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 1d94b16560..b336789e46 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -697,7 +697,7 @@ TEST_CASE("SimpleLinearNoBiasLayerTest", "[ANNLayerTest]") */ TEST_CASE("SimplePaddingLayerTest", "[ANNLayerTest]") { - arma::mat output, input, delta; + arma::mat output, input, delta, input1, output1; Padding<> module(1, 2, 3, 4); // Test the Forward function. @@ -710,6 +710,26 @@ TEST_CASE("SimplePaddingLayerTest", "[ANNLayerTest]") // Test the Backward function. module.Backward(input, output, delta); CheckMatrices(delta, input); + + // Test forward function for multiple filters. + // Here it's 3 filters with height = 224, width = 224 + // the output should be [226 * 226 * 3, 1] with 1 padding. + Padding<> module1(1, 1, 1, 1, 224, 224); + input1 = arma::randu(224 * 224 * 3, 1); + module1.Forward(input1, output1); + REQUIRE(arma::accu(input1) == arma::accu(output1)); + REQUIRE(output1.n_rows == (226 * 226 * 3)); + REQUIRE(output1.n_cols == 1); + + // Test forward function for multiple batches with multiple filters. + // Here it's 3 filters with height = 244, width = 244 + // the output should be [246 * 246 * 3, 3] with 1 padding. + Padding<> module2(1 ,1, 1, 1, 244, 244); + input1 = arma::randu(244 * 244 * 3, 3); + module2.Forward(input1, output1); + REQUIRE(arma::accu(input1) == arma::accu(output1)); + REQUIRE(output1.n_rows == (246 * 246 * 3)); + REQUIRE(output1.n_cols == 3); } /** From 6428557f47cd36e4f0a0b0644fc78e97e5b6431d Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 18 Jun 2021 20:57:25 -0400 Subject: [PATCH 412/729] Include ensmallen so ENS_VERSION_MAJOR is defined. --- src/mlpack/methods/reinforcement_learning/q_learning.hpp | 1 + src/mlpack/methods/reinforcement_learning/sac.hpp | 1 + .../reinforcement_learning/worker/n_step_q_learning_worker.hpp | 1 + .../reinforcement_learning/worker/one_step_q_learning_worker.hpp | 1 + .../reinforcement_learning/worker/one_step_sarsa_worker.hpp | 1 + 5 files changed, 5 insertions(+) diff --git a/src/mlpack/methods/reinforcement_learning/q_learning.hpp b/src/mlpack/methods/reinforcement_learning/q_learning.hpp index afbdcff33e..3e03bb8c40 100644 --- a/src/mlpack/methods/reinforcement_learning/q_learning.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_learning.hpp @@ -14,6 +14,7 @@ #define MLPACK_METHODS_RL_Q_LEARNING_HPP #include +#include #include "replay/random_replay.hpp" #include "replay/prioritized_replay.hpp" diff --git a/src/mlpack/methods/reinforcement_learning/sac.hpp b/src/mlpack/methods/reinforcement_learning/sac.hpp index f0431185f8..27ddb5cba0 100644 --- a/src/mlpack/methods/reinforcement_learning/sac.hpp +++ b/src/mlpack/methods/reinforcement_learning/sac.hpp @@ -14,6 +14,7 @@ #define MLPACK_METHODS_RL_SAC_HPP #include +#include #include "replay/random_replay.hpp" #include diff --git a/src/mlpack/methods/reinforcement_learning/worker/n_step_q_learning_worker.hpp b/src/mlpack/methods/reinforcement_learning/worker/n_step_q_learning_worker.hpp index b332752d64..4b052ec892 100644 --- a/src/mlpack/methods/reinforcement_learning/worker/n_step_q_learning_worker.hpp +++ b/src/mlpack/methods/reinforcement_learning/worker/n_step_q_learning_worker.hpp @@ -13,6 +13,7 @@ #ifndef MLPACK_METHODS_RL_WORKER_N_STEP_Q_LEARNING_WORKER_HPP #define MLPACK_METHODS_RL_WORKER_N_STEP_Q_LEARNING_WORKER_HPP +#include #include namespace mlpack { diff --git a/src/mlpack/methods/reinforcement_learning/worker/one_step_q_learning_worker.hpp b/src/mlpack/methods/reinforcement_learning/worker/one_step_q_learning_worker.hpp index a85d7cb13a..6916e22185 100644 --- a/src/mlpack/methods/reinforcement_learning/worker/one_step_q_learning_worker.hpp +++ b/src/mlpack/methods/reinforcement_learning/worker/one_step_q_learning_worker.hpp @@ -13,6 +13,7 @@ #ifndef MLPACK_METHODS_RL_WORKER_ONE_STEP_Q_LEARNING_WORKER_HPP #define MLPACK_METHODS_RL_WORKER_ONE_STEP_Q_LEARNING_WORKER_HPP +#include #include namespace mlpack { diff --git a/src/mlpack/methods/reinforcement_learning/worker/one_step_sarsa_worker.hpp b/src/mlpack/methods/reinforcement_learning/worker/one_step_sarsa_worker.hpp index 95451d30d4..1b114a1bde 100644 --- a/src/mlpack/methods/reinforcement_learning/worker/one_step_sarsa_worker.hpp +++ b/src/mlpack/methods/reinforcement_learning/worker/one_step_sarsa_worker.hpp @@ -13,6 +13,7 @@ #ifndef MLPACK_METHODS_RL_WORKER_ONE_STEP_SARSA_WORKER_HPP #define MLPACK_METHODS_RL_WORKER_ONE_STEP_SARSA_WORKER_HPP +#include #include namespace mlpack { From ec986cb4fe744923880e1d802ad98fcf98032f87 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 19 Jun 2021 22:51:53 +0200 Subject: [PATCH 413/729] Increase the cmake version in README Signed-off-by: Omar Shrit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 10f82a2c12..8e9ad6a05e 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ mlpack has the following dependencies: Armadillo >= 8.400.0 Boost (math_c99, spirit) >= 1.58.0 - CMake >= 3.2.2 + CMake >= 3.6 ensmallen >= 2.10.0 cereal >= 1.1.2 From fe2f32eb642b70680e12fb01c1508009b31f12f1 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 20 Jun 2021 09:04:56 +0200 Subject: [PATCH 414/729] Remove trailing space Signed-off-by: Omar Shrit --- CMake/ConfigureCrossCompile.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ConfigureCrossCompile.cmake b/CMake/ConfigureCrossCompile.cmake index 75e28bc453..ba78707ec3 100644 --- a/CMake/ConfigureCrossCompile.cmake +++ b/CMake/ConfigureCrossCompile.cmake @@ -33,7 +33,7 @@ macro(search_openblas version) endif() file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a") set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) - set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) + set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES}) set(BLA_VENDOR OpenBLAS) set(BLAS_FOUND ON) endif() From e3276d9437002c13cb24705221b4cacadd18352c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 20 Jun 2021 09:08:36 +0200 Subject: [PATCH 415/729] Do not check for BLAS and LAPACK if we are cross compiling and we have already found it. Signed-off-by: Omar Shrit --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19021de485..abddba2c1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -279,7 +279,7 @@ if (DISABLE_DOWNLOADS) find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED) else() find_package(Armadillo "${ARMADILLO_VERSION}") - if (NOT ARMADILLO_FOUND) + if (NOT ARMADILLO_FOUND AND NOT CMAKE_CROSSCOMPILING) find_package(BLAS QUIET) find_package(LAPACK QUIET) if (NOT BLAS_FOUND AND NOT LAPACK_FOUND) From 99e4b6b2aef26f416df1227ec88f60430c81034c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 20 Jun 2021 10:35:05 +0200 Subject: [PATCH 416/729] Separate both of the check Signed-off-by: Omar Shrit --- CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abddba2c1f..cc5e4a5dc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -279,11 +279,13 @@ if (DISABLE_DOWNLOADS) find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED) else() find_package(Armadillo "${ARMADILLO_VERSION}") - if (NOT ARMADILLO_FOUND AND NOT CMAKE_CROSSCOMPILING) - find_package(BLAS QUIET) - find_package(LAPACK QUIET) - if (NOT BLAS_FOUND AND NOT LAPACK_FOUND) - message(FATAL_ERROR "Can not find BLAS or LAPACK! These are required for Armadillo. Please install one of them---or install Armadillo---before installing mlpack.") + if (NOT ARMADILLO_FOUND) + if (NOT CMAKE_CROSSCOMPILING) + find_package(BLAS QUIET) + find_package(LAPACK QUIET) + if (NOT BLAS_FOUND AND NOT LAPACK_FOUND) + message(FATAL_ERROR "Can not find BLAS or LAPACK! These are required for Armadillo. Please install one of them---or install Armadillo---before installing mlpack.") + endif() endif() get_deps(http://files.mlpack.org/armadillo-10.3.0.tar.gz armadillo armadillo-10.3.0.tar.gz) set(ARMADILLO_INCLUDE_DIR ${GENERIC_INCLUDE_DIR}) From ff1041282a4a700674c27b9fa5444fa8cbe3c091 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 20 Jun 2021 20:43:08 +0530 Subject: [PATCH 417/729] Improved speed of lp forward pass --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 24 ++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 1c2b841e24..64ee64f607 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -161,12 +161,22 @@ class LpPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { + arma::Mat inputPre = input; + input = arma::pow(input, normType); + + for (size_t i = 1; i < input.n_cols; ++i) + inputPre.col(i) += inputPre.col(i - 1); + + for (size_t i = 1; i < input.n_rows; ++i) + inputPre.row(i) += inputPre.row(i - 1); + for (size_t j = 0, colidx = 0; j < output.n_cols; ++j, colidx += strideHeight) { for (size_t i = 0, rowidx = 0; i < output.n_rows; ++i, rowidx += strideWidth) { + double val = 0.0; size_t rowEnd = rowidx + kernelWidth - 1; size_t colEnd = colidx + kernelHeight - 1; @@ -175,12 +185,16 @@ class LpPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; - arma::mat subInput = input( - arma::span(rowidx, rowEnd), - arma::span(colidx, colEnd)); + if (rowidx >= 1) + { + if (colidx >= 1) + val += inputPre(rowidx - 1, colidx - 1); + val -= inputPre(rowidx - 1, colEnd); + } + if (colidx >= 1) + val -= inputPre(rowEnd, colidx - 1); - output(i, j) = pow(arma::accu(arma::pow(subInput, - normType)), 1.0 / normType); + output(i, j) = pow(val, 1.0 / normType); } } } From 18efd64977ad3fd94179a125fa6b300aa3c2d5d6 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 20 Jun 2021 20:48:50 +0530 Subject: [PATCH 418/729] Fixed the computation of submatrix sum --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 64ee64f607..7f97c0adc1 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -185,6 +185,7 @@ class LpPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; + val += inputPre(rowEnd, colEnd); if (rowidx >= 1) { if (colidx >= 1) From 821a2f27125e5233abce675b26ee31d588e4e4ff Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 20 Jun 2021 23:18:39 +0530 Subject: [PATCH 419/729] Update lp_pooling.hpp --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 7f97c0adc1..7af72e00bf 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -162,7 +162,7 @@ class LpPooling void Pooling(const arma::Mat& input, arma::Mat& output) { arma::Mat inputPre = input; - input = arma::pow(input, normType); + inputPre = arma::pow(inputPre, normType); for (size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); From 83207c4439ce3072e9b590cd6d2feeafdd25f2bd Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Mon, 21 Jun 2021 12:10:20 +0530 Subject: [PATCH 420/729] Use arma::pow to use fast armadillo computation --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 7af72e00bf..b87c496004 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -195,9 +195,10 @@ class LpPooling if (colidx >= 1) val -= inputPre(rowEnd, colidx - 1); - output(i, j) = pow(val, 1.0 / normType); + output(i, j) = val; } } + output = arma::pow(output, 1.0 / normType); } /** From a08bbf13169b3b4a6493b293b2481d678e4a9b04 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Mon, 21 Jun 2021 14:18:52 +0530 Subject: [PATCH 421/729] Apply suggestions from code review Co-authored-by: kartikdutt18 <39593019+kartikdutt18@users.noreply.github.com> --- src/mlpack/methods/ann/layer/lp_pooling.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index b87c496004..ef8a12f2f8 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -192,12 +192,14 @@ class LpPooling val += inputPre(rowidx - 1, colidx - 1); val -= inputPre(rowidx - 1, colEnd); } + if (colidx >= 1) val -= inputPre(rowEnd, colidx - 1); output(i, j) = val; } } + output = arma::pow(output, 1.0 / normType); } From 9fc0513b26b14a5690b6d1fcb9022ada85b12d82 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Tue, 22 Jun 2021 03:34:04 +0200 Subject: [PATCH 422/729] Style fixes (line length, extra spaces, newline). --- .../bindings/python/print_class_defn.hpp | 21 +++++++++++-------- src/mlpack/bindings/python/print_pyx.cpp | 6 ++++-- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- src/mlpack/methods/ann/layer/padding.hpp | 4 ++-- src/mlpack/methods/ann/layer/padding_impl.hpp | 5 ++--- src/mlpack/tests/ann_layer_test.cpp | 2 +- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index ff1de4b26e..73b2a1fa68 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -63,11 +63,11 @@ void PrintClassDefn( * cdef class Type: * cdef * modelptr * cdef public dict scrubbed_params - * + * * def __cinit__(self): * self.modelptr = new () * self.scrubbed_params = dict() - * + * * def __dealloc__(self): * del self.modelptr * @@ -82,18 +82,18 @@ void PrintClassDefn( * * def _get_cpp_params(self): * return SerializeOutJSON(self.modelptr, "") - * + * * def _set_cpp_params(self, state): * SerializeInJSON(self.modelptr, state, "") - * + * * def get_cpp_params(self, return_str=False): * params = self._get_cpp_params() * return process_params_out(self, params, return_str=return_str) - * + * * def set_cpp_params(self, params_dic): * params_str = process_params_in(self, params_dic) * self._set_cpp_params(params_str) - * + * * @endcode */ std::cout << "cdef class " << strippedType << "Type:" << std::endl; @@ -129,11 +129,14 @@ void PrintClassDefn( std::cout << std::endl; std::cout << " def get_cpp_params(self, return_str=False):" << std::endl; std::cout << " params = self._get_cpp_params()" << std::endl; - std::cout << " return process_params_out(self, params, return_str=return_str)" << std::endl; + std::cout << " return process_params_out(self, params, " + << "return_str=return_str)" << std::endl; std::cout << std::endl; std::cout << " def set_cpp_params(self, params_dic):" << std::endl; - std::cout << " params_str = process_params_in(self, params_dic)" << std::endl; - std::cout << " self._set_cpp_params(params_str.encode(\"utf-8\"))" << std::endl; + std::cout << " params_str = process_params_in(self, params_dic)" + << std::endl; + std::cout << " self._set_cpp_params(params_str.encode(\"utf-8\"))" + << std::endl; std::cout << std::endl; } diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index e85e0fa082..6fd4899c3e 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,8 +80,10 @@ void PrintPYX(const util::BindingDetails& doc, cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, " << "ResetTimers, EnableTimers" << endl; cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl; - cout << "from preprocess_json_params import process_params_out, process_params_in" << endl; - cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON, SerializeInJSON" << endl; + cout << "from preprocess_json_params import process_params_out, " + << "process_params_in" << endl; + cout << "from serialization cimport SerializeIn, SerializeOut, " + << "SerializeOutJSON, SerializeInJSON" << endl; cout << endl; cout << "import numpy as np" << endl; cout << "cimport numpy as np" << endl; diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 7789247018..4156667beb 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -216,7 +216,7 @@ class MeanPooling // `errorArea * kernalArea` and for each element in error we are doing `kernalArea` // number of operations. Whereas in the prefix method the total number of operations // will be `4 * errorArea + 2 * inputArea`. The term `2 * inputArea` comes from - // prefix sums performed (col-wise and row-wise). + // prefix sums performed (col-wise and row-wise). // We can use this to determine which method to use. const bool condition = (error.n_elem * kernelHeight * kernelWidth) > (4 * error.n_elem + 2 * input.n_elem); diff --git a/src/mlpack/methods/ann/layer/padding.hpp b/src/mlpack/methods/ann/layer/padding.hpp index eab4bb0f05..b7bfcab976 100644 --- a/src/mlpack/methods/ann/layer/padding.hpp +++ b/src/mlpack/methods/ann/layer/padding.hpp @@ -152,10 +152,10 @@ class Padding //! Locally-stored input width. size_t inputWidth; - + //! Locally-stored output height. size_t outputHeight; - + //! Locally-stored output width. size_t outputWidth; diff --git a/src/mlpack/methods/ann/layer/padding_impl.hpp b/src/mlpack/methods/ann/layer/padding_impl.hpp index 29eabd1645..73507a5f90 100644 --- a/src/mlpack/methods/ann/layer/padding_impl.hpp +++ b/src/mlpack/methods/ann/layer/padding_impl.hpp @@ -46,7 +46,7 @@ void Padding::Forward( { nRows = input.n_rows; nCols = input.n_cols; - + if (inputWidth == 0 || inputHeight == 0) { output = arma::zeros(nRows + padWLeft + padWRight, @@ -62,7 +62,7 @@ void Padding::Forward( outputTemp = arma::zeros>(inputWidth + padWLeft + padWRight, inputHeight + padHTop + padHBottom, inSize * nCols); for (size_t i = 0; i < inputTemp.n_slices; ++i) - { + { outputTemp.slice(i).submat(padWLeft, padHTop, padWLeft + inputWidth - 1, padHTop + inputHeight - 1) = inputTemp.slice(i); } @@ -103,4 +103,3 @@ void Padding::serialize( } // namespace mlpack #endif - \ No newline at end of file diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index b336789e46..5de93453dc 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -724,7 +724,7 @@ TEST_CASE("SimplePaddingLayerTest", "[ANNLayerTest]") // Test forward function for multiple batches with multiple filters. // Here it's 3 filters with height = 244, width = 244 // the output should be [246 * 246 * 3, 3] with 1 padding. - Padding<> module2(1 ,1, 1, 1, 244, 244); + Padding<> module2(1, 1, 1, 1, 244, 244); input1 = arma::randu(244 * 244 * 3, 3); module2.Forward(input1, output1); REQUIRE(arma::accu(input1) == arma::accu(output1)); From bcb3735a67ff26ad7f0c3325c918c1127414208c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 22 Jun 2021 14:12:57 +0200 Subject: [PATCH 423/729] Use std::is_same instead of boost::is_same Signed-off-by: Omar Shrit --- src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp b/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp index 4f1282b276..fb906c59b0 100644 --- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp +++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp @@ -54,7 +54,7 @@ template::value, + static_assert(std::is_same::value, "RectangleTree: MetricType must be metric::EuclideanDistance."); public: From f1adf41a2e9941d850a5949fd80bad1ef5b0b6db Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 22 Jun 2021 14:17:06 +0200 Subject: [PATCH 424/729] Fix small bug JSON -> txt Signed-off-by: Omar Shrit --- src/mlpack/core/data/save.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/core/data/save.hpp b/src/mlpack/core/data/save.hpp index 6f8889cf8e..685e7ebeb3 100644 --- a/src/mlpack/core/data/save.hpp +++ b/src/mlpack/core/data/save.hpp @@ -32,7 +32,7 @@ namespace data /** Functions to load and save matrices. */ { * The supported types of files are the same as found in Armadillo: * * - CSV (arma::csv_ascii), denoted by .csv, or optionally .txt - * - ASCII (arma::raw_ascii), denoted by .json + * - ASCII (arma::raw_ascii), denoted by .txt * - Armadillo ASCII (arma::arma_ascii), also denoted by .txt * - PGM (arma::pgm_binary), denoted by .pgm * - PPM (arma::ppm_binary), denoted by .ppm From 8c09b1f4a73c28b4e45795c330d488c2f2d6b414 Mon Sep 17 00:00:00 2001 From: Marcus Edel Date: Tue, 22 Jun 2021 12:47:25 -0400 Subject: [PATCH 425/729] Apply suggestions from code review. Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_class_defn.hpp | 6 +++--- src/mlpack/bindings/python/print_pyx.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 73b2a1fa68..158ae0ce7d 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -130,13 +130,13 @@ void PrintClassDefn( std::cout << " def get_cpp_params(self, return_str=False):" << std::endl; std::cout << " params = self._get_cpp_params()" << std::endl; std::cout << " return process_params_out(self, params, " - << "return_str=return_str)" << std::endl; + << "return_str=return_str)" << std::endl; std::cout << std::endl; std::cout << " def set_cpp_params(self, params_dic):" << std::endl; std::cout << " params_str = process_params_in(self, params_dic)" - << std::endl; + << std::endl; std::cout << " self._set_cpp_params(params_str.encode(\"utf-8\"))" - << std::endl; + << std::endl; std::cout << std::endl; } diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 6fd4899c3e..4fcda954e9 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -81,7 +81,7 @@ void PrintPYX(const util::BindingDetails& doc, << "ResetTimers, EnableTimers" << endl; cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl; cout << "from preprocess_json_params import process_params_out, " - << "process_params_in" << endl; + << "process_params_in" << endl; cout << "from serialization cimport SerializeIn, SerializeOut, " << "SerializeOutJSON, SerializeInJSON" << endl; cout << endl; From 312553af1b018ab0dc5d8e0498ee1815886090e1 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:03:07 -0400 Subject: [PATCH 426/729] Add Params class to store data for each binding call. --- src/mlpack/core/util/params.cpp | 139 +++++++++++++++++++++++ src/mlpack/core/util/params.hpp | 145 ++++++++++++++++++++++++ src/mlpack/core/util/params_impl.hpp | 162 +++++++++++++++++++++++++++ 3 files changed, 446 insertions(+) create mode 100644 src/mlpack/core/util/params.cpp create mode 100644 src/mlpack/core/util/params.hpp create mode 100644 src/mlpack/core/util/params_impl.hpp diff --git a/src/mlpack/core/util/params.cpp b/src/mlpack/core/util/params.cpp new file mode 100644 index 0000000000..5cf3ee5799 --- /dev/null +++ b/src/mlpack/core/util/params.cpp @@ -0,0 +1,139 @@ +/** + * @file params.cpp + * @author Ryan Curtin + * + * Implementation of functions in the Param class. + */ +#include "params.hpp" +#include + +namespace mlpack { +namespace util { + +Params::Params(const std::map& aliases, + const std::map& parameters, + Params::FunctionMapType& functionMap, + const std::string& bindingName, + const BindingDetails& doc) : + // Copy all the given inputs. + aliases(aliases), + parameters(parameters), + functionMap(functionMap), + bindingName(bindingName), + doc(doc) +{ + // Nothing to do. +} + +/** + * Return `true` if the specified parameter was given. + * + * @param identifier The name of the parameter in question. + */ +bool Params::Has(const std::string& key) const +{ + std::string usedKey = key; + + if (!parameters.count(key)) + { + // Check any aliases, but only after we are sure the actual option as given + // does not exist. + // TODO: can we isolate alias support inside of the CLI binding code? + if (key.length() == 1 && aliases.count(key[0])) + usedKey = aliases.at(key[0]); + + if (!parameters.count(usedKey)) + { + Log::Fatal << "Parameter '" << key << "' does not exist in this " + << "program." << std::endl; + } + } + const std::string& checkKey = usedKey; + + return (parameters.at(checkKey).wasPassed > 0); +} + +/** + * Given two (matrix) parameters, ensure that the first is an in-place copy of + * the second. This will generally do nothing (as the bindings already do + * this automatically), except for command-line bindings, where we need to + * ensure that the output filename is the same as the input filename. + * + * @param outputParamName Name of output (matrix) parameter. + * @param inputParamName Name of input (matrix) parameter. + */ +void Params::MakeInPlaceCopy(const std::string& outputParamName, + const std::string& inputParamName) +{ + if (!parameters.count(outputParamName)) + Log::Fatal << "Unknown parameter '" << outputParamName << "'!" << std::endl; + if (!parameters.count(inputParamName)) + Log::Fatal << "Unknown parameter '" << inputParamName << "'!" << std::endl; + + ParamData& output = parameters[outputParamName]; + ParamData& input = parameters[inputParamName]; + + if (output.cppType != input.cppType) + { + Log::Fatal << "Cannot call MakeInPlaceCopy() with different types (" + << output.cppType << " and " << input.cppType << ")!" << std::endl; + } + + // Is there a function to do this? + if (functionMap[output.tname].count("InPlaceCopy") != 0) + { + functionMap[output.tname]["InPlaceCopy"](output, (void*) &input, NULL); + } +} + +/** + * Set the particular parameter as passed. + * + * @param identifier The name of the parameter to set as passed. + */ +void Params::SetPassed(const std::string& name) +{ + if (parameters.count(name) == 0) + { + throw std::invalid_argument("Params::SetPassed(): parameter " + name + + " not known for binding " + bindingName + "!"); + } + + // Set passed to true. + parameters[name].wasPassed = true; +} + +/** + * Check all input matrices for NaN and inf values, and throw an exception if + * any are found. + */ +void Params::CheckInputMatrices() +{ + typedef typename std::tuple TupleType; + std::map::iterator itr; + + for (itr = parameters.begin(); itr != parameters.end(); ++itr) + { + std::string paramName = itr->first; + std::string paramType = itr->second.cppType; + if (paramType == "arma::mat") + { + CheckInputMatrix(Get(paramName), paramName); + } + else if (paramType == "arma::vec") + { + CheckInputMatrix(Get(paramName), paramName); + } + else if (paramType == "arma::rowvec") + { + CheckInputMatrix(Get(paramName), paramName); + } + else if (paramType == "std::tuple") + { + CheckInputMatrix(std::get<1>(Get(paramName)), paramName); + } + } +} + +} // namespace util +} // namespace mlpack diff --git a/src/mlpack/core/util/params.hpp b/src/mlpack/core/util/params.hpp new file mode 100644 index 0000000000..577133071c --- /dev/null +++ b/src/mlpack/core/util/params.hpp @@ -0,0 +1,145 @@ +/** + * @file params.hpp + * @author Ryan Curtin + * + * The Params class stores parameter settings for an individual binding. + */ +#ifndef MLPACK_CORE_UTIL_PARAMS_HPP +#define MLPACK_CORE_UTIL_PARAMS_HPP + +#include "param_data.hpp" +#include "binding_details.hpp" + +namespace mlpack { +namespace util { + +/** + * The Params class holds all information about the parameters passed to a + * specific binding. + */ +class Params +{ + public: + // Convenience typedef for function maps. + typedef std::map> FunctionMapType; + + /** + * Create a new Params class. In general this should only be called via + * `IO::Parameters()`. + */ + Params(const std::map& aliases, + const std::map& parameters, + FunctionMapType& functionMap, + const std::string& bindingName, + const BindingDetails& doc); + + /** + * Return `true` if the specified parameter was given. + * + * @param identifier The name of the parameter in question. + */ + bool Has(const std::string& identifier) const; + + /** + * Get the value of type T found for the parameter specified by `identifier`. + * You can set the value using this reference safely. + * + * @param identifier The name of the parameter in question. + */ + template + T& Get(const std::string& identifier); + + /** + * Cast the given parameter of the given type to a short, printable + * `std::string`, for use in status messages. The message returned here + * should be only a handful of characters, and certainly no longer than one + * line. + * + * @param identifier The name of the parameter in question. + */ + template + std::string GetPrintable(const std::string& identifier); + + /** + * Get the raw value of the parameter before any processing that Get() might + * normally do. So, e.g., for command-line programs, this does not + * perform any data loading or manipulation like Get() does. So if you + * want to access a matrix or model (or similar) parameter before it is + * loaded, this is the method to use. + * + * @param identifier The name of the parameter in question. + */ + template + T& GetRaw(const std::string& identifier); + + /** + * Given two (matrix) parameters, ensure that the first is an in-place copy of + * the second. This will generally do nothing (as the bindings already do + * this automatically), except for command-line bindings, where we need to + * ensure that the output filename is the same as the input filename. + * + * @param outputParamName Name of output (matrix) parameter. + * @param inputParamName Name of input (matrix) parameter. + */ + // TODO: it would be really nice to remove this! It's only used by MeanShift + // and KMeans bindings. + void MakeInPlaceCopy(const std::string& outputParamName, + const std::string& inputParamName); + + //! Get the map of parameters. + std::map& Parameters() { return parameters; } + //! Get the map of aliases. + std::map& Aliases() { return aliases; } + + //! Get the binding name. + const std::string& BindingName() const { return bindingName; } + + //! Get the binding details. + const BindingDetails& Doc() const { return doc; } + + /** + * Set the particular parameter as passed. + * + * @param identifier The name of the parameter to set as passed. + */ + void SetPassed(const std::string& identifier); + + /** + * Check all input matrices for NaN and inf values, and throw an exception if + * any are found. + */ + void CheckInputMatrices(); + + private: + //! Convenience map from alias values to names. + std::map aliases; + //! Map of parameters. + std::map parameters; + + public: + //! Map for functions and types. + //! Note: this was originally created as a way to avoid virtual inheritance. + //! However, the design would be much cleaner if we simply used virtual + //! inheritance for different option types. + FunctionMapType functionMap; + + private: + //! Holds the name of the binding. + std::string bindingName; + + //! Holds the BindingDetails object. + BindingDetails doc; + + //! Utility function, used by CheckInputMatrices(). + template + void CheckInputMatrix(const T& matrix, const std::string& identifier); +}; + +} // namespace util +} // namespace mlpack + +// Include implementation. +#include "params_impl.hpp" + +#endif diff --git a/src/mlpack/core/util/params_impl.hpp b/src/mlpack/core/util/params_impl.hpp new file mode 100644 index 0000000000..6c7e35c465 --- /dev/null +++ b/src/mlpack/core/util/params_impl.hpp @@ -0,0 +1,162 @@ +/** + * @file params_impl.hpp + * @author Ryan Curtin + * @author Matthew Amidon + * + * Implementation of functions in the Params class. + */ +#ifndef MLPACK_CORE_UTIL_PARAMS_IMPL_HPP +#define MLPACK_CORE_UTIL_PARAMS_IMPL_HPP + +// Include definition, if needed. +#include "params.hpp" + +namespace mlpack { +namespace util { + +/** + * Get the value of type T found for the parameter specified by `identifier`. + * You can set the value using this reference safely. + * + * @param identifier The name of the parameter in question. + */ +template +T& Params::Get(const std::string& identifier) +{ + // TODO: can we remove the alias support here? + // Only use the alias if the parameter does not exist as given. + std::string key = (parameters.count(identifier) == 0 && + identifier.length() == 1 && aliases.count(identifier[0])) ? + aliases[identifier[0]] : identifier; + + if (parameters.count(key) == 0) + Log::Fatal << "Parameter '" << key << "' does not exist in this program!" + << std::endl; + + ParamData& d = parameters[key]; + + // Make sure the types are correct. + if (TYPENAME(T) != d.tname) + Log::Fatal << "Attempted to access parameter '" << key << "' as type " + << TYPENAME(T) << ", but its true type is " << d.tname << "!" + << std::endl; + + // Do we have a special mapped function? + if (functionMap[d.tname].count("GetParam") != 0) + { + T* output = NULL; + functionMap[d.tname]["GetParam"](d, NULL, (void*) &output); + return *output; + } + else + { + return *boost::any_cast(&d.value); + } +} + +/** + * Cast the given parameter of the given type to a short, printable + * `std::string`, for use in status messages. The message returned here + * should be only a handful of characters, and certainly no longer than one + * line. + * + * @param identifier The name of the parameter in question. + */ +template +std::string Params::GetPrintable(const std::string& identifier) +{ + // TODO: can we remove the alias support here? + // Only use the alias if the parameter does not exist as given. + std::string key = ((parameters.count(identifier) == 0) && + (identifier.length() == 1) && (aliases.count(identifier[0]) > 0)) ? + aliases[identifier[0]] : identifier; + + if (parameters.count(key) == 0) + Log::Fatal << "Parameter '" << key << "' does not exist in this program!" + << std::endl; + + ParamData& d = parameters[key]; + + // Make sure the types are correct. + if (TYPENAME(T) != d.tname) + Log::Fatal << "Attempted to access parameter '" << key << "' as type " + << TYPENAME(T) << ", but its true type is " << d.tname << "!" + << std::endl; + + // Do we have a special mapped function? + if (functionMap[d.tname].count("GetPrintableParam") != 0) + { + std::string output; + functionMap[d.tname]["GetPrintableParam"](d, NULL, (void*) &output); + return output; + } + else + { + std::ostringstream oss; + oss << "no GetPrintableParam function handler registered for type " + << d.cppType; + throw std::runtime_error(oss.str()); + } +} + +/** + * Get the raw value of the parameter before any processing that Get() might + * normally do. So, e.g., for command-line programs, this does not + * perform any data loading or manipulation like Get() does. So if you + * want to access a matrix or model (or similar) parameter before it is + * loaded, this is the method to use. + * + * @param identifier The name of the parameter in question. + */ +template +T& Params::GetRaw(const std::string& identifier) +{ + // TODO: can we remove the alias support here? + // Only use the alias if the parameter does not exist as given. + std::string key = (parameters.count(identifier) == 0 && + identifier.length() == 1 && aliases.count(identifier[0])) ? + aliases[identifier[0]] : identifier; + + if (parameters.count(key) == 0) + Log::Fatal << "Parameter '" << key << "' does not exist in this program!" + << std::endl; + + ParamData& d = parameters[key]; + + // Make sure the types are correct. + if (TYPENAME(T) != d.tname) + Log::Fatal << "Attempted to access parameter '" << key << "' as type " + << TYPENAME(T) << ", but its true type is " << d.tname << "!" + << std::endl; + + // Do we have a special mapped function? + if (functionMap[d.tname].count("GetRawParam") != 0) + { + T* output = NULL; + functionMap[d.tname]["GetRawParam"](d, NULL, (void*) &output); + return *output; + } + else + { + // Use the regular GetParam(). + return Get(identifier); + } +} + +//! Utility function, used by CheckInputMatrices(). +template +void Params::CheckInputMatrix(const T& matrix, const std::string& identifier) +{ + const std::string errMsg1 = "The input '" + identifier + "' has NaN values."; + const std::string errMsg2 = "The input '" + identifier + "' has inf values."; + + if (matrix.has_nan()) + Log::Fatal << errMsg1 << std::endl; + if (matrix.has_inf()) + Log::Fatal << errMsg2 << std::endl; +} + +} // namespace util +} // namespace mlpack + +#endif From 541c62c148b39b43bc816b787eed3769c27b517f Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:03:36 -0400 Subject: [PATCH 427/729] Adapt IO to remove binding-call-specific data. --- src/mlpack/core/util/io.cpp | 312 +++++++++++-------------------- src/mlpack/core/util/io.hpp | 169 ++++++----------- src/mlpack/core/util/io_impl.hpp | 139 -------------- 3 files changed, 168 insertions(+), 452 deletions(-) diff --git a/src/mlpack/core/util/io.cpp b/src/mlpack/core/util/io.cpp index 904a155cc0..94c463b56a 100644 --- a/src/mlpack/core/util/io.cpp +++ b/src/mlpack/core/util/io.cpp @@ -19,13 +19,13 @@ using namespace mlpack::util; /* Constructors, Destructors, Copy */ /* Make the constructor private, to preclude unauthorized instances */ -IO::IO() : didParse(false) +IO::IO() { return; } // Private copy constructor; don't want copies floating around. -IO::IO(const IO& /* other */) : didParse(false) +IO::IO(const IO& /* other */) { return; } @@ -33,7 +33,7 @@ IO::IO(const IO& /* other */) : didParse(false) // Private copy operator; don't want copies floating around. IO& IO::operator=(const IO& /* other */) { return *this; } -void IO::Add(ParamData&& data) +void IO::AddParameter(const std::string& bindingName, ParamData&& data) { // Temporarily define color code escape sequences. #ifndef _WIN32 @@ -52,95 +52,115 @@ void IO::Add(ParamData&& data) #undef BASH_CLEAR // Define identifier and alias maps. - std::map& parameters = - GetSingleton().parameters; - std::map& aliases = GetSingleton().aliases; + std::map& bindingParams = + GetSingleton().parameters[bindingName]; + std::map& bindingAliases = + GetSingleton().aliases[bindingName]; // If found in current map, print fatal error and terminate the program, but // only if the parameter is not consistent. - if (parameters.count(data.name) && !data.persistent) + if (bindingParams.count(data.name) && !data.persistent) { - outstr << "Parameter --" << data.name << " (-" << data.alias << ") " + outstr << "Parameter '" << data.name << "' ('" << data.alias << "') " << "is defined multiple times with the same identifiers." << std::endl; } - if (data.alias != '\0' && aliases.count(data.alias) && !data.persistent) + if (data.alias != '\0' && bindingAliases.count(data.alias) && + !data.persistent) { - outstr << "Parameter --" << data.name << " (-" << data.alias << ") " + outstr << "Parameter '" << data.name << " ('" << data.alias << "') " << "is defined multiple times with the same alias." << std::endl; } // Add the alias, if necessary. + std::lock_guard lock(GetSingleton().mapMutex); if (data.alias != '\0') - GetSingleton().aliases[data.alias] = data.name; + bindingAliases[data.alias] = data.name; - GetSingleton().parameters[data.name] = std::move(data); + bindingParams[data.name] = std::move(data); } /** - * See if the specified flag was found while parsing. + * Add a function to the function map. * - * @param identifier The name of the parameter in question. + * @param type Type that this function should be called for. + * @param name Name of the function. + * @param func Function to call. */ -bool IO::HasParam(const std::string& key) +void IO::AddFunction(const std::string& type, + const std::string& name, + void (*func)(util::ParamData&, const void*, void*)) { - std::string usedKey = key; - const std::map& parameters = - GetSingleton().parameters; - - if (!parameters.count(key)) - { - // Check any aliases, but only after we are sure the actual option as given - // does not exist. - if (key.length() == 1 && GetSingleton().aliases.count(key[0])) - usedKey = GetSingleton().aliases[key[0]]; - - if (!parameters.count(usedKey)) - { - Log::Fatal << "Parameter '--" << key << "' does not exist in this " - << "program." << std::endl; - } - } - const std::string& checkKey = usedKey; - - return (parameters.at(checkKey).wasPassed > 0); + std::lock_guard lock(GetSingleton().mapMutex); + GetSingleton().functionMap[type][name] = func; } /** - * Given two (matrix) parameters, ensure that the first is an in-place copy of - * the second. This will generally do nothing (as the bindings already do - * this automatically), except for command-line bindings, where we need to - * ensure that the output filename is the same as the input filename. + * Add a user-friendly name for a binding. * - * @param outputParamName Name of output (matrix) parameter. - * @param inputParamName Name of input (matrix) parameter. + * @param bindingName Name of the binding to add the user-friendly name for. + * @param name User-friendly name. */ -void IO::MakeInPlaceCopy(const std::string& outputParamName, - const std::string& inputParamName) +void IO::AddBindingName(const std::string& bindingName, const std::string& name) { - std::map& parameters = - GetSingleton().parameters; + std::lock_guard lock(GetSingleton().mapMutex); + GetSingleton().docs[bindingName].name = name; +} - if (!parameters.count(outputParamName)) - Log::Fatal << "Unknown parameter '" << outputParamName << "'!" << std::endl; - if (!parameters.count(inputParamName)) - Log::Fatal << "Unknown parameter '" << inputParamName << "'!" << std::endl; +/** + * Add a short description for a binding. + * + * @param bindingName Name of the binding to add the description for. + * @param shortDescription Description to use. + */ +void IO::AddShortDescription(const std::string& bindingName, + const std::string& shortDescription) +{ + std::lock_guard lock(GetSingleton().docMutex); + GetSingleton().docs[bindingName].shortDescription = shortDescription; +} - util::ParamData& output = parameters[outputParamName]; - util::ParamData& input = parameters[inputParamName]; +/** + * Add a long description for a binding. + * + * @param bindingName Name of the binding to add the description for. + * @param longDescription Function that returns the long description. + */ +void IO::AddLongDescription( + const std::string& bindingName, + const std::function& longDescription) +{ + std::lock_guard lock(GetSingleton().docMutex); + GetSingleton().docs[bindingName].longDescription = longDescription; +} - if (output.cppType != input.cppType) - { - Log::Fatal << "Cannot call MakeInPlaceCopy() with different types (" - << output.cppType << " and " << input.cppType << ")!" << std::endl; - } +/** + * Add an example for a binding. + * + * @param bindingName Name of the binding to add the example for. + * @param example Function that returns the example. + */ +void IO::AddExample(const std::string& bindingName, + const std::function& example) +{ + std::lock_guard lock(GetSingleton().docMutex); + GetSingleton().docs[bindingName].example.push_back(std::move(example)); +} - // Is there a function to do this? - if (IO::GetSingleton().functionMap[output.tname].count("InPlaceCopy") != 0) - { - IO::GetSingleton().functionMap[output.tname]["InPlaceCopy"](output, (void*) - &input, NULL); - } +/** + * Add a SeeAlso for a binding. + * + * @param bindingName Name of the binding to add the example for. + * @param description Description of the SeeAlso. + * @param link Link of the SeeAlso. + */ +void IO::AddSeeAlso(const std::string& bindingName, + const std::string& description, + const std::string& link) +{ + std::lock_guard lock(GetSingleton().docMutex); + GetSingleton().docs[bindingName].seeAlso.push_back( + std::make_pair(description, link)); } // Returns the sole instance of this class. @@ -150,149 +170,29 @@ IO& IO::GetSingleton() return singleton; } -// Get the parameters that the IO object knows about. -std::map& IO::Parameters() +/** + * Return a new Params object initialized with all the parameters of the + * binding `bindingName`. This is intended to be called at the beginning of + * the run of a binding. + */ +util::Params IO::Parameters(const std::string& bindingName) { - return GetSingleton().parameters; -} - -// Get the parameters that the IO object knows about. -std::map& IO::Aliases() -{ - return GetSingleton().aliases; -} - -// Get the program name as set by BINDING_NAME(). -std::string IO::ProgramName() -{ - return GetSingleton().doc.programName; -} - -// Set a particular parameter as passed. -void IO::SetPassed(const std::string& name) -{ - if (GetSingleton().parameters.count(name) == 0) - { - throw std::invalid_argument("IO::SetPassed(): parameter " + name + - " not known!"); - } - - // Set passed to true. - GetSingleton().parameters[name].wasPassed = true; -} - -// Store settings. -void IO::StoreSettings(const std::string& name) -{ - // Take all of the parameters and put them in the map. Clear anything old - // first. - std::get<0>(GetSingleton().storageMap[name]) = GetSingleton().parameters; - std::get<1>(GetSingleton().storageMap[name]) = GetSingleton().aliases; - std::get<2>(GetSingleton().storageMap[name]) = GetSingleton().functionMap; - - ClearSettings(); -} - -// Restore settings. -void IO::RestoreSettings(const std::string& name, const bool fatal) -{ - if (GetSingleton().storageMap.count(name) == 0 && fatal) - { - throw std::invalid_argument("no settings stored under the name '" + name - + "'"); - } - else if (GetSingleton().storageMap.count(name) == 0 && !fatal) - { - // Nothing to do, just clear what's there. - ClearSettings(); - } - else - { - GetSingleton().parameters = std::get<0>(GetSingleton().storageMap[name]); - GetSingleton().aliases = std::get<1>(GetSingleton().storageMap[name]); - GetSingleton().functionMap = std::get<2>(GetSingleton().storageMap[name]); - } -} - -// Clear settings. -void IO::ClearSettings() -{ - // Check for any parameters we need to keep. - std::map persistent; - std::map persistentAliases; - FunctionMapType persistentFunctions; - - // For the function mappings we have to preserve, we have to collect the - // types. - std::vector persistentTypes; - - std::map::const_iterator it = - GetSingleton().parameters.begin(); - while (it != GetSingleton().parameters.end()) - { - // Is the parameter persistent? - if (it->second.persistent) - { - persistent[it->first] = it->second; // Save the parameter. - // Add to the list of types, if it hasn't already been added. - if (std::find(persistentTypes.begin(), persistentTypes.end(), - it->second.tname) == persistentTypes.end()) - persistentTypes.push_back(it->second.tname); - } - - ++it; - } - - // Now check if there are any persistent aliases. - std::map::const_iterator it2 = - GetSingleton().aliases.begin(); - while (it2 != GetSingleton().aliases.end()) - { - // Is this an alias to a persistent parameter? - if (persistent.count(it2->second) > 0) - persistentAliases[it2->first] = it2->second; // Save it. - - ++it2; - } - - for (size_t i = 0; i < persistentTypes.size(); ++i) - { - // Add to persistent function map. - persistentFunctions[persistentTypes[i]] = - GetSingleton().functionMap[persistentTypes[i]]; - } - - // Save only the persistent parameters. - GetSingleton().parameters = persistent; - GetSingleton().aliases = persistentAliases; - GetSingleton().functionMap = persistentFunctions; -} - -void IO::CheckInputMatrices() -{ - typedef typename std::tuple TupleType; - std::map::iterator itr; - - for (itr = IO::Parameters().begin(); itr != IO::Parameters().end(); ++itr) - { - std::string paramName = itr->first; - std::string paramType = itr->second.cppType; - if (paramType == "arma::mat") - { - IO::CheckInputMatrix(IO::GetParam(paramName), paramName); - } - else if (paramType == "arma::vec") - { - IO::CheckInputMatrix(IO::GetParam(paramName), paramName); - } - else if (paramType == "arma::rowvec") - { - IO::CheckInputMatrix(IO::GetParam(paramName), paramName); - } - else if (paramType == "std::tuple") - { - IO::CheckInputMatrix( - std::get<1>(IO::GetParam(paramName)), paramName); - } - } + // We don't need a mutex here, because we are only randomly accessing elements + // of the maps. + + std::map resultAliases = + GetSingleton().aliases[bindingName]; + // Merge in any persistent parameters (e.g. parameters in the "" binding map). + std::map persistentAliases = GetSingleton().aliases[""]; + resultAliases.insert(persistentAliases.begin(), persistentAliases.end()); + + std::map resultParams = + GetSingleton().parameters[bindingName]; + // Merge in any persistent parameters (e.g. parameters in the "" binding map). + std::map persistentParams = + GetSingleton().parameters[""]; + resultParams.insert(persistentParams.begin(), persistentParams.end()); + + return Params(resultAliases, resultParams, GetSingleton().functionMap, + bindingName, GetSingleton().docs[bindingName]); } diff --git a/src/mlpack/core/util/io.hpp b/src/mlpack/core/util/io.hpp index aa9d71c16f..ead1a03dd1 100644 --- a/src/mlpack/core/util/io.hpp +++ b/src/mlpack/core/util/io.hpp @@ -28,12 +28,16 @@ #include "version.hpp" #include "param_data.hpp" +#include "params.hpp" #include #include +// TODO: this entire set of code is related to the bindings and maybe should go +// into src/mlpack/bindings/util/. namespace mlpack { +// TODO: completely go through this documentation and clean it up /** * @brief Parses the command line for parameters and holds user-specified * parameters. @@ -176,69 +180,77 @@ class IO * Adds a parameter to the hierarchy; use the PARAM_*() macros instead of this * (i.e. PARAM_INT()). * + * @param bindingName Name of the binding that this parameter is associated + * with. * @param d Utility structure holding parameter data. */ - static void Add(util::ParamData&& d); + static void AddParameter(const std::string& bindingName, util::ParamData&& d); /** - * See if the specified flag was found while parsing. + * Add a function to the function map. * - * @param identifier The name of the parameter in question. + * @param type Type that this function should be called for. + * @param name Name of the function. + * @param func Function to call. */ - static bool HasParam(const std::string& identifier); + static void AddFunction(const std::string& type, + const std::string& name, + void (*func)(util::ParamData&, const void*, void*)); /** - * Get the value of type T found while parsing. You can set the value using - * this reference safely. + * Add a user-friendly name for a binding. * - * @param identifier The name of the parameter in question. + * @param bindingName Name of the binding to add the user-friendly name for. + * @param name User-friendly name. */ - template - static T& GetParam(const std::string& identifier); + static void AddBindingName(const std::string& bindingName, + const std::string& name); /** - * Cast the given parameter of the given type to a short, printable - * std::string, for use in status messages. Ideally the message returned here - * should be only a handful of characters, and certainly no longer than one - * line. + * Add a short description for a binding. * - * @param identifier The name of the parameter in question. + * @param bindingName Name of the binding to add the description for. + * @param shortDescription Description to use. */ - template - static std::string GetPrintableParam(const std::string& identifier); + static void AddShortDescription(const std::string& bindingName, + const std::string& shortDescription); /** - * Get the raw value of the parameter before any processing that GetParam() - * might normally do. So, e.g., for command-line programs, this does not - * perform any data loading or manipulation like GetParam() does. So if you - * want to access a matrix or model (or similar) parameter before it is - * loaded, this is the method to use. + * Add a long description for a binding. * - * @param identifier The name of the parameter in question. + * @param bindingName Name of the binding to add the description for. + * @param longDescription Function that returns the long description. */ - template - static T& GetRawParam(const std::string& identifier); + static void AddLongDescription( + const std::string& bindingName, + const std::function& longDescription); /** - * Utility function for CheckInputMatrices(). + * Add an example for a binding. * - * @param matrix Matrix to check. - * @param identifier Name of the parameter in question. + * @param bindingName Name of the binding to add the example for. + * @param example Function that returns the example. */ - template - static void CheckInputMatrix(const T& matrix, const std::string& identifier); + static void AddExample(const std::string& bindingName, + const std::function& example); /** - * Given two (matrix) parameters, ensure that the first is an in-place copy of - * the second. This will generally do nothing (as the bindings already do - * this automatically), except for command-line bindings, where we need to - * ensure that the output filename is the same as the input filename. + * Add a SeeAlso for a binding. * - * @param outputParamName Name of output (matrix) parameter. - * @param inputParamName Name of input (matrix) parameter. + * @param bindingName Name of the binding to add the example for. + * @param description Description of the SeeAlso. + * @param link Link of the SeeAlso. */ - static void MakeInPlaceCopy(const std::string& outputParamName, - const std::string& inputParamName); + static void AddSeeAlso(const std::string& bindingName, + const std::string& description, + const std::string& link); + + /** + * Return a new Params object initialized with all the parameters of the + * binding `bindingName`. This is intended to be called at the beginning of + * the run of a binding. + */ + static util::Params Parameters(const std::string& bindingName); /** * Retrieve the singleton. As an end user, if you are just using the IO @@ -253,87 +265,30 @@ class IO */ static IO& GetSingleton(); - //! Return a modifiable list of parameters that IO knows about. - static std::map& Parameters(); - //! Return a modifiable list of aliases that IO knows about. - static std::map& Aliases(); - - //! Get the program name as set by the BINDING_NAME() macro. - static std::string ProgramName(); - - /** - * Mark a particular parameter as passed. - * - * @param name Name of the parameter. - */ - static void SetPassed(const std::string& name); - - /** - * Take all parameters and function mappings and store them, under the given - * name. This can later be restored with RestoreSettings(). If settings have - * already been saved under the given name, they will be overwritten. This - * also clears the current parameters and function map. - * - * @param name Name of settings to save. - */ - static void StoreSettings(const std::string& name); - - /** - * Restore all of the parameters and function mappings of the given name, if - * they exist. A std::invalid_argument exception will be thrown if fatal is - * true and no settings with the given name have been stored (with - * StoreSettings()). - * - * @param name Name of settings to restore. - * @param fatal Whether to throw an exception on an unknown name. - */ - static void RestoreSettings(const std::string& name, const bool fatal = true); - - /** - * Clear all of the settings, removing all parameters and function mappings. - */ - static void ClearSettings(); - - /** - * Checks all input matrices for NaN and inf values, exits if found any. - */ - static void CheckInputMatrices(); - private: - //! Convenience map from alias values to names. - std::map aliases; - //! Map of parameters. - std::map parameters; - - public: - //! Map for functions and types. - //! Use as functionMap["typename"]["functionName"]. + //! Ensure only one thread can call Add() at a time to modify the map. + std::mutex mapMutex; + //! Map from alias values to names, for each binding name. + std::map> aliases; + //! Map of parameters, for each binding name. + std::map> parameters; + //! Map of functions. Note that this is not specific to a binding, so we only + //! have one. typedef std::map> FunctionMapType; FunctionMapType functionMap; - private: - //! Storage map for parameters. - std::map, - std::map, FunctionMapType>> storageMap; - - public: - //! True, if IO was used to parse command line options. - bool didParse; - - //! Holds the name of the program for --version. This is the true program - //! name (argv[0]) not what is given in BindingDetails. - std::string programName; + //! Ensure only one thread can modify the docs map at a time. + std::mutex docMutex; + //! Map of binding details. + std::map docs; //! Holds the timer objects. - Timers timer; + util::Timers timer; //! So that Timer::Start() and Timer::Stop() can access the timer variable. friend class Timer; - //! Holds the bindingDetails objects. - util::BindingDetails doc; - private: /** * Make the constructor private, to preclude unauthorized instances. */ diff --git a/src/mlpack/core/util/io_impl.hpp b/src/mlpack/core/util/io_impl.hpp index e7407efd7f..2b6d7e96c8 100644 --- a/src/mlpack/core/util/io_impl.hpp +++ b/src/mlpack/core/util/io_impl.hpp @@ -18,145 +18,6 @@ namespace mlpack { -/** - * @brief Returns the value of the specified parameter. - * If the parameter is unspecified, an undefined but - * more or less valid value is returned. - * - * @tparam T The type of the parameter. - * @param identifier The full name of the parameter. - * - * @return The value of the parameter. Use IO::CheckValue to determine if it's - * valid. - */ -template -T& IO::GetParam(const std::string& identifier) -{ - // Only use the alias if the parameter does not exist as given. - std::string key = - (GetSingleton().parameters.count(identifier) == 0 && - identifier.length() == 1 && GetSingleton().aliases.count(identifier[0])) - ? GetSingleton().aliases[identifier[0]] : identifier; - - if (GetSingleton().parameters.count(key) == 0) - Log::Fatal << "Parameter --" << key << " does not exist in this program!" - << std::endl; - - util::ParamData& d = GetSingleton().parameters[key]; - - // Make sure the types are correct. - if (TYPENAME(T) != d.tname) - Log::Fatal << "Attempted to access parameter --" << key << " as type " - << TYPENAME(T) << ", but its true type is " << d.tname << "!" - << std::endl; - - // Do we have a special mapped function? - if (IO::GetSingleton().functionMap[d.tname].count("GetParam") != 0) - { - T* output = NULL; - IO::GetSingleton().functionMap[d.tname]["GetParam"](d, NULL, - (void*) &output); - return *output; - } - else - { - return *boost::any_cast(&d.value); - } -} - -/** - * Cast the given parameter of the given type to a short, printable std::string, - * for use in status messages. Ideally the message returned here should be only - * a handful of characters, and certainly no longer than one line. - * - * @param identifier The name of the parameter in question. - */ -template -std::string IO::GetPrintableParam(const std::string& identifier) -{ - // Only use the alias if the parameter does not exist as given. - std::string key = ((GetSingleton().parameters.count(identifier) == 0) && - (identifier.length() == 1) && - (GetSingleton().aliases.count(identifier[0]) > 0)) ? - GetSingleton().aliases[identifier[0]] : identifier; - - if (GetSingleton().parameters.count(key) == 0) - Log::Fatal << "Parameter --" << key << " does not exist in this program!" - << std::endl; - - util::ParamData& d = GetSingleton().parameters[key]; - - // Make sure the types are correct. - if (TYPENAME(T) != d.tname) - Log::Fatal << "Attempted to access parameter --" << key << " as type " - << TYPENAME(T) << ", but its true type is " << d.tname << "!" - << std::endl; - - // Do we have a special mapped function? - if (IO::GetSingleton().functionMap[d.tname].count("GetPrintableParam") != 0) - { - std::string output; - IO::GetSingleton().functionMap[d.tname]["GetPrintableParam"](d, NULL, - (void*) &output); - return output; - } - else - { - std::ostringstream oss; - oss << "no GetPrintableParam function handler registered for type " - << d.cppType; - throw std::runtime_error(oss.str()); - } -} - -template -T& IO::GetRawParam(const std::string& identifier) -{ - // Only use the alias if the parameter does not exist as given. - std::string key = - (GetSingleton().parameters.count(identifier) == 0 && - identifier.length() == 1 && GetSingleton().aliases.count(identifier[0])) - ? GetSingleton().aliases[identifier[0]] : identifier; - - if (GetSingleton().parameters.count(key) == 0) - Log::Fatal << "Parameter --" << key << " does not exist in this program!" - << std::endl; - - util::ParamData& d = GetSingleton().parameters[key]; - - // Make sure the types are correct. - if (TYPENAME(T) != d.tname) - Log::Fatal << "Attempted to access parameter --" << key << " as type " - << TYPENAME(T) << ", but its true type is " << d.tname << "!" - << std::endl; - - // Do we have a special mapped function? - if (IO::GetSingleton().functionMap[d.tname].count("GetRawParam") != 0) - { - T* output = NULL; - IO::GetSingleton().functionMap[d.tname]["GetRawParam"](d, NULL, - (void*) &output); - return *output; - } - else - { - // Use the regular GetParam(). - return GetParam(identifier); - } -} - -template -void IO::CheckInputMatrix(const T& matrix, const std::string& identifier) -{ - std::string errMsg1 = "The input " + identifier + " has NaN values."; - std::string errMsg2 = "The input " + identifier + " has inf values."; - - if (matrix.has_nan()) - Log::Fatal << errMsg1 << std::endl; - if (matrix.has_inf()) - Log::Fatal << errMsg2 << std::endl; -} - } // namespace mlpack #endif From 1cf6b0dcb6facac72f6c9fe4bd015067496b2ab2 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:05:37 -0400 Subject: [PATCH 428/729] Use STRINGIFY(BINDING_NAME) to set the binding name. --- src/mlpack/core/util/param.hpp | 95 ++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/src/mlpack/core/util/param.hpp b/src/mlpack/core/util/param.hpp index fc809c5b6e..74a32e46ae 100644 --- a/src/mlpack/core/util/param.hpp +++ b/src/mlpack/core/util/param.hpp @@ -38,13 +38,15 @@ using DatasetInfo = DatasetMapper; // unique identifier inside of the PARAM() module. #define JOIN(x, y) JOIN_AGAIN(x, y) #define JOIN_AGAIN(x, y) x ## y +#define STRINGIFY(x) STRINGIFY_AGAIN(x) +#define STRINGIFY_AGAIN(x) #x /** @endcond */ /** - * Specify the program name of a binding. Only one instance of this macro - * should be present in your program! Therefore, use it in the main.cpp - * (or corresponding binding) in your program. + * Specify the user-friendly name of a binding. Only one instance of this macro + * should be present per binding. BINDING_NAME should be set before calling + * this. * * @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(), * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(), @@ -52,11 +54,13 @@ using DatasetInfo = DatasetMapper; * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(), * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ(). * - * @param NAME Short string representing the name of the program. + * @param NAME User-friendly name. */ -#define BINDING_NAME(NAME) static \ - mlpack::util::ProgramName \ - io_programname_dummy_object = mlpack::util::ProgramName(NAME); +// TODO: use __COUNTER__ here and elsewhere! +#define BINDING_USER_NAME(NAME) static \ + mlpack::util::BindingName \ + io_bindingname_dummy_object = mlpack::util::BindingName( \ + STRINGIFY(BINDING_NAME), NAME); /** * Specify the short description of a binding. Only one instance of this macro @@ -76,7 +80,7 @@ using DatasetInfo = DatasetMapper; #define BINDING_SHORT_DESC(SHORT_DESC) static \ mlpack::util::ShortDescription \ io_programshort_desc_dummy_object = mlpack::util::ShortDescription( \ - SHORT_DESC); + STRINGIFY(BINDING_NAME), SHORT_DESC); /** * Specify the long description of a binding. Only one instance of this macro @@ -98,7 +102,7 @@ using DatasetInfo = DatasetMapper; #define BINDING_LONG_DESC(LONG_DESC) static \ mlpack::util::LongDescription \ io_programlong_desc_dummy_object = mlpack::util::LongDescription( \ - []() { return std::string(LONG_DESC); }); + STRINGIFY(BINDING_NAME), []() { return std::string(LONG_DESC); }); /** * Specify the example of a binding. Mutiple instance of this macro can be @@ -122,13 +126,13 @@ using DatasetInfo = DatasetMapper; mlpack::util::Example \ JOIN(io_programexample_dummy_object_, __COUNTER__) = \ mlpack::util::Example( \ - []() { return(std::string(EXAMPLE)); }); + STRINGIFY(BINDING_NAME), []() { return(std::string(EXAMPLE)); }); #else #define BINDING_EXAMPLE(EXAMPLE) static \ mlpack::util::Example \ JOIN(JOIN(io_programexample_dummy_object_, __LINE__), opt) = \ mlpack::util::Example( \ - []() { return(std::string(EXAMPLE)); }); + STRINGIFY(BINDING_NAME), []() { return(std::string(EXAMPLE)); }); #endif /** @@ -158,12 +162,12 @@ using DatasetInfo = DatasetMapper; #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \ mlpack::util::SeeAlso \ JOIN(io_programsee_also_dummy_object_, __COUNTER__) = \ - mlpack::util::SeeAlso(DESCRIPTION, LINK); + mlpack::util::SeeAlso(STRINGIFY(BINDING_NAME), DESCRIPTION, LINK); #else #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \ mlpack::util::SeeAlso \ JOIN(JOIN(io_programsee_also_dummy_object_, __LINE__), opt) = \ - mlpack::util::SeeAlso(DESCRIPTION, LINK); + mlpack::util::SeeAlso(STRINGIFY(BINDING_NAME), DESCRIPTION, LINK); #endif /** @@ -175,8 +179,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -202,8 +206,8 @@ using DatasetInfo = DatasetMapper; * @param ALIAS An alias for the parameter (one letter). * @param DEF Default value of the parameter. * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug // Use a forward declaration of the class. @@ -234,8 +238,8 @@ using DatasetInfo = DatasetMapper; * printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others * here---it will cause problems. * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -261,8 +265,8 @@ using DatasetInfo = DatasetMapper; * @param ALIAS An alias for the parameter (one letter). * @param DEF Default value of the parameter. * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -292,8 +296,8 @@ using DatasetInfo = DatasetMapper; * printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others * here---it will cause problems. * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -321,8 +325,8 @@ using DatasetInfo = DatasetMapper; * @param ALIAS An alias for the parameter (one letter). * @param DEF Default value of the parameter. * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -353,8 +357,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -928,8 +932,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -962,8 +966,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -1002,8 +1006,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS One-character string representing the alias of the parameter. * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -1117,8 +1121,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -1142,8 +1146,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -1167,8 +1171,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -1194,8 +1198,8 @@ using DatasetInfo = DatasetMapper; * here---it will cause problems. * @param ALIAS An alias for the parameter (one letter). * - * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(), - * BINDING_EXAMPLE() and BINDING_SEE_ALSO(). + * @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(), + * BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO(). * * @bug * The __COUNTER__ variable is used in most cases to guarantee a unique global @@ -1261,14 +1265,15 @@ using DatasetInfo = DatasetMapper; #define PARAM(T, ID, DESC, ALIAS, NAME, REQ, IN, TRANS, DEF) \ static mlpack::util::Option \ JOIN(io_option_dummy_object_in_, __COUNTER__) \ - (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, testName); + (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, STRINGIFY(BINDING_NAME)); // There are no uses of required models, so that is not an option to this // macro (it would be easy to add). #define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \ static mlpack::util::Option \ JOIN(io_option_dummy_model_, __COUNTER__) \ - (nullptr, ID, DESC, ALIAS, #TYPE, REQ, IN, false, testName); + (nullptr, ID, DESC, ALIAS, #TYPE, REQ, IN, false, \ + STRINGIFY(BINDING_NAME)); #else // We have to do some really bizarre stuff since __COUNTER__ isn't defined. I // don't think we can absolutely guarantee success, but it should be "good @@ -1277,13 +1282,13 @@ using DatasetInfo = DatasetMapper; #define PARAM(T, ID, DESC, ALIAS, NAME, REQ, IN, TRANS, DEF) \ static mlpack::util::Option \ JOIN(JOIN(io_option_dummy_object_in_, __LINE__), opt) \ - (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, testName); + (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, STRINGIFY(BINDING_NAME)); #define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \ static mlpack::util::Option \ JOIN(JOIN(io_option_dummy_object_model_, __LINE__), opt) \ (nullptr, ID, DESC, ALIAS, #TYPE, REQ, IN, false, \ - testName); + STRINGIFY(BINDING_NAME)); #endif #endif From 5cf377063d5c047ec9aa9e04b25deba4be93c366 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:05:57 -0400 Subject: [PATCH 429/729] Overhaul BindingDetails. --- src/mlpack/core/util/binding_details.hpp | 4 +- src/mlpack/core/util/program_doc.cpp | 49 +++++++++++++++--------- src/mlpack/core/util/program_doc.hpp | 38 +++++++++++------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/mlpack/core/util/binding_details.hpp b/src/mlpack/core/util/binding_details.hpp index 34fabe6627..2320aed8cb 100644 --- a/src/mlpack/core/util/binding_details.hpp +++ b/src/mlpack/core/util/binding_details.hpp @@ -23,8 +23,8 @@ namespace util { */ struct BindingDetails { - //! Name of the binding. - std::string programName; + //! User-friendly name of the binding. + std::string name; //! A short two-sentence description of the binding, what it does, and what //! it is useful for. std::string shortDescription; diff --git a/src/mlpack/core/util/program_doc.cpp b/src/mlpack/core/util/program_doc.cpp index 4306bc504c..f95f560c96 100644 --- a/src/mlpack/core/util/program_doc.cpp +++ b/src/mlpack/core/util/program_doc.cpp @@ -3,8 +3,8 @@ * @author Yashwant Singh Parihar * @author Ryan Curtin * - * Implementation of mutiple classes that store information related to a binding. - * The classes register themselves with IO when constructed. + * Implementation of mutiple classes that store information related to a + * binding. The classes register themselves with IO when constructed. * * 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 @@ -21,69 +21,80 @@ using namespace mlpack::util; using namespace std; /** - * Construct a ProgramName object. When constructed, it will register itself - * with IO. A fatal error will be thrown if more than one is constructed. + * Construct a BindingName object. When constructed, it will register itself + * with IO. A fatal error will be thrown if more than one is constructed for + * a given bindingName. * - * @param programName Name of the binding. + * @param bindingName Name of the binding. + * @param name Name displayed to user of the binding. */ -ProgramName::ProgramName(const std::string& programName) +BindingName::BindingName(const std::string& bindingName, + const std::string& name) { // Register this with IO. - IO::GetSingleton().doc.programName = std::move(programName); + IO::AddBindingName(bindingName, name); } /** * Construct a ShortDescription object. When constructed, it will register * itself with IO. A fatal error will be thrown if more than one is - * constructed. + * constructed for a given `bindingName`. * + * @param bindingName Name of the binding. * @param shortDescription A short two-sentence description of the binding, * what it does, and what it is useful for. */ -ShortDescription::ShortDescription(const std::string& shortDescription) +ShortDescription::ShortDescription(const std::string& bindingName, + const std::string& shortDescription) { // Register this with IO. - IO::GetSingleton().doc.shortDescription = std::move(shortDescription); + IO::AddShortDescription(bindingName, shortDescription); } /** * Construct a LongDescription object. When constructed, it will register itself - * with IO. A fatal error will be thrown if more than one is constructed. + * with IO. A fatal error will be thrown if more than one is constructed for a + * given `bindingName`. * + * @param bindingName Name of the binding. * @param longDescription Long string containing documentation on * what it is. No newline characters are necessary; this is * taken care of by IO later. */ LongDescription::LongDescription( + const std::string& bindingName, const std::function& longDescription) { // Register this with IO. - IO::GetSingleton().doc.longDescription = std::move(longDescription); + IO::AddLongDescription(bindingName, longDescription); } /** * Construct a Example object. When constructed, it will register itself - * with IO. + * with IO for the given `bindingName`. * + * @param bindingName Name of the binding. * @param example Documentation on how to use the binding. */ -Example::Example( - const std::function& example) +Example::Example(const std::string& bindingName, + const std::function& example) { // Register this with IO. - IO::GetSingleton().doc.example.push_back(std::move(example)); + IO::AddExample(bindingName, example); } /** * Construct a SeeAlso object. When constructed, it will register itself * with IO. * + * @param bindingName Name of the binding. * @param description Description of SeeAlso. * @param link Link of SeeAlso. */ -SeeAlso::SeeAlso( - const std::string& description, const std::string& link) +SeeAlso::SeeAlso(const std::string& bindingName, + const std::string& description, + const std::string& link) { // Register this with IO. - IO::GetSingleton().doc.seeAlso.push_back(make_pair(description, link)); + IO::AddSeeAlso(bindingName, description, link); } diff --git a/src/mlpack/core/util/program_doc.hpp b/src/mlpack/core/util/program_doc.hpp index 0d71d93fe5..7d6f64d7c4 100644 --- a/src/mlpack/core/util/program_doc.hpp +++ b/src/mlpack/core/util/program_doc.hpp @@ -17,16 +17,18 @@ namespace mlpack { namespace util { -class ProgramName +class BindingName { public: /** - * Construct a ProgramName object. When constructed, it will register itself - * with IO. A fatal error will be thrown if more than one is constructed. + * Construct a BindingName object. When constructed, it will register itself + * with IO. A fatal error will be thrown if more than one is constructed for + * a given bindingName. * - * @param programName Name of the binding. + * @param bindingName Name of the binding. + * @param name Name displayed to user of the binding. */ - ProgramName(const std::string& programName); + BindingName(const std::string& bindingName, const std::string& name); }; class ShortDescription @@ -37,24 +39,29 @@ class ShortDescription * itself with IO. A fatal error will be thrown if more than one is * constructed. * + * @param bindingName Name of the binding. * @param shortDescription A short two-sentence description of the binding, * what it does, and what it is useful for. */ - ShortDescription(const std::string& shortDescription); + ShortDescription(const std::string& bindingName, + const std::string& shortDescription); }; class LongDescription { public: /** - * Construct a LongDescription object. When constructed, it will register itself - * with IO. A fatal error will be thrown if more than one is constructed. + * Construct a LongDescription object. When constructed, it will register + * itself with IO. A fatal error will be thrown if more than one is + * constructed for a given `bindingName`. * + * @param bindingName Name of the binding. * @param longDescription Long string containing documentation on * what it is. No newline characters are necessary; this is * taken care of by IO later. */ - LongDescription(const std::function& longDescription); + LongDescription(const std::string& bindingName, + const std::function& longDescription); }; class Example @@ -62,11 +69,13 @@ class Example public: /** * Construct a Example object. When constructed, it will register itself - * with IO. + * with IO for the given `bindingName`. * + * @param bindingName Name of the binding. * @param example Documentation on how to use the binding. */ - Example(const std::function& example); + Example(const std::string& bindingName, + const std::function& example); }; class SeeAlso @@ -74,12 +83,15 @@ class SeeAlso public: /** * Construct a SeeAlso object. When constructed, it will register itself - * with IO. + * with IO for the given `bindingName`. * + * @param bindingName Name of the binding. * @param description Description of SeeAlso. * @param link Link of SeeAlso. */ - SeeAlso(const std::string& description, const std::string& link); + SeeAlso(const std::string& bindingName, + const std::string& description, + const std::string& link); }; } // namespace util From 8fbdcd7968a17564bf3ee18c103c97529f431179 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:06:18 -0400 Subject: [PATCH 430/729] Use a util::Params to do the checks. --- src/mlpack/core/util/param_checks.hpp | 16 +++++++-- src/mlpack/core/util/param_checks_impl.hpp | 39 +++++++++++++--------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/mlpack/core/util/param_checks.hpp b/src/mlpack/core/util/param_checks.hpp index c1ac39aeea..9b9bcfc11f 100644 --- a/src/mlpack/core/util/param_checks.hpp +++ b/src/mlpack/core/util/param_checks.hpp @@ -39,6 +39,7 @@ namespace util { * sense. The custom error message should not have a capitalized first * character and no ending punctuation (a '!' will be added by this function). * + * @param params Set of parameters to check. * @param constraints Set of parameters from which only one should be passed. * @param fatal If true, output goes to Log::Fatal instead of Log::Warn and an * exception is thrown. @@ -47,6 +48,7 @@ namespace util { * parameters in the constraints were passed. */ void RequireOnlyOnePassed( + util::Params& params, const std::vector& constraints, const bool fatal = true, const std::string& customErrorMessage = "", @@ -75,12 +77,14 @@ void RequireOnlyOnePassed( * sense. The custom error message should not have a capitalized first * character and no ending punctuation (a '!' will be added by this function). * + * @param params Set of parameters to check. * @param constraints Set of parameters from which only one should be passed. * @param fatal If true, output goes to Log::Fatal instead of Log::Warn and an * exception is thrown. * @param customErrorMessage Error message to append. */ void RequireAtLeastOnePassed( + util::Params& params, const std::vector& constraints, const bool fatal = true, const std::string& customErrorMessage = ""); @@ -105,12 +109,14 @@ void RequireAtLeastOnePassed( * sense. The custom error message should not have a capitalized first * character and no ending punctuation (a '!' will be added by this function). * + * @param params Set of parameters to check. * @param constraints Set of parameters of which none or all should be passed. * @param fatal If true, output goes to Log::Fatal instead of Log::Warn and an * exception is thrown. * @param customErrorMessage Error message to append. */ void RequireNoneOrAllPassed( + util::Params& params, const std::vector& constraints, const bool fatal = true, const std::string& customErrorMessage = ""); @@ -133,13 +139,15 @@ void RequireNoneOrAllPassed( * weak learner type". * * @tparam T Type of parameter. + * @param params Set of parameters to check. * @param paramName Name of parameter to check. * @param set Set of valid values for parameter. * @param fatal If true, an exception is thrown and output goes to Log::Fatal. * @param errorMessage Error message to output. */ template -void RequireParamInSet(const std::string& paramName, +void RequireParamInSet(util::Params& params, + const std::string& paramName, const std::vector& set, const bool fatal, const std::string& errorMessage); @@ -161,6 +169,7 @@ void RequireParamInSet(const std::string& paramName, * sense. * * @tparam T Type of parameter to check. + * @param params Set of parameters to check. * @param paramName Name of parameter to check. * @param conditional Function to use to check parameter value; should return * 'true' if the parameter value is okay. @@ -168,7 +177,8 @@ void RequireParamInSet(const std::string& paramName, * @param errorMessage Error message to output. */ template -void RequireParamValue(const std::string& paramName, +void RequireParamValue(util::Params& params, + const std::string& paramName, const std::function& conditional, const bool fatal, const std::string& errorMessage); @@ -180,10 +190,12 @@ void RequireParamValue(const std::string& paramName, * then a warning will be issued noting that the parameter is ignored. The * warning will go to Log::Warn. * + * @param params Set of parameters to check. * @param constraints Set of constraints. * @param paramName Name of parameter to check. */ void ReportIgnoredParam( + util::Params& params, const std::vector>& constraints, const std::string& paramName); diff --git a/src/mlpack/core/util/param_checks_impl.hpp b/src/mlpack/core/util/param_checks_impl.hpp index 8562e1341f..2e0cbfc348 100644 --- a/src/mlpack/core/util/param_checks_impl.hpp +++ b/src/mlpack/core/util/param_checks_impl.hpp @@ -19,6 +19,7 @@ namespace util { // Check that the arguments are given. inline void RequireOnlyOnePassed( + util::Params& params, const std::vector& constraints, const bool fatal, const std::string& errorMessage, @@ -30,7 +31,7 @@ inline void RequireOnlyOnePassed( size_t set = 0; for (size_t i = 0; i < constraints.size(); ++i) { - if (IO::HasParam(constraints[i])) + if (params.Has(constraints[i])) ++set; } @@ -90,6 +91,7 @@ inline void RequireOnlyOnePassed( } inline void RequireAtLeastOnePassed( + util::Params& params, const std::vector& constraints, const bool fatal, const std::string& errorMessage) @@ -100,7 +102,7 @@ inline void RequireAtLeastOnePassed( size_t set = 0; for (size_t i = 0; i < constraints.size(); ++i) { - if (IO::HasParam(constraints[i])) + if (params.Has(constraints[i])) ++set; } @@ -136,6 +138,7 @@ inline void RequireAtLeastOnePassed( } inline void RequireNoneOrAllPassed( + util::Params& params, const std::vector& constraints, const bool fatal, const std::string& errorMessage) @@ -146,7 +149,7 @@ inline void RequireNoneOrAllPassed( size_t set = 0; for (size_t i = 0; i < constraints.size(); ++i) { - if (IO::HasParam(constraints[i])) + if (params.Has(constraints[i])) ++set; } @@ -178,20 +181,21 @@ inline void RequireNoneOrAllPassed( } template -void RequireParamInSet(const std::string& name, - const std::vector& set, - const bool fatal, - const std::string& errorMessage) +void RequireParamInSet(util::Params& params, + const std::string& name, + const std::vector& set, + const bool fatal, + const std::string& errorMessage) { if (BINDING_IGNORE_CHECK(name)) return; - if (std::find(set.begin(), set.end(), IO::GetParam(name)) == set.end()) + if (std::find(set.begin(), set.end(), params.Get(name)) == set.end()) { // The item was not found in the set. util::PrefixedOutStream& stream = fatal ? Log::Fatal : Log::Warn; stream << "Invalid value of " << PRINT_PARAM_STRING(name) << " specified (" - << PRINT_PARAM_VALUE(IO::GetParam(name), true) << "); "; + << PRINT_PARAM_VALUE(params.Get(name), true) << "); "; if (!errorMessage.empty()) stream << errorMessage << "; "; stream << "must be one of "; @@ -203,7 +207,8 @@ void RequireParamInSet(const std::string& name, } template -void RequireParamValue(const std::string& name, +void RequireParamValue(util::Params& params, + const std::string& name, const std::function& conditional, const bool fatal, const std::string& errorMessage) @@ -212,18 +217,19 @@ void RequireParamValue(const std::string& name, return; // We need to make sure that the condition holds. - bool condition = conditional(IO::GetParam(name)); + bool condition = conditional(params.Get(name)); if (!condition) { // The condition failed. util::PrefixedOutStream& stream = fatal ? Log::Fatal : Log::Warn; stream << "Invalid value of " << PRINT_PARAM_STRING(name) << " specified (" - << PRINT_PARAM_VALUE(IO::GetParam(name), false) << "); " + << PRINT_PARAM_VALUE(params.Get(name), false) << "); " << errorMessage << "!" << std::endl; } } inline void ReportIgnoredParam( + util::Params& params, const std::vector>& constraints, const std::string& paramName) { @@ -234,7 +240,7 @@ inline void ReportIgnoredParam( bool condition = true; for (size_t i = 0; i < constraints.size(); ++i) { - if (IO::HasParam(constraints[i].first) != constraints[i].second) + if (params.Has(constraints[i].first) != constraints[i].second) { condition = false; break; @@ -243,7 +249,7 @@ inline void ReportIgnoredParam( // If the condition is satisfied, then report that the parameter is ignored // (if the user passed it). - if (condition && IO::HasParam(paramName)) + if (condition && params.Has(paramName)) { // The output will be different depending on whether there are 1, 2, or more // constraints. @@ -288,11 +294,12 @@ inline void ReportIgnoredParam( } } -inline void ReportIgnoredParam(const std::string& paramName, +inline void ReportIgnoredParam(util::Params& params, + const std::string& paramName, const std::string& reason) { // If the argument was passed, we need to print the reason. - if (IO::HasParam(paramName)) + if (params.Has(paramName)) { Log::Warn << PRINT_PARAM_STRING(paramName) << " ignored because " << reason << "!" << std::endl; From 1eae2b39b7ab310c8608631d274f12a16dcfb2d9 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:06:41 -0400 Subject: [PATCH 431/729] Adapt timers to have one per binding call. --- src/mlpack/core/util/timers.cpp | 59 ++++++++++++++++----------------- src/mlpack/core/util/timers.hpp | 31 +++++++++-------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/mlpack/core/util/timers.cpp b/src/mlpack/core/util/timers.cpp index 1d892f7a4a..b93f5731fe 100644 --- a/src/mlpack/core/util/timers.cpp +++ b/src/mlpack/core/util/timers.cpp @@ -19,6 +19,7 @@ #include using namespace mlpack; +using namespace mlpack::util; using namespace std; using namespace chrono; @@ -27,7 +28,7 @@ using namespace chrono; */ void Timer::Start(const string& name) { - IO::GetSingleton().timer.StartTimer(name, this_thread::get_id()); + IO::GetSingleton().timer.Start(name, this_thread::get_id()); } /** @@ -35,7 +36,7 @@ void Timer::Start(const string& name) */ void Timer::Stop(const string& name) { - IO::GetSingleton().timer.StopTimer(name, this_thread::get_id()); + IO::GetSingleton().timer.Stop(name, this_thread::get_id()); } /** @@ -43,7 +44,7 @@ void Timer::Stop(const string& name) */ microseconds Timer::Get(const string& name) { - return IO::GetSingleton().timer.GetTimer(name); + return IO::GetSingleton().timer.Get(name); } // Enable timing. @@ -64,6 +65,11 @@ void Timer::ResetAll() IO::GetSingleton().timer.Reset(); } +std::map Timer::GetAllTimers() +{ + return IO::GetSingleton().timer.GetAllTimers(); +} + // Reset a Timers object. void Timers::Reset() { @@ -79,7 +85,7 @@ map Timers::GetAllTimers() return timers; } -microseconds Timers::GetTimer(const string& timerName) +microseconds Timers::Get(const string& timerName) { if (!enabled) return microseconds(0); @@ -88,23 +94,15 @@ microseconds Timers::GetTimer(const string& timerName) return timers[timerName]; } -bool Timers::GetState(const string& timerName, - const thread::id& threadId) -{ - lock_guard lock(timersMutex); - if (timerStartTime.count(threadId) == 0) - return 0; - return (timerStartTime[threadId].count(timerName) > 0); -} - -void Timers::PrintTimer(const string& timerName) +std::string Timers::Print(const microseconds& totalDuration) { // Convert microseconds to seconds. - microseconds totalDuration = GetTimer(timerName); seconds totalDurationSec = duration_cast(totalDuration); microseconds totalDurationMicroSec = duration_cast(totalDuration % seconds(1)); - Log::Info << totalDurationSec.count() << "." << setw(6) + + std::ostringstream oss; + oss << totalDurationSec.count() << "." << setw(6) << setfill('0') << totalDurationMicroSec.count() << "s"; // Also output convenient day/hr/min/sec. @@ -118,43 +116,44 @@ void Timers::PrintTimer(const string& timerName) if (!(d.count() == 0 && h.count() == 0 && m.count() == 0)) { bool output = false; // Denotes if we have output anything yet. - Log::Info << " ("; + oss << " ("; // Only output units if they have nonzero values (yes, a bit tedious). if (d.count() > 0) { - Log::Info << d.count() << " days"; + oss << d.count() << " days"; output = true; } if (h.count() > 0) { if (output) - Log::Info << ", "; - Log::Info << h.count() << " hrs"; + oss << ", "; + oss << h.count() << " hrs"; output = true; } if (m.count() > 0) { if (output) - Log::Info << ", "; - Log::Info << m.count() << " mins"; + oss << ", "; + oss << m.count() << " mins"; output = true; } if (s.count() > 0) { if (output) - Log::Info << ", "; - Log::Info << s.count() << "." << setw(1) + oss << ", "; + oss << s.count() << "." << setw(1) << (totalDurationMicroSec.count() / 100000) << " secs"; } - Log::Info << ")"; + oss << ")"; } - Log::Info << endl; + oss << endl; + return oss.str(); } void Timers::StopAllTimers() @@ -172,8 +171,8 @@ void Timers::StopAllTimers() timerStartTime.clear(); } -void Timers::StartTimer(const string& timerName, - const thread::id& threadId) +void Timers::Start(const string& timerName, + const thread::id& threadId) { // Don't do anything if we aren't timing. if (!enabled) @@ -201,8 +200,8 @@ void Timers::StartTimer(const string& timerName, timerStartTime[threadId][timerName] = currTime; } -void Timers::StopTimer(const string& timerName, - const thread::id& threadId) +void Timers::Stop(const string& timerName, + const thread::id& threadId) { // Don't do anything if we aren't timing. if (!enabled) diff --git a/src/mlpack/core/util/timers.hpp b/src/mlpack/core/util/timers.hpp index 8316695377..177850de52 100644 --- a/src/mlpack/core/util/timers.hpp +++ b/src/mlpack/core/util/timers.hpp @@ -93,8 +93,15 @@ class Timer * existing timers. */ static void ResetAll(); + + /** + * Returns a copy of all the timers used via this interface. + */ + static std::map GetAllTimers(); }; +namespace util { + class Timers { public: @@ -118,15 +125,15 @@ class Timers * * @param timerName The name of the timer in question. */ - std::chrono::microseconds GetTimer(const std::string& timerName); + std::chrono::microseconds Get(const std::string& timerName); /** * Prints the specified timer. If it took longer than a minute to complete * the timer will be displayed in days, hours, and minutes as well. * - * @param timerName The name of the timer in question. + * @param timerName The number of microseconds to print. */ - void PrintTimer(const std::string& timerName); + static std::string Print(const std::chrono::microseconds& totalDuration); /** * Initializes a timer, available like a normal value specified on @@ -137,8 +144,8 @@ class Timers * @param timerName The name of the timer in question. * @param threadId Id of the thread accessing the timer. */ - void StartTimer(const std::string& timerName, - const std::thread::id& threadId = std::thread::id()); + void Start(const std::string& timerName, + const std::thread::id& threadId = std::thread::id()); /** * Halts the timer, and replaces its value with the delta time from its start. @@ -146,17 +153,8 @@ class Timers * @param timerName The name of the timer in question. * @param threadId Id of the thread accessing the timer. */ - void StopTimer(const std::string& timerName, - const std::thread::id& threadId = std::thread::id()); - - /** - * Returns state of the given timer. - * - * @param timerName The name of the timer in question. - * @param threadId Id of the thread accessing the timer. - */ - bool GetState(const std::string& timerName, - const std::thread::id& threadId = std::thread::id()); + void Stop(const std::string& timerName, + const std::thread::id& threadId = std::thread::id()); /** * Stop all timers. @@ -181,6 +179,7 @@ class Timers std::atomic enabled; }; +} // namespace util } // namespace mlpack #endif // MLPACK_CORE_UTILITIES_TIMERS_HPP From 10cfa634634c1c5d9fd8d2d30d5649f04aabc999 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:07:07 -0400 Subject: [PATCH 432/729] Adapt mlpack_main.hpp for BINDING_TYPE_CLI. --- src/mlpack/core/util/mlpack_main.hpp | 44 ++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index b639e9f442..ec989b8403 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -43,7 +43,8 @@ * PRINT_PARAM_STRING() returns a string that contains the correct * language-specific representation of a parameter's name. */ -#define PRINT_PARAM_STRING mlpack::bindings::cli::ParamString +#define PRINT_PARAM_STRING(x) mlpack::bindings::cli::ParamString( \ + STRINGIFY(BINDING_NAME), x) /** * PRINT_PARAM_VALUE() returns a string that contains a correct @@ -92,26 +93,32 @@ static const std::string testName = ""; #include #include -static void mlpackMain(); // This is typically defined after this include. +#ifndef BINDING_NAME + #error "BINDING_NAME not defined!" +#endif + +static void BINDING_NAME(mlpack::util::Params&, mlpack::util::Timers&); int main(int argc, char** argv) { // Parse the command-line options; put them into CLI. - mlpack::bindings::cli::ParseCommandLine(argc, argv); - // Enable timing. - mlpack::Timer::EnableTiming(); + mlpack::util::Params params = + mlpack::bindings::cli::ParseCommandLine(argc, argv); + // Create a new timer object for this call. + mlpack::util::Timers timers; + timers.Enabled() = true; // A "total_time" timer is run by default for each mlpack program. - mlpack::Timer::Start("total_time"); - - mlpackMain(); + timers.Start("total_time"); + BINDING_NAME(params, timers); + timers.Stop("total_time"); // Print output options, print verbose information, save model parameters, // clean up, and so forth. - mlpack::bindings::cli::EndProgram(); + mlpack::bindings::cli::EndProgram(params, timers); } -#elif(BINDING_TYPE == BINDING_TYPE_TEST) // This is a unit test. +#elif (BINDING_TYPE == BINDING_TYPE_TEST) // This is a unit test. // Matrices are not transposed on load/save. #define BINDING_MATRIX_TRANSPOSED false @@ -212,8 +219,9 @@ using Option = mlpack::bindings::python::PyOption; static const std::string testName = ""; #include -#undef BINDING_NAME -#define BINDING_NAME(NAME) static \ +// TODO: fix this... +#undef BINDING_USER_NAME +#define BINDING_USER_NAME(NAME) static \ mlpack::util::ProgramName \ io_programname_dummy_object = mlpack::util::ProgramName(NAME); \ namespace mlpack { \ @@ -262,8 +270,8 @@ using Option = mlpack::bindings::julia::JuliaOption; static const std::string testName = ""; #include -#undef BINDING_NAME -#define BINDING_NAME(NAME) static \ +#undef BINDING_USER_NAME +#define BINDING_USER_NAME(NAME) static \ mlpack::util::ProgramName \ io_programname_dummy_object = mlpack::util::ProgramName(NAME); \ namespace mlpack { \ @@ -306,8 +314,8 @@ using Option = mlpack::bindings::go::GoOption; static const std::string testName = ""; #include -#undef BINDING_NAME -#define BINDING_NAME(NAME) static \ +#undef BINDING_USER_NAME +#define BINDING_USER_NAME(NAME) static \ mlpack::util::ProgramName \ io_programname_dummy_object = mlpack::util::ProgramName(NAME); \ namespace mlpack { \ @@ -424,13 +432,13 @@ using Option = mlpack::bindings::markdown::MDOption; #include #include -#undef BINDING_NAME +#undef BINDING_USER_NAME #undef BINDING_SHORT_DESC #undef BINDING_LONG_DESC #undef BINDING_EXAMPLE #undef BINDING_SEE_ALSO -#define BINDING_NAME(NAME) static \ +#define BINDING_USER_NAME(NAME) static \ mlpack::bindings::markdown::ProgramNameWrapper \ io_programname_dummy_object = \ mlpack::bindings::markdown::ProgramNameWrapper( \ From 519152d68b45c86986313fe4ec0bf1b1a32c66b6 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:07:17 -0400 Subject: [PATCH 433/729] Add new files to build configuration. --- src/mlpack/core/util/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mlpack/core/util/CMakeLists.txt b/src/mlpack/core/util/CMakeLists.txt index ef21ff91ca..65a467573e 100644 --- a/src/mlpack/core/util/CMakeLists.txt +++ b/src/mlpack/core/util/CMakeLists.txt @@ -21,6 +21,9 @@ set(SOURCES param_checks.hpp param_checks_impl.hpp param_data.hpp + params.hpp + params_impl.hpp + params.cpp prefixedoutstream.hpp prefixedoutstream.cpp prefixedoutstream_impl.hpp From 39322708338a7dd17bbad37c376b4c8cbf4a5682 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:07:31 -0400 Subject: [PATCH 434/729] Re-implement LinearRegression to use thread-local parameters. --- .../linear_regression_main.cpp | 70 ++++++++++--------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/mlpack/methods/linear_regression/linear_regression_main.cpp b/src/mlpack/methods/linear_regression/linear_regression_main.cpp index 13fcacc386..6cec62cf39 100644 --- a/src/mlpack/methods/linear_regression/linear_regression_main.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME linear_regression + #include #include "linear_regression.hpp" @@ -22,7 +28,7 @@ using namespace arma; using namespace std; // Program Name. -BINDING_NAME("Simple Linear Regression and Prediction"); +BINDING_USER_NAME("Simple Linear Regression and Prediction"); // Short description. BINDING_SHORT_DESC( @@ -108,44 +114,44 @@ PARAM_ROW_OUT("output_predictions", "If --test_file is specified, this " PARAM_DOUBLE_IN("lambda", "Tikhonov regularization for ridge regression. If 0," " the method reduces to linear regression.", "l", 0.0); -static void mlpackMain() +static void linear_regression(util::Params& params, util::Timers& timer) { - const double lambda = IO::GetParam("lambda"); + const double lambda = params.Get("lambda"); - RequireOnlyOnePassed({ "training", "input_model" }, true); + RequireOnlyOnePassed(params, { "training", "input_model" }, true); - ReportIgnoredParam({{ "test", true }}, "output_predictions"); + ReportIgnoredParam(params, {{ "test", true }}, "output_predictions"); mat regressors; rowvec responses; LinearRegression* lr; - const bool computeModel = !IO::HasParam("input_model"); - const bool computePrediction = IO::HasParam("test"); + const bool computeModel = !params.Has("input_model"); + const bool computePrediction = params.Has("test"); // If they specified a model file, we also need a test file or we // have nothing to do. if (!computeModel) { - RequireAtLeastOnePassed({ "test" }, true, "test points must be specified " - "when an input model is given"); + RequireAtLeastOnePassed(params, { "test" }, true, "test points must be " + "specified when an input model is given"); } - ReportIgnoredParam({{ "input_model", true }}, "lambda"); + ReportIgnoredParam(params, {{ "input_model", true }}, "lambda"); - RequireAtLeastOnePassed({ "output_model", "output_predictions" }, false, - "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "output_predictions" }, + false, "no output will be saved"); // An input file was given and we need to generate the model. if (computeModel) { - Timer::Start("load_regressors"); - regressors = std::move(IO::GetParam("training")); - Timer::Stop("load_regressors"); + timer.Start("load_regressors"); + regressors = std::move(params.Get("training")); + timer.Stop("load_regressors"); // Are the responses in a separate file? - if (!IO::HasParam("training_responses")) + if (!params.Has("training_responses")) { // The initial predictors for y, Nx1. if (regressors.n_rows < 2) @@ -159,9 +165,9 @@ static void mlpackMain() else { // The initial predictors for y, Nx1. - Timer::Start("load_responses"); - responses = IO::GetParam("training_responses"); - Timer::Stop("load_responses"); + timer.Start("load_responses"); + responses = params.Get("training_responses"); + timer.Stop("load_responses"); if (responses.n_cols != regressors.n_cols) { @@ -170,16 +176,16 @@ static void mlpackMain() } } - Timer::Start("regression"); + timer.Start("regression"); lr = new LinearRegression(regressors, responses, lambda); - Timer::Stop("regression"); + timer.Stop("regression"); } else { // A model file was passed in, so load it. - Timer::Start("load_model"); - lr = IO::GetParam("input_model"); - Timer::Stop("load_model"); + timer.Start("load_model"); + lr = params.Get("input_model"); + timer.Stop("load_model"); } // Did we want to predict, too? @@ -188,13 +194,13 @@ static void mlpackMain() // Cache the output of GetPrintableParam before we std::move() the test // matrix. Loading actually will happen during GetPrintableParam() since // that needs to load to print the size. - Timer::Start("load_test_points"); + timer.Start("load_test_points"); std::ostringstream oss; - oss << IO::GetPrintableParam("test"); + oss << params.GetPrintable("test"); std::string testOutput = oss.str(); - Timer::Stop("load_test_points"); + timer.Stop("load_test_points"); - mat points = std::move(IO::GetParam("test")); + mat points = std::move(params.Get("test")); // Ensure that test file data has the right number of features. if ((lr->Parameters().n_elem - 1) != points.n_rows) @@ -211,14 +217,14 @@ static void mlpackMain() // Perform the predictions using our model. rowvec predictions; - Timer::Start("prediction"); + timer.Start("prediction"); lr->Predict(points, predictions); - Timer::Stop("prediction"); + timer.Stop("prediction"); // Save predictions. - IO::GetParam("output_predictions") = std::move(predictions); + params.Get("output_predictions") = std::move(predictions); } // Save the model if needed. - IO::GetParam("output_model") = lr; + params.Get("output_model") = lr; } From c6b76c25d8cca5cf508fcc804f50b01304c92865 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:07:55 -0400 Subject: [PATCH 435/729] Temporary work to make libmlpack.so compile. --- src/mlpack/bindings/tests/CMakeLists.txt | 4 ++-- src/mlpack/bindings/tests/clean_memory.cpp | 14 +++++++------- src/mlpack/bindings/tests/clean_memory.hpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mlpack/bindings/tests/CMakeLists.txt b/src/mlpack/bindings/tests/CMakeLists.txt index 70b9928f91..8035dcc93d 100644 --- a/src/mlpack/bindings/tests/CMakeLists.txt +++ b/src/mlpack/bindings/tests/CMakeLists.txt @@ -1,8 +1,8 @@ # Define the files we need to compile. # Anything not in this list will not be compiled into mlpack. set(SOURCES - clean_memory.hpp - clean_memory.cpp + #clean_memory.hpp +# clean_memory.cpp test_option.hpp ignore_check.hpp delete_allocated_memory.hpp diff --git a/src/mlpack/bindings/tests/clean_memory.cpp b/src/mlpack/bindings/tests/clean_memory.cpp index 76664b2dba..2d297311cd 100644 --- a/src/mlpack/bindings/tests/clean_memory.cpp +++ b/src/mlpack/bindings/tests/clean_memory.cpp @@ -12,6 +12,7 @@ #include "clean_memory.hpp" #include +#include namespace mlpack { namespace bindings { @@ -20,20 +21,20 @@ namespace tests { /** * Delete any pointers held by the IO object. */ -void CleanMemory() +void CleanMemory(util::Params& params) { // If we are holding any pointers, then we "own" them. But we may hold the // same pointer twice, so we have to be careful to not delete it multiple // times. std::unordered_map memoryAddresses; - auto it = IO::Parameters().begin(); - while (it != IO::Parameters().end()) + auto it = params.Parameters().begin(); + while (it != params.Parameters().end()) { util::ParamData& data = it->second; void* result; - IO::GetSingleton().functionMap[data.tname]["GetAllocatedMemory"](data, - NULL, (void*) &result); + params.functionMap[data.tname]["GetAllocatedMemory"](data, NULL, + (void*) &result); if (result != NULL && memoryAddresses.count(result) == 0) memoryAddresses[result] = &data; @@ -47,8 +48,7 @@ void CleanMemory() { util::ParamData& data = *(it2->second); - IO::GetSingleton().functionMap[data.tname]["DeleteAllocatedMemory"](data, - NULL, NULL); + params.functionMap[data.tname]["DeleteAllocatedMemory"](data, NULL, NULL); ++it2; } diff --git a/src/mlpack/bindings/tests/clean_memory.hpp b/src/mlpack/bindings/tests/clean_memory.hpp index 1ae5e0f84b..e4a96759d6 100644 --- a/src/mlpack/bindings/tests/clean_memory.hpp +++ b/src/mlpack/bindings/tests/clean_memory.hpp @@ -20,7 +20,7 @@ namespace tests { /** * Delete any unique pointers that are held by the IO object. */ -void CleanMemory(); +void CleanMemory(util::Params& params); } // namespace tests } // namespace bindings From 20d42a08436b37cc6f17186de7332c45acd13844 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 22 Jun 2021 19:08:09 -0400 Subject: [PATCH 436/729] Adapt CLI bindings to use thread-local util::Params objects. --- src/mlpack/bindings/cli/add_to_cli11.hpp | 6 +- src/mlpack/bindings/cli/cli_option.hpp | 70 +++++-------------- src/mlpack/bindings/cli/end_program.hpp | 46 +++++++----- .../bindings/cli/parse_command_line.hpp | 37 +++++----- .../bindings/cli/print_doc_functions.hpp | 9 ++- .../bindings/cli/print_doc_functions_impl.hpp | 62 ++++++++-------- src/mlpack/bindings/cli/print_help.cpp | 26 +++---- src/mlpack/bindings/cli/print_help.hpp | 2 +- 8 files changed, 123 insertions(+), 135 deletions(-) diff --git a/src/mlpack/bindings/cli/add_to_cli11.hpp b/src/mlpack/bindings/cli/add_to_cli11.hpp index ceb03c64e2..f052512dc2 100644 --- a/src/mlpack/bindings/cli/add_to_cli11.hpp +++ b/src/mlpack/bindings/cli/add_to_cli11.hpp @@ -24,7 +24,7 @@ namespace cli { /** * Add a tuple option to CLI11. - * + * * @param cliName The name of the option to add to CLI11. * @param param an object of util::ParamData. * @param app A CLI11 object to add parameter to. @@ -56,7 +56,7 @@ void AddToCLI11(const std::string& cliName, /** * Add a serializable option to CLI11. - * + * * @param cliName The name of the option to add to CLI11. * @param param an object of util::ParamData. * @param app a CLI11 object to add parameter to. @@ -118,7 +118,7 @@ void AddToCLI11(const std::string& cliName, /** * Add an option to CLI11. - * + * * @param cliName The name of the option to add to CLI11. * @param param an object of util::ParamData. * @param app a CLI11 object to add parameter to. diff --git a/src/mlpack/bindings/cli/cli_option.hpp b/src/mlpack/bindings/cli/cli_option.hpp index eeebc2d7cc..107a65c506 100644 --- a/src/mlpack/bindings/cli/cli_option.hpp +++ b/src/mlpack/bindings/cli/cli_option.hpp @@ -63,7 +63,8 @@ class CLIOption * @param input Whether or not the option is an input option. * @param noTranspose If the parameter is a matrix and this is true, then the * matrix will not be transposed on loading. - * @param * (testName) Is not used and added for compatibility reasons. + * @param bindingName Name of the binding that this option is for. If empty, + * then it will be added to every binding. */ CLIOption(const N defaultValue, const std::string& identifier, @@ -73,7 +74,7 @@ class CLIOption const bool required = false, const bool input = true, const bool noTranspose = false, - const std::string& /*testName*/ = "") + const std::string& bindingName = "") { // Create the ParamData object to give to CLI. util::ParamData data; @@ -109,58 +110,23 @@ class CLIOption std::string progOptId = (alias[0] != '\0') ? "-" + std::string(1, alias[0]) + ",--" + cliName : "--" + cliName; - // Do a check to ensure that the boost name isn't already in use. - const std::map& parameters = - IO::Parameters(); - if (parameters.count(cliName) > 0) - { - // Create a fake Log::Fatal since it may not yet be initialized. - // Temporarily define color code escape sequences. - #ifndef _WIN32 - #define BASH_RED "\033[0;31m" - #define BASH_CLEAR "\033[0m" - #else - #define BASH_RED "" - #define BASH_CLEAR "" - #endif - - // Temporary outstream object for detecting duplicate identifiers. - util::PrefixedOutStream outstr(std::cerr, - BASH_RED "[FATAL] " BASH_CLEAR, false, true /* fatal */); - - #undef BASH_RED - #undef BASH_CLEAR - - outstr << "Parameter --" << cliName << " (" << data.alias << ") " - << "is defined multiple times with the same identifiers." - << std::endl; - } - - IO::Add(std::move(data)); + IO::AddParameter(bindingName, std::move(data)); // Set some function pointers that we need. - IO::GetSingleton().functionMap[tname]["DefaultParam"] = - &DefaultParam; - IO::GetSingleton().functionMap[tname]["OutputParam"] = - &OutputParam; - IO::GetSingleton().functionMap[tname]["GetPrintableParam"] = - &GetPrintableParam; - IO::GetSingleton().functionMap[tname]["StringTypeParam"] = - &StringTypeParam; - IO::GetSingleton().functionMap[tname]["GetParam"] = &GetParam; - IO::GetSingleton().functionMap[tname]["GetRawParam"] = &GetRawParam; - IO::GetSingleton().functionMap[tname]["AddToCLI11"] = &AddToCLI11; - IO::GetSingleton().functionMap[tname]["MapParameterName"] = - &MapParameterName; - IO::GetSingleton().functionMap[tname]["GetPrintableParamName"] = - &GetPrintableParamName; - IO::GetSingleton().functionMap[tname]["GetPrintableParamValue"] = - &GetPrintableParamValue; - IO::GetSingleton().functionMap[tname]["GetAllocatedMemory"] = - &GetAllocatedMemory; - IO::GetSingleton().functionMap[tname]["DeleteAllocatedMemory"] = - &DeleteAllocatedMemory; - IO::GetSingleton().functionMap[tname]["InPlaceCopy"] = &InPlaceCopy; + IO::AddFunction(tname, "DefaultParam", &DefaultParam); + IO::AddFunction(tname, "OutputParam", &OutputParam); + IO::AddFunction(tname, "GetPrintableParam", &GetPrintableParam); + IO::AddFunction(tname, "StringTypeParam", &StringTypeParam); + IO::AddFunction(tname, "GetParam", &GetParam); + IO::AddFunction(tname, "GetRawParam", &GetRawParam); + IO::AddFunction(tname, "AddToCLI11", &AddToCLI11); + IO::AddFunction(tname, "MapParameterName", &MapParameterName); + IO::AddFunction(tname, "GetPrintableParamName", &GetPrintableParamName); + IO::AddFunction(tname, "GetPrintableParamValue", + &GetPrintableParamValue); + IO::AddFunction(tname, "GetAllocatedMemory", &GetAllocatedMemory); + IO::AddFunction(tname, "DeleteAllocatedMemory", &DeleteAllocatedMemory); + IO::AddFunction(tname, "InPlaceCopy", &InPlaceCopy); } }; diff --git a/src/mlpack/bindings/cli/end_program.hpp b/src/mlpack/bindings/cli/end_program.hpp index 7fa5b112f9..6a79d9f65c 100644 --- a/src/mlpack/bindings/cli/end_program.hpp +++ b/src/mlpack/bindings/cli/end_program.hpp @@ -23,21 +23,21 @@ namespace cli { * Handle command-line program termination. If --help or --info was passed, we * won't make it here, so we don't have to write any contingencies for that. */ -inline void EndProgram() +inline void EndProgram(util::Params& params, util::Timers& timers) { - // Stop the CLI timers. - IO::GetSingleton().timer.StopAllTimers(); + // Stop the timers. + timers.StopAllTimers(); // Print any output. - std::map& parameters = IO::Parameters(); + std::map& parameters = params.Parameters(); for (auto& it : parameters) { util::ParamData& d = it.second; if (!d.input) - IO::GetSingleton().functionMap[d.tname]["OutputParam"](d, NULL, NULL); + params.functionMap[d.tname]["OutputParam"](d, NULL, NULL); } - if (IO::HasParam("verbose")) + if (params.Has("verbose")) { Log::Info << std::endl << "Execution parameters:" << std::endl; @@ -48,21 +48,34 @@ inline void EndProgram() // We can handle strings, ints, bools, doubles. util::ParamData& data = it.second; std::string cliName; - IO::GetSingleton().functionMap[data.tname]["MapParameterName"](data, - NULL, (void*) &cliName); + params.functionMap[data.tname]["MapParameterName"](data, NULL, + (void*) &cliName); Log::Info << " " << cliName << ": "; std::string printableParam; - IO::GetSingleton().functionMap[data.tname]["GetPrintableParam"](data, - NULL, (void*) &printableParam); + params.functionMap[data.tname]["GetPrintableParam"](data, NULL, + (void*) &printableParam); Log::Info << printableParam << std::endl; } Log::Info << "Program timers:" << std::endl; - for (auto& it2 : IO::GetSingleton().timer.GetAllTimers()) + + // Merge the global timers with the binding-specific ones. + std::map timerMap = + timers.GetAllTimers(); + std::map globalTimerMap = + Timer::GetAllTimers(); + for (auto& it : globalTimerMap) { - Log::Info << " " << it2.first << ": "; - IO::GetSingleton().timer.PrintTimer(it2.first); + if (timerMap.count(it.first) == 1) + timerMap[it.first] += it.second; + else + timerMap[it.first] = it.second; + } + + for (auto& it2 : timerMap) + { + Log::Info << " " << it2.first << ": " << timers.Print(it2.second); } } @@ -75,8 +88,8 @@ inline void EndProgram() util::ParamData& data = it.second; void* result; - IO::GetSingleton().functionMap[data.tname]["GetAllocatedMemory"](data, - NULL, (void*) &result); + params.functionMap[data.tname]["GetAllocatedMemory"](data, NULL, + (void*) &result); if (result != NULL && memoryAddresses.count(result) == 0) memoryAddresses[result] = &data; } @@ -88,8 +101,7 @@ inline void EndProgram() { util::ParamData& data = *(it2->second); - IO::GetSingleton().functionMap[data.tname]["DeleteAllocatedMemory"](data, - NULL, NULL); + params.functionMap[data.tname]["DeleteAllocatedMemory"](data, NULL, NULL); ++it2; } diff --git a/src/mlpack/bindings/cli/parse_command_line.hpp b/src/mlpack/bindings/cli/parse_command_line.hpp index 381d749bc1..129dd93722 100644 --- a/src/mlpack/bindings/cli/parse_command_line.hpp +++ b/src/mlpack/bindings/cli/parse_command_line.hpp @@ -33,27 +33,26 @@ PARAM_FLAG("version", "Display the version of mlpack.", "V"); * Parse the command line, setting all of the options inside of the CLI object * to their appropriate given values. */ -void ParseCommandLine(int argc, char** argv) +mlpack::util::Params ParseCommandLine(int argc, char** argv) { // First, we need to build the CLI11 variables for parsing. CLI::App app; app.set_help_flag(); + // Get an empty Params object that will hold all of the parameters for this + // call. + mlpack::util::Params params = IO::Parameters(STRINGIFY(BINDING_NAME)); // Go through list of options in order to add them. - std::map& parameters = IO::Parameters(); + std::map& parameters = params.Parameters(); using ItType = std::map::iterator; for (ItType it = parameters.begin(); it != parameters.end(); ++it) { // Add the parameter to desc. util::ParamData& d = it->second; - IO::GetSingleton().functionMap[d.tname]["AddToCLI11"](d, NULL, (void*) - &app); + params.functionMap[d.tname]["AddToCLI11"](d, NULL, (void*) &app); } - // Mark that we did parsing. - IO::GetSingleton().didParse = true; - // Parse the command line, then place the values in the right place. try { @@ -85,37 +84,37 @@ void ParseCommandLine(int argc, char** argv) // --info), handle those. // --version is prioritized over --help. - if (IO::HasParam("version")) + if (params.Has("version")) { - std::cout << IO::GetSingleton().ProgramName() << ": part of " - << util::GetVersion() << "." << std::endl; + std::cout << params.Doc().name << ": part of " << util::GetVersion() << "." + << std::endl; exit(0); // Don't do anything else. } // Default help message. - if (IO::HasParam("help")) + if (params.Has("help")) { Log::Info.ignoreInput = false; - PrintHelp(); + PrintHelp(params); exit(0); // The user doesn't want to run the program, he wants help. } // Info on a specific parameter. - if (IO::HasParam("info")) + if (params.Has("info")) { Log::Info.ignoreInput = false; - std::string str = IO::GetParam("info"); + std::string str = params.Get("info"); // The info node should always be there, but the user may not have specified // anything. if (str != "") { - PrintHelp(str); + PrintHelp(params, str); exit(0); } // Otherwise just print the generalized help. - PrintHelp(); + PrintHelp(params); exit(0); } @@ -123,7 +122,7 @@ void ParseCommandLine(int argc, char** argv) // if we have not compiled in debugging mode. Log::Debug << "Compiled with debugging symbols." << std::endl; - if (IO::HasParam("verbose")) + if (params.Has("verbose")) { // Give [INFO ] output. Log::Info.ignoreInput = false; @@ -138,7 +137,7 @@ void ParseCommandLine(int argc, char** argv) { // CLI11 expects the parameter name to have "--" prepended. std::string cliName; - IO::GetSingleton().functionMap[d.tname]["MapParameterName"](d, NULL, + params.functionMap[d.tname]["MapParameterName"](d, NULL, (void*) &cliName); cliName = "--" + cliName; @@ -149,6 +148,8 @@ void ParseCommandLine(int argc, char** argv) } } } + + return params; } } // namespace cli diff --git a/src/mlpack/bindings/cli/print_doc_functions.hpp b/src/mlpack/bindings/cli/print_doc_functions.hpp index 1f7e9390bb..63cf52575e 100644 --- a/src/mlpack/bindings/cli/print_doc_functions.hpp +++ b/src/mlpack/bindings/cli/print_doc_functions.hpp @@ -55,7 +55,8 @@ inline std::string PrintValue(const T& value, bool quotes); /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName); +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName); /** * Print a dataset type parameter (add .csv and return). @@ -82,7 +83,8 @@ inline std::string ProcessOptions(); * Print an option for a command-line argument. */ template -std::string ProcessOptions(const std::string& paramName, +std::string ProcessOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args); @@ -106,7 +108,8 @@ inline std::string ProgramCall(const std::string& programName); * that all of the PARAM_*() declarataions need to come before * BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.) */ -inline std::string ParamString(const std::string& paramName); +inline std::string ParamString(const std::string& bindingName, + const std::string& paramName); /** * Return whether or not a runtime check on parameters should be ignored. We diff --git a/src/mlpack/bindings/cli/print_doc_functions_impl.hpp b/src/mlpack/bindings/cli/print_doc_functions_impl.hpp index fe100fe2ad..ae6911f99f 100644 --- a/src/mlpack/bindings/cli/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/cli/print_doc_functions_impl.hpp @@ -90,16 +90,17 @@ inline std::string PrintValue(const std::vector& value, bool quotes) /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName) +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName) { - if (IO::Parameters().count(paramName) == 0) + util::Params p = IO::Parameters(bindingName); + if (p.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; std::string defaultValue; - IO::GetSingleton().functionMap[d.tname]["DefaultParam"](d, NULL, - (void*) &defaultValue); + p.functionMap[d.tname]["DefaultParam"](d, NULL, (void*) &defaultValue); return defaultValue; } @@ -121,32 +122,33 @@ inline std::string PrintModel(const std::string& model) } // Base case for recursion. -inline std::string ProcessOptions() { return ""; } +inline std::string ProcessOptions(util::Params& /* params */) { return ""; } /** * Print an option for a command-line argument. */ template -std::string ProcessOptions(const std::string& paramName, +std::string ProcessOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args) { // See if it is part of the program. std::string result = ""; - if (IO::Parameters().count(paramName) > 0) + if (params.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; std::string name; - IO::GetSingleton().functionMap[d.tname]["GetPrintableParamName"](d, NULL, + params.functionMap[d.tname]["GetPrintableParamName"](d, NULL, (void*) &name); std::ostringstream ossValue; ossValue << value; std::string rawValue = ossValue.str(); std::string fullValue; - IO::GetSingleton().functionMap[d.tname]["GetPrintableParamValue"](d, - (void*) &rawValue, (void*) &fullValue); + params.functionMap[d.tname]["GetPrintableParamValue"](d, (void*) &rawValue, + (void*) &fullValue); std::ostringstream oss; if (d.tname != TYPENAME(bool)) @@ -162,7 +164,7 @@ std::string ProcessOptions(const std::string& paramName, + " and BINDING_EXAMPLE() declaration."); } - std::string rest = ProcessOptions(args...); + std::string rest = ProcessOptions(params, args...); if (rest != "") result += " " + rest; @@ -176,8 +178,9 @@ std::string ProcessOptions(const std::string& paramName, template std::string ProgramCall(const std::string& programName, Args... args) { + util::Params params = IO::Parameters(programName); return util::HyphenateString("$ " + GetBindingName(programName) + " " + - ProcessOptions(args...), 2); + ProcessOptions(params, args...), 2); } /** @@ -190,7 +193,8 @@ inline std::string ProgramCall(const std::string& programName) oss << "$ " << GetBindingName(programName); // Handle all options---first input options, then output options. - std::map& parameters = IO::Parameters(); + util::Params p = IO::Parameters(programName); + std::map& parameters = p.Parameters(); for (auto& it : parameters) { @@ -199,12 +203,12 @@ inline std::string ProgramCall(const std::string& programName) // Otherwise, print the name and the default value. std::string name; - IO::GetSingleton().functionMap[it.second.tname]["GetPrintableParamName"]( - it.second, NULL, (void*) &name); + p.functionMap[it.second.tname]["GetPrintableParamName"]( it.second, NULL, + (void*) &name); std::string value; - IO::GetSingleton().functionMap[it.second.tname]["DefaultParam"]( - it.second, NULL, (void*) &value); + p.functionMap[it.second.tname]["DefaultParam"]( it.second, NULL, + (void*) &value); if (value == "''") value = ""; @@ -228,12 +232,12 @@ inline std::string ProgramCall(const std::string& programName) // Otherwise, print the name and the default value. std::string name; - IO::GetSingleton().functionMap[it.second.tname]["GetPrintableParamName"]( - it.second, NULL, (void*) &name); + p.functionMap[it.second.tname]["GetPrintableParamName"]( it.second, NULL, + (void*) &name); std::string value; - IO::GetSingleton().functionMap[it.second.tname]["DefaultParam"]( - it.second, NULL, (void*) &value); + p.functionMap[it.second.tname]["DefaultParam"]( it.second, NULL, + (void*) &value); if (value == "''") value = ""; @@ -253,16 +257,18 @@ inline std::string ProgramCall(const std::string& programName) * that all of the PARAM_*() declarataions need to come before * BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.) */ -inline std::string ParamString(const std::string& paramName) +inline std::string ParamString(const std::string& bindingName, + const std::string& paramName) { + util::Params p = IO::Parameters(bindingName); + // Return the correct parameter name. - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; std::string output; - IO::GetSingleton().functionMap[d.tname]["GetPrintableParamName"](d, NULL, - (void*) &output); + p.functionMap[d.tname]["GetPrintableParamName"](d, NULL, (void*) &output); // Is there an alias? std::string alias = ""; if (d.alias != '\0') diff --git a/src/mlpack/bindings/cli/print_help.cpp b/src/mlpack/bindings/cli/print_help.cpp index a1cf44089f..34c82ab0b7 100644 --- a/src/mlpack/bindings/cli/print_help.cpp +++ b/src/mlpack/bindings/cli/print_help.cpp @@ -20,12 +20,12 @@ namespace bindings { namespace cli { /* Prints the descriptions of the current hierarchy. */ -void PrintHelp(const std::string& param) +void PrintHelp(util::Params& params, const std::string& param) { std::string usedParam = param; - std::map& parameters = IO::Parameters(); - const std::map& aliases = IO::Aliases(); - util::BindingDetails& bindingDetails = IO::GetSingleton().doc; + std::map& parameters = params.Parameters(); + const std::map& aliases = params.Aliases(); + const util::BindingDetails& bindingDetails = params.Doc(); // If we pass a single param, alias it if necessary. if (usedParam.length() == 1 && aliases.count(usedParam[0])) usedParam = aliases.at(usedParam[0]); @@ -39,7 +39,7 @@ void PrintHelp(const std::string& param) // Figure out the name of the type. std::string printableType; - IO::GetSingleton().functionMap[data.tname]["StringTypeParam"](data, NULL, + params.functionMap[data.tname]["StringTypeParam"](data, NULL, (void*) &printableType); std::string type = " [" + printableType + "]"; @@ -63,9 +63,9 @@ void PrintHelp(const std::string& param) } // Print out the descriptions. - if (bindingDetails.programName != "") + if (bindingDetails.name != "") { - std::cout << bindingDetails.programName << std::endl << std::endl; + std::cout << bindingDetails.name << std::endl << std::endl; std::cout << " " << util::HyphenateString(bindingDetails.longDescription(), 2) << std::endl << std::endl; for (size_t j = 0; j < bindingDetails.example.size(); ++j) @@ -85,8 +85,8 @@ void PrintHelp(const std::string& param) { util::ParamData& data = iter.second; const std::string key; - IO::GetSingleton().functionMap[data.tname]["MapParameterName"](data, - NULL, (void*) &key); + params.functionMap[data.tname]["MapParameterName"](data, NULL, + (void*) &key); std::string desc = data.desc; std::string alias = (iter.second.alias != '\0') ? @@ -125,15 +125,15 @@ void PrintHelp(const std::string& param) data.cppType == "std::vector")) { std::string defaultValue; - IO::GetSingleton().functionMap[data.tname]["DefaultParam"](data, - NULL, (void*) &defaultValue); + params.functionMap[data.tname]["DefaultParam"](data, NULL, + (void*) &defaultValue); desc += " Default value " + defaultValue + "."; } // Now, print the descriptions. std::string printableType; - IO::GetSingleton().functionMap[data.tname]["StringTypeParam"](data, - NULL, (void*) &printableType); + params.functionMap[data.tname]["StringTypeParam"](data, NULL, + (void*) &printableType); std::string type = " [" + printableType + "]"; std::string fullDesc = " --" + key + alias + type + " "; diff --git a/src/mlpack/bindings/cli/print_help.hpp b/src/mlpack/bindings/cli/print_help.hpp index 9f1cefb2dd..054123e72b 100644 --- a/src/mlpack/bindings/cli/print_help.hpp +++ b/src/mlpack/bindings/cli/print_help.hpp @@ -24,7 +24,7 @@ namespace cli { * * @param param Parameter name to print help for. */ -void PrintHelp(const std::string& param = ""); +void PrintHelp(util::Params& params, const std::string& param = ""); } // namespace cli } // namespace bindings From 08f9f2e33e1c266f5406c680e5d78600181a2ced Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 23 Jun 2021 13:57:56 -0400 Subject: [PATCH 437/729] Use BINDING_NAME() for the main function. --- src/mlpack/methods/linear_regression/linear_regression_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/linear_regression/linear_regression_main.cpp b/src/mlpack/methods/linear_regression/linear_regression_main.cpp index 6cec62cf39..a01baf8e63 100644 --- a/src/mlpack/methods/linear_regression/linear_regression_main.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression_main.cpp @@ -114,7 +114,7 @@ PARAM_ROW_OUT("output_predictions", "If --test_file is specified, this " PARAM_DOUBLE_IN("lambda", "Tikhonov regularization for ridge regression. If 0," " the method reduces to linear regression.", "l", 0.0); -static void linear_regression(util::Params& params, util::Timers& timer) +static void BINDING_NAME(util::Params& params, util::Timers& timer) { const double lambda = params.Get("lambda"); From f1b5ae05334945ae8ecdb35f70bc2fbe5e5e838f Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 23 Jun 2021 15:47:48 -0400 Subject: [PATCH 438/729] Remove all main tests except linear_regression_main_test.cpp. --- src/mlpack/tests/CMakeLists.txt | 92 ++++++++++++++++----------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 2119879ab7..16f5020b8a 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -128,53 +128,53 @@ add_executable(mlpack_test union_find_test.cpp vantage_point_tree_test.cpp wgan_test.cpp - main_tests/adaboost_test.cpp - main_tests/approx_kfn_test.cpp - main_tests/bayesian_linear_regression_test.cpp - main_tests/cf_test.cpp - main_tests/dbscan_test.cpp - main_tests/decision_tree_test.cpp - main_tests/det_test.cpp - main_tests/emst_test.cpp - main_tests/fastmks_test.cpp - main_tests/gmm_generate_test.cpp - main_tests/gmm_probability_test.cpp - main_tests/gmm_train_test.cpp - main_tests/hmm_generate_test.cpp - main_tests/hmm_loglik_test.cpp - main_tests/hmm_test_utils.hpp - main_tests/hmm_train_test.cpp - main_tests/hmm_viterbi_test.cpp - main_tests/hoeffding_tree_test.cpp - main_tests/image_converter_test.cpp - main_tests/kde_test.cpp - main_tests/kernel_pca_test.cpp - main_tests/kfn_test.cpp - main_tests/kmeans_test.cpp - main_tests/knn_test.cpp - main_tests/krann_test.cpp +# main_tests/adaboost_test.cpp +# main_tests/approx_kfn_test.cpp +# main_tests/bayesian_linear_regression_test.cpp +# main_tests/cf_test.cpp +# main_tests/dbscan_test.cpp +# main_tests/decision_tree_test.cpp +# main_tests/det_test.cpp +# main_tests/emst_test.cpp +# main_tests/fastmks_test.cpp +# main_tests/gmm_generate_test.cpp +# main_tests/gmm_probability_test.cpp +# main_tests/gmm_train_test.cpp +# main_tests/hmm_generate_test.cpp +# main_tests/hmm_loglik_test.cpp +# main_tests/hmm_test_utils.hpp +# main_tests/hmm_train_test.cpp +# main_tests/hmm_viterbi_test.cpp +# main_tests/hoeffding_tree_test.cpp +# main_tests/image_converter_test.cpp +# main_tests/kde_test.cpp +# main_tests/kernel_pca_test.cpp +# main_tests/kfn_test.cpp +# main_tests/kmeans_test.cpp +# main_tests/knn_test.cpp +# main_tests/krann_test.cpp main_tests/linear_regression_test.cpp - main_tests/lmnn_test.cpp - main_tests/linear_svm_test.cpp - 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/nca_test.cpp - main_tests/nmf_test.cpp - main_tests/pca_test.cpp - main_tests/perceptron_test.cpp - main_tests/preprocess_binarize_test.cpp - main_tests/preprocess_imputer_test.cpp - main_tests/preprocess_one_hot_encode_test.cpp - main_tests/preprocess_scale_test.cpp - main_tests/preprocess_split_test.cpp - main_tests/radical_test.cpp - main_tests/random_forest_test.cpp - main_tests/softmax_regression_test.cpp - main_tests/sparse_coding_test.cpp - main_tests/range_search_test.cpp +# main_tests/lmnn_test.cpp +# main_tests/linear_svm_test.cpp +# 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/nca_test.cpp +# main_tests/nmf_test.cpp +# main_tests/pca_test.cpp +# main_tests/perceptron_test.cpp +# main_tests/preprocess_binarize_test.cpp +# main_tests/preprocess_imputer_test.cpp +# main_tests/preprocess_one_hot_encode_test.cpp +# main_tests/preprocess_scale_test.cpp +# main_tests/preprocess_split_test.cpp +# main_tests/radical_test.cpp +# main_tests/random_forest_test.cpp +# main_tests/softmax_regression_test.cpp +# main_tests/sparse_coding_test.cpp +# main_tests/range_search_test.cpp main_tests/test_helper.hpp ) From ce913710dec2b973953e3366a79a760d14b4bb74 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 23 Jun 2021 15:48:42 -0400 Subject: [PATCH 439/729] These two tests will need to be reworked, too. --- src/mlpack/tests/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 16f5020b8a..332b676687 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -22,7 +22,7 @@ add_executable(mlpack_test block_krylov_svd_test.cpp callback_test.cpp cf_test.cpp - cli_binding_test.cpp +# cli_binding_test.cpp convolutional_network_test.cpp convolution_test.cpp cosine_tree_test.cpp @@ -47,7 +47,7 @@ add_executable(mlpack_test image_load_test.cpp imputation_test.cpp init_rules_test.cpp - io_test.cpp +# io_test.cpp kde_test.cpp kernel_pca_test.cpp kernel_test.cpp From 6f0ee6d0147e30fbfd70892bf4a95bfa0a1c7cbb Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 24 Jun 2021 20:21:06 +0530 Subject: [PATCH 440/729] Update src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp Co-authored-by: kartikdutt18 <39593019+kartikdutt18@users.noreply.github.com> --- src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp index 6fda08704d..19062df91a 100644 --- a/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/channel_shuffle_impl.hpp @@ -83,7 +83,6 @@ void ChannelShuffle::Forward( } } } - } template From bff82395b2e1b8059d6ff7c15532b9ab533bdec3 Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Fri, 25 Jun 2021 00:07:47 +0530 Subject: [PATCH 441/729] changed program_doc_functions and py_option --- .../python/print_doc_functions_impl.hpp | 57 ++++++++++++------- src/mlpack/bindings/python/py_option.hpp | 40 +++++-------- 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp index 577ff6f958..8997e02bdc 100644 --- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp @@ -107,15 +107,18 @@ inline std::string PrintValue(const bool& value, bool quotes) /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName) +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName) { - if (IO::Parameters().count(paramName) == 0) + util::Params p = IO::Parameters(bindingName); + + if (p.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; std::string defaultValue; - IO::GetSingleton().functionMap[d.tname]["DefaultParam"](d, NULL, + p.functionMap[d.tname]["DefaultParam"](d, NULL, (void*) &defaultValue); return defaultValue; @@ -130,15 +133,18 @@ std::string PrintInputOptions() { return ""; } * something like x=5. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(const std::string& bindingName, + const std::string& paramName, const T& value, Args... args) { + util::Params p = IO::Parameters(bindingName); + // See if this is part of the program. std::string result = ""; - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; if (d.input) { // Print the input option. @@ -173,15 +179,18 @@ std::string PrintInputOptions(const std::string& paramName, inline std::string PrintOutputOptions() { return ""; } template -std::string PrintOutputOptions(const std::string& paramName, +std::string PrintOutputOptions(const std::string& bindingName, + const std::string& paramName, const T& value, Args... args) { + util::Params p = IO::Parameters(bindingName); + // See if this is part of the program. std::string result = ""; - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; if (!d.input) { // Print a new line for the output option. @@ -244,13 +253,15 @@ std::string ProgramCall(const std::string& programName, Args... args) * Given the name of a binding, print a program call assuming that all options * are specified. The programName should not be the output of GetBindingName(). */ -inline std::string ProgramCall(const std::string& programName) +inline std::string ProgramCall(const std::string& programName) // TODO: here programName is the bindingName?? { + util::Params p = IO::Parameters()[programName]; + std::ostringstream oss; oss << ">>> "; // Determine if we have any output options. - std::map& parameters = IO::Parameters(); + std::map& parameters = p.Parameters(); bool hasOutput = false; for (auto it = parameters.begin(); it != parameters.end(); ++it) { @@ -286,7 +297,7 @@ inline std::string ProgramCall(const std::string& programName) oss << it->second.name << "_="; std::string value; - IO::GetSingleton().functionMap[it->second.tname]["DefaultParam"]( + p.functionMap[it->second.tname]["DefaultParam"]( it->second, NULL, (void*) &value); oss << value; } @@ -367,16 +378,21 @@ inline std::string ParamString(const std::string& paramName, const T& value) return oss.str(); } -inline bool IgnoreCheck(const std::string& paramName) +inline bool IgnoreCheck(const std::string& bindingName, + const std::string& paramName) { - return !IO::Parameters()[paramName].input; + util::Params p = IO::Parameters(bindingName); + return !p.Parameters()[paramName].input; } -inline bool IgnoreCheck(const std::vector& constraints) +inline bool IgnoreCheck(const std::string& bindingName, + const std::vector& constraints) { + util::Params p = IO::Parameters(bindingName); + for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i]].input) + if (!p.Parameters()[constraints[i]].input) return true; } @@ -384,16 +400,19 @@ inline bool IgnoreCheck(const std::vector& constraints) } inline bool IgnoreCheck( + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName) { + util::Params p = IO::Parameters(bindingName); + for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i].first].input) + if (!p.Parameters()[constraints[i].first].input) return true; } - return !IO::Parameters()[paramName].input; + return !p.Parameters()[paramName].input; } } // namespace python diff --git a/src/mlpack/bindings/python/py_option.hpp b/src/mlpack/bindings/python/py_option.hpp index b3d8519f84..e698feb9e9 100644 --- a/src/mlpack/bindings/python/py_option.hpp +++ b/src/mlpack/bindings/python/py_option.hpp @@ -50,7 +50,7 @@ class PyOption const bool required = false, const bool input = true, const bool noTranspose = false, - const std::string& /*testName*/ = "") + const std::string& bindingName = "") { // Create the ParamData object to give to IO. util::ParamData data; @@ -76,39 +76,25 @@ class PyOption // Every parameter we'll get from Python will have the correct type. data.value = boost::any(defaultValue); - // Restore the parameters for this program. - if (identifier != "verbose" && identifier != "copy_all_inputs") - IO::RestoreSettings(programName, false); - // Set the function pointers that we'll need. All of these function // pointers will be used by both the program that generates the pyx, and // also the binding itself. (The binding itself will only use GetParam, // GetPrintableParam, and GetRawParam.) - IO::GetSingleton().functionMap[data.tname]["GetParam"] = &GetParam; - IO::GetSingleton().functionMap[data.tname]["GetPrintableParam"] = - &GetPrintableParam; - - IO::GetSingleton().functionMap[data.tname]["DefaultParam"] = - &DefaultParam; + IO::AddFunction(tname, "GetParam", &GetParam); + IO::AddFunction(tname, "GetPrintableParam", &GetPrintableParam); + IO::AddFunction(tname, "DefaultParam", &DefaultParam); // These are used by the pyx generator. - IO::GetSingleton().functionMap[data.tname]["PrintClassDefn"] = - &PrintClassDefn; - IO::GetSingleton().functionMap[data.tname]["PrintDefn"] = &PrintDefn; - IO::GetSingleton().functionMap[data.tname]["PrintDoc"] = &PrintDoc; - IO::GetSingleton().functionMap[data.tname]["PrintOutputProcessing"] = - &PrintOutputProcessing; - IO::GetSingleton().functionMap[data.tname]["PrintInputProcessing"] = - &PrintInputProcessing; - IO::GetSingleton().functionMap[data.tname]["ImportDecl"] = &ImportDecl; + IO::AddFunction(tname, "PrintClassDefn", &PrintClassDefn); + IO::AddFunction(tname, "PrintDefn", &PrintDefn); + IO::AddFunction(tname, "PrintDoc", &PrintDoc); + IO::AddFunction(tname, "PrintOutputProcessing", &PrintOutputProcessing); + IO::AddFunction(tname, "PrintInputProcessing", &PrintInputProcessing); + IO::AddFunction(tname, "ImportDecl", &ImportDecl); - // Add the ParamData object, then store. This is necessary because we may - // import more than one .so that uses IO, so we have to keep the options - // separate. programName is a global variable from mlpack_main.hpp. - IO::Add(std::move(data)); - if (identifier != "verbose" && identifier != "copy_all_inputs") - IO::StoreSettings(programName); - IO::ClearSettings(); + // Add the ParamData object to the IO class + // for the correct binding name. + IO::AddParameter(bindingName, std::move(data)); } }; From 33adf02ed880c76d3df2adea5f1c713e841de3c6 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 25 Jun 2021 10:14:16 -0400 Subject: [PATCH 442/729] Make LinearRegressionMainTest compile successfully. --- src/mlpack/bindings/tests/CMakeLists.txt | 4 +- src/mlpack/bindings/tests/clean_memory.hpp | 2 + src/mlpack/bindings/tests/test_option.hpp | 27 ++----- src/mlpack/tests/CMakeLists.txt | 4 +- .../main_tests/linear_regression_test.cpp | 78 +++++++------------ src/mlpack/tests/main_tests/test_helper.hpp | 39 ---------- 6 files changed, 41 insertions(+), 113 deletions(-) delete mode 100644 src/mlpack/tests/main_tests/test_helper.hpp diff --git a/src/mlpack/bindings/tests/CMakeLists.txt b/src/mlpack/bindings/tests/CMakeLists.txt index 8035dcc93d..70b9928f91 100644 --- a/src/mlpack/bindings/tests/CMakeLists.txt +++ b/src/mlpack/bindings/tests/CMakeLists.txt @@ -1,8 +1,8 @@ # Define the files we need to compile. # Anything not in this list will not be compiled into mlpack. set(SOURCES - #clean_memory.hpp -# clean_memory.cpp + clean_memory.hpp + clean_memory.cpp test_option.hpp ignore_check.hpp delete_allocated_memory.hpp diff --git a/src/mlpack/bindings/tests/clean_memory.hpp b/src/mlpack/bindings/tests/clean_memory.hpp index e4a96759d6..5e642ad6a6 100644 --- a/src/mlpack/bindings/tests/clean_memory.hpp +++ b/src/mlpack/bindings/tests/clean_memory.hpp @@ -13,6 +13,8 @@ #ifndef MLPACK_BINDINGS_TESTS_CLEAN_MEMORY_HPP #define MLPACK_BINDINGS_TESTS_CLEAN_MEMORY_HPP +#include + namespace mlpack { namespace bindings { namespace tests { diff --git a/src/mlpack/bindings/tests/test_option.hpp b/src/mlpack/bindings/tests/test_option.hpp index 206126f958..75f4e30784 100644 --- a/src/mlpack/bindings/tests/test_option.hpp +++ b/src/mlpack/bindings/tests/test_option.hpp @@ -66,7 +66,7 @@ class TestOption const bool required = false, const bool input = true, const bool noTranspose = false, - const std::string& testName = "") + const std::string& bindingName = "") { // Create the ParamData object to give to IO. util::ParamData data; @@ -75,7 +75,8 @@ class TestOption data.name = identifier; data.tname = TYPENAME(N); data.alias = alias[0]; - data.wasPassed = false; + // If this is an output option, set it as passed. + data.wasPassed = !input; data.noTranspose = noTranspose; data.required = required; data.input = input; @@ -86,25 +87,13 @@ class TestOption const std::string tname = data.tname; - IO::RestoreSettings(testName, false); - // Set some function pointers that we need. - IO::GetSingleton().functionMap[tname]["GetPrintableParam"] = - &GetPrintableParam; - IO::GetSingleton().functionMap[tname]["GetParam"] = &GetParam; - IO::GetSingleton().functionMap[tname]["GetAllocatedMemory"] = - &GetAllocatedMemory; - IO::GetSingleton().functionMap[tname]["DeleteAllocatedMemory"] = - &DeleteAllocatedMemory; + IO::AddFunction(tname, "GetPrintableParam", &GetPrintableParam); + IO::AddFunction(tname, "GetParam", &GetParam); + IO::AddFunction(tname, "GetAllocatedMemory", &GetAllocatedMemory); + IO::AddFunction(tname, "DeleteAllocatedMemory", &DeleteAllocatedMemory); - IO::Add(std::move(data)); - - // If this is an output option, set it as passed. - if (!input) - IO::SetPassed(identifier); - - IO::StoreSettings(testName); - IO::ClearSettings(); + IO::AddParameter(bindingName, std::move(data)); } }; diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 332b676687..f6cf78da7d 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -85,7 +85,7 @@ add_executable(mlpack_test pca_test.cpp perceptron_test.cpp prefixedoutstream_test.cpp - python_binding_test.cpp +# python_binding_test.cpp qdafn_test.cpp quic_svd_test.cpp q_learning_test.cpp @@ -175,7 +175,7 @@ add_executable(mlpack_test # main_tests/softmax_regression_test.cpp # main_tests/sparse_coding_test.cpp # main_tests/range_search_test.cpp - main_tests/test_helper.hpp + main_tests/main_test_fixture.hpp ) if(NOT BUILD_SHARED_LIBS) diff --git a/src/mlpack/tests/main_tests/linear_regression_test.cpp b/src/mlpack/tests/main_tests/linear_regression_test.cpp index c6f9e19a14..83cd045ce1 100644 --- a/src/mlpack/tests/main_tests/linear_regression_test.cpp +++ b/src/mlpack/tests/main_tests/linear_regression_test.cpp @@ -2,50 +2,27 @@ * @file tests/main_tests/linear_regression_test.cpp * @author Eugene Freyman * - * Test mlpackMain() of linear_regression_main.cpp. + * Test RUN_BINDING() of linear_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "LinearRegression"; +#define BINDING_NAME linear_regression #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct LRTestFixture -{ - public: - LRTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~LRTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -void ResetSettings() -{ - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(LRTestFixture); /** * Training a model with different regularization parameter and ensuring that @@ -67,10 +44,9 @@ TEST_CASE_METHOD(LRTestFixture, "LRDifferentLambdas", SetInputParam("lambda", 0.1); // The first solution. - mlpackMain(); - const double testY1 = IO::GetParam("output_predictions")(0); + RUN_BINDING(); + const double testY1 = params.Get("output_predictions")(0); - bindings::tests::CleanMemory(); ResetSettings(); SetInputParam("training", std::move(trainX)); @@ -79,8 +55,8 @@ TEST_CASE_METHOD(LRTestFixture, "LRDifferentLambdas", SetInputParam("lambda", 1.0); // The second solution. - mlpackMain(); - const double testY2 = IO::GetParam("output_predictions")(0); + RUN_BINDING(); + const double testY2 = params.Get("output_predictions")(0); // Second solution has stronger regularization, // so the predicted value should be smaller. @@ -103,10 +79,10 @@ TEST_CASE_METHOD(LRTestFixture, "LRResponsesRepresentation", SetInputParam("test", testX); // The first solution. - mlpackMain(); - const double testY1 = IO::GetParam("output_predictions")(0); + RUN_BINDING(); + const double testY1 = params.Get("output_predictions")(0); - bindings::tests::CleanMemory(); + CleanMemory(); ResetSettings(); arma::mat trainX2({1.0, 2.0, 3.0}); @@ -116,8 +92,8 @@ TEST_CASE_METHOD(LRTestFixture, "LRResponsesRepresentation", SetInputParam("test", std::move(testX)); // The second solution. - mlpackMain(); - const double testY2 = IO::GetParam("output_predictions")(0); + RUN_BINDING(); + const double testY2 = params.Get("output_predictions")(0); REQUIRE(fabs(testY1 - testY2) < delta); } @@ -141,19 +117,19 @@ TEST_CASE_METHOD(LRTestFixture, "LRModelReload", SetInputParam("training_responses", std::move(trainY)); SetInputParam("test", testX); - mlpackMain(); + RUN_BINDING(); - LinearRegression* model = IO::GetParam("output_model"); - const arma::rowvec testY1 = IO::GetParam("output_predictions"); + LinearRegression* model = params.Get("output_model"); + const arma::rowvec testY1 = params.Get("output_predictions"); ResetSettings(); SetInputParam("input_model", model); SetInputParam("test", std::move(testX)); - mlpackMain(); + RUN_BINDING(); - const arma::rowvec testY2 = IO::GetParam("output_predictions"); + const arma::rowvec testY2 = params.Get("output_predictions"); double norm = arma::norm(testY1 - testY2, 2); REQUIRE(norm < delta); @@ -175,7 +151,7 @@ TEST_CASE_METHOD(LRTestFixture, "LRWrongResponseSizeTest", SetInputParam("training_responses", std::move(trainY)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -198,7 +174,7 @@ TEST_CASE_METHOD(LRTestFixture, "LRWrongDimOfDataTest1t", SetInputParam("test", std::move(testX)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -218,9 +194,9 @@ TEST_CASE_METHOD(LRTestFixture, "LRWrongDimOfDataTest2", SetInputParam("training", std::move(trainX)); SetInputParam("training_responses", std::move(trainY)); - mlpackMain(); + RUN_BINDING(); - LinearRegression* model = IO::GetParam("output_model"); + LinearRegression* model = params.Get("output_model"); ResetSettings(); @@ -229,7 +205,7 @@ TEST_CASE_METHOD(LRTestFixture, "LRWrongDimOfDataTest2", SetInputParam("test", std::move(testX)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -251,9 +227,9 @@ TEST_CASE_METHOD(LRTestFixture, "LRPredictionSizeCheck", SetInputParam("training_responses", std::move(trainY)); SetInputParam("test", std::move(testX)); - mlpackMain(); + RUN_BINDING(); - const arma::rowvec testY = IO::GetParam("output_predictions"); + const arma::rowvec testY = params.Get("output_predictions"); REQUIRE(testY.n_rows == 1); REQUIRE(testY.n_cols == M); @@ -272,7 +248,7 @@ TEST_CASE_METHOD(LRTestFixture, "LRNoResponses", SetInputParam("training", std::move(trainX)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -288,6 +264,6 @@ TEST_CASE_METHOD(LRTestFixture, "LRNoTrainingData", SetInputParam("training_responses", std::move(trainY)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/test_helper.hpp b/src/mlpack/tests/main_tests/test_helper.hpp deleted file mode 100644 index 8a745ad2dc..0000000000 --- a/src/mlpack/tests/main_tests/test_helper.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file tests/main_tests/test_helper.hpp - * @author Eugene Freyman - * - * Helper functions for testing. - * - * 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_TESTS_MAIN_TESTS_TEST_HELPER_HPP -#define MLPACK_TESTS_MAIN_TESTS_TEST_HELPER_HPP - -#include - -namespace mlpack { -namespace util { - -/** - * Utility function that is used in binding tests for setting a parameter and - * marking it as passed; it uses copy semantics for lvalues and move semantics - * for rvalues. - * - * @param name Name of parameter to set. - * @param value Value to set parameter to. - */ -template -void SetInputParam(const std::string& name, T&& value) -{ - IO::GetParam::type>(name) = - std::forward(value); - IO::SetPassed(name); -} - -} // namespace util -} // namespace mlpack - -#endif From 9eb26c8f8d48678fc99919c064732efeb3c333e8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 25 Jun 2021 10:14:36 -0400 Subject: [PATCH 443/729] Add MainTestFixture. --- .../tests/main_tests/main_test_fixture.hpp | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/mlpack/tests/main_tests/main_test_fixture.hpp diff --git a/src/mlpack/tests/main_tests/main_test_fixture.hpp b/src/mlpack/tests/main_tests/main_test_fixture.hpp new file mode 100644 index 0000000000..08bbf8f4af --- /dev/null +++ b/src/mlpack/tests/main_tests/main_test_fixture.hpp @@ -0,0 +1,112 @@ +/** + * @file tests/main_tests/main_test_fixture.hpp + * @author Ryan Curtin + * + * Implementation of MainTestFixture, the base class for the test fixture for + * all main classes. This also defines the MAIN_TEST_FIXTURE() convenience + * macro. + * + * 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_TESTS_MAIN_TEST_FIXTURE_HPP +#define MLPACK_TESTS_MAIN_TEST_FIXTURE_HPP + +#include +#include + +/** + * Define a test fixture for an mlpack binding test with the name given as + * `CLASS_NAME`. This fixture has all the same methods as `MainTestFixture` and + * can be used to set input parameters for a binding test. When all the + * parameters are set, use the `RUN_BINDING()` macro to actually run the + * binding. + * + * Before calling this macro, make sure the `BINDING_NAME` macro is defined + * appropriately! + */ +#define BINDING_TEST_FIXTURE(CLASS_NAME) \ + class CLASS_NAME : public MainTestFixture \ + { \ + public: \ + CLASS_NAME() : MainTestFixture(IO::Parameters(STRINGIFY(BINDING_NAME))) \ + { } \ + }; + +/** + * Run the binding. This depends on the `BINDING_NAME` macro being defined + * appropriately! + */ +#define RUN_BINDING() BINDING_NAME(params, timers) + +/** + * MainTestFixture is a base class for Catch fixtures for mlpack binding tests. + * Instead of using this class directly, use the `BINDING_TEST_FIXTURE()` macro + * to correctly define a fixture once `BINDING_NAME` is defined in your test + * file. Then, you can use all the methods in this class inside the tests. + */ +class MainTestFixture +{ + public: + //! Create a MainTestFixture with the given set of parameters. + MainTestFixture(const util::Params& paramsIn) : + paramsClean(paramsIn), + params(paramsIn) + { + // Nothing to do. + } + + //! Clean up any memory associated with the MainTestFixture. + ~MainTestFixture() + { + // Clean any allocated memory associated with any parameters. + CleanMemory(); + } + + /** + * Reset the `params` object to its initial state. After calling this method, + * it is as though no parameters at all have been set with `SetInputParam()`. + * Note that this does *not* clean memory associated with the current + * parameters! So, you may want to call `ClearMemory()` before calling this. + */ + void ResetSettings() + { + // Reset the parameters. + params = paramsClean; + + // Reset the timers too... + timers.StopAllTimers(); + timers.Reset(); + } + + /** + * Clean any memory associated with the `params` object. + */ + void CleanMemory() + { + bindings::tests::CleanMemory(params); + } + + /** + * Set the input parameter `name` to have value `value`. + */ + template + void SetInputParam(const std::string& name, T&& value) + { + params.Get::type>(name) = + std::forward(value); + params.SetPassed(name); + } + + protected: + //! Untouched "clean" parameters object, used for resetting. + util::Params paramsClean; + //! Parameters object, which the binding will be called with. + util::Params params; + //! Timers object, which the binding will be called with. + util::Timers timers; +}; + +#endif From 99b812a7a8e31a904d86124a4faba99a132ba635 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 25 Jun 2021 10:20:28 -0400 Subject: [PATCH 444/729] Don't set BINDING_NAME in the test file. --- src/mlpack/tests/main_tests/linear_regression_test.cpp | 1 - src/mlpack/tests/main_tests/main_test_fixture.hpp | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mlpack/tests/main_tests/linear_regression_test.cpp b/src/mlpack/tests/main_tests/linear_regression_test.cpp index 83cd045ce1..e482daa692 100644 --- a/src/mlpack/tests/main_tests/linear_regression_test.cpp +++ b/src/mlpack/tests/main_tests/linear_regression_test.cpp @@ -10,7 +10,6 @@ * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ #define BINDING_TYPE BINDING_TYPE_TEST -#define BINDING_NAME linear_regression #include #include diff --git a/src/mlpack/tests/main_tests/main_test_fixture.hpp b/src/mlpack/tests/main_tests/main_test_fixture.hpp index 08bbf8f4af..d4e184a2d5 100644 --- a/src/mlpack/tests/main_tests/main_test_fixture.hpp +++ b/src/mlpack/tests/main_tests/main_test_fixture.hpp @@ -25,7 +25,8 @@ * binding. * * Before calling this macro, make sure the `BINDING_NAME` macro is defined - * appropriately! + * appropriately. This is generally done simply by including the binding's + * `*_main.cpp` file. */ #define BINDING_TEST_FIXTURE(CLASS_NAME) \ class CLASS_NAME : public MainTestFixture \ @@ -37,7 +38,8 @@ /** * Run the binding. This depends on the `BINDING_NAME` macro being defined - * appropriately! + * appropriately. This is generally done simply by including the binding's + * `*_main.cpp` file. */ #define RUN_BINDING() BINDING_NAME(params, timers) From 3740a1ac7cd9ac79e09d42a99a1bbc8e05e670d7 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 26 Jun 2021 17:05:57 +0200 Subject: [PATCH 445/729] First successful test Signed-off-by: Omar Shrit --- src/mlpack/bindings/cli/add_to_cli11.hpp | 76 ++++++++++++------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/mlpack/bindings/cli/add_to_cli11.hpp b/src/mlpack/bindings/cli/add_to_cli11.hpp index ceb03c64e2..cf117067d3 100644 --- a/src/mlpack/bindings/cli/add_to_cli11.hpp +++ b/src/mlpack/bindings/cli/add_to_cli11.hpp @@ -33,15 +33,15 @@ template void AddToCLI11(const std::string& cliName, util::ParamData& param, CLI::App& app, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if< - arma::is_arma_type>::type* = 0, - const typename boost::disable_if< - data::HasSerialize>::type* = 0, - const typename boost::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>>::type* = 0) + arma::mat>>::value>::type* = 0) { app.add_option_function(cliName.c_str(), [¶m](const std::string& value) @@ -65,15 +65,15 @@ template void AddToCLI11(const std::string& cliName, util::ParamData& param, CLI::App& app, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if< - arma::is_arma_type>::type* = 0, - const typename boost::enable_if< - data::HasSerialize>::type* = 0, - const typename boost::disable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if< + data::HasSerialize::value>::type* = 0, + const typename std::enable_if>>::type* = 0) + arma::mat>>::value>::type* = 0) { app.add_option_function(cliName.c_str(), [¶m](const std::string& value) @@ -97,13 +97,13 @@ template void AddToCLI11(const std::string& cliName, util::ParamData& param, CLI::App& app, - const typename boost::disable_if< - std::is_same>::type* = 0, - const typename boost::enable_if< - arma::is_arma_type>::type* = 0, - const typename boost::disable_if::value>::type* = 0, + const typename std::enable_if< + arma::is_arma_type::value>::type* = 0, + const typename std::enable_if>>::type* = 0) + arma::mat>>::value>::type* = 0) { app.add_option_function(cliName.c_str(), [¶m](const std::string& value) @@ -127,15 +127,15 @@ template void AddToCLI11(const std::string& cliName, util::ParamData& param, CLI::App& app, - const typename boost::disable_if< - std::is_same>::type* = 0, - const typename boost::disable_if< - arma::is_arma_type>::type* = 0, - const typename boost::disable_if< - data::HasSerialize>::type* = 0, - const typename boost::disable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>>::type* = 0) + arma::mat>>::value>::type* = 0) { app.add_option_function(cliName.c_str(), [¶m](const T& value) @@ -157,15 +157,15 @@ template void AddToCLI11(const std::string& cliName, util::ParamData& param, CLI::App& app, - const typename boost::enable_if< - std::is_same>::type* = 0, - const typename boost::disable_if< - arma::is_arma_type>::type* = 0, - const typename boost::disable_if< - data::HasSerialize>::type* = 0, - const typename boost::disable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>>::type* = 0) + arma::mat>>::value>::type* = 0) { app.add_flag_function(cliName.c_str(), [¶m](const T& value) From 93de3217f20a471c2d1e5b1611c5b64107584e7c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 26 Jun 2021 18:04:37 +0200 Subject: [PATCH 446/729] Remove half of boost in this directory Signed-off-by: Omar Shrit --- src/mlpack/bindings/cli/default_param.hpp | 20 ++++++++--------- .../bindings/cli/default_param_impl.hpp | 20 ++++++++--------- .../bindings/cli/get_printable_param.hpp | 14 ++++++------ .../bindings/cli/get_printable_param_name.hpp | 18 +++++++-------- .../cli/get_printable_param_name_impl.hpp | 18 +++++++-------- .../bindings/cli/get_printable_type_impl.hpp | 14 ++++++------ src/mlpack/bindings/cli/output_param.hpp | 22 +++++++++---------- src/mlpack/bindings/cli/output_param_impl.hpp | 22 +++++++++---------- src/mlpack/bindings/cli/print_type_doc.hpp | 14 ++++++------ .../bindings/cli/print_type_doc_impl.hpp | 14 ++++++------ 10 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/mlpack/bindings/cli/default_param.hpp b/src/mlpack/bindings/cli/default_param.hpp index 1eecd76eec..f8a7ea894c 100644 --- a/src/mlpack/bindings/cli/default_param.hpp +++ b/src/mlpack/bindings/cli/default_param.hpp @@ -26,12 +26,12 @@ namespace cli { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return the default value of a vector option. @@ -39,7 +39,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a string option. @@ -47,7 +47,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a matrix option, a tuple option, a @@ -69,8 +69,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Return the default value of an option. This is the function that will be diff --git a/src/mlpack/bindings/cli/default_param_impl.hpp b/src/mlpack/bindings/cli/default_param_impl.hpp index 26e9d7e6cd..db95caf008 100644 --- a/src/mlpack/bindings/cli/default_param_impl.hpp +++ b/src/mlpack/bindings/cli/default_param_impl.hpp @@ -24,12 +24,12 @@ namespace cli { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; if (!std::is_same::value) @@ -44,7 +44,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { // Print each element in an array delimited by square brackets. std::ostringstream oss; @@ -88,7 +88,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { const std::string& s = *boost::any_cast(&data.value); return "'" + s + "'"; @@ -115,8 +115,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { return "''"; } diff --git a/src/mlpack/bindings/cli/get_printable_param.hpp b/src/mlpack/bindings/cli/get_printable_param.hpp index ca13c679e9..2cd2221101 100644 --- a/src/mlpack/bindings/cli/get_printable_param.hpp +++ b/src/mlpack/bindings/cli/get_printable_param.hpp @@ -27,11 +27,11 @@ namespace cli { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Print a vector option, with spaces between it. @@ -57,8 +57,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print an option into a std::string. This should print a short, one-line diff --git a/src/mlpack/bindings/cli/get_printable_param_name.hpp b/src/mlpack/bindings/cli/get_printable_param_name.hpp index 38d3c64164..b875d2f72d 100644 --- a/src/mlpack/bindings/cli/get_printable_param_name.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_name.hpp @@ -26,10 +26,10 @@ namespace cli { template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter name for a matrix type (where the user has to pass the file @@ -38,7 +38,7 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a serializable model type (where the user has to @@ -47,8 +47,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a mapped matrix type (where the user has to pass @@ -57,8 +57,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter's name as seen by the user. diff --git a/src/mlpack/bindings/cli/get_printable_param_name_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_name_impl.hpp index 4bb0da75e0..7c355c3dbc 100644 --- a/src/mlpack/bindings/cli/get_printable_param_name_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_name_impl.hpp @@ -26,10 +26,10 @@ namespace cli { template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "--" + data.name; } @@ -41,7 +41,7 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { return "--" + data.name + "_file"; } @@ -53,8 +53,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "--" + data.name + "_file"; } @@ -66,8 +66,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return "--" + data.name + "_file"; } diff --git a/src/mlpack/bindings/cli/get_printable_type_impl.hpp b/src/mlpack/bindings/cli/get_printable_type_impl.hpp index 7e7da8b038..d02dae49fc 100644 --- a/src/mlpack/bindings/cli/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_type_impl.hpp @@ -25,11 +25,11 @@ namespace cli { template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { if (std::is_same::value) return "flag"; @@ -101,8 +101,8 @@ std::string GetPrintableType( template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return data.cppType + " file"; } diff --git a/src/mlpack/bindings/cli/output_param.hpp b/src/mlpack/bindings/cli/output_param.hpp index 898f2d1a39..bef23ed43e 100644 --- a/src/mlpack/bindings/cli/output_param.hpp +++ b/src/mlpack/bindings/cli/output_param.hpp @@ -26,11 +26,11 @@ namespace cli { template void OutputParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Output a vector option (print to stdout). @@ -38,7 +38,7 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Output a matrix option (this saves it to the given file). @@ -46,7 +46,7 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Output a serializable class option (this saves it to the given file). @@ -54,8 +54,8 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Output a mapped dataset. @@ -63,8 +63,8 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); /** * Output an option. This is the function that will be called by the IO diff --git a/src/mlpack/bindings/cli/output_param_impl.hpp b/src/mlpack/bindings/cli/output_param_impl.hpp index ab2f1e8822..d34b55fd74 100644 --- a/src/mlpack/bindings/cli/output_param_impl.hpp +++ b/src/mlpack/bindings/cli/output_param_impl.hpp @@ -24,11 +24,11 @@ namespace cli { template void OutputParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if>::value>::type* /* junk */) { std::cout << data.name << ": " << *boost::any_cast(&data.value) << std::endl; @@ -38,7 +38,7 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { std::cout << data.name << ": "; const T& t = *boost::any_cast(&data.value); @@ -51,7 +51,7 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { typedef std::tuple> TupleType; const T& output = std::get<0>(*boost::any_cast(&data.value)); @@ -71,8 +71,8 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { // The const cast is necessary here because Serialize() can't ever be marked // const. In this case we can assume it though, since we will be saving and @@ -91,8 +91,8 @@ void OutputParamImpl( template void OutputParamImpl( util::ParamData& data, - const typename boost::enable_if>>::type* /* junk */) + const typename std::enable_if>::value>::type* /* junk */) { // Output the matrix with the mappings. typedef std::tuple> TupleType; diff --git a/src/mlpack/bindings/cli/print_type_doc.hpp b/src/mlpack/bindings/cli/print_type_doc.hpp index 873d5465f2..10acab4f5b 100644 --- a/src/mlpack/bindings/cli/print_type_doc.hpp +++ b/src/mlpack/bindings/cli/print_type_doc.hpp @@ -25,11 +25,11 @@ namespace cli { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -62,8 +62,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. diff --git a/src/mlpack/bindings/cli/print_type_doc_impl.hpp b/src/mlpack/bindings/cli/print_type_doc_impl.hpp index 51e3106de5..1836732bf8 100644 --- a/src/mlpack/bindings/cli/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/cli/print_type_doc_impl.hpp @@ -24,11 +24,11 @@ namespace cli { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { // A flag type. if (std::is_same::value) @@ -165,8 +165,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& /* data */, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "A filename containing an mlpack model. These can have one of three " "formats: binary (.bin), text (.txt), and XML (.xml). The XML format " From 632b43b46717096b91eae46a008c31711bfe7db3 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 26 Jun 2021 18:54:19 +0200 Subject: [PATCH 447/729] Compiling, remove boost_enable_if entirely from CLI binding Signed-off-by: Omar Shrit --- src/mlpack/bindings/cli/default_param.hpp | 2 +- src/mlpack/bindings/cli/default_param_impl.hpp | 2 +- .../bindings/cli/delete_allocated_memory.hpp | 10 +++++----- .../bindings/cli/get_allocated_memory.hpp | 10 +++++----- src/mlpack/bindings/cli/get_param.hpp | 18 +++++++++--------- .../bindings/cli/get_printable_param_impl.hpp | 14 +++++++------- .../bindings/cli/get_printable_param_value.hpp | 18 +++++++++--------- .../cli/get_printable_param_value_impl.hpp | 18 +++++++++--------- src/mlpack/bindings/cli/get_printable_type.hpp | 14 +++++++------- src/mlpack/bindings/cli/get_raw_param.hpp | 14 +++++++------- src/mlpack/bindings/cli/map_parameter_name.hpp | 10 +++++----- src/mlpack/bindings/cli/set_param.hpp | 18 +++++++++--------- src/mlpack/bindings/cli/string_type_param.hpp | 8 ++++---- .../bindings/cli/string_type_param_impl.hpp | 8 ++++---- 14 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/mlpack/bindings/cli/default_param.hpp b/src/mlpack/bindings/cli/default_param.hpp index f8a7ea894c..093a03c567 100644 --- a/src/mlpack/bindings/cli/default_param.hpp +++ b/src/mlpack/bindings/cli/default_param.hpp @@ -57,7 +57,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */ = 0); diff --git a/src/mlpack/bindings/cli/default_param_impl.hpp b/src/mlpack/bindings/cli/default_param_impl.hpp index db95caf008..b002e94611 100644 --- a/src/mlpack/bindings/cli/default_param_impl.hpp +++ b/src/mlpack/bindings/cli/default_param_impl.hpp @@ -100,7 +100,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */) diff --git a/src/mlpack/bindings/cli/delete_allocated_memory.hpp b/src/mlpack/bindings/cli/delete_allocated_memory.hpp index 35d305bb99..f3123c52e8 100644 --- a/src/mlpack/bindings/cli/delete_allocated_memory.hpp +++ b/src/mlpack/bindings/cli/delete_allocated_memory.hpp @@ -21,8 +21,8 @@ namespace cli { template void DeleteAllocatedMemoryImpl( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Do nothing. } @@ -30,7 +30,7 @@ void DeleteAllocatedMemoryImpl( template void DeleteAllocatedMemoryImpl( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Do nothing. } @@ -38,8 +38,8 @@ void DeleteAllocatedMemoryImpl( template void DeleteAllocatedMemoryImpl( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Delete the allocated memory (hopefully we actually own it). typedef std::tuple TupleType; diff --git a/src/mlpack/bindings/cli/get_allocated_memory.hpp b/src/mlpack/bindings/cli/get_allocated_memory.hpp index 0f70fe0adf..08e97e1e39 100644 --- a/src/mlpack/bindings/cli/get_allocated_memory.hpp +++ b/src/mlpack/bindings/cli/get_allocated_memory.hpp @@ -22,8 +22,8 @@ namespace cli { template void* GetAllocatedMemory( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return NULL; } @@ -31,7 +31,7 @@ void* GetAllocatedMemory( template void* GetAllocatedMemory( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return NULL; } @@ -39,8 +39,8 @@ void* GetAllocatedMemory( template void* GetAllocatedMemory( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Here we have a model, which is a tuple, and we need the address of the // memory. diff --git a/src/mlpack/bindings/cli/get_param.hpp b/src/mlpack/bindings/cli/get_param.hpp index d401e0e554..34463e939c 100644 --- a/src/mlpack/bindings/cli/get_param.hpp +++ b/src/mlpack/bindings/cli/get_param.hpp @@ -28,10 +28,10 @@ namespace cli { template T& GetParam( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { // No mapping is needed, so just cast it directly. return *boost::any_cast(&d.value); @@ -45,7 +45,7 @@ T& GetParam( template T& GetParam( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // If the matrix is an input matrix, we have to load the matrix. 'value' // contains the filename. It's possible we could load empty matrices many @@ -80,8 +80,8 @@ T& GetParam( template T& GetParam( util::ParamData& d, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // If this is an input parameter, we need to load both the matrix and the // dataset info. @@ -110,8 +110,8 @@ T& GetParam( template T*& GetParam( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // If the model is an input model, we have to load it from file. 'value' // contains the filename. diff --git a/src/mlpack/bindings/cli/get_printable_param_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_impl.hpp index 9898c49ee6..89f3c066f0 100644 --- a/src/mlpack/bindings/cli/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_impl.hpp @@ -23,11 +23,11 @@ namespace cli { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -103,8 +103,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { // Extract the string from the tuple that's being held. typedef std::tuple::type> TupleType; diff --git a/src/mlpack/bindings/cli/get_printable_param_value.hpp b/src/mlpack/bindings/cli/get_printable_param_value.hpp index 208afdb87b..621640b3c1 100644 --- a/src/mlpack/bindings/cli/get_printable_param_value.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_value.hpp @@ -27,10 +27,10 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter name for a matrix type (where the user has to pass the file @@ -40,7 +40,7 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a serializable model type (where the user has to @@ -50,8 +50,8 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a mapped matrix type (where the user has to pass @@ -61,8 +61,8 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter's name as seen by the user. diff --git a/src/mlpack/bindings/cli/get_printable_param_value_impl.hpp b/src/mlpack/bindings/cli/get_printable_param_value_impl.hpp index 09389614a1..3bb42b01b1 100644 --- a/src/mlpack/bindings/cli/get_printable_param_value_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_param_value_impl.hpp @@ -28,10 +28,10 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return input; } @@ -44,7 +44,7 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { return input + ".csv"; } @@ -57,8 +57,8 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return input + ".bin"; } @@ -71,8 +71,8 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return input + ".arff"; } diff --git a/src/mlpack/bindings/cli/get_printable_type.hpp b/src/mlpack/bindings/cli/get_printable_type.hpp index 9c29711240..07fd10609a 100644 --- a/src/mlpack/bindings/cli/get_printable_type.hpp +++ b/src/mlpack/bindings/cli/get_printable_type.hpp @@ -23,11 +23,11 @@ namespace cli { template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -60,8 +60,8 @@ std::string GetPrintableType( template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. diff --git a/src/mlpack/bindings/cli/get_raw_param.hpp b/src/mlpack/bindings/cli/get_raw_param.hpp index 46c3956a1f..38b340387e 100644 --- a/src/mlpack/bindings/cli/get_raw_param.hpp +++ b/src/mlpack/bindings/cli/get_raw_param.hpp @@ -27,10 +27,10 @@ namespace cli { template T& GetRawParam( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { // No mapping is needed, so just cast it directly. return *boost::any_cast(&d.value); @@ -42,7 +42,7 @@ T& GetRawParam( template T& GetRawParam( util::ParamData& d, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* = 0) @@ -59,8 +59,8 @@ T& GetRawParam( template T*& GetRawParam( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Don't load the model. typedef std::tuple TupleType; diff --git a/src/mlpack/bindings/cli/map_parameter_name.hpp b/src/mlpack/bindings/cli/map_parameter_name.hpp index 1835bd5602..74f20a6431 100644 --- a/src/mlpack/bindings/cli/map_parameter_name.hpp +++ b/src/mlpack/bindings/cli/map_parameter_name.hpp @@ -27,10 +27,10 @@ namespace cli { template std::string MapParameterName( const std::string& identifier, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { return identifier; } @@ -43,7 +43,7 @@ std::string MapParameterName( template std::string MapParameterName( const std::string& identifier, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value || diff --git a/src/mlpack/bindings/cli/set_param.hpp b/src/mlpack/bindings/cli/set_param.hpp index f800fe0553..f76f058d2e 100644 --- a/src/mlpack/bindings/cli/set_param.hpp +++ b/src/mlpack/bindings/cli/set_param.hpp @@ -27,11 +27,11 @@ template void SetParam( util::ParamData& d, const boost::any& value, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // No mapping is needed. d.value = value; @@ -44,7 +44,7 @@ template void SetParam( util::ParamData& d, const boost::any& /* value */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Force set to the value of whether or not this was passed. d.value = d.wasPassed; @@ -60,7 +60,7 @@ void SetParam( const boost::any& value, const typename std::enable_if::value || std::is_same>::value>::type* = 0) + std::tuple>::value::value>::type* = 0) { // We're setting the string filename. typedef std::tuple::type> TupleType; @@ -76,8 +76,8 @@ template void SetParam( util::ParamData& d, const boost::any& value, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // We're setting the string filename. typedef std::tuple::type> TupleType; diff --git a/src/mlpack/bindings/cli/string_type_param.hpp b/src/mlpack/bindings/cli/string_type_param.hpp index eb4550e3ca..decf9e794d 100644 --- a/src/mlpack/bindings/cli/string_type_param.hpp +++ b/src/mlpack/bindings/cli/string_type_param.hpp @@ -26,22 +26,22 @@ namespace cli { */ template std::string StringTypeParamImpl( - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Return a string containing the type of the parameter, for vector options. */ template std::string StringTypeParamImpl( - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return a string containing the type of the parameter, */ template std::string StringTypeParamImpl( - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return a string containing the type of a parameter. This overload is used if diff --git a/src/mlpack/bindings/cli/string_type_param_impl.hpp b/src/mlpack/bindings/cli/string_type_param_impl.hpp index 7bf1df6516..195d1b5a3b 100644 --- a/src/mlpack/bindings/cli/string_type_param_impl.hpp +++ b/src/mlpack/bindings/cli/string_type_param_impl.hpp @@ -23,8 +23,8 @@ namespace cli { */ template std::string StringTypeParamImpl( - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { // Don't know what type this is. return "unknown"; @@ -35,7 +35,7 @@ std::string StringTypeParamImpl( */ template std::string StringTypeParamImpl( - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { return "vector"; } @@ -45,7 +45,7 @@ std::string StringTypeParamImpl( */ template std::string StringTypeParamImpl( - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { return "string"; } From 88ddd5baf470428aba2213c3a3edef72416f96b0 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 26 Jun 2021 19:38:24 +0200 Subject: [PATCH 448/729] Yeah, markdown have changed now Signed-off-by: Omar Shrit --- .../bindings/cli/get_printable_type_impl.hpp | 2 +- .../bindings/markdown/get_printable_param.hpp | 22 +++++++++---------- .../markdown/get_printable_param_name.hpp | 18 +++++++-------- .../get_printable_param_name_impl.hpp | 18 +++++++-------- .../markdown/get_printable_param_value.hpp | 18 +++++++-------- .../get_printable_param_value_impl.hpp | 18 +++++++-------- .../bindings/markdown/is_serializable.hpp | 6 ++--- 7 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/mlpack/bindings/cli/get_printable_type_impl.hpp b/src/mlpack/bindings/cli/get_printable_type_impl.hpp index d02dae49fc..14a259b8b6 100644 --- a/src/mlpack/bindings/cli/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/cli/get_printable_type_impl.hpp @@ -101,7 +101,7 @@ std::string GetPrintableType( template std::string GetPrintableType( util::ParamData& data, - const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*) { return data.cppType + " file"; diff --git a/src/mlpack/bindings/markdown/get_printable_param.hpp b/src/mlpack/bindings/markdown/get_printable_param.hpp index 91df84d61f..e94e9a7ca9 100644 --- a/src/mlpack/bindings/markdown/get_printable_param.hpp +++ b/src/mlpack/bindings/markdown/get_printable_param.hpp @@ -25,11 +25,11 @@ namespace markdown { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -42,7 +42,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const T& t = boost::any_cast(data.value); @@ -58,7 +58,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Get the matrix. const T& matrix = boost::any_cast(data.value); @@ -74,8 +74,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::ostringstream oss; oss << data.cppType << " model at " << boost::any_cast(data.value); @@ -88,8 +88,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // Get the matrix. const T& tuple = boost::any_cast(data.value); diff --git a/src/mlpack/bindings/markdown/get_printable_param_name.hpp b/src/mlpack/bindings/markdown/get_printable_param_name.hpp index 9d19c05f6d..c222ea10fd 100644 --- a/src/mlpack/bindings/markdown/get_printable_param_name.hpp +++ b/src/mlpack/bindings/markdown/get_printable_param_name.hpp @@ -26,10 +26,10 @@ namespace markdown { template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter name for a matrix type (where the user has to pass the file @@ -38,7 +38,7 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a serializable model type (where the user has to @@ -47,8 +47,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a mapped matrix type (where the user has to pass @@ -57,8 +57,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter's name as seen by the user. diff --git a/src/mlpack/bindings/markdown/get_printable_param_name_impl.hpp b/src/mlpack/bindings/markdown/get_printable_param_name_impl.hpp index 5a7a63a001..b7e9f91fac 100644 --- a/src/mlpack/bindings/markdown/get_printable_param_name_impl.hpp +++ b/src/mlpack/bindings/markdown/get_printable_param_name_impl.hpp @@ -26,10 +26,10 @@ namespace markdown { template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "--" + data.name; } @@ -41,7 +41,7 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { return "--" + data.name + "_file"; } @@ -53,8 +53,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "--" + data.name + "_file"; } @@ -66,8 +66,8 @@ std::string GetPrintableParamName( template std::string GetPrintableParamName( util::ParamData& data, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return "--" + data.name + "_file"; } diff --git a/src/mlpack/bindings/markdown/get_printable_param_value.hpp b/src/mlpack/bindings/markdown/get_printable_param_value.hpp index c7e44ebd07..a0708fc2af 100644 --- a/src/mlpack/bindings/markdown/get_printable_param_value.hpp +++ b/src/mlpack/bindings/markdown/get_printable_param_value.hpp @@ -27,10 +27,10 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter name for a matrix type (where the user has to pass the file @@ -40,7 +40,7 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a serializable model type (where the user has to @@ -50,8 +50,8 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Get the parameter name for a mapped matrix type (where the user has to pass @@ -61,8 +61,8 @@ template std::string GetPrintableParamValue( util::ParamData& data, const std::string& value, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); /** * Get the parameter's name as seen by the user. diff --git a/src/mlpack/bindings/markdown/get_printable_param_value_impl.hpp b/src/mlpack/bindings/markdown/get_printable_param_value_impl.hpp index 22da560948..0753a7b03e 100644 --- a/src/mlpack/bindings/markdown/get_printable_param_value_impl.hpp +++ b/src/mlpack/bindings/markdown/get_printable_param_value_impl.hpp @@ -28,10 +28,10 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return input; } @@ -44,7 +44,7 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { return input + ".csv"; } @@ -57,8 +57,8 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return input + ".bin"; } @@ -71,8 +71,8 @@ template std::string GetPrintableParamValue( util::ParamData& /* data */, const std::string& input, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return input + ".arff"; } diff --git a/src/mlpack/bindings/markdown/is_serializable.hpp b/src/mlpack/bindings/markdown/is_serializable.hpp index daeda8e9cb..fa66d53f08 100644 --- a/src/mlpack/bindings/markdown/is_serializable.hpp +++ b/src/mlpack/bindings/markdown/is_serializable.hpp @@ -25,7 +25,7 @@ namespace markdown { */ template bool IsSerializable( - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return false; } @@ -35,8 +35,8 @@ bool IsSerializable( */ template bool IsSerializable( - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return true; } From 9e8eeb5c7e26dc2a11d7a284bab0aebfd9ad3a3f Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Sat, 26 Jun 2021 23:27:38 +0530 Subject: [PATCH 449/729] able to compile and use linear_regression.pyx successfully --- src/mlpack/bindings/python/CMakeLists.txt | 4 +- .../bindings/python/generate_pyx.cpp.in | 7 +- src/mlpack/bindings/python/mlpack/io.pxd | 35 ++----- src/mlpack/bindings/python/mlpack/io_util.hpp | 34 ++++--- src/mlpack/bindings/python/mlpack/params.pxd | 23 +++++ src/mlpack/bindings/python/mlpack/timers.pxd | 19 ++++ .../bindings/python/print_doc_functions.hpp | 20 ++-- .../python/print_doc_functions_impl.hpp | 42 ++++---- .../python/print_input_processing.hpp | 98 +++++++++---------- .../python/print_output_processing.hpp | 53 +++++----- src/mlpack/bindings/python/print_pyx.cpp | 56 ++++++----- src/mlpack/bindings/python/py_option.hpp | 24 ++--- src/mlpack/core/util/mlpack_main.hpp | 25 ++--- src/mlpack/core/util/params.cpp | 5 + src/mlpack/core/util/params.hpp | 5 + src/mlpack/methods/CMakeLists.txt | 94 +++++++++--------- .../linear_regression_main.cpp | 5 + 17 files changed, 297 insertions(+), 252 deletions(-) create mode 100644 src/mlpack/bindings/python/mlpack/params.pxd create mode 100644 src/mlpack/bindings/python/mlpack/timers.pxd diff --git a/src/mlpack/bindings/python/CMakeLists.txt b/src/mlpack/bindings/python/CMakeLists.txt index cf0066a132..50488f5c28 100644 --- a/src/mlpack/bindings/python/CMakeLists.txt +++ b/src/mlpack/bindings/python/CMakeLists.txt @@ -132,7 +132,9 @@ set(CYTHON_SOURCES mlpack/matrix_utils.py mlpack/serialization.hpp mlpack/serialization.pxd + mlpack/params.pxd mlpack/preprocess_json_params.py + mlpack/timers.pxd ) set(TEST_SOURCES @@ -295,7 +297,7 @@ if (BUILD_PYTHON_BINDINGS) # Add the convenience import to __init__.py. Note that this happens during # configuration. file(APPEND ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/__init__.py - "from .${name} import ${name}\n") + "from .${name} import ${name}_py\n") endif () endmacro () diff --git a/src/mlpack/bindings/python/generate_pyx.cpp.in b/src/mlpack/bindings/python/generate_pyx.cpp.in index 09905be574..8cefd5ec26 100644 --- a/src/mlpack/bindings/python/generate_pyx.cpp.in +++ b/src/mlpack/bindings/python/generate_pyx.cpp.in @@ -41,9 +41,6 @@ using namespace mlpack::util; int main(int /* argc */, char** /* argv */) { - // All the parameters are registered, but stored, so restore them. - // programName is defined in mlpack_main.hpp. - IO::RestoreSettings(programName); - - PrintPYX(IO::GetSingleton().doc, "${PROGRAM_MAIN_FILE}", "${PROGRAM_NAME}"); + PrintPYX(IO::Parameters(STRINGIFY(BINDING_NAME)).Doc(), + "${PROGRAM_MAIN_FILE}", STRINGIFY(BINDING_NAME)); } diff --git a/src/mlpack/bindings/python/mlpack/io.pxd b/src/mlpack/bindings/python/mlpack/io.pxd index 67961d59c9..6e5682dbf8 100644 --- a/src/mlpack/bindings/python/mlpack/io.pxd +++ b/src/mlpack/bindings/python/mlpack/io.pxd @@ -11,43 +11,22 @@ terms of the 3-clause BSD license. You should have received a copy of the http://www.opensource.org/licenses/BSD-3-Clause for more information. """ cimport cython - from libcpp.string cimport string from libcpp cimport bool +from params cimport Params cdef extern from "" namespace "mlpack" nogil: cdef cppclass IO: @staticmethod - (T&) GetParam[T](string) nogil except + - - @staticmethod - bool HasParam(string) nogil except + - - @staticmethod - void SetPassed(string) nogil except + - - @staticmethod - void Destroy() nogil except + - - @staticmethod - void StoreSettings(string) nogil except + - - @staticmethod - void RestoreSettings(string) nogil except + - - @staticmethod - void ClearSettings() nogil except + - - @staticmethod - void CheckInputMatrices() nogil except + + Params Parameters(string) nogil except + cdef extern from "" \ namespace "mlpack::util" nogil: - void SetParam[T](string, T&) nogil except + - void SetParamPtr[T](string, T*, bool) nogil except + - void SetParamWithInfo[T](string, T&, const bool*) nogil except + - (T*) GetParamPtr[T](string) nogil except + - (T&) GetParamWithInfo[T](string) nogil except + + void SetParam[T](Params, string, T&) nogil except + + void SetParamPtr[T](Params, string, T*, bool) nogil except + + void SetParamWithInfo[T](Params, string, T&, const bool*) nogil except + + (T*) GetParamPtr[T](Params, string) nogil except + + (T&) GetParamWithInfo[T](Params, string) nogil except + void EnableVerbose() nogil except + void DisableVerbose() nogil except + void DisableBacktrace() nogil except + diff --git a/src/mlpack/bindings/python/mlpack/io_util.hpp b/src/mlpack/bindings/python/mlpack/io_util.hpp index 3a69b06d2d..282dce8c46 100644 --- a/src/mlpack/bindings/python/mlpack/io_util.hpp +++ b/src/mlpack/bindings/python/mlpack/io_util.hpp @@ -12,7 +12,7 @@ */ #ifndef MLPACK_BINDINGS_PYTHON_CYTHON_IO_UTIL_HPP #define MLPACK_BINDINGS_PYTHON_CYTHON_IO_UTIL_HPP - +// TODO: Change this. #include #include @@ -29,9 +29,11 @@ namespace util { * @param value Value to set parameter to. */ template -inline void SetParam(const std::string& identifier, T& value) +inline void SetParam(util::Params& p, + const std::string& identifier, + T& value) { - IO::GetParam(identifier) = std::move(value); + p.Get(identifier) = std::move(value); } /** @@ -45,18 +47,20 @@ inline void SetParam(const std::string& identifier, T& value) * @param copy Whether or not the object should be copied. */ template -inline void SetParamPtr(const std::string& identifier, +inline void SetParamPtr(util::Params& p, + const std::string& identifier, T* value, const bool copy) { - IO::GetParam(identifier) = copy ? new T(*value) : value; + p.Get(identifier) = copy ? new T(*value) : value; } /** * Set the parameter (which is a matrix/DatasetInfo tuple) to the given value. */ template -inline void SetParamWithInfo(const std::string& identifier, +inline void SetParamWithInfo(util::Params& p, + const std::string& identifier, T& matrix, const bool* dims) { @@ -65,8 +69,8 @@ inline void SetParamWithInfo(const std::string& identifier, // The true type of the parameter is std::tuple. const size_t dimensions = matrix.n_rows; - std::get<1>(IO::GetParam(identifier)) = std::move(matrix); - data::DatasetInfo& di = std::get<0>(IO::GetParam(identifier)); + std::get<1>(p.Get(identifier)) = std::move(matrix); + data::DatasetInfo& di = std::get<0>(p.Get(identifier)); di = data::DatasetInfo(dimensions); bool hasCategoricals = false; @@ -83,7 +87,7 @@ inline void SetParamWithInfo(const std::string& identifier, if (hasCategoricals) { arma::vec maxs = arma::max( - std::get<1>(IO::GetParam(identifier)), 1); + std::get<1>(p.Get(identifier)), 1); for (size_t i = 0; i < dimensions; ++i) { @@ -106,20 +110,22 @@ inline void SetParamWithInfo(const std::string& identifier, * of support for template pointer types. */ template -T* GetParamPtr(const std::string& paramName) +T* GetParamPtr(util::Params& p, + const std::string& paramName) { - return IO::GetParam(paramName); + return p.Get(paramName); } /** * Return the matrix part of a matrix + dataset info parameter. */ template -T& GetParamWithInfo(const std::string& paramName) +T& GetParamWithInfo(util::Params& p, + const std::string& paramName) { // T will be the Armadillo type. typedef std::tuple TupleType; - return std::get<1>(IO::GetParam(paramName)); + return std::get<1>(p.Get(paramName)); } /** @@ -152,7 +158,7 @@ inline void DisableBacktrace() inline void ResetTimers() { // Just get a new object---removes all old timers. - IO::GetSingleton().timer.Reset(); + Timer::ResetAll(); } /** diff --git a/src/mlpack/bindings/python/mlpack/params.pxd b/src/mlpack/bindings/python/mlpack/params.pxd new file mode 100644 index 0000000000..d77866ffb1 --- /dev/null +++ b/src/mlpack/bindings/python/mlpack/params.pxd @@ -0,0 +1,23 @@ +#!/usr/bin/env python +""" +params.pxd: Cython functionality for mlpack::util::Params. + +This file imports the GetParam() function from mlpack::IO, plus a utility +SetParam() function because Cython can't seem to support lvalue references. + +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. +""" +cimport cython +from libcpp.string cimport string +from libcpp cimport bool + +cdef extern from "" namespace "mlpack::util" nogil: + cdef cppclass Params: + Params() nogil + (T&) Get[T](string) nogil except + + bool Has(string) nogil except + + void SetPassed(string) nogil except + + void CheckInputMatrices() nogil except + diff --git a/src/mlpack/bindings/python/mlpack/timers.pxd b/src/mlpack/bindings/python/mlpack/timers.pxd new file mode 100644 index 0000000000..9b5bd6fb58 --- /dev/null +++ b/src/mlpack/bindings/python/mlpack/timers.pxd @@ -0,0 +1,19 @@ +#!/usr/bin/env python +""" +params.pxd: Cython functionality for mlpack::util::Params. + +This file imports the GetParam() function from mlpack::IO, plus a utility +SetParam() function because Cython can't seem to support lvalue references. + +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. +""" +cimport cython +from libcpp.string cimport string +from libcpp cimport bool + +cdef extern from "" namespace "mlpack::util" nogil: + cdef cppclass Timers: + Timers() nogil diff --git a/src/mlpack/bindings/python/print_doc_functions.hpp b/src/mlpack/bindings/python/print_doc_functions.hpp index 59ac53a0ef..05b1fc1910 100644 --- a/src/mlpack/bindings/python/print_doc_functions.hpp +++ b/src/mlpack/bindings/python/print_doc_functions.hpp @@ -52,10 +52,11 @@ inline std::string PrintValue(const bool& value, bool quotes); /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName); +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName); // Recursion base case. -inline std::string PrintInputOptions(); +inline std::string PrintInputOptions(util::Params& params); /** * Print an input option. This will throw an exception if the parameter does @@ -63,15 +64,17 @@ inline std::string PrintInputOptions(); * something like x=5. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args); // Recursion base case. -inline std::string PrintOutputOptions(); +inline std::string PrintOutputOptions(util::Params& params); template -std::string PrintOutputOptions(const std::string& paramName, +std::string PrintOutputOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args); @@ -110,14 +113,16 @@ inline std::string ParamString(const std::string& paramName); * Python bindings, we ignore any checks on output parameters, so if paramName * is an output parameter, this returns true. */ -inline bool IgnoreCheck(const std::string& paramName); +inline bool IgnoreCheck(const std::string& bindingName, + const std::string& paramName); /** * Print whether or not we should ignore a check on the given set of * constraints. For Python bindings, we ignore any checks on output parameters, * so if any parameter is an output parameter, this returns true. */ -inline bool IgnoreCheck(const std::vector& constraints); +inline bool IgnoreCheck(const std::string& bindingName, + const std::vector& constraints); /** * Print whether or not we should ignore a check on the given set of @@ -126,6 +131,7 @@ inline bool IgnoreCheck(const std::vector& constraints); * this returns true. */ inline bool IgnoreCheck( + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName); diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp index 8997e02bdc..aa41c0233f 100644 --- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp @@ -125,7 +125,7 @@ inline std::string PrintDefault(const std::string& bindingName, } // Recursion base case. -std::string PrintInputOptions() { return ""; } +std::string PrintInputOptions(util::Params& /* params */) { return ""; } /** * Print an input option. This will throw an exception if the parameter does @@ -133,18 +133,16 @@ std::string PrintInputOptions() { return ""; } * something like x=5. */ template -std::string PrintInputOptions(const std::string& bindingName, - const std::string& paramName, +std::string PrintInputOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args) { - util::Params p = IO::Parameters(bindingName); - // See if this is part of the program. std::string result = ""; - if (p.Parameters().count(paramName) > 0) + if (params.Parameters().count(paramName) > 0) { - util::ParamData& d = p.Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; if (d.input) { // Print the input option. @@ -166,7 +164,7 @@ std::string PrintInputOptions(const std::string& bindingName, } // Continue recursion. - std::string rest = PrintInputOptions(args...); + std::string rest = PrintInputOptions(params, args...); if (rest != "" && result != "") result += ", " + rest; else if (result == "") @@ -176,21 +174,19 @@ std::string PrintInputOptions(const std::string& bindingName, } // Recursion base case. -inline std::string PrintOutputOptions() { return ""; } +inline std::string PrintOutputOptions(util::Params& /* params */) { return ""; } template -std::string PrintOutputOptions(const std::string& bindingName, - const std::string& paramName, +std::string PrintOutputOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args) { - util::Params p = IO::Parameters(bindingName); - // See if this is part of the program. std::string result = ""; - if (p.Parameters().count(paramName) > 0) + if (params.Parameters().count(paramName) > 0) { - util::ParamData& d = p.Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; if (!d.input) { // Print a new line for the output option. @@ -208,7 +204,7 @@ std::string PrintOutputOptions(const std::string& bindingName, } // Continue recursion. - std::string rest = PrintOutputOptions(args...); + std::string rest = PrintOutputOptions(params, args...); if (rest != "" && result != "") result += '\n'; result += rest; @@ -224,25 +220,27 @@ std::string PrintOutputOptions(const std::string& bindingName, template std::string ProgramCall(const std::string& programName, Args... args) { + util::Params params = IO::Parameters(programName); + std::ostringstream oss; oss << ">>> "; // Find out if we have any output options first. std::ostringstream ossOutput; - ossOutput << PrintOutputOptions(args...); + ossOutput << PrintOutputOptions(params, args...); if (ossOutput.str() != "") oss << "output = "; oss << programName << "("; // Now process each input option. - oss << PrintInputOptions(args...); + oss << PrintInputOptions(params, args...); oss << ")"; std::string call = oss.str(); oss.str(""); // Reset it. // Now process each output option. - oss << PrintOutputOptions(args...); + oss << PrintOutputOptions(params, args...); if (oss.str() == "") return util::HyphenateString(call, 2); else @@ -255,13 +253,13 @@ std::string ProgramCall(const std::string& programName, Args... args) */ inline std::string ProgramCall(const std::string& programName) // TODO: here programName is the bindingName?? { - util::Params p = IO::Parameters()[programName]; + util::Params params = IO::Parameters(programName); std::ostringstream oss; oss << ">>> "; // Determine if we have any output options. - std::map& parameters = p.Parameters(); + std::map& parameters = params.Parameters(); bool hasOutput = false; for (auto it = parameters.begin(); it != parameters.end(); ++it) { @@ -297,7 +295,7 @@ inline std::string ProgramCall(const std::string& programName) // TODO: here pro oss << it->second.name << "_="; std::string value; - p.functionMap[it->second.tname]["DefaultParam"]( + params.functionMap[it->second.tname]["DefaultParam"]( it->second, NULL, (void*) &value); oss << value; } diff --git a/src/mlpack/bindings/python/print_input_processing.hpp b/src/mlpack/bindings/python/print_input_processing.hpp index c4a8ed5006..32d1581ce4 100644 --- a/src/mlpack/bindings/python/print_input_processing.hpp +++ b/src/mlpack/bindings/python/print_input_processing.hpp @@ -57,8 +57,8 @@ void PrintInputProcessing( * # Detect if the parameter was passed; set if so. * if param_name is not None: * if isinstance(param_name, int): - * SetParam[int](\ 'param_name', param_name) - * IO.SetPassed(\ 'param_name') + * SetParam[int](p, \ 'param_name', param_name) + * p.SetPassed(\ 'param_name') * else: * raise TypeError("'param_name' must have type 'list'!") */ @@ -82,13 +82,13 @@ void PrintInputProcessing( } std::cout << prefix << " SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', "; + << "](p, '" << d.name << "', "; if (GetCythonType(d) == "string") std::cout << name << ".encode(\"UTF-8\")"; else std::cout << name; std::cout << ")" << std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; // If this parameter is "verbose", then enable verbose output. @@ -127,7 +127,7 @@ void PrintInputProcessing( << GetPrintableType(d) << "):" << std::endl; } - std::cout << prefix << " SetParam[" << GetCythonType(d) << "]((d) << "](p, '" << d.name << "', "; if (GetCythonType(d) == "string") std::cout << name << ".encode(\"UTF-8\")"; @@ -136,7 +136,7 @@ void PrintInputProcessing( else std::cout << name; std::cout << ")" << std::endl; - std::cout << prefix << " IO.SetPassed( '" + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; if (GetPrintableType(d) == "bool") @@ -178,8 +178,8 @@ void PrintInputProcessing( * if isinstance(param_name, list): * if len(param_name) > 0: * if isinstance(param_name[0], str): - * SetParam[vector[string]](\ 'param_name', param_name) - * IO.SetPassed(\ 'param_name') + * SetParam[vector[string]](p, \ 'param_name', param_name) + * p.SetPassed(\ 'param_name') * else: * raise TypeError("'param_name' must have type 'list of strs'!") * else: @@ -199,14 +199,14 @@ void PrintInputProcessing( std::cout << prefix << " if isinstance(" << d.name << "[0], " << GetPrintableType(d) << "):" << std::endl; std::cout << prefix << " SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', "; + << "](p, '" << d.name << "', "; // Strings need special handling. if (GetCythonType(d) == "vector[string]") std::cout << "[i.encode(\"UTF-8\") for i in " << d.name << "]"; else std::cout << d.name; std::cout << ")" << std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << " else:" << std::endl; std::cout << prefix << " raise TypeError(" <<"\"'"<< d.name @@ -225,14 +225,14 @@ void PrintInputProcessing( std::cout << prefix << " if isinstance(" << d.name << "[0], " << GetPrintableType(d) << "):" << std::endl; std::cout << prefix << " SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', "; + << "](p, '" << d.name << "', "; // Strings need special handling. if (GetCythonType(d) == "vector[string]") std::cout << "[i.encode(\"UTF-8\") for i in " << d.name << "]"; else std::cout << d.name; std::cout << ")" << std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << " else:" << std::endl; std::cout << prefix << " raise TypeError(" <<"\"'"<< d.name @@ -267,8 +267,8 @@ void PrintInputProcessing( * param_name_tuple[0].shape = (param_name_tuple[0].size,) * param_name_mat = arma_numpy.numpy_to_mat_s(param_name_tuple[0], * param_name_tuple[1]) - * SetParam[mat](\ 'param_name', dereference(param_name_mat)) - * IO.SetPassed(\ 'param_name') + * SetParam[mat](p, \ 'param_name', dereference(param_name_mat)) + * p.SetPassed(\ 'param_name') * */ std::cout << prefix << "# Detect if the parameter was passed; set if so." @@ -280,7 +280,7 @@ void PrintInputProcessing( std::cout << prefix << "if " << d.name << " is not None:" << std::endl; std::cout << prefix << " " << d.name << "_tuple = to_matrix(" << d.name << ", dtype=" << GetNumpyType() - << ", copy=IO.HasParam('copy_all_inputs'))" << std::endl; + << ", copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " if len(" << d.name << "_tuple[0].shape) > 1:" << std::endl; std::cout << prefix << " if " << d.name << "_tuple[0]" @@ -292,9 +292,9 @@ void PrintInputProcessing( << GetArmaType() << "_" << GetNumpyTypeChar() << "(" << d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl; std::cout << prefix << " SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', dereference(" + << "](p, '" << d.name << "', dereference(" << d.name << "_mat))"<< std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << " del " << d.name << "_mat" << std::endl; } @@ -303,7 +303,7 @@ void PrintInputProcessing( std::cout << prefix << "if " << d.name << " is not None:" << std::endl; std::cout << prefix << " " << d.name << "_tuple = to_matrix(" << d.name << ", dtype=" << GetNumpyType() - << ", copy=IO.HasParam('copy_all_inputs'))" << std::endl; + << ", copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " if len(" << d.name << "_tuple[0].shape" << ") < 2:" << std::endl; std::cout << prefix << " " << d.name << "_tuple[0].shape = (" << d.name @@ -312,9 +312,9 @@ void PrintInputProcessing( << GetArmaType() << "_" << GetNumpyTypeChar() << "(" << d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl; std::cout << prefix << " SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', dereference(" + << "](p, '" << d.name << "', dereference(" << d.name << "_mat))"<< std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << " del " << d.name << "_mat" << std::endl; } @@ -325,7 +325,7 @@ void PrintInputProcessing( { std::cout << prefix << d.name << "_tuple = to_matrix(" << d.name << ", dtype=" << GetNumpyType() - << ", copy=IO.HasParam('copy_all_inputs'))" << std::endl; + << ", copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << "if len(" << d.name << "_tuple[0].shape) > 1:" << std::endl; std::cout << prefix << " if " << d.name << "_tuple[0].shape[0] == 1 or " @@ -336,9 +336,9 @@ void PrintInputProcessing( << GetArmaType() << "_" << GetNumpyTypeChar() << "(" << d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl; std::cout << prefix << "SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', dereference(" + << "](p, '" << d.name << "', dereference(" << d.name << "_mat))"<< std::endl; - std::cout << prefix << "IO.SetPassed( '" << d.name << "')" + std::cout << prefix << "p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << "del " << d.name << "_mat" << std::endl; } @@ -346,7 +346,7 @@ void PrintInputProcessing( { std::cout << prefix << d.name << "_tuple = to_matrix(" << d.name << ", dtype=" << GetNumpyType() - << ", copy=IO.HasParam('copy_all_inputs'))" << std::endl; + << ", copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << "if len(" << d.name << "_tuple[0].shape) > 2:" << std::endl; std::cout << prefix << " " << d.name << "_tuple[0].shape = (" << d.name @@ -355,9 +355,9 @@ void PrintInputProcessing( << GetArmaType() << "_" << GetNumpyTypeChar() << "(" << d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl; std::cout << prefix << "SetParam[" << GetCythonType(d) - << "]( '" << d.name << "', dereference(" << d.name + << "](p, '" << d.name << "', dereference(" << d.name << "_mat))" << std::endl; - std::cout << prefix << "IO.SetPassed( '" << d.name << "')" + std::cout << prefix << "p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << "del " << d.name << "_mat" << std::endl; } @@ -388,15 +388,15 @@ void PrintInputProcessing( * # Detect if the parameter was passed; set if so. * if param_name is not None: * try: - * SetParamPtr[Model]('param_name', (\ param_name).modelptr, - * IO.HasParam('copy_all_inputs')) + * SetParamPtr[Model](p, 'param_name', (\ param_name).modelptr, + * p.Has('copy_all_inputs')) * except TypeError as e: * if type(param_name).__name__ == "ModelType": - * SetParamPtr[Model]('param_name', (\ param_name).modelptr, - * IO.HasParam('copy_all_inputs')) + * SetParamPtr[Model](p, 'param_name', (\ param_name).modelptr, + * p.Has('copy_all_inputs')) * else: * raise e - * IO.SetPassed(\ 'param_name') + * p.SetPassed( 'param_name') */ std::cout << prefix << "# Detect if the parameter was passed; set if so." << std::endl; @@ -404,35 +404,35 @@ void PrintInputProcessing( { std::cout << prefix << "if " << d.name << " is not None:" << std::endl; std::cout << prefix << " try:" << std::endl; - std::cout << prefix << " SetParamPtr[" << strippedType << "]('" << d.name + std::cout << prefix << " SetParamPtr[" << strippedType << "](p, '" << d.name << "', (<" << strippedType << "Type?> " << d.name << ").modelptr, " - << "IO.HasParam('copy_all_inputs'))" << std::endl; + << "p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " except TypeError as e:" << std::endl; std::cout << prefix << " if type(" << d.name << ").__name__ == '" << strippedType << "Type':" << std::endl; - std::cout << prefix << " SetParamPtr[" << strippedType << "]('" + std::cout << prefix << " SetParamPtr[" << strippedType << "](p, '" << d.name << "', (<" << strippedType << "Type> " << d.name - << ").modelptr, IO.HasParam('copy_all_inputs'))" << std::endl; + << ").modelptr, p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " else:" << std::endl; std::cout << prefix << " raise e" << std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name << "')" + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; } else { std::cout << prefix << "try:" << std::endl; - std::cout << prefix << " SetParamPtr[" << strippedType << "]('" << d.name + std::cout << prefix << " SetParamPtr[" << strippedType << "](p, '" << d.name << "', (<" << strippedType << "Type?> " << d.name << ").modelptr, " - << "IO.HasParam('copy_all_inputs'))" << std::endl; + << "p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << "except TypeError as e:" << std::endl; std::cout << prefix << " if type(" << d.name << ").__name__ == '" << strippedType << "Type':" << std::endl; - std::cout << prefix << " SetParamPtr[" << strippedType << "]('" << d.name + std::cout << prefix << " SetParamPtr[" << strippedType << "](p,'" << d.name << "', (<" << strippedType << "Type> " << d.name << ").modelptr, " - << "IO.HasParam('copy_all_inputs'))" << std::endl; + << "p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " else:" << std::endl; std::cout << prefix << " raise e" << std::endl; - std::cout << prefix << "IO.SetPassed( '" << d.name << "')" + std::cout << prefix << "p.SetPassed( '" << d.name << "')" << std::endl; } std::cout << std::endl; @@ -459,9 +459,9 @@ void PrintInputProcessing( * if len(param_name_tuple[0].shape) < 2: * param_name_tuple[0].shape = (param_name_tuple[0].size,) * param_name_mat = arma_numpy.numpy_to_matrix_d(param_name_tuple[0]) - * SetParamWithInfo[mat](\ 'param_name', + * SetParamWithInfo[mat](p, \ 'param_name', * dereference(param_name_mat), ¶m_name_tuple[1][0]) - * IO.SetPassed(\ 'param_name') + * p.SetPassed(\ 'param_name') */ std::cout << prefix << "cdef np.ndarray " << d.name << "_dims" << std::endl; std::cout << prefix << "# Detect if the parameter was passed; set if so." @@ -470,7 +470,7 @@ void PrintInputProcessing( { std::cout << prefix << "if " << d.name << " is not None:" << std::endl; std::cout << prefix << " " << d.name << "_tuple = to_matrix_with_info(" - << d.name << ", dtype=np.double, copy=IO.HasParam('copy_all_inputs'))" + << d.name << ", dtype=np.double, copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " if len(" << d.name << "_tuple[0].shape" << ") < 2:" << std::endl; @@ -480,17 +480,17 @@ void PrintInputProcessing( << d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl; std::cout << prefix << " " << d.name << "_dims = " << d.name << "_tuple[2]" << std::endl; - std::cout << prefix << " SetParamWithInfo[arma.Mat[double]]( '" << d.name << "', dereference(" << d.name << "_mat), " << " " << d.name << "_dims.data)" << std::endl; - std::cout << prefix << " IO.SetPassed( '" << d.name + std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << " del " << d.name << "_mat" << std::endl; } else { std::cout << prefix << d.name << "_tuple = to_matrix_with_info(" << d.name - << ", dtype=np.double, copy=IO.HasParam('copy_all_inputs'))" + << ", dtype=np.double, copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << "if len(" << d.name << "_tuple[0].shape" << ") < 2:" << std::endl; @@ -500,10 +500,10 @@ void PrintInputProcessing( << d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl; std::cout << prefix << d.name << "_dims = " << d.name << "_tuple[2]" << std::endl; - std::cout << prefix << "SetParamWithInfo[arma.Mat[double]]( '" << d.name << "', dereference(" << d.name << "_mat), " << " " << d.name << "_dims.data)" << std::endl; - std::cout << prefix << "IO.SetPassed( '" << d.name << "')" + std::cout << prefix << "p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << "del " << d.name << "_mat" << std::endl; } diff --git a/src/mlpack/bindings/python/print_output_processing.hpp b/src/mlpack/bindings/python/print_output_processing.hpp index af1ef95a93..fb04309fbd 100644 --- a/src/mlpack/bindings/python/print_output_processing.hpp +++ b/src/mlpack/bindings/python/print_output_processing.hpp @@ -27,6 +27,7 @@ namespace python { */ template void PrintOutputProcessing( + util::Params& /* params */, util::ParamData& d, const size_t indent, const bool onlyOutput, @@ -42,9 +43,9 @@ void PrintOutputProcessing( /** * This gives us code like: * - * result = IO.GetParam[int]('param_name') + * result = p.Get[int]('param_name') */ - std::cout << prefix << "result = " << "IO.GetParam[" << GetCythonType(d) + std::cout << prefix << "result = " << "p.Get[" << GetCythonType(d) << "](\"" << d.name << "\")"; if (GetCythonType(d) == "string") { @@ -61,9 +62,9 @@ void PrintOutputProcessing( /** * This gives us code like: * - * result['param_name'] = IO.GetParam[int]('param_name') + * result['param_name'] = p.Get[int]('param_name') */ - std::cout << prefix << "result['" << d.name << "'] = IO.GetParam[" + std::cout << prefix << "result['" << d.name << "'] = p.Get[" << GetCythonType(d) << "](\"" << d.name << "\")" << std::endl; if (GetCythonType(d) == "string") { @@ -83,6 +84,7 @@ void PrintOutputProcessing( */ template void PrintOutputProcessing( + util::Params& /* params */, util::ParamData& d, const size_t indent, const bool onlyOutput, @@ -95,12 +97,12 @@ void PrintOutputProcessing( /** * This gives us code like: * - * result = arma_numpy.mat_to_numpy_X(IO.GetParam[mat]("name")) + * result = arma_numpy.mat_to_numpy_X(p.Get[mat]("name")) * * where X indicates the type to convert to. */ std::cout << prefix << "result = arma_numpy." << GetArmaType() - << "_to_numpy_" << GetNumpyTypeChar() << "(IO.GetParam[" + << "_to_numpy_" << GetNumpyTypeChar() << "(p.Get[" << GetCythonType(d) << "](\"" << d.name << "\"))" << std::endl; } else @@ -109,13 +111,13 @@ void PrintOutputProcessing( * This gives us code like: * * result['param_name'] = - * arma_numpy.mat_to_numpy_X(IO.GetParam[mat]('name') + * arma_numpy.mat_to_numpy_X(p.Get[mat]('name') * * where X indicates the type to convert to. */ std::cout << prefix << "result['" << d.name << "'] = arma_numpy." << GetArmaType() << "_to_numpy_" - << GetNumpyTypeChar() << "(IO.GetParam[" << GetCythonType(d) + << GetNumpyTypeChar() << "(p.Get[" << GetCythonType(d) << "]('" << d.name << "'))" << std::endl; } } @@ -125,6 +127,7 @@ void PrintOutputProcessing( */ template void PrintOutputProcessing( + util::Params& /* params */, util::ParamData& d, const size_t indent, const bool onlyOutput, @@ -140,11 +143,11 @@ void PrintOutputProcessing( /** * This gives us code like: * - * result = arma_numpy.mat_to_numpy_X(GetParamWithInfo[mat]('name')) + * result = arma_numpy.mat_to_numpy_X(GetParamWithInfo[mat](p, 'name')) */ std::cout << prefix << "result = arma_numpy.mat_to_numpy_" << GetNumpyTypeChar() - << "(GetParamWithInfo[arma.Mat[double]]('" << d.name << "'))" + << "(GetParamWithInfo[arma.Mat[double]](p, '" << d.name << "'))" << std::endl; } else @@ -153,11 +156,11 @@ void PrintOutputProcessing( * This gives us code like: * * result['param_name'] = - * arma_numpy.mat_to_numpy_X(GetParamWithInfo[mat]('name')) + * arma_numpy.mat_to_numpy_X(GetParamWithInfo[mat](p, 'name')) */ std::cout << prefix << "result['" << d.name << "'] = arma_numpy.mat_to_numpy_" << GetNumpyTypeChar() - << "(GetParamWithInfo[arma.Mat[double]]('" << d.name << "'))" + << "(GetParamWithInfo[arma.Mat[double]](p, '" << d.name << "'))" << std::endl; } } @@ -167,9 +170,10 @@ void PrintOutputProcessing( */ template void PrintOutputProcessing( + util::Params& params, util::ParamData& d, const size_t indent, - const bool onlyOutput, + const bool onlyOutput, const typename boost::disable_if>::type* = 0, const typename boost::enable_if>::type* = 0) { @@ -185,11 +189,11 @@ void PrintOutputProcessing( * This gives us code like: * * result = ModelType() - * ( result).modelptr = GetParamPtr[Model]('name') + * ( result).modelptr = GetParamPtr[Model](p, 'name') */ std::cout << prefix << "result = " << strippedType << "Type()" << std::endl; std::cout << prefix << "(<" << strippedType << "Type?> result).modelptr = " - << "GetParamPtr[" << strippedType << "]('" << d.name << "')" + << "GetParamPtr[" << strippedType << "](p, '" << d.name << "')" << std::endl; /** @@ -198,7 +202,7 @@ void PrintOutputProcessing( * So we need to loop through all input parameters that have the same type, * and double-check. */ - std::map& parameters = IO::Parameters(); + std::map& parameters = params.Parameters(); for (auto it = parameters.begin(); it != parameters.end(); ++it) { // Is it an input parameter of the same type? @@ -233,12 +237,12 @@ void PrintOutputProcessing( * This gives us code like: * * result['name'] = ModelType() - * ( result['name']).modelptr = GetParamPtr[Model]('name')) + * ( result['name']).modelptr = GetParamPtr[Model](p, 'name')) */ std::cout << prefix << "result['" << d.name << "'] = " << strippedType << "Type()" << std::endl; std::cout << prefix << "(<" << strippedType << "Type?> result['" << d.name - << "']).modelptr = GetParamPtr[" << strippedType << "]('" << d.name + << "']).modelptr = GetParamPtr[" << strippedType << "](p, '" << d.name << "')" << std::endl; /** @@ -247,7 +251,7 @@ void PrintOutputProcessing( * So we need to loop through all input parameters that have the same type, * and double-check. */ - std::map& parameters = IO::Parameters(); + std::map& parameters = params.Parameters(); for (auto it = parameters.begin(); it != parameters.end(); ++it) { // Is it an input parameter of the same type? @@ -286,7 +290,9 @@ void PrintOutputProcessing( * data.input is false, and should not be called when data.input is true. If * this is the only output, the results will be different. * - * The input pointer should be a pointer to a std::tuple where the + * The input pointer should be a pointer to a + * std::tuple> where the first element is + * the parameters of the binding and the second element is a tuple where the * first element is the indentation and the second element is a boolean * representing whether or not this is the only output parameter. * @@ -299,10 +305,11 @@ void PrintOutputProcessing(util::ParamData& d, const void* input, void* /* output */) { - std::tuple* tuple = (std::tuple*) input; + typedef std::tuple> TupleType; + TupleType* tuple = (TupleType*) input; - PrintOutputProcessing::type>(d, - std::get<0>(*tuple), std::get<1>(*tuple)); + PrintOutputProcessing::type>(std::get<0>(*tuple), + d, std::get<0>(std::get<1>(*tuple)), std::get<1>(std::get<1>(*tuple))); } } // namespace python diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index e85e0fa082..569cb9e39e 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -29,16 +29,17 @@ namespace python { * @param doc Documentation for the program. * @param mainFilename Filename of the main program (i.e. * "/path/to/pca_main.cpp"). - * @param functionName Name of the function (i.e. "pca"). + * @param bindingName Name of the binding (i.e. "pca"). */ void PrintPYX(const util::BindingDetails& doc, const string& mainFilename, - const string& functionName) + const string& bindingName) { - // Restore parameters. - IO::RestoreSettings(doc.programName); + std::string functionName = bindingName + "_py"; - std::map& parameters = IO::Parameters(); + util::Params p = IO::Parameters(bindingName); + + std::map& parameters = p.Parameters(); typedef std::map::iterator ParamIter; // Split into input and output parameters. Take two passes on the input @@ -75,6 +76,8 @@ void PrintPYX(const util::BindingDetails& doc, cout << "cimport arma" << endl; cout << "cimport arma_numpy" << endl; cout << "from io cimport IO" << endl; + cout << "from params cimport Params" << endl; + cout << "from timers cimport Timers" << endl; cout << "from io cimport SetParam, SetParamPtr, SetParamWithInfo, " << "GetParamPtr" << endl; cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, " @@ -97,7 +100,7 @@ void PrintPYX(const util::BindingDetails& doc, // Import the program we will be using. cout << "cdef extern from \"<" << mainFilename << ">\" nogil:" << endl; - cout << " cdef void mlpackMain() nogil except +RuntimeError" << endl; + cout << " cdef void " << bindingName << "(Params, Timers)" << " nogil except +RuntimeError" << endl; cout << " " << endl; // Print any class definitions we need to have. std::set classes; @@ -107,7 +110,7 @@ void PrintPYX(const util::BindingDetails& doc, if (classes.count(d.cppType) == 0) { const size_t indent = 2; - IO::GetSingleton().functionMap[d.tname]["ImportDecl"](d, (void*) &indent, + p.functionMap[d.tname]["ImportDecl"](d, (void*) &indent, NULL); // Make sure we don't double-print the definition. @@ -122,7 +125,7 @@ void PrintPYX(const util::BindingDetails& doc, { util::ParamData& d = it->second; if (d.input) - IO::GetSingleton().functionMap[d.tname]["PrintClassDefn"](d, NULL, NULL); + p.functionMap[d.tname]["PrintClassDefn"](d, NULL, NULL); } // Print the definition. @@ -131,11 +134,10 @@ void PrintPYX(const util::BindingDetails& doc, for (size_t i = 0; i < inputOptions.size(); ++i) { util::ParamData& d = parameters.at(inputOptions[i]); - if (i != 0) cout << "," << endl << std::string(indent, ' '); - IO::GetSingleton().functionMap[d.tname]["PrintDefn"](d, NULL, NULL); + p.functionMap[d.tname]["PrintDefn"](d, NULL, NULL); } // Print closing brace for function definition. @@ -143,7 +145,7 @@ void PrintPYX(const util::BindingDetails& doc, // Print the comment describing the function and its parameters. cout << " \"\"\"" << endl; - cout << " " << doc.programName << endl; + cout << " " << doc.name << endl; cout << endl; // Print the description. @@ -164,7 +166,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << " "; size_t indent = 4; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, (void*) &indent, + p.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, NULL); cout << endl; } @@ -177,7 +179,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << " "; size_t indent = 4; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, (void*) &indent, + p.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, NULL); cout << endl; } @@ -192,16 +194,17 @@ void PrintPYX(const util::BindingDetails& doc, cout << " DisableBacktrace()" << endl; cout << " DisableVerbose()" << endl; - // Restore the parameters. - cout << " IO.RestoreSettings(\"" << doc.programName << "\")" + // Get the Params object from IO. + cout << " cdef Params p = IO.Parameters(\"" << bindingName << "\")" << endl; + cout << " cdef Timers t" << endl; // Determine whether or not we need to copy parameters. cout << " if isinstance(copy_all_inputs, bool):" << endl; cout << " if copy_all_inputs:" << endl; - cout << " SetParam[cbool]( 'copy_all_inputs', " + cout << " SetParam[cbool](p, 'copy_all_inputs', " << "copy_all_inputs)" << endl; - cout << " IO.SetPassed( 'copy_all_inputs')" << endl; + cout << " p.SetPassed( 'copy_all_inputs')" << endl; cout << " else:" << endl; cout << " raise TypeError(" <<"\"'copy_all_inputs\' must have type " << "\'bool'!\")" << endl; @@ -213,7 +216,7 @@ void PrintPYX(const util::BindingDetails& doc, util::ParamData& d = parameters.at(inputOptions[i]); size_t indent = 2; - IO::GetSingleton().functionMap[d.tname]["PrintInputProcessing"](d, + p.functionMap[d.tname]["PrintInputProcessing"](d, (void*) &indent, NULL); } @@ -222,7 +225,7 @@ void PrintPYX(const util::BindingDetails& doc, for (size_t i = 0; i < outputOptions.size(); ++i) { util::ParamData& d = parameters.at(outputOptions[i]); - cout << " IO.SetPassed( '" << d.name << "')" << endl; + cout << " p.SetPassed( '" << d.name << "')" << endl; } // Checking the type of check_input_matrices parameter. @@ -234,29 +237,28 @@ void PrintPYX(const util::BindingDetails& doc, // Before calling mlpackMain(), we check input matrices for NaN values if // needed. cout << " if check_input_matrices:" << endl; - cout << " IO.CheckInputMatrices()" << endl; + cout << " p.CheckInputMatrices()" << endl; // Call the method. cout << " # Call the mlpack program." << endl; - cout << " mlpackMain()" << endl; + cout << " " << bindingName << "(p, t)" << endl; // Do any output processing and return. cout << " # Initialize result dictionary." << endl; cout << " result = {}" << endl; cout << endl; + typedef std::tuple> TupleType; + for (size_t i = 0; i < outputOptions.size(); ++i) { util::ParamData& d = parameters.at(outputOptions[i]); std::tuple t = std::make_tuple(2, false); - IO::GetSingleton().functionMap[d.tname]["PrintOutputProcessing"](d, - (void*) &t, NULL); + TupleType tWithParams= std::make_tuple(p, t); + p.functionMap[d.tname]["PrintOutputProcessing"](d, + (void*) &tWithParams, NULL); } - - // Clear the parameters. - cout << endl; - cout << " IO.ClearSettings()" << endl; cout << endl; cout << " return result" << endl; diff --git a/src/mlpack/bindings/python/py_option.hpp b/src/mlpack/bindings/python/py_option.hpp index e698feb9e9..c26170a55e 100644 --- a/src/mlpack/bindings/python/py_option.hpp +++ b/src/mlpack/bindings/python/py_option.hpp @@ -27,9 +27,6 @@ namespace mlpack { namespace bindings { namespace python { -// Defined in mlpack_main.hpp. -extern std::string programName; - /** * The Python option class. */ @@ -39,8 +36,7 @@ class PyOption public: /** * Construct a PyOption object. When constructed, it will register itself - * with IO. The testName parameter is not used and added for compatibility - * reasons. + * with IO. */ PyOption(const T defaultValue, const std::string& identifier, @@ -80,17 +76,17 @@ class PyOption // pointers will be used by both the program that generates the pyx, and // also the binding itself. (The binding itself will only use GetParam, // GetPrintableParam, and GetRawParam.) - IO::AddFunction(tname, "GetParam", &GetParam); - IO::AddFunction(tname, "GetPrintableParam", &GetPrintableParam); - IO::AddFunction(tname, "DefaultParam", &DefaultParam); + IO::AddFunction(data.tname, "GetParam", &GetParam); + IO::AddFunction(data.tname, "GetPrintableParam", &GetPrintableParam); + IO::AddFunction(data.tname, "DefaultParam", &DefaultParam); // These are used by the pyx generator. - IO::AddFunction(tname, "PrintClassDefn", &PrintClassDefn); - IO::AddFunction(tname, "PrintDefn", &PrintDefn); - IO::AddFunction(tname, "PrintDoc", &PrintDoc); - IO::AddFunction(tname, "PrintOutputProcessing", &PrintOutputProcessing); - IO::AddFunction(tname, "PrintInputProcessing", &PrintInputProcessing); - IO::AddFunction(tname, "ImportDecl", &ImportDecl); + IO::AddFunction(data.tname, "PrintClassDefn", &PrintClassDefn); + IO::AddFunction(data.tname, "PrintDefn", &PrintDefn); + IO::AddFunction(data.tname, "PrintDoc", &PrintDoc); + IO::AddFunction(data.tname, "PrintOutputProcessing", &PrintOutputProcessing); + IO::AddFunction(data.tname, "PrintInputProcessing", &PrintInputProcessing); + IO::AddFunction(data.tname, "ImportDecl", &ImportDecl); // Add the ParamData object to the IO class // for the correct binding name. diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index ec989b8403..858028eea7 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -172,7 +172,8 @@ using Option = mlpack::bindings::tests::TestOption; * PRINT_PARAM_STRING() returns a string that contains the correct * language-specific representation of a parameter's name. */ -#define PRINT_PARAM_STRING mlpack::bindings::python::ParamString +#define PRINT_PARAM_STRING(x) mlpack::bindings::python::ParamString( \ + STRINGIFY(BINDING_NAME), x) /** * PRINT_PARAM_VALUE() returns a string that contains a correct @@ -205,7 +206,8 @@ using Option = mlpack::bindings::tests::TestOption; * BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or * not a specific parameter check should be ignored. */ -#define BINDING_IGNORE_CHECK mlpack::bindings::python::IgnoreCheck +#define BINDING_IGNORE_CHECK(x) mlpack::bindings::python::IgnoreCheck( \ + STRINGIFY(BINDING_NAME), x) namespace mlpack { namespace util { @@ -216,21 +218,14 @@ using Option = mlpack::bindings::python::PyOption; } } -static const std::string testName = ""; #include -// TODO: fix this... -#undef BINDING_USER_NAME -#define BINDING_USER_NAME(NAME) static \ - mlpack::util::ProgramName \ - io_programname_dummy_object = mlpack::util::ProgramName(NAME); \ - namespace mlpack { \ - namespace bindings { \ - namespace python { \ - std::string programName = NAME; \ - } \ - } \ - } +// These parameters should not be registered to any BINDING_NAME, +// they are registered under "". +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME PARAM_FLAG("verbose", "Display informational messages and the full list of " "parameters and timers at the end of execution.", "v"); diff --git a/src/mlpack/core/util/params.cpp b/src/mlpack/core/util/params.cpp index 5cf3ee5799..cfd9b0fd11 100644 --- a/src/mlpack/core/util/params.cpp +++ b/src/mlpack/core/util/params.cpp @@ -25,6 +25,11 @@ Params::Params(const std::map& aliases, // Nothing to do. } +Params::Params() +{ + // Nothing to do. +} + /** * Return `true` if the specified parameter was given. * diff --git a/src/mlpack/core/util/params.hpp b/src/mlpack/core/util/params.hpp index 577133071c..00cd31a908 100644 --- a/src/mlpack/core/util/params.hpp +++ b/src/mlpack/core/util/params.hpp @@ -34,6 +34,11 @@ class Params const std::string& bindingName, const BindingDetails& doc); + /** + * Empty constructor. For wrapping in bindings. + */ + Params(); + /** * Return `true` if the specified parameter was given. * diff --git a/src/mlpack/methods/CMakeLists.txt b/src/mlpack/methods/CMakeLists.txt index 4268a2e1bc..3e0fd695b4 100644 --- a/src/mlpack/methods/CMakeLists.txt +++ b/src/mlpack/methods/CMakeLists.txt @@ -1,54 +1,54 @@ # Recurse into each method mlpack provides. set(DIRS # mvu # Note: this implementation of MVU does not work. See #189. - adaboost - amf - ann - approx_kfn - bias_svd - bayesian_linear_regression - block_krylov_svd - cf - dbscan - decision_tree - det - emst - fastmks - gmm - hmm - hoeffding_trees - kde - kernel_pca - kmeans - lars + # adaboost + # amf + # ann + # approx_kfn + # bias_svd + # bayesian_linear_regression + # block_krylov_svd + # cf + # dbscan + # decision_tree + # det + # emst + # fastmks + # gmm + # hmm + # hoeffding_trees + # kde + # kernel_pca + # kmeans + # lars linear_regression - linear_svm - lmnn - local_coordinate_coding - logistic_regression - lsh - matrix_completion - mean_shift - naive_bayes - nca - neighbor_search - nmf - nystroem_method - pca - perceptron - preprocess - quic_svd - radical - random_forest - randomized_svd - range_search - rann - regularized_svd - reinforcement_learning - softmax_regression - sparse_autoencoder - sparse_coding - svdplusplus + # linear_svm + # lmnn + # local_coordinate_coding + # logistic_regression + # lsh + # matrix_completion + # mean_shift + # naive_bayes + # nca + # neighbor_search + # nmf + # nystroem_method + # pca + # perceptron + # preprocess + # quic_svd + # radical + # random_forest + # randomized_svd + # range_search + # rann + # regularized_svd + # reinforcement_learning + # softmax_regression + # sparse_autoencoder + # sparse_coding + # svdplusplus ) foreach(dir ${DIRS}) diff --git a/src/mlpack/methods/linear_regression/linear_regression_main.cpp b/src/mlpack/methods/linear_regression/linear_regression_main.cpp index a01baf8e63..ea015085e6 100644 --- a/src/mlpack/methods/linear_regression/linear_regression_main.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression_main.cpp @@ -19,6 +19,11 @@ #include +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME linear_regression + #include "linear_regression.hpp" using namespace mlpack; From 20e114a8248732fe5718c2028e4a671c4ed6da83 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 26 Jun 2021 20:31:18 +0200 Subject: [PATCH 450/729] Yeah, Julia bindings too. Signed-off-by: Omar Shrit --- src/mlpack/bindings/julia/default_param.hpp | 24 +++++++++---------- .../bindings/julia/default_param_impl.hpp | 22 ++++++++--------- .../bindings/julia/get_printable_param.hpp | 22 ++++++++--------- .../bindings/julia/get_printable_type.hpp | 14 +++++------ .../julia/get_printable_type_impl.hpp | 14 +++++------ .../bindings/julia/print_type_doc_impl.hpp | 14 +++++------ 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/mlpack/bindings/julia/default_param.hpp b/src/mlpack/bindings/julia/default_param.hpp index 4c61cec7e6..fca7d4a488 100644 --- a/src/mlpack/bindings/julia/default_param.hpp +++ b/src/mlpack/bindings/julia/default_param.hpp @@ -26,12 +26,12 @@ namespace julia { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return the default value of a vector option. @@ -39,7 +39,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a string option. @@ -47,7 +47,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a matrix option, a tuple option, a @@ -57,10 +57,10 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */ = 0); + arma::mat>>::value>::type* = 0); /** * Return the default value of a model option (this returns the default @@ -69,8 +69,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Return the default value of an option. This is the function that will be diff --git a/src/mlpack/bindings/julia/default_param_impl.hpp b/src/mlpack/bindings/julia/default_param_impl.hpp index 9b975989e1..f1a71e7cf2 100644 --- a/src/mlpack/bindings/julia/default_param_impl.hpp +++ b/src/mlpack/bindings/julia/default_param_impl.hpp @@ -24,12 +24,12 @@ namespace julia { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; if (std::is_same::value) @@ -46,7 +46,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { // Print each element in an array delimited by square brackets. std::ostringstream oss; @@ -89,7 +89,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { const std::string& s = *boost::any_cast(&data.value); return "\"" + s + "\""; @@ -102,7 +102,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */) @@ -134,8 +134,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { return "nothing"; } diff --git a/src/mlpack/bindings/julia/get_printable_param.hpp b/src/mlpack/bindings/julia/get_printable_param.hpp index a7c241857e..f6e7e442bc 100644 --- a/src/mlpack/bindings/julia/get_printable_param.hpp +++ b/src/mlpack/bindings/julia/get_printable_param.hpp @@ -25,11 +25,11 @@ namespace julia { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -42,7 +42,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const T& t = boost::any_cast(data.value); @@ -58,7 +58,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Get the matrix. const T& matrix = boost::any_cast(data.value); @@ -74,8 +74,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::ostringstream oss; oss << data.cppType << " model at " << boost::any_cast(data.value); @@ -88,8 +88,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // Get the matrix. const T& tuple = boost::any_cast(data.value); diff --git a/src/mlpack/bindings/julia/get_printable_type.hpp b/src/mlpack/bindings/julia/get_printable_type.hpp index 5d4a24c3ee..9fa2a03fec 100644 --- a/src/mlpack/bindings/julia/get_printable_type.hpp +++ b/src/mlpack/bindings/julia/get_printable_type.hpp @@ -23,11 +23,11 @@ namespace julia { template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -60,8 +60,8 @@ std::string GetPrintableType( template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. diff --git a/src/mlpack/bindings/julia/get_printable_type_impl.hpp b/src/mlpack/bindings/julia/get_printable_type_impl.hpp index f11c92dd8c..bbf32869b2 100644 --- a/src/mlpack/bindings/julia/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/julia/get_printable_type_impl.hpp @@ -26,11 +26,11 @@ namespace julia { template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { if (std::is_same::value) return "Bool"; @@ -102,8 +102,8 @@ std::string GetPrintableType( template std::string GetPrintableType( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { std::string type = util::StripType(data.cppType); if (type == "mlpackModel") diff --git a/src/mlpack/bindings/julia/print_type_doc_impl.hpp b/src/mlpack/bindings/julia/print_type_doc_impl.hpp index 7e6da1f606..6b72612f69 100644 --- a/src/mlpack/bindings/julia/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/julia/print_type_doc_impl.hpp @@ -24,11 +24,11 @@ namespace julia { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { // A flag type. if (std::is_same::value) @@ -153,8 +153,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& /* data */, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "An mlpack model pointer. `` refers to the type of model that " "is being stored, so, e.g., for `CF()`, the type will be `CFModel`. " From 7e6dea54968857e68625708f7a73353f5ee28d83 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sat, 26 Jun 2021 20:37:52 +0200 Subject: [PATCH 451/729] Ooops, a missing file Signed-off-by: Omar Shrit --- src/mlpack/bindings/julia/print_type_doc.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mlpack/bindings/julia/print_type_doc.hpp b/src/mlpack/bindings/julia/print_type_doc.hpp index 407fa3ee1d..eabda5a067 100644 --- a/src/mlpack/bindings/julia/print_type_doc.hpp +++ b/src/mlpack/bindings/julia/print_type_doc.hpp @@ -25,11 +25,11 @@ namespace julia { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -62,8 +62,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. From f751dbea53665e4bd4f02a56b74722a4ce70e4f4 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 27 Jun 2021 07:57:59 +0530 Subject: [PATCH 452/729] removed unnecessary imports from timers.pxd --- src/mlpack/bindings/python/mlpack/timers.pxd | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/timers.pxd b/src/mlpack/bindings/python/mlpack/timers.pxd index 9b5bd6fb58..f7549f3fa6 100644 --- a/src/mlpack/bindings/python/mlpack/timers.pxd +++ b/src/mlpack/bindings/python/mlpack/timers.pxd @@ -1,6 +1,6 @@ #!/usr/bin/env python """ -params.pxd: Cython functionality for mlpack::util::Params. +params.pxd: Cython wrapper for Timers. This file imports the GetParam() function from mlpack::IO, plus a utility SetParam() function because Cython can't seem to support lvalue references. @@ -11,8 +11,6 @@ terms of the 3-clause BSD license. You should have received a copy of the http://www.opensource.org/licenses/BSD-3-Clause for more information. """ cimport cython -from libcpp.string cimport string -from libcpp cimport bool cdef extern from "" namespace "mlpack::util" nogil: cdef cppclass Timers: From 007530d285c9ecc831f6b33d1fa72f8a25dd71a1 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 27 Jun 2021 07:59:55 +0530 Subject: [PATCH 453/729] style fix print_doc_functions.hpp --- src/mlpack/bindings/python/print_doc_functions_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp index aa41c0233f..33ba918243 100644 --- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp @@ -377,14 +377,14 @@ inline std::string ParamString(const std::string& paramName, const T& value) } inline bool IgnoreCheck(const std::string& bindingName, - const std::string& paramName) + const std::string& paramName) { util::Params p = IO::Parameters(bindingName); return !p.Parameters()[paramName].input; } inline bool IgnoreCheck(const std::string& bindingName, - const std::vector& constraints) + const std::vector& constraints) { util::Params p = IO::Parameters(bindingName); From 096abf598653ef22996e4ba801d06e9fe5697f02 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 27 Jun 2021 08:02:05 +0530 Subject: [PATCH 454/729] style fix print_doc_functions_impl --- .../bindings/python/print_doc_functions_impl.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp index 33ba918243..4982b68db9 100644 --- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp @@ -110,7 +110,7 @@ inline std::string PrintValue(const bool& value, bool quotes) inline std::string PrintDefault(const std::string& bindingName, const std::string& paramName) { - util::Params p = IO::Parameters(bindingName); + util::Params p = IO::Parameters(bindingName); if (p.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); @@ -253,7 +253,7 @@ std::string ProgramCall(const std::string& programName, Args... args) */ inline std::string ProgramCall(const std::string& programName) // TODO: here programName is the bindingName?? { - util::Params params = IO::Parameters(programName); + util::Params params = IO::Parameters(programName); std::ostringstream oss; oss << ">>> "; @@ -379,14 +379,14 @@ inline std::string ParamString(const std::string& paramName, const T& value) inline bool IgnoreCheck(const std::string& bindingName, const std::string& paramName) { - util::Params p = IO::Parameters(bindingName); + util::Params p = IO::Parameters(bindingName); return !p.Parameters()[paramName].input; } inline bool IgnoreCheck(const std::string& bindingName, const std::vector& constraints) { - util::Params p = IO::Parameters(bindingName); + util::Params p = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { @@ -398,11 +398,11 @@ inline bool IgnoreCheck(const std::string& bindingName, } inline bool IgnoreCheck( - const std::string& bindingName, + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName) { - util::Params p = IO::Parameters(bindingName); + util::Params p = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { From 2be89a32785c8944b2459c113cf487cab176bcfb Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sun, 27 Jun 2021 08:05:02 +0530 Subject: [PATCH 455/729] style fix mlpack_main --- src/mlpack/core/util/mlpack_main.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index 858028eea7..ca8bfd2aa0 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -207,7 +207,7 @@ using Option = mlpack::bindings::tests::TestOption; * not a specific parameter check should be ignored. */ #define BINDING_IGNORE_CHECK(x) mlpack::bindings::python::IgnoreCheck( \ - STRINGIFY(BINDING_NAME), x) + STRINGIFY(BINDING_NAME), x) namespace mlpack { namespace util { @@ -223,7 +223,7 @@ using Option = mlpack::bindings::python::PyOption; // These parameters should not be registered to any BINDING_NAME, // they are registered under "". #ifdef BINDING_NAME - #undef BINDING_NAME + #undef BINDING_NAME #endif #define BINDING_NAME From 863c5672e5a7f7c8272d15d752d8088a48293508 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 27 Jun 2021 16:29:36 +0200 Subject: [PATCH 456/729] Add the R bindings Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/default_param.hpp | 22 ++--- src/mlpack/bindings/R/default_param_impl.hpp | 22 ++--- src/mlpack/bindings/R/get_printable_param.hpp | 22 ++--- src/mlpack/bindings/R/get_printable_type.hpp | 84 +++++++++---------- .../bindings/R/get_printable_type_impl.hpp | 84 +++++++++---------- src/mlpack/bindings/R/get_r_type.hpp | 76 ++++++++--------- src/mlpack/bindings/R/get_type.hpp | 80 +++++++++--------- .../bindings/R/print_input_processing.hpp | 18 ++-- .../bindings/R/print_output_processing.hpp | 18 ++-- src/mlpack/bindings/R/print_type_doc.hpp | 20 ++--- src/mlpack/bindings/R/print_type_doc_impl.hpp | 20 ++--- 11 files changed, 233 insertions(+), 233 deletions(-) diff --git a/src/mlpack/bindings/R/default_param.hpp b/src/mlpack/bindings/R/default_param.hpp index 4d50eb16f5..8fdf41dfbf 100644 --- a/src/mlpack/bindings/R/default_param.hpp +++ b/src/mlpack/bindings/R/default_param.hpp @@ -26,12 +26,12 @@ namespace r { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return the default value of a vector option. @@ -39,7 +39,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a string option. @@ -47,7 +47,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a matrix option, a tuple option, a @@ -57,7 +57,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */ = 0); @@ -69,8 +69,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Return the default value of an option. This is the function that will be diff --git a/src/mlpack/bindings/R/default_param_impl.hpp b/src/mlpack/bindings/R/default_param_impl.hpp index de529d011a..751834baca 100644 --- a/src/mlpack/bindings/R/default_param_impl.hpp +++ b/src/mlpack/bindings/R/default_param_impl.hpp @@ -24,12 +24,12 @@ namespace r { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; if (std::is_same::value) @@ -46,7 +46,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { // Print each element in an array delimited by square brackets. std::ostringstream oss; @@ -89,7 +89,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { const std::string& s = *boost::any_cast(&data.value); return "\"" + s + "\""; @@ -102,7 +102,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */) @@ -132,8 +132,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { return "NA"; } diff --git a/src/mlpack/bindings/R/get_printable_param.hpp b/src/mlpack/bindings/R/get_printable_param.hpp index b76d62efa8..261d363642 100644 --- a/src/mlpack/bindings/R/get_printable_param.hpp +++ b/src/mlpack/bindings/R/get_printable_param.hpp @@ -25,11 +25,11 @@ namespace r { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -42,7 +42,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const T& t = boost::any_cast(data.value); @@ -58,7 +58,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Get the matrix. const T& matrix = boost::any_cast(data.value); @@ -74,8 +74,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::ostringstream oss; oss << data.cppType << " model at " << boost::any_cast(data.value); @@ -88,8 +88,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // Get the matrix. const T& tuple = boost::any_cast(data.value); diff --git a/src/mlpack/bindings/R/get_printable_type.hpp b/src/mlpack/bindings/R/get_printable_type.hpp index 730422cade..4b19c21cdf 100644 --- a/src/mlpack/bindings/R/get_printable_type.hpp +++ b/src/mlpack/bindings/R/get_printable_type.hpp @@ -23,84 +23,84 @@ namespace r { template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template void GetPrintableType(util::ParamData& d, diff --git a/src/mlpack/bindings/R/get_printable_type_impl.hpp b/src/mlpack/bindings/R/get_printable_type_impl.hpp index cedecdf2ab..a163a615f5 100644 --- a/src/mlpack/bindings/R/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/R/get_printable_type_impl.hpp @@ -22,11 +22,11 @@ namespace r { template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "unknown"; } @@ -34,11 +34,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "integer"; } @@ -46,11 +46,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "numeric"; } @@ -58,11 +58,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "character"; } @@ -70,11 +70,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "integer"; } @@ -82,11 +82,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "logical"; } @@ -94,9 +94,9 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "vector of " + GetPrintableType(d) + "s"; } @@ -104,9 +104,9 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { std::string type = "numeric matrix"; if (std::is_same::value) @@ -127,8 +127,8 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return "categorical matrix/data.frame"; } @@ -136,10 +136,10 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { std::string type = util::StripType(d.cppType); if (type == "mlpackModel") diff --git a/src/mlpack/bindings/R/get_r_type.hpp b/src/mlpack/bindings/R/get_r_type.hpp index a32995dbca..d01559ea66 100644 --- a/src/mlpack/bindings/R/get_r_type.hpp +++ b/src/mlpack/bindings/R/get_r_type.hpp @@ -23,11 +23,11 @@ namespace r { template inline std::string GetRType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { return "unknown"; } @@ -35,11 +35,11 @@ inline std::string GetRType( template<> inline std::string GetRType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "logical"; } @@ -47,11 +47,11 @@ inline std::string GetRType( template<> inline std::string GetRType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "integer"; } @@ -59,11 +59,11 @@ inline std::string GetRType( template<> inline std::string GetRType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "integer"; } @@ -71,11 +71,11 @@ inline std::string GetRType( template<> inline std::string GetRType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "numeric"; } @@ -83,11 +83,11 @@ inline std::string GetRType( template<> inline std::string GetRType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "character"; } @@ -95,7 +95,7 @@ inline std::string GetRType( template inline std::string GetRType( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return GetRType(d) + " vector"; } @@ -103,9 +103,9 @@ inline std::string GetRType( template inline std::string GetRType( util::ParamData& d, - const typename boost::disable_if>>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if>::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::string elemType = GetRType(d); std::string type = "matrix"; @@ -120,8 +120,8 @@ inline std::string GetRType( template inline std::string GetRType( util::ParamData& /* d */, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { return "numeric matrix/data.frame with info"; } @@ -129,8 +129,8 @@ inline std::string GetRType( template inline std::string GetRType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return util::StripType(d.cppType); } diff --git a/src/mlpack/bindings/R/get_type.hpp b/src/mlpack/bindings/R/get_type.hpp index 0437fefab0..574ec6674c 100644 --- a/src/mlpack/bindings/R/get_type.hpp +++ b/src/mlpack/bindings/R/get_type.hpp @@ -24,11 +24,11 @@ namespace r { template inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { return "unknown"; } @@ -36,11 +36,11 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "Int"; } @@ -48,11 +48,11 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "Float"; } @@ -60,11 +60,11 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "Double"; } @@ -72,11 +72,11 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "String"; } @@ -84,11 +84,11 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "Bool"; } @@ -96,9 +96,9 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& d, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { return "Vec" + GetType(d); } @@ -106,9 +106,9 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::string type = ""; if (std::is_same::value) @@ -136,8 +136,8 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& /* d */, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { return "MatWithInfo"; } @@ -145,8 +145,8 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return d.cppType; } diff --git a/src/mlpack/bindings/R/print_input_processing.hpp b/src/mlpack/bindings/R/print_input_processing.hpp index 4565a6d503..34d10d5b1a 100644 --- a/src/mlpack/bindings/R/print_input_processing.hpp +++ b/src/mlpack/bindings/R/print_input_processing.hpp @@ -26,10 +26,10 @@ namespace r { template void PrintInputProcessing( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { if (!d.required) { @@ -72,7 +72,7 @@ void PrintInputProcessing( template void PrintInputProcessing( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { if (!d.required) { @@ -108,8 +108,8 @@ void PrintInputProcessing( template void PrintInputProcessing( util::ParamData& d, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { if (!d.required) { @@ -155,8 +155,8 @@ void PrintInputProcessing( template void PrintInputProcessing( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { if (!d.required) { diff --git a/src/mlpack/bindings/R/print_output_processing.hpp b/src/mlpack/bindings/R/print_output_processing.hpp index 3345f6e437..77c6e4451c 100644 --- a/src/mlpack/bindings/R/print_output_processing.hpp +++ b/src/mlpack/bindings/R/print_output_processing.hpp @@ -26,10 +26,10 @@ namespace r { template void PrintOutputProcessing( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { /** * This gives us code like: @@ -48,7 +48,7 @@ void PrintOutputProcessing( template void PrintOutputProcessing( util::ParamData& d, - const typename boost::enable_if>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0) { @@ -69,8 +69,8 @@ void PrintOutputProcessing( template void PrintOutputProcessing( util::ParamData& d, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { /** * This gives us code like: @@ -89,8 +89,8 @@ void PrintOutputProcessing( template void PrintOutputProcessing( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { /** * This gives us code like: diff --git a/src/mlpack/bindings/R/print_type_doc.hpp b/src/mlpack/bindings/R/print_type_doc.hpp index c6b37ce1e4..92bbd07dbe 100644 --- a/src/mlpack/bindings/R/print_type_doc.hpp +++ b/src/mlpack/bindings/R/print_type_doc.hpp @@ -25,11 +25,11 @@ namespace r { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -37,7 +37,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value>::type* = 0); + const typename std::enable_if::value::value>::type* = 0); /** * Return a string representing the command-line type of a matrix option. @@ -45,7 +45,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value>::type* = 0); + const typename std::enable_if::value::value>::type* = 0); /** * Return a string representing the command-line type of a matrix tuple option. @@ -54,7 +54,7 @@ template std::string PrintTypeDoc( util::ParamData& data, const typename std::enable_if>::value>::type* = 0); + std::tuple>::value::value>::type* = 0); /** * Return a string representing the command-line type of a model. @@ -62,8 +62,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. diff --git a/src/mlpack/bindings/R/print_type_doc_impl.hpp b/src/mlpack/bindings/R/print_type_doc_impl.hpp index b2b87bdbdd..79c03bed48 100644 --- a/src/mlpack/bindings/R/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/R/print_type_doc_impl.hpp @@ -24,11 +24,11 @@ namespace r { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { // A flag type. if (std::is_same::value) @@ -64,7 +64,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value>::type*) + const typename std::enable_if::value::value>::type*) { if (std::is_same>::value) { @@ -86,7 +86,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value>::type*) + const typename std::enable_if::value::value>::type*) { if (std::is_same::value) { @@ -129,7 +129,7 @@ template std::string PrintTypeDoc( util::ParamData& /* data */, const typename std::enable_if>::value>::type*) + std::tuple>::value::value>::type*) { return "A 2-d array containing `numeric` data. Like the regular 2-d matrices" ", this can be a `matrix`, or a `data.frame`. However, this type can also" @@ -146,8 +146,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& /* data */, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "An mlpack model pointer. `` refers to the type of model that " "is being stored, so, e.g., for `cf()`, the type will be `CFModel`. " From fe7bfbbb789b9fe14be35822ea674fe875eb0c2c Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 27 Jun 2021 16:57:27 +0200 Subject: [PATCH 457/729] Python Binding now... Signed-off-by: Omar Shrit --- src/mlpack/bindings/python/default_param.hpp | 24 +++--- .../bindings/python/default_param_impl.hpp | 22 ++--- .../bindings/python/get_cython_type.hpp | 44 +++++----- .../bindings/python/get_printable_param.hpp | 22 ++--- .../bindings/python/get_printable_type.hpp | 84 +++++++++---------- .../python/get_printable_type_impl.hpp | 84 +++++++++---------- src/mlpack/bindings/python/import_decl.hpp | 10 +-- .../bindings/python/print_class_defn.hpp | 10 +-- .../python/print_input_processing.hpp | 36 ++++---- .../python/print_output_processing.hpp | 18 ++-- src/mlpack/bindings/python/print_type_doc.hpp | 14 ++-- .../bindings/python/print_type_doc_impl.hpp | 14 ++-- 12 files changed, 191 insertions(+), 191 deletions(-) diff --git a/src/mlpack/bindings/python/default_param.hpp b/src/mlpack/bindings/python/default_param.hpp index 15504a74b4..36a6b19c32 100644 --- a/src/mlpack/bindings/python/default_param.hpp +++ b/src/mlpack/bindings/python/default_param.hpp @@ -26,12 +26,12 @@ namespace python { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return the default value of a vector option. @@ -39,7 +39,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a string option. @@ -47,7 +47,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a matrix option, a tuple option, a @@ -57,10 +57,10 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */ = 0); + arma::mat>>::value>::type* = 0); /** * Return the default value of a model option (this returns the default @@ -69,8 +69,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Return the default value of an option. This is the function that will be diff --git a/src/mlpack/bindings/python/default_param_impl.hpp b/src/mlpack/bindings/python/default_param_impl.hpp index 15c7f344ae..d953c2efb2 100644 --- a/src/mlpack/bindings/python/default_param_impl.hpp +++ b/src/mlpack/bindings/python/default_param_impl.hpp @@ -24,12 +24,12 @@ namespace python { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; if (std::is_same::value) @@ -46,7 +46,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { // Print each element in an array delimited by square brackets. std::ostringstream oss; @@ -89,7 +89,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { const std::string& s = *boost::any_cast(&data.value); return "'" + s + "'"; @@ -102,7 +102,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */) @@ -134,8 +134,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { return "None"; } diff --git a/src/mlpack/bindings/python/get_cython_type.hpp b/src/mlpack/bindings/python/get_cython_type.hpp index bb01da538e..705b785758 100644 --- a/src/mlpack/bindings/python/get_cython_type.hpp +++ b/src/mlpack/bindings/python/get_cython_type.hpp @@ -23,9 +23,9 @@ namespace python { template inline std::string GetCythonType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return "unknown"; } @@ -33,9 +33,9 @@ inline std::string GetCythonType( template<> inline std::string GetCythonType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "int"; } @@ -43,9 +43,9 @@ inline std::string GetCythonType( template<> inline std::string GetCythonType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "double"; } @@ -53,9 +53,9 @@ inline std::string GetCythonType( template<> inline std::string GetCythonType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "string"; } @@ -63,9 +63,9 @@ inline std::string GetCythonType( template<> inline std::string GetCythonType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "size_t"; } @@ -73,9 +73,9 @@ inline std::string GetCythonType( template<> inline std::string GetCythonType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "cbool"; } @@ -83,7 +83,7 @@ inline std::string GetCythonType( template inline std::string GetCythonType( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return "vector[" + GetCythonType(d) + "]"; } @@ -91,7 +91,7 @@ inline std::string GetCythonType( template inline std::string GetCythonType( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { std::string type = "Mat"; if (T::is_row) @@ -105,8 +105,8 @@ inline std::string GetCythonType( template inline std::string GetCythonType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return d.cppType + "*"; } diff --git a/src/mlpack/bindings/python/get_printable_param.hpp b/src/mlpack/bindings/python/get_printable_param.hpp index effdf4f07b..44ab825687 100644 --- a/src/mlpack/bindings/python/get_printable_param.hpp +++ b/src/mlpack/bindings/python/get_printable_param.hpp @@ -25,11 +25,11 @@ namespace python { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -42,7 +42,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const T& t = boost::any_cast(data.value); @@ -58,7 +58,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Get the matrix. const T& matrix = boost::any_cast(data.value); @@ -74,8 +74,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::ostringstream oss; oss << data.cppType << " model at " << boost::any_cast(data.value); @@ -88,8 +88,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // Get the matrix. const T& tuple = boost::any_cast(data.value); diff --git a/src/mlpack/bindings/python/get_printable_type.hpp b/src/mlpack/bindings/python/get_printable_type.hpp index 2b7cfb40ed..41593e4681 100644 --- a/src/mlpack/bindings/python/get_printable_type.hpp +++ b/src/mlpack/bindings/python/get_printable_type.hpp @@ -23,84 +23,84 @@ namespace python { template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template void GetPrintableType(util::ParamData& d, diff --git a/src/mlpack/bindings/python/get_printable_type_impl.hpp b/src/mlpack/bindings/python/get_printable_type_impl.hpp index 0181079aa1..9494065b4b 100644 --- a/src/mlpack/bindings/python/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/python/get_printable_type_impl.hpp @@ -22,11 +22,11 @@ namespace python { template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "unknown"; } @@ -34,11 +34,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "int"; } @@ -46,11 +46,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "float"; } @@ -58,11 +58,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "str"; } @@ -70,11 +70,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "int"; } @@ -82,11 +82,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "bool"; } @@ -94,9 +94,9 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "list of " + GetPrintableType(d) + "s"; } @@ -104,9 +104,9 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { std::string type = "matrix"; if (std::is_same::value) @@ -127,8 +127,8 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return "categorical matrix"; } @@ -136,10 +136,10 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return d.cppType + "Type"; } diff --git a/src/mlpack/bindings/python/import_decl.hpp b/src/mlpack/bindings/python/import_decl.hpp index b060a66dfe..e6518ce461 100644 --- a/src/mlpack/bindings/python/import_decl.hpp +++ b/src/mlpack/bindings/python/import_decl.hpp @@ -26,8 +26,8 @@ template void ImportDecl( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // First, we have to parse the type. If we have something like, e.g., // 'LogisticRegression<>', we must convert this to 'LogisticRegression[T=*].' @@ -53,8 +53,8 @@ template void ImportDecl( util::ParamData& /* d */, const size_t /* indent */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Print nothing. } @@ -66,7 +66,7 @@ template void ImportDecl( util::ParamData& /* d */, const size_t /* indent */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Print nothing. } diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index ff1de4b26e..53d07d11e7 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -25,8 +25,8 @@ namespace python { template void PrintClassDefn( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Do nothing. } @@ -37,7 +37,7 @@ void PrintClassDefn( template void PrintClassDefn( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Do nothing. } @@ -48,8 +48,8 @@ void PrintClassDefn( template void PrintClassDefn( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // First, we have to parse the type. If we have something like, e.g., // 'LogisticRegression<>', we must convert this to 'LogisticRegression[].' diff --git a/src/mlpack/bindings/python/print_input_processing.hpp b/src/mlpack/bindings/python/print_input_processing.hpp index c4a8ed5006..5137db40e9 100644 --- a/src/mlpack/bindings/python/print_input_processing.hpp +++ b/src/mlpack/bindings/python/print_input_processing.hpp @@ -31,11 +31,11 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { // The copy_all_inputs parameter must be handled first, and therefore is // outside the scope of this code. @@ -164,11 +164,11 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -251,8 +251,8 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -372,9 +372,9 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // First, get the correct class name if needed. std::string strippedType, printedType, defaultsType; @@ -445,9 +445,9 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { // The user should pass in a matrix type of some sort. const std::string prefix(indent, ' '); diff --git a/src/mlpack/bindings/python/print_output_processing.hpp b/src/mlpack/bindings/python/print_output_processing.hpp index af1ef95a93..e9c89200b3 100644 --- a/src/mlpack/bindings/python/print_output_processing.hpp +++ b/src/mlpack/bindings/python/print_output_processing.hpp @@ -30,10 +30,10 @@ void PrintOutputProcessing( util::ParamData& d, const size_t indent, const bool onlyOutput, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -86,7 +86,7 @@ void PrintOutputProcessing( util::ParamData& d, const size_t indent, const bool onlyOutput, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -128,8 +128,8 @@ void PrintOutputProcessing( util::ParamData& d, const size_t indent, const bool onlyOutput, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -170,8 +170,8 @@ void PrintOutputProcessing( util::ParamData& d, const size_t indent, const bool onlyOutput, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Get the type names we need to use. std::string strippedType, printedType, defaultsType; diff --git a/src/mlpack/bindings/python/print_type_doc.hpp b/src/mlpack/bindings/python/print_type_doc.hpp index 88186faafb..aad90ee4b7 100644 --- a/src/mlpack/bindings/python/print_type_doc.hpp +++ b/src/mlpack/bindings/python/print_type_doc.hpp @@ -25,11 +25,11 @@ namespace python { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -62,8 +62,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 8ab5986721..64b6ca3e22 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -24,11 +24,11 @@ namespace python { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { // A flag type. if (std::is_same::value) @@ -150,8 +150,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& /* data */, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "An mlpack model pointer. This type can be pickled to or from disk, " "and internally holds a pointer to C++ memory containing the mlpack " From c6e76d5919d84b3dc50ccc68367dd00f6a9eb409 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 27 Jun 2021 17:20:27 +0200 Subject: [PATCH 458/729] GO also, could not check it locally, hard to install gonum Signed-off-by: Omar Shrit --- src/mlpack/bindings/go/default_param.hpp | 24 +++--- src/mlpack/bindings/go/default_param_impl.hpp | 22 +++--- src/mlpack/bindings/go/get_go_type.hpp | 76 +++++++++---------- .../bindings/go/get_printable_param.hpp | 22 +++--- src/mlpack/bindings/go/get_printable_type.hpp | 74 +++++++++--------- .../bindings/go/get_printable_type_impl.hpp | 74 +++++++++--------- src/mlpack/bindings/go/get_type.hpp | 44 +++++------ src/mlpack/bindings/go/print_defn_input.hpp | 18 ++--- src/mlpack/bindings/go/print_defn_output.hpp | 18 ++--- .../bindings/go/print_input_processing.hpp | 18 ++--- .../bindings/go/print_method_config.hpp | 18 ++--- src/mlpack/bindings/go/print_method_init.hpp | 18 ++--- .../bindings/go/print_output_processing.hpp | 18 ++--- src/mlpack/bindings/go/print_type_doc.hpp | 14 ++-- .../bindings/go/print_type_doc_impl.hpp | 14 ++-- 15 files changed, 236 insertions(+), 236 deletions(-) diff --git a/src/mlpack/bindings/go/default_param.hpp b/src/mlpack/bindings/go/default_param.hpp index 7469b30ac3..4b967b270e 100644 --- a/src/mlpack/bindings/go/default_param.hpp +++ b/src/mlpack/bindings/go/default_param.hpp @@ -26,12 +26,12 @@ namespace go { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return the default value of a vector option. @@ -39,7 +39,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a string option. @@ -47,7 +47,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return the default value of a matrix option, a tuple option, a @@ -57,10 +57,10 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */ = 0); + arma::mat>>::value>::type* = 0); /** * Return the default value of a model option (this returns the default @@ -69,8 +69,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Return the default value of an option. This is the function that will be diff --git a/src/mlpack/bindings/go/default_param_impl.hpp b/src/mlpack/bindings/go/default_param_impl.hpp index e3a9a07103..4d3c0feca1 100644 --- a/src/mlpack/bindings/go/default_param_impl.hpp +++ b/src/mlpack/bindings/go/default_param_impl.hpp @@ -24,12 +24,12 @@ namespace go { template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; if (std::is_same::value) @@ -46,7 +46,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { // Print each element in an array delimited by square brackets. std::ostringstream oss; @@ -90,7 +90,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& data, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*) { const std::string& s = *boost::any_cast(&data.value); return "\"" + s + "\""; @@ -102,7 +102,7 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::enable_if_c< + const typename std::enable_if< arma::is_arma_type::value || std::is_same>::value>::type* /* junk */) @@ -134,8 +134,8 @@ std::string DefaultParamImpl( template std::string DefaultParamImpl( util::ParamData& /* data */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { return "nil"; } diff --git a/src/mlpack/bindings/go/get_go_type.hpp b/src/mlpack/bindings/go/get_go_type.hpp index 77c851cb99..55bafb2ddb 100644 --- a/src/mlpack/bindings/go/get_go_type.hpp +++ b/src/mlpack/bindings/go/get_go_type.hpp @@ -25,11 +25,11 @@ namespace go { template inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { return "unknown"; } @@ -37,11 +37,11 @@ inline std::string GetGoType( template<> inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "int"; } @@ -49,11 +49,11 @@ inline std::string GetGoType( template<> inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "float32"; } @@ -61,11 +61,11 @@ inline std::string GetGoType( template<> inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "float64"; } @@ -73,11 +73,11 @@ inline std::string GetGoType( template<> inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "string"; } @@ -85,11 +85,11 @@ inline std::string GetGoType( template<> inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "bool"; } @@ -97,7 +97,7 @@ inline std::string GetGoType( template inline std::string GetGoType( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return "[]" + GetGoType(d); } @@ -105,9 +105,9 @@ inline std::string GetGoType( template inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::disable_if>>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if>::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return "mat.Dense"; } @@ -115,8 +115,8 @@ inline std::string GetGoType( template inline std::string GetGoType( util::ParamData& /* d */, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { return "matrixWithInfo"; } @@ -124,8 +124,8 @@ inline std::string GetGoType( template inline std::string GetGoType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::string goStrippedType, strippedType, printedType, defaultsType; StripType(d.cppType, goStrippedType, strippedType, printedType, defaultsType); diff --git a/src/mlpack/bindings/go/get_printable_param.hpp b/src/mlpack/bindings/go/get_printable_param.hpp index 90e5f74590..091bfcba80 100644 --- a/src/mlpack/bindings/go/get_printable_param.hpp +++ b/src/mlpack/bindings/go/get_printable_param.hpp @@ -25,11 +25,11 @@ namespace go { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -42,7 +42,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const T& t = boost::any_cast(data.value); @@ -58,7 +58,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Get the matrix. const T& matrix = boost::any_cast(data.value); @@ -74,8 +74,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { std::ostringstream oss; oss << data.cppType << " model at " << boost::any_cast(data.value); @@ -88,8 +88,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // Get the matrix. const T& tuple = boost::any_cast(data.value); diff --git a/src/mlpack/bindings/go/get_printable_type.hpp b/src/mlpack/bindings/go/get_printable_type.hpp index 014fcad297..b16533da18 100644 --- a/src/mlpack/bindings/go/get_printable_type.hpp +++ b/src/mlpack/bindings/go/get_printable_type.hpp @@ -23,75 +23,75 @@ namespace go { template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*); + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*); template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); template void GetPrintableType(util::ParamData& d, diff --git a/src/mlpack/bindings/go/get_printable_type_impl.hpp b/src/mlpack/bindings/go/get_printable_type_impl.hpp index da4df3bec9..921f5f53a1 100644 --- a/src/mlpack/bindings/go/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/go/get_printable_type_impl.hpp @@ -23,11 +23,11 @@ namespace go { template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "unknown"; } @@ -35,11 +35,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "int"; } @@ -47,11 +47,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "float64"; } @@ -59,11 +59,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "string"; } @@ -71,11 +71,11 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "bool"; } @@ -83,9 +83,9 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { return "array of " + GetPrintableType(d) + "s"; } @@ -93,9 +93,9 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { std::string type = "*mat.Dense"; if (T::is_row || T::is_col) @@ -107,8 +107,8 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& /* d */, - const typename boost::enable_if>>::type*) + const typename std::enable_if>::value>::type*) { return "matrixWithInfo"; } @@ -116,10 +116,10 @@ inline std::string GetPrintableType( template inline std::string GetPrintableType( util::ParamData& d, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { std::string goStrippedType, strippedType, printedType, defaultsType; StripType(d.cppType, goStrippedType, strippedType, printedType, defaultsType); diff --git a/src/mlpack/bindings/go/get_type.hpp b/src/mlpack/bindings/go/get_type.hpp index c46c87651d..0a1417ccab 100644 --- a/src/mlpack/bindings/go/get_type.hpp +++ b/src/mlpack/bindings/go/get_type.hpp @@ -24,9 +24,9 @@ namespace go { template inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return "unknown"; } @@ -34,9 +34,9 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "Int"; } @@ -44,9 +44,9 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "Float"; } @@ -54,9 +54,9 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "Double"; } @@ -64,9 +64,9 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "String"; } @@ -74,9 +74,9 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "Bool"; } @@ -84,7 +84,7 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return "Vec" + GetType(d); } @@ -92,7 +92,7 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { std::string type = ""; if (std::is_same::value) @@ -120,8 +120,8 @@ inline std::string GetType( template inline std::string GetType( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return d.cppType + "*"; } diff --git a/src/mlpack/bindings/go/print_defn_input.hpp b/src/mlpack/bindings/go/print_defn_input.hpp index 5ae6662a97..c51dfa110b 100644 --- a/src/mlpack/bindings/go/print_defn_input.hpp +++ b/src/mlpack/bindings/go/print_defn_input.hpp @@ -28,10 +28,10 @@ namespace go { template void PrintDefnInput( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { if (d.required) { @@ -46,7 +46,7 @@ void PrintDefnInput( template void PrintDefnInput( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // param_name *mat.Dense if (d.required) @@ -62,8 +62,8 @@ void PrintDefnInput( template void PrintDefnInput( util::ParamData& d, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // param_name *DataWithInfo if (d.required) @@ -79,8 +79,8 @@ void PrintDefnInput( template void PrintDefnInput( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Get the type names we need to use. std::string goStrippedType, strippedType, printedType, defaultsType; diff --git a/src/mlpack/bindings/go/print_defn_output.hpp b/src/mlpack/bindings/go/print_defn_output.hpp index fa70517f10..b18233d1d0 100644 --- a/src/mlpack/bindings/go/print_defn_output.hpp +++ b/src/mlpack/bindings/go/print_defn_output.hpp @@ -27,10 +27,10 @@ namespace go { template void PrintDefnOutput( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { std::cout << GetGoType(d); } @@ -41,7 +41,7 @@ void PrintDefnOutput( template void PrintDefnOutput( util::ParamData& d, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // *mat.Dense std::cout << "*" << GetGoType(d); @@ -53,8 +53,8 @@ void PrintDefnOutput( template void PrintDefnOutput( util::ParamData& d, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { // *mat.Dense std::cout << "*" << GetGoType(d); @@ -66,8 +66,8 @@ void PrintDefnOutput( template void PrintDefnOutput( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Get the type names we need to use. std::string goStrippedType, strippedType, printedType, defaultsType; diff --git a/src/mlpack/bindings/go/print_input_processing.hpp b/src/mlpack/bindings/go/print_input_processing.hpp index 99b0f9a9ed..8b6fa77eea 100644 --- a/src/mlpack/bindings/go/print_input_processing.hpp +++ b/src/mlpack/bindings/go/print_input_processing.hpp @@ -29,10 +29,10 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -129,7 +129,7 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -189,8 +189,8 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -250,8 +250,8 @@ template void PrintInputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // First, get the correct classparamName if needed. std::string goStrippedType, strippedType, printedType, defaultsType; diff --git a/src/mlpack/bindings/go/print_method_config.hpp b/src/mlpack/bindings/go/print_method_config.hpp index b4be743d1a..6a51d7205d 100644 --- a/src/mlpack/bindings/go/print_method_config.hpp +++ b/src/mlpack/bindings/go/print_method_config.hpp @@ -29,10 +29,10 @@ template void PrintMethodConfig( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -64,7 +64,7 @@ template void PrintMethodConfig( util::ParamData& d, const size_t indent, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -96,8 +96,8 @@ template void PrintMethodConfig( util::ParamData& d, const size_t indent, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -129,8 +129,8 @@ template void PrintMethodConfig( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); diff --git a/src/mlpack/bindings/go/print_method_init.hpp b/src/mlpack/bindings/go/print_method_init.hpp index f1877f48ff..1a9a363c48 100644 --- a/src/mlpack/bindings/go/print_method_init.hpp +++ b/src/mlpack/bindings/go/print_method_init.hpp @@ -29,10 +29,10 @@ template void PrintMethodInit( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -86,7 +86,7 @@ template void PrintMethodInit( util::ParamData& d, const size_t indent, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -118,8 +118,8 @@ template void PrintMethodInit( util::ParamData& d, const size_t indent, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -151,8 +151,8 @@ template void PrintMethodInit( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { const std::string prefix(indent, ' '); diff --git a/src/mlpack/bindings/go/print_output_processing.hpp b/src/mlpack/bindings/go/print_output_processing.hpp index 5a5c77fa74..46cec80184 100644 --- a/src/mlpack/bindings/go/print_output_processing.hpp +++ b/src/mlpack/bindings/go/print_output_processing.hpp @@ -29,10 +29,10 @@ template void PrintOutputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -56,7 +56,7 @@ template void PrintOutputProcessing( util::ParamData& d, const size_t indent, - const typename boost::enable_if>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0) { @@ -83,8 +83,8 @@ template void PrintOutputProcessing( util::ParamData& d, const size_t indent, - const typename boost::enable_if>>::type* = 0) + const typename std::enable_if>::value>::type* = 0) { const std::string prefix(indent, ' '); @@ -109,8 +109,8 @@ template void PrintOutputProcessing( util::ParamData& d, const size_t indent, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Get the type names we need to use. std::string goStrippedType, strippedType, printedType, defaultsType; diff --git a/src/mlpack/bindings/go/print_type_doc.hpp b/src/mlpack/bindings/go/print_type_doc.hpp index 2da51fbb67..b5dde90fa0 100644 --- a/src/mlpack/bindings/go/print_type_doc.hpp +++ b/src/mlpack/bindings/go/print_type_doc.hpp @@ -25,11 +25,11 @@ namespace go { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Return a string representing the command-line type of a vector. @@ -62,8 +62,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print the command-line type of an option into a string. diff --git a/src/mlpack/bindings/go/print_type_doc_impl.hpp b/src/mlpack/bindings/go/print_type_doc_impl.hpp index d0a5fef659..568ef9b059 100644 --- a/src/mlpack/bindings/go/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/go/print_type_doc_impl.hpp @@ -24,11 +24,11 @@ namespace go { template std::string PrintTypeDoc( util::ParamData& data, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>::type*, - const typename boost::disable_if>>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, + const typename std::enable_if>::value>::type*) { // A flag type. if (std::is_same::value) @@ -122,8 +122,8 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& /* data */, - const typename boost::disable_if>::type*, - const typename boost::enable_if>::type*) + const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*) { return "An mlpack model pointer. This type holds a pointer to C++ memory " "containing the mlpack model. Note that this means the mlpack model " From 3c7d044227c5bf455853c33fd9ecb3bca988206e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 27 Jun 2021 17:22:17 +0200 Subject: [PATCH 459/729] Fix value::value, even if it has passed the tests Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/print_type_doc.hpp | 6 +++--- src/mlpack/bindings/R/print_type_doc_impl.hpp | 6 +++--- src/mlpack/bindings/cli/set_param.hpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mlpack/bindings/R/print_type_doc.hpp b/src/mlpack/bindings/R/print_type_doc.hpp index 92bbd07dbe..5f0253578b 100644 --- a/src/mlpack/bindings/R/print_type_doc.hpp +++ b/src/mlpack/bindings/R/print_type_doc.hpp @@ -37,7 +37,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value::value>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return a string representing the command-line type of a matrix option. @@ -45,7 +45,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value::value>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Return a string representing the command-line type of a matrix tuple option. @@ -54,7 +54,7 @@ template std::string PrintTypeDoc( util::ParamData& data, const typename std::enable_if>::value::value>::type* = 0); + std::tuple>::value>::type* = 0); /** * Return a string representing the command-line type of a model. diff --git a/src/mlpack/bindings/R/print_type_doc_impl.hpp b/src/mlpack/bindings/R/print_type_doc_impl.hpp index 79c03bed48..bc8ba85f25 100644 --- a/src/mlpack/bindings/R/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/R/print_type_doc_impl.hpp @@ -64,7 +64,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value::value>::type*) + const typename std::enable_if::value>::type*) { if (std::is_same>::value) { @@ -86,7 +86,7 @@ std::string PrintTypeDoc( template std::string PrintTypeDoc( util::ParamData& data, - const typename std::enable_if::value::value>::type*) + const typename std::enable_if::value>::type*) { if (std::is_same::value) { @@ -129,7 +129,7 @@ template std::string PrintTypeDoc( util::ParamData& /* data */, const typename std::enable_if>::value::value>::type*) + std::tuple>::value>::type*) { return "A 2-d array containing `numeric` data. Like the regular 2-d matrices" ", this can be a `matrix`, or a `data.frame`. However, this type can also" diff --git a/src/mlpack/bindings/cli/set_param.hpp b/src/mlpack/bindings/cli/set_param.hpp index f76f058d2e..8fab3e0fb0 100644 --- a/src/mlpack/bindings/cli/set_param.hpp +++ b/src/mlpack/bindings/cli/set_param.hpp @@ -60,7 +60,7 @@ void SetParam( const boost::any& value, const typename std::enable_if::value || std::is_same>::value::value>::type* = 0) + std::tuple>::value>::type* = 0) { // We're setting the string filename. typedef std::tuple::type> TupleType; From dc28faa8b44397653976e8e384f5bf3d99562040 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 27 Jun 2021 17:25:23 +0200 Subject: [PATCH 460/729] Finish with tests Signed-off-by: Omar Shrit --- .../tests/delete_allocated_memory.hpp | 10 ++++----- .../bindings/tests/get_allocated_memory.hpp | 10 ++++----- .../bindings/tests/get_printable_param.hpp | 22 +++++++++---------- .../tests/get_printable_param_impl.hpp | 22 +++++++++---------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/mlpack/bindings/tests/delete_allocated_memory.hpp b/src/mlpack/bindings/tests/delete_allocated_memory.hpp index 08f59d74e8..5dd60fa294 100644 --- a/src/mlpack/bindings/tests/delete_allocated_memory.hpp +++ b/src/mlpack/bindings/tests/delete_allocated_memory.hpp @@ -21,8 +21,8 @@ namespace tests { template void DeleteAllocatedMemoryImpl( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Do nothing. } @@ -30,7 +30,7 @@ void DeleteAllocatedMemoryImpl( template void DeleteAllocatedMemoryImpl( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { // Do nothing. } @@ -38,8 +38,8 @@ void DeleteAllocatedMemoryImpl( template void DeleteAllocatedMemoryImpl( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Delete the allocated memory (hopefully we actually own it). delete *boost::any_cast(&d.value); diff --git a/src/mlpack/bindings/tests/get_allocated_memory.hpp b/src/mlpack/bindings/tests/get_allocated_memory.hpp index 579dbfdc8e..fb4a903b80 100644 --- a/src/mlpack/bindings/tests/get_allocated_memory.hpp +++ b/src/mlpack/bindings/tests/get_allocated_memory.hpp @@ -22,8 +22,8 @@ namespace tests { template void* GetAllocatedMemory( util::ParamData& /* d */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { return NULL; } @@ -31,7 +31,7 @@ void* GetAllocatedMemory( template void* GetAllocatedMemory( util::ParamData& /* d */, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0) { return NULL; } @@ -39,8 +39,8 @@ void* GetAllocatedMemory( template void* GetAllocatedMemory( util::ParamData& d, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0) { // Here we have a model; return its memory location. return *boost::any_cast(&d.value); diff --git a/src/mlpack/bindings/tests/get_printable_param.hpp b/src/mlpack/bindings/tests/get_printable_param.hpp index 556c28bd2f..0bf5e2ff24 100644 --- a/src/mlpack/bindings/tests/get_printable_param.hpp +++ b/src/mlpack/bindings/tests/get_printable_param.hpp @@ -27,11 +27,11 @@ namespace tests { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0); /** * Print a vector option, with spaces between it. @@ -39,7 +39,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Print a matrix option (this just prints the filename). @@ -47,7 +47,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0); /** * Print a serializable class option (this just prints the filename). @@ -55,8 +55,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* = 0, - const typename boost::enable_if>::type* = 0); + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0); /** * Print a mapped matrix option (this just prints the filename). @@ -64,8 +64,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>>::type* = 0); + const typename std::enable_if>::value>::type* = 0); /** * Print an option into a std::string. This should print a short, one-line diff --git a/src/mlpack/bindings/tests/get_printable_param_impl.hpp b/src/mlpack/bindings/tests/get_printable_param_impl.hpp index c14d8a4bed..3a6c604b69 100644 --- a/src/mlpack/bindings/tests/get_printable_param_impl.hpp +++ b/src/mlpack/bindings/tests/get_printable_param_impl.hpp @@ -22,11 +22,11 @@ namespace tests { template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>::type* /* junk */, - const typename boost::disable_if>>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if>::value>::type* /* junk */) { std::ostringstream oss; oss << boost::any_cast(data.value); @@ -37,7 +37,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { const T& t = boost::any_cast(data.value); @@ -51,7 +51,7 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& /* data */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */) { return "matrix type"; } @@ -60,8 +60,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& data, - const typename boost::disable_if>::type* /* junk */, - const typename boost::enable_if>::type* /* junk */) + const typename std::enable_if::value>::type* /* junk */, + const typename std::enable_if::value>::type* /* junk */) { // Extract the string from the tuple that's being held. std::ostringstream oss; @@ -73,8 +73,8 @@ std::string GetPrintableParam( template std::string GetPrintableParam( util::ParamData& /* data */, - const typename boost::enable_if>>::type* /* junk */) + const typename std::enable_if>::value>::type* /* junk */) { return "matrix/DatatsetInfo tuple"; } From 2e0b7980e5acc94f3fb8da3715e5c9b573dedf5a Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 27 Jun 2021 17:31:25 +0200 Subject: [PATCH 461/729] Forgetten one.. Signed-off-by: Omar Shrit --- src/mlpack/bindings/cli/in_place_copy.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/bindings/cli/in_place_copy.hpp b/src/mlpack/bindings/cli/in_place_copy.hpp index d3ed1c9521..f266267bb6 100644 --- a/src/mlpack/bindings/cli/in_place_copy.hpp +++ b/src/mlpack/bindings/cli/in_place_copy.hpp @@ -31,10 +31,10 @@ template void InPlaceCopyInternal( util::ParamData& /* d */, util::ParamData& /* input */, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>::type* = 0, - const typename boost::disable_if>>::type* = 0) + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, + const typename std::enable_if>::value>::type* = 0) { // Nothing to do. } From 1fd6d5e7d3ba679c6022596ccda6a28589211d51 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:17:00 +0530 Subject: [PATCH 462/729] Update src/mlpack/bindings/python/mlpack/timers.pxd Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/mlpack/timers.pxd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/timers.pxd b/src/mlpack/bindings/python/mlpack/timers.pxd index f7549f3fa6..f154d4ebca 100644 --- a/src/mlpack/bindings/python/mlpack/timers.pxd +++ b/src/mlpack/bindings/python/mlpack/timers.pxd @@ -1,6 +1,6 @@ #!/usr/bin/env python """ -params.pxd: Cython wrapper for Timers. +timers.pxd: Cython wrapper for Timers. This file imports the GetParam() function from mlpack::IO, plus a utility SetParam() function because Cython can't seem to support lvalue references. From 6572780785d5e7cb3ebabcaf449a9b6b95fe5b97 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:17:19 +0530 Subject: [PATCH 463/729] Update src/mlpack/bindings/python/print_doc_functions.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_doc_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_doc_functions.hpp b/src/mlpack/bindings/python/print_doc_functions.hpp index 05b1fc1910..63805a2fff 100644 --- a/src/mlpack/bindings/python/print_doc_functions.hpp +++ b/src/mlpack/bindings/python/print_doc_functions.hpp @@ -53,7 +53,7 @@ inline std::string PrintValue(const bool& value, bool quotes); * Given a parameter name, print its corresponding default value. */ inline std::string PrintDefault(const std::string& bindingName, - const std::string& paramName); + const std::string& paramName); // Recursion base case. inline std::string PrintInputOptions(util::Params& params); From 2b340bcd34473185d176f70ca3f1b5186024f91e Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:17:37 +0530 Subject: [PATCH 464/729] Update src/mlpack/bindings/python/print_doc_functions.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_doc_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_doc_functions.hpp b/src/mlpack/bindings/python/print_doc_functions.hpp index 63805a2fff..46730d2174 100644 --- a/src/mlpack/bindings/python/print_doc_functions.hpp +++ b/src/mlpack/bindings/python/print_doc_functions.hpp @@ -114,7 +114,7 @@ inline std::string ParamString(const std::string& paramName); * is an output parameter, this returns true. */ inline bool IgnoreCheck(const std::string& bindingName, - const std::string& paramName); + const std::string& paramName); /** * Print whether or not we should ignore a check on the given set of From 5486b096897718d6517c8ef92836a916e6084f31 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:17:49 +0530 Subject: [PATCH 465/729] Update src/mlpack/bindings/python/print_doc_functions.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_doc_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_doc_functions.hpp b/src/mlpack/bindings/python/print_doc_functions.hpp index 46730d2174..29cec01922 100644 --- a/src/mlpack/bindings/python/print_doc_functions.hpp +++ b/src/mlpack/bindings/python/print_doc_functions.hpp @@ -122,7 +122,7 @@ inline bool IgnoreCheck(const std::string& bindingName, * so if any parameter is an output parameter, this returns true. */ inline bool IgnoreCheck(const std::string& bindingName, - const std::vector& constraints); + const std::vector& constraints); /** * Print whether or not we should ignore a check on the given set of From b38690f84b7b88cc18c6e46c02c08fd18d59dec1 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:17:59 +0530 Subject: [PATCH 466/729] Update src/mlpack/bindings/python/print_doc_functions.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_doc_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_doc_functions.hpp b/src/mlpack/bindings/python/print_doc_functions.hpp index 29cec01922..9e363c1caa 100644 --- a/src/mlpack/bindings/python/print_doc_functions.hpp +++ b/src/mlpack/bindings/python/print_doc_functions.hpp @@ -131,7 +131,7 @@ inline bool IgnoreCheck(const std::string& bindingName, * this returns true. */ inline bool IgnoreCheck( - const std::string& bindingName, + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName); From abb39ec52a955be38961a4c17e4be3ab14319087 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:18:35 +0530 Subject: [PATCH 467/729] Update src/mlpack/bindings/python/print_output_processing.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_output_processing.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_output_processing.hpp b/src/mlpack/bindings/python/print_output_processing.hpp index fb04309fbd..13cae1a83b 100644 --- a/src/mlpack/bindings/python/print_output_processing.hpp +++ b/src/mlpack/bindings/python/print_output_processing.hpp @@ -173,7 +173,7 @@ void PrintOutputProcessing( util::Params& params, util::ParamData& d, const size_t indent, - const bool onlyOutput, + const bool onlyOutput, const typename boost::disable_if>::type* = 0, const typename boost::enable_if>::type* = 0) { From 0d032eb92f2ae474f14200a53026e594060ed810 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Mon, 28 Jun 2021 08:18:46 +0530 Subject: [PATCH 468/729] Update src/mlpack/bindings/python/print_pyx.cpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_pyx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 569cb9e39e..c340a72869 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -255,7 +255,7 @@ void PrintPYX(const util::BindingDetails& doc, util::ParamData& d = parameters.at(outputOptions[i]); std::tuple t = std::make_tuple(2, false); - TupleType tWithParams= std::make_tuple(p, t); + TupleType tWithParams = std::make_tuple(p, t); p.functionMap[d.tname]["PrintOutputProcessing"](d, (void*) &tWithParams, NULL); } From 96703ce69d67093220d78ba0756b71fca99b9fc8 Mon Sep 17 00:00:00 2001 From: Aakash Kaushik Date: Mon, 28 Jun 2021 21:54:38 +0530 Subject: [PATCH 469/729] correcting serialization param --- src/mlpack/methods/ann/layer/batch_norm_impl.hpp | 2 +- src/mlpack/methods/ann/layer/virtual_batch_norm_impl.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/layer/batch_norm_impl.hpp b/src/mlpack/methods/ann/layer/batch_norm_impl.hpp index 8534f9d5ef..1b6637928c 100644 --- a/src/mlpack/methods/ann/layer/batch_norm_impl.hpp +++ b/src/mlpack/methods/ann/layer/batch_norm_impl.hpp @@ -234,7 +234,7 @@ void BatchNorm::serialize( if (cereal::is_loading()) { weights.set_size(size + size, 1); - loading = false; + loading = true; } ar(CEREAL_NVP(eps)); diff --git a/src/mlpack/methods/ann/layer/virtual_batch_norm_impl.hpp b/src/mlpack/methods/ann/layer/virtual_batch_norm_impl.hpp index 7bd20415a2..112c625b9b 100644 --- a/src/mlpack/methods/ann/layer/virtual_batch_norm_impl.hpp +++ b/src/mlpack/methods/ann/layer/virtual_batch_norm_impl.hpp @@ -142,7 +142,7 @@ void VirtualBatchNorm::serialize( if (cereal::is_loading()) { weights.set_size(size + size, 1); - loading = false; + loading = true; } ar(CEREAL_NVP(eps)); From e6ead307efd91c8784af7b187f4e696fb7926d7e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 29 Jun 2021 12:03:01 +0200 Subject: [PATCH 470/729] Let us test the asterix solution * Signed-off-by: Omar Shrit --- CMake/Autodownload.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/Autodownload.cmake b/CMake/Autodownload.cmake index 9d93704801..8302e4733c 100644 --- a/CMake/Autodownload.cmake +++ b/CMake/Autodownload.cmake @@ -50,7 +50,7 @@ macro(get_deps LINK DEPS_NAME PACKAGE) install(DIRECTORY "${Boost_INCLUDE_DIR}/boost" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") else() set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") - install(DIRECTORY "${GENERIC_INCLUDE_DIR}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(DIRECTORY "${GENERIC_INCLUDE_DIR}/*" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") endif() else () message(FATAL_ERROR From 4fea37fc2ae43563dd1611df0f2d3df5a7582c99 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Tue, 29 Jun 2021 12:27:25 +0200 Subject: [PATCH 471/729] No need for Asterix Signed-off-by: Omar Shrit --- CMake/Autodownload.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/Autodownload.cmake b/CMake/Autodownload.cmake index 8302e4733c..4864e5004c 100644 --- a/CMake/Autodownload.cmake +++ b/CMake/Autodownload.cmake @@ -50,7 +50,7 @@ macro(get_deps LINK DEPS_NAME PACKAGE) install(DIRECTORY "${Boost_INCLUDE_DIR}/boost" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") else() set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include") - install(DIRECTORY "${GENERIC_INCLUDE_DIR}/*" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(DIRECTORY "${GENERIC_INCLUDE_DIR}/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") endif() else () message(FATAL_ERROR From fac256a861f9ce73911a174e4fa04f004b85f3fc Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 29 Jun 2021 09:48:28 -0400 Subject: [PATCH 472/729] Attempt to adapt Julia bindings. --- CMake/julia/ConfigureJuliaHCPP.cmake | 20 +- .../bindings/cli/print_doc_functions.hpp | 4 +- src/mlpack/bindings/julia/CMakeLists.txt | 12 +- src/mlpack/bindings/julia/generate_jl.cpp.in | 8 +- src/mlpack/bindings/julia/julia_method.cpp.in | 12 +- src/mlpack/bindings/julia/julia_method.h.in | 2 +- src/mlpack/bindings/julia/julia_option.hpp | 44 +- src/mlpack/bindings/julia/julia_util.cpp | 404 +++++++++++------- src/mlpack/bindings/julia/julia_util.h | 223 +++++----- src/mlpack/bindings/julia/mlpack/io.jl.in | 360 ---------------- src/mlpack/bindings/julia/mlpack/mlpack.jl.in | 2 +- .../bindings/julia/print_doc_functions.hpp | 17 +- .../julia/print_doc_functions_impl.hpp | 95 ++-- .../bindings/julia/print_input_processing.hpp | 6 +- .../julia/print_input_processing_impl.hpp | 18 +- src/mlpack/bindings/julia/print_jl.cpp | 89 ++-- src/mlpack/bindings/julia/print_jl.hpp | 2 +- .../julia/print_output_processing.hpp | 4 +- .../julia/print_output_processing_impl.hpp | 12 +- src/mlpack/core/util/mlpack_main.hpp | 31 +- 20 files changed, 566 insertions(+), 799 deletions(-) delete mode 100644 src/mlpack/bindings/julia/mlpack/io.jl.in diff --git a/CMake/julia/ConfigureJuliaHCPP.cmake b/CMake/julia/ConfigureJuliaHCPP.cmake index 38c7be5cbf..53de18e915 100644 --- a/CMake/julia/ConfigureJuliaHCPP.cmake +++ b/CMake/julia/ConfigureJuliaHCPP.cmake @@ -26,9 +26,11 @@ if (${NUM_MODEL_TYPES} GREATER 0) # Generate the definition. set(MODEL_PTR_DEFNS "${MODEL_PTR_DEFNS} // Get the pointer to a ${MODEL_TYPE} parameter. -void* IO_GetParam${MODEL_SAFE_TYPE}Ptr(const char* paramName); +void* GetParam${MODEL_SAFE_TYPE}Ptr(void* params, const char* paramName); // Set the pointer to a ${MODEL_TYPE} parameter. -void IO_SetParam${MODEL_SAFE_TYPE}Ptr(const char* paramName, void* ptr); +void SetParam${MODEL_SAFE_TYPE}Ptr(void* params, + const char* paramName, + void* ptr); // Delete a ${MODEL_TYPE} pointer. void Delete${MODEL_SAFE_TYPE}Ptr(void* ptr); // Serialize a ${MODEL_TYPE} pointer. @@ -40,16 +42,20 @@ void* Deserialize${MODEL_SAFE_TYPE}Ptr(const char* buffer, const size_t length); # Generate the implementation. set(MODEL_PTR_IMPLS "${MODEL_PTR_IMPLS} // Get the pointer to a ${MODEL_TYPE} parameter. -void* IO_GetParam${MODEL_SAFE_TYPE}Ptr(const char* paramName) +void* GetParam${MODEL_SAFE_TYPE}Ptr(void* params, const char* paramName) { - return (void*) IO::GetParam<${MODEL_TYPE}*>(paramName); + util::Params* p = (util::Params*) params; + return (void*) p->Get<${MODEL_TYPE}*>(paramName); } // Set the pointer to a ${MODEL_TYPE} parameter. -void IO_SetParam${MODEL_SAFE_TYPE}Ptr(const char* paramName, void* ptr) +void SetParam${MODEL_SAFE_TYPE}Ptr(void* params, + const char* paramName, + void* ptr) { - IO::GetParam<${MODEL_TYPE}*>(paramName) = (${MODEL_TYPE}*) ptr; - IO::SetPassed(paramName); + util::Params* p = (util::Params*) params; + p->Get<${MODEL_TYPE}*>(paramName) = (${MODEL_TYPE}*) ptr; + p->SetPassed(paramName); } // Delete a ${MODEL_TYPE} pointer. diff --git a/src/mlpack/bindings/cli/print_doc_functions.hpp b/src/mlpack/bindings/cli/print_doc_functions.hpp index 63cf52575e..a9af686c23 100644 --- a/src/mlpack/bindings/cli/print_doc_functions.hpp +++ b/src/mlpack/bindings/cli/print_doc_functions.hpp @@ -93,7 +93,9 @@ std::string ProcessOptions(util::Params& params, * be. */ template -std::string ProgramCall(const std::string& programName, Args... args); +std::string ProgramCall(const std::string& bindingName, + const std::string& programName, + Args... args); /** * Given a program name, print a program call invocation assuming that all diff --git a/src/mlpack/bindings/julia/CMakeLists.txt b/src/mlpack/bindings/julia/CMakeLists.txt index ef0b6c1dea..d92f5988be 100644 --- a/src/mlpack/bindings/julia/CMakeLists.txt +++ b/src/mlpack/bindings/julia/CMakeLists.txt @@ -73,11 +73,13 @@ if (BUILD_JULIA_BINDINGS) get_property(CYTHON_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) - configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/mlpack/Project.toml.in - ${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/Project.toml) - # Configure io.jl.in with the right suffix for libraries. - configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/mlpack/io.jl.in - ${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/io.jl) + configure_file( + ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/mlpack/Project.toml.in + ${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/Project.toml) + # Configure params.jl.in with the right suffix for libraries. + configure_file( + ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/mlpack/params.jl.in + ${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/params.jl) # Create the empty mlpack.jl file that we will fill with includes using the # exsiting template. Unfortunately COPY doesn't let us change the extension diff --git a/src/mlpack/bindings/julia/generate_jl.cpp.in b/src/mlpack/bindings/julia/generate_jl.cpp.in index 8dbd38470c..34d93b89f8 100644 --- a/src/mlpack/bindings/julia/generate_jl.cpp.in +++ b/src/mlpack/bindings/julia/generate_jl.cpp.in @@ -17,7 +17,6 @@ #endif #include -#include #include // This will include the ParamData options that are part of the program. @@ -31,9 +30,6 @@ using namespace mlpack::util; int main(int /* argc */, char** /* argv */) { - // All the parameters are registered, but stored, so restore them. - // programName is defined in mlpack_main.hpp. - IO::RestoreSettings(programName); - - PrintJL(IO::GetSingleton().doc, "${NAME}", "${MLPACK_JL_LIB_SUFFIX}"); + // All the parameters are registered under the name BINDING_NAME. + PrintJL(STRINGIFY(BINDING_NAME), "${NAME}", "${MLPACK_JL_LIB_SUFFIX}"); } diff --git a/src/mlpack/bindings/julia/julia_method.cpp.in b/src/mlpack/bindings/julia/julia_method.cpp.in index 85ad110268..4c04bcf89a 100644 --- a/src/mlpack/bindings/julia/julia_method.cpp.in +++ b/src/mlpack/bindings/julia/julia_method.cpp.in @@ -9,19 +9,17 @@ #define BINDING_TYPE BINDING_TYPE_JL #include <${PROGRAM_MAIN_FILE}> -static void ${PROGRAM_NAME}_mlpackMain() -{ - mlpackMain(); -} - extern "C" { -bool ${PROGRAM_NAME}() +bool BINDING_NAME(void* params, void* timers) { + util::Params* p = (util::Params*) params; + util::Timers* t = (util::Timers*) timers; + try { - ${PROGRAM_NAME}_mlpackMain(); + BINDING_NAME(*p, *t); return true; } catch (std::runtime_error& e) diff --git a/src/mlpack/bindings/julia/julia_method.h.in b/src/mlpack/bindings/julia/julia_method.h.in index c5ee94c344..b65429b5f4 100644 --- a/src/mlpack/bindings/julia/julia_method.h.in +++ b/src/mlpack/bindings/julia/julia_method.h.in @@ -15,7 +15,7 @@ extern "C" { #endif -bool ${PROGRAM_NAME}(); +bool BINDING_NAME(void* params, void* timers); // This is just used to force Julia to load each .so in the order we need. void loadSymbols(); diff --git a/src/mlpack/bindings/julia/julia_option.hpp b/src/mlpack/bindings/julia/julia_option.hpp index b111d3e66c..e1c5376e5d 100644 --- a/src/mlpack/bindings/julia/julia_option.hpp +++ b/src/mlpack/bindings/julia/julia_option.hpp @@ -27,9 +27,6 @@ namespace mlpack { namespace bindings { namespace julia { -// Defined in mlpack_main.hpp. -extern std::string programName; - /** * The Julia option class. */ @@ -50,7 +47,7 @@ class JuliaOption const bool required = false, const bool input = true, const bool noTranspose = false, - const std::string& /* testName */ = "") + const std::string& bindingName = "") { // Create the ParamData object to give to IO. util::ParamData data; @@ -75,42 +72,31 @@ class JuliaOption // Every parameter we'll get from Julia will have the correct type. data.value = boost::any(defaultValue); - // Restore the parameters for this program. - if (identifier != "verbose") - IO::RestoreSettings(programName, false); - // Set the function pointers that we'll need. All of these function // pointers will be used by both the program that generates the pyx, and // also the binding itself. (The binding itself will only use GetParam, // GetPrintableParam, and GetRawParam.) - IO::GetSingleton().functionMap[data.tname]["GetParam"] = &GetParam; - IO::GetSingleton().functionMap[data.tname]["GetPrintableParam"] = - &GetPrintableParam; + IO::AddFunction(data.tname, "GetParam", &GetParam); + IO::AddFunction(data.tname, "GetPrintableParam", &GetPrintableParam); // These are used by the jl generator. - IO::GetSingleton().functionMap[data.tname]["PrintParamDefn"] = - &PrintParamDefn; - IO::GetSingleton().functionMap[data.tname]["PrintInputParam"] = - &PrintInputParam; - IO::GetSingleton().functionMap[data.tname]["PrintOutputProcessing"] = - &PrintOutputProcessing; - IO::GetSingleton().functionMap[data.tname]["PrintInputProcessing"] = - &PrintInputProcessing; - IO::GetSingleton().functionMap[data.tname]["PrintDoc"] = &PrintDoc; - IO::GetSingleton().functionMap[data.tname]["PrintModelTypeImport"] = - &PrintModelTypeImport; + IO::AddFunction(data.tname, "PrintParamDefn", &PrintParamDefn); + IO::AddFunction(data.tname, "PrintInputParam", &PrintInputParam); + IO::AddFunction(data.tname, "PrintOutputProcessing", + &PrintOutputProcessing); + IO::AddFunction(data.tname, "PrintInputProcessing", + &PrintInputProcessing); + IO::AddFunction(data.tname, "PrintDoc", &PrintDoc); + IO::AddFunction(data.tname, "PrintModelTypeImport", + &PrintModelTypeImport); // This is needed for the Markdown binding output. - IO::GetSingleton().functionMap[data.tname]["DefaultParam"] = - &DefaultParam; + IO::AddFunction(data.tname, "DefaultParam", &DefaultParam); // Add the ParamData object, then store. This is necessary because we may // import more than one .so that uses IO, so we have to keep the options - // separate. programName is a global variable from mlpack_main.hpp. - IO::Add(std::move(data)); - if (identifier != "verbose") - IO::StoreSettings(programName); - IO::ClearSettings(); + // separate. + IO::AddParameter(bindingName, std::move(data)); } }; diff --git a/src/mlpack/bindings/julia/julia_util.cpp b/src/mlpack/bindings/julia/julia_util.cpp index ac8663eab0..9a41665525 100644 --- a/src/mlpack/bindings/julia/julia_util.cpp +++ b/src/mlpack/bindings/julia/julia_util.cpp @@ -19,78 +19,120 @@ using namespace mlpack; extern "C" { /** - * Call IO::RestoreSettings() for a given program name. + * Get a new util::Params object, encoded as a stack-allocated void pointer. + * You are responsible for freeing this! */ -void IO_RestoreSettings(const char* programName) +void* GetParameters(const char* bindingName) { - IO::RestoreSettings(programName); + util::Params* p = new util::Params(IO::Parameters(bindingName)); + return (void*) p; } /** - * Call IO::SetParam(). + * Delete a util::Params object that has been encoded as a void pointer. */ -void IO_SetParamInt(const char* paramName, int paramValue) +void DeleteParameters(void* in) { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Params* p = (util::Params*) in; + delete p; } /** - * Call IO::SetParam(). + * Get a new util::Timers object, encoded as a heap-allocated void pointer. You + * are responsible for freeing this! You can use `DeleteTimers(void*)`. */ -void IO_SetParamDouble(const char* paramName, double paramValue) +void* Timers() { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Timers* t = new util::Timers(); + return (void*) t; } /** - * Call IO::SetParam(). + * Delete a util::Timers object that has been encoded as a void pointer. */ -void IO_SetParamString(const char* paramName, const char* paramValue) +void DeleteTimers(void* in) { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Timers* t = (util::Timers*) in; + delete t; } /** - * Call IO::SetParam(). + * Call params.SetParam(). */ -void IO_SetParamBool(const char* paramName, bool paramValue) +void SetParamInt(void* params, const char* paramName, int paramValue) { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Params* p = (util::Params*) params; + p->Get(paramName) = paramValue; + p->SetPassed(paramName); } /** - * Call IO::SetParam>() to set the length. + * Call params.SetParam(). */ -void IO_SetParamVectorStrLen(const char* paramName, - const size_t length) +void SetParamDouble(void* params, const char* paramName, double paramValue) { - IO::GetParam>(paramName).clear(); - IO::GetParam>(paramName).resize(length); - IO::SetPassed(paramName); + util::Params* p = (util::Params*) params; + p->Get(paramName) = paramValue; + p->SetPassed(paramName); } /** - * Call IO::SetParam>() to set an individual element. + * Call params.SetParam(). */ -void IO_SetParamVectorStrStr(const char* paramName, - const char* str, - const size_t element) +void SetParamString(void* params, const char* paramName, const char* paramValue) { - IO::GetParam>(paramName)[element] = + util::Params* p = (util::Params*) params; + p->Get(paramName) = paramValue; + p->SetPassed(paramName); +} + +/** + * Call params.SetParam(). + */ +void SetParamBool(void* params, const char* paramName, bool paramValue) +{ + util::Params* p = (util::Params*) params; + p->Get(paramName) = paramValue; + p->SetPassed(paramName); +} + +/** + * Call params.SetParam>() to set the length. + */ +void SetParamVectorStrLen(void* params, + const char* paramName, + const size_t length) +{ + util::Params* p = (util::Params*) params; + p->Get>(paramName).clear(); + p->Get>(paramName).resize(length); + p->SetPassed(paramName); +} + +/** + * Call params.SetParam>() to set an individual + * element. + */ +void SetParamVectorStrStr(void* params, + const char* paramName, + const char* str, + const size_t element) +{ + util::Params* p = (util::Params*) params; + p->Get>(paramName)[element] = std::string(str); } /** - * Call IO::SetParam>(). + * Call params.SetParam>(). */ -void IO_SetParamVectorInt(const char* paramName, - int* ints, - const size_t length) +void SetParamVectorInt(void* params, + const char* paramName, + int* ints, + const size_t length) { + util::Params* p = (util::Params*) params; + // Create a std::vector object; unfortunately this requires copying the // vector elements. std::vector vec; @@ -98,100 +140,116 @@ void IO_SetParamVectorInt(const char* paramName, for (size_t i = 0; i < length; ++i) vec[i] = ints[i]; - IO::GetParam>(paramName) = std::move(vec); - IO::SetPassed(paramName); + p->Get>(paramName) = std::move(vec); + p->SetPassed(paramName); } /** - * Call IO::SetParam(). + * Call params.SetParam(). */ -void IO_SetParamMat(const char* paramName, - double* memptr, - const size_t rows, - const size_t cols, - const bool pointsAsRows) +void SetParamMat(void* params, + const char* paramName, + double* memptr, + const size_t rows, + const size_t cols, + const bool pointsAsRows) { + util::Params* p = (util::Params*) params; + // Create the matrix as an alias. arma::mat m(memptr, arma::uword(rows), arma::uword(cols), false, true); - IO::GetParam(paramName) = pointsAsRows ? m.t() : std::move(m); - IO::SetPassed(paramName); + p->Get(paramName) = pointsAsRows ? m.t() : std::move(m); + p->SetPassed(paramName); } /** - * Call IO::SetParam>(). + * Call params.SetParam>(). */ -void IO_SetParamUMat(const char* paramName, - size_t* memptr, - const size_t rows, - const size_t cols, - const bool pointsAsRows) +void SetParamUMat(void* params, + const char* paramName, + size_t* memptr, + const size_t rows, + const size_t cols, + const bool pointsAsRows) { + util::Params* p = (util::Params*) params; + // Create the matrix as an alias. arma::Mat m(memptr, arma::uword(rows), arma::uword(cols), false, true); - IO::GetParam>(paramName) = pointsAsRows ? m.t() : + p->Get>(paramName) = pointsAsRows ? m.t() : std::move(m); - IO::SetPassed(paramName); + p->SetPassed(paramName); } /** - * Call IO::SetParam(). + * Call params.SetParam(). */ -void IO_SetParamRow(const char* paramName, - double* memptr, - const size_t cols) +void SetParamRow(void* params, + const char* paramName, + double* memptr, + const size_t cols) { + util::Params* p = (util::Params*) params; arma::rowvec m(memptr, arma::uword(cols), false, true); - IO::GetParam(paramName) = std::move(m); - IO::SetPassed(paramName); + p->Get(paramName) = std::move(m); + p->SetPassed(paramName); } /** - * Call IO::SetParam>(). + * Call params.SetParam>(). */ -void IO_SetParamURow(const char* paramName, - size_t* memptr, - const size_t cols) +void SetParamURow(void* params, + const char* paramName, + size_t* memptr, + const size_t cols) { + util::Params* p = (util::Params*) params; arma::Row m(memptr, arma::uword(cols), false, true); - IO::GetParam>(paramName) = std::move(m); - IO::SetPassed(paramName); + p->Get>(paramName) = std::move(m); + p->SetPassed(paramName); } /** - * Call IO::SetParam(). + * Call params.SetParam(). */ -void IO_SetParamCol(const char* paramName, - double* memptr, - const size_t rows) +void SetParamCol(void* params, + const char* paramName, + double* memptr, + const size_t rows) { + util::Params* p = (util::Params*) params; arma::vec m(memptr, arma::uword(rows), false, true); - IO::GetParam(paramName) = std::move(m); - IO::SetPassed(paramName); + p->Get(paramName) = std::move(m); + p->SetPassed(paramName); } /** - * Call IO::SetParam>(). + * Call params.SetParam>(). */ -void IO_SetParamUCol(const char* paramName, - size_t* memptr, - const size_t rows) +void SetParamUCol(void* params, + const char* paramName, + size_t* memptr, + const size_t rows) { + util::Params* p = (util::Params*) params; arma::Col m(memptr, arma::uword(rows), false, true); - IO::GetParam>(paramName) = std::move(m); - IO::SetPassed(paramName); + p->Get>(paramName) = std::move(m); + p->SetPassed(paramName); } /** - * Call IO::SetParam>(). + * Call params.SetParam>(). */ -void IO_SetParamMatWithInfo(const char* paramName, - bool* dimensions, - double* memptr, - const size_t rows, - const size_t cols, - const bool pointsAreRows) +void SetParamMatWithInfo(void* params, + const char* paramName, + bool* dimensions, + double* memptr, + const size_t rows, + const size_t cols, + const bool pointsAreRows) { + util::Params* p = (util::Params*) params; data::DatasetInfo d(pointsAreRows ? cols : rows); for (size_t i = 0; i < d.Dimensionality(); ++i) { @@ -200,82 +258,92 @@ void IO_SetParamMatWithInfo(const char* paramName, } arma::mat m(memptr, arma::uword(rows), arma::uword(cols), false, true); - std::get<0>(IO::GetParam>( + std::get<0>(p->Get>( paramName)) = std::move(d); - std::get<1>(IO::GetParam>( + std::get<1>(p->Get>( paramName)) = pointsAreRows ? m.t() : std::move(m); - IO::SetPassed(paramName); + p->SetPassed(paramName); } /** - * Call IO::GetParam(). + * Call params.GetParam(). */ -int IO_GetParamInt(const char* paramName) +int GetParamInt(void* params, const char* paramName) { - return IO::GetParam(paramName); + util::Params* p = (util::Params*) params; + return p->Get(paramName); } /** - * Call IO::GetParam(). + * Call params.GetParam(). */ -double IO_GetParamDouble(const char* paramName) +double GetParamDouble(void* params, const char* paramName) { - return IO::GetParam(paramName); + util::Params* p = (util::Params*) params; + return p->Get(paramName); } /** - * Call IO::GetParam(). + * Call params.GetParam(). */ -const char* IO_GetParamString(const char* paramName) +const char* GetParamString(void* params, const char* paramName) { - return IO::GetParam(paramName).c_str(); + util::Params* p = (util::Params*) params; + return p->Get(paramName).c_str(); } /** - * Call IO::GetParam(). + * Call params.GetParam(). */ -bool IO_GetParamBool(const char* paramName) +bool GetParamBool(void* params, const char* paramName) { - return IO::GetParam(paramName); + util::Params* p = (util::Params*) params; + return p->Get(paramName); } /** - * Call IO::GetParam>() and get the length of the + * Call params.GetParam>() and get the length of the * vector. */ -size_t IO_GetParamVectorStrLen(const char* paramName) +size_t GetParamVectorStrLen(void* params, const char* paramName) { - return IO::GetParam>(paramName).size(); + util::Params* p = (util::Params*) params; + return p->Get>(paramName).size(); } /** - * Call IO::GetParam>() and get the i'th string. + * Call params.GetParam>() and get the i'th string. */ -const char* IO_GetParamVectorStrStr(const char* paramName, const size_t i) +const char* GetParamVectorStrStr(void* params, + const char* paramName, + const size_t i) { - return IO::GetParam>(paramName)[i].c_str(); + util::Params* p = (util::Params*) params; + return p->Get>(paramName)[i].c_str(); } /** - * Call IO::GetParam>() and get the length of the vector. + * Call params.GetParam>() and get the length of the vector. */ -size_t IO_GetParamVectorIntLen(const char* paramName) +size_t GetParamVectorIntLen(void* params, const char* paramName) { - return IO::GetParam>(paramName).size(); + util::Params* p = (util::Params*) params; + return p->Get>(paramName).size(); } /** - * Call IO::GetParam>() and return a pointer to the vector. + * Call params.GetParam>() and return a pointer to the vector. * The vector will be created in-place and it is expected that the calling * function will take ownership. */ -int* IO_GetParamVectorIntPtr(const char* paramName) +int* GetParamVectorIntPtr(void* params, const char* paramName) { - const size_t size = IO::GetParam>(paramName).size(); + util::Params* p = (util::Params*) params; + const size_t size = p->Get>(paramName).size(); int* ints = new int[size]; for (size_t i = 0; i < size; ++i) - ints[i] = IO::GetParam>(paramName)[i]; + ints[i] = p->Get>(paramName)[i]; return ints; } @@ -283,17 +351,19 @@ int* IO_GetParamVectorIntPtr(const char* paramName) /** * Get the number of rows in a matrix parameter. */ -size_t IO_GetParamMatRows(const char* paramName) +size_t GetParamMatRows(void* params, const char* paramName) { - return IO::GetParam(paramName).n_rows; + util::Params* p = (util::Params*) params; + return p->Get(paramName).n_rows; } /** * Get the number of columns in a matrix parameter. */ -size_t IO_GetParamMatCols(const char* paramName) +size_t GetParamMatCols(void* params, const char* paramName) { - return IO::GetParam(paramName).n_cols; + util::Params* p = (util::Params*) params; + return p->Get(paramName).n_cols; } /** @@ -301,11 +371,13 @@ size_t IO_GetParamMatCols(const char* paramName) * Note that this will assume that whatever is calling will take ownership of * the memory! */ -double* IO_GetParamMat(const char* paramName) +double* GetParamMat(void* params, const char* paramName) { + util::Params* p = (util::Params*) params; + // Are we using preallocated memory? If so we have to handle this more // carefully. - arma::mat& mat = IO::GetParam(paramName); + arma::mat& mat = p->Get(paramName); if (mat.n_elem <= arma::arma_config::mat_prealloc) { // Copy the memory to something that we can give back to Julia. @@ -326,17 +398,19 @@ double* IO_GetParamMat(const char* paramName) /** * Get the number of rows in an unsigned matrix parameter. */ -size_t IO_GetParamUMatRows(const char* paramName) +size_t GetParamUMatRows(void* params, const char* paramName) { - return IO::GetParam>(paramName).n_rows; + util::Params* p = (util::Params*) params; + return p->Get>(paramName).n_rows; } /** * Get the number of columns in an unsigned matrix parameter. */ -size_t IO_GetParamUMatCols(const char* paramName) +size_t GetParamUMatCols(void* params, const char* paramName) { - return IO::GetParam>(paramName).n_cols; + util::Params* p = (util::Params*) params; + return p->Get>(paramName).n_cols; } /** @@ -344,9 +418,10 @@ size_t IO_GetParamUMatCols(const char* paramName) * Note that this will assume that whatever is calling will take ownership of * the memory! */ -size_t* IO_GetParamUMat(const char* paramName) +size_t* GetParamUMat(void* params, const char* paramName) { - arma::Mat& mat = IO::GetParam>(paramName); + util::Params* p = (util::Params*) params; + arma::Mat& mat = p->Get>(paramName); // Are we using preallocated memory? If so we have to handle this more // carefully. @@ -370,9 +445,10 @@ size_t* IO_GetParamUMat(const char* paramName) /** * Get the number of rows in a column vector parameter. */ -size_t IO_GetParamColRows(const char* paramName) +size_t GetParamColRows(void* params, const char* paramName) { - return IO::GetParam(paramName).n_rows; + util::Params* p = (util::Params*) params; + return p->Get(paramName).n_rows; } /** @@ -380,11 +456,13 @@ size_t IO_GetParamColRows(const char* paramName) * Note that this will assume that whatever is calling will take ownership of * the memory! */ -double* IO_GetParamCol(const char* paramName) +double* GetParamCol(void* params, const char* paramName) { + util::Params* p = (util::Params*) params; + // Are we using preallocated memory? If so we have to handle this more // carefully. - arma::vec& vec = IO::GetParam(paramName); + arma::vec& vec = p->Get(paramName); if (vec.n_elem <= arma::arma_config::mat_prealloc) { // Copy the memory to something we can give back to Julia. @@ -405,9 +483,10 @@ double* IO_GetParamCol(const char* paramName) /** * Get the number of columns in an unsigned column vector parameter. */ -size_t IO_GetParamUColRows(const char* paramName) +size_t GetParamUColRows(void* params, const char* paramName) { - return IO::GetParam>(paramName).n_rows; + util::Params* p = (util::Params*) params; + return p->Get>(paramName).n_rows; } /** @@ -415,9 +494,11 @@ size_t IO_GetParamUColRows(const char* paramName) * Note that this will assume that whatever is calling will take ownership of * the memory! */ -size_t* IO_GetParamUCol(const char* paramName) +size_t* GetParamUCol(void* params, const char* paramName) { - arma::Col& vec = IO::GetParam>(paramName); + util::Params* p = (util::Params*) params; + + arma::Col& vec = p->Get>(paramName); // Are we using preallocated memory? If so we have to handle this more // carefully. @@ -441,9 +522,10 @@ size_t* IO_GetParamUCol(const char* paramName) /** * Get the number of columns in a row parameter. */ -size_t IO_GetParamRowCols(const char* paramName) +size_t GetParamRowCols(void* params, const char* paramName) { - return IO::GetParam(paramName).n_cols; + util::Params* p = (util::Params*) params; + return p->Get(paramName).n_cols; } /** @@ -451,11 +533,13 @@ size_t IO_GetParamRowCols(const char* paramName) * Note that this will assume that whatever is calling will take ownership of * the memory! */ -double* IO_GetParamRow(const char* paramName) +double* GetParamRow(void* params, const char* paramName) { + util::Params* p = (util::Params*) params; + // Are we using preallocated memory? If so we have to handle this more // carefully. - arma::rowvec& vec = IO::GetParam(paramName); + arma::rowvec& vec = p->Get(paramName); if (vec.n_elem <= arma::arma_config::mat_prealloc) { // Copy the memory to something we can give back to Julia. @@ -476,9 +560,10 @@ double* IO_GetParamRow(const char* paramName) /** * Get the number of columns in a row parameter. */ -size_t IO_GetParamURowCols(const char* paramName) +size_t GetParamURowCols(void* params, const char* paramName) { - return IO::GetParam>(paramName).n_cols; + util::Params* p = (util::Params*) params; + return p->Get>(paramName).n_cols; } /** @@ -486,9 +571,11 @@ size_t IO_GetParamURowCols(const char* paramName) * Note that this will assume that whatever is calling will take ownership of * the memory! */ -size_t* IO_GetParamURow(const char* paramName) +size_t* GetParamURow(void* params, const char* paramName) { - arma::Row& vec = IO::GetParam>(paramName); + util::Params* p = (util::Params*) params; + + arma::Row& vec = p->Get>(paramName); // Are we using preallocated memory? If so we have to handle this more // carefully. @@ -512,18 +599,20 @@ size_t* IO_GetParamURow(const char* paramName) /** * Get the number of rows in a matrix with DatasetInfo parameter. */ -size_t IO_GetParamMatWithInfoRows(const char* paramName) +size_t GetParamMatWithInfoRows(void* params, const char* paramName) { - return std::get<1>(IO::GetParam>( + util::Params* p = (util::Params*) params; + return std::get<1>(p->Get>( paramName)).n_rows; } /** * Get the number of columns in a matrix with DatasetInfo parameter. */ -size_t IO_GetParamMatWithInfoCols(const char* paramName) +size_t GetParamMatWithInfoCols(void* params, const char* paramName) { - return std::get<1>(IO::GetParam>( + util::Params* p = (util::Params*) params; + return std::get<1>(p->Get>( paramName)).n_cols; } @@ -532,10 +621,12 @@ size_t IO_GetParamMatWithInfoCols(const char* paramName) * are categorical. The calling function is expected to handle the memory * management. */ -bool* IO_GetParamMatWithInfoBoolPtr(const char* paramName) +bool* GetParamMatWithInfoBoolPtr(void* params, const char* paramName) { + util::Params* p = (util::Params*) params; + const data::DatasetInfo& d = std::get<0>( - IO::GetParam>(paramName)); + p->Get>(paramName)); bool* dims = new bool[d.Dimensionality()]; for (size_t i = 0; i < d.Dimensionality(); ++i) @@ -548,12 +639,14 @@ bool* IO_GetParamMatWithInfoBoolPtr(const char* paramName) * Get a pointer to the memory of the matrix. The calling function is expected * to own the memory. */ -double* IO_GetParamMatWithInfoPtr(const char* paramName) +double* GetParamMatWithInfoPtr(void* params, const char* paramName) { + util::Params* p = (util::Params*) params; + // Are we using preallocated memory? If so we have to handle this more // carefully. arma::mat& m = std::get<1>( - IO::GetParam>(paramName)); + p->Get>(paramName)); if (m.n_elem <= arma::arma_config::mat_prealloc) { double* newMem = new double[m.n_elem]; @@ -573,7 +666,7 @@ double* IO_GetParamMatWithInfoPtr(const char* paramName) /** * Enable verbose output. */ -void IO_EnableVerbose() +void EnableVerbose() { Log::Info.ignoreInput = false; } @@ -581,25 +674,18 @@ void IO_EnableVerbose() /** * Disable verbose output. */ -void IO_DisableVerbose() +void DisableVerbose() { Log::Info.ignoreInput = true; } -/** - * Reset the state of all timers. - */ -void IO_ResetTimers() -{ - IO::GetSingleton().timer.Reset(); -} - /** * Set an argument as passed to the IO object. */ -void IO_SetPassed(const char* paramName) +void SetPassed(void* params, const char* paramName) { - IO::SetPassed(paramName); + util::Params* p = (util::Params*) params; + p->SetPassed(paramName); } } // extern "C" diff --git a/src/mlpack/bindings/julia/julia_util.h b/src/mlpack/bindings/julia/julia_util.h index 0f93aaeb12..b990678d7f 100644 --- a/src/mlpack/bindings/julia/julia_util.h +++ b/src/mlpack/bindings/julia/julia_util.h @@ -20,273 +20,300 @@ extern "C" #endif /** - * Call IO::RestoreSettings() for a given program name. + * Get a new util::Params object, encoded as a heap-allocated void pointer. + * You are responsible for freeing this! You can use `DeleteParameters(void*)`. */ -void IO_RestoreSettings(const char* programName); +void* GetParameters(const char* bindingName); /** - * Call IO::SetParam(). + * Delete a util::Params object that has been encoded as a void pointer. */ -void IO_SetParamInt(const char* paramName, int paramValue); +void DeleteParameters(void* p); /** - * Call IO::SetParam(). + * Get a new util::Timers object, encoded as a heap-allocated void pointer. You + * are responsible for freeing this! You can use `DeleteTimers(void*)`. */ -void IO_SetParamDouble(const char* paramName, double paramValue); +void* Timers(); /** - * Call IO::SetParam(). + * Delete a util::Timers object that has been encoded as a void pointer. */ -void IO_SetParamString(const char* paramName, const char* paramValue); +void DeleteTimers(void* t); /** - * Call IO::SetParam(). + * Call params.SetParam(). */ -void IO_SetParamBool(const char* paramName, bool paramValue); +void SetParamInt(void* params, const char* paramName, int paramValue); /** - * Call IO::SetParam>() to set the length. + * Call params.SetParam(). */ -void IO_SetParamVectorStrLen(const char* paramName, - const size_t length); +void SetParamDouble(void* params, const char* paramName, double paramValue); /** - * Call IO::SetParam>() to set an individual element. + * Call params.SetParam(). */ -void IO_SetParamVectorStrStr(const char* paramName, - const char* str, - const size_t element); +void SetParamString(void* params, + const char* paramName, + const char* paramValue); /** - * Call IO::SetParam>(). + * Call params.SetParam(). */ -void IO_SetParamVectorInt(const char* paramName, - int* ints, - const size_t length); +void SetParamBool(void* params, const char* paramName, bool paramValue); /** - * Call IO::SetParam(). + * Call params.SetParam>() to set the length. */ -void IO_SetParamMat(const char* paramName, - double* memptr, - const size_t rows, - const size_t cols, - const bool pointsAsRows); +void SetParamVectorStrLen(void* params, + const char* paramName, + const size_t length); /** - * Call IO::SetParam>(). + * Call params.SetParam>() to set an individual + * element. */ -void IO_SetParamUMat(const char* paramName, - size_t* memptr, - const size_t rows, - const size_t cols, - const bool pointsAsRows); +void SetParamVectorStrStr(void* params, + const char* paramName, + const char* str, + const size_t element); /** - * Call IO::SetParam(). + * Call params.SetParam>(). */ -void IO_SetParamRow(const char* paramName, - double* memptr, - const size_t cols); +void SetParamVectorInt(void* params, + const char* paramName, + int* ints, + const size_t length); /** - * Call IO::SetParam>(). + * Call params.SetParam(). */ -void IO_SetParamURow(const char* paramName, - size_t* memptr, - const size_t cols); +void SetParamMat(void* params, + const char* paramName, + double* memptr, + const size_t rows, + const size_t cols, + const bool pointsAsRows); /** - * Call IO::SetParam(). + * Call params.SetParam>(). */ -void IO_SetParamCol(const char* paramName, - double* memptr, - const size_t rows); +void SetParamUMat(void* params, + const char* paramName, + size_t* memptr, + const size_t rows, + const size_t cols, + const bool pointsAsRows); /** - * Call IO::SetParam>(). + * Call params.SetParam(). */ -void IO_SetParamUCol(const char* paramName, - size_t* memptr, - const size_t rows); +void SetParamRow(void* params, + const char* paramName, + double* memptr, + const size_t cols); /** - * Call IO::SetParam>(). + * Call params.SetParam>(). */ -void IO_SetParamMatWithInfo(const char* paramName, - bool* dimensions, - double* memptr, - const size_t rows, - const size_t cols, - const bool pointsAreRows); +void SetParamURow(void* params, + const char* paramName, + size_t* memptr, + const size_t cols); /** - * Call IO::GetParam(). + * Call params.SetParam(). */ -int IO_GetParamInt(const char* paramName); +void SetParamCol(void* params, + const char* paramName, + double* memptr, + const size_t rows); /** - * Call IO::GetParam(). + * Call params.SetParam>(). */ -double IO_GetParamDouble(const char* paramName); +void SetParamUCol(void* params, + const char* paramName, + size_t* memptr, + const size_t rows); /** - * Call IO::GetParam(). + * Call params.SetParam>(). */ -const char* IO_GetParamString(const char* paramName); +void SetParamMatWithInfo(void* params, + const char* paramName, + bool* dimensions, + double* memptr, + const size_t rows, + const size_t cols, + const bool pointsAreRows); /** - * Call IO::GetParam(). + * Call params.GetParam(). */ -bool IO_GetParamBool(const char* paramName); +int GetParamInt(void* params, const char* paramName); /** - * Call IO::GetParam>() and get the length of the + * Call params.GetParam(). + */ +double GetParamDouble(void* params, const char* paramName); + +/** + * Call params.GetParam(). + */ +const char* GetParamString(void* params, const char* paramName); + +/** + * Call params.GetParam(). + */ +bool GetParamBool(void* params, const char* paramName); + +/** + * Call params.GetParam>() and get the length of the * vector. */ -size_t IO_GetParamVectorStrLen(const char* paramName); +size_t GetParamVectorStrLen(void* params, const char* paramName); /** - * Call IO::GetParam>() and get the i'th string. + * Call params.GetParam>() and get the i'th string. */ -const char* IO_GetParamVectorStrStr(const char* paramName, const size_t i); +const char* GetParamVectorStrStr(void* params, + const char* paramName, + const size_t i); /** - * Call IO::GetParam>() and get the length of the vector. + * Call params.GetParam>() and get the length of the vector. */ -size_t IO_GetParamVectorIntLen(const char* paramName); +size_t GetParamVectorIntLen(void* params, const char* paramName); /** - * Call IO::GetParam>() and return a pointer to the vector. + * Call params.GetParam>() and return a pointer to the vector. * The vector will be created in-place and it is expected that the calling * function will take ownership. */ -int* IO_GetParamVectorIntPtr(const char* paramName); +int* GetParamVectorIntPtr(void* params, const char* paramName); /** * Get the number of rows in a matrix parameter. */ -size_t IO_GetParamMatRows(const char* paramName); +size_t GetParamMatRows(void* params, const char* paramName); /** * Get the number of columns in a matrix parameter. */ -size_t IO_GetParamMatCols(const char* paramName); +size_t GetParamMatCols(void* params, const char* paramName); /** * Get the memory pointer for a matrix parameter. * Note that this will assume that whatever is calling will take ownership of * the memory! */ -double* IO_GetParamMat(const char* paramName); +double* GetParamMat(void* params, const char* paramName); /** * Get the number of rows in an unsigned matrix parameter. */ -size_t IO_GetParamUMatRows(const char* paramName); +size_t GetParamUMatRows(void* params, const char* paramName); /** * Get the number of columns in an unsigned matrix parameter. */ -size_t IO_GetParamUMatCols(const char* paramName); +size_t GetParamUMatCols(void* params, const char* paramName); /** * Get the memory pointer for an unsigned matrix parameter. * Note that this will assume that whatever is calling will take ownership of * the memory! */ -size_t* IO_GetParamUMat(const char* paramName); +size_t* GetParamUMat(void* params, const char* paramName); /** * Get the number of rows in a column parameter. */ -size_t IO_GetParamColRows(const char* paramName); +size_t GetParamColRows(void* params, const char* paramName); /** * Get the memory pointer for a column vector parameter. * Note that this will assume that whatever is calling will take ownership of * the memory! */ -double* IO_GetParamCol(const char* paramName); +double* GetParamCol(void* params, const char* paramName); /** * Get the number of columns in an unsigned column vector parameter. */ -size_t IO_GetParamUColRows(const char* paramName); +size_t GetParamUColRows(void* params, const char* paramName); /** * Get the memory pointer for an unsigned column vector parameter. * Note that this will assume that whatever is calling will take ownership of * the memory! */ -size_t* IO_GetParamUCol(const char* paramName); +size_t* GetParamUCol(void* params, const char* paramName); /** * Get the number of columns in a row parameter. */ -size_t IO_GetParamRowCols(const char* paramName); +size_t GetParamRowCols(void* params, const char* paramName); /** * Get the memory pointer for a row parameter. * Note that this will assume that whatever is calling will take ownership of * the memory! */ -double* IO_GetParamRow(const char* paramName); +double* GetParamRow(void* params, const char* paramName); /** * Get the number of columns in a row parameter. */ -size_t IO_GetParamURowCols(const char* paramName); +size_t GetParamURowCols(void* params, const char* paramName); /** * Get the memory pointer for a row parameter. * Note that this will assume that whatever is calling will take ownership of * the memory! */ -size_t* IO_GetParamURow(const char* paramName); +size_t* GetParamURow(void* params, const char* paramName); /** * Get the number of rows in a matrix with DatasetInfo parameter. */ -size_t IO_GetParamMatWithInfoRows(const char* paramName); +size_t GetParamMatWithInfoRows(void* params, const char* paramName); /** * Get the number of columns in a matrix with DatasetInfo parameter. */ -size_t IO_GetParamMatWithInfoCols(const char* paramName); +size_t GetParamMatWithInfoCols(void* params, const char* paramName); /** * Get a pointer to an array of booleans representing whether or not dimensions * are categorical. The calling function is expected to handle the memory * management. */ -bool* IO_GetParamMatWithInfoBoolPtr(const char* paramName); +bool* GetParamMatWithInfoBoolPtr(void* params, const char* paramName); /** * Get a pointer to the memory of the matrix. The calling function is expected * to own the memory. */ -double* IO_GetParamMatWithInfoPtr(const char* paramName); +double* GetParamMatWithInfoPtr(void* params, const char* paramName); /** * Enable verbose output. */ -void IO_EnableVerbose(); +void EnableVerbose(); /** * Disable verbose output. */ -void IO_DisableVerbose(); - -/** - * Reset timers. - */ -void IO_ResetTimers(); +void DisableVerbose(); /** * Set an argument as passed to the IO object. */ -void IO_SetPassed(const char* paramName); +void SetPassed(void* params, const char* paramName); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/src/mlpack/bindings/julia/mlpack/io.jl.in b/src/mlpack/bindings/julia/mlpack/io.jl.in deleted file mode 100644 index 96cb9e3bd9..0000000000 --- a/src/mlpack/bindings/julia/mlpack/io.jl.in +++ /dev/null @@ -1,360 +0,0 @@ -module io - -export IORestoreSettings -export IOSetParam -export IOSetParamMat -export IOSetParamUMat -export IOSetParamRow -export IOSetParamCol -export IOSetParamURow -export IOSetParamUCol -export IOGetParamBool -export IOGetParamInt -export IOGetParamDouble -export IOGetParamString -export IOGetParamVectorStr -export IOGetParamVectorInt -export IOGetParamMat -export IOGetParamUMat -export IOGetParamCol -export IOGetParamRow -export IOGetParamUCol -export IOGetParamURow -export IOGetParamMatWithInfo -export IOEnableVerbose -export IODisableVerbose -export IOSetPassed - -const library = joinpath(@__DIR__, "libmlpack_julia_util${CMAKE_SHARED_LIBRARY_SUFFIX}") - -# Utility function to convert 1d object to 2d. -function convert_to_2d(in::Array{T, 1})::Array{T, 2} where T - reshape(in, length(in), 1) -end - -# Utility function to convert 2d object to 1d. Fails if the size of one -# dimension is not 1. -function convert_to_1d(in::Array{T, 2})::Array{T, 1} where T - if size(in, 1) != 1 && size(in, 2) != 1 - throw(ArgumentError("given matrix must be 1-dimensional; but its size is " * - "$(size(in))")) - end - - vec(in) -end - -# Utility function to convert to and return a matrix. -function to_matrix(input, T::Type) - if isa(input, Array{T, 1}) - convert_to_2d(input) - else - convert(Array{T, 2}, input) - end -end - -# Utility function to convert to and return a vector. -function to_vector(input, T::Type) - if isa(input, Array{T, 1}) - input - else - convert_to_1d(convert(Array{T, 2}, input)) - end -end - -function IORestoreSettings(programName::String) - ccall((:IO_RestoreSettings, library), Nothing, (Cstring,), programName); -end - -function IOSetParam(paramName::String, paramValue::Int) - ccall((:IO_SetParamInt, library), Nothing, (Cstring, Cint), paramName, - Cint(paramValue)); -end - -function IOSetParam(paramName::String, paramValue::Float64) - ccall((:IO_SetParamDouble, library), Nothing, (Cstring, Float64), paramName, - paramValue); -end - -function IOSetParam(paramName::String, paramValue::Bool) - ccall((:IO_SetParamBool, library), Nothing, (Cstring, Bool), paramName, - paramValue); -end - -function IOSetParam(paramName::String, paramValue::String) - ccall((:IO_SetParamString, library), Nothing, (Cstring, Cstring), paramName, - paramValue); -end - -function IOSetParamMat(paramName::String, - paramValue, - pointsAsRows::Bool) - paramMat = to_matrix(paramValue, Float64) - ccall((:IO_SetParamMat, library), Nothing, (Cstring, Ptr{Float64}, Csize_t, - Csize_t, Bool), paramName, Base.pointer(paramMat), size(paramMat, 1), - size(paramMat, 2), pointsAsRows); -end - -function IOSetParamUMat(paramName::String, - paramValue, - pointsAsRows::Bool) - paramMat = to_matrix(paramValue, Int) - - # Sanity check. - if minimum(paramMat) <= 0 - throw(DomainError("Input $(paramName) cannot have 0 or negative values! " * - "Must be 1 or greater.")) - end - - m = convert(Array{Csize_t, 2}, paramMat .- 1) - ccall((:IO_SetParamUMat, library), Nothing, (Cstring, Ptr{Csize_t}, Csize_t, - Csize_t, Bool), paramName, Base.pointer(m), size(paramValue, 1), - size(paramValue, 2), pointsAsRows); -end - -function IOSetParam(paramName::String, - vector::Vector{String}) - # For this we have to set the size of the vector then each string - # sequentially. I am not sure if this is fully necessary but I have some - # reservations about Julia's support for passing arrays of strings correctly - # as a const char**. - ccall((:IO_SetParamVectorStrLen, library), Nothing, (Cstring, Csize_t), - paramName, size(vector, 1)); - for i in 1:size(vector, 1) - ccall((:IO_SetParamVectorStrStr, library), Nothing, (Cstring, Cstring, - Csize_t), paramName, vector[i], i .- 1); - end -end - -function IOSetParam(paramName::String, - vector::Vector{Int}) - cint_vec = convert(Vector{Cint}, vector) - ccall((:IO_SetParamVectorInt, library), Nothing, (Cstring, Ptr{Cint}, - Csize_t), paramName, Base.pointer(cint_vec), size(cint_vec, 1)); -end - -function IOSetParam(paramName::String, - matWithInfo::Tuple{Array{Bool, 1}, Array{Float64, 2}}, - pointsAsRows::Bool) - ccall((:IO_SetParamMatWithInfo, library), Nothing, (Cstring, Ptr{Bool}, - Ptr{Float64}, Int, Int, Bool), paramName, - Base.pointer(matWithInfo[1]), Base.pointer(matWithInfo[2]), - size(matWithInfo[2], 1), size(matWithInfo[2], 2), pointsAsRows); -end - -function IOSetParamRow(paramName::String, - paramValue) - paramVec = to_vector(paramValue, Float64) - ccall((:IO_SetParamRow, library), Nothing, (Cstring, Ptr{Float64}, Csize_t), - paramName, Base.pointer(paramVec), size(paramVec, 1)); -end - -function IOSetParamCol(paramName::String, - paramValue) - paramVec = to_vector(paramValue, Float64) - ccall((:IO_SetParamCol, library), Nothing, (Cstring, Ptr{Float64}, Csize_t), - paramName, Base.pointer(paramVec), size(paramVec, 1)); -end - -function IOSetParamURow(paramName::String, - paramValue) - paramVec = to_vector(paramValue, Int) - - # Sanity check. - if minimum(paramVec) <= 0 - throw(DomainError("Input $(paramName) cannot have 0 or negative values! " * - "Must be 1 or greater.")) - end - m = convert(Array{Csize_t, 1}, paramVec .- 1) - - ccall((:IO_SetParamURow, library), Nothing, (Cstring, Ptr{Csize_t}, Csize_t), - paramName, Base.pointer(m), size(paramValue, 1)); -end - -function IOSetParamUCol(paramName::String, - paramValue) - paramVec = to_vector(paramValue, Int) - - # Sanity check. - if minimum(paramVec) <= 0 - throw(DomainError("Input $(paramName) cannot have 0 or negative values! " * - "Must be 1 or greater.")) - end - m = convert(Array{Csize_t, 1}, paramValue .- 1) - - ccall((:IO_SetParamUCol, library), Nothing, (Cstring, Ptr{Csize_t}, Csize_t), - paramName, Base.pointer(m), size(paramValue, 1)); -end - -function IOGetParamBool(paramName::String) - return ccall((:IO_GetParamBool, library), Bool, (Cstring,), paramName) -end - -function IOGetParamInt(paramName::String) - return Int(ccall((:IO_GetParamInt, library), Cint, (Cstring,), paramName)) -end - -function IOGetParamDouble(paramName::String) - return ccall((:IO_GetParamDouble, library), Float64, (Cstring,), paramName) -end - -function IOGetParamString(paramName::String) - return ccall((:IO_GetParamString, library), Cstring, (Cstring,), paramName) -end - -function IOGetParamVectorStr(paramName::String) - local size::Csize_t - local ptr::Ptr{String} - - # Get the size of the vector, then each element. - size = ccall((:IO_GetParamVectorStrLen, library), Csize_t, (Cstring,), - paramName); - out = Array{String, 1}() - for i = 1:size - s = ccall((:IO_GetParamVectorStrStr, library), Cstring, (Cstring, Csize_t), - paramName, i .- 1) - push!(out, Base.unsafe_string(s)) - end - - return out -end - -function IOGetParamVectorInt(paramName::String) - local size::Csize_t - local ptr::Ptr{Cint} - - # Get the size of the vector, then the pointer to it. We will own the - # pointer. - size = ccall((:IO_GetParamVectorIntLen, library), Csize_t, (Cstring,), - paramName); - ptr = ccall((:IO_GetParamVectorIntPtr, library), Ptr{Cint}, (Cstring,), - paramName); - - return convert(Array{Int, 1}, Base.unsafe_wrap(Array{Cint, 1}, ptr, (size), - own=true)) -end - -function IOGetParamMat(paramName::String, pointsAsRows::Bool) - # Can we return different return types? For now let's restrict to a matrix to - # make it easy... - local ptr::Ptr{Float64} - local rows::Csize_t, cols::Csize_t; - # I suppose it would be possible to do this all in one call, but this seems - # easy enough. - rows = ccall((:IO_GetParamMatRows, library), Csize_t, (Cstring,), paramName); - cols = ccall((:IO_GetParamMatCols, library), Csize_t, (Cstring,), paramName); - ptr = ccall((:IO_GetParamMat, library), Ptr{Float64}, (Cstring,), paramName); - - if pointsAsRows - # In this case we have to transpose, unfortunately. - m = Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), own=true) - return m'; - else - # Here no transpose is necessary. - return Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), own=true); - end -end - -function IOGetParamUMat(paramName::String, pointsAsRows::Bool) - # Can we return different return types? For now let's restrict to a matrix to - # make it easy... - local ptr::Ptr{Csize_t} - local rows::Csize_t, cols::Csize_t; - # I suppose it would be possible to do this all in one call, but this seems - # easy enough. - rows = ccall((:IO_GetParamUMatRows, library), Csize_t, (Cstring,), paramName); - cols = ccall((:IO_GetParamUMatCols, library), Csize_t, (Cstring,), paramName); - ptr = ccall((:IO_GetParamUMat, library), Ptr{Csize_t}, (Cstring,), paramName); - - if pointsAsRows - # In this case we have to transpose, unfortunately. - m = Base.unsafe_wrap(Array{Csize_t, 2}, ptr, (rows, cols), own=true); - return convert(Array{Int, 2}, m' .+ 1) # Add 1 because these are indexes. - else - # Here no transpose is necessary. - m = Base.unsafe_wrap(Array{Csize_t, 2}, ptr, (rows, cols), own=true); - return convert(Array{Int, 2}, m .+ 1) - end -end - -function IOGetParamCol(paramName::String) - local ptr::Ptr{Float64}; - local rows::Csize_t; - - rows = ccall((:IO_GetParamColRows, library), Csize_t, (Cstring,), paramName); - ptr = ccall((:IO_GetParamCol, library), Ptr{Float64}, (Cstring,), paramName); - - return Base.unsafe_wrap(Array{Float64, 1}, ptr, rows, own=true); -end - -function IOGetParamRow(paramName::String) - local ptr::Ptr{Float64}; - local cols::Csize_t; - - cols = ccall((:IO_GetParamRowCols, library), Csize_t, (Cstring,), paramName); - ptr = ccall((:IO_GetParamRow, library), Ptr{Float64}, (Cstring,), paramName); - - return Base.unsafe_wrap(Array{Float64, 1}, ptr, cols, own=true); -end - -function IOGetParamUCol(paramName::String) - local ptr::Ptr{Csize_t}; - local rows::Csize_t; - - rows = ccall((:IO_GetParamUColRows, library), Csize_t, (Cstring,), paramName); - ptr = ccall((:IO_GetParamUCol, library), Ptr{Csize_t}, (Cstring,), paramName); - - m = Base.unsafe_wrap(Array{Csize_t, 1}, ptr, rows, own=true); - return convert(Array{Int, 1}, m .+ 1) -end - -function IOGetParamURow(paramName::String) - local ptr::Ptr{Csize_t}; - local cols::Csize_t; - - cols = ccall((:IO_GetParamURowCols, library), Csize_t, (Cstring,), paramName); - ptr = ccall((:IO_GetParamURow, library), Ptr{Csize_t}, (Cstring,), paramName); - - m = Base.unsafe_wrap(Array{Csize_t, 1}, ptr, cols, own=true); - return convert(Array{Int, 1}, m .+ 1) -end - -function IOGetParamMatWithInfo(paramName::String, pointsAsRows::Bool) - local ptrBool::Ptr{Bool}; - local ptrData::Ptr{Float64}; - local rows::Csize_t; - local cols::Csize_t; - - rows = ccall((:IO_GetParamMatWithInfoRows, library), Csize_t, (Cstring,), - paramName); - cols = ccall((:IO_GetParamMatWithInfoCols, library), Csize_t, (Cstring,), - paramName); - ptrBool = ccall((:IO_GetParamMatWithInfoBoolPtr, library), Ptr{Bool}, - (Cstring,), paramName); - ptrMem = ccall((:IO_GetParamMatWithInfoPtr, library), Ptr{Float64}, - (Cstring,), paramName); - - types = Base.unsafe_wrap(Array{Bool, 1}, ptrBool, (rows), own=true) - if pointsAsRows - # In this case we have to transpose, unfortunately. - m = Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), own=true) - return (types, m'); - else - # Here no transpose is necessary. - return (types, Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), - own=true)); - end -end - -function IOEnableVerbose() - ccall((:IO_EnableVerbose, library), Nothing, ()); -end - -function IODisableVerbose() - ccall((:IO_DisableVerbose, library), Nothing, ()); -end - -function IOSetPassed(paramName::String) - ccall((:IO_SetPassed, library), Nothing, (Cstring,), paramName); -end - -end # module io diff --git a/src/mlpack/bindings/julia/mlpack/mlpack.jl.in b/src/mlpack/bindings/julia/mlpack/mlpack.jl.in index a2c9c6abcf..62ff3704e2 100644 --- a/src/mlpack/bindings/julia/mlpack/mlpack.jl.in +++ b/src/mlpack/bindings/julia/mlpack/mlpack.jl.in @@ -30,4 +30,4 @@ around!) """ module _Internal -include("io.jl") +include("params.jl") diff --git a/src/mlpack/bindings/julia/print_doc_functions.hpp b/src/mlpack/bindings/julia/print_doc_functions.hpp index 9f5d5dcb5e..35a69f10d7 100644 --- a/src/mlpack/bindings/julia/print_doc_functions.hpp +++ b/src/mlpack/bindings/julia/print_doc_functions.hpp @@ -58,7 +58,8 @@ inline std::string PrintValue(const bool& value, bool quotes); /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName); +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName); /** * Print a dataset type parameter. @@ -76,7 +77,7 @@ inline std::string PrintModel(const std::string& model); inline std::string PrintType(util::ParamData& param); // Recursion base case. -inline std::string PrintInputOptions(); +inline std::string PrintInputOptions(util::Params& p); /** * Print an input option. This will throw an exception if the parameter does @@ -84,15 +85,17 @@ inline std::string PrintInputOptions(); * something like x=5. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(util::Params& p, + const std::string& paramName, const T& value, Args... args); // Recursion base case. -inline std::string PrintOutputOptions(); +inline std::string PrintOutputOptions(util::Params& p); template -std::string PrintOutputOptions(const std::string& paramName, +std::string PrintOutputOptions(util::Params& p, + const std::string& paramName, const T& value, Args... args); @@ -101,7 +104,9 @@ std::string PrintOutputOptions(const std::string& paramName, * contents), print the corresponding function call. */ template -std::string ProgramCall(const std::string& programName, Args... args); +std::string ProgramCall(const std::string& bindingName, + const std::string& programName, + Args... args); /** * Given the parameter name, determine what it would actually be when passed to diff --git a/src/mlpack/bindings/julia/print_doc_functions_impl.hpp b/src/mlpack/bindings/julia/print_doc_functions_impl.hpp index 51baf4c81b..b30c17a692 100644 --- a/src/mlpack/bindings/julia/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/julia/print_doc_functions_impl.hpp @@ -107,36 +107,38 @@ inline std::string PrintValue(const bool& value, bool quotes) /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName) +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName) { - if (IO::Parameters().count(paramName) == 0) + util::Params p = IO::Parameters(bindingName); + if (p.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; std::string defaultValue; - IO::GetSingleton().functionMap[d.tname]["DefaultParam"](d, NULL, (void*) - &defaultValue); + p.functionMap[d.tname]["DefaultParam"](d, NULL, (void*) &defaultValue); return defaultValue; } // Recursion base case. -inline std::string CreateInputArguments() { return ""; } +inline std::string CreateInputArguments(util::Params& /* p */) { return ""; } /** * This prints anything that is required to create an input value. We only need * to create input values for matrices. */ template -inline std::string CreateInputArguments(const std::string& paramName, +inline std::string CreateInputArguments(util::Params& p, + const std::string& paramName, const T& value, Args... args) { // We only need to do anything if it is an input option. - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; std::ostringstream oss; if (d.input) @@ -158,7 +160,7 @@ inline std::string CreateInputArguments(const std::string& paramName, } } - oss << CreateInputArguments(args...); + oss << CreateInputArguments(p, args...); return oss.str(); } @@ -201,6 +203,7 @@ inline std::string PrintInputOption(const std::string& paramName, // Base case: no modification needed. inline void GetOptions( + util::Params& /* p */, std::vector>& /* results */, bool /* input */) { @@ -214,6 +217,7 @@ inline void GetOptions( */ template inline void GetOptions( + util::Params& p, std::vector>& results, bool input, const std::string& paramName, @@ -221,9 +225,9 @@ inline void GetOptions( Args... args) { // Determine whether or not the value is required. - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; if (d.input && input) { @@ -239,7 +243,7 @@ inline void GetOptions( results.push_back(std::make_tuple(paramName, oss.str())); } - GetOptions(results, input, args...); + GetOptions(p, results, input, args...); } else { @@ -256,34 +260,32 @@ inline void GetOptions( * the parameter is required. */ template -inline std::string PrintInputOptions(Args... args) +inline std::string PrintInputOptions(util::Params& p, Args... args) { // Gather list of required and non-required options. std::vector inputOptions; - for (auto it = IO::Parameters().begin(); it != IO::Parameters().end(); ++it) + for (auto it = p.Parameters().begin(); it != p.Parameters().end(); ++it) { util::ParamData& d = it->second; if (d.input && d.required) { // Ignore some parameters. - if (d.name != "help" && d.name != "info" && - d.name != "version") + if (d.name != "help" && d.name != "info" && d.name != "version") inputOptions.push_back(it->first); } } - for (auto it = IO::Parameters().begin(); it != IO::Parameters().end(); ++it) + for (auto it = p.Parameters().begin(); it != p.Parameters().end(); ++it) { util::ParamData& d = it->second; - if (d.input && !d.required && - d.name != "help" && d.name != "info" && + if (d.input && !d.required && d.name != "help" && d.name != "info" && d.name != "version") inputOptions.push_back(it->first); } // Now collect the way that we print all the parameters. std::vector> printedParameters; - GetOptions(printedParameters, true, args...); + GetOptions(p, printedParameters, true, args...); // Next, we need to match each option. Note that required options will come // first. @@ -292,7 +294,7 @@ inline std::string PrintInputOptions(Args... args) bool printedAny = false; for (size_t i = 0; i < inputOptions.size(); ++i) { - util::ParamData& d = IO::Parameters()[inputOptions[i]]; + util::ParamData& d = p.Parameters()[inputOptions[i]]; // Does this option exist? bool found = false; size_t index = printedParameters.size(); @@ -342,14 +344,14 @@ inline std::string PrintInputOptions(Args... args) } // Recursion base case. -inline std::string PrintOutputOptions() { return ""; } +inline std::string PrintOutputOptions(util::Params& /* p */) { return ""; } template -inline std::string PrintOutputOptions(Args... args) +inline std::string PrintOutputOptions(util::Params& p, Args... args) { // Get the list of output options for the binding. std::vector outputOptions; - for (auto it = IO::Parameters().begin(); it != IO::Parameters().end(); ++it) + for (auto it = p.Parameters().begin(); it != p.Parameters().end(); ++it) { util::ParamData& d = it->second; if (!d.input) @@ -358,7 +360,7 @@ inline std::string PrintOutputOptions(Args... args) // Now get the full list of output options that we have. std::vector> passedOptions; - GetOptions(passedOptions, false, args...); + GetOptions(p, passedOptions, false, args...); // Next, iterate over all the options. std::ostringstream oss; @@ -401,8 +403,12 @@ inline std::string PrintOutputOptions(Args... args) * contents), print the corresponding function call. */ template -inline std::string ProgramCall(const std::string& programName, Args... args) +inline std::string ProgramCall(const std::string& bindingName, + const std::string& programName, + Args... args) { + util::Params p = IO::Parameters(bindingName); + std::ostringstream oss; // The code should appear in a Markdown code block. @@ -411,7 +417,7 @@ inline std::string ProgramCall(const std::string& programName, Args... args) // Print any input argument definitions. The only input argument definitions // will be the definitions of matrices, which use the CSV.jl package, so we // should also include a `using CSV` in there too. - std::string inputArgs = CreateInputArguments(args...); + std::string inputArgs = CreateInputArguments(p, args...); if (inputArgs != "") inputArgs = "julia> using CSV\n" + inputArgs; @@ -422,13 +428,13 @@ inline std::string ProgramCall(const std::string& programName, Args... args) // Find out if we have any output options first. std::ostringstream ossOutput; - ossOutput << PrintOutputOptions(args...); + ossOutput << PrintOutputOptions(p, args...); if (ossOutput.str() != "") ossCall << ossOutput.str() << " = "; ossCall << programName << "("; // Now process each input option. - ossCall << PrintInputOptions(args...); + ossCall << PrintInputOptions(p, args...); ossCall << ")"; // Since `julia> ` is 8 characters, let's indent 12 otherwise it looks weird. @@ -460,13 +466,16 @@ inline std::string PrintDataset(const std::string& datasetName) /** * Given the name of a binding, print its invocation. */ -inline std::string ProgramCall(const std::string& programName) +inline std::string ProgramCall(const std::string& bindingName, + const std::string& programName) { std::ostringstream result; result << "julia> "; + util::Params p = IO::Parameters(bindingName); + // First, print all output options. - std::map& parameters = IO::Parameters(); + std::map& parameters = p.Parameters(); size_t outputs = 0; for (auto it = parameters.begin(); it != parameters.end(); ++it) { @@ -518,8 +527,8 @@ inline std::string ProgramCall(const std::string& programName) result << it->second.name; result << "="; std::string value; - IO::GetSingleton().functionMap[it->second.tname]["DefaultParam"]( - it->second, NULL, (void*) &value); + p.functionMap[it->second.tname]["DefaultParam"]( it->second, NULL, + (void*) &value); result << value; ++nonreqInputs; } @@ -561,16 +570,20 @@ inline std::string ParamString(const std::string& paramName, const T& value) return oss.str(); } -inline bool IgnoreCheck(const std::string& paramName) +inline bool IgnoreCheck(const std::string& bindingName, + const std::string& paramName) { - return !IO::Parameters()[paramName].input; + util::Params p = IO::Parameters(bindingName); + return !p.Parameters()[paramName].input; } -inline bool IgnoreCheck(const std::vector& constraints) +inline bool IgnoreCheck(const std::string& bindingName, + const std::vector& constraints) { + util::Params p = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i]].input) + if (!p.Parameters()[constraints[i]].input) return true; } @@ -578,16 +591,18 @@ inline bool IgnoreCheck(const std::vector& constraints) } inline bool IgnoreCheck( + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName) { + util::Params p = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i].first].input) + if (!p.Parameters()[constraints[i].first].input) return true; } - return !IO::Parameters()[paramName].input; + return !p.Parameters()[paramName].input; } } // namespace julia diff --git a/src/mlpack/bindings/julia/print_input_processing.hpp b/src/mlpack/bindings/julia/print_input_processing.hpp index 3a4eff7604..cd19359fd3 100644 --- a/src/mlpack/bindings/julia/print_input_processing.hpp +++ b/src/mlpack/bindings/julia/print_input_processing.hpp @@ -17,7 +17,7 @@ namespace bindings { namespace julia { /** - * Print the input processing (basically calling IO::GetParam<>()) for a + * Print the input processing (basically calling params.Get<>()) for a * non-serializable type. */ template @@ -53,7 +53,7 @@ void PrintInputProcessing( std::tuple>::value>::type* = 0); /** - * Print the input processing (basically calling IO::GetParam<>()) for a + * Print the input processing (basically calling params.Get<>()) for a * matrix with DatasetInfo type. */ template @@ -64,7 +64,7 @@ void PrintInputProcessing( std::tuple>::value>::type* = 0); /** - * Print the input processing (basically calling IO::GetParam<>()) for a type. + * Print the input processing (basically calling params.Get<>()) for a type. */ template void PrintInputProcessing(util::ParamData& d, diff --git a/src/mlpack/bindings/julia/print_input_processing_impl.hpp b/src/mlpack/bindings/julia/print_input_processing_impl.hpp index bfb5608929..25c429353c 100644 --- a/src/mlpack/bindings/julia/print_input_processing_impl.hpp +++ b/src/mlpack/bindings/julia/print_input_processing_impl.hpp @@ -41,8 +41,8 @@ void PrintInputProcessing( { // This gives us code like the following: // - // IOSetParam("", ) - std::cout << " IOSetParam(\"" << d.name << "\", " << juliaName << ")" + // SetParam(p, "", ) + std::cout << " SetParam(p, \"" << d.name << "\", " << juliaName << ")" << std::endl; } else @@ -50,10 +50,10 @@ void PrintInputProcessing( // This gives us code like the following: // // if !ismissing() - // IOSetParam("", convert(, )) + // SetParam(p, "", convert(, )) // end std::cout << " if !ismissing(" << juliaName << ")" << std::endl; - std::cout << " IOSetParam(\"" << d.name << "\", convert(" + std::cout << " SetParam(p, \"" << d.name << "\", convert(" << GetJuliaType(d) << ", " << juliaName << "))" << std::endl; std::cout << " end" << std::endl; } @@ -103,7 +103,7 @@ void PrintInputProcessing( } // Now print the IOSetParam call. - std::cout << indent << "IOSetParam" << uChar << matTypeModifier << "(\"" + std::cout << indent << "SetParam" << uChar << matTypeModifier << "(p, \"" << d.name << "\", " << juliaName << extra << ")" << std::endl; if (!d.required) @@ -178,8 +178,8 @@ void PrintInputProcessing( { // This gives us code like the following: // - // IOSetParam("", convert(, )) - std::cout << " IOSetParam(\"" << d.name << "\", convert(" + // IOSetParam(p, "", convert(, )) + std::cout << " SetParam(p, \"" << d.name << "\", convert(" << GetJuliaType(d) << ", " << juliaName << "), points_are_rows)" << std::endl; } @@ -188,10 +188,10 @@ void PrintInputProcessing( // This gives us code like the following: // // if !ismissing() - // IOSetParam("", convert(, )) + // SetParam(p, "", convert(, )) // end std::cout << " if !ismissing(" << juliaName << ")" << std::endl; - std::cout << " IOSetParam(\"" << d.name << "\", convert(" + std::cout << " SetParam(p, \"" << d.name << "\", convert(" << GetJuliaType(d) << ", " << juliaName << "), points_are_rows)" << std::endl; std::cout << " end" << std::endl; diff --git a/src/mlpack/bindings/julia/print_jl.cpp b/src/mlpack/bindings/julia/print_jl.cpp index 6b4c4f5ac0..6fefcbe53e 100644 --- a/src/mlpack/bindings/julia/print_jl.cpp +++ b/src/mlpack/bindings/julia/print_jl.cpp @@ -26,27 +26,26 @@ extern std::string programName; /** * Print the code for a .jl binding for an mlpack program to stdout. */ -void PrintJL(const util::BindingDetails& doc, +void PrintJL(const string& bindingName, const string& functionName, - const std::string& mlpackJuliaLibSuffix) + const string& mlpackJuliaLibSuffix) { - // Restore parameters. - IO::RestoreSettings(doc.programName); + Params p = IO::Parameters(bindingName); + const BindingDetails& doc = p.Doc(); - map& parameters = IO::Parameters(); - typedef map::iterator ParamIter; + map& parameters = p.Parameters(); + typedef map::iterator ParamIter; // First, let's get a list of input and output options. We'll take two passes // so that the required input options are the first in the list. vector inputOptions, outputOptions; for (ParamIter it = parameters.begin(); it != parameters.end(); ++it) { - util::ParamData& d = it->second; + ParamData& d = it->second; if (d.input && d.required) { // Ignore some parameters. - if (d.name != "help" && d.name != "info" && - d.name != "version") + if (d.name != "help" && d.name != "info" && d.name != "version") inputOptions.push_back(it->first); } else if (!d.input) @@ -57,9 +56,8 @@ void PrintJL(const util::BindingDetails& doc, for (ParamIter it = parameters.begin(); it != parameters.end(); ++it) { - util::ParamData& d = it->second; - if (d.input && !d.required && - d.name != "help" && d.name != "info" && + ParamData& d = it->second; + if (d.input && !d.required && d.name != "help" && d.name != "info" && d.name != "version") inputOptions.push_back(it->first); } @@ -72,11 +70,10 @@ void PrintJL(const util::BindingDetails& doc, set classNames; for (ParamIter it = parameters.begin(); it != parameters.end(); ++it) { - util::ParamData& d = it->second; + ParamData& d = it->second; if (classNames.count(d.cppType) == 0) { - IO::GetSingleton().functionMap[d.tname]["PrintModelTypeImport"](d, NULL, - NULL); + p.functionMap[d.tname]["PrintModelTypeImport"](d, NULL, NULL); // Avoid adding this import again. classNames.insert(d.cppType); @@ -85,7 +82,7 @@ void PrintJL(const util::BindingDetails& doc, cout << endl; // We need to include utility functions. - cout << "using mlpack._Internal.io" << endl; + cout << "using mlpack._Internal.params" << endl; cout << endl; // Make sure the libraries we need are accessible. @@ -97,9 +94,9 @@ void PrintJL(const util::BindingDetails& doc, // Define mlpackMain() function to call. cout << "# Call the C binding of the mlpack " << functionName << " binding." << endl; - cout << "function " << functionName << "_mlpackMain()" << endl; + cout << "function call_" << bindingName << "(p, t)" << endl; cout << " success = ccall((:" << functionName << ", " << functionName - << "Library), Bool, ())" << endl; + << "Library), Bool, (Ptr{Nothing}, Ptr{Nothing}), p, t)" << endl; cout << " if !success" << endl; cout << " # Throw an exception---false means there was a C++ exception." << endl; @@ -122,11 +119,10 @@ void PrintJL(const util::BindingDetails& doc, classNames.clear(); for (ParamIter it = parameters.begin(); it != parameters.end(); ++it) { - util::ParamData& d = it->second; + ParamData& d = it->second; if (classNames.count(d.cppType) == 0) { - IO::GetSingleton().functionMap[d.tname]["PrintParamDefn"](d, (void*) - &functionName, NULL); + p.functionMap[d.tname]["PrintParamDefn"](d, (void*) &functionName, NULL); // Avoid adding this definition again. classNames.insert(d.cppType); @@ -146,7 +142,7 @@ void PrintJL(const util::BindingDetails& doc, for (size_t i = 0; i < inputOptions.size(); ++i) { const string& opt = inputOptions[i]; - util::ParamData& d = parameters.at(opt); + ParamData& d = parameters.at(opt); if (!defaults && !d.required) { @@ -182,14 +178,14 @@ void PrintJL(const util::BindingDetails& doc, for (size_t i = 0; i < inputOptions.size(); ++i) { const string& opt = inputOptions[i]; - util::ParamData& d = parameters.at(opt); + ParamData& d = parameters.at(opt); std::ostringstream oss; oss << " - "; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &oss); + p.functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &oss); - cout << util::HyphenateString(oss.str(), 6) << endl; + cout << HyphenateString(oss.str(), 6) << endl; } cout << endl; @@ -199,14 +195,14 @@ void PrintJL(const util::BindingDetails& doc, for (size_t i = 0; i < outputOptions.size(); ++i) { const string& opt = outputOptions[i]; - util::ParamData& d = parameters.at(opt); + ParamData& d = parameters.at(opt); std::ostringstream oss; oss << " - "; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &oss); + p.functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &oss); - cout << util::HyphenateString(oss.str(), 6) << endl; + cout << HyphenateString(oss.str(), 6) << endl; } cout << endl; @@ -222,7 +218,7 @@ void PrintJL(const util::BindingDetails& doc, for (size_t i = 0; i < inputOptions.size(); ++i) { const string& opt = inputOptions[i]; - util::ParamData& d = parameters.at(opt); + ParamData& d = parameters.at(opt); if (!defaults && !d.required) { @@ -234,8 +230,7 @@ void PrintJL(const util::BindingDetails& doc, cout << "," << endl << string(indent, ' '); } - IO::GetSingleton().functionMap[d.tname]["PrintInputParam"](d, NULL, - NULL); + p.functionMap[d.tname]["PrintInputParam"](d, NULL, NULL); } // Print the 'points_are_rows' option. @@ -257,8 +252,9 @@ void PrintJL(const util::BindingDetails& doc, cout << " modelPtrs = Set{Ptr{Nothing}}()" << endl; cout << endl; - // Restore IO settings. - cout << " IORestoreSettings(\"" << programName << "\")" << endl; + // Get an empty Params and Timers object. + cout << " p = IOGetParameters(\"" << bindingName << "\")" << endl; + cout << " t = Timers()" << endl; cout << endl; // Handle each input argument's processing before calling mlpackMain(). @@ -268,30 +264,36 @@ void PrintJL(const util::BindingDetails& doc, { if (opt != "verbose") { - util::ParamData& d = parameters.at(opt); - IO::GetSingleton().functionMap[d.tname]["PrintInputProcessing"](d, - &functionName, NULL); + ParamData& d = parameters.at(opt); + p.functionMap[d.tname]["PrintInputProcessing"](d, &functionName, NULL); } } // Special handling for verbose output. cout << " if verbose !== nothing && verbose === true" << endl; - cout << " IOEnableVerbose()" << endl; + cout << " EnableVerbose()" << endl; cout << " else" << endl; - cout << " IODisableVerbose()" << endl; + cout << " DisableVerbose()" << endl; cout << " end" << endl; cout << endl; // Mark output parameters as passed. for (const string& opt : outputOptions) { - util::ParamData& d = parameters.at(opt); - cout << " IOSetPassed(\"" << d.name << "\")" << endl; + ParamData& d = parameters.at(opt); + cout << " SetPassed(p, \"" << d.name << "\")" << endl; } // Call the program. cout << " # Call the program." << endl; - cout << " " << functionName << "_mlpackMain()" << endl; + cout << " call_" << bindingName << "(p, t)" << endl; + cout << endl; + + // Clean up. + cout << " # We are responsible for cleaning up the `p` and `t` objects." + << endl; + cout << " DeleteParameters(p)" << endl; + cout << " DeleteTimers(t)" << endl; cout << endl; // Extract the results in order. @@ -299,9 +301,8 @@ void PrintJL(const util::BindingDetails& doc, string indentStr(9, ' '); for (size_t i = 0; i < outputOptions.size(); ++i) { - util::ParamData& d = parameters.at(outputOptions[i]); - IO::GetSingleton().functionMap[d.tname]["PrintOutputProcessing"](d, - &functionName, NULL); + ParamData& d = parameters.at(outputOptions[i]); + p.functionMap[d.tname]["PrintOutputProcessing"](d, &functionName, NULL); // Print newlines if we are returning multiple output options. if (i + 1 < outputOptions.size()) diff --git a/src/mlpack/bindings/julia/print_jl.hpp b/src/mlpack/bindings/julia/print_jl.hpp index 5e73f590ff..8b7ea2204d 100644 --- a/src/mlpack/bindings/julia/print_jl.hpp +++ b/src/mlpack/bindings/julia/print_jl.hpp @@ -21,7 +21,7 @@ namespace julia { /** * Print the code for a .jl binding for an mlpack program to stdout. */ -void PrintJL(const util::BindingDetails& doc, +void PrintJL(const std::string& bindingName, const std::string& functionName, const std::string& mlpackJuliaLibSuffix); diff --git a/src/mlpack/bindings/julia/print_output_processing.hpp b/src/mlpack/bindings/julia/print_output_processing.hpp index 7c8e13ac48..e4f72ede36 100644 --- a/src/mlpack/bindings/julia/print_output_processing.hpp +++ b/src/mlpack/bindings/julia/print_output_processing.hpp @@ -19,7 +19,7 @@ namespace bindings { namespace julia { /** - * Print the output processing (basically calling IO::GetParam<>()) for a + * Print the output processing (basically calling params.Get<>()) for a * non-serializable type. */ template @@ -65,7 +65,7 @@ void PrintOutputProcessing( std::tuple>::value>::type* = 0); /** - * Print the output processing (basically calling IO::GetParam<>()) for a type. + * Print the output processing (basically calling params.Get<>()) for a type. */ template void PrintOutputProcessing(util::ParamData& d, diff --git a/src/mlpack/bindings/julia/print_output_processing_impl.hpp b/src/mlpack/bindings/julia/print_output_processing_impl.hpp index 5515fbf2df..1a3b7c0b9d 100644 --- a/src/mlpack/bindings/julia/print_output_processing_impl.hpp +++ b/src/mlpack/bindings/julia/print_output_processing_impl.hpp @@ -22,7 +22,7 @@ namespace bindings { namespace julia { /** - * Print the output processing (basically calling IO::GetParam<>()) for a + * Print the output processing (basically calling params.GetParam<>()) for a * non-serializable type. */ template @@ -54,7 +54,7 @@ void PrintOutputProcessing( if (std::is_same::value) std::cout << "Base.unsafe_string("; - std::cout << "IOGetParam" << type << "(\"" << d.name << "\")"; + std::cout << "GetParam" << type << "(p, \"" << d.name << "\")"; if (std::is_same::value) std::cout << ")"; @@ -89,7 +89,7 @@ void PrintOutputProcessing( extra = ", points_are_rows"; } - std::cout << "IOGetParam" << uChar << matTypeSuffix << "(\"" << d.name + std::cout << "GetParam" << uChar << matTypeSuffix << "(p, \"" << d.name << "\"" << extra << ")"; } @@ -106,8 +106,8 @@ void PrintOutputProcessing( std::tuple>::value>::type*) { std::string type = util::StripType(d.cppType); - std::cout << functionName << "_internal.IOGetParam" - << type << "(\"" << d.name << "\", modelPtrs)"; + std::cout << functionName << "_internal.GetParam" + << type << "(p, \"" << d.name << "\", modelPtrs)"; } /** @@ -120,7 +120,7 @@ void PrintOutputProcessing( const typename std::enable_if>::value>::type*) { - std::cout << "IOGetParamMatWithInfo(\"" << d.name << "\")"; + std::cout << "GetParamMatWithInfo(p, \"" << d.name << "\")"; } } // namespace julia diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index ec989b8403..3a00ef2267 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -255,8 +255,10 @@ PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked " #define PRINT_PARAM_VALUE mlpack::bindings::julia::PrintValue #define PRINT_DATASET mlpack::bindings::julia::PrintDataset #define PRINT_MODEL mlpack::bindings::julia::PrintModel -#define PRINT_CALL mlpack::bindings::julia::ProgramCall -#define BINDING_IGNORE_CHECK mlpack::bindings::julia::IgnoreCheck +#define PRINT_CALL(...) mlpack::bindings::julia::ProgramCall( \ + STRINGIFY(BINDING_NAME), __VA_ARGS__) +#define BINDING_IGNORE_CHECK(...) mlpack::bindings::julia::IgnoreCheck( \ + STRINGIFY(BINDING_NAME), __VA_ARGS__) namespace mlpack { namespace util { @@ -267,24 +269,25 @@ using Option = mlpack::bindings::julia::JuliaOption; } } -static const std::string testName = ""; #include -#undef BINDING_USER_NAME -#define BINDING_USER_NAME(NAME) static \ - mlpack::util::ProgramName \ - io_programname_dummy_object = mlpack::util::ProgramName(NAME); \ - namespace mlpack { \ - namespace bindings { \ - namespace julia { \ - std::string programName = NAME; \ - } \ - } \ - } +#ifdef BINDING_NAME + #define OLD_BINDING_NAME BINDING_NAME +#undef BINDING_NAME +#endif +#define BINDING_NAME PARAM_FLAG("verbose", "Display informational messages and the full list of " "parameters and timers at the end of execution.", "v"); +#ifdef OLD_BINDING_NAME + #undef BINDING_NAME + #define BINDING_NAME OLD_BINDING_NAME + #undef OLD_BINDING_NAME +#else + #undef BINDING_NAME +#endif + // Nothing else needs to be defined---the binding will use mlpackMain() as-is. #elif(BINDING_TYPE == BINDING_TYPE_GO) // This is a Go binding. From 40ff57871df101b38e115b4eef53ee81420807cc Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 29 Jun 2021 09:51:03 -0400 Subject: [PATCH 473/729] Add missing file. --- src/mlpack/bindings/julia/mlpack/params.jl.in | 410 ++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 src/mlpack/bindings/julia/mlpack/params.jl.in diff --git a/src/mlpack/bindings/julia/mlpack/params.jl.in b/src/mlpack/bindings/julia/mlpack/params.jl.in new file mode 100644 index 0000000000..bf3309c1a8 --- /dev/null +++ b/src/mlpack/bindings/julia/mlpack/params.jl.in @@ -0,0 +1,410 @@ +module params + +export GetParameters +export DeleteParameters +export Timers +export DeleteTimers +export SetParam +export SetParamMat +export SetParamUMat +export SetParamRow +export SetParamCol +export SetParamURow +export SetParamUCol +export GetParamBool +export GetParamInt +export GetParamDouble +export GetParamString +export GetParamVectorStr +export GetParamVectorInt +export GetParamMat +export GetParamUMat +export GetParamCol +export GetParamRow +export GetParamUCol +export GetParamURow +export GetParamMatWithInfo +export EnableVerbose +export DisableVerbose +export SetPassed + +const library = joinpath(@__DIR__, "libmlpack_julia_util${CMAKE_SHARED_LIBRARY_SUFFIX}") + +# Utility function to convert 1d object to 2d. +function convert_to_2d(in::Array{T, 1})::Array{T, 2} where T + reshape(in, length(in), 1) +end + +# Utility function to convert 2d object to 1d. Fails if the size of one +# dimension is not 1. +function convert_to_1d(in::Array{T, 2})::Array{T, 1} where T + if size(in, 1) != 1 && size(in, 2) != 1 + throw(ArgumentError("given matrix must be 1-dimensional; but its size is " * + "$(size(in))")) + end + + vec(in) +end + +# Utility function to convert to and return a matrix. +function to_matrix(input, T::Type) + if isa(input, Array{T, 1}) + convert_to_2d(input) + else + convert(Array{T, 2}, input) + end +end + +# Utility function to convert to and return a vector. +function to_vector(input, T::Type) + if isa(input, Array{T, 1}) + input + else + convert_to_1d(convert(Array{T, 2}, input)) + end +end + +function GetParameters(bindingName::String) + ccall((:GetParameters, library), Ptr{Nothing}, (Cstring,), bindingName) +end + +function DeleteParameters(params::Ptr{Nothing}) + ccall((:DeleteParameters, library), Nothing, (Ptr{Nothing},), params) +end + +function Timers() + ccall((:Timers, library), Ptr{Nothing}, ()) +end + +function DeleteTimers(timers) + ccall((:DeleteTimers, library), Nothing, (Ptr{Nothing},), timers) +end + +function SetParam(params::Ptr{Nothing}, paramName::String, paramValue::Int) + ccall((:SetParamInt, library), Nothing, (Ptr{Nothing}, Cstring, Cint), params, + paramName, Cint(paramValue)) +end + +function SetParam(params::Ptr{Nothing}, paramName::String, paramValue::Float64) + ccall((:SetParamDouble, library), Nothing, (Ptr{Nothing}, Cstring, Float64), + params, paramName, paramValue) +end + +function SetParam(params::Ptr{Nothing}, paramName::String, paramValue::Bool) + ccall((:SetParamBool, library), Nothing, (Ptr{Nothing}, Cstring, Bool), + params, paramName, paramValue) +end + +function SetParam(params::Ptr{Nothing}, paramName::String, paramValue::String) + ccall((:SetParamString, library), Nothing, (Ptr{Nothing}, Cstring, Cstring), + params, paramName, paramValue) +end + +function SetParamMat(params::Ptr{Nothing}, + paramName::String, + paramValue, + pointsAsRows::Bool) + paramMat = to_matrix(paramValue, Float64) + ccall((:SetParamMat, library), Nothing, (Ptr{Nothing}, Cstring, Ptr{Float64}, + Csize_t, Csize_t, Bool), params, paramName, Base.pointer(paramMat), + size(paramMat, 1), size(paramMat, 2), pointsAsRows) +end + +function SetParamUMat(params::Ptr{Nothing}, + paramName::String, + paramValue, + pointsAsRows::Bool) + paramMat = to_matrix(paramValue, Int) + + # Sanity check. + if minimum(paramMat) <= 0 + throw(DomainError("Input $(paramName) cannot have 0 or negative values! " * + "Must be 1 or greater.")) + end + + m = convert(Array{Csize_t, 2}, paramMat .- 1) + ccall((:SetParamUMat, library), Nothing, (Ptr{Nothing}, Cstring, Ptr{Csize_t}, + Csize_t, Csize_t, Bool), params, paramName, Base.pointer(m), + size(paramValue, 1), size(paramValue, 2), pointsAsRows) +end + +function SetParam(params::Ptr{Nothing}, + paramName::String, + vector::Vector{String}) + # For this we have to set the size of the vector then each string + # sequentially. I am not sure if this is fully necessary but I have some + # reservations about Julia's support for passing arrays of strings correctly + # as a const char**. + ccall((:SetParamVectorStrLen, library), Nothing, (Ptr{Nothing}, Cstring, + Csize_t), params, paramName, size(vector, 1)) + for i in 1:size(vector, 1) + ccall((:SetParamVectorStrStr, library), Nothing, (Ptr{Nothing}, Cstring, + Cstring, Csize_t), params, paramName, vector[i], i .- 1) + end +end + +function SetParam(params::Ptr{Nothing}, + paramName::String, + vector::Vector{Int}) + cint_vec = convert(Vector{Cint}, vector) + ccall((:SetParamVectorInt, library), Nothing, (Ptr{Nothing}, Cstring, + Ptr{Cint}, Csize_t), params, paramName, Base.pointer(cint_vec), + size(cint_vec, 1)) +end + +function SetParam(params::Ptr{Nothing}, + paramName::String, + matWithInfo::Tuple{Array{Bool, 1}, Array{Float64, 2}}, + pointsAsRows::Bool) + ccall((:SetParamMatWithInfo, library), Nothing, (Ptr{Nothing}, Cstring, + Ptr{Bool}, Ptr{Float64}, Int, Int, Bool), params, paramName, + Base.pointer(matWithInfo[1]), Base.pointer(matWithInfo[2]), + size(matWithInfo[2], 1), size(matWithInfo[2], 2), pointsAsRows) +end + +function SetParamRow(params::Ptr{Nothing}, + paramName::String, + paramValue) + paramVec = to_vector(paramValue, Float64) + ccall((:SetParamRow, library), Nothing, (Ptr{Nothing}, Cstring, Ptr{Float64}, + Csize_t), params, paramName, Base.pointer(paramVec), size(paramVec, 1)) +end + +function SetParamCol(params::Ptr{Nothing}, + paramName::String, + paramValue) + paramVec = to_vector(paramValue, Float64) + ccall((:SetParamCol, library), Nothing, (Ptr{Nothing}, Cstring, Ptr{Float64}, + Csize_t), params, paramName, Base.pointer(paramVec), size(paramVec, 1)) +end + +function SetParamURow(params::Ptr{Nothing}, + paramName::String, + paramValue) + paramVec = to_vector(paramValue, Int) + + # Sanity check. + if minimum(paramVec) <= 0 + throw(DomainError("Input $(paramName) cannot have 0 or negative values! " * + "Must be 1 or greater.")) + end + m = convert(Array{Csize_t, 1}, paramVec .- 1) + + ccall((:SetParamURow, library), Nothing, (Ptr{Nothing}, Cstring, Ptr{Csize_t}, + Csize_t), params, paramName, Base.pointer(m), size(paramValue, 1)) +end + +function SetParamUCol(params::Ptr{Nothing}, + paramName::String, + paramValue) + paramVec = to_vector(paramValue, Int) + + # Sanity check. + if minimum(paramVec) <= 0 + throw(DomainError("Input $(paramName) cannot have 0 or negative values! " * + "Must be 1 or greater.")) + end + m = convert(Array{Csize_t, 1}, paramValue .- 1) + + ccall((:SetParamUCol, library), Nothing, (Ptr{Nothing}, Cstring, Ptr{Csize_t}, + Csize_t), params, paramName, Base.pointer(m), size(paramValue, 1)) +end + +function GetParamBool(params::Ptr{Nothing}, paramName::String) + return ccall((:GetParamBool, library), Bool, (Ptr{Nothing}, Cstring,), params, + paramName) +end + +function GetParamInt(params::Ptr{Nothing}, paramName::String) + return Int(ccall((:GetParamInt, library), Cint, (Ptr{Nothing}, Cstring,), + params, paramName)) +end + +function GetParamDouble(params::Ptr{Nothing}, paramName::String) + return ccall((:GetParamDouble, library), Float64, (Ptr{Nothing}, Cstring,), + params, paramName) +end + +function GetParamString(params::Ptr{Nothing}, paramName::String) + return ccall((:GetParamString, library), Cstring, (Ptr{Nothing}, Cstring,), + params, paramName) +end + +function GetParamVectorStr(params::Ptr{Nothing}, paramName::String) + local size::Csize_t + local ptr::Ptr{String} + + # Get the size of the vector, then each element. + size = ccall((:GetParamVectorStrLen, library), Csize_t, (Ptr{Nothing}, + Cstring,), params, paramName) + out = Array{String, 1}() + for i = 1:size + s = ccall((:GetParamVectorStrStr, library), Cstring, (Ptr{Nothing}, Cstring, + Csize_t), params, paramName, i .- 1) + push!(out, Base.unsafe_string(s)) + end + + return out +end + +function GetParamVectorInt(params::Ptr{Nothing}, paramName::String) + local size::Csize_t + local ptr::Ptr{Cint} + + # Get the size of the vector, then the pointer to it. We will own the + # pointer. + size = ccall((:GetParamVectorIntLen, library), Csize_t, (Ptr{Nothing}, + Cstring,), params, paramName) + ptr = ccall((:GetParamVectorIntPtr, library), Ptr{Cint}, (Ptr{Nothing}, + Cstring,), params, paramName) + + return convert(Array{Int, 1}, Base.unsafe_wrap(Array{Cint, 1}, ptr, (size), + own=true)) +end + +function GetParamMat(params::Ptr{Nothing}, + paramName::String, + pointsAsRows::Bool) + # Can we return different return types? For now let's restrict to a matrix to + # make it easy... + local ptr::Ptr{Float64} + local rows::Csize_t, cols::Csize_t + # I suppose it would be possible to do this all in one call, but this seems + # easy enough. + rows = ccall((:GetParamMatRows, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + cols = ccall((:GetParamMatCols, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + ptr = ccall((:GetParamMat, library), Ptr{Float64}, (Ptr{Nothing}, Cstring,), + params, paramName) + + if pointsAsRows + # In this case we have to transpose, unfortunately. + m = Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), own=true) + return m' + else + # Here no transpose is necessary. + return Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), own=true) + end +end + +function GetParamUMat(params::Ptr{Nothing}, + paramName::String, + pointsAsRows::Bool) + # Can we return different return types? For now let's restrict to a matrix to + # make it easy... + local ptr::Ptr{Csize_t} + local rows::Csize_t, cols::Csize_t + # I suppose it would be possible to do this all in one call, but this seems + # easy enough. + rows = ccall((:GetParamUMatRows, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + cols = ccall((:GetParamUMatCols, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + ptr = ccall((:GetParamUMat, library), Ptr{Csize_t}, (Ptr{Nothing}, Cstring,), + params, paramName) + + if pointsAsRows + # In this case we have to transpose, unfortunately. + m = Base.unsafe_wrap(Array{Csize_t, 2}, ptr, (rows, cols), own=true) + return convert(Array{Int, 2}, m' .+ 1) # Add 1 because these are indexes. + else + # Here no transpose is necessary. + m = Base.unsafe_wrap(Array{Csize_t, 2}, ptr, (rows, cols), own=true) + return convert(Array{Int, 2}, m .+ 1) + end +end + +function GetParamCol(params::Ptr{Nothing}, paramName::String) + local ptr::Ptr{Float64} + local rows::Csize_t + + rows = ccall((:GetParamColRows, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + ptr = ccall((:GetParamCol, library), Ptr{Float64}, (Ptr{Nothing}, Cstring,), + params, paramName) + + return Base.unsafe_wrap(Array{Float64, 1}, ptr, rows, own=true) +end + +function GetParamRow(params::Ptr{Nothing}, paramName::String) + local ptr::Ptr{Float64} + local cols::Csize_t + + cols = ccall((:GetParamRowCols, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + ptr = ccall((:GetParamRow, library), Ptr{Float64}, (Ptr{Nothing}, Cstring,), + params, paramName) + + return Base.unsafe_wrap(Array{Float64, 1}, ptr, cols, own=true) +end + +function GetParamUCol(params::Ptr{Nothing}, paramName::String) + local ptr::Ptr{Csize_t} + local rows::Csize_t + + rows = ccall((:GetParamUColRows, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + ptr = ccall((:GetParamUCol, library), Ptr{Csize_t}, (Ptr{Nothing}, Cstring,), + params, paramName) + + m = Base.unsafe_wrap(Array{Csize_t, 1}, ptr, rows, own=true) + return convert(Array{Int, 1}, m .+ 1) +end + +function GetParamURow(params::Ptr{Nothing}, paramName::String) + local ptr::Ptr{Csize_t} + local cols::Csize_t + + cols = ccall((:GetParamURowCols, library), Csize_t, (Ptr{Nothing}, Cstring,), + params, paramName) + ptr = ccall((:GetParamURow, library), Ptr{Csize_t}, (Ptr{Nothing}, Cstring,), + params, paramName) + + m = Base.unsafe_wrap(Array{Csize_t, 1}, ptr, cols, own=true) + return convert(Array{Int, 1}, m .+ 1) +end + +function GetParamMatWithInfo(params::Ptr{Nothing}, + paramName::String, + pointsAsRows::Bool) + local ptrBool::Ptr{Bool} + local ptrData::Ptr{Float64} + local rows::Csize_t + local cols::Csize_t + + rows = ccall((:GetParamMatWithInfoRows, library), Csize_t, (Ptr{Nothing}, + Cstring,), params, paramName) + cols = ccall((:GetParamMatWithInfoCols, library), Csize_t, (Ptr{Nothing}, + Cstring,), params, paramName) + ptrBool = ccall((:GetParamMatWithInfoBoolPtr, library), Ptr{Bool}, + (Ptr{Nothing}, Cstring,), params, paramName) + ptrMem = ccall((:GetParamMatWithInfoPtr, library), Ptr{Float64}, + (Ptr{Nothing}, Cstring,), params, paramName) + + types = Base.unsafe_wrap(Array{Bool, 1}, ptrBool, (rows), own=true) + if pointsAsRows + # In this case we have to transpose, unfortunately. + m = Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), own=true) + return (types, m') + else + # Here no transpose is necessary. + return (types, Base.unsafe_wrap(Array{Float64, 2}, ptr, (rows, cols), + own=true)) + end +end + +function EnableVerbose() + ccall((:EnableVerbose, library), Nothing, ()) +end + +function DisableVerbose() + ccall((:DisableVerbose, library), Nothing, ()) +end + +function SetPassed(params::Ptr{Nothing}, paramName::String) + ccall((:SetPassed, library), Nothing, (Ptr{Nothing}, Cstring,), params, + paramName) +end + +end # module params From cca8493235661764dc53da0ea6ccf2b0430dde50 Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Tue, 29 Jun 2021 19:40:20 +0530 Subject: [PATCH 474/729] changed comments and replaced p with params --- src/mlpack/bindings/python/mlpack/io.pxd | 8 ++-- src/mlpack/bindings/python/mlpack/io_util.hpp | 26 ++++++------ src/mlpack/bindings/python/mlpack/params.pxd | 9 +++- src/mlpack/bindings/python/mlpack/timers.pxd | 4 +- .../python/print_doc_functions_impl.hpp | 42 +++++++++---------- src/mlpack/bindings/python/print_pyx.cpp | 20 ++++----- src/mlpack/core/util/mlpack_main.hpp | 15 ++++++- .../linear_regression_main.cpp | 5 --- 8 files changed, 71 insertions(+), 58 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/io.pxd b/src/mlpack/bindings/python/mlpack/io.pxd index 6e5682dbf8..99159561a9 100644 --- a/src/mlpack/bindings/python/mlpack/io.pxd +++ b/src/mlpack/bindings/python/mlpack/io.pxd @@ -1,9 +1,11 @@ #!/usr/bin/env python """ -io.pyx: Cython functionality for mlpack::IO. +io.pyx: Cython functionality for mlpack::IO and other utilities. -This file imports the GetParam() function from mlpack::IO, plus a utility -SetParam() function because Cython can't seem to support lvalue references. +This file imports the Parameters() function from mlpack::IO, plus other utility +functions: SetParam(), SetParamPtr(), SetParamWithInfo(), GetParam(), +GetParamWithInfo(), EnableVerbose(), DisableVerbose(), DisableBacktrace(), +EnableTimers() and ResetTimers(). 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 diff --git a/src/mlpack/bindings/python/mlpack/io_util.hpp b/src/mlpack/bindings/python/mlpack/io_util.hpp index 282dce8c46..3276eead6e 100644 --- a/src/mlpack/bindings/python/mlpack/io_util.hpp +++ b/src/mlpack/bindings/python/mlpack/io_util.hpp @@ -12,7 +12,7 @@ */ #ifndef MLPACK_BINDINGS_PYTHON_CYTHON_IO_UTIL_HPP #define MLPACK_BINDINGS_PYTHON_CYTHON_IO_UTIL_HPP -// TODO: Change this. + #include #include @@ -29,11 +29,11 @@ namespace util { * @param value Value to set parameter to. */ template -inline void SetParam(util::Params& p, +inline void SetParam(util::Params& params, const std::string& identifier, T& value) { - p.Get(identifier) = std::move(value); + params.Get(identifier) = std::move(value); } /** @@ -47,19 +47,19 @@ inline void SetParam(util::Params& p, * @param copy Whether or not the object should be copied. */ template -inline void SetParamPtr(util::Params& p, +inline void SetParamPtr(util::Params& params, const std::string& identifier, T* value, const bool copy) { - p.Get(identifier) = copy ? new T(*value) : value; + params.Get(identifier) = copy ? new T(*value) : value; } /** * Set the parameter (which is a matrix/DatasetInfo tuple) to the given value. */ template -inline void SetParamWithInfo(util::Params& p, +inline void SetParamWithInfo(util::Params& params, const std::string& identifier, T& matrix, const bool* dims) @@ -69,8 +69,8 @@ inline void SetParamWithInfo(util::Params& p, // The true type of the parameter is std::tuple. const size_t dimensions = matrix.n_rows; - std::get<1>(p.Get(identifier)) = std::move(matrix); - data::DatasetInfo& di = std::get<0>(p.Get(identifier)); + std::get<1>(params.Get(identifier)) = std::move(matrix); + data::DatasetInfo& di = std::get<0>(params.Get(identifier)); di = data::DatasetInfo(dimensions); bool hasCategoricals = false; @@ -87,7 +87,7 @@ inline void SetParamWithInfo(util::Params& p, if (hasCategoricals) { arma::vec maxs = arma::max( - std::get<1>(p.Get(identifier)), 1); + std::get<1>(params.Get(identifier)), 1); for (size_t i = 0; i < dimensions; ++i) { @@ -110,22 +110,22 @@ inline void SetParamWithInfo(util::Params& p, * of support for template pointer types. */ template -T* GetParamPtr(util::Params& p, +T* GetParamPtr(util::Params& params, const std::string& paramName) { - return p.Get(paramName); + return params.Get(paramName); } /** * Return the matrix part of a matrix + dataset info parameter. */ template -T& GetParamWithInfo(util::Params& p, +T& GetParamWithInfo(util::Params& params, const std::string& paramName) { // T will be the Armadillo type. typedef std::tuple TupleType; - return std::get<1>(p.Get(paramName)); + return std::get<1>(params.Get(paramName)); } /** diff --git a/src/mlpack/bindings/python/mlpack/params.pxd b/src/mlpack/bindings/python/mlpack/params.pxd index d77866ffb1..32491d5798 100644 --- a/src/mlpack/bindings/python/mlpack/params.pxd +++ b/src/mlpack/bindings/python/mlpack/params.pxd @@ -2,8 +2,13 @@ """ params.pxd: Cython functionality for mlpack::util::Params. -This file imports the GetParam() function from mlpack::IO, plus a utility -SetParam() function because Cython can't seem to support lvalue references. +This file provides the wrapper to the Params class, along with some of +its methods that are: +Get() - Used to "get" a reference to a parameter with the given name. +Has() - Used to know if a parameter with a given name exists in the program. +SetPassed() - Used to set a parameter as "passed". +CheckInputMatrices() - Sanity check for matrics to know if a matrix has NULL + or NaN values. 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 diff --git a/src/mlpack/bindings/python/mlpack/timers.pxd b/src/mlpack/bindings/python/mlpack/timers.pxd index f154d4ebca..9cdcf3bbfe 100644 --- a/src/mlpack/bindings/python/mlpack/timers.pxd +++ b/src/mlpack/bindings/python/mlpack/timers.pxd @@ -2,8 +2,8 @@ """ timers.pxd: Cython wrapper for Timers. -This file imports the GetParam() function from mlpack::IO, plus a utility -SetParam() function because Cython can't seem to support lvalue references. +This file provides a basic wrapper for Timers class, that is used in calling +the main program function. 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 diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp index 4982b68db9..4e61b19e61 100644 --- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp @@ -110,15 +110,15 @@ inline std::string PrintValue(const bool& value, bool quotes) inline std::string PrintDefault(const std::string& bindingName, const std::string& paramName) { - util::Params p = IO::Parameters(bindingName); + util::Params params = IO::Parameters(bindingName); - if (p.Parameters().count(paramName) == 0) + if (params.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); - util::ParamData& d = p.Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; std::string defaultValue; - p.functionMap[d.tname]["DefaultParam"](d, NULL, + params.functionMap[d.tname]["DefaultParam"](d, NULL, (void*) &defaultValue); return defaultValue; @@ -214,13 +214,13 @@ std::string PrintOutputOptions(util::Params& params, /** * Given a name of a binding and a variable number of arguments (and their - * contents), print the corresponding function call. The given programName + * contents), print the corresponding function call. The given bindingName * should not be the output of GetBindingName(). */ template -std::string ProgramCall(const std::string& programName, Args... args) +std::string ProgramCall(const std::string& bindingName, Args... args) { - util::Params params = IO::Parameters(programName); + util::Params params = IO::Parameters(bindingName); std::ostringstream oss; oss << ">>> "; @@ -230,7 +230,7 @@ std::string ProgramCall(const std::string& programName, Args... args) ossOutput << PrintOutputOptions(params, args...); if (ossOutput.str() != "") oss << "output = "; - oss << programName << "("; + oss << bindingName << "("; // Now process each input option. oss << PrintInputOptions(params, args...); @@ -249,11 +249,11 @@ std::string ProgramCall(const std::string& programName, Args... args) /** * Given the name of a binding, print a program call assuming that all options - * are specified. The programName should not be the output of GetBindingName(). + * are specified. The bindingName should not be the output of GetBindingName(). */ -inline std::string ProgramCall(const std::string& programName) // TODO: here programName is the bindingName?? +inline std::string ProgramCall(const std::string& bindingName) { - util::Params params = IO::Parameters(programName); + util::Params params = IO::Parameters(bindingName); std::ostringstream oss; oss << ">>> "; @@ -273,7 +273,7 @@ inline std::string ProgramCall(const std::string& programName) // TODO: here pro if (hasOutput) oss << "d = "; - oss << programName << "("; + oss << bindingName << "("; // Now iterate over every input option. bool first = true; @@ -377,20 +377,20 @@ inline std::string ParamString(const std::string& paramName, const T& value) } inline bool IgnoreCheck(const std::string& bindingName, - const std::string& paramName) + const std::string& paramName) { - util::Params p = IO::Parameters(bindingName); - return !p.Parameters()[paramName].input; + util::Params params = IO::Parameters(bindingName); + return !params.Parameters()[paramName].input; } inline bool IgnoreCheck(const std::string& bindingName, - const std::vector& constraints) + const std::vector& constraints) { - util::Params p = IO::Parameters(bindingName); + util::Params params = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!p.Parameters()[constraints[i]].input) + if (!params.Parameters()[constraints[i]].input) return true; } @@ -402,15 +402,15 @@ inline bool IgnoreCheck( const std::vector>& constraints, const std::string& paramName) { - util::Params p = IO::Parameters(bindingName); + util::Params params = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!p.Parameters()[constraints[i].first].input) + if (!params.Parameters()[constraints[i].first].input) return true; } - return !p.Parameters()[paramName].input; + return !params.Parameters()[paramName].input; } } // namespace python diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index c340a72869..9e84539a75 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -37,9 +37,9 @@ void PrintPYX(const util::BindingDetails& doc, { std::string functionName = bindingName + "_py"; - util::Params p = IO::Parameters(bindingName); + util::Params params = IO::Parameters(bindingName); - std::map& parameters = p.Parameters(); + std::map& parameters = params.Parameters(); typedef std::map::iterator ParamIter; // Split into input and output parameters. Take two passes on the input @@ -110,7 +110,7 @@ void PrintPYX(const util::BindingDetails& doc, if (classes.count(d.cppType) == 0) { const size_t indent = 2; - p.functionMap[d.tname]["ImportDecl"](d, (void*) &indent, + params.functionMap[d.tname]["ImportDecl"](d, (void*) &indent, NULL); // Make sure we don't double-print the definition. @@ -125,7 +125,7 @@ void PrintPYX(const util::BindingDetails& doc, { util::ParamData& d = it->second; if (d.input) - p.functionMap[d.tname]["PrintClassDefn"](d, NULL, NULL); + params.functionMap[d.tname]["PrintClassDefn"](d, NULL, NULL); } // Print the definition. @@ -137,7 +137,7 @@ void PrintPYX(const util::BindingDetails& doc, if (i != 0) cout << "," << endl << std::string(indent, ' '); - p.functionMap[d.tname]["PrintDefn"](d, NULL, NULL); + params.functionMap[d.tname]["PrintDefn"](d, NULL, NULL); } // Print closing brace for function definition. @@ -166,7 +166,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << " "; size_t indent = 4; - p.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, + params.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, NULL); cout << endl; } @@ -179,7 +179,7 @@ void PrintPYX(const util::BindingDetails& doc, cout << " "; size_t indent = 4; - p.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, + params.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, NULL); cout << endl; } @@ -216,7 +216,7 @@ void PrintPYX(const util::BindingDetails& doc, util::ParamData& d = parameters.at(inputOptions[i]); size_t indent = 2; - p.functionMap[d.tname]["PrintInputProcessing"](d, + params.functionMap[d.tname]["PrintInputProcessing"](d, (void*) &indent, NULL); } @@ -255,8 +255,8 @@ void PrintPYX(const util::BindingDetails& doc, util::ParamData& d = parameters.at(outputOptions[i]); std::tuple t = std::make_tuple(2, false); - TupleType tWithParams = std::make_tuple(p, t); - p.functionMap[d.tname]["PrintOutputProcessing"](d, + TupleType tWithParams = std::make_tuple(params, t); + params.functionMap[d.tname]["PrintOutputProcessing"](d, (void*) &tWithParams, NULL); } cout << endl; diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index ca8bfd2aa0..89b76edf14 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -220,10 +220,14 @@ using Option = mlpack::bindings::python::PyOption; #include +#ifndef BINDING_NAME + #error "BINDING_NAME not defined!" +#endif // These parameters should not be registered to any BINDING_NAME, // they are registered under "". #ifdef BINDING_NAME - #undef BINDING_NAME + #define OLD_BINDING_NAME BINDING_NAME + #undef BINDING_NAME #endif #define BINDING_NAME @@ -236,7 +240,14 @@ PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep" PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked " "for NaN and inf values; an exception is thrown if any are found.", ""); -// Nothing else needs to be defined---the binding will use mlpackMain() as-is. +// redefining BINDING_NAME. +#ifdef OLD_BINDING_NAME + #undef BINDING_NAME + #define BINDING_NAME OLD_BINDING_NAME + #undef OLD_BINDING_NAME +#endif + +// Nothing else needs to be defined---the binding will use BINDING_NAME() as-is. #elif(BINDING_TYPE == BINDING_TYPE_JL) // This is a Julia binding. diff --git a/src/mlpack/methods/linear_regression/linear_regression_main.cpp b/src/mlpack/methods/linear_regression/linear_regression_main.cpp index ea015085e6..a01baf8e63 100644 --- a/src/mlpack/methods/linear_regression/linear_regression_main.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression_main.cpp @@ -19,11 +19,6 @@ #include -#ifdef BINDING_NAME - #undef BINDING_NAME -#endif -#define BINDING_NAME linear_regression - #include "linear_regression.hpp" using namespace mlpack; From b76fa0f53bc5014e02a2beef61a43da4969d5814 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 29 Jun 2021 19:35:52 -0400 Subject: [PATCH 475/729] Add --probabilities option to softmax regression binding. --- .../softmax_regression_main.cpp | 12 +++++ .../main_tests/softmax_regression_test.cpp | 48 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp index 571b239187..ce67e9e42c 100644 --- a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp +++ b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp @@ -112,6 +112,8 @@ PARAM_MODEL_OUT(SoftmaxRegression, "output_model", "File to save trained " PARAM_MATRIX_IN("test", "Matrix containing test dataset.", "T"); PARAM_UROW_OUT("predictions", "Matrix to save predictions for test dataset " "into.", "p"); +PARAM_MATRIX_OUT("probabilities", "Matrix to save class probabilities for test " + "dataset into.", "P"); PARAM_UROW_IN("test_labels", "Matrix containing test labels.", "L"); // Softmax configuration options. @@ -250,6 +252,16 @@ void TestClassifyAcc(size_t numClasses, const Model& model) // Save predictions, if desired. if (IO::HasParam("predictions")) IO::GetParam>("predictions") = std::move(predictLabels); + + // Compute probabiltiies, if desired. + if (IO::HasParam("probabilities")) + { + Log::Info << "Calculating class probabilities of points in '" + << IO::GetPrintableParam("test") << "'." << endl; + arma::mat probabilities; + model.Classify(testData, probabilities); + IO::GetParam("probabilities") = std::move(probabilities); + } } template diff --git a/src/mlpack/tests/main_tests/softmax_regression_test.cpp b/src/mlpack/tests/main_tests/softmax_regression_test.cpp index 5f64c7a315..5e9f18e732 100644 --- a/src/mlpack/tests/main_tests/softmax_regression_test.cpp +++ b/src/mlpack/tests/main_tests/softmax_regression_test.cpp @@ -497,3 +497,51 @@ TEST_CASE_METHOD( IO::GetParam("output_model")->Parameters().n_cols == modelParam.n_cols + 1); } + +/** + * Check that we can get output probabilities, and also that they are + * reasonable. + */ +TEST_CASE_METHOD( + SoftmaxRegressionTestFixture, + "SoftmaxRegressionProbabilitiesTest", + "[SoftmaxRegressionMainTest][BindingsTest]") +{ + // Train softmax regression. + arma::mat data; + if (!data::Load("vc2.csv", data)) + FAIL("Cannot load train dataset 'vc2.csv'!"); + // Get the labels out. + arma::Row labels; + if (!data::Load("vc2_labels.txt", labels)) + FAIL("Cannot load training labels 'vc2_labels.txt'!"); + + // Input training data. + SetInputParam("training", data); + SetInputParam("labels", labels); + SetInputParam("no_intercept", (bool) true); + + // Input test data. + SetInputParam("test", data); + + mlpackMain(); + + // Get predictions and probabilities. + arma::Row& predictions = + IO::GetParam>("predictions"); + arma::mat& probabilities = IO::GetParam("probabilities"); + + REQUIRE(predictions.n_elem == probabilities.n_cols); + REQUIRE(probabilities.n_rows == arma::max(labels) + 1); + + // Manually compute the predictions and ensure they match, and also check that + // the probabilities sum to 1. + for (size_t i = 0; i < probabilities.n_cols; ++i) + { + const double sum = arma::accu(probabilities.col(i)); + REQUIRE(sum == Approx(1.0)); + + size_t classPrediction = (size_t) arma::index_max(probabilities.col(i)); + REQUIRE(classPrediction == predictions[i]); + } +} From 7e71a8c1135a9635454eb725ebbdb93f2687070b Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 29 Jun 2021 19:38:25 -0400 Subject: [PATCH 476/729] Update HISTORY.md. --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 1c1c157cf8..98f8241432 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -63,6 +63,9 @@ * Fix `LoadCSV()` to use pre-populated `DatasetInfo` objects (#2980). + * Add `probabilities` option to softmax regression binding, to get class + probabilities for test points (#3001). + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From d28763560e4c7f6a4d72966018dad473227e639d Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Wed, 30 Jun 2021 18:55:15 +0530 Subject: [PATCH 477/729] removed persitent from ParamData and corresponding calls --- src/mlpack/bindings/R/R_option.hpp | 6 ------ src/mlpack/bindings/R/print_doc_functions_impl.hpp | 3 +-- src/mlpack/bindings/cli/cli_option.hpp | 1 - .../bindings/cli/print_doc_functions_impl.hpp | 2 +- src/mlpack/bindings/go/go_option.hpp | 5 ----- .../bindings/go/print_doc_functions_impl.hpp | 2 +- src/mlpack/bindings/julia/julia_option.hpp | 6 ------ .../bindings/julia/print_doc_functions_impl.hpp | 3 +-- src/mlpack/bindings/markdown/md_option.hpp | 6 ------ .../bindings/markdown/print_doc_functions_impl.hpp | 1 - src/mlpack/bindings/python/generate_pyx.cpp.in | 3 +-- .../bindings/python/print_doc_functions_impl.hpp | 3 +-- src/mlpack/bindings/python/py_option.hpp | 9 +-------- src/mlpack/bindings/tests/test_option.hpp | 1 - src/mlpack/core/util/io.cpp | 12 ++---------- src/mlpack/core/util/mlpack_main.hpp | 14 -------------- src/mlpack/core/util/param_data.hpp | 3 --- 17 files changed, 9 insertions(+), 71 deletions(-) diff --git a/src/mlpack/bindings/R/R_option.hpp b/src/mlpack/bindings/R/R_option.hpp index ce93d57336..77f74c091f 100644 --- a/src/mlpack/bindings/R/R_option.hpp +++ b/src/mlpack/bindings/R/R_option.hpp @@ -70,12 +70,6 @@ class ROption data.required = required; data.input = input; data.loaded = false; - - // Only "verbose" will be persistent. - if (identifier == "verbose") - data.persistent = true; - else - data.persistent = false; data.cppType = cppName; // Every parameter we'll get from R will have the correct type. diff --git a/src/mlpack/bindings/R/print_doc_functions_impl.hpp b/src/mlpack/bindings/R/print_doc_functions_impl.hpp index 76b956812e..fab8904eec 100644 --- a/src/mlpack/bindings/R/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/R/print_doc_functions_impl.hpp @@ -289,8 +289,7 @@ inline std::string ProgramCall(const std::string& programName) bool first = true; for (auto it = parameters.begin(); it != parameters.end(); ++it) { - if (!it->second.input || (it->second.persistent && - it->second.name != "verbose")) + if (!it->second.input) continue; if (!first) diff --git a/src/mlpack/bindings/cli/cli_option.hpp b/src/mlpack/bindings/cli/cli_option.hpp index 107a65c506..112453f4bf 100644 --- a/src/mlpack/bindings/cli/cli_option.hpp +++ b/src/mlpack/bindings/cli/cli_option.hpp @@ -88,7 +88,6 @@ class CLIOption data.required = required; data.input = input; data.loaded = false; - data.persistent = false; // All CLI parameters are not persistent. data.cppType = cppName; // Apply default value. diff --git a/src/mlpack/bindings/cli/print_doc_functions_impl.hpp b/src/mlpack/bindings/cli/print_doc_functions_impl.hpp index ae6911f99f..be7d83a6cc 100644 --- a/src/mlpack/bindings/cli/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/cli/print_doc_functions_impl.hpp @@ -198,7 +198,7 @@ inline std::string ProgramCall(const std::string& programName) for (auto& it : parameters) { - if (!it.second.input || it.second.persistent) + if (!it.second.input) continue; // Otherwise, print the name and the default value. diff --git a/src/mlpack/bindings/go/go_option.hpp b/src/mlpack/bindings/go/go_option.hpp index 33e549fc44..a6607fe47f 100644 --- a/src/mlpack/bindings/go/go_option.hpp +++ b/src/mlpack/bindings/go/go_option.hpp @@ -79,11 +79,6 @@ class GoOption data.required = required; data.input = input; data.loaded = false; - // Only "verbose" and "copy_all_inputs" will be persistent. - if (identifier == "verbose" /*|| identifier == "copy_all_inputs"*/) - data.persistent = true; - else - data.persistent = false; data.cppType = cppName; data.value = boost::any(defaultValue); diff --git a/src/mlpack/bindings/go/print_doc_functions_impl.hpp b/src/mlpack/bindings/go/print_doc_functions_impl.hpp index 1f250aafb5..3675bdf4e3 100644 --- a/src/mlpack/bindings/go/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/go/print_doc_functions_impl.hpp @@ -439,7 +439,7 @@ inline std::string ProgramCall(const std::string& programName) // Now iterate over every optional input option. for (auto it = parameters.begin(); it != parameters.end(); ++it) { - if (it->second.input && !it->second.required && !it->second.persistent) + if (it->second.input && !it->second.required) { // Print the input option. ossInputs << "param." << util::CamelCase(it->second.name, false) << " = "; diff --git a/src/mlpack/bindings/julia/julia_option.hpp b/src/mlpack/bindings/julia/julia_option.hpp index b111d3e66c..b5dbd952ed 100644 --- a/src/mlpack/bindings/julia/julia_option.hpp +++ b/src/mlpack/bindings/julia/julia_option.hpp @@ -64,12 +64,6 @@ class JuliaOption data.required = required; data.input = input; data.loaded = false; - - // Only "verbose" will be persistent. - if (identifier == "verbose") - data.persistent = true; - else - data.persistent = false; data.cppType = cppName; // Every parameter we'll get from Julia will have the correct type. diff --git a/src/mlpack/bindings/julia/print_doc_functions_impl.hpp b/src/mlpack/bindings/julia/print_doc_functions_impl.hpp index 51baf4c81b..1ea1500dc2 100644 --- a/src/mlpack/bindings/julia/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/julia/print_doc_functions_impl.hpp @@ -505,8 +505,7 @@ inline std::string ProgramCall(const std::string& programName) size_t nonreqInputs = 0; for (auto it = parameters.begin(); it != parameters.end(); ++it) { - if (it->second.input && !it->second.required && - (it->second.name == "verbose" || !it->second.persistent)) + if (it->second.input && !it->second.required) { if (inputs == 0 && nonreqInputs == 0) result << " ; "; diff --git a/src/mlpack/bindings/markdown/md_option.hpp b/src/mlpack/bindings/markdown/md_option.hpp index 528b385b50..d1f5d3dff4 100644 --- a/src/mlpack/bindings/markdown/md_option.hpp +++ b/src/mlpack/bindings/markdown/md_option.hpp @@ -60,12 +60,6 @@ class MDOption data.required = required; data.input = input; data.loaded = false; - // Several options from Python and CLI bindings are persistent. - if (identifier == "verbose" || identifier == "copy_all_inputs" || - identifier == "help" || identifier == "info" || identifier == "version") - data.persistent = true; - else - data.persistent = false; data.cppType = cppName; // Every parameter we'll get from Markdown will have the correct type. diff --git a/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp b/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp index 06ebaab813..34e03d2697 100644 --- a/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp @@ -245,7 +245,6 @@ inline std::string PrintTypeDocs() data.required = false; data.input = true; data.loaded = false; - data.persistent = false; data.value = boost::any(int(0)); std::string type = GetPrintableType(data); diff --git a/src/mlpack/bindings/python/generate_pyx.cpp.in b/src/mlpack/bindings/python/generate_pyx.cpp.in index 8cefd5ec26..3d9653c0e4 100644 --- a/src/mlpack/bindings/python/generate_pyx.cpp.in +++ b/src/mlpack/bindings/python/generate_pyx.cpp.in @@ -27,7 +27,6 @@ #endif #include -#include #include // This will include the ParamData options that are a part of the program. @@ -41,6 +40,6 @@ using namespace mlpack::util; int main(int /* argc */, char** /* argv */) { - PrintPYX(IO::Parameters(STRINGIFY(BINDING_NAME)).Doc(), + PrintPYX(IO::Parameters(STRINGIFY(BINDING_NAME)).Doc(), "${PROGRAM_MAIN_FILE}", STRINGIFY(BINDING_NAME)); } diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp index 4e61b19e61..3417520274 100644 --- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp @@ -279,8 +279,7 @@ inline std::string ProgramCall(const std::string& bindingName) bool first = true; for (auto it = parameters.begin(); it != parameters.end(); ++it) { - if (!it->second.input || (it->second.persistent && - it->second.name != "verbose")) + if (!it->second.input) continue; if (!first) diff --git a/src/mlpack/bindings/python/py_option.hpp b/src/mlpack/bindings/python/py_option.hpp index c26170a55e..645279173b 100644 --- a/src/mlpack/bindings/python/py_option.hpp +++ b/src/mlpack/bindings/python/py_option.hpp @@ -60,13 +60,6 @@ class PyOption data.required = required; data.input = input; data.loaded = false; - // Only "verbose", "copy_all_inputs" and "check_input_matrices" - // will be persistent. - if (identifier == "verbose" || identifier == "copy_all_inputs" || - identifier == "check_input_matrices") - data.persistent = true; - else - data.persistent = false; data.cppType = cppName; // Every parameter we'll get from Python will have the correct type. @@ -88,7 +81,7 @@ class PyOption IO::AddFunction(data.tname, "PrintInputProcessing", &PrintInputProcessing); IO::AddFunction(data.tname, "ImportDecl", &ImportDecl); - // Add the ParamData object to the IO class + // Add the ParamData object to the IO class // for the correct binding name. IO::AddParameter(bindingName, std::move(data)); } diff --git a/src/mlpack/bindings/tests/test_option.hpp b/src/mlpack/bindings/tests/test_option.hpp index 206126f958..9d0e355c64 100644 --- a/src/mlpack/bindings/tests/test_option.hpp +++ b/src/mlpack/bindings/tests/test_option.hpp @@ -82,7 +82,6 @@ class TestOption data.loaded = false; data.cppType = cppName; data.value = boost::any(defaultValue); - data.persistent = false; const std::string tname = data.tname; diff --git a/src/mlpack/core/util/io.cpp b/src/mlpack/core/util/io.cpp index 94c463b56a..ebae34c72a 100644 --- a/src/mlpack/core/util/io.cpp +++ b/src/mlpack/core/util/io.cpp @@ -59,14 +59,13 @@ void IO::AddParameter(const std::string& bindingName, ParamData&& data) // If found in current map, print fatal error and terminate the program, but // only if the parameter is not consistent. - if (bindingParams.count(data.name) && !data.persistent) + if (bindingParams.count(data.name)) { outstr << "Parameter '" << data.name << "' ('" << data.alias << "') " << "is defined multiple times with the same identifiers." << std::endl; } - if (data.alias != '\0' && bindingAliases.count(data.alias) && - !data.persistent) + if (data.alias != '\0' && bindingAliases.count(data.alias)) { outstr << "Parameter '" << data.name << " ('" << data.alias << "') " << "is defined multiple times with the same alias." << std::endl; @@ -182,16 +181,9 @@ util::Params IO::Parameters(const std::string& bindingName) std::map resultAliases = GetSingleton().aliases[bindingName]; - // Merge in any persistent parameters (e.g. parameters in the "" binding map). - std::map persistentAliases = GetSingleton().aliases[""]; - resultAliases.insert(persistentAliases.begin(), persistentAliases.end()); std::map resultParams = GetSingleton().parameters[bindingName]; - // Merge in any persistent parameters (e.g. parameters in the "" binding map). - std::map persistentParams = - GetSingleton().parameters[""]; - resultParams.insert(persistentParams.begin(), persistentParams.end()); return Params(resultAliases, resultParams, GetSingleton().functionMap, bindingName, GetSingleton().docs[bindingName]); diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index 89b76edf14..8ab7f6aa42 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -223,13 +223,6 @@ using Option = mlpack::bindings::python::PyOption; #ifndef BINDING_NAME #error "BINDING_NAME not defined!" #endif -// These parameters should not be registered to any BINDING_NAME, -// they are registered under "". -#ifdef BINDING_NAME - #define OLD_BINDING_NAME BINDING_NAME - #undef BINDING_NAME -#endif -#define BINDING_NAME PARAM_FLAG("verbose", "Display informational messages and the full list of " "parameters and timers at the end of execution.", "v"); @@ -240,13 +233,6 @@ PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep" PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked " "for NaN and inf values; an exception is thrown if any are found.", ""); -// redefining BINDING_NAME. -#ifdef OLD_BINDING_NAME - #undef BINDING_NAME - #define BINDING_NAME OLD_BINDING_NAME - #undef OLD_BINDING_NAME -#endif - // Nothing else needs to be defined---the binding will use BINDING_NAME() as-is. #elif(BINDING_TYPE == BINDING_TYPE_JL) // This is a Julia binding. diff --git a/src/mlpack/core/util/param_data.hpp b/src/mlpack/core/util/param_data.hpp index a578247cfd..ba7855345a 100644 --- a/src/mlpack/core/util/param_data.hpp +++ b/src/mlpack/core/util/param_data.hpp @@ -74,9 +74,6 @@ struct ParamData //! If this is an input parameter that needs extra loading, this indicates //! whether or not it has been loaded. bool loaded; - //! If this should be preserved across different settings (i.e. if it should - //! exist for every binding), this should be set to true. - bool persistent; //! The actual value that is held. If the user has passed a different type, //! this may be a tuple containing multiple values. boost::any value; From 873b35e37f38d1d451a8d790956848213a8bc3b9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 30 Jun 2021 17:42:39 +0530 Subject: [PATCH 478/729] Add SSE Loss for xgboost --- .../xgboost/loss_functions/sse_loss.hpp | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp new file mode 100644 index 0000000000..f702052537 --- /dev/null +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -0,0 +1,100 @@ +/** + * @file methods/xgboost/loss_functions/sse_loss.hpp + * @author Rishabh Garg + * + * The sum of squared error loss class, which is a loss funtion for gradient + * xgboost based decision trees. + * + * 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_DECISION_TREE_SSE_LOSS_HPP +#define MLPACK_METHODS_DECISION_TREE_SSE_LOSS_HPP + +#include + +namespace mlpack { +namespace ensemble { + +/** + * The SSE (Sum of Squared Errors) loss is a loss function to measure the + * quality of prediction of response values present in the node of each + * xgboost tree. It is also a good measure to compare the spread of two + * distributions. We will try to minimize this value while training. + * + * Loss = 1 / 2 * (Observed - Predicted)^2 + */ +class SSELoss +{ + public: + /** + * Returns the initial predition for gradient boosting. + */ + template + eT InitialPrediction(const arma::Row& values) + { + return arma::accu(values) / (eT) values.n_elem; + } + + /** + * Returns the first order gradient of the loss function with respect to the + * values. + * + * This is primarily used in calculating the residuals and split gain for the + * gradient boosted trees. + * + * @tparam T The type of input data. This can be both a vector or a scalar. + * @param observed The true observed values. + * @param values The values with respect to which the gradient will be + * calculated. + */ + template + T Gradients(const T& observed, const T& values) + { + return - (observed - values); + } + + /** + * Returns the second order gradient of the loss function with respect to the + * values. This is used only for scalars. + */ + template + T Hessians(const T& /* observed */, const T& /* values */) + { + return (T) 1; + } + + /** + * Returns the second order gradient of the loss function with respect to the + * values. This is used only for vectors. + */ + template::value || + arma::is_Row::value>> + VecType Hessians(const VecType& /* observed */, const VecType& values) + { + VecType h(values.n_elem, 1); + return h; + } + + /** + * Returns the pseudo residuals of the predictions. + * This is equal to the negative gradient of the loss function with respect + * to the predicted values f. + * + * @param observed The true observed values. + * @param f The prediction at the current step of boosting. + */ + template + VecType Residuals(const VecType& observed, const VecType& f) + { + return - Gradients(observed, f); + } +} + +} // namespace ensemble +} // namespace mlpack + +#endif From e9cba5a179a82759238aa47782a72feaacb6da45 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 30 Jun 2021 17:43:59 +0530 Subject: [PATCH 479/729] Fix name of header guards --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index f702052537..64b965fbc9 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -10,8 +10,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_METHODS_DECISION_TREE_SSE_LOSS_HPP -#define MLPACK_METHODS_DECISION_TREE_SSE_LOSS_HPP +#ifndef MLPACK_METHODS_XGBOOST_LOSS_FUNCTIONS_SSE_LOSS_HPP +#define MLPACK_METHODS_XGBOOST_LOSS_FUNCTIONS_SSE_LOSS_HPP #include From e4b073f3ee7f876580f92e2859b17262a7802dbe Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 30 Jun 2021 20:46:12 +0530 Subject: [PATCH 480/729] Update template for InitialPrediction so that it can take any armadillo vector instead of just arma::Row --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 64b965fbc9..7ae8b8379b 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -32,10 +32,10 @@ class SSELoss /** * Returns the initial predition for gradient boosting. */ - template - eT InitialPrediction(const arma::Row& values) + template + VecType::elem_type InitialPrediction(const VecType& values) { - return arma::accu(values) / (eT) values.n_elem; + return arma::accu(values) / (VecType::elem_type) values.n_elem; } /** From b80ecf2e958d472a0b507632a8160683296a8ba4 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 30 Jun 2021 20:50:40 +0530 Subject: [PATCH 481/729] Add missing typename --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 7ae8b8379b..a06c7123b8 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -33,9 +33,9 @@ class SSELoss * Returns the initial predition for gradient boosting. */ template - VecType::elem_type InitialPrediction(const VecType& values) + typename VecType::elem_type InitialPrediction(const VecType& values) { - return arma::accu(values) / (VecType::elem_type) values.n_elem; + return arma::accu(values) / (typename VecType::elem_type) values.n_elem; } /** From a609a6412c9f0194ccc9b4fdfd5d959ec9d9ec63 Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Wed, 30 Jun 2021 22:29:47 +0530 Subject: [PATCH 482/729] added PARAM_GLOBAL, able to build linear_regression_py --- src/mlpack/core/util/io.cpp | 7 +++++++ src/mlpack/core/util/mlpack_main.hpp | 19 +++++++++++-------- src/mlpack/core/util/param.hpp | 14 ++++++++++++-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/mlpack/core/util/io.cpp b/src/mlpack/core/util/io.cpp index ebae34c72a..c2d407e7c6 100644 --- a/src/mlpack/core/util/io.cpp +++ b/src/mlpack/core/util/io.cpp @@ -181,9 +181,16 @@ util::Params IO::Parameters(const std::string& bindingName) std::map resultAliases = GetSingleton().aliases[bindingName]; + // Merge in any persistent parameters (e.g. parameters in the "" binding map). + std::map persistentAliases = GetSingleton().aliases[""]; + resultAliases.insert(persistentAliases.begin(), persistentAliases.end()); std::map resultParams = GetSingleton().parameters[bindingName]; + // Merge in any persistent parameters (e.g. parameters in the "" binding map). + std::map persistentParams = + GetSingleton().parameters[""]; + resultParams.insert(persistentParams.begin(), persistentParams.end()); return Params(resultAliases, resultParams, GetSingleton().functionMap, bindingName, GetSingleton().docs[bindingName]); diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index 8ab7f6aa42..f3338538a3 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -224,14 +224,17 @@ using Option = mlpack::bindings::python::PyOption; #error "BINDING_NAME not defined!" #endif -PARAM_FLAG("verbose", "Display informational messages and the full list of " - "parameters and timers at the end of execution.", "v"); -PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep" - " copied before the method is run. This is useful for debugging problems " - "where the input parameters are being modified by the algorithm, but can " - "slow down the code.", ""); -PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked " - "for NaN and inf values; an exception is thrown if any are found.", ""); +PARAM_GLOBAL(bool, "verbose", "Display informational messages and the full " + "list of parameters and timers at the end of execution.", "v", "bool", + false, true, false, false) +PARAM_GLOBAL(bool, "copy_all_inputs", "If specified, all input parameters " + "will be deep copied before the method is run. This is useful for " + "debugging problems where the input parameters are being modified " + "by the algorithm, but can slow down the code.", "", "bool", + false, true, false, false) +PARAM_GLOBAL(bool, "check_input_matrices", "If specified, the input matrix " + "is checked for NaN and inf values; an exception is thrown if any are " + "found.", "", "bool", false, true, false, false) // Nothing else needs to be defined---the binding will use BINDING_NAME() as-is. diff --git a/src/mlpack/core/util/param.hpp b/src/mlpack/core/util/param.hpp index 74a32e46ae..3c876e9c24 100644 --- a/src/mlpack/core/util/param.hpp +++ b/src/mlpack/core/util/param.hpp @@ -1246,9 +1246,9 @@ using DatasetInfo = DatasetMapper; REQ, IN, TRANS, arma::Row()); /** - * Define the PARAM(), PARAM_MODEL() macro. Don't use this function; + * Define the PARAM(), PARAM_MODEL() macro. Don't use this function; * use the other ones above that call it. Note that we are using the __LINE__ - * macro for naming these actual parameters when __COUNTER__ does not exist, + * macro for naming these actual parameters when __COUNTER__ does not exist, * which is a bit of an ugly hack... but this is the preprocessor, after all. * We don't have much choice other than ugliness. * @@ -1267,6 +1267,11 @@ using DatasetInfo = DatasetMapper; JOIN(io_option_dummy_object_in_, __COUNTER__) \ (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, STRINGIFY(BINDING_NAME)); + #define PARAM_GLOBAL(T, ID, DESC, ALIAS, NAME, REQ, IN, TRANS, DEF) \ + static mlpack::util::Option \ + JOIN(io_option_global_dummy_object_in_, __COUNTER__) \ + (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, ""); + // There are no uses of required models, so that is not an option to this // macro (it would be easy to add). #define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \ @@ -1284,6 +1289,11 @@ using DatasetInfo = DatasetMapper; JOIN(JOIN(io_option_dummy_object_in_, __LINE__), opt) \ (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, STRINGIFY(BINDING_NAME)); + #define PARAM_GLOBAL(T, ID, DESC, ALIAS, NAME, REQ, IN, TRANS, DEF) \ + static mlpack::util::Option \ + JOIN(JOIN(io_option_global_dummy_object_in_, __LINE__), opt) \ + (DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, ""); + #define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \ static mlpack::util::Option \ JOIN(JOIN(io_option_dummy_object_model_, __LINE__), opt) \ From bebd49c4a38396165ca6ed831acde40a9477347d Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Wed, 30 Jun 2021 22:38:03 +0530 Subject: [PATCH 483/729] changed python tests --- .../python/tests/test_python_binding_main.cpp | 110 +++++++++--------- 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp index ec24202d8e..ee503af642 100644 --- a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp +++ b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME python_binding_test + #include #include @@ -19,7 +25,7 @@ using namespace mlpack; using namespace mlpack::kernel; // Program Name. -BINDING_NAME("Python binding test"); +BINDING_USER_NAME("Python binding test"); // Short description. BINDING_SHORT_DESC( @@ -73,32 +79,32 @@ PARAM_MODEL_OUT(GaussianKernel, "model_out", "Output model, with twice the " "bandwidth.", ""); PARAM_DOUBLE_OUT("model_bw_out", "The bandwidth of the model."); -static void mlpackMain() +static void BINDING_NAME(util::Params& params, util::Timers& timer) { - const string s = IO::GetParam("string_in"); - const int i = IO::GetParam("int_in"); - const double d = IO::GetParam("double_in"); + const string s = params.Get("string_in"); + const int i = params.Get("int_in"); + const double d = params.Get("double_in"); - IO::GetParam("string_out") = "wrong"; - IO::GetParam("int_out") = 11; - IO::GetParam("double_out") = 3.0; + params.Get("string_out") = "wrong"; + params.Get("int_out") = 11; + params.Get("double_out") = 3.0; // Check that everything is right on the input, and then set output // accordingly. - if (!IO::HasParam("flag2") && IO::HasParam("flag1")) + if (!params.Has("flag2") && params.Has("flag1")) { if (s == "hello") - IO::GetParam("string_out") = "hello2"; + params.Get("string_out") = "hello2"; if (i == 12) - IO::GetParam("int_out") = 13; + params.Get("int_out") = 13; if (d == 4.0) - IO::GetParam("double_out") = 5.0; + params.Get("double_out") = 5.0; } - const arma::mat& matReqIn = IO::GetParam("mat_req_in"); - const arma::vec& colReqIn = IO::GetParam("col_req_in"); + const arma::mat& matReqIn = params.Get("mat_req_in"); + const arma::vec& colReqIn = params.Get("col_req_in"); if (matReqIn.n_rows != 1 || matReqIn.n_cols != 1 || matReqIn(0, 0) != 1.0) { throw std::invalid_argument("mat_req_in must be 1x1 and contain only " @@ -113,103 +119,103 @@ static void mlpackMain() // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("matrix_in")) + if (params.Has("matrix_in")) { - arma::mat out = move(IO::GetParam("matrix_in")); + arma::mat out = move(params.Get("matrix_in")); out.shed_row(4); out.row(2) *= 2.0; - IO::GetParam("matrix_out") = move(out); + params.Get("matrix_out") = move(out); } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("umatrix_in")) + if (params.Has("umatrix_in")) { arma::Mat out = - move(IO::GetParam>("umatrix_in")); + move(params.Get>("umatrix_in")); out.shed_row(4); out.row(2) *= 2; - IO::GetParam>("umatrix_out") = move(out); + params.Get>("umatrix_out") = move(out); } // An input matrix (pandas.Series) should have all elements multiplied by two. - if (IO::HasParam("smatrix_in")) + if (params.Has("smatrix_in")) { - arma::mat out = move(IO::GetParam("smatrix_in")); + arma::mat out = move(params.Get("smatrix_in")); out *= 2.0; - IO::GetParam("smatrix_out") = move(out); + params.Get("smatrix_out") = move(out); } // An input matrix (pandas.Series) should have all elements multiplied by two. - if (IO::HasParam("s_umatrix_in")) + if (params.Has("s_umatrix_in")) { arma::Mat out = - move(IO::GetParam>("s_umatrix_in")); + move(params.Get>("s_umatrix_in")); out *= 2; - IO::GetParam>("s_umatrix_out") = move(out); + params.Get>("s_umatrix_out") = move(out); } // An input column or row should have all elements multiplied by two. - if (IO::HasParam("col_in")) + if (params.Has("col_in")) { - arma::vec out = move(IO::GetParam("col_in")); + arma::vec out = move(params.Get("col_in")); out *= 2.0; - IO::GetParam("col_out") = move(out); + params.Get("col_out") = move(out); } - if (IO::HasParam("ucol_in")) + if (params.Has("ucol_in")) { arma::Col out = - move(IO::GetParam>("ucol_in")); + move(params.Get>("ucol_in")); out *= 2; - IO::GetParam>("ucol_out") = move(out); + params.Get>("ucol_out") = move(out); } - if (IO::HasParam("row_in")) + if (params.Has("row_in")) { - arma::rowvec out = move(IO::GetParam("row_in")); + arma::rowvec out = move(params.Get("row_in")); out *= 2.0; - IO::GetParam("row_out") = move(out); + params.Get("row_out") = move(out); } - if (IO::HasParam("urow_in")) + if (params.Has("urow_in")) { arma::Row out = - move(IO::GetParam>("urow_in")); + move(params.Get>("urow_in")); out *= 2; - IO::GetParam>("urow_out") = move(out); + params.Get>("urow_out") = move(out); } // Vector arguments should have the last element removed. - if (IO::HasParam("vector_in")) + if (params.Has("vector_in")) { - vector out = move(IO::GetParam>("vector_in")); + vector out = move(params.Get>("vector_in")); out.pop_back(); - IO::GetParam>("vector_out") = move(out); + params.Get>("vector_out") = move(out); } - if (IO::HasParam("str_vector_in")) + if (params.Has("str_vector_in")) { - vector out = move(IO::GetParam>("str_vector_in")); + vector out = move(params.Get>("str_vector_in")); out.pop_back(); - IO::GetParam>("str_vector_out") = move(out); + params.Get>("str_vector_out") = move(out); } // All numeric elements should be multiplied by 3. - if (IO::HasParam("matrix_and_info_in")) + if (params.Has("matrix_and_info_in")) { typedef tuple TupleType; - TupleType tuple = move(IO::GetParam("matrix_and_info_in")); + TupleType tuple = move(params.Get("matrix_and_info_in")); const data::DatasetInfo& di = std::get<0>(tuple); arma::mat& m = std::get<1>(tuple); @@ -220,19 +226,19 @@ static void mlpackMain() m.row(i) *= 2.0; } - IO::GetParam("matrix_and_info_out") = move(m); + params.Get("matrix_and_info_out") = move(m); } // If we got a request to build a model, then build it. - if (IO::HasParam("build_model")) + if (params.Has("build_model")) { - IO::GetParam("model_out") = new GaussianKernel(10.0); + params.Get("model_out") = new GaussianKernel(10.0); } // If we got an input model, double the bandwidth and output that. - if (IO::HasParam("model_in")) + if (params.Has("model_in")) { - IO::GetParam("model_bw_out") = - IO::GetParam("model_in")->Bandwidth() * 2.0; + params.Get("model_bw_out") = + params.Get("model_in")->Bandwidth() * 2.0; } } From b8b12f50112bda1c8968498f83aabc2a69b51703 Mon Sep 17 00:00:00 2001 From: Nippun Sharma Date: Wed, 30 Jun 2021 22:39:31 +0530 Subject: [PATCH 484/729] changed name of python tests --- src/mlpack/bindings/python/tests/test_python_binding_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp index ee503af642..19b5f5aa4b 100644 --- a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp +++ b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp @@ -15,7 +15,7 @@ #ifdef BINDING_NAME #undef BINDING_NAME #endif -#define BINDING_NAME python_binding_test +#define BINDING_NAME test_python_binding #include #include From 61e88e6b3c914807bf23da8e39d239f9102364dd Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 30 Jun 2021 23:00:50 +0530 Subject: [PATCH 485/729] Add OutputValue and SimilarityScore methods --- .../xgboost/loss_functions/sse_loss.hpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index a06c7123b8..fc4f941620 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -92,6 +92,33 @@ class SSELoss { return - Gradients(observed, f); } + + /** + * Returns the output value for the leaf in the tree. + */ + template + typename VecType::elem_type + OutputValue(const VecType& gradients, const VecType& hessians, + const double lambda) + { + return - arma::accu(gradients) / (arma::accu(hessians) + lambda); + } + + /** + * Calculates the similarity score for evaluating the splits. + */ + template + double SimilarityScore(const VecType& observed, const VecType& residuals, + const size_t begin, const size_t end, const double lambda) + { + VecType gradients = Gradients(observed.subvec(begin, end), + residuals.subvec(begin, end)); + VecType hessians = Hessians(observed.subvec(begin, end), + residuals.subvec(begin, end)); + + return std::pow(arma::accu(gradients), 2) / + (arma::accu(hessians) + lambda); + } } } // namespace ensemble From 093c4433f13d54718e893ee3fc81e3ec0f1bdc5f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 30 Jun 2021 23:02:53 +0530 Subject: [PATCH 486/729] Fixed filling the hessian vector with 1 --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index fc4f941620..c754e9e7eb 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -75,7 +75,7 @@ class SSELoss arma::is_Row::value>> VecType Hessians(const VecType& /* observed */, const VecType& values) { - VecType h(values.n_elem, 1); + VecType h(values.n_elem, arma::fill::ones); return h; } From c09e82f245ae818a612f06537ad3cfd8f75e448b Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 30 Jun 2021 20:29:15 -0400 Subject: [PATCH 487/729] First attempt to adapt all bindings to use `Params`. --- src/mlpack/methods/adaboost/adaboost_main.cpp | 76 +++++----- .../methods/approx_kfn/approx_kfn_main.cpp | 110 ++++++++------- .../bayesian_linear_regression_main.cpp | 52 ++++--- src/mlpack/methods/cf/cf_main.cpp | 126 +++++++++-------- src/mlpack/methods/dbscan/dbscan_main.cpp | 46 +++--- .../decision_tree/decision_tree_main.cpp | 89 ++++++------ src/mlpack/methods/det/det_main.cpp | 86 +++++------ src/mlpack/methods/emst/emst_main.cpp | 31 ++-- src/mlpack/methods/fastmks/fastmks_main.cpp | 94 +++++++------ src/mlpack/methods/gmm/gmm_generate_main.cpp | 25 ++-- .../methods/gmm/gmm_probability_main.cpp | 19 ++- src/mlpack/methods/gmm/gmm_train_main.cpp | 117 ++++++++------- src/mlpack/methods/hmm/hmm_generate_main.cpp | 38 ++--- src/mlpack/methods/hmm/hmm_loglik_main.cpp | 16 ++- src/mlpack/methods/hmm/hmm_train_main.cpp | 76 +++++----- src/mlpack/methods/hmm/hmm_viterbi_main.cpp | 19 ++- .../hoeffding_trees/hoeffding_tree_main.cpp | 98 +++++++------ src/mlpack/methods/kde/kde_main.cpp | 91 ++++++------ .../methods/kernel_pca/kernel_pca_main.cpp | 49 ++++--- src/mlpack/methods/kmeans/kmeans_main.cpp | 101 ++++++------- src/mlpack/methods/lars/lars_main.cpp | 48 ++++--- .../methods/linear_svm/linear_svm_main.cpp | 125 ++++++++-------- src/mlpack/methods/lmnn/lmnn_main.cpp | 105 +++++++------- .../local_coordinate_coding_main.cpp | 97 +++++++------ .../logistic_regression_main.cpp | 122 ++++++++-------- src/mlpack/methods/lsh/lsh_main.cpp | 100 +++++++------ .../methods/mean_shift/mean_shift_main.cpp | 48 ++++--- src/mlpack/methods/mvu/mvu_main.cpp | 29 ++-- src/mlpack/methods/naive_bayes/nbc_main.cpp | 62 ++++---- src/mlpack/methods/nca/nca_main.cpp | 82 ++++++----- .../methods/neighbor_search/kfn_main.cpp | 120 ++++++++-------- .../methods/neighbor_search/knn_main.cpp | 132 ++++++++--------- src/mlpack/methods/nmf/nmf_main.cpp | 57 ++++---- src/mlpack/methods/pca/pca_main.cpp | 44 +++--- .../methods/perceptron/perceptron_main.cpp | 72 +++++----- .../preprocess/image_converter_main.cpp | 53 ++++--- .../preprocess/preprocess_binarize_main.cpp | 39 ++--- .../preprocess/preprocess_describe_main.cpp | 28 ++-- .../preprocess/preprocess_imputer_main.cpp | 50 ++++--- .../preprocess_one_hot_encoding_main.cpp | 26 ++-- .../preprocess/preprocess_scale_main.cpp | 44 +++--- .../preprocess/preprocess_split_main.cpp | 77 +++++----- src/mlpack/methods/radical/radical_main.cpp | 52 ++++--- .../random_forest/random_forest_main.cpp | 133 ++++++++++-------- .../range_search/range_search_main.cpp | 105 +++++++------- src/mlpack/methods/rann/krann_main.cpp | 110 ++++++++------- .../softmax_regression_main.cpp | 72 +++++----- .../sparse_coding/sparse_coding_main.cpp | 119 ++++++++-------- 48 files changed, 1930 insertions(+), 1580 deletions(-) diff --git a/src/mlpack/methods/adaboost/adaboost_main.cpp b/src/mlpack/methods/adaboost/adaboost_main.cpp index 4635d438f6..705ae4db1a 100644 --- a/src/mlpack/methods/adaboost/adaboost_main.cpp +++ b/src/mlpack/methods/adaboost/adaboost_main.cpp @@ -33,8 +33,14 @@ */ #include #include -#include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME adaboost + #include +#include #include "adaboost.hpp" #include "adaboost_model.hpp" @@ -47,7 +53,7 @@ using namespace mlpack::perceptron; using namespace mlpack::util; // Program Name. -BINDING_NAME("AdaBoost"); +BINDING_USER_NAME("AdaBoost"); // Short description. BINDING_SHORT_DESC( @@ -146,33 +152,33 @@ PARAM_MODEL_IN(AdaBoostModel, "input_model", "Input AdaBoost model.", "m"); PARAM_MODEL_OUT(AdaBoostModel, "output_model", "Output trained AdaBoost model.", "M"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Check input parameters and issue warnings/errors as necessary. // The user cannot specify both a training file and an input model file. - RequireOnlyOnePassed({ "training", "input_model" }); + RequireOnlyOnePassed(params, { "training", "input_model" }); // The weak learner must make sense. - RequireParamInSet("weak_learner", + RequireParamInSet(params, "weak_learner", { "decision_stump", "perceptron" }, true, "unknown weak learner type"); // --labels can't be specified without --training. - ReportIgnoredParam({{ "training", false }}, "labels"); + ReportIgnoredParam(params, {{ "training", false }}, "labels"); // Sanity check on iterations. - RequireParamValue("iterations", [](int x) { return x > 0; }, + RequireParamValue(params, "iterations", [](int x) { return x > 0; }, true, "invalid number of iterations specified"); // If a weak learner is specified with a model, it will be ignored. - ReportIgnoredParam({{ "input_model", true }}, "weak_learner"); + ReportIgnoredParam(params, {{ "input_model", true }}, "weak_learner"); // Training parameters are ignored if no training file is given. - ReportIgnoredParam({{ "training", false }}, "tolerance"); - ReportIgnoredParam({{ "training", false }}, "iterations"); + ReportIgnoredParam(params, {{ "training", false }}, "tolerance"); + ReportIgnoredParam(params, {{ "training", false }}, "iterations"); // If we gave an input model but no test set, issue a warning. - if (IO::HasParam("input_model")) + if (params.Has("input_model")) RequireAtLeastOnePassed({ "test" }, false, "no task will be performed"); RequireAtLeastOnePassed({ "output_model", "output", "predictions" }, false, @@ -182,18 +188,18 @@ static void mlpackMain() ReportIgnoredParam({{ "test", false }}, "predictions"); AdaBoostModel* m; - if (IO::HasParam("training")) + if (params.Has("training")) { - mat trainingData = std::move(IO::GetParam("training")); + mat trainingData = std::move(params.Get("training")); m = new AdaBoostModel(); // Load labels. arma::Row labelsIn; - if (IO::HasParam("labels")) + if (params.Has("labels")) { // Load labels. - labelsIn = std::move(IO::GetParam>("labels")); + labelsIn = std::move(params.Get>("labels")); } else { @@ -212,9 +218,9 @@ static void mlpackMain() data::NormalizeLabels(labelsIn, labels, m->Mappings()); // Get other training parameters. - const double tolerance = IO::GetParam("tolerance"); - const size_t iterations = (size_t) IO::GetParam("iterations"); - const string weakLearner = IO::GetParam("weak_learner"); + const double tolerance = params.Get("tolerance"); + const size_t iterations = (size_t) params.Get("iterations"); + const string weakLearner = params.Get("weak_learner"); if (weakLearner == "decision_stump") m->WeakLearnerType() = AdaBoostModel::WeakLearnerTypes::DECISION_STUMP; else if (weakLearner == "perceptron") @@ -223,20 +229,20 @@ static void mlpackMain() const size_t numClasses = m->Mappings().n_elem; Log::Info << numClasses << " classes in dataset." << endl; - Timer::Start("adaboost_training"); + timers.Start(("adaboost_training"); m->Train(trainingData, labels, numClasses, iterations, tolerance); - Timer::Stop("adaboost_training"); + timers.Stop("adaboost_training"); } else { // We have a specified input model. - m = IO::GetParam("input_model"); + m = params.Get("input_model"); } // Perform classification, if desired. - if (IO::HasParam("test")) + if (params.Has("test")) { - mat testingData = std::move(IO::GetParam("test")); + mat testingData = std::move(params.Get("test")); if (testingData.n_rows != m->Dimensionality()) Log::Fatal << "Test data dimensionality (" << testingData.n_rows << ") " @@ -246,30 +252,30 @@ static void mlpackMain() Row predictedLabels(testingData.n_cols); mat probabilities; - if (IO::HasParam("probabilities")) + if (params.Has("probabilities")) { - Timer::Start("adaboost_classification"); + timers.Start(("adaboost_classification"); m->Classify(testingData, predictedLabels, probabilities); - Timer::Stop("adaboost_classification"); + timers.Stop("adaboost_classification"); } else { - Timer::Start("adaboost_classification"); + timers.Start(("adaboost_classification"); m->Classify(testingData, predictedLabels); - Timer::Stop("adaboost_classification"); + timers.Stop("adaboost_classification"); } Row results; data::RevertLabels(predictedLabels, m->Mappings(), results); // Save the predicted labels. - if (IO::HasParam("output")) - IO::GetParam>("output") = results; - if (IO::HasParam("predictions")) - IO::GetParam>("predictions") = std::move(results); - if (IO::HasParam("probabilities")) - IO::GetParam("probabilities") = std::move(probabilities); + if (params.Has("output")) + params.Get>("output") = results; + if (params.Has("predictions")) + params.Get>("predictions") = std::move(results); + if (params.Has("probabilities")) + params.Get("probabilities") = std::move(probabilities); } - IO::GetParam("output_model") = m; + params.Get("output_model") = m; } diff --git a/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp b/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp index 6a8e4946cd..9be229e664 100644 --- a/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp +++ b/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp @@ -11,8 +11,14 @@ */ #include #include -#include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME approx_kfn + #include +#include #include "drusilla_select.hpp" #include "qdafn.hpp" @@ -22,7 +28,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Approximate furthest neighbor search"); +BINDING_USER_NAME("Approximate furthest neighbor search"); // Short description. BINDING_SHORT_DESC( @@ -171,140 +177,140 @@ PARAM_MODEL_IN(ApproxKFNModel, "input_model", "File containing input model.", PARAM_MODEL_OUT(ApproxKFNModel, "output_model", "File to save output model to.", "M"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // We have to pass either a reference set or an input model. - RequireOnlyOnePassed({ "reference", "input_model" }); + RequireOnlyOnePassed(params, { "reference", "input_model" }); // Warn if no task will be performed. - RequireAtLeastOnePassed({ "reference", "k" }, false, + RequireAtLeastOnePassed(params, { "reference", "k" }, false, "no task will be performed"); // Warn if no output is going to be saved. - RequireAtLeastOnePassed({ "neighbors", "distances", "output_model" }, false, - "no output will be saved"); + RequireAtLeastOnePassed(params, { "neighbors", "distances", "output_model" }, + false, "no output will be saved"); // Check that the user specified a valid algorithm. - RequireParamInSet("algorithm", { "ds", "qdafn" }, true, + RequireParamInSet(params, "algorithm", { "ds", "qdafn" }, true, "unknown algorithm"); // If we are searching, we need a set to search in. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireAtLeastOnePassed({ "reference", "query" }, true, + RequireAtLeastOnePassed(params, { "reference", "query" }, true, "if search is being performed, at least one set must be specified"); } // Validate parameters. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireParamValue("k", [](int x) { return x > 0; }, true, + RequireParamValue(params, "k", [](int x) { return x > 0; }, true, "number of neighbors to search for must be positive"); } - RequireParamValue("num_tables", [](int x) { return x > 0; }, true, - "number of tables must be positive"); - RequireParamValue("num_projections", [](int x) { return x > 0; }, true, - "number of projections must be positive"); + RequireParamValue(params, "num_tables", [](int x) { return x > 0; }, + true, "number of tables must be positive"); + RequireParamValue(params, "num_projections", [](int x) { return x > 0; }, + true, "number of projections must be positive"); - ReportIgnoredParam({{ "input_model", true }}, "algorithm"); - ReportIgnoredParam({{ "input_model", true }}, "num_tables"); - ReportIgnoredParam({{ "input_model", true }}, "num_projections"); - ReportIgnoredParam({{ "k", false }}, "calculate_error"); - ReportIgnoredParam({{ "calculate_error", false }}, "exact_distances"); + ReportIgnoredParam(params, {{ "input_model", true }}, "algorithm"); + ReportIgnoredParam(params, {{ "input_model", true }}, "num_tables"); + ReportIgnoredParam(params, {{ "input_model", true }}, "num_projections"); + ReportIgnoredParam(params, {{ "k", false }}, "calculate_error"); + ReportIgnoredParam(params, {{ "calculate_error", false }}, "exact_distances"); - if (IO::HasParam("calculate_error")) + if (params.Has("calculate_error")) { RequireAtLeastOnePassed({ "exact_distances", "reference" }, true, "if error is to be calculated, either precalculated exact distances or " "the reference set must be passed"); } - if (IO::HasParam("k") && IO::HasParam("reference") && - ((size_t) IO::GetParam("k")) > - IO::GetParam("reference").n_cols) + if (params.Has("k") && params.Has("reference") && + ((size_t) params.Get("k")) > + params.Get("reference").n_cols) { Log::Fatal << "Number of neighbors to search for (" - << IO::GetParam("k") << ") must be less than the number of " + << params.Get("k") << ") must be less than the number of " << "reference points (" - << IO::GetParam("reference").n_cols << ")." << std::endl; + << params.Get("reference").n_cols << ")." << std::endl; } // Do the building of a model, if necessary. ApproxKFNModel* m; arma::mat referenceSet; // This may be used at query time. - if (IO::HasParam("reference")) + if (params.Has("reference")) { - referenceSet = std::move(IO::GetParam("reference")); + referenceSet = std::move(params.Get("reference")); m = new ApproxKFNModel(); - const size_t numTables = (size_t) IO::GetParam("num_tables"); + const size_t numTables = (size_t) params.Get("num_tables"); const size_t numProjections = - (size_t) IO::GetParam("num_projections"); - const string algorithm = IO::GetParam("algorithm"); + (size_t) params.Get("num_projections"); + const string algorithm = params.Get("algorithm"); if (algorithm == "ds") { - Timer::Start("drusilla_select_construct"); + timers.Start(("drusilla_select_construct"); Log::Info << "Building DrusillaSelect model..." << endl; m->type = 0; m->ds = DrusillaSelect<>(referenceSet, numTables, numProjections); - Timer::Stop("drusilla_select_construct"); + timers.Stop("drusilla_select_construct"); } else { - Timer::Start("qdafn_construct"); + timers.Start(("qdafn_construct"); Log::Info << "Building QDAFN model..." << endl; m->type = 1; m->qdafn = QDAFN<>(referenceSet, numTables, numProjections); - Timer::Stop("qdafn_construct"); + timers.Stop("qdafn_construct"); } Log::Info << "Model built." << endl; } else { // We must load the model from what was passed. - m = IO::GetParam("input_model"); + m = params.Get("input_model"); } // Now, do we need to do any queries? - if (IO::HasParam("k")) + if (params.Has("k")) { arma::mat querySet; // This may or may not be used. - const size_t k = (size_t) IO::GetParam("k"); + const size_t k = (size_t) params.Get("k"); arma::Mat neighbors; arma::mat distances; - arma::mat& set = IO::HasParam("query") ? querySet : referenceSet; - if (IO::HasParam("query")) - querySet = std::move(IO::GetParam("query")); + arma::mat& set = params.Has("query") ? querySet : referenceSet; + if (params.Has("query")) + querySet = std::move(params.Get("query")); if (m->type == 0) { - Timer::Start("drusilla_select_search"); + timers.Start(("drusilla_select_search"); Log::Info << "Searching for " << k << " furthest neighbors with " << "DrusillaSelect..." << endl; m->ds.Search(set, k, neighbors, distances); - Timer::Stop("drusilla_select_search"); + timers.Stop("drusilla_select_search"); } else { - Timer::Start("qdafn_search"); + timers.Start(("qdafn_search"); Log::Info << "Searching for " << k << " furthest neighbors with " << "QDAFN..." << endl; m->qdafn.Search(set, k, neighbors, distances); - Timer::Stop("qdafn_search"); + timers.Stop("qdafn_search"); } Log::Info << "Search complete." << endl; // Should we calculate error? - if (IO::HasParam("calculate_error")) + if (params.Has("calculate_error")) { arma::mat exactDistances; - if (IO::HasParam("exact_distances")) + if (params.Has("exact_distances")) { // Check the exact distances matrix has the right dimensions. - exactDistances = std::move(IO::GetParam("exact_distances")); + exactDistances = std::move(params.Get("exact_distances")); if (exactDistances.n_rows != k) { @@ -346,9 +352,9 @@ static void mlpackMain() } // Save results, if desired. - IO::GetParam>("neighbors") = std::move(neighbors); - IO::GetParam("distances") = std::move(distances); + params.Get>("neighbors") = std::move(neighbors); + params.Get("distances") = std::move(distances); } - IO::GetParam("output_model") = m; + params.Get("output_model") = m; } diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp index 01ce9ae4f9..6964b75595 100644 --- a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME bayesian_linear_regression + #include #include "bayesian_linear_regression.hpp" @@ -22,7 +28,7 @@ using namespace mlpack::regression; using namespace mlpack::util; // Program Name. -BINDING_NAME("BayesianLinearRegression"); +BINDING_USER_NAME("BayesianLinearRegression"); // Short description. BINDING_SHORT_DESC( @@ -127,42 +133,42 @@ PARAM_FLAG("center", "Center the data and fit the intercept if enabled.", "c"); PARAM_FLAG("scale", "Scale each feature by their standard deviations if " "enabled.", "s"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - bool center = IO::GetParam("center"); - bool scale = IO::GetParam("scale"); + bool center = params.Get("center"); + bool scale = params.Get("scale"); // Check parameters -- make sure everything given makes sense. - RequireOnlyOnePassed({"input", "input_model"}, true); - if (IO::HasParam("input")) + RequireOnlyOnePassed(params, {"input", "input_model"}, true); + if (params.Has("input")) { - RequireOnlyOnePassed({"responses"}, true, "if input data is specified, " - "responses must also be specified"); + RequireOnlyOnePassed(params, {"responses"}, true, "if input data is " + "specified, responses must also be specified"); } - ReportIgnoredParam({{"input", false }}, "responses"); + ReportIgnoredParam(params, {{"input", false }}, "responses"); - RequireAtLeastOnePassed({"predictions", "output_model", "stds"}, false, - "no results will be saved"); + RequireAtLeastOnePassed(params, {"predictions", "output_model", "stds"}, + false, "no results will be saved"); // Ignore out_predictions unless test is specified. - ReportIgnoredParam({{"test", false}}, "predictions"); + ReportIgnoredParam(params, {{"test", false}}, "predictions"); BayesianLinearRegression* bayesLinReg; - if (IO::HasParam("input")) + if (params.Has("input")) { - Log::Info << "input detected " << std::endl; + Log::Info << "Input given; model will be trained." << std::endl; // Initialize the object. bayesLinReg = new BayesianLinearRegression(center, scale); // Load covariates. We can avoid LARS transposing our data by choosing to // not transpose this data (that's why we used PARAM_TMATRIX_IN). - mat matX = std::move(IO::GetParam("input")); + mat matX = std::move(params.Get("input")); // Load responses. The responses should be a one-dimensional vector, and it // seems more likely that these will be stored with one response per line // (one per row). So we should not transpose upon loading. arma::rowvec responses = std::move( - IO::GetParam("responses")); + params.Get("responses")); if (responses.n_elem != matX.n_cols) { @@ -177,23 +183,23 @@ static void mlpackMain() } else // We must have --input_model_file. { - bayesLinReg = IO::GetParam("input_model"); + bayesLinReg = params.Get("input_model"); } - if (IO::HasParam("test")) + if (params.Has("test")) { Log::Info << "Regressing on test points." << endl; // Load test points. - mat testPoints = std::move(IO::GetParam("test")); + mat testPoints = std::move(params.Get("test")); arma::rowvec predictions; - if (IO::HasParam("stds")) + if (params.Has("stds")) { arma::rowvec std; bayesLinReg->Predict(testPoints, predictions, std); // Save the standard deviation of the test points (one per line). - IO::GetParam("stds") = std::move(std); + params.Get("stds") = std::move(std); } else { @@ -201,8 +207,8 @@ static void mlpackMain() } // Save test predictions (one per line). - IO::GetParam("predictions") = std::move(predictions); + params.Get("predictions") = std::move(predictions); } - IO::GetParam("output_model") = bayesLinReg; + params.Get("output_model") = bayesLinReg; } diff --git a/src/mlpack/methods/cf/cf_main.cpp b/src/mlpack/methods/cf/cf_main.cpp index 0c8cd49539..3cfec63e9c 100644 --- a/src/mlpack/methods/cf/cf_main.cpp +++ b/src/mlpack/methods/cf/cf_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME cf + #include #include @@ -33,7 +39,6 @@ #include #include - using namespace mlpack; using namespace mlpack::cf; using namespace mlpack::amf; @@ -42,7 +47,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Collaborative Filtering"); +BINDING_USER_NAME("Collaborative Filtering"); // Short description. BINDING_SHORT_DESC( @@ -194,54 +199,58 @@ PARAM_STRING_IN("interpolation", "Algorithm used for weight interpolation.", PARAM_STRING_IN("neighbor_search", "Algorithm used for neighbor search.", "S", "euclidean"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") == 0) + if (params.Get("seed") == 0) math::RandomSeed(std::time(NULL)); else - math::RandomSeed(IO::GetParam("seed")); + math::RandomSeed(params.Get("seed")); // Validate parameters. - RequireOnlyOnePassed({ "training", "input_model" }, true); + RequireOnlyOnePassed(params, { "training", "input_model" }, true); // Check that nothing stupid is happening. - if (IO::HasParam("query") || IO::HasParam("all_user_recommendations")) - RequireOnlyOnePassed({ "query", "all_user_recommendations" }, true); + if (params.Has("query") || params.Has("all_user_recommendations")) + RequireOnlyOnePassed(params, { "query", "all_user_recommendations" }, true); - RequireAtLeastOnePassed({ "output", "output_model" }, false, + RequireAtLeastOnePassed(params, { "output", "output_model" }, false, "no output will be saved"); - if (!IO::HasParam("query") && !IO::HasParam("all_user_recommendations")) - ReportIgnoredParam("output", "no recommendations requested"); + if (!params.Has("query") && !params.Has("all_user_recommendations")) + ReportIgnoredParam(params, "output", "no recommendations requested"); RequireParamInSet("algorithm", { "NMF", "BatchSVD", "SVDIncompleteIncremental", "SVDCompleteIncremental", "RegSVD", "RandSVD", "BiasSVD", "SVDPP" }, true, "unknown algorithm"); - ReportIgnoredParam({{ "iteration_only_termination", true }}, "min_residue"); + ReportIgnoredParam(params, {{ "iteration_only_termination", true }}, + "min_residue"); - RequireParamValue("recommendations", [](int x) { return x > 0; }, true, - "recommendations must be positive"); + RequireParamValue(params, "recommendations", + [](int x) { return x > 0; }, true, "recommendations must be positive"); // Either load from a model, or train a model. CFModel* cf; - if (IO::HasParam("training")) + if (params.Has("training")) { // Train a model. // Validate Parameters. - ReportIgnoredParam({{ "iteration_only_termination", true }}, "min_residue"); - RequireParamValue("rank", [](int x) { return x >= 0; }, true, + ReportIgnoredParam(params, {{ "iteration_only_termination", true }}, + "min_residue"); + RequireParamValue(params, "rank", [](int x) { return x >= 0; }, true, "rank must be non-negative"); - RequireParamValue("min_residue", [](double x) { return x >= 0; }, - true, "min_residue must be non-negative"); - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, + RequireParamValue(params, "min_residue", + [](double x) { return x >= 0; }, true, + "min_residue must be non-negative"); + RequireParamValue(params, "max_iterations", + [](int x) { return x >= 0; }, true, "max_iterations must be non-negative"); - RequireParamValue("neighborhood", [](int x) { return x > 0; }, true, - "neighborhood must be positive"); + RequireParamValue(params, "neighborhood", + [](int x) { return x > 0; }, true, "neighborhood must be positive"); // Read from the input file. - arma::mat dataset = std::move(IO::GetParam("training")); + arma::mat dataset = std::move(params.Get("training")); - RequireParamValue("neighborhood", + RequireParamValue(params, "neighborhood", [&dataset](int x) { return x <= max(dataset.row(0)) + 1; }, true, "neighborbood must be less than or equal to the number of users"); @@ -249,14 +258,14 @@ static void mlpackMain() arma::Mat recommendations; // Get parameters. - const size_t rank = (size_t) IO::GetParam("rank"); + const size_t rank = (size_t) params.Get("rank"); cf = new CFModel(); // Perform decomposition to prepare for recommendations. Log::Info << "Performing CF matrix decomposition on dataset..." << endl; - const string algo = IO::GetParam("algorithm"); + const string algo = params.Get("algorithm"); if (algo == "NMF") { cf->DecompositionType() = CFModel::NMF; @@ -275,37 +284,38 @@ static void mlpackMain() } else if (algo == "RegSVD") { - ReportIgnoredParam("min_residue", "Regularized SVD terminates only " - "when max_iterations is reached"); + ReportIgnoredParam(params, "min_residue", "Regularized SVD terminates " + "only when max_iterations is reached"); cf->DecompositionType() = CFModel::REG_SVD; } else if (algo == "RandSVD") { - ReportIgnoredParam("min_residue", "Randomized SVD terminates only " - "when max_iterations is reached"); + ReportIgnoredParam(params, "min_residue", "Randomized SVD terminates " + "only when max_iterations is reached"); cf->DecompositionType() = CFModel::RANDOMIZED_SVD; } else if (algo == "BiasSVD") { - ReportIgnoredParam("min_residue", "Bias SVD terminates only " + ReportIgnoredParam(params, "min_residue", "Bias SVD terminates only " "when max_iterations is reached"); cf->DecompositionType() = CFModel::BIAS_SVD; } else if (algo == "SVDPP") { - ReportIgnoredParam("min_residue", "SVD++ terminates only " + ReportIgnoredParam(params, "min_residue", "SVD++ terminates only " "when max_iterations is reached"); cf->DecompositionType() = CFModel::SVD_PLUS_PLUS; } // Perform the factorization and do whatever the user wanted. - const size_t neighborhood = (size_t) IO::GetParam("neighborhood"); + const size_t neighborhood = (size_t) params.Get("neighborhood"); // Make sure the normalization strategy is valid. - RequireParamInSet("normalization", { "overall_mean", "item_mean", - "user_mean", "z_score", "none" }, true, "unknown normalization type"); + RequireParamInSet(params, "normalization", { "overall_mean", + "item_mean", "user_mean", "z_score", "none" }, true, + "unknown normalization type"); - const string normalizationType = IO::GetParam("normalization"); + const string normalizationType = params.Get("normalization"); if (normalizationType == "none") cf->NormalizationType() = CFModel::NO_NORMALIZATION; else if (normalizationType == "item_mean") @@ -320,56 +330,56 @@ static void mlpackMain() cf->Train(dataset, neighborhood, rank, - size_t(IO::GetParam("max_iterations")), - IO::GetParam("min_residue"), - IO::HasParam("iteration_only_termination")); + size_t(params.Get("max_iterations")), + params.Get("min_residue"), + params.Has("iteration_only_termination")); } else { // Load from a model after validating parameters. - RequireAtLeastOnePassed({ "query", "all_user_recommendations", "test" }, - true); + RequireAtLeastOnePassed(params, { "query", "all_user_recommendations", + "test" }, true); // Load an input model. - cf = std::move(IO::GetParam("input_model")); + cf = std::move(params.Get("input_model")); } // Get the types of the neighbor search method and the interpolation. (These // may or may not be used.) NeighborSearchTypes nsType; - RequireParamInSet("neighbor_search", { "cosine", + RequireParamInSet(params, "neighbor_search", { "cosine", "euclidean", "pearson" }, true, "unknown neighbor search algorithm"); - if (IO::GetParam("neighbor_search") == "cosine") + if (params.Get("neighbor_search") == "cosine") nsType = COSINE_SEARCH; - else if (IO::GetParam("neighbor_search") == "euclidean") + else if (params.Get("neighbor_search") == "euclidean") nsType = EUCLIDEAN_SEARCH; - else // if (IO::GetParam("neighbor_search") == "pearson") + else // if (params.Get("neighbor_search") == "pearson") nsType = PEARSON_SEARCH; InterpolationTypes interpolationType; - RequireParamInSet("interpolation", { "average", + RequireParamInSet(params, "interpolation", { "average", "regression", "similarity" }, true, "unknown interpolation algorithm"); - if (IO::GetParam("interpolation") == "average") + if (params.Get("interpolation") == "average") interpolationType = AVERAGE_INTERPOLATION; - else if (IO::GetParam("interpolation") == "regression") + else if (params.Get("interpolation") == "regression") interpolationType = REGRESSION_INTERPOLATION; - else // if (IO::GetParam("interpolation") == "similarity") + else // if (params.Get("interpolation") == "similarity") interpolationType = SIMILARITY_INTERPOLATION; - if (IO::HasParam("query") || IO::HasParam("all_user_recommendations")) + if (params.Has("query") || params.Has("all_user_recommendations")) { // Get parameters for generating recommendations. - const size_t numRecs = (size_t) IO::GetParam("recommendations"); + const size_t numRecs = (size_t) params.Get("recommendations"); // Get the recommendations. arma::Mat recommendations; // Reading users. - if (IO::HasParam("query")) + if (params.Has("query")) { // User matrix. arma::Mat users = - std::move(IO::GetParam>("query")); + std::move(params.Get>("query")); if (users.n_rows > 1) { users = users.t(); @@ -395,13 +405,13 @@ static void mlpackMain() } // Save the output. - IO::GetParam>("output") = recommendations; + params.Get>("output") = recommendations; } - if (IO::HasParam("test")) + if (params.Has("test")) { // Now, compute each test point. - arma::mat testData = std::move(IO::GetParam("test")); + arma::mat testData = std::move(params.Get("test")); // Assemble the combination matrix to get RMSE value. arma::Mat combinations(2, testData.n_cols); @@ -425,5 +435,5 @@ static void mlpackMain() Log::Info << "RMSE is " << rmse << "." << endl; } - IO::GetParam("output_model") = cf; + params.Get("output_model") = cf; } diff --git a/src/mlpack/methods/dbscan/dbscan_main.cpp b/src/mlpack/methods/dbscan/dbscan_main.cpp index a9b2bcb435..50f58928de 100644 --- a/src/mlpack/methods/dbscan/dbscan_main.cpp +++ b/src/mlpack/methods/dbscan/dbscan_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME dbscan + #include #include #include @@ -28,7 +34,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("DBSCAN clustering"); +BINDING_USER_NAME("DBSCAN clustering"); // Short description. BINDING_SHORT_DESC( @@ -104,41 +110,41 @@ template void RunDBSCAN(RangeSearchType rs, PointSelectionPolicy pointSelector = PointSelectionPolicy()) { - if (IO::HasParam("single_mode")) + if (params.Has("single_mode")) rs.SingleMode() = true; // Load dataset. - arma::mat dataset = std::move(IO::GetParam("input")); - const double epsilon = IO::GetParam("epsilon"); - const size_t minSize = (size_t) IO::GetParam("min_size"); + arma::mat dataset = std::move(params.Get("input")); + const double epsilon = params.Get("epsilon"); + const size_t minSize = (size_t) params.Get("min_size"); arma::Row assignments; DBSCAN d(epsilon, minSize, - !IO::HasParam("single_mode"), rs, pointSelector); + !params.Has("single_mode"), rs, pointSelector); // If possible, avoid the overhead of calculating centroids. - if (IO::HasParam("centroids")) + if (params.Has("centroids")) { arma::mat centroids; d.Cluster(dataset, assignments, centroids); - IO::GetParam("centroids") = std::move(centroids); + params.Get("centroids") = std::move(centroids); } else { d.Cluster(dataset, assignments); } - if (IO::HasParam("assignments")) - IO::GetParam>("assignments") = std::move(assignments); + if (params.Has("assignments")) + params.Get>("assignments") = std::move(assignments); } // Choose the point selection policy. template void ChoosePointSelectionPolicy(RangeSearchType rs = RangeSearchType()) { - const string selectionType = IO::GetParam("selection_type"); + const string selectionType = params.Get("selection_type"); if (selectionType == "ordered") RunDBSCAN(rs); @@ -146,34 +152,34 @@ void ChoosePointSelectionPolicy(RangeSearchType rs = RangeSearchType()) RunDBSCAN(rs); } -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - RequireAtLeastOnePassed({ "assignments", "centroids" }, false, + RequireAtLeastOnePassed(params, { "assignments", "centroids" }, false, "no output will be saved"); - ReportIgnoredParam({{ "naive", true }}, "single_mode"); + ReportIgnoredParam(params, {{ "naive", true }}, "single_mode"); - RequireParamInSet("tree_type", { "kd", "cover", "r", "r-star", "x", - "hilbert-r", "r-plus", "r-plus-plus", "ball" }, true, + RequireParamInSet(params, "tree_type", { "kd", "cover", "r", "r-star", + "x", "hilbert-r", "r-plus", "r-plus-plus", "ball" }, true, "unknown tree type"); // Value of epsilon should be positive. - RequireParamValue("epsilon", [](double x) { return x > 0; }, + RequireParamValue(params, "epsilon", [](double x) { return x > 0; }, true, "invalid value of epsilon specified"); // Value of min_size should be positive. - RequireParamValue("min_size", [](int y) { return y > 0; }, + RequireParamValue(params, "min_size", [](int y) { return y > 0; }, true, "invalid value of min_size specified"); // Fire off naive search if needed. - if (IO::HasParam("naive")) + if (params.Has("naive")) { RangeSearch<> rs(true); ChoosePointSelectionPolicy(rs); } else { - const string treeType = IO::GetParam("tree_type"); + const string treeType = params.Get("tree_type"); if (treeType == "kd") { ChoosePointSelectionPolicy>(); diff --git a/src/mlpack/methods/decision_tree/decision_tree_main.cpp b/src/mlpack/methods/decision_tree/decision_tree_main.cpp index d19e22eb8a..74117e3656 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_main.cpp +++ b/src/mlpack/methods/decision_tree/decision_tree_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME decision_tree + #include #include "decision_tree.hpp" @@ -21,7 +27,7 @@ using namespace mlpack::data; using namespace mlpack::util; // Program Name. -BINDING_NAME("Decision tree"); +BINDING_USER_NAME("Decision tree"); // Short description. BINDING_SHORT_DESC( @@ -155,29 +161,30 @@ PARAM_MODEL_OUT(DecisionTreeModel, "output_model", "Output for trained decision" // Convenience typedef. typedef tuple TupleType; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Check parameters. - RequireOnlyOnePassed({ "training", "input_model" }, true); - ReportIgnoredParam({{ "test", false }}, "test_labels"); - RequireAtLeastOnePassed({ "output_model", "probabilities", "predictions" }, - false, "no output will be saved"); - ReportIgnoredParam({{ "training", false }}, "print_training_accuracy"); + RequireOnlyOnePassed(params, { "training", "input_model" }, true); + ReportIgnoredParam(params, {{ "test", false }}, "test_labels"); + RequireAtLeastOnePassed(params, { "output_model", "probabilities", + "predictions" }, false, "no output will be saved"); + ReportIgnoredParam(params, {{ "training", false }}, + "print_training_accuracy"); - ReportIgnoredParam({{ "test", false }}, "predictions"); - ReportIgnoredParam({{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); - RequireParamValue("minimum_leaf_size", [](int x) { return x > 0; }, true, - "leaf size must be positive"); + RequireParamValue(params, "minimum_leaf_size", + [](int x) { return x > 0; }, true, "leaf size must be positive"); - RequireParamValue("maximum_depth", [](int x) { return x >= 0; }, true, - "maximum depth must not be negative"); + RequireParamValue(params, "maximum_depth", + [](int x) { return x >= 0; }, true, "maximum depth must not be negative"); - RequireParamValue("minimum_gain_split", [](double x) - { return (x > 0.0 && x < 1.0); }, true, - "gain split must be a fraction in range [0,1]"); + RequireParamValue(params, "minimum_gain_split", + [](double x) { return (x > 0.0 && x < 1.0); }, true, + "gain split must be a fraction in range [0,1]"); - if (IO::HasParam("print_training_error")) + if (params.Has("print_training_error")) { Log::Warn << "The option " << PRINT_PARAM_STRING("print_training_error") << " is deprecated and will be removed in mlpack 4.0.0." << std::endl; @@ -188,14 +195,14 @@ static void mlpackMain() arma::mat trainingSet; arma::Row labels; - if (IO::HasParam("training")) + if (params.Has("training")) { model = new DecisionTreeModel(); - model->info = std::move(std::get<0>(IO::GetParam("training"))); - trainingSet = std::move(std::get<1>(IO::GetParam("training"))); - if (IO::HasParam("labels")) + model->info = std::move(std::get<0>(params.Get("training"))); + trainingSet = std::move(std::get<1>(params.Get("training"))); + if (params.Has("labels")) { - labels = std::move(IO::GetParam>("labels")); + labels = std::move(params.Get>("labels")); } else { @@ -210,18 +217,18 @@ static void mlpackMain() const size_t numClasses = arma::max(arma::max(labels)) + 1; // Now build the tree. - const size_t minLeafSize = (size_t) IO::GetParam("minimum_leaf_size"); - const size_t maxDepth = (size_t) IO::GetParam("maximum_depth"); + const size_t minLeafSize = (size_t) params.Get("minimum_leaf_size"); + const size_t maxDepth = (size_t) params.Get("maximum_depth"); const double minimumGainSplit = - (double) IO::GetParam("minimum_gain_split"); + (double) params.Get("minimum_gain_split"); // Create decision tree with weighted labels. - if (IO::HasParam("weights")) + if (params.Has("weights")) { arma::Row weights = - std::move(IO::GetParam>("weights")); - if (IO::HasParam("print_training_error") || - IO::HasParam("print_training_accuracy")) + std::move(params.Get>("weights")); + if (params.Has("print_training_error") || + params.Has("print_training_accuracy")) { model->tree = DecisionTree<>(trainingSet, model->info, labels, numClasses, std::move(weights), minLeafSize, minimumGainSplit, @@ -236,7 +243,7 @@ static void mlpackMain() } else { - if (IO::HasParam("print_training_error")) + if (params.Has("print_training_error")) { model->tree = DecisionTree<>(trainingSet, model->info, labels, numClasses, minLeafSize, minimumGainSplit, maxDepth); @@ -250,8 +257,8 @@ static void mlpackMain() } // Do we need to print training error? - if (IO::HasParam("print_training_error") || - IO::HasParam("print_training_accuracy")) + if (params.Has("print_training_error") || + params.Has("print_training_accuracy")) { arma::Row predictions; arma::mat probabilities; @@ -271,14 +278,14 @@ static void mlpackMain() } else { - model = IO::GetParam("input_model"); + model = params.Get("input_model"); } // Do we need to get predictions? - if (IO::HasParam("test")) + if (params.Has("test")) { - std::get<0>(IO::GetRawParam("test")) = model->info; - arma::mat testPoints = std::get<1>(IO::GetParam("test")); + std::get<0>(params.GetRaw("test")) = model->info; + arma::mat testPoints = std::get<1>(params.Get("test")); arma::Row predictions; arma::mat probabilities; @@ -286,10 +293,10 @@ static void mlpackMain() model->tree.Classify(testPoints, predictions, probabilities); // Do we need to calculate accuracy? - if (IO::HasParam("test_labels")) + if (params.Has("test_labels")) { arma::Row testLabels = - std::move(IO::GetParam>("test_labels")); + std::move(params.Get>("test_labels")); size_t correct = 0; for (size_t i = 0; i < testPoints.n_cols; ++i) @@ -303,10 +310,10 @@ static void mlpackMain() } // Do we need to save outputs? - IO::GetParam>("predictions") = predictions; - IO::GetParam("probabilities") = probabilities; + params.Get>("predictions") = predictions; + params.Get("probabilities") = probabilities; } // Do we need to save the model? - IO::GetParam("output_model") = model; + params.Get("output_model") = model; } diff --git a/src/mlpack/methods/det/det_main.cpp b/src/mlpack/methods/det/det_main.cpp index 97193c19e2..940e92737f 100644 --- a/src/mlpack/methods/det/det_main.cpp +++ b/src/mlpack/methods/det/det_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME det + #include #include "dt_utils.hpp" @@ -20,7 +26,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Density Estimation With Density Estimation Trees"); +BINDING_USER_NAME("Density Estimation With Density Estimation Trees"); // Short description. BINDING_SHORT_DESC( @@ -119,27 +125,27 @@ PARAM_FLAG("volume_regularization", "This flag gives the used the option to use" "penalize low volume leaves.", "R"); */ - -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Validate input parameters. - RequireOnlyOnePassed({ "training", "input_model" }, true); + RequireOnlyOnePassed(params, { "training", "input_model" }, true); - ReportIgnoredParam({{ "training", false }}, "training_set_estimates"); - ReportIgnoredParam({{ "training", false }}, "folds"); - ReportIgnoredParam({{ "training", false }}, "min_leaf_size"); - ReportIgnoredParam({{ "training", false }}, "max_leaf_size"); + ReportIgnoredParam(params, {{ "training", false }}, "training_set_estimates"); + ReportIgnoredParam(params, {{ "training", false }}, "folds"); + ReportIgnoredParam(params, {{ "training", false }}, "min_leaf_size"); + ReportIgnoredParam(params, {{ "training", false }}, "max_leaf_size"); - if (IO::HasParam("tag_file")) - RequireAtLeastOnePassed({ "training", "test" }, true); + if (params.Has("tag_file")) + RequireAtLeastOnePassed(params, { "training", "test" }, true); - if (IO::HasParam("training")) + if (params.Has("training")) { - RequireAtLeastOnePassed({ "output_model", "training_set_estimates", "vi", - "tag_file", "tag_counters_file" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "training_set_estimates", + "vi", "tag_file", "tag_counters_file" }, false, + "no output will be saved"); } - ReportIgnoredParam({{ "test", false }}, "test_set_estimates"); + ReportIgnoredParam(params, {{ "test", false }}, "test_set_estimates"); RequireParamValue("folds", [](int x) { return x >= 0; }, true, "folds must be non-negative"); @@ -153,16 +159,16 @@ static void mlpackMain() arma::mat trainingData; arma::mat testData; - if (IO::HasParam("training")) + if (params.Has("training")) { - trainingData = std::move(IO::GetParam("training")); + trainingData = std::move(params.Get("training")); const bool regularization = false; -// const bool regularization = IO::HasParam("volume_regularization"); - const int maxLeafSize = IO::GetParam("max_leaf_size"); - const int minLeafSize = IO::GetParam("min_leaf_size"); - const bool skipPruning = IO::HasParam("skip_pruning"); - size_t folds = IO::GetParam("folds"); +// const bool regularization = params.Has("volume_regularization"); + const int maxLeafSize = params.Get("max_leaf_size"); + const int minLeafSize = params.Get("min_leaf_size"); + const bool skipPruning = params.Has("skip_pruning"); + size_t folds = params.Get("folds"); if (folds == 0) folds = trainingData.n_cols; @@ -175,7 +181,7 @@ static void mlpackMain() Timer::Stop("det_training"); // Compute training set estimates, if desired. - if (IO::HasParam("training_set_estimates")) + if (params.Has("training_set_estimates")) { // Compute density estimates for each point in the training set. arma::rowvec trainingDensities(trainingData.n_cols); @@ -184,21 +190,21 @@ static void mlpackMain() trainingDensities[i] = tree->ComputeValue(trainingData.unsafe_col(i)); Timer::Stop("det_estimation_time"); - IO::GetParam("training_set_estimates") = + params.Get("training_set_estimates") = std::move(trainingDensities); } } else { - tree = IO::GetParam*>("input_model"); + tree = params.Get*>("input_model"); } // Compute the density at the provided test points and output the density in // the given file. - if (IO::HasParam("test")) + if (params.Has("test")) { - testData = std::move(IO::GetParam("test")); - if (IO::HasParam("test_set_estimates")) + testData = std::move(params.Get("test")); + if (params.Has("test_set_estimates")) { // Compute test set densities. Timer::Start("det_test_set_estimation"); @@ -209,23 +215,23 @@ static void mlpackMain() Timer::Stop("det_test_set_estimation"); - IO::GetParam("test_set_estimates") = std::move(testDensities); + params.Get("test_set_estimates") = std::move(testDensities); } // Print variable importance. - if (IO::HasParam("vi")) + if (params.Has("vi")) { arma::vec importances; tree->ComputeVariableImportance(importances); - IO::GetParam("vi") = importances.t(); + params.Get("vi") = importances.t(); } } - if (IO::HasParam("tag_file")) + if (params.Has("tag_file")) { const arma::mat& estimationData = - IO::HasParam("test") ? testData : trainingData; - const string tagFile = IO::GetParam("tag_file"); + params.Has("test") ? testData : trainingData; + const string tagFile = params.Get("tag_file"); std::ofstream ofs; ofs.open(tagFile, std::ofstream::out); @@ -237,10 +243,10 @@ static void mlpackMain() Log::Warn << "Unable to open file '" << tagFile << "' to save tag membership info." << std::endl; } - else if (IO::HasParam("path_format")) + else if (params.Has("path_format")) { - const bool reqCounters = IO::HasParam("tag_counters_file"); - const string pathFormat = IO::GetParam("path_format"); + const bool reqCounters = params.Has("tag_counters_file"); + const string pathFormat = params.Get("path_format"); PathCacher::PathFormat theFormat; if (pathFormat == "lr" || pathFormat == "LR") @@ -272,7 +278,7 @@ static void mlpackMain() if (reqCounters) { - ofs.open(IO::GetParam("tag_counters_file"), + ofs.open(params.Get("tag_counters_file"), std::ofstream::out); for (size_t j = 0; j < counters.n_elem; ++j) @@ -296,8 +302,8 @@ static void mlpackMain() counters(tag) += 1; } - if (IO::HasParam("tag_counters_file")) - data::Save(IO::GetParam("tag_counters_file"), counters); + if (params.Has("tag_counters_file")) + data::Save(params.Get("tag_counters_file"), counters); } Timer::Stop("det_test_set_tagging"); @@ -305,5 +311,5 @@ static void mlpackMain() } // Save the model, if desired. - IO::GetParam*>("output_model") = tree; + params.Get*>("output_model") = tree; } diff --git a/src/mlpack/methods/emst/emst_main.cpp b/src/mlpack/methods/emst/emst_main.cpp index c078af4381..7a868dcd1e 100644 --- a/src/mlpack/methods/emst/emst_main.cpp +++ b/src/mlpack/methods/emst/emst_main.cpp @@ -26,12 +26,18 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME emst + #include #include "dtb.hpp" // Program Name. -BINDING_NAME("Fast Euclidean Minimum Spanning Tree"); +BINDING_USER_NAME("Fast Euclidean Minimum Spanning Tree"); // Short description. BINDING_SHORT_DESC( @@ -92,14 +98,15 @@ using namespace mlpack::metric; using namespace mlpack::util; using namespace std; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - RequireAtLeastOnePassed({ "output" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no output will be saved"); - arma::mat dataPoints = std::move(IO::GetParam("input")); + arma::mat dataPoints = std::move(params.Get("input")); // Do naive computation if necessary. - if (IO::GetParam("naive")) + if (params.Get("naive")) { Log::Info << "Running naive algorithm." << endl; @@ -108,20 +115,20 @@ static void mlpackMain() arma::mat naiveResults; naive.ComputeMST(naiveResults); - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(naiveResults); + if (params.Has("output")) + params.Get("output") = std::move(naiveResults); } else { Log::Info << "Building tree.\n"; // Check that the leaf size is reasonable. - RequireParamValue("leaf_size", [](int x) { return x > 0; }, true, - "leaf size must be greater than or equal to 1"); + RequireParamValue(params, "leaf_size", [](int x) { return x > 0; }, + true, "leaf size must be greater than or equal to 1"); // Initialize the tree and get ready to compute the MST. Compute the tree // by hand. - const size_t leafSize = (size_t) IO::GetParam("leaf_size"); + const size_t leafSize = (size_t) params.Get("leaf_size"); Timer::Start("tree_building"); std::vector oldFromNew; @@ -158,7 +165,7 @@ static void mlpackMain() unmappedResults(2, i) = results(2, i); } - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(unmappedResults); + if (params.Has("output")) + params.Get("output") = std::move(unmappedResults); } } diff --git a/src/mlpack/methods/fastmks/fastmks_main.cpp b/src/mlpack/methods/fastmks/fastmks_main.cpp index 1638f64922..51cc43dea5 100644 --- a/src/mlpack/methods/fastmks/fastmks_main.cpp +++ b/src/mlpack/methods/fastmks/fastmks_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME fastmks + #include #include "fastmks.hpp" @@ -25,7 +31,7 @@ using namespace mlpack::metric; using namespace mlpack::util; // Program Name. -BINDING_NAME("FastMKS (Fast Max-Kernel Search)"); +BINDING_USER_NAME("FastMKS (Fast Max-Kernel Search)"); // Short description. BINDING_SHORT_DESC( @@ -105,70 +111,70 @@ PARAM_FLAG("single", "If true, single-tree search is used (as opposed to " PARAM_MATRIX_OUT("kernels", "Output matrix of kernels.", "p"); PARAM_UMATRIX_OUT("indices", "Output matrix of indices.", "i"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Validate command-line parameters. - RequireOnlyOnePassed({ "reference", "input_model" }, true); + RequireOnlyOnePassed(params, { "reference", "input_model" }, true); - ReportIgnoredParam({{ "input_model", true }}, "kernel"); - ReportIgnoredParam({{ "input_model", true }}, "bandwidth"); - ReportIgnoredParam({{ "input_model", true }}, "degree"); - ReportIgnoredParam({{ "input_model", true }}, "offset"); + ReportIgnoredParam(params, {{ "input_model", true }}, "kernel"); + ReportIgnoredParam(params, {{ "input_model", true }}, "bandwidth"); + ReportIgnoredParam(params, {{ "input_model", true }}, "degree"); + ReportIgnoredParam(params, {{ "input_model", true }}, "offset"); - ReportIgnoredParam({{ "k", false }}, "indices"); - ReportIgnoredParam({{ "k", false }}, "kernels"); - ReportIgnoredParam({{ "k", false }}, "query"); + ReportIgnoredParam(params, {{ "k", false }}, "indices"); + ReportIgnoredParam(params, {{ "k", false }}, "kernels"); + ReportIgnoredParam(params, {{ "k", false }}, "query"); - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireAtLeastOnePassed({ "indices", "kernels" }, false, + RequireAtLeastOnePassed(params, { "indices", "kernels" }, false, "no output will be saved"); } // Check on kernel type. - RequireParamInSet("kernel", { "linear", "polynomial", "cosine", - "gaussian", "triangular", "hyptan", "epanechnikov" }, true, + RequireParamInSet(params, "kernel", { "linear", "polynomial", + "cosine", "gaussian", "triangular", "hyptan", "epanechnikov" }, true, "unknown kernel type"); // Make sure number of maximum kernels is greater than 0. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireParamValue("k", [](int x) { return x > 0; }, true, + RequireParamValue(params, "k", [](int x) { return x > 0; }, true, "number of maximum kernels must be greater than 0"); } - if (IO::HasParam("base")) + if (params.Has("base")) { - RequireParamValue("base", [](double x) { return x > 1.0; }, true, - "base must be greater than or equal to 1!"); + RequireParamValue(params, "base", [](double x) { return x > 1.0; }, + true, "base must be greater than or equal to 1!"); } // Naive mode overrides single mode. - ReportIgnoredParam({{ "naive", true }}, "single"); + ReportIgnoredParam(params, {{ "naive", true }}, "single"); FastMKSModel* model; arma::mat referenceData; - if (IO::HasParam("reference")) + if (params.Has("reference")) { model = new FastMKSModel(); - referenceData = std::move(IO::GetParam("reference")); + referenceData = std::move(params.Get("reference")); Log::Info << "Loaded reference data (" << referenceData.n_rows << " x " << referenceData.n_cols << ")." << endl; // For cover tree construction. - const double base = IO::GetParam("base"); + const double base = params.Get("base"); // Kernel parameters. - const string kernelType = IO::GetParam("kernel"); - const double degree = IO::GetParam("degree"); - const double offset = IO::GetParam("offset"); - const double bandwidth = IO::GetParam("bandwidth"); - const double scale = IO::GetParam("scale"); + const string kernelType = params.Get("kernel"); + const double degree = params.Get("degree"); + const double offset = params.Get("offset"); + const double bandwidth = params.Get("bandwidth"); + const double scale = params.Get("scale"); // Search preferences. - const bool naive = IO::HasParam("naive"); - const bool single = IO::HasParam("single"); + const bool naive = params.Has("naive"); + const bool single = params.Has("single"); if (kernelType == "linear") { @@ -216,37 +222,37 @@ static void mlpackMain() else { // Load model from file, then do whatever is necessary. - model = IO::GetParam("input_model"); + model = params.Get("input_model"); } // Set search preferences. - model->Naive() = IO::HasParam("naive"); - model->SingleMode() = IO::HasParam("single"); + model->Naive() = params.Has("naive"); + model->SingleMode() = params.Has("single"); // Should we do search? - if (IO::HasParam("k")) + if (params.Has("k")) { arma::mat kernels; arma::Mat indices; - if (IO::HasParam("query")) + if (params.Has("query")) { - const double base = IO::GetParam("base"); + const double base = params.Get("base"); - arma::mat queryData = std::move(IO::GetParam("query")); + arma::mat queryData = std::move(params.Get("query")); Log::Info << "Loaded query data (" << queryData.n_rows << " x " << queryData.n_cols << ")." << endl; try { - model->Search(queryData, (size_t) IO::GetParam("k"), indices, + model->Search(queryData, (size_t) params.Get("k"), indices, kernels, base); } catch (std::invalid_argument& e) { // Delete the memory, if needed. - if (IO::HasParam("reference")) + if (params.Has("reference")) delete model; throw; } @@ -255,22 +261,22 @@ static void mlpackMain() { try { - model->Search((size_t) IO::GetParam("k"), indices, kernels); + model->Search((size_t) params.Get("k"), indices, kernels); } catch (std::invalid_argument& e) { // Delete the memory, if needed. - if (IO::HasParam("reference")) + if (params.Has("reference")) delete model; throw; } } // Save output. - IO::GetParam("kernels") = std::move(kernels); - IO::GetParam>("indices") = std::move(indices); + params.Get("kernels") = std::move(kernels); + params.Get>("indices") = std::move(indices); } // Save the model. - IO::GetParam("output_model") = model; + params.Get("output_model") = model; } diff --git a/src/mlpack/methods/gmm/gmm_generate_main.cpp b/src/mlpack/methods/gmm/gmm_generate_main.cpp index aa6e995567..b52d89544c 100644 --- a/src/mlpack/methods/gmm/gmm_generate_main.cpp +++ b/src/mlpack/methods/gmm/gmm_generate_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME gmm_generate + #include #include "gmm.hpp" @@ -20,7 +26,7 @@ using namespace mlpack::gmm; using namespace mlpack::util; // Program Name. -BINDING_NAME("GMM Sample Generator"); +BINDING_USER_NAME("GMM Sample Generator"); // Short description. BINDING_SHORT_DESC( @@ -61,27 +67,28 @@ PARAM_MATRIX_OUT("output", "Matrix to save output samples in.", "o"); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Parameter sanity checks. - RequireAtLeastOnePassed({ "output" }, false, "no results will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no results will be saved"); - if (IO::GetParam("seed") == 0) + if (params.Get("seed") == 0) mlpack::math::RandomSeed(time(NULL)); else - mlpack::math::RandomSeed((size_t) IO::GetParam("seed")); + mlpack::math::RandomSeed((size_t) params.Get("seed")); - RequireParamValue("samples", [](int x) { return x > 0; }, true, + RequireParamValue(params, "samples", [](int x) { return x > 0; }, true, "number of samples must be greater than 0"); - GMM* gmm = IO::GetParam("input_model"); + GMM* gmm = params.Get("input_model"); - size_t length = (size_t) IO::GetParam("samples"); + size_t length = (size_t) params.Get("samples"); Log::Info << "Generating " << length << " samples..." << endl; arma::mat samples(gmm->Dimensionality(), length); for (size_t i = 0; i < length; ++i) samples.col(i) = gmm->Random(); // Save, if the user asked for it. - IO::GetParam("output") = std::move(samples); + params.Get("output") = std::move(samples); } diff --git a/src/mlpack/methods/gmm/gmm_probability_main.cpp b/src/mlpack/methods/gmm/gmm_probability_main.cpp index 54597696e4..2d1468d34c 100644 --- a/src/mlpack/methods/gmm/gmm_probability_main.cpp +++ b/src/mlpack/methods/gmm/gmm_probability_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME gmm_probability + #include #include "gmm.hpp" @@ -20,7 +26,7 @@ using namespace mlpack::gmm; using namespace mlpack::util; // Program Name. -BINDING_NAME("GMM Probability Calculator"); +BINDING_USER_NAME("GMM Probability Calculator"); // Short description. BINDING_SHORT_DESC( @@ -61,14 +67,15 @@ PARAM_MATRIX_IN_REQ("input", "Input matrix to calculate probabilities of.", PARAM_MATRIX_OUT("output", "Matrix to store calculated probabilities in.", "o"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - RequireAtLeastOnePassed({ "output" }, false, "no results will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no results will be saved"); // Get the GMM and the points. - GMM* gmm = IO::GetParam("input_model"); + GMM* gmm = params.Get("input_model"); - arma::mat dataset = std::move(IO::GetParam("input")); + arma::mat dataset = std::move(params.Get("input")); // Now calculate the probabilities. arma::rowvec probabilities(dataset.n_cols); @@ -76,5 +83,5 @@ static void mlpackMain() probabilities[i] = gmm->Probability(dataset.unsafe_col(i)); // And save the result. - IO::GetParam("output") = std::move(probabilities); + params.Get("output") = std::move(probabilities); } diff --git a/src/mlpack/methods/gmm/gmm_train_main.cpp b/src/mlpack/methods/gmm/gmm_train_main.cpp index daa911b204..079068d794 100644 --- a/src/mlpack/methods/gmm/gmm_train_main.cpp +++ b/src/mlpack/methods/gmm/gmm_train_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME gmm_train + #include #include "gmm.hpp" @@ -27,7 +33,7 @@ using namespace mlpack::kmeans; using namespace std; // Program Name. -BINDING_NAME("Gaussian Mixture Model (GMM) Training"); +BINDING_USER_NAME("Gaussian Mixture Model (GMM) Training"); // Short description. BINDING_SHORT_DESC( @@ -145,51 +151,54 @@ PARAM_MODEL_IN(GMM, "input_model", "Initial input GMM model to start training " "with.", "m"); PARAM_MODEL_OUT(GMM, "output_model", "Output for trained GMM model.", "M"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Check parameters and load data. - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); - RequireParamValue("gaussians", [](int x) { return x > 0; }, true, + RequireParamValue(params, "gaussians", [](int x) { return x > 0; }, true, "number of Gaussians must be positive"); - const int gaussians = IO::GetParam("gaussians"); + const int gaussians = params.Get("gaussians"); - RequireParamValue("trials", [](int x) { return x > 0; }, true, + RequireParamValue(params, "trials", [](int x) { return x > 0; }, true, "trials must be greater than 0"); - ReportIgnoredParam({{ "diagonal_covariance", true }}, "no_force_positive"); - RequireAtLeastOnePassed({ "output_model" }, false, "no model will be saved"); + ReportIgnoredParam(params, {{ "diagonal_covariance", true }}, + "no_force_positive"); + RequireAtLeastOnePassed(params, { "output_model" }, false, + "no model will be saved"); - RequireParamValue("noise", [](double x) { return x >= 0.0; }, true, - "variance of noise must be greater than or equal to 0"); + RequireParamValue(params, "noise", [](double x) { return x >= 0.0; }, + true, "variance of noise must be greater than or equal to 0"); - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, - "max_iterations must be greater than or equal to 0"); - RequireParamValue("kmeans_max_iterations", [](int x) { return x >= 0; }, - true, "kmeans_max_iterations must be greater than or equal to 0"); + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, + true, "max_iterations must be greater than or equal to 0"); + RequireParamValue(params, "kmeans_max_iterations", + [](int x) { return x >= 0; }, true, + "kmeans_max_iterations must be greater than or equal to 0"); - arma::mat dataPoints = std::move(IO::GetParam("input")); + arma::mat dataPoints = std::move(params.Get("input")); // Do we need to add noise to the dataset? - if (IO::HasParam("noise")) + if (params.Has("noise")) { - Timer::Start("noise_addition"); - const double noise = IO::GetParam("noise"); + timers.Start(("noise_addition"); + const double noise = params.Get("noise"); dataPoints += noise * arma::randn(dataPoints.n_rows, dataPoints.n_cols); Log::Info << "Added zero-mean Gaussian noise with variance " << noise << " to dataset." << std::endl; - Timer::Stop("noise_addition"); + timers.Stop("noise_addition"); } // Initialize GMM. GMM* gmm = NULL; - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { - gmm = IO::GetParam("input_model"); + gmm = params.Get("input_model"); if (gmm->Dimensionality() != dataPoints.n_rows) Log::Fatal << "Given input data (with " << PRINT_PARAM_STRING("input") @@ -199,31 +208,31 @@ static void mlpackMain() } // Gather parameters for EMFit object. - const size_t maxIterations = (size_t) IO::GetParam("max_iterations"); - const double tolerance = IO::GetParam("tolerance"); - const bool forcePositive = !IO::HasParam("no_force_positive"); - const bool diagonalCovariance = IO::HasParam("diagonal_covariance"); + const size_t maxIterations = (size_t) params.Get("max_iterations"); + const double tolerance = params.Get("tolerance"); + const bool forcePositive = !params.Has("no_force_positive"); + const bool diagonalCovariance = params.Has("diagonal_covariance"); const size_t kmeansMaxIterations = - (size_t) IO::GetParam("kmeans_max_iterations"); + (size_t) params.Get("kmeans_max_iterations"); // This gets a bit weird because we need different types depending on whether // --refined_start is specified. double likelihood; - if (IO::HasParam("refined_start")) + if (params.Has("refined_start")) { - RequireParamValue("samplings", [](int x) { return x > 0; }, true, - "number of samplings must be positive"); - RequireParamValue("percentage", [](double x) { + RequireParamValue(params, "samplings", [](int x) { return x > 0; }, + true, "number of samplings must be positive"); + RequireParamValue(params, "percentage", [](double x) { return x > 0.0 && x <= 1.0; }, true, "percentage to sample must be " "be greater than 0.0 and less than or equal to 1.0"); // Initialize the GMM if needed. (We didn't do this earlier, because // RequireParamValue() would leak the memory if the check failed.) - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) gmm = new GMM(size_t(gaussians), dataPoints.n_rows); - const int samplings = IO::GetParam("samplings"); - const double percentage = IO::GetParam("percentage"); + const int samplings = params.Get("samplings"); + const double percentage = params.Get("percentage"); typedef KMeans KMeansType; @@ -245,14 +254,14 @@ static void mlpackMain() dgmm.Weights() = gmm->Weights(); // Compute the parameters of the model using the EM algorithm. - Timer::Start("em"); + timers.Start(("em"); EMFit em(maxIterations, tolerance, k); - likelihood = dgmm.Train(dataPoints, IO::GetParam("trials"), false, + likelihood = dgmm.Train(dataPoints, params.Get("trials"), false, em); - Timer::Stop("em"); + timers.Stop("em"); // Convert DiagonalGMMs into GMMs. for (size_t i = 0; i < size_t(gaussians); ++i) @@ -266,26 +275,26 @@ static void mlpackMain() else if (forcePositive) { // Compute the parameters of the model using the EM algorithm. - Timer::Start("em"); + timers.Start(("em"); EMFit em(maxIterations, tolerance, k); - likelihood = gmm->Train(dataPoints, IO::GetParam("trials"), false, + likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); - Timer::Stop("em"); + timers.Stop("em"); } else { // Compute the parameters of the model using the EM algorithm. - Timer::Start("em"); + timers.Start(("em"); EMFit em(maxIterations, tolerance, k); - likelihood = gmm->Train(dataPoints, IO::GetParam("trials"), false, + likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); - Timer::Stop("em"); + timers.Stop("em"); } } else { // Initialize the GMM if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) gmm = new GMM(size_t(gaussians), dataPoints.n_rows); // Depending on the value of forcePositive and diagonalCovariance, we have @@ -303,14 +312,14 @@ static void mlpackMain() dgmm.Weights() = gmm->Weights(); // Compute the parameters of the model using the EM algorithm. - Timer::Start("em"); + timers.Start(("em"); EMFit, PositiveDefiniteConstraint, distribution::DiagonalGaussianDistribution> em(maxIterations, tolerance, KMeans<>(kmeansMaxIterations)); - likelihood = dgmm.Train(dataPoints, IO::GetParam("trials"), false, + likelihood = dgmm.Train(dataPoints, params.Get("trials"), false, em); - Timer::Stop("em"); + timers.Stop("em"); // Convert DiagonalGMMs into GMMs. for (size_t i = 0; i < size_t(gaussians); ++i) @@ -324,25 +333,25 @@ static void mlpackMain() else if (forcePositive) { // Compute the parameters of the model using the EM algorithm. - Timer::Start("em"); + timers.Start(("em"); EMFit<> em(maxIterations, tolerance, KMeans<>(kmeansMaxIterations)); - likelihood = gmm->Train(dataPoints, IO::GetParam("trials"), false, + likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); - Timer::Stop("em"); + timers.Stop("em"); } else { // Compute the parameters of the model using the EM algorithm. - Timer::Start("em"); + timers.Start(("em"); KMeans<> k(kmeansMaxIterations); EMFit, NoConstraint> em(maxIterations, tolerance, k); - likelihood = gmm->Train(dataPoints, IO::GetParam("trials"), false, + likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); - Timer::Stop("em"); + timers.Stop("em"); } } Log::Info << "Log-likelihood of estimate: " << likelihood << "." << endl; - IO::GetParam("output_model") = gmm; + params.Get("output_model") = gmm; } diff --git a/src/mlpack/methods/hmm/hmm_generate_main.cpp b/src/mlpack/methods/hmm/hmm_generate_main.cpp index 579524e36c..8aba1b0cf7 100644 --- a/src/mlpack/methods/hmm/hmm_generate_main.cpp +++ b/src/mlpack/methods/hmm/hmm_generate_main.cpp @@ -13,6 +13,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME hmm_generate + #include #include "hmm.hpp" @@ -31,7 +37,7 @@ using namespace arma; using namespace std; // Program Name. -BINDING_NAME("Hidden Markov Model (HMM) Sequence Generator"); +BINDING_USER_NAME("Hidden Markov Model (HMM) Sequence Generator"); // Short description. BINDING_SHORT_DESC( @@ -90,14 +96,14 @@ struct Generate mat observations; Row sequence; - RequireParamValue("start_state", [](int x) { return x >= 0; }, true, - "Invalid start state"); - RequireParamValue("length", [](int x) { return x >= 0; }, true, + RequireParamValue(params, "start_state", [](int x) { return x >= 0; }, + true, "Invalid start state"); + RequireParamValue(params, "length", [](int x) { return x >= 0; }, true, "Length must be >= 0"); // Load the parameters. - const size_t startState = (size_t) IO::GetParam("start_state"); - const size_t length = (size_t) IO::GetParam("length"); + const size_t startState = (size_t) params.Get("start_state"); + const size_t length = (size_t) params.Get("length"); Log::Info << "Generating sequence of length " << length << "..." << endl; if (startState >= hmm.Transition().n_rows) @@ -110,28 +116,28 @@ struct Generate hmm.Generate(length, observations, sequence, startState); // Now save the output. - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(observations); + if (params.Has("output")) + params.Get("output") = std::move(observations); // Do we want to save the hidden sequence? - if (IO::HasParam("state")) - IO::GetParam>("state") = std::move(sequence); + if (params.Has("state")) + params.Get>("state") = std::move(sequence); } }; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - RequireAtLeastOnePassed({ "output", "state" }, false, "no output will be " - "saved"); + RequireAtLeastOnePassed(params, { "output", "state" }, false, + "no output will be saved"); // Set random seed. - if (IO::GetParam("seed") != 0) - RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + RandomSeed((size_t) params.Get("seed")); else RandomSeed((size_t) time(NULL)); // Load model, and perform the generation. HMMModel* hmm; - hmm = std::move(IO::GetParam("model")); + hmm = std::move(params.Get("model")); hmm->PerformAction(NULL); // No extra data required. } diff --git a/src/mlpack/methods/hmm/hmm_loglik_main.cpp b/src/mlpack/methods/hmm/hmm_loglik_main.cpp index ed5b587abe..00788e1a15 100644 --- a/src/mlpack/methods/hmm/hmm_loglik_main.cpp +++ b/src/mlpack/methods/hmm/hmm_loglik_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME hmm_loglik + #include #include "hmm.hpp" @@ -28,7 +34,7 @@ using namespace arma; using namespace std; // Program Name. -BINDING_NAME("Hidden Markov Model (HMM) Sequence Log-Likelihood"); +BINDING_USER_NAME("Hidden Markov Model (HMM) Sequence Log-Likelihood"); // Short description. BINDING_SHORT_DESC( @@ -75,7 +81,7 @@ struct Loglik static void Apply(HMMType& hmm, void* /* extraInfo */) { // Load the data sequence. - mat dataSeq = std::move(IO::GetParam("input")); + mat dataSeq = std::move(params.Get("input")); // Detect if we need to transpose the data, in the case where the input data // has one dimension. @@ -95,12 +101,12 @@ struct Loglik const double loglik = hmm.LogLikelihood(dataSeq); - IO::GetParam("log_likelihood") = loglik; + params.Get("log_likelihood") = loglik; } }; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Load model, and calculate the log-likelihood of the sequence. - IO::GetParam("input_model")->PerformAction((void*) NULL); + params.Get("input_model")->PerformAction((void*) NULL); } diff --git a/src/mlpack/methods/hmm/hmm_train_main.cpp b/src/mlpack/methods/hmm/hmm_train_main.cpp index 62ca02b069..198047524d 100644 --- a/src/mlpack/methods/hmm/hmm_train_main.cpp +++ b/src/mlpack/methods/hmm/hmm_train_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME hmm_train + #include #include "hmm.hpp" @@ -29,7 +35,7 @@ using namespace arma; using namespace std; // Program Name. -BINDING_NAME("Hidden Markov Model (HMM) Training"); +BINDING_USER_NAME("Hidden Markov Model (HMM) Training"); // Short description. BINDING_SHORT_DESC( @@ -100,8 +106,8 @@ struct Init template static void Apply(HMMType& hmm, vector* trainSeq) { - const size_t states = IO::GetParam("states"); - const double tolerance = IO::GetParam("tolerance"); + const size_t states = params.Get("states"); + const double tolerance = params.Get("tolerance"); // Create the initialized-to-zero model. Create(hmm, *trainSeq, states, tolerance); @@ -166,7 +172,7 @@ struct Init { // Find dimension of the data. const size_t dimensionality = trainSeq[0].n_rows; - const int gaussians = IO::GetParam("gaussians"); + const int gaussians = params.Get("gaussians"); if (gaussians == 0) { @@ -185,7 +191,7 @@ struct Init tolerance); // Issue a warning if the user didn't give labels. - if (!IO::HasParam("labels_file")) + if (!params.Has("labels_file")) { Log::Warn << "Unlabeled training of GMM HMMs is almost certainly not " << "going to produce good results!" << endl; @@ -200,7 +206,7 @@ struct Init { // Find dimension of the data. const size_t dimensionality = trainSeq[0].n_rows; - const int gaussians = IO::GetParam("gaussians"); + const int gaussians = params.Get("gaussians"); if (gaussians == 0) { @@ -219,7 +225,7 @@ struct Init dimensionality), tolerance); // Issue a warning if the user didn't give labels. - if (!IO::HasParam("labels_file")) + if (!params.Has("labels_file")) { Log::Warn << "Unlabeled training of Diagonal GMM HMMs is almost " << "certainly not going to produce good results!" << endl; @@ -259,7 +265,7 @@ struct Init e[i].Weights() /= arma::accu(e[i].Weights()); // Random means and covariances. - for (int g = 0; g < IO::GetParam("gaussians"); ++g) + for (int g = 0; g < params.Get("gaussians"); ++g) { const size_t dimensionality = e[i].Component(g).Mean().n_rows; e[i].Component(g).Mean().randu(); @@ -282,7 +288,7 @@ struct Init e[i].Weights() /= arma::accu(e[i].Weights()); // Random means and covariances. - for (int g = 0; g < IO::GetParam("gaussians"); ++g) + for (int g = 0; g < params.Get("gaussians"); ++g) { const size_t dimensionality = e[i].Component(g).Mean().n_rows; e[i].Component(g).Mean().randu(); @@ -302,14 +308,14 @@ struct Train template static void Apply(HMMType& hmm, vector* trainSeqPtr) { - const bool batch = IO::HasParam("batch"); - const double tolerance = IO::GetParam("tolerance"); + const bool batch = params.Has("batch"); + const double tolerance = params.Get("tolerance"); // Do we need to replace the tolerance? - if (IO::HasParam("tolerance")) + if (params.Has("tolerance")) hmm.Tolerance() = tolerance; - const string labelsFile = IO::GetParam("labels_file"); + const string labelsFile = params.Get("labels_file"); // Verify that the dimensionality of our observations is the same as the // dimensionality of our HMM's emissions. @@ -326,7 +332,7 @@ struct Train } vector> labelSeq; // May be empty. - if (IO::HasParam("labels_file")) + if (params.Has("labels_file")) { // Do we have multiple label files to load? char lineBuf[1024]; @@ -421,47 +427,47 @@ struct Train } }; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Set random seed. - if (IO::GetParam("seed") != 0) - RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + RandomSeed((size_t) params.Get("seed")); else RandomSeed((size_t) time(NULL)); // Validate parameters. - const string inputFile = IO::GetParam("input_file"); - const string type = IO::GetParam("type"); - const bool batch = IO::HasParam("batch"); - const double tolerance = IO::GetParam("tolerance"); + const string inputFile = params.Get("input_file"); + const string type = params.Get("type"); + const bool batch = params.Has("batch"); + const double tolerance = params.Get("tolerance"); // If no model is specified, make sure we are training with valid parameters. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) { // Validate number of states. - RequireAtLeastOnePassed({ "states" }, true); - RequireAtLeastOnePassed({ "type" }, true); - RequireParamValue("states", [](int x) { return x > 0; }, true, + RequireAtLeastOnePassed(params, { "states" }, true); + RequireAtLeastOnePassed(params, { "type" }, true); + RequireParamValue(params, "states", [](int x) { return x > 0; }, true, "number of states must be positive"); } - if (IO::HasParam("input_model") && IO::HasParam("tolerance")) + if (params.Has("input_model") && params.Has("tolerance")) { Log::Info << "Tolerance of existing model in '" - << IO::GetPrintableParam("input_model") << "' will be " + << params.GetPrintable("input_model") << "' will be " << "replaced with specified tolerance of " << tolerance << "." << endl; } - ReportIgnoredParam({{ "input_model", true }}, "type"); + ReportIgnoredParam(params, {{ "input_model", true }}, "type"); - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) { - RequireParamInSet("type", { "discrete", "gaussian", "gmm", + RequireParamInSet(params, "type", { "discrete", "gaussian", "gmm", "diag_gmm" }, true, "unknown HMM type"); } - RequireParamValue("tolerance", [](double x) { return x >= 0; }, true, - "tolerance must be non-negative"); + RequireParamValue(params, "tolerance", + [](double x) { return x >= 0; }, true, "tolerance must be non-negative"); // Load the input data. vector trainSeq; @@ -523,9 +529,9 @@ static void mlpackMain() // If we have a model file, we can autodetect the type. HMMModel* hmm; - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { - hmm = IO::GetParam("input_model"); + hmm = params.Get("input_model"); hmm->PerformAction>(&trainSeq); } @@ -548,5 +554,5 @@ static void mlpackMain() } // If necessary, save the output. - IO::GetParam("output_model") = hmm; + params.Get("output_model") = hmm; } diff --git a/src/mlpack/methods/hmm/hmm_viterbi_main.cpp b/src/mlpack/methods/hmm/hmm_viterbi_main.cpp index ccc9aaa4fd..affb5795b9 100644 --- a/src/mlpack/methods/hmm/hmm_viterbi_main.cpp +++ b/src/mlpack/methods/hmm/hmm_viterbi_main.cpp @@ -12,6 +12,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME hmm_viterbi + #include #include "hmm.hpp" @@ -29,7 +35,7 @@ using namespace arma; using namespace std; // Program Name. -BINDING_NAME("Hidden Markov Model (HMM) Viterbi State Prediction"); +BINDING_USER_NAME("Hidden Markov Model (HMM) Viterbi State Prediction"); // Short description. BINDING_SHORT_DESC( @@ -78,7 +84,7 @@ struct Viterbi static void Apply(HMMType& hmm, void* /* extraInfo */) { // Load observations. - mat dataSeq = std::move(IO::GetParam("input")); + mat dataSeq = std::move(params.Get("input")); // See if transposing the data could make it the right dimensionality. if ((dataSeq.n_cols == 1) && (hmm.Emission()[0].Dimensionality() == 1)) @@ -100,13 +106,14 @@ struct Viterbi hmm.Predict(dataSeq, sequence); // Save output. - IO::GetParam>("output") = std::move(sequence); + params.Get>("output") = std::move(sequence); } }; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - RequireAtLeastOnePassed({ "output" }, false, "no results will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no results will be saved"); - IO::GetParam("input_model")->PerformAction((void*) NULL); + params.Get("input_model")->PerformAction((void*) NULL); } diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp index 3a02d4c02b..b678884f25 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME hoeffding_tree + #include #include @@ -26,7 +32,7 @@ using namespace mlpack::data; using namespace mlpack::util; // Program Name. -BINDING_NAME("Hoeffding trees"); +BINDING_USER_NAME("Hoeffding trees"); // Short description. BINDING_SHORT_DESC( @@ -138,75 +144,75 @@ static void mlpackMain() { // Check input parameters for validity. const string numericSplitStrategy = - IO::GetParam("numeric_split_strategy"); + params.Get("numeric_split_strategy"); - RequireAtLeastOnePassed({ "training", "input_model" }, true); + RequireAtLeastOnePassed(params, { "training", "input_model" }, true); - RequireAtLeastOnePassed({ "output_model", "predictions", "probabilities", - "test_labels" }, false, "no output will be given"); + RequireAtLeastOnePassed(params, { "output_model", "predictions", + "probabilities", "test_labels" }, false, "no output will be given"); - ReportIgnoredParam({{ "test", false }}, "probabilities"); - ReportIgnoredParam({{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); - ReportIgnoredParam({{ "training", false }}, "batch_mode"); - ReportIgnoredParam({{ "training", false }}, "passes"); + ReportIgnoredParam(params, {{ "training", false }}, "batch_mode"); + ReportIgnoredParam(params, {{ "training", false }}, "passes"); - if (IO::HasParam("test")) + if (params.Has("test")) { - RequireAtLeastOnePassed({ "predictions", "probabilities", "test_labels" }, - false, "no output will be given"); + RequireAtLeastOnePassed(params, { "predictions", "probabilities", + "test_labels" }, false, "no output will be given"); } - RequireParamInSet("numeric_split_strategy", { "domingos", "binary" }, - true, "unrecognized numeric split strategy"); + RequireParamInSet(params, "numeric_split_strategy", { "domingos", + "binary" }, true, "unrecognized numeric split strategy"); // Do we need to load a model or do we already have one? HoeffdingTreeModel* model; DatasetInfo datasetInfo; arma::mat trainingSet; arma::Row labels; - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { - model = IO::GetParam("input_model"); + model = params.Get("input_model"); } else { // Initialize a model. - if (!IO::HasParam("info_gain") && (numericSplitStrategy == "domingos")) + if (!params.Has("info_gain") && (numericSplitStrategy == "domingos")) model = new HoeffdingTreeModel(HoeffdingTreeModel::GINI_HOEFFDING); - else if (!IO::HasParam("info_gain") && (numericSplitStrategy == "binary")) + else if (!params.Has("info_gain") && (numericSplitStrategy == "binary")) model = new HoeffdingTreeModel(HoeffdingTreeModel::GINI_BINARY); - else if (IO::HasParam("info_gain") && (numericSplitStrategy == "domingos")) + else if (params.Has("info_gain") && (numericSplitStrategy == "domingos")) model = new HoeffdingTreeModel(HoeffdingTreeModel::INFO_HOEFFDING); else model = new HoeffdingTreeModel(HoeffdingTreeModel::INFO_BINARY); } // Now, do we need to train? - if (IO::HasParam("training")) + if (params.Has("training")) { // Load necessary parameters for training. - const double confidence = IO::GetParam("confidence"); - const size_t maxSamples = (size_t) IO::GetParam("max_samples"); - const size_t minSamples = (size_t) IO::GetParam("min_samples"); - bool batchTraining = IO::HasParam("batch_mode"); - const size_t bins = (size_t) IO::GetParam("bins"); + const double confidence = params.Get("confidence"); + const size_t maxSamples = (size_t) params.Get("max_samples"); + const size_t minSamples = (size_t) params.Get("min_samples"); + bool batchTraining = params.Has("batch_mode"); + const size_t bins = (size_t) params.Get("bins"); const size_t observationsBeforeBinning = (size_t) - IO::GetParam("observations_before_binning"); - size_t passes = (size_t) IO::GetParam("passes"); + params.Get("observations_before_binning"); + size_t passes = (size_t) params.Get("passes"); if (passes > 1) batchTraining = false; // We already warned about this earlier. // We need to train the model. First, load the data. - datasetInfo = std::move(std::get<0>(IO::GetParam("training"))); - trainingSet = std::move(std::get<1>(IO::GetParam("training"))); + datasetInfo = std::move(std::get<0>(params.Get("training"))); + trainingSet = std::move(std::get<1>(params.Get("training"))); for (size_t i = 0; i < trainingSet.n_rows; ++i) Log::Info << datasetInfo.NumMappings(i) << " mappings in dimension " << i << "." << endl; - if (IO::HasParam("labels")) + if (params.Has("labels")) { - labels = std::move(IO::GetParam>("labels")); + labels = std::move(params.Get>("labels")); } else { @@ -222,10 +228,10 @@ static void mlpackMain() // appropriate type of instantiated numeric split type. This is a little // bit ugly. Maybe there is a nicer way to get this numeric split // information to the trees, but this is ok for now. - Timer::Start("tree_training"); + timers.Start(("tree_training"); // Do we need to initialize a model? - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) { // Build the model. model->BuildModel(trainingSet, datasetInfo, labels, @@ -239,7 +245,7 @@ static void mlpackMain() { // We only need to do batch training if we've not already called // BuildModel. - if (IO::HasParam("input_model")) + if (params.Has("input_model")) model->Train(trainingSet, labels, true); } else @@ -248,11 +254,11 @@ static void mlpackMain() model->Train(trainingSet, labels, false); } - Timer::Stop("tree_training"); + timers.Stop("tree_training"); } // Do we need to evaluate the training set error? - if (IO::HasParam("training")) + if (params.Has("training")) { // Get training error. arma::Row predictions; @@ -272,24 +278,24 @@ static void mlpackMain() Log::Info << model->NumNodes() << " nodes in the tree." << endl; // The tree is trained or loaded. Now do any testing if we need. - if (IO::HasParam("test")) + if (params.Has("test")) { // Before loading, pre-set the dataset info by getting the raw parameter // (that doesn't call data::Load()). - std::get<0>(IO::GetRawParam("test")) = datasetInfo; - arma::mat testSet = std::get<1>(IO::GetParam("test")); + std::get<0>(params.GetRaw("test")) = datasetInfo; + arma::mat testSet = std::get<1>(params.Get("test")); arma::Row predictions; arma::rowvec probabilities; - Timer::Start("tree_testing"); + timers.Start(("tree_testing"); model->Classify(testSet, predictions, probabilities); - Timer::Stop("tree_testing"); + timers.Stop("tree_testing"); - if (IO::HasParam("test_labels")) + if (params.Has("test_labels")) { arma::Row testLabels = - std::move(IO::GetParam>("test_labels")); + std::move(params.Get>("test_labels")); size_t correct = 0; for (size_t i = 0; i < testLabels.n_elem; ++i) @@ -302,10 +308,10 @@ static void mlpackMain() 100.0 << ")." << endl; } - IO::GetParam>("predictions") = std::move(predictions); - IO::GetParam("probabilities") = std::move(probabilities); + params.Get>("predictions") = std::move(predictions); + params.Get("probabilities") = std::move(probabilities); } // Check the accuracy on the training set. - IO::GetParam("output_model") = model; + params.Get("output_model") = model; } diff --git a/src/mlpack/methods/kde/kde_main.cpp b/src/mlpack/methods/kde/kde_main.cpp index 3a9bd919f8..b2dad09aef 100644 --- a/src/mlpack/methods/kde/kde_main.cpp +++ b/src/mlpack/methods/kde/kde_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME kde + #include #include @@ -23,7 +29,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Kernel Density Estimation"); +BINDING_USER_NAME("Kernel Density Estimation"); // Short description. BINDING_SHORT_DESC( @@ -192,69 +198,72 @@ PARAM_COL_OUT("predictions", "Vector to store density predictions.", // Maybe, in the future, it could be interesting to implement different metrics. -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Get some parameters. - const double bandwidth = IO::GetParam("bandwidth"); - const std::string kernelStr = IO::GetParam("kernel"); - const std::string treeStr = IO::GetParam("tree"); - const std::string modeStr = IO::GetParam("algorithm"); - const double relError = IO::GetParam("rel_error"); - const double absError = IO::GetParam("abs_error"); - const bool monteCarlo = IO::GetParam("monte_carlo"); - const double mcProb = IO::GetParam("mc_probability"); - const int initialSampleSize = IO::GetParam("initial_sample_size"); - const double mcEntryCoef = IO::GetParam("mc_entry_coef"); - const double mcBreakCoef = IO::GetParam("mc_break_coef"); + const double bandwidth = params.Get("bandwidth"); + const std::string kernelStr = params.Get("kernel"); + const std::string treeStr = params.Get("tree"); + const std::string modeStr = params.Get("algorithm"); + const double relError = params.Get("rel_error"); + const double absError = params.Get("abs_error"); + const bool monteCarlo = params.Get("monte_carlo"); + const double mcProb = params.Get("mc_probability"); + const int initialSampleSize = params.Get("initial_sample_size"); + const double mcEntryCoef = params.Get("mc_entry_coef"); + const double mcBreakCoef = params.Get("mc_break_coef"); // Initialize results vector. arma::vec estimations; // You can only specify reference data or a pre-trained model. - RequireOnlyOnePassed({ "reference", "input_model" }, true); - ReportIgnoredParam({{ "input_model", true }}, "tree"); - ReportIgnoredParam({{ "input_model", true }}, "kernel"); + RequireOnlyOnePassed(params, { "reference", "input_model" }, true); + ReportIgnoredParam(params, {{ "input_model", true }}, "tree"); + ReportIgnoredParam(params, {{ "input_model", true }}, "kernel"); // Monte Carlo parameters only make sense if it is activated. - ReportIgnoredParam({{ "monte_carlo", false }}, "mc_probability"); - ReportIgnoredParam({{ "monte_carlo", false }}, "initial_sample_size"); - ReportIgnoredParam({{ "monte_carlo", false }}, "mc_entry_coef"); - ReportIgnoredParam({{ "monte_carlo", false }}, "mc_break_coef"); + ReportIgnoredParam(params, {{ "monte_carlo", false }}, "mc_probability"); + ReportIgnoredParam(params, {{ "monte_carlo", false }}, "initial_sample_size"); + ReportIgnoredParam(params, {{ "monte_carlo", false }}, "mc_entry_coef"); + ReportIgnoredParam(params, {{ "monte_carlo", false }}, "mc_break_coef"); if (monteCarlo && kernelStr != "gaussian") { - ReportIgnoredParam("monte_carlo", + ReportIgnoredParam(params, "monte_carlo", "Monte Carlo only works with Gaussian kernel"); } // Requirements for parameter values. - RequireParamInSet("kernel", { "gaussian", "epanechnikov", + RequireParamInSet(params, "kernel", { "gaussian", "epanechnikov", "laplacian", "spherical", "triangular" }, true, "unknown kernel type"); - RequireParamInSet("tree", { "kd-tree", "ball-tree", "cover-tree", - "octree", "r-tree"}, true, "unknown tree type"); - RequireParamInSet("algorithm", { "dual-tree", "single-tree"}, + RequireParamInSet(params, "tree", { "kd-tree", "ball-tree", + "cover-tree", "octree", "r-tree"}, true, "unknown tree type"); + RequireParamInSet(params, "algorithm", { "dual-tree", "single-tree"}, true, "unknown algorithm"); - RequireParamValue("rel_error", [](double x){return x >= 0 && x <= 1;}, + RequireParamValue(params, "rel_error", + [](double x){ return x >= 0 && x <= 1; }, true, "relative error must be between 0 and 1"); - RequireParamValue("abs_error", [](double x){return x >= 0;}, + RequireParamValue(params, "abs_error", + [](double x){ return x >= 0; }, true, "absolute error must be equal to or greater than 0"); - RequireParamValue("mc_probability", - [](double x){return x >= 0 && x < 1;}, true, + RequireParamValue(params, "mc_probability", + [](double x){ return x >= 0 && x < 1; }, true, "Monte Carlo probability must be greater than or equal to 0 or less " "than 1"); - RequireParamValue("initial_sample_size", [](int x){return x > 0;}, + RequireParamValue(params, "initial_sample_size", + [](int x){ return x > 0; }, true, "initial sample size must be greater than 0"); - RequireParamValue("mc_entry_coef", [](double x){return x >= 1;}, + RequireParamValue(params, "mc_entry_coef", [](double x){return x >= 1;}, true, "Monte Carlo entry coefficient must be greater than or equal to 1"); - RequireParamValue("mc_break_coef", - [](double x){return x > 0 && x <= 1;}, true, + RequireParamValue(params, "mc_break_coef", + [](double x){ return x > 0 && x <= 1; }, true, "Monte Carlo break coefficient must be greater than 0 and less than " "or equal to 1"); KDEModel* kde; - if (IO::HasParam("reference")) + if (params.Has("reference")) { - arma::mat reference = std::move(IO::GetParam("reference")); + arma::mat reference = std::move(params.Get("reference")); kde = new KDEModel(); @@ -294,7 +303,7 @@ static void mlpackMain() else { // Load model. - kde = IO::GetParam("input_model"); + kde = params.Get("input_model"); } // Set model parameters. @@ -308,9 +317,9 @@ static void mlpackMain() kde->MCBreakCoefficient(mcBreakCoef); // Evaluation. - if (IO::HasParam("query")) + if (params.Has("query")) { - arma::mat query = std::move(IO::GetParam("query")); + arma::mat query = std::move(params.Get("query")); kde->Evaluate(std::move(query), estimations); } else @@ -319,9 +328,9 @@ static void mlpackMain() } // Output predictions if needed. - if (IO::HasParam("predictions")) - IO::GetParam("predictions") = std::move(estimations); + if (params.Has("predictions")) + params.Get("predictions") = std::move(estimations); // Save model. - IO::GetParam("output_model") = kde; + params.Get("output_model") = kde; } diff --git a/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp b/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp index a70c70ef08..574a7109ac 100644 --- a/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp +++ b/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME kernel_pca + #include #include #include @@ -41,7 +47,7 @@ using namespace std; using namespace arma; // Program Name. -BINDING_NAME("Kernel Principal Components Analysis"); +BINDING_USER_NAME("Kernel Principal Components Analysis"); // Short description. BINDING_SHORT_DESC( @@ -184,18 +190,19 @@ void RunKPCA(arma::mat& dataset, } } -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - RequireAtLeastOnePassed({ "output" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no output will be saved"); // Load input dataset. - mat dataset = std::move(IO::GetParam("input")); + mat dataset = std::move(params.Get("input")); // Get the new dimensionality, if it is necessary. size_t newDim = dataset.n_rows; - if (IO::GetParam("new_dimensionality") != 0) + if (params.Get("new_dimensionality") != 0) { - newDim = IO::GetParam("new_dimensionality"); + newDim = params.Get("new_dimensionality"); if (newDim > dataset.n_rows) { @@ -206,14 +213,14 @@ static void mlpackMain() } // Get the kernel type and make sure it is valid. - RequireParamInSet("kernel", { "linear", "gaussian", "polynomial", - "hyptan", "laplacian", "epanechnikov", "cosine" }, true, + RequireParamInSet(params, "kernel", { "linear", "gaussian", + "polynomial", "hyptan", "laplacian", "epanechnikov", "cosine" }, true, "unknown kernel type"); - const string kernelType = IO::GetParam("kernel"); + const string kernelType = params.Get("kernel"); - const bool centerTransformedData = IO::HasParam("center"); - const bool nystroem = IO::HasParam("nystroem_method"); - const string sampling = IO::GetParam("sampling"); + const bool centerTransformedData = params.Has("center"); + const bool nystroem = params.Has("nystroem_method"); + const string sampling = params.Get("sampling"); if (kernelType == "linear") { @@ -223,7 +230,7 @@ static void mlpackMain() } else if (kernelType == "gaussian") { - const double bandwidth = IO::GetParam("bandwidth"); + const double bandwidth = params.Get("bandwidth"); GaussianKernel kernel(bandwidth); RunKPCA(dataset, centerTransformedData, nystroem, newDim, @@ -231,8 +238,8 @@ static void mlpackMain() } else if (kernelType == "polynomial") { - const double degree = IO::GetParam("degree"); - const double offset = IO::GetParam("offset"); + const double degree = params.Get("degree"); + const double offset = params.Get("offset"); PolynomialKernel kernel(degree, offset); RunKPCA(dataset, centerTransformedData, nystroem, @@ -240,8 +247,8 @@ static void mlpackMain() } else if (kernelType == "hyptan") { - const double scale = IO::GetParam("kernel_scale"); - const double offset = IO::GetParam("offset"); + const double scale = params.Get("kernel_scale"); + const double offset = params.Get("offset"); HyperbolicTangentKernel kernel(scale, offset); RunKPCA(dataset, centerTransformedData, nystroem, @@ -249,7 +256,7 @@ static void mlpackMain() } else if (kernelType == "laplacian") { - const double bandwidth = IO::GetParam("bandwidth"); + const double bandwidth = params.Get("bandwidth"); LaplacianKernel kernel(bandwidth); RunKPCA(dataset, centerTransformedData, nystroem, newDim, @@ -257,7 +264,7 @@ static void mlpackMain() } else if (kernelType == "epanechnikov") { - const double bandwidth = IO::GetParam("bandwidth"); + const double bandwidth = params.Get("bandwidth"); EpanechnikovKernel kernel(bandwidth); RunKPCA(dataset, centerTransformedData, nystroem, @@ -271,6 +278,6 @@ static void mlpackMain() } // Save the output dataset. - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(dataset); + if (params.Has("output")) + params.Get("output") = std::move(dataset); } diff --git a/src/mlpack/methods/kmeans/kmeans_main.cpp b/src/mlpack/methods/kmeans/kmeans_main.cpp index 4707c05b7e..126df7b382 100644 --- a/src/mlpack/methods/kmeans/kmeans_main.cpp +++ b/src/mlpack/methods/kmeans/kmeans_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME kmeans + #include #include "kmeans.hpp" @@ -29,7 +35,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("K-Means Clustering"); +BINDING_USER_NAME("K-Means Clustering"); // Short description. BINDING_SHORT_DESC( @@ -175,33 +181,33 @@ template class LloydStepType> void RunKMeans(const InitialPartitionPolicy& ipp); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Initialize random seed. - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); - RequireOnlyOnePassed({ "refined_start", "kmeans_plus_plus" }, true, + RequireOnlyOnePassed(params, { "refined_start", "kmeans_plus_plus" }, true, "Only one initialization strategy can be specified!", true); // Now, start building the KMeans type that we'll be using. Start with the // initial partition policy. The call to FindEmptyClusterPolicy<> results in // a call to RunKMeans<> and the algorithm is completed. - if (IO::HasParam("refined_start")) + if (params.Has("refined_start")) { - RequireParamValue("samplings", [](int x) { return x > 0; }, true, - "number of samplings must be positive"); - const int samplings = IO::GetParam("samplings"); - RequireParamValue("percentage", + RequireParamValue(params, "samplings", [](int x) { return x > 0; }, + true, "number of samplings must be positive"); + const int samplings = params.Get("samplings"); + RequireParamValue(params, "percentage", [](double x) { return x > 0.0 && x <= 1.0; }, true, "percentage to " "sample must be greater than 0.0 and less than or equal to 1.0"); - const double percentage = IO::GetParam("percentage"); + const double percentage = params.Get("percentage"); FindEmptyClusterPolicy(RefinedStart(samplings, percentage)); } - else if (IO::HasParam("kmeans_plus_plus")) + else if (params.Has("kmeans_plus_plus")) { FindEmptyClusterPolicy( KMeansPlusPlusInitialization()); @@ -217,14 +223,14 @@ static void mlpackMain() template void FindEmptyClusterPolicy(const InitialPartitionPolicy& ipp) { - if (IO::HasParam("allow_empty_clusters") || - IO::HasParam("kill_empty_clusters")) - RequireOnlyOnePassed({ "allow_empty_clusters", "kill_empty_clusters" }, - true); + if (params.Has("allow_empty_clusters") || + params.Has("kill_empty_clusters")) + RequireOnlyOnePassed(params, { "allow_empty_clusters", + "kill_empty_clusters" }, true); - if (IO::HasParam("allow_empty_clusters")) + if (params.Has("allow_empty_clusters")) FindLloydStepType(ipp); - else if (IO::HasParam("kill_empty_clusters")) + else if (params.Has("kill_empty_clusters")) FindLloydStepType(ipp); else FindLloydStepType(ipp); @@ -235,11 +241,11 @@ void FindEmptyClusterPolicy(const InitialPartitionPolicy& ipp) template void FindLloydStepType(const InitialPartitionPolicy& ipp) { - RequireParamInSet("algorithm", { "elkan", "hamerly", "pelleg-moore", - "dualtree", "dualtree-covertree", "naive" }, true, "unknown k-means " - "algorithm"); + RequireParamInSet(params, "algorithm", { "elkan", "hamerly", + "pelleg-moore", "dualtree", "dualtree-covertree", "naive" }, true, + "unknown k-means algorithm"); - const string algorithm = IO::GetParam("algorithm"); + const string algorithm = params.Get("algorithm"); if (algorithm == "elkan") RunKMeans(ipp); else if (algorithm == "hamerly") @@ -264,18 +270,18 @@ template("clusters", [](int x) { return x > 0; }, true, - "number of clusters must be positive"); + RequireParamValue(params, "clusters", [](int x) { return x > 0; }, + true, "number of clusters must be positive"); } else { - ReportIgnoredParam({{ "initial_centroids", true }}, "clusters"); + ReportIgnoredParam(params, {{ "initial_centroids", true }}, "clusters"); } - int clusters = IO::GetParam("clusters"); - if (clusters == 0 && IO::HasParam("initial_centroids")) + int clusters = params.Get("clusters"); + if (clusters == 0 && params.Has("initial_centroids")) { Log::Info << "Detecting number of clusters automatically from input " << "centroids." << endl; @@ -283,45 +289,46 @@ void RunKMeans(const InitialPartitionPolicy& ipp) RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, "maximum iterations must be positive or 0 (for no limit)"); - const int maxIterations = IO::GetParam("max_iterations"); + const int maxIterations = params.Get("max_iterations"); // Make sure we have an output file if we're not doing the work in-place. - RequireOnlyOnePassed({ "in_place", "output", "centroid" }, false, + RequireOnlyOnePassed(params, { "in_place", "output", "centroid" }, false, "no results will be saved"); - arma::mat dataset = IO::GetParam("input"); // Load our dataset. + arma::mat dataset = params.Get("input"); // Load our dataset. arma::mat centroids; - const bool initialCentroidGuess = IO::HasParam("initial_centroids"); + const bool initialCentroidGuess = params.Has("initial_centroids"); // Load initial centroids if the user asked for it. if (initialCentroidGuess) { - centroids = std::move(IO::GetParam("initial_centroids")); + centroids = std::move(params.Get("initial_centroids")); if (clusters == 0) clusters = centroids.n_cols; - ReportIgnoredParam({{ "refined_start", true }}, "initial_centroids"); + ReportIgnoredParam(params, {{ "refined_start", true }}, + "initial_centroids"); - if (!IO::HasParam("refined_start")) + if (!params.Has("refined_start")) Log::Info << "Using initial centroid guesses." << endl; } - Timer::Start("clustering"); + timers.Start(("clustering"); KMeans kmeans(maxIterations, metric::EuclideanDistance(), ipp); - if (IO::HasParam("output") || IO::HasParam("in_place")) + if (params.Has("output") || params.Has("in_place")) { // We need to get the assignments. arma::Row assignments; kmeans.Cluster(dataset, clusters, assignments, centroids, false, initialCentroidGuess); - Timer::Stop("clustering"); + timers.Stop("clustering"); // Now figure out what to do with our results. - if (IO::HasParam("in_place")) + if (params.Has("in_place")) { // Add the column of assignments to the dataset; but we have to convert // them to type double first. @@ -332,16 +339,16 @@ void RunKMeans(const InitialPartitionPolicy& ipp) dataset.insert_rows(dataset.n_rows, converted); // Save the dataset. - IO::MakeInPlaceCopy("output", "input"); - IO::GetParam("output") = std::move(dataset); + params.MakeInPlaceCopy("output", "input"); + params.Get("output") = std::move(dataset); } else { - if (IO::HasParam("labels_only")) + if (params.Has("labels_only")) { // Save only the labels. TODO: figure out how to get this to output an // arma::Mat instead of an arma::mat. - IO::GetParam("output") = + params.Get("output") = arma::conv_to::from(assignments); } else @@ -354,7 +361,7 @@ void RunKMeans(const InitialPartitionPolicy& ipp) dataset.insert_rows(dataset.n_rows, converted); // Now save, in the different file. - IO::GetParam("output") = std::move(dataset); + params.Get("output") = std::move(dataset); } } } @@ -362,10 +369,10 @@ void RunKMeans(const InitialPartitionPolicy& ipp) { // Just save the centroids. kmeans.Cluster(dataset, clusters, centroids, initialCentroidGuess); - Timer::Stop("clustering"); + timers.Stop("clustering"); } // Should we write the centroids to a file? - if (IO::HasParam("centroid")) - IO::GetParam("centroid") = std::move(centroids); + if (params.Has("centroid")) + params.Get("centroid") = std::move(centroids); } diff --git a/src/mlpack/methods/lars/lars_main.cpp b/src/mlpack/methods/lars/lars_main.cpp index 202daf4af7..aa5308daed 100644 --- a/src/mlpack/methods/lars/lars_main.cpp +++ b/src/mlpack/methods/lars/lars_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME lars + #include #include "lars.hpp" @@ -22,7 +28,7 @@ using namespace mlpack::regression; using namespace mlpack::util; // Program Name. -BINDING_NAME("LARS"); +BINDING_USER_NAME("LARS"); // Short description. BINDING_SHORT_DESC( @@ -121,39 +127,39 @@ PARAM_DOUBLE_IN("lambda2", "Regularization parameter for l2-norm penalty.", "L", PARAM_FLAG("use_cholesky", "Use Cholesky decomposition during computation " "rather than explicitly computing the full Gram matrix.", "c"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - double lambda1 = IO::GetParam("lambda1"); - double lambda2 = IO::GetParam("lambda2"); - bool useCholesky = IO::HasParam("use_cholesky"); + double lambda1 = params.Get("lambda1"); + double lambda2 = params.Get("lambda2"); + bool useCholesky = params.Has("use_cholesky"); // Check parameters -- make sure everything given makes sense. - RequireOnlyOnePassed({ "input", "input_model" }, true); - if (IO::HasParam("input")) + RequireOnlyOnePassed(params, { "input", "input_model" }, true); + if (params.Has("input")) { - RequireOnlyOnePassed({ "responses" }, true, "if input data is specified, " - "responses must also be specified"); + RequireOnlyOnePassed(params, { "responses" }, true, "if input data is " + "specified, responses must also be specified"); } - ReportIgnoredParam({{ "input", false }}, "responses"); + ReportIgnoredParam(params, {{ "input", false }}, "responses"); - RequireAtLeastOnePassed({ "output_predictions", "output_model" }, false, - "no results will be saved"); - ReportIgnoredParam({{ "test", true }}, "output_predictions"); + RequireAtLeastOnePassed(params, { "output_predictions", "output_model" }, + false, "no results will be saved"); + ReportIgnoredParam(params, {{ "test", true }}, "output_predictions"); LARS* lars; - if (IO::HasParam("input")) + if (params.Has("input")) { // Initialize the object. lars = new LARS(useCholesky, lambda1, lambda2); // Load covariates. We can avoid LARS transposing our data by choosing to // not transpose this data (that's why we used PARAM_TMATRIX_IN). - mat matX = std::move(IO::GetParam("input")); + mat matX = std::move(params.Get("input")); // Load responses. The responses should be a one-dimensional vector, and it // seems more likely that these will be stored with one response per line // (one per row). So we should not transpose upon loading. - mat matY = std::move(IO::GetParam("responses")); + mat matY = std::move(params.Get("responses")); // Make sure y is oriented the right way. if (matY.n_cols == 1) @@ -171,15 +177,15 @@ static void mlpackMain() } else // We must have --input_model_file. { - lars = IO::GetParam("input_model"); + lars = params.Get("input_model"); } - if (IO::HasParam("test")) + if (params.Has("test")) { Log::Info << "Regressing on test points." << endl; // Load test points. - mat testPoints = std::move(IO::GetParam("test")); + mat testPoints = std::move(params.Get("test")); // Make sure the dimensionality is right. We haven't transposed, so, we // check n_cols not n_rows. @@ -192,8 +198,8 @@ static void mlpackMain() lars->Predict(testPoints.t(), predictions, false); // Save test predictions (one per line). - IO::GetParam("output_predictions") = predictions.t(); + params.Get("output_predictions") = predictions.t(); } - IO::GetParam("output_model") = lars; + params.Get("output_model") = lars; } diff --git a/src/mlpack/methods/linear_svm/linear_svm_main.cpp b/src/mlpack/methods/linear_svm/linear_svm_main.cpp index ce645e964b..465ba970a5 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_main.cpp +++ b/src/mlpack/methods/linear_svm/linear_svm_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME linear_svm + #include #include @@ -24,7 +30,7 @@ using namespace mlpack::svm; using namespace mlpack::util; // Program Name. -BINDING_NAME("Linear SVM is an L2-regularized support vector machine."); +BINDING_USER_NAME("Linear SVM is an L2-regularized support vector machine."); // Short description. BINDING_SHORT_DESC( @@ -169,63 +175,64 @@ PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " "matrix is where the class probabilities for the test set will be saved.", "p"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // Collect command-line options. - const double lambda = IO::GetParam("lambda"); - const double delta = IO::GetParam("delta"); - const string optimizerType = IO::GetParam("optimizer"); - const double tolerance = IO::GetParam("tolerance"); - const bool intercept = !IO::HasParam("no_intercept"); - const size_t epochs = (size_t) IO::GetParam("epochs"); - const size_t maxIterations = (size_t) IO::GetParam("max_iterations"); + const double lambda = params.Get("lambda"); + const double delta = params.Get("delta"); + const string optimizerType = params.Get("optimizer"); + const double tolerance = params.Get("tolerance"); + const bool intercept = !params.Has("no_intercept"); + const size_t epochs = (size_t) params.Get("epochs"); + const size_t maxIterations = (size_t) params.Get("max_iterations"); // One of training and input_model must be specified. - RequireAtLeastOnePassed({ "training", "input_model" }, true); + RequireAtLeastOnePassed(params, { "training", "input_model" }, true); // If no output file is given, the user should know that the model will not be // saved, but only if a model is being trained. - RequireAtLeastOnePassed({ "output_model", "predictions", "probabilities"}, - false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "predictions", + "probabilities" }, false, "no output will be saved"); - ReportIgnoredParam({{ "test", false }}, "predictions"); - ReportIgnoredParam({{ "test", false }}, "probabilities"); - ReportIgnoredParam({{ "test", false }}, "test_labels"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{ "test", false }}, "test_labels"); // Max Iterations needs to be positive. - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, true, "max_iterations must be non-negative"); // Tolerance needs to be positive. - RequireParamValue("tolerance", [](double x) { return x >= 0.0; }, + RequireParamValue(params, "tolerance", + [](double x) { return x >= 0.0; }, true, "tolerance must be non-negative"); // Optimizer has to be L-BFGS or parallel SGD. - RequireParamInSet("optimizer", { "lbfgs", "psgd" }, + RequireParamInSet(params, "optimizer", { "lbfgs", "psgd" }, true, "unknown optimizer"); // Epochs needs to be non-negative. - RequireParamValue("epochs", [](int x) { return x >= 0; }, true, + RequireParamValue(params, "epochs", [](int x) { return x >= 0; }, true, "maximum number of epochs must be non-negative"); if (optimizerType != "psgd") { - if (IO::HasParam("step_size")) + if (params.Has("step_size")) { Log::Warn << PRINT_PARAM_STRING("step_size") << " ignored because " << "optimizer type is not 'psgd'." << std::endl; } - if (IO::HasParam("shuffle")) + if (params.Has("shuffle")) { Log::Warn << PRINT_PARAM_STRING("shuffle") << " ignored because " << "optimizer type is not 'psgd'." << std::endl; } - if (IO::HasParam("epochs")) + if (params.Has("epochs")) { Log::Warn << PRINT_PARAM_STRING("epochs") << " ignored because " << "optimizer type is not 'psgd'." << std::endl; @@ -234,7 +241,7 @@ static void mlpackMain() if (optimizerType != "lbfgs") { - if (IO::HasParam("max_iterations")) + if (params.Has("max_iterations")) { Log::Warn << PRINT_PARAM_STRING("max_iterations") << " ignored because " << "optimizer type is not 'lbfgs'." << std::endl; @@ -242,24 +249,24 @@ static void mlpackMain() } // Step Size must be positive. - RequireParamValue("step_size", [](double x) { return x > 0.0; }, - true, "step size must be positive"); + RequireParamValue(params, "step_size", + [](double x) { return x > 0.0; }, true, "step size must be positive"); // Lambda must be positive. - RequireParamValue("lambda", [](double x) { return x >= 0.0; }, + RequireParamValue(params, "lambda", [](double x) { return x >= 0.0; }, true, "lambda must be non-negative"); // Number of Classes must be Non-Negative - RequireParamValue("num_classes", [](int x) { return x >= 0; }, + RequireParamValue(params, "num_classes", [](int x) { return x >= 0; }, true, "number of classes must be greater than or " "equal to 0 (equal to 0 in case of unspecified.)"); // Delta must be positive. - RequireParamValue("delta", [](double x) { return x >= 0.0; }, true, - "delta must be non-negative"); + RequireParamValue(params, "delta", [](double x) { return x >= 0.0; }, + true, "delta must be non-negative"); // Delta must be positive. - RequireParamValue("epochs", [](int x) { return x > 0; }, true, + RequireParamValue(params, "epochs", [](int x) { return x > 0; }, true, "epochs must be non-negative"); // These are the matrices we might use. @@ -271,20 +278,20 @@ static void mlpackMain() size_t numClasses; // Load data matrix. - if (IO::HasParam("training")) - trainingSet = std::move(IO::GetParam("training")); + if (params.Has("training")) + trainingSet = std::move(params.Get("training")); // Check if the labels are in a separate file. - if (IO::HasParam("training") && IO::HasParam("labels")) + if (params.Has("training") && params.Has("labels")) { - rawLabels = std::move(IO::GetParam>("labels")); + rawLabels = std::move(params.Get>("labels")); if (trainingSet.n_cols != rawLabels.n_cols) { Log::Fatal << "The labels must have the same number of points as the " << "training dataset." << endl; } } - else if (IO::HasParam("training")) + else if (params.Has("training")) { // Checking the size of training data if no labels are passed. if (trainingSet.n_rows < 2) @@ -301,9 +308,9 @@ static void mlpackMain() // Load the model, if necessary. LinearSVMModel* model; - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { - model = IO::GetParam("input_model"); + model = params.Get("input_model"); } else { @@ -311,11 +318,11 @@ static void mlpackMain() } // Now, do the training. - if (IO::HasParam("training")) + if (params.Has("training")) { data::NormalizeLabels(rawLabels, labels, model->mappings); - numClasses = IO::GetParam("num_classes") == 0 ? - model->mappings.n_elem : IO::GetParam("num_classes"); + numClasses = params.Get("num_classes") == 0 ? + model->mappings.n_elem : params.Get("num_classes"); model->svm.Lambda() = lambda; model->svm.Delta() = delta; model->svm.NumClasses() = numClasses; @@ -323,7 +330,7 @@ static void mlpackMain() if (numClasses <= 1) { - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; throw std::invalid_argument("Given input data has only 1 class!"); } @@ -341,8 +348,8 @@ static void mlpackMain() } else if (optimizerType == "psgd") { - const double stepSize = IO::GetParam("step_size"); - const bool shuffle = !IO::HasParam("shuffle"); + const double stepSize = params.Get("step_size"); + const bool shuffle = !params.Has("shuffle"); const size_t maxIt = epochs * trainingSet.n_cols; ens::ConstantStep decayPolicy(stepSize); @@ -365,16 +372,16 @@ static void mlpackMain() model->svm.Train(trainingSet, labels, numClasses, psgdOpt); } } - if (IO::HasParam("test")) + if (params.Has("test")) { // Cache the value of GetPrintableParam for the test matrix before we // std::move() it. std::ostringstream oss; - oss << IO::GetPrintableParam("test"); + oss << params.GetPrintable("test"); std::string testOutput = oss.str(); // Get the test dataset, and get predictions. - testSet = std::move(IO::GetParam("test")); + testSet = std::move(params.Get("test")); arma::Row predictions; size_t trainingDimensionality; @@ -388,7 +395,7 @@ static void mlpackMain() if (testSet.n_rows != trainingDimensionality) { // Clean memory if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; Log::Fatal << "Test data dimensionality (" << testSet.n_rows << ") must " << "be the same as the dimensionality of the training data (" @@ -396,30 +403,30 @@ static void mlpackMain() } // Save class probabilities, if desired. - if (IO::HasParam("probabilities")) + if (params.Has("probabilities")) { Log::Info << "Calculating class probabilities of points in " << testOutput << "." << endl; arma::mat probabilities; model->svm.Classify(testSet, probabilities); - IO::GetParam("probabilities") = std::move(probabilities); + params.Get("probabilities") = std::move(probabilities); } model->svm.Classify(testSet, predictedLabels); data::RevertLabels(predictedLabels, model->mappings, predictions); // Calculate accuracy, if desired. - if (IO::HasParam("test_labels")) + if (params.Has("test_labels")) { arma::Row testLabels; arma::Row testRawLabels = - std::move(IO::GetParam>("test_labels")); + std::move(params.Get>("test_labels")); data::NormalizeLabels(testRawLabels, testLabels, model->mappings); if (testSet.n_cols != testLabels.n_elem) { - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; Log::Fatal << "Test data given with " << PRINT_PARAM_STRING("test") << " has " << testSet.n_cols << " points, but labels in " @@ -427,8 +434,8 @@ static void mlpackMain() << testLabels.n_elem << " labels!" << endl; } - numClasses = IO::GetParam("num_classes") == 0 ? - model->mappings.n_elem : IO::GetParam("num_classes"); + numClasses = params.Get("num_classes") == 0 ? + model->mappings.n_elem : params.Get("num_classes"); arma::Col correctClassCounts; arma::Col labelSize; correctClassCounts.zeros(numClasses); @@ -460,13 +467,13 @@ static void mlpackMain() } // Save predictions, if desired. - if (IO::HasParam("predictions")) + if (params.Has("predictions")) { Log::Info << "Predicting classes of points in '" << testOutput << "'." << endl; - IO::GetParam>("predictions") = std::move(predictions); + params.Get>("predictions") = std::move(predictions); } } - IO::GetParam("output_model") = model; + params.Get("output_model") = model; } diff --git a/src/mlpack/methods/lmnn/lmnn_main.cpp b/src/mlpack/methods/lmnn/lmnn_main.cpp index 2aa49b6321..3fdc6b8620 100644 --- a/src/mlpack/methods/lmnn/lmnn_main.cpp +++ b/src/mlpack/methods/lmnn/lmnn_main.cpp @@ -11,8 +11,14 @@ */ #include #include -#include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME lmnn + #include +#include #include #include #include @@ -22,7 +28,7 @@ #include // Program Name. -BINDING_NAME("Large Margin Nearest Neighbors (LMNN)"); +BINDING_USER_NAME("Large Margin Nearest Neighbors (LMNN)"); // Short description. BINDING_SHORT_DESC( @@ -229,76 +235,81 @@ double KNNAccuracy(const arma::mat& dataset, return ((double) count / dataset.n_cols) * 100; } -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); - RequireAtLeastOnePassed({ "output" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no output will be saved"); - const string optimizerType = IO::GetParam("optimizer"); - RequireParamInSet("optimizer", { "amsgrad", "bbsgd", "sgd", + const string optimizerType = params.Get("optimizer"); + RequireParamInSet(params, "optimizer", { "amsgrad", "bbsgd", "sgd", "lbfgs" }, true, "unknown optimizer type"); // Warn on unused parameters. if (optimizerType == "amsgrad") { - ReportIgnoredParam("max_iterations", "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "max_iterations", + "L-BFGS optimizer is not being used"); } else if (optimizerType == "bbsgd") { - ReportIgnoredParam("max_iterations", "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "max_iterations", + "L-BFGS optimizer is not being used"); } else if (optimizerType == "sgd") { - ReportIgnoredParam("max_iterations", "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "max_iterations", + "L-BFGS optimizer is not being used"); } else if (optimizerType == "lbfgs") { - ReportIgnoredParam("step_size", "SGD optimizer is not being used"); - ReportIgnoredParam("linear_scan", "SGD optimizer is not being used"); - ReportIgnoredParam("batch_size", "SGD optimizer is not being used"); + ReportIgnoredParam(params, "step_size", "SGD optimizer is not being used"); + ReportIgnoredParam(params, "linear_scan", + "SGD optimizer is not being used"); + ReportIgnoredParam(params, "batch_size", "SGD optimizer is not being used"); } - RequireParamValue("k", [](int x) { return x > 0; }, true, + RequireParamValue(params, "k", [](int x) { return x > 0; }, true, "number of targets must be positive"); - RequireParamValue("range", [](int x) { return x > 0; }, true, + RequireParamValue(params, "range", [](int x) { return x > 0; }, true, "range must be positive"); - RequireParamValue("batch_size", [](int x) { return x > 0; }, true, + RequireParamValue(params, "batch_size", [](int x) { return x > 0; }, true, "batch size must be positive"); - RequireParamValue("regularization", [](double x) + RequireParamValue(params, "regularization", [](double x) { return x >= 0.0; }, true, "regularization value must be non-negative"); - RequireParamValue("step_size", [](double x) + RequireParamValue(params, "step_size", [](double x) { return x >= 0.0; }, true, "step size value must be non-negative"); - RequireParamValue("max_iterations", [](int x) + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, true, "maximum number of iterations must be non-negative"); - RequireParamValue("passes", [](int x) { return x >= 0; }, true, + RequireParamValue(params, "passes", [](int x) { return x >= 0; }, true, "maximum number of passes must be non-negative"); - RequireParamValue("tolerance", + RequireParamValue(params, "tolerance", [](double x) { return x >= 0.0; }, true, "tolerance must be non-negative"); - RequireParamValue("rank", [](int x) + RequireParamValue(params, "rank", [](int x) { return x >= 0; }, true, "rank must be nonnegative"); - const size_t k = (size_t) IO::GetParam("k"); - const double regularization = IO::GetParam("regularization"); - const double stepSize = IO::GetParam("step_size"); - const size_t passes = (size_t) IO::GetParam("passes"); - const size_t maxIterations = (size_t) IO::GetParam("max_iterations"); - const double tolerance = IO::GetParam("tolerance"); - const bool normalize = IO::HasParam("normalize"); - const bool center = IO::HasParam("center"); - const bool printAccuracy = IO::HasParam("print_accuracy"); - const bool shuffle = !IO::HasParam("linear_scan"); - const size_t batchSize = (size_t) IO::GetParam("batch_size"); - const size_t range = (size_t) IO::GetParam("range"); - const size_t rank = (size_t) IO::GetParam("rank"); + const size_t k = (size_t) params.Get("k"); + const double regularization = params.Get("regularization"); + const double stepSize = params.Get("step_size"); + const size_t passes = (size_t) params.Get("passes"); + const size_t maxIterations = (size_t) params.Get("max_iterations"); + const double tolerance = params.Get("tolerance"); + const bool normalize = params.Has("normalize"); + const bool center = params.Has("center"); + const bool printAccuracy = params.Has("print_accuracy"); + const bool shuffle = !params.Has("linear_scan"); + const size_t batchSize = (size_t) params.Get("batch_size"); + const size_t range = (size_t) params.Get("range"); + const size_t rank = (size_t) params.Get("rank"); // Load data. - arma::mat data = std::move(IO::GetParam("input")); + arma::mat data = std::move(params.Get("input")); // Carry out mean-centering on the dataset, if necessary. if (center) @@ -311,9 +322,9 @@ static void mlpackMain() // Do we want to load labels separately? arma::Row rawLabels(data.n_cols); - if (IO::HasParam("labels")) + if (params.Has("labels")) { - rawLabels = std::move(IO::GetParam>("labels")); + rawLabels = std::move(params.Get>("labels")); } else { @@ -331,9 +342,9 @@ static void mlpackMain() arma::mat distance; - if (IO::HasParam("distance")) + if (params.Has("distance")) { - distance = std::move(IO::GetParam("distance")); + distance = std::move(params.Get("distance")); } else if (rank) { @@ -423,14 +434,14 @@ static void mlpackMain() } // Save the output. - if (IO::HasParam("output")) - IO::GetParam("output") = distance; - if (IO::HasParam("transformed_data")) - IO::GetParam("transformed_data") = distance * data; - if (IO::HasParam("centered_data")) + if (params.Has("output")) + params.Get("output") = distance; + if (params.Has("transformed_data")) + params.Get("transformed_data") = distance * data; + if (params.Has("centered_data")) { if (center) - IO::GetParam("centered_data") = std::move(data); + params.Get("centered_data") = std::move(data); else Log::Info << "Mean-centering was not performed. Centered dataset " "will not be saved." << endl; diff --git a/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp b/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp index b68d91f052..7785f571c1 100644 --- a/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp +++ b/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME local_coordinate_coding + #include #include "lcc.hpp" @@ -24,7 +30,7 @@ using namespace mlpack::sparse_coding; // For NothingInitializer. using namespace mlpack::util; // Program Name. -BINDING_NAME("Local Coordinate Coding"); +BINDING_USER_NAME("Local Coordinate Coding"); // Short description. BINDING_SHORT_DESC( @@ -116,42 +122,42 @@ PARAM_MATRIX_OUT("codes", "Output codes matrix.", "c"); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + RandomSeed((size_t) params.Get("seed")); else RandomSeed((size_t) std::time(NULL)); // Check for parameter validity. - RequireOnlyOnePassed({ "training", "input_model" }, true); + RequireOnlyOnePassed(params, { "training", "input_model" }, true); - if (IO::HasParam("training")) - RequireAtLeastOnePassed({ "atoms" }, true); + if (params.Has("training")) + RequireAtLeastOnePassed(params, { "atoms" }, true); - RequireAtLeastOnePassed({ "codes", "dictionary", "output_model" }, false, - "no output will be saved"); + RequireAtLeastOnePassed(params, { "codes", "dictionary", "output_model" }, + false, "no output will be saved"); - ReportIgnoredParam({{ "test", false }}, "codes"); + ReportIgnoredParam(params, {{ "test", false }}, "codes"); - ReportIgnoredParam({{ "training", false }}, "atoms"); - ReportIgnoredParam({{ "training", false }}, "lambda"); - ReportIgnoredParam({{ "training", false }}, "initial_dictionary"); - ReportIgnoredParam({{ "training", false }}, "max_iterations"); - ReportIgnoredParam({{ "training", false }}, "normalize"); - ReportIgnoredParam({{ "training", false }}, "tolerance"); + ReportIgnoredParam(params, {{ "training", false }}, "atoms"); + ReportIgnoredParam(params, {{ "training", false }}, "lambda"); + ReportIgnoredParam(params, {{ "training", false }}, "initial_dictionary"); + ReportIgnoredParam(params, {{ "training", false }}, "max_iterations"); + ReportIgnoredParam(params, {{ "training", false }}, "normalize"); + ReportIgnoredParam(params, {{ "training", false }}, "tolerance"); // Do we have an existing model? LocalCoordinateCoding* lcc = NULL; - if (IO::HasParam("input_model")) - lcc = IO::GetParam("input_model"); + if (params.Has("input_model")) + lcc = params.Get("input_model"); - if (IO::HasParam("training")) + if (params.Has("training")) { - mat matX = std::move(IO::GetParam("training")); + mat matX = std::move(params.Get("training")); // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) + if (params.Has("normalize")) { Log::Info << "Normalizing data before coding..." << endl; for (size_t i = 0; i < matX.n_cols; ++i) @@ -159,42 +165,43 @@ static void mlpackMain() } // Check if the parameters lie within the bounds. - RequireParamValue("atoms", [&matX](int x) + RequireParamValue(params, "atoms", [&matX](int x) { return (x > 0) && ((size_t) x < matX.n_cols); }, 1, "Number of atoms must lie between 1 and number of training points"); - RequireParamValue("lambda", [](double x) { return x >= 0; }, 1, - "The regularization parameter should be a non-negative real number"); + RequireParamValue(params, "lambda", [](double x) { return x >= 0; }, + 1, "The regularization parameter should be a non-negative real number"); - RequireParamValue("tolerance", [](double x) { return x > 0; }, 1, + RequireParamValue(params, "tolerance", + [](double x) { return x > 0; }, 1, "Tolerance should be a positive real number"); lcc = new LocalCoordinateCoding(0, 0.0); - lcc->Lambda() = IO::GetParam("lambda"); - lcc->Atoms() = (size_t) IO::GetParam("atoms"); - lcc->MaxIterations() = (size_t) IO::GetParam("max_iterations"); - lcc->Tolerance() = IO::GetParam("tolerance"); + lcc->Lambda() = params.Get("lambda"); + lcc->Atoms() = (size_t) params.Get("atoms"); + lcc->MaxIterations() = (size_t) params.Get("max_iterations"); + lcc->Tolerance() = params.Get("tolerance"); // Inform the user if we are overwriting their model. - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { Log::Info << "Using dictionary from existing model in '" - << IO::GetPrintableParam("input_model") << "' as initial " + << params.GetPrintable("input_model") << "' as initial " << "dictionary for training." << endl; lcc->Train(matX); } - else if (IO::HasParam("initial_dictionary")) + else if (params.Has("initial_dictionary")) { // Load initial dictionary directly into LCC object. - lcc->Dictionary() = std::move(IO::GetParam("initial_dictionary")); + lcc->Dictionary() = std::move(params.Get("initial_dictionary")); // Validate the size of the initial dictionary. if (lcc->Dictionary().n_cols != lcc->Atoms()) { const size_t dictionarySize = lcc->Dictionary().n_cols; const size_t atoms = lcc->Atoms(); - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete lcc; Log::Fatal << "The initial dictionary has " << dictionarySize << " atoms, but the number of atoms was specified to be " @@ -204,7 +211,7 @@ static void mlpackMain() if (lcc->Dictionary().n_rows != matX.n_rows) { const size_t dictionaryDimension = lcc->Dictionary().n_rows; - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete lcc; Log::Fatal << "The initial dictionary has " << dictionaryDimension << " dimensions, but the data has " << matX.n_rows << " dimensions!" @@ -222,23 +229,23 @@ static void mlpackMain() } // Now, do we have any matrix to encode? - if (IO::HasParam("test")) + if (params.Has("test")) { - if (IO::GetParam("test").n_rows != lcc->Dictionary().n_rows) + if (params.Get("test").n_rows != lcc->Dictionary().n_rows) { const size_t dictionaryDimension = lcc->Dictionary().n_rows; - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete lcc; Log::Fatal << "Model was trained with a dimensionality of " << dictionaryDimension << ", but data in test file " - << IO::GetPrintableParam("test") << " has a dimensionality of " - << IO::GetParam("test").n_rows << "!" << endl; + << params.GetPrintable("test") << " has a dimensionality of " + << params.Get("test").n_rows << "!" << endl; } - mat matY = std::move(IO::GetParam("test")); + mat matY = std::move(params.Get("test")); // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) + if (params.Has("normalize")) { Log::Info << "Normalizing test data before coding..." << endl; for (size_t i = 0; i < matY.n_cols; ++i) @@ -248,10 +255,10 @@ static void mlpackMain() mat codes; lcc->Encode(matY, codes); - IO::GetParam("codes") = std::move(codes); + params.Get("codes") = std::move(codes); } // Save the dictionary and the model. - IO::GetParam("dictionary") = lcc->Dictionary(); - IO::GetParam("output_model") = lcc; + params.Get("dictionary") = lcc->Dictionary(); + params.Get("output_model") = lcc; } diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 408385875e..1fe4552d2e 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME logistic_regression + #include #include "logistic_regression.hpp" @@ -171,76 +177,78 @@ PARAM_DOUBLE_IN("decision_boundary", "Decision boundary for prediction; if the " "logistic function for a point is less than the boundary, the class is " "taken to be 0; otherwise, the class is 1.", "d", 0.5); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Collect command-line options. - const double lambda = IO::GetParam("lambda"); - const string optimizerType = IO::GetParam("optimizer"); - const double tolerance = IO::GetParam("tolerance"); - const double stepSize = IO::GetParam("step_size"); - const size_t batchSize = (size_t) IO::GetParam("batch_size"); - const size_t maxIterations = (size_t) IO::GetParam("max_iterations"); - const double decisionBoundary = IO::GetParam("decision_boundary"); + const double lambda = params.Get("lambda"); + const string optimizerType = params.Get("optimizer"); + const double tolerance = params.Get("tolerance"); + const double stepSize = params.Get("step_size"); + const size_t batchSize = (size_t) params.Get("batch_size"); + const size_t maxIterations = (size_t) params.Get("max_iterations"); + const double decisionBoundary = params.Get("decision_boundary"); // One of training and input_model must be specified. - RequireAtLeastOnePassed({ "training", "input_model" }, true); + RequireAtLeastOnePassed(params, { "training", "input_model" }, true); // If no output file is given, the user should know that the model will not be // saved, but only if a model is being trained. - if (IO::HasParam("training")) + if (params.Has("training")) { - RequireAtLeastOnePassed({ "output_model" }, false, "trained model will not " - "be saved"); + RequireAtLeastOnePassed(params, { "output_model" }, false, "trained model " + "will not be saved"); } // options "output" and "output_probabilities" are deprecated and replaced by // "predictions" and "probabilities" respectively // options "output" and "output_probabilities" can be removed in mlpack 4 - RequireAtLeastOnePassed({ "output_model", "output", "output_probabilities", - "predictions", "probabilities"}, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "output", + "output_probabilities", "predictions", "probabilities"}, false, + "no output will be saved"); // "output" and "output_probabilities" lines can be removed in mlpack 4 - ReportIgnoredParam({{ "test", false }}, "output"); - ReportIgnoredParam({{ "test", false }}, "output_probabilities"); - ReportIgnoredParam({{ "test", false }}, "predictions"); - ReportIgnoredParam({{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{ "test", false }}, "output"); + ReportIgnoredParam(params, {{ "test", false }}, "output_probabilities"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); // Max Iterations needs to be positive. - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, true, "max_iterations must be positive or zero"); // Batch Size needs to be greater than zero. - RequireParamValue("batch_size", [](int x) { return x > 0; }, + RequireParamValue(params, "batch_size", [](int x) { return x > 0; }, true, "batch_size must be greater than zero"); // Tolerance needs to be positive. - RequireParamValue("tolerance", [](double x) { return x >= 0.0; }, + RequireParamValue(params, "tolerance", + [](double x) { return x >= 0.0; }, true, "tolerance must be positive or zero"); // Optimizer has to be L-BFGS or SGD. - RequireParamInSet("optimizer", { "lbfgs", "sgd" }, + RequireParamInSet(params, "optimizer", { "lbfgs", "sgd" }, true, "unknown optimizer"); // Lambda must be positive. - RequireParamValue("lambda", [](double x) { return x >= 0.0; }, + RequireParamValue(params, "lambda", [](double x) { return x >= 0.0; }, true, "lambda must be positive or zero"); // Decision boundary must be between 0 and 1. - RequireParamValue("decision_boundary", + RequireParamValue(params, "decision_boundary", [](double x) { return x >= 0.0 && x <= 1.0; }, true, "decision boundary must be between 0.0 and 1.0"); - RequireParamValue("step_size", [](double x) { return x >= 0.0; }, - true, "step size must be positive"); + RequireParamValue(params, "step_size", + [](double x) { return x >= 0.0; }, true, "step size must be positive"); if (optimizerType != "sgd") { - if (IO::HasParam("step_size")) + if (params.Has("step_size")) { Log::Warn << PRINT_PARAM_STRING("step_size") << " ignored because " << "optimizer type is not 'sgd'." << std::endl; } - if (IO::HasParam("batch_size")) + if (params.Has("batch_size")) { Log::Warn << PRINT_PARAM_STRING("batch_size") << " ignored because " << "optimizer type is not 'sgd'." << std::endl; @@ -254,45 +262,45 @@ static void mlpackMain() arma::Row predictions; // Load data matrix. - if (IO::HasParam("training")) - regressors = std::move(IO::GetParam("training")); + if (params.Has("training")) + regressors = std::move(params.Get("training")); // Load the model, if necessary. LogisticRegression<>* model; - if (IO::HasParam("input_model")) - model = IO::GetParam*>("input_model"); + if (params.Has("input_model")) + model = params.Get*>("input_model"); else { model = new LogisticRegression<>(0, 0); // Set the size of the parameters vector, if necessary. - if (!IO::HasParam("labels")) + if (!params.Has("labels")) model->Parameters() = arma::zeros(regressors.n_rows); else model->Parameters() = arma::zeros(regressors.n_rows + 1); } // Check if the responses are in a separate file. - if (IO::HasParam("training") && IO::HasParam("labels")) + if (params.Has("training") && params.Has("labels")) { - responses = std::move(IO::GetParam>("labels")); + responses = std::move(params.Get>("labels")); if (responses.n_cols != regressors.n_cols) { // Clean memory if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; Log::Fatal << "The labels must have the same number of points as the " << "training dataset." << endl; } } - else if (IO::HasParam("training")) + else if (params.Has("training")) { // Checking the size of training data if no labels are passed. if (regressors.n_rows < 2) { // Clean memory if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; Log::Fatal << "Can't get responses from training data since it has less " @@ -306,10 +314,10 @@ static void mlpackMain() } // Verify the labels. - if (IO::HasParam("training") && max(responses) > 1) + if (params.Has("training") && max(responses) > 1) { // Clean memory if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; Log::Fatal << "The labels must be either 0 or 1, not " << max(responses) @@ -317,7 +325,7 @@ static void mlpackMain() } // Now, do the training. - if (IO::HasParam("training")) + if (params.Has("training")) { model->Lambda() = lambda; @@ -345,16 +353,16 @@ static void mlpackMain() } } - if (IO::HasParam("test")) + if (params.Has("test")) { - const arma::mat& testSet = IO::GetParam("test"); + const arma::mat& testSet = params.Get("test"); // Checking the dimensionality of the test data. if (testSet.n_rows != model->Parameters().n_cols - 1) { // Clean memory if needed. const size_t trainingDimensionality = model->Parameters().n_cols - 1; - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete model; Log::Fatal << "Test data dimensionality (" << testSet.n_rows << ") must " @@ -364,36 +372,36 @@ static void mlpackMain() // We must perform predictions on the test set. Training (and the // optimizer) are irrelevant here; we'll pass in the model we have. - if (IO::HasParam("predictions") || IO::HasParam("output")) + if (params.Has("predictions") || params.Has("output")) { Log::Info << "Predicting classes of points in '" - << IO::GetPrintableParam("test") << "'." << endl; + << params.GetPrintable("test") << "'." << endl; model->Classify(testSet, predictions, decisionBoundary); // The IO param "output" is deprecated and replaced by "predictions" // "output" parameter will be removed in mlpack 4. - if (IO::HasParam("predictions")) - IO::GetParam>("predictions") = predictions; - if (IO::HasParam("output")) - IO::GetParam>("output") = std::move(predictions); + if (params.Has("predictions")) + params.Get>("predictions") = predictions; + if (params.Has("output")) + params.Get>("output") = std::move(predictions); } // The IO param "output_probabilities" is deprecated // and replaced by "probabilities" // "output_probabilities" parameter will be removed in mlpack 4. - if (IO::HasParam("output_probabilities") || IO::HasParam("probabilities")) + if (params.Has("output_probabilities") || params.Has("probabilities")) { Log::Info << "Calculating class probabilities of points in '" - << IO::GetPrintableParam("test") << "'." << endl; + << params.GetPrintable("test") << "'." << endl; arma::mat probabilities; model->Classify(testSet, probabilities); - if (IO::HasParam("output_probabilities")) - IO::GetParam("output_probabilities") = probabilities; - if (IO::HasParam("probabilities")) - IO::GetParam("probabilities") = std::move(probabilities); + if (params.Has("output_probabilities")) + params.Get("output_probabilities") = probabilities; + if (params.Has("probabilities")) + params.Get("probabilities") = std::move(probabilities); } } - IO::GetParam*>("output_model") = model; + params.Get*>("output_model") = model; } diff --git a/src/mlpack/methods/lsh/lsh_main.cpp b/src/mlpack/methods/lsh/lsh_main.cpp index 7f36100311..ea5a82bf48 100644 --- a/src/mlpack/methods/lsh/lsh_main.cpp +++ b/src/mlpack/methods/lsh/lsh_main.cpp @@ -12,6 +12,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME lsh + #include #include @@ -24,7 +30,7 @@ using namespace mlpack::neighbor; using namespace mlpack::util; // Program Name. -BINDING_NAME("K-Approximate-Nearest-Neighbor Search with LSH"); +BINDING_USER_NAME("K-Approximate-Nearest-Neighbor Search with LSH"); // Short description. BINDING_SHORT_DESC( @@ -105,53 +111,55 @@ PARAM_INT_IN("bucket_size", "The size of a bucket in the second level hash.", "B", 500); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) time(NULL)); // Get all the parameters after checking them. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireParamValue("k", [](int x) { return x > 0; }, true, + RequireParamValue(params, "k", [](int x) { return x > 0; }, true, "k must be greater than 0"); } - RequireParamValue("second_hash_size", [](int x) { return x > 0; }, true, + RequireParamValue(params, "second_hash_size", + [](int x) { return x > 0; }, true, "second hash size must be greater than 0"); - RequireParamValue("bucket_size", [](int x) { return x > 0; }, true, - "bucket size must be greater than 0"); + RequireParamValue(params, "bucket_size", [](int x) { return x > 0; }, + true, "bucket size must be greater than 0"); - size_t k = IO::GetParam("k"); - size_t secondHashSize = IO::GetParam("second_hash_size"); - size_t bucketSize = IO::GetParam("bucket_size"); + size_t k = params.Get("k"); + size_t secondHashSize = params.Get("second_hash_size"); + size_t bucketSize = params.Get("bucket_size"); RequireOnlyOnePassed({ "input_model", "reference" }, true); - RequireAtLeastOnePassed({ "neighbors", "distances", "output_model" }, false, - "no results will be saved"); - if (IO::HasParam("k")) + RequireAtLeastOnePassed(params, { "neighbors", "distances", "output_model" }, + false, "no results will be saved"); + + if (params.Has("k")) { - RequireAtLeastOnePassed({ "query", "reference", "input_model" }, true, - "must pass set to search"); + RequireAtLeastOnePassed(params, { "query", "reference", "input_model" }, + true, "must pass set to search"); } - if (IO::HasParam("input_model") && IO::HasParam("k") && - !IO::HasParam("query")) + if (params.Has("input_model") && params.Has("k") && + !params.Has("query")) { Log::Info << "Performing LSH-based approximate nearest neighbor search on " << "the reference dataset in the model stored in '" - << IO::GetPrintableParam>("input_model") << "'." << endl; + << params.GetPrintable>("input_model") << "'." << endl; } - ReportIgnoredParam({{ "k", false }}, "neighbors"); - ReportIgnoredParam({{ "k", false }}, "distances"); + ReportIgnoredParam(params, {{ "k", false }}, "neighbors"); + ReportIgnoredParam(params, {{ "k", false }}, "distances"); - ReportIgnoredParam({{ "reference", false }}, "bucket_size"); - ReportIgnoredParam({{ "reference", false }}, "second_hash_size"); - ReportIgnoredParam({{ "reference", false }}, "hash_width"); + ReportIgnoredParam(params, {{ "reference", false }}, "bucket_size"); + ReportIgnoredParam(params, {{ "reference", false }}, "second_hash_size"); + ReportIgnoredParam(params, {{ "reference", false }}, "hash_width"); - if (IO::HasParam("input_model") && !IO::HasParam("k")) + if (params.Has("input_model") && !params.Has("k")) { Log::Warn << PRINT_PARAM_STRING("k") << " not passed; no search will be " << "performed!" << std::endl; @@ -162,10 +170,10 @@ static void mlpackMain() arma::mat queryData; // Pick up the LSH-specific parameters. - const size_t numProj = IO::GetParam("projections"); - const size_t numTables = IO::GetParam("tables"); - const double hashWidth = IO::GetParam("hash_width"); - const size_t numProbes = (size_t) IO::GetParam("num_probes"); + const size_t numProj = params.Get("projections"); + const size_t numTables = params.Get("tables"); + const double hashWidth = params.Get("hash_width"); + const size_t numProbes = (size_t) params.Get("num_probes"); arma::Mat neighbors; arma::mat distances; @@ -178,12 +186,12 @@ static void mlpackMain() numTables << " tables (L) with hash width (r): " << hashWidth << endl; LSHSearch<>* allkann; - if (IO::HasParam("reference")) + if (params.Has("reference")) { allkann = new LSHSearch<>(); Log::Info << "Using reference data from " - << IO::GetPrintableParam("reference") << "." << endl; - referenceData = std::move(IO::GetParam("reference")); + << params.GetPrintable("reference") << "." << endl; + referenceData = std::move(params.Get("reference")); Timer::Start("hash_building"); allkann->Train(std::move(referenceData), numProj, numTables, hashWidth, @@ -192,18 +200,18 @@ static void mlpackMain() } else // We must have an input model. { - allkann = IO::GetParam*>("input_model"); + allkann = params.Get*>("input_model"); } - if (IO::HasParam("k")) + if (params.Has("k")) { Log::Info << "Computing " << k << " distance approximate nearest neighbors." << endl; - if (IO::HasParam("query")) + if (params.Has("query")) { Log::Info << "Loaded query data from " - << IO::GetPrintableParam("query") << "." << endl; - queryData = std::move(IO::GetParam("query")); + << params.GetPrintable("query") << "." << endl; + queryData = std::move(params.Get("query")); allkann->Search(queryData, k, neighbors, distances, 0, numProbes); } @@ -216,21 +224,21 @@ static void mlpackMain() } // Compute recall, if desired. - if (IO::HasParam("true_neighbors")) + if (params.Has("true_neighbors")) { Log::Info << "Using true neighbor indices from '" - << IO::GetPrintableParam>("true_neighbors") << "'." + << params.GetPrintable>("true_neighbors") << "'." << endl; // Load the true neighbors. arma::Mat trueNeighbors = - std::move(IO::GetParam>("true_neighbors")); + std::move(params.Get>("true_neighbors")); if (trueNeighbors.n_rows != neighbors.n_rows || trueNeighbors.n_cols != neighbors.n_cols) { // Delete the model if needed. - if (IO::HasParam("reference")) + if (params.Has("reference")) delete allkann; Log::Fatal << "The true neighbors file must have the same number of " << "values as the set of neighbors being queried!" << endl; @@ -244,10 +252,10 @@ static void mlpackMain() } // Save output, if we did a search.. - if (IO::HasParam("k")) + if (params.Has("k")) { - IO::GetParam("distances") = std::move(distances); - IO::GetParam>("neighbors") = std::move(neighbors); + params.Get("distances") = std::move(distances); + params.Get>("neighbors") = std::move(neighbors); } - IO::GetParam*>("output_model") = allkann; + params.Get*>("output_model") = allkann; } diff --git a/src/mlpack/methods/mean_shift/mean_shift_main.cpp b/src/mlpack/methods/mean_shift/mean_shift_main.cpp index b38a86a364..c0b212583b 100644 --- a/src/mlpack/methods/mean_shift/mean_shift_main.cpp +++ b/src/mlpack/methods/mean_shift/mean_shift_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME mean_shift + #include #include @@ -23,7 +29,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Mean Shift Clustering"); +BINDING_USER_NAME("Mean Shift Clustering"); // Short description. BINDING_SHORT_DESC( @@ -92,22 +98,22 @@ PARAM_DOUBLE_IN("radius", "If the distance between two centroids is less than " "the given radius, one will be removed. A radius of 0 or less means an " "estimate will be calculated and used for the radius.", "r", 0); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - const double radius = IO::GetParam("radius"); - const int maxIterations = IO::GetParam("max_iterations"); + const double radius = params.Get("radius"); + const int maxIterations = params.Get("max_iterations"); - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, - "maximum iterations must be greater than or equal to 0"); + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, + true, "maximum iterations must be greater than or equal to 0"); // Make sure we have an output file if we're not doing the work in-place. - RequireAtLeastOnePassed({ "in_place", "output", "centroid" }, false, + RequireAtLeastOnePassed(params, { "in_place", "output", "centroid" }, false, "no results will be saved"); - ReportIgnoredParam({{ "output", false }}, "labels_only"); - ReportIgnoredParam({{ "in_place", true }}, "output"); - ReportIgnoredParam({{ "in_place", true }}, "labels_only"); + ReportIgnoredParam(params, {{ "output", false }}, "labels_only"); + ReportIgnoredParam(params, {{ "in_place", true }}, "output"); + ReportIgnoredParam(params, {{ "in_place", true }}, "labels_only"); - arma::mat dataset = std::move(IO::GetParam("input")); + arma::mat dataset = std::move(params.Get("input")); arma::mat centroids; arma::Row assignments; @@ -116,14 +122,14 @@ static void mlpackMain() Timer::Start("clustering"); Log::Info << "Performing mean shift clustering..." << endl; meanShift.Cluster(dataset, assignments, centroids, - IO::HasParam("force_convergence")); + params.Has("force_convergence")); Timer::Stop("clustering"); Log::Info << "Found " << centroids.n_cols << " centroids." << endl; if (radius <= 0.0) Log::Info << "Estimated radius was " << meanShift.Radius() << ".\n"; - if (IO::HasParam("in_place")) + if (params.Has("in_place")) { // Add the column of assignments to the dataset; but we have to convert them // to type double first. @@ -134,12 +140,12 @@ static void mlpackMain() dataset.insert_rows(dataset.n_rows, trans(converted)); // Save the dataset. - IO::MakeInPlaceCopy("output", "input"); - IO::GetParam("output") = std::move(dataset); + params.MakeInPlaceCopy("output", "input"); + params.Get("output") = std::move(dataset); } - else if (IO::HasParam("output")) + else if (params.Has("output")) { - if (!IO::HasParam("labels_only")) + if (!params.Has("labels_only")) { // Convert the assignments to doubles. arma::vec converted(assignments.n_elem); @@ -149,18 +155,18 @@ static void mlpackMain() dataset.insert_rows(dataset.n_rows, trans(converted)); // Now save, in the different file. - IO::GetParam("output") = std::move(dataset); + params.Get("output") = std::move(dataset); } else { // TODO: figure out how to output as an arma::Mat so that files // aren't way larger than needed. - IO::GetParam("output") = + params.Get("output") = arma::conv_to::from(assignments); } } // Should we write the centroids to a file? - if (IO::HasParam("centroid")) - IO::GetParam("centroid") = std::move(centroids); + if (params.Has("centroid")) + params.Get("centroid") = std::move(centroids); } diff --git a/src/mlpack/methods/mvu/mvu_main.cpp b/src/mlpack/methods/mvu/mvu_main.cpp index e61fc9eacf..029f29c0f6 100644 --- a/src/mlpack/methods/mvu/mvu_main.cpp +++ b/src/mlpack/methods/mvu/mvu_main.cpp @@ -13,10 +13,17 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME mvu + +#include #include "mvu.hpp" // Program Name. -BINDING_NAME("Maximum Variance Unfolding (MVU)"); +BINDING_USER_NAME("Maximum Variance Unfolding (MVU)"); // Long description. BINDING_LONG_DESC("This program implements " @@ -39,16 +46,14 @@ using namespace mlpack::util; using namespace arma; using namespace std; -int main(int argc, char **argv) +void BINDING_NAME(util::Params& params, util::Timers& timers); { - // Read from command line. - IO::ParseCommandLine(argc, argv); - const string inputFile = IO::GetParam("input_file"); - const string outputFile = IO::GetParam("output_file"); - const int newDim = IO::GetParam("new_dim"); - const int numNeighbors = IO::GetParam("num_neighbors"); + const string inputFile = params.Get("input_file"); + const string outputFile = params.Get("output_file"); + const int newDim = params.Get("new_dim"); + const int numNeighbors = params.Get("num_neighbors"); - if (!IO::HasParam("output")) + if (!params.Has("output")) { Log::Warn << "--output_file (-o) is not specified; no results will be " << "saved!" << endl; @@ -57,7 +62,7 @@ int main(int argc, char **argv) RandomSeed(time(NULL)); // Load input dataset. - mat data = std::move(IO::GetParam("input")); + mat data = std::move(params.Get("input")); // Verify that the requested dimensionality is valid. if (newDim <= 0 || newDim > (int) data.n_rows) @@ -82,6 +87,6 @@ int main(int argc, char **argv) mvu.Unfold(newDim, numNeighbors, output); // Save results to file. - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(output); + if (params.Has("output")) + params.Get("output") = std::move(output); } diff --git a/src/mlpack/methods/naive_bayes/nbc_main.cpp b/src/mlpack/methods/naive_bayes/nbc_main.cpp index 5fd980bc7d..ef7c0cf140 100644 --- a/src/mlpack/methods/naive_bayes/nbc_main.cpp +++ b/src/mlpack/methods/naive_bayes/nbc_main.cpp @@ -14,6 +14,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME nbc + #include #include @@ -26,7 +32,7 @@ using namespace std; using namespace arma; // Program Name. -BINDING_NAME("Parametric Naive Bayes Classifier"); +BINDING_USER_NAME("Parametric Naive Bayes Classifier"); // Short description. BINDING_SHORT_DESC( @@ -137,33 +143,33 @@ PARAM_MATRIX_OUT("output_probs", "The matrix in which the predicted probability" PARAM_MATRIX_OUT("probabilities", "The matrix in which the predicted" " probability of labels for the test set will be written.", "p"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Check input parameters. - RequireOnlyOnePassed({ "training", "input_model" }, true); - ReportIgnoredParam({{ "training", false }}, "labels"); - ReportIgnoredParam({{ "training", false }}, "incremental_variance"); - RequireAtLeastOnePassed({ "output", "predictions", "output_model", + RequireOnlyOnePassed(params, { "training", "input_model" }, true); + ReportIgnoredParam(params, {{ "training", false }}, "labels"); + ReportIgnoredParam(params, {{ "training", false }}, "incremental_variance"); + RequireAtLeastOnePassed(params, { "output", "predictions", "output_model", "output_probs", "probabilities" }, false, "no output will be saved"); - ReportIgnoredParam({{ "test", false }}, "output"); - ReportIgnoredParam({{ "test", false }}, "predictions"); - if (IO::HasParam("input_model") && !IO::HasParam("test")) + ReportIgnoredParam(params, {{ "test", false }}, "output"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); + if (params.Has("input_model") && !params.Has("test")) Log::Warn << "No test set given; no task will be performed!" << std::endl; // Either we have to train a model, or load a model. NBCModel* model; - if (IO::HasParam("training")) + if (params.Has("training")) { model = new NBCModel(); - mat trainingData = std::move(IO::GetParam("training")); + mat trainingData = std::move(params.Get("training")); Row labels; // Did the user pass in labels? - if (IO::HasParam("labels")) + if (params.Has("labels")) { // Load labels. - Row rawLabels = std::move(IO::GetParam>("labels")); + Row rawLabels = std::move(params.Get>("labels")); data::NormalizeLabels(rawLabels, labels, model->mappings); } else @@ -176,7 +182,7 @@ static void mlpackMain() // Remove the label row. trainingData.shed_row(trainingData.n_rows - 1); } - const bool incrementalVariance = IO::HasParam("incremental_variance"); + const bool incrementalVariance = params.Has("incremental_variance"); Timer::Start("nbc_training"); model->nbc = NaiveBayesClassifier<>(trainingData, labels, @@ -186,13 +192,13 @@ static void mlpackMain() else { // Load the model from file. - model = IO::GetParam("input_model"); + model = params.Get("input_model"); } // Do we need to do testing? - if (IO::HasParam("test")) + if (params.Has("test")) { - mat testingData = std::move(IO::GetParam("test")); + mat testingData = std::move(params.Get("test")); if (testingData.n_rows != model->nbc.Means().n_rows) { @@ -208,25 +214,25 @@ static void mlpackMain() model->nbc.Classify(testingData, predictions, probabilities); Timer::Stop("nbc_testing"); - if (IO::HasParam("output") || IO::HasParam("predictions")) + if (params.Has("output") || params.Has("predictions")) { // Un-normalize labels to prepare output. Row rawResults; data::RevertLabels(predictions, model->mappings, rawResults); - if (IO::HasParam("predictions")) - IO::GetParam>("predictions") = rawResults; - if (IO::HasParam("output")) - IO::GetParam>("output") = std::move(rawResults); + if (params.Has("predictions")) + params.Get>("predictions") = rawResults; + if (params.Has("output")) + params.Get>("output") = std::move(rawResults); } - if (IO::HasParam("output_probs") || IO::HasParam("probabilities")) + if (params.Has("output_probs") || params.Has("probabilities")) { - if (IO::HasParam("probabilities")) - IO::GetParam("probabilities") = probabilities; - if (IO::HasParam("output_probs")) - IO::GetParam("output_probs") = std::move(probabilities); + if (params.Has("probabilities")) + params.Get("probabilities") = probabilities; + if (params.Has("output_probs")) + params.Get("output_probs") = std::move(probabilities); } } - IO::GetParam("output_model") = model; + params.Get("output_model") = model; } diff --git a/src/mlpack/methods/nca/nca_main.cpp b/src/mlpack/methods/nca/nca_main.cpp index ba4447b831..a317af66e7 100644 --- a/src/mlpack/methods/nca/nca_main.cpp +++ b/src/mlpack/methods/nca/nca_main.cpp @@ -11,8 +11,14 @@ */ #include #include -#include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME nca + #include +#include #include #include @@ -21,7 +27,7 @@ #include // Program Name. -BINDING_NAME("Neighborhood Components Analysis (NCA)"); +BINDING_USER_NAME("Neighborhood Components Analysis (NCA)"); // Short description. BINDING_SHORT_DESC( @@ -143,59 +149,65 @@ using namespace mlpack::metric; using namespace mlpack::util; using namespace std; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); - RequireAtLeastOnePassed({ "output" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no output will be saved"); - const string optimizerType = IO::GetParam("optimizer"); - RequireParamInSet("optimizer", { "sgd", "lbfgs" }, + const string optimizerType = params.Get("optimizer"); + RequireParamInSet(params, "optimizer", { "sgd", "lbfgs" }, true, "unknown optimizer type"); // Warn on unused parameters. if (optimizerType == "sgd") { - ReportIgnoredParam("num_basis", "L-BFGS optimizer is not being used"); - ReportIgnoredParam("armijo_constant", "L-BFGS optimizer is not being used"); - ReportIgnoredParam("wolfe", "L-BFGS optimizer is not being used"); - ReportIgnoredParam("max_line_search_trials", + ReportIgnoredParam(params, "num_basis", + "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "armijo_constant", + "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "wolfe", "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "max_line_search_trials", + "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "min_step", + "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "max_step", + "L-BFGS optimizer is not being used"); + ReportIgnoredParam(params, "batch_size", "L-BFGS optimizer is not being used"); - ReportIgnoredParam("min_step", "L-BFGS optimizer is not being used"); - ReportIgnoredParam("max_step", "L-BFGS optimizer is not being used"); - ReportIgnoredParam("batch_size", "L-BFGS optimizer is not being used"); } else if (optimizerType == "lbfgs") { - ReportIgnoredParam("step_size", "SGD optimizer is not being used"); - ReportIgnoredParam("linear_scan", "SGD optimizer is not being used"); - ReportIgnoredParam("batch_size", "SGD optimizer is not being used"); + ReportIgnoredParam(params, "step_size", "SGD optimizer is not being used"); + ReportIgnoredParam(params, "linear_scan", "SGD optimizer is not being used"); + ReportIgnoredParam(params, "batch_size", "SGD optimizer is not being used"); } - const double stepSize = IO::GetParam("step_size"); - const size_t maxIterations = (size_t) IO::GetParam("max_iterations"); - const double tolerance = IO::GetParam("tolerance"); - const bool normalize = IO::HasParam("normalize"); - const bool shuffle = !IO::HasParam("linear_scan"); - const int numBasis = IO::GetParam("num_basis"); - const double armijoConstant = IO::GetParam("armijo_constant"); - const double wolfe = IO::GetParam("wolfe"); - const int maxLineSearchTrials = IO::GetParam("max_line_search_trials"); - const double minStep = IO::GetParam("min_step"); - const double maxStep = IO::GetParam("max_step"); - const size_t batchSize = (size_t) IO::GetParam("batch_size"); + const double stepSize = params.Get("step_size"); + const size_t maxIterations = (size_t) params.Get("max_iterations"); + const double tolerance = params.Get("tolerance"); + const bool normalize = params.Has("normalize"); + const bool shuffle = !params.Has("linear_scan"); + const int numBasis = params.Get("num_basis"); + const double armijoConstant = params.Get("armijo_constant"); + const double wolfe = params.Get("wolfe"); + const int maxLineSearchTrials = params.Get("max_line_search_trials"); + const double minStep = params.Get("min_step"); + const double maxStep = params.Get("max_step"); + const size_t batchSize = (size_t) params.Get("batch_size"); // Load data. - arma::mat data = std::move(IO::GetParam("input")); + arma::mat data = std::move(params.Get("input")); // Do we want to load labels separately? arma::Row rawLabels(data.n_cols); - if (IO::HasParam("labels")) + if (params.Has("labels")) { - rawLabels = std::move(IO::GetParam>("labels")); + rawLabels = std::move(params.Get>("labels")); if (rawLabels.n_elem != data.n_cols) { @@ -265,6 +277,6 @@ static void mlpackMain() } // Save the output. - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(distance); + if (params.Has("output")) + params.Get("output") = std::move(distance); } diff --git a/src/mlpack/methods/neighbor_search/kfn_main.cpp b/src/mlpack/methods/neighbor_search/kfn_main.cpp index 65f3083d56..0903c8e1e7 100644 --- a/src/mlpack/methods/neighbor_search/kfn_main.cpp +++ b/src/mlpack/methods/neighbor_search/kfn_main.cpp @@ -12,6 +12,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME kfn + #include #include @@ -33,7 +39,7 @@ using namespace mlpack::util; typedef NSModel KFNModel; // Program Name. -BINDING_NAME("k-Furthest-Neighbors Search"); +BINDING_USER_NAME("k-Furthest-Neighbors Search"); // Short description. BINDING_SHORT_DESC( @@ -115,22 +121,22 @@ PARAM_DOUBLE_IN("percentage", "If specified, will do approximate furthest " "neighbors will be at least (p*100) % of the distance as the true furthest " "neighbor.", "p", 1); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. - RequireOnlyOnePassed({ "reference", "input_model" }, true); + RequireOnlyOnePassed(params, { "reference", "input_model" }, true); - ReportIgnoredParam({{ "input_model", true }}, "tree_type"); - ReportIgnoredParam({{ "input_model", true }}, "random_basis"); + ReportIgnoredParam(params, {{ "input_model", true }}, "tree_type"); + ReportIgnoredParam(params, {{ "input_model", true }}, "random_basis"); // Notify the user of parameters that will be only be considered for query // tree. - if (IO::HasParam("input_model") && IO::HasParam("leaf_size")) + if (params.Has("input_model") && params.Has("leaf_size")) { Log::Warn << PRINT_PARAM_STRING("leaf_size") << " will only be considered" << " for the query tree, because " @@ -138,51 +144,51 @@ static void mlpackMain() } // The user should give something to do... - RequireAtLeastOnePassed({ "k", "output_model" }, false, + RequireAtLeastOnePassed(params, { "k", "output_model" }, false, "no results will be saved"); // If the user specifies k but no output files, they should be warned. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireAtLeastOnePassed({ "neighbors", "distances" }, false, + RequireAtLeastOnePassed(params, { "neighbors", "distances" }, false, "furthest neighbor search results will not be saved"); } // If the user specifies output files but no k, they should be warned. - ReportIgnoredParam({{ "k", false }}, "neighbors"); - ReportIgnoredParam({{ "k", false }}, "distances"); - ReportIgnoredParam({{ "k", false }}, "true_neighbors"); - ReportIgnoredParam({{ "k", false }}, "true_distances"); - ReportIgnoredParam({{ "k", false }}, "query"); + ReportIgnoredParam(params, {{ "k", false }}, "neighbors"); + ReportIgnoredParam(params, {{ "k", false }}, "distances"); + ReportIgnoredParam(params, {{ "k", false }}, "true_neighbors"); + ReportIgnoredParam(params, {{ "k", false }}, "true_distances"); + ReportIgnoredParam(params, {{ "k", false }}, "query"); // Sanity check on leaf size. - RequireParamValue("leaf_size", [](int x) { return x > 0; }, + RequireParamValue(params, "leaf_size", [](int x) { return x > 0; }, true, "leaf size must be positive"); - const int lsInt = IO::GetParam("leaf_size"); + const int lsInt = params.Get("leaf_size"); // Sanity check on epsilon. - double epsilon = IO::GetParam("epsilon"); - RequireParamValue("epsilon", [](double x) + double epsilon = params.Get("epsilon"); + RequireParamValue(params, "epsilon", [](double x) { return x >= 0.0 && x < 1; }, true, "epsilon must be in the range [0, 1)."); // Sanity check on percentage. - const double percentage = IO::GetParam("percentage"); - RequireParamValue("percentage", + const double percentage = params.Get("percentage"); + RequireParamValue(params, "percentage", [](double x) { return x > 0.0 && x <= 1.0; }, true, "percentage must be in the range (0, 1]"); - ReportIgnoredParam({{ "epsilon", true }}, "percentage"); + ReportIgnoredParam(params, {{ "epsilon", true }}, "percentage"); - if (IO::HasParam("percentage")) + if (params.Has("percentage")) epsilon = 1 - percentage; // We either have to load the reference data, or we have to load the model. NSModel* kfn; - const string algorithm = IO::GetParam("algorithm"); - RequireParamInSet("algorithm", { "naive", "single_tree", "dual_tree", - "greedy" }, true, "unknown neighbor search algorithm"); + const string algorithm = params.Get("algorithm"); + RequireParamInSet(params, "algorithm", { "naive", "single_tree", + "dual_tree", "greedy" }, true, "unknown neighbor search algorithm"); NeighborSearchMode searchMode = DUAL_TREE_MODE; if (algorithm == "naive") @@ -194,14 +200,14 @@ static void mlpackMain() else if (algorithm == "greedy") searchMode = GREEDY_SINGLE_TREE_MODE; - if (IO::HasParam("reference")) + if (params.Has("reference")) { // Get all the parameters. - RequireParamInSet("tree_type", { "kd", "cover", "r", "r-star", - "ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "vp", "rp", "max-rp", - "ub", "oct" }, true, "unknown tree type"); - const string treeType = IO::GetParam("tree_type"); - const bool randomBasis = IO::HasParam("random_basis"); + RequireParamInSet(params, "tree_type", { "kd", "cover", "r", + "r-star", "ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "vp", "rp", + "max-rp", "ub", "oct" }, true, "unknown tree type"); + const string treeType = params.Get("tree_type"); + const bool randomBasis = params.Has("random_basis"); kfn = new KFNModel(); @@ -240,16 +246,16 @@ static void mlpackMain() kfn->LeafSize() = size_t(lsInt); Log::Info << "Using reference data from " - << IO::GetPrintableParam("reference") << "." << endl; + << params.GetPrintable("reference") << "." << endl; - arma::mat referenceSet = std::move(IO::GetParam("reference")); + arma::mat referenceSet = std::move(params.Get("reference")); kfn->BuildModel(std::move(referenceSet), searchMode, epsilon); } else { // Load the model from file. - kfn = IO::GetParam("input_model"); + kfn = params.Get("input_model"); // Adjust search mode. kfn->SearchMode() = searchMode; @@ -258,31 +264,31 @@ static void mlpackMain() // If leaf_size wasn't provided, let's consider the current value in the // loaded model. Else, update it (only considered when building the query // tree). - if (IO::HasParam("leaf_size")) + if (params.Has("leaf_size")) kfn->LeafSize() = size_t(lsInt); Log::Info << "Using kFN model from '" - << IO::GetPrintableParam("input_model") << "' (trained on " + << params.GetPrintable("input_model") << "' (trained on " << kfn->Dataset().n_rows << "x" << kfn->Dataset().n_cols << " dataset)." << endl; } // Perform search, if desired. - if (IO::HasParam("k")) + if (params.Has("k")) { - const size_t k = (size_t) IO::GetParam("k"); + const size_t k = (size_t) params.Get("k"); arma::mat queryData; - if (IO::HasParam("query")) + if (params.Has("query")) { Log::Info << "Using query data from " - << IO::GetPrintableParam("query") << "." << endl; - queryData = std::move(IO::GetParam("query")); + << params.GetPrintable("query") << "." << endl; + queryData = std::move(params.Get("query")); if (queryData.n_rows != kfn->Dataset().n_rows) { // Clean memory if needed. const size_t dimensions = kfn->Dataset().n_rows; - if (IO::HasParam("reference")) + if (params.Has("reference")) delete kfn; Log::Fatal << "Query has invalid dimensions (" << queryData.n_rows << "); should be " << dimensions << "!" << endl; @@ -296,7 +302,7 @@ static void mlpackMain() { // Clean memory if needed. const size_t referencePoints = kfn->Dataset().n_cols; - if (IO::HasParam("reference")) + if (params.Has("reference")) delete kfn; Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less " << "than or equal to the number of reference points (" @@ -305,11 +311,11 @@ static void mlpackMain() // Sanity check on k value: must not be equal to the number of reference // points when query data has not been provided. - if (!IO::HasParam("query") && k == kfn->Dataset().n_cols) + if (!params.Has("query") && k == kfn->Dataset().n_cols) { // Clean memory if needed. const size_t referencePoints = kfn->Dataset().n_cols; - if (IO::HasParam("reference")) + if (params.Has("reference")) delete kfn; Log::Fatal << "Invalid k: " << k << "; must be less than the number of " << "reference points (" << referencePoints << ") if query data has " @@ -320,14 +326,14 @@ static void mlpackMain() arma::Mat neighbors; arma::mat distances; - if (IO::HasParam("query")) + if (params.Has("query")) kfn->Search(std::move(queryData), k, neighbors, distances); else kfn->Search(k, neighbors, distances); Log::Info << "Search complete." << endl; // Calculate the effective error, if desired. - if (IO::HasParam("true_distances")) + if (params.Has("true_distances")) { if (kfn->Epsilon() == 0) Log::Warn << PRINT_PARAM_STRING("true_distances") << " specified, but " @@ -335,13 +341,13 @@ static void mlpackMain() << "error!" << endl; arma::mat trueDistances = - std::move(IO::GetParam("true_distances")); + std::move(params.Get("true_distances")); if (trueDistances.n_rows != distances.n_rows || trueDistances.n_cols != distances.n_cols) { // Clean memory if needed. - if (IO::HasParam("reference")) + if (params.Has("reference")) delete kfn; Log::Fatal << "The true distances file must have the same number of " << "values than the set of distances being queried!" << endl; @@ -352,7 +358,7 @@ static void mlpackMain() } // Calculate the recall, if desired. - if (IO::HasParam("true_neighbors")) + if (params.Has("true_neighbors")) { if (kfn->Epsilon() == 0) Log::Warn << PRINT_PARAM_STRING("true_neighbors") << " specified, but " @@ -360,13 +366,13 @@ static void mlpackMain() << "recall!" << endl; arma::Mat trueNeighbors = - std::move(IO::GetParam>("true_neighbors")); + std::move(params.Get>("true_neighbors")); if (trueNeighbors.n_rows != neighbors.n_rows || trueNeighbors.n_cols != neighbors.n_cols) { // Clean memory if needed. - if (IO::HasParam("reference")) + if (params.Has("reference")) delete kfn; Log::Fatal << "The true neighbors file must have the same number of " << "values than the set of neighbors being queried!" << endl; @@ -376,9 +382,9 @@ static void mlpackMain() } // Save output. - IO::GetParam>("neighbors") = std::move(neighbors); - IO::GetParam("distances") = std::move(distances); + params.Get>("neighbors") = std::move(neighbors); + params.Get("distances") = std::move(distances); } - IO::GetParam("output_model") = kfn; + params.Get("output_model") = kfn; } diff --git a/src/mlpack/methods/neighbor_search/knn_main.cpp b/src/mlpack/methods/neighbor_search/knn_main.cpp index 87ca2203b0..98cc810af8 100644 --- a/src/mlpack/methods/neighbor_search/knn_main.cpp +++ b/src/mlpack/methods/neighbor_search/knn_main.cpp @@ -12,6 +12,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME knn + #include #include #include @@ -35,7 +41,7 @@ using namespace mlpack::util; typedef NSModel KNNModel; // Program Name. -BINDING_NAME("k-Nearest-Neighbors Search"); +BINDING_USER_NAME("k-Nearest-Neighbors Search"); // Short description. BINDING_SHORT_DESC( @@ -123,21 +129,21 @@ PARAM_STRING_IN("algorithm", "Type of neighbor search: 'naive', 'single_tree', " PARAM_DOUBLE_IN("epsilon", "If specified, will do approximate nearest neighbor " "search with given relative error.", "e", 0); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. - RequireOnlyOnePassed({ "reference", "input_model" }, true); + RequireOnlyOnePassed(params, { "reference", "input_model" }, true); - ReportIgnoredParam({{ "input_model", true }}, "tree_type"); - ReportIgnoredParam({{ "input_model", true }}, "random_basis"); - ReportIgnoredParam({{ "input_model", true }}, "tau"); - ReportIgnoredParam({{ "input_model", true }}, "rho"); - if (IO::HasParam("input_model") && IO::HasParam("leaf_size")) + ReportIgnoredParam(params, {{ "input_model", true }}, "tree_type"); + ReportIgnoredParam(params, {{ "input_model", true }}, "random_basis"); + ReportIgnoredParam(params, {{ "input_model", true }}, "tau"); + ReportIgnoredParam(params, {{ "input_model", true }}, "rho"); + if (params.Has("input_model") && params.Has("leaf_size")) { Log::Warn << PRINT_PARAM_STRING("leaf_size") << " will only be considered" << " for the query tree, because --input_model_file is specified." @@ -145,56 +151,56 @@ static void mlpackMain() } // The user should give something to do... - RequireAtLeastOnePassed({ "k", "output_model" }, false, + RequireAtLeastOnePassed(params, { "k", "output_model" }, false, "no results will be saved"); // If the user specifies k but no output files, they should be warned. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireAtLeastOnePassed({ "neighbors", "distances" }, false, + RequireAtLeastOnePassed(params, { "neighbors", "distances" }, false, "nearest neighbor search results will not be saved"); } // If the user specifies output files but no k, they should be warned. - ReportIgnoredParam({{ "k", false }}, "neighbors"); - ReportIgnoredParam({{ "k", false }}, "distances"); - ReportIgnoredParam({{ "k", false }}, "true_neighbors"); - ReportIgnoredParam({{ "k", false }}, "true_distances"); - ReportIgnoredParam({{ "k", false }}, "query"); + ReportIgnoredParam(params, {{ "k", false }}, "neighbors"); + ReportIgnoredParam(params, {{ "k", false }}, "distances"); + ReportIgnoredParam(params, {{ "k", false }}, "true_neighbors"); + ReportIgnoredParam(params, {{ "k", false }}, "true_distances"); + ReportIgnoredParam(params, {{ "k", false }}, "query"); // Sanity check on leaf size. - RequireParamValue("leaf_size", [](int x) { return x > 0; }, + RequireParamValue(params, "leaf_size", [](int x) { return x > 0; }, true, "leaf size must be positive"); - const int lsInt = IO::GetParam("leaf_size"); + const int lsInt = params.Get("leaf_size"); // Sanity check on tau. - RequireParamValue("tau", [](double x) { return x >= 0.0; }, + RequireParamValue(params, "tau", [](double x) { return x >= 0.0; }, true, "tau must be positive"); - const double tau = IO::GetParam("tau"); + const double tau = params.Get("tau"); // Sanity check on rho. - const double rho = IO::GetParam("rho"); - RequireParamValue("rho", + const double rho = params.Get("rho"); + RequireParamValue(params, "rho", [](double x) { return x >= 0.0 && x <= 1.0; }, true, "rho must be in the range [0, 1]"); - if (IO::GetParam("tree_type") != "spill") + if (params.Get("tree_type") != "spill") { - ReportIgnoredParam("tau", "spill trees are not being used"); - ReportIgnoredParam("rho", "spill trees are not being used"); + ReportIgnoredParam(params, "tau", "spill trees are not being used"); + ReportIgnoredParam(params, "rho", "spill trees are not being used"); } // Sanity check on epsilon. - const double epsilon = IO::GetParam("epsilon"); - RequireParamValue("epsilon", [](double x) { return x >= 0.0; }, true, - "epsilon must be positive"); + const double epsilon = params.Get("epsilon"); + RequireParamValue(params, "epsilon", + [](double x) { return x >= 0.0; }, true, "epsilon must be positive"); // We either have to load the reference data, or we have to load the model. KNNModel* knn; - const string algorithm = IO::GetParam("algorithm"); - RequireParamInSet("algorithm", { "naive", "single_tree", "dual_tree", - "greedy" }, true, "unknown neighbor search algorithm"); + const string algorithm = params.Get("algorithm"); + RequireParamInSet(params, "algorithm", { "naive", "single_tree", + "dual_tree", "greedy" }, true, "unknown neighbor search algorithm"); NeighborSearchMode searchMode = DUAL_TREE_MODE; if (algorithm == "naive") @@ -206,16 +212,16 @@ static void mlpackMain() else if (algorithm == "greedy") searchMode = GREEDY_SINGLE_TREE_MODE; - if (IO::HasParam("reference")) + if (params.Has("reference")) { // Get all the parameters. - const string treeType = IO::GetParam("tree_type"); - const bool randomBasis = IO::HasParam("random_basis"); + const string treeType = params.Get("tree_type"); + const bool randomBasis = params.Has("random_basis"); KNNModel::TreeTypes tree = KNNModel::KD_TREE; - RequireParamInSet("tree_type", { "kd", "cover", "r", "r-star", - "ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "spill", "vp", "rp", - "max-rp", "ub", "oct" }, true, "unknown tree type"); + RequireParamInSet(params, "tree_type", { "kd", "cover", "r", + "r-star", "ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "spill", + "vp", "rp", "max-rp", "ub", "oct" }, true, "unknown tree type"); knn = new KNNModel(); @@ -257,16 +263,16 @@ static void mlpackMain() knn->Rho() = rho; Log::Info << "Using reference data from " - << IO::GetPrintableParam("reference") << "." << endl; + << params.GetPrintable("reference") << "." << endl; - arma::mat referenceSet = std::move(IO::GetParam("reference")); + arma::mat referenceSet = std::move(params.Get("reference")); knn->BuildModel(std::move(referenceSet), searchMode, epsilon); } else { // Load the model from file. - knn = IO::GetParam("input_model"); + knn = params.Get("input_model"); // Adjust search mode. knn->SearchMode() = searchMode; @@ -275,31 +281,31 @@ static void mlpackMain() // If leaf_size wasn't provided, let's consider the current value in the // loaded model. Else, update it (only considered when building the query // tree). - if (IO::HasParam("leaf_size")) + if (params.Has("leaf_size")) knn->LeafSize() = size_t(lsInt); Log::Info << "Loaded kNN model from '" - << IO::GetPrintableParam("input_model") << "' (trained on " + << params.GetPrintable("input_model") << "' (trained on " << knn->Dataset().n_rows << "x" << knn->Dataset().n_cols << " dataset)." << endl; } // Perform search, if desired. - if (IO::HasParam("k")) + if (params.Has("k")) { - const size_t k = (size_t) IO::GetParam("k"); + const size_t k = (size_t) params.Get("k"); arma::mat queryData; - if (IO::HasParam("query")) + if (params.Has("query")) { Log::Info << "Using query data from " - << IO::GetPrintableParam("query") << "." << endl; - queryData = std::move(IO::GetParam("query")); + << params.GetPrintable("query") << "." << endl; + queryData = std::move(params.Get("query")); if (queryData.n_rows != knn->Dataset().n_rows) { // Clean memory if needed before crashing. const size_t dimensions = knn->Dataset().n_rows; - if (IO::HasParam("reference")) + if (params.Has("reference")) delete knn; Log::Fatal << "Query has invalid dimensions(" << queryData.n_rows << "); should be " << dimensions << "!" << endl; @@ -313,7 +319,7 @@ static void mlpackMain() { // Clean memory if needed before crashing. const size_t referencePoints = knn->Dataset().n_cols; - if (IO::HasParam("reference")) + if (params.Has("reference")) delete knn; Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less " << "than or equal to the number of reference points (" @@ -322,11 +328,11 @@ static void mlpackMain() // Sanity check on k value: must not be equal to the number of reference // points when query data has not been provided. - if (!IO::HasParam("query") && k == knn->Dataset().n_cols) + if (!params.Has("query") && k == knn->Dataset().n_cols) { // Clean memory if needed before crashing. const size_t referencePoints = knn->Dataset().n_cols; - if (IO::HasParam("reference")) + if (params.Has("reference")) delete knn; Log::Fatal << "Invalid k: " << k << "; must be less than the number of " << "reference points (" << referencePoints << ") if query data has " @@ -337,14 +343,14 @@ static void mlpackMain() arma::Mat neighbors; arma::mat distances; - if (IO::HasParam("query")) + if (params.Has("query")) knn->Search(std::move(queryData), k, neighbors, distances); else knn->Search(k, neighbors, distances); Log::Info << "Search complete." << endl; // Calculate the effective error, if desired. - if (IO::HasParam("true_distances")) + if (params.Has("true_distances")) { if (knn->TreeType() != KNNModel::SPILL_TREE && knn->Epsilon() == 0) Log::Warn << PRINT_PARAM_STRING("true_distances") << "specified, but " @@ -352,12 +358,12 @@ static void mlpackMain() << "error!" << endl; arma::mat trueDistances = - std::move(IO::GetParam("true_distances")); + std::move(params.Get("true_distances")); if (trueDistances.n_rows != distances.n_rows || trueDistances.n_cols != distances.n_cols) { - if (IO::HasParam("reference")) + if (params.Has("reference")) delete knn; Log::Fatal << "The true distances file must have the same number of " << "values than the set of distances being queried!" << endl; @@ -368,7 +374,7 @@ static void mlpackMain() } // Calculate the recall, if desired. - if (IO::HasParam("true_neighbors")) + if (params.Has("true_neighbors")) { if (knn->TreeType() != KNNModel::SPILL_TREE && knn->Epsilon() == 0) Log::Warn << PRINT_PARAM_STRING("true_neighbors") << " specified, but " @@ -376,12 +382,12 @@ static void mlpackMain() << "recall!" << endl; arma::Mat trueNeighbors = - std::move(IO::GetParam>("true_neighbors")); + std::move(params.Get>("true_neighbors")); if (trueNeighbors.n_rows != neighbors.n_rows || trueNeighbors.n_cols != neighbors.n_cols) { - if (IO::HasParam("reference")) + if (params.Has("reference")) delete knn; Log::Fatal << "The true neighbors file must have the same number of " << "values than the set of neighbors being queried!" << endl; @@ -391,9 +397,9 @@ static void mlpackMain() } // Save output. - IO::GetParam>("neighbors") = std::move(neighbors); - IO::GetParam("distances") = std::move(distances); + params.Get>("neighbors") = std::move(neighbors); + params.Get("distances") = std::move(distances); } - IO::GetParam("output_model") = knn; + params.Get("output_model") = knn; } diff --git a/src/mlpack/methods/nmf/nmf_main.cpp b/src/mlpack/methods/nmf/nmf_main.cpp index 56066a673b..a5faf8809e 100644 --- a/src/mlpack/methods/nmf/nmf_main.cpp +++ b/src/mlpack/methods/nmf/nmf_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME nmf + #include #include @@ -28,7 +34,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Non-negative Matrix Factorization"); +BINDING_USER_NAME("Non-negative Matrix Factorization"); // Short description. BINDING_SHORT_DESC( @@ -113,13 +119,13 @@ void LoadInitialWH(const bool bindingTransposed, arma::mat& w, arma::mat& h) // from amf.Apply() as H, and vice versa. if (bindingTransposed) { - w = IO::GetParam("initial_h"); - h = IO::GetParam("initial_w"); + w = params.Get("initial_h"); + h = params.Get("initial_w"); } else { - h = IO::GetParam("initial_h"); - w = IO::GetParam("initial_w"); + h = params.Get("initial_h"); + w = params.Get("initial_w"); } } @@ -128,13 +134,13 @@ void SaveWH(const bool bindingTransposed, arma::mat&& w, arma::mat&& h) // The same transposition applies when saving. if (bindingTransposed) { - IO::GetParam("w") = std::move(h); - IO::GetParam("h") = std::move(w); + params.Get("w") = std::move(h); + params.Get("h") = std::move(w); } else { - IO::GetParam("h") = std::move(h); - IO::GetParam("w") = std::move(w); + params.Get("h") = std::move(h); + params.Get("w") = std::move(w); } } @@ -144,8 +150,8 @@ void ApplyFactorization(const arma::mat& V, arma::mat& W, arma::mat& H) { - const size_t maxIterations = IO::GetParam("max_iterations"); - const double minResidue = IO::GetParam("min_residue"); + const size_t maxIterations = params.Get("max_iterations"); + const double minResidue = params.Get("min_residue"); SimpleResidueTermination srt(minResidue, maxIterations); @@ -153,7 +159,7 @@ void ApplyFactorization(const arma::mat& V, // BINDING_MATRIX_TRANSPOSED macro, which will be 'true' or 'false'. arma::mat initialW, initialH; LoadInitialWH(BINDING_MATRIX_TRANSPOSED, initialW, initialH); - if (IO::HasParam("initial_w") && IO::HasParam("initial_h")) + if (params.Has("initial_w") && params.Has("initial_h")) { // Initialize W and H with given matrices GivenInitialization ginit = GivenInitialization(initialW, initialH); @@ -162,7 +168,7 @@ void ApplyFactorization(const arma::mat& V, UpdateRuleType> amf(srt, ginit); amf.Apply(V, r, W, H); } - else if (IO::HasParam("initial_w")) + else if (params.Has("initial_w")) { // Merge GivenInitialization and RandomInitialization rules // to initialize W with the given matrix, and H with random noise @@ -176,7 +182,7 @@ void ApplyFactorization(const arma::mat& V, UpdateRuleType> amf(srt, minit); amf.Apply(V, r, W, H); } - else if (IO::HasParam("initial_h")) + else if (params.Has("initial_h")) { // Merge GivenInitialization and RandomInitialization rules // to initialize H with the given matrix, and W with random noise @@ -200,29 +206,30 @@ void ApplyFactorization(const arma::mat& V, } } -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Initialize random seed. - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // Gather parameters. - const size_t r = IO::GetParam("rank"); - const string updateRules = IO::GetParam("update_rules"); + const size_t r = params.Get("rank"); + const string updateRules = params.Get("update_rules"); // Validate parameters. - RequireParamValue("rank", [](int x) { return x > 0; }, true, + RequireParamValue(params, "rank", [](int x) { return x > 0; }, true, "the rank of the factorization must be greater than 0"); - RequireParamInSet("update_rules", { "multdist", "multdiv", "als" }, - true, "unknown update rules"); - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, + RequireParamInSet(params, "update_rules", { "multdist", "multdiv", + "als" }, true, "unknown update rules"); + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, true, "max_iterations must be non-negative"); - RequireAtLeastOnePassed({ "h", "w" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "h", "w" }, false, + "no output will be saved"); - arma::mat V = std::move(IO::GetParam("input")); + arma::mat V = std::move(params.Get("input")); arma::mat W; arma::mat H; diff --git a/src/mlpack/methods/pca/pca_main.cpp b/src/mlpack/methods/pca/pca_main.cpp index 8f5e78d68f..d3c27162a8 100644 --- a/src/mlpack/methods/pca/pca_main.cpp +++ b/src/mlpack/methods/pca/pca_main.cpp @@ -12,6 +12,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME pca + #include #include "pca.hpp" @@ -26,7 +32,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Principal Components Analysis"); +BINDING_USER_NAME("Principal Components Analysis"); // Short description. BINDING_SHORT_DESC( @@ -100,9 +106,9 @@ void RunPCA(arma::mat& dataset, Log::Info << "Performing PCA on dataset..." << endl; double varRetained; - if (IO::HasParam("var_to_retain")) + if (params.Has("var_to_retain")) { - if (IO::HasParam("new_dimensionality")) + if (params.Has("new_dimensionality")) Log::Warn << "New dimensionality (-d) ignored because --var_to_retain " << "(-r) was specified." << endl; @@ -117,39 +123,41 @@ void RunPCA(arma::mat& dataset, dataset.n_rows << " dimensions)." << endl; } -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Load input dataset. - arma::mat& dataset = IO::GetParam("input"); + arma::mat& dataset = params.Get("input"); // Issue a warning if the user did not specify an output file. - RequireAtLeastOnePassed({ "output" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no output will be saved"); // Check decomposition method validity. - RequireParamInSet("decomposition_method", { "exact", "randomized", - "randomized-block-krylov", "quic" }, true, + RequireParamInSet(params, "decomposition_method", + { "exact", "randomized", "randomized-block-krylov", "quic" }, true, "unknown decomposition method"); // Find out what dimension we want. - RequireParamValue("new_dimensionality", [](int x) { return x >= 0; }, + RequireParamValue(params, "new_dimensionality", + [](int x) { return x >= 0; }, true, "new dimensionality must be non-negative"); std::ostringstream error; error << "cannot be greater than existing dimensionality (" << dataset.n_rows << ")"; - RequireParamValue("new_dimensionality", + RequireParamValue(params, "new_dimensionality", [dataset](int x) { return x <= (int) dataset.n_rows; }, true, error.str()); - RequireParamValue("var_to_retain", + RequireParamValue(params, "var_to_retain", [](double x) { return x >= 0.0 && x <= 1.0; }, true, "variance retained must be between 0 and 1"); - size_t newDimension = (IO::GetParam("new_dimensionality") == 0) ? - dataset.n_rows : IO::GetParam("new_dimensionality"); + size_t newDimension = (params.Get("new_dimensionality") == 0) ? + dataset.n_rows : params.Get("new_dimensionality"); // Get the options for running PCA. - const bool scale = IO::HasParam("scale"); - const double varToRetain = IO::GetParam("var_to_retain"); - const string decompositionMethod = IO::GetParam( + const bool scale = params.Has("scale"); + const double varToRetain = params.Get("var_to_retain"); + const string decompositionMethod = params.Get( "decomposition_method"); // Perform PCA. @@ -172,6 +180,6 @@ static void mlpackMain() } // Now save the results. - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(dataset); + if (params.Has("output")) + params.Get("output") = std::move(dataset); } diff --git a/src/mlpack/methods/perceptron/perceptron_main.cpp b/src/mlpack/methods/perceptron/perceptron_main.cpp index d2e8682730..d66d706d74 100644 --- a/src/mlpack/methods/perceptron/perceptron_main.cpp +++ b/src/mlpack/methods/perceptron/perceptron_main.cpp @@ -14,8 +14,14 @@ */ #include #include -#include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME perceptron + #include +#include #include "perceptron.hpp" @@ -26,7 +32,7 @@ using namespace std; using namespace arma; // Program Name. -BINDING_NAME("Perceptron"); +BINDING_USER_NAME("Perceptron"); // Short description. BINDING_SHORT_DESC( @@ -149,34 +155,34 @@ PARAM_UROW_OUT("output", "The matrix in which the predicted labels for the" PARAM_UROW_OUT("predictions", "The matrix in which the predicted labels for the" " test set will be written.", "P"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // First, get all parameters and validate them. - const size_t maxIterations = (size_t) IO::GetParam("max_iterations"); + const size_t maxIterations = (size_t) params.Get("max_iterations"); // We must either load a model or train a model. - RequireAtLeastOnePassed({ "input_model", "training" }, true); + RequireAtLeastOnePassed(params, { "input_model", "training" }, true); // If the user isn't going to save the output model or any predictions, we // should issue a warning. - RequireAtLeastOnePassed({ "output_model", "output", "predictions" }, false, - "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "output", "predictions" }, + false, "no output will be saved"); // "output" will be removed in mlpack 4.0.0. - ReportIgnoredParam({{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); // Check parameter validity. - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, true, "maximum number of iterations must be nonnegative"); // Now, load our model, if there is one. PerceptronModel* p; - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { Log::Info << "Using saved perceptron from " - << IO::GetPrintableParam("input_model") << "." + << params.GetPrintable("input_model") << "." << endl; - p = IO::GetParam("input_model"); + p = params.Get("input_model"); } else { @@ -184,18 +190,18 @@ static void mlpackMain() } // Next, load the training data and labels (if they have been given). - if (IO::HasParam("training")) + if (params.Has("training")) { // Get and cache the value of GetPrintableParam("training"). std::ostringstream oss; - oss << IO::GetPrintableParam("training"); + oss << params.GetPrintable("training"); std::string trainingOutput = oss.str(); Log::Info << "Training perceptron on dataset '" << trainingOutput; - if (IO::HasParam("labels")) + if (params.Has("labels")) { Log::Info << "' with labels in '" - << IO::GetPrintableParam>("labels") << "'"; + << params.GetPrintable>("labels") << "'"; } else { @@ -204,21 +210,21 @@ static void mlpackMain() Log::Info << " for a maximum of " << maxIterations << " iterations." << endl; - mat trainingData = std::move(IO::GetParam("training")); + mat trainingData = std::move(params.Get("training")); // Load labels. Row labelsIn; // Did the user pass in labels? - if (IO::HasParam("labels")) + if (params.Has("labels")) { - labelsIn = std::move(IO::GetParam>("labels")); + labelsIn = std::move(params.Get>("labels")); // Checking the size of the responses and training data. if (labelsIn.n_cols != trainingData.n_cols) { // Clean memory if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete p; Log::Fatal << "The responses must have the same number of columns " @@ -231,7 +237,7 @@ static void mlpackMain() if (trainingData.n_rows < 2) { // Clean memory if needed. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete p; Log::Fatal << "Can't get responses from training data " @@ -253,7 +259,7 @@ static void mlpackMain() // Now, if we haven't already created a perceptron, do it. Otherwise, make // sure the dimensions are right, then continue training. - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) { // Create and train the classifier. Timer::Start("training"); @@ -266,7 +272,7 @@ static void mlpackMain() if (p->P().Weights().n_rows != trainingData.n_rows) { Log::Fatal << "Perceptron from '" - << IO::GetPrintableParam("input_model") + << params.GetPrintable("input_model") << "' is built on data with " << p->P().Weights().n_rows << " dimensions, but data in '" << trainingOutput << "' has " << trainingData.n_rows << "dimensions!" << endl; @@ -276,7 +282,7 @@ static void mlpackMain() if (numClasses > p->P().Weights().n_cols) { Log::Fatal << "Perceptron from '" - << IO::GetPrintableParam("input_model") << "' " + << params.GetPrintable("input_model") << "' " << "has " << p->P().Weights().n_cols << " classes, but the training" << " data has " << numClasses + 1 << " classes!" << endl; } @@ -290,17 +296,17 @@ static void mlpackMain() } // Now, the training procedure is complete. Do we have any test data? - if (IO::HasParam("test")) + if (params.Has("test")) { Log::Info << "Classifying dataset '" - << IO::GetPrintableParam("test") << "'." << endl; - mat testData = std::move(IO::GetParam("test")); + << params.GetPrintable("test") << "'." << endl; + mat testData = std::move(params.Get("test")); if (testData.n_rows != p->P().Weights().n_rows) { // Clean memory if needed. const size_t perceptronDimensionality = p->P().Weights().n_rows; - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete p; Log::Fatal << "Test data dimensionality (" << testData.n_rows << ") must " @@ -319,12 +325,12 @@ static void mlpackMain() data::RevertLabels(predictedLabels, p->Map(), results); // Save the predicted labels. - if (IO::HasParam("output")) - IO::GetParam>("output") = results; - if (IO::HasParam("predictions")) - IO::GetParam>("predictions") = std::move(results); + if (params.Has("output")) + params.Get>("output") = results; + if (params.Has("predictions")) + params.Get>("predictions") = std::move(results); } // Lastly, save the output model. - IO::GetParam("output_model") = p; + params.Get("output_model") = p; } diff --git a/src/mlpack/methods/preprocess/image_converter_main.cpp b/src/mlpack/methods/preprocess/image_converter_main.cpp index 22bc727a59..16c48bc954 100644 --- a/src/mlpack/methods/preprocess/image_converter_main.cpp +++ b/src/mlpack/methods/preprocess/image_converter_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME image_converter + #include #include @@ -21,7 +27,7 @@ using namespace std; using namespace mlpack::data; // Program Name. -BINDING_NAME("Image Converter"); +BINDING_USER_NAME("Image Converter"); // Short description. BINDING_SHORT_DESC( @@ -80,45 +86,48 @@ PARAM_INT_IN("height", "Height of the images.", "H", 0); PARAM_FLAG("save", "Save a dataset as images.", "s"); PARAM_MATRIX_IN("dataset", "Input matrix to save as images.", "I"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - Timer::Start("Loading/Saving Image"); // Parse command line options. - const vector fileNames = IO::GetParam >("input"); + const vector fileNames = params.Get >("input"); arma::mat out; - if (!IO::HasParam("save")) + if (!params.Has("save")) { - ReportIgnoredParam("width", "Width of image is determined from file."); - ReportIgnoredParam("height", "Height of image is determined from file."); - ReportIgnoredParam("channels", "Number of channels determined from file."); + ReportIgnoredParam(params, "width", "Width of image is determined from " + "file."); + ReportIgnoredParam(params, "height", "Height of image is determined from " + "file."); + ReportIgnoredParam(params, "channels", "Number of channels determined from " + "file."); data::ImageInfo info; Load(fileNames, out, info, true); - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(out); + if (params.Has("output")) + params.Get("output") = std::move(out); } else { - RequireNoneOrAllPassed({ "save", "width", "height", "channels", "dataset" } - , true, "Image size information is needed when 'save' is specified!"); + RequireNoneOrAllPassed(params, { "save", "width", "height", "channels", + "dataset" } , true, "Image size information is needed when 'save' is " + "specified!"); // Positive value for width. - RequireParamValue("width", [](int x) { return x >= 0;}, true, + RequireParamValue(params, "width", [](int x) { return x >= 0;}, true, "width must be positive"); // Positive value for height. - RequireParamValue("height", [](int x) { return x >= 0;}, true, + RequireParamValue(params, "height", [](int x) { return x >= 0;}, true, "height must be positive"); // Positive value for channel. - RequireParamValue("channels", [](int x) { return x >= 0;}, true, - "channels must be positive"); + RequireParamValue(params, "channels", [](int x) { return x >= 0;}, + true, "channels must be positive"); // Positive value for quality. - RequireParamValue("quality", [](int x) { return x >= 0;}, true, + RequireParamValue(params, "quality", [](int x) { return x >= 0;}, true, "quality must be positive"); - const size_t height = IO::GetParam("height"); - const size_t width = IO::GetParam("width"); - const size_t channels = IO::GetParam("channels"); - const size_t quality = IO::GetParam("quality"); + const size_t height = params.Get("height"); + const size_t width = params.Get("width"); + const size_t channels = params.Get("channels"); + const size_t quality = params.Get("quality"); data::ImageInfo info(width, height, channels, quality); - Save(fileNames, IO::GetParam("dataset"), info, true); + Save(fileNames, params.Get("dataset"), info, true); } } diff --git a/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp b/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp index f47e623e27..171a0f02db 100644 --- a/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp @@ -11,11 +11,17 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME preprocess_binarize + #include #include // Program Name. -BINDING_NAME("Binarize Data"); +BINDING_USER_NAME("Binarize Data"); // Short description. BINDING_SHORT_DESC( @@ -72,41 +78,42 @@ using namespace mlpack::util; using namespace arma; using namespace std; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - const size_t dimension = (size_t) IO::GetParam("dimension"); - const double threshold = IO::GetParam("threshold"); + const size_t dimension = (size_t) params.Get("dimension"); + const double threshold = params.Get("threshold"); // Check on data parameters. - if (!IO::HasParam("dimension")) + if (!params.Has("dimension")) { Log::Warn << "You did not specify " << PRINT_PARAM_STRING("dimension") << ", so the program will perform binarization on every dimension." << endl; } - if (!IO::HasParam("threshold")) + if (!params.Has("threshold")) { Log::Warn << "You did not specify " << PRINT_PARAM_STRING("threshold") << ", so the threshold will be automatically set to '0.0'." << endl; } - RequireAtLeastOnePassed({ "output" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output" }, false, + "no output will be saved"); // Load the data. - arma::mat input = std::move(IO::GetParam("input")); + arma::mat input = std::move(params.Get("input")); arma::mat output; - RequireParamValue("dimension", [](int x) { return x >= 0; }, true, - "dimension to binarize must be nonnegative"); + RequireParamValue(params, "dimension", [](int x) { return x >= 0; }, + true, "dimension to binarize must be nonnegative"); std::ostringstream error; error << "dimension to binarize must be less than the number of dimensions " << "of the input data (" << input.n_rows << ")"; - RequireParamValue("dimension", + RequireParamValue(params, "dimension", [input](int x) { return size_t(x) < input.n_rows; }, true, error.str()); - Timer::Start("binarize"); - if (IO::HasParam("dimension")) + timers.Start(("binarize"); + if (params.Has("dimension")) { data::Binarize(input, output, threshold, dimension); } @@ -115,8 +122,8 @@ static void mlpackMain() // Binarize the whole dataset. data::Binarize(input, output, threshold); } - Timer::Stop("binarize"); + timers.Stop("binarize"); - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(output); + if (params.Has("output")) + params.Get("output") = std::move(output); } diff --git a/src/mlpack/methods/preprocess/preprocess_describe_main.cpp b/src/mlpack/methods/preprocess/preprocess_describe_main.cpp index 316cdd2ef9..72297d8f17 100644 --- a/src/mlpack/methods/preprocess/preprocess_describe_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_describe_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME preprocess_describe + #include #include @@ -23,7 +29,7 @@ using namespace std; using namespace boost; // Program Name. -BINDING_NAME("Descriptive Statistics"); +BINDING_USER_NAME("Descriptive Statistics"); // Short description. BINDING_SHORT_DESC( @@ -170,16 +176,16 @@ double StandardError(const size_t size, const double& fStd) return fStd / sqrt(size); } -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - const size_t dimension = static_cast(IO::GetParam("dimension")); - const size_t precision = static_cast(IO::GetParam("precision")); - const size_t width = static_cast(IO::GetParam("width")); - const bool population = IO::HasParam("population"); - const bool rowMajor = IO::HasParam("row_major"); + const size_t dimension = static_cast(params.Get("dimension")); + const size_t precision = static_cast(params.Get("precision")); + const size_t width = static_cast(params.Get("width")); + const bool population = params.Has("population"); + const bool rowMajor = params.Has("row_major"); // Load the data. - arma::mat& data = IO::GetParam("input"); + arma::mat& data = params.Get("input"); // Generate boost format recipe. const string widthPrecision("%-" + to_string(width) + "." + @@ -195,7 +201,7 @@ static void mlpackMain() numberFormat += widthPrecision + "f"; } - Timer::Start("statistics"); + timers.Start(("statistics"); // Print the headers. Log::Info << boost::format(stringFormat) % "dim" % "var" % "mean" % "std" % "median" % "min" % "max" @@ -234,7 +240,7 @@ static void mlpackMain() // If the user specified dimension, describe statistics of the given // dimension. If a dimension is not specified, describe all dimensions. - if (IO::HasParam("dimension")) + if (params.Has("dimension")) { PrintStatResults(dimension, rowMajor); } @@ -246,5 +252,5 @@ static void mlpackMain() PrintStatResults(i, rowMajor); } } - Timer::Stop("statistics"); + timers.Stop("statistics"); } diff --git a/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp b/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp index 374f03d02a..e85042db32 100644 --- a/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp @@ -10,9 +10,15 @@ * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ #include -#include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME preprocess_imputer + #include +#include #include #include #include @@ -23,7 +29,7 @@ #include // Program Name. -BINDING_NAME("Impute Data"); +BINDING_USER_NAME("Impute Data"); // Short description. BINDING_SHORT_DESC( @@ -72,30 +78,36 @@ using namespace arma; using namespace std; using namespace data; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - const string inputFile = IO::GetParam("input_file"); - const string outputFile = IO::GetParam("output_file"); - const string missingValue = IO::GetParam("missing_value"); - const double customValue = IO::GetParam("custom_value"); - const size_t dimension = (size_t) IO::GetParam("dimension"); - string strategy = IO::GetParam("strategy"); + const string inputFile = params.Get("input_file"); + const string outputFile = params.Get("output_file"); + const string missingValue = params.Get("missing_value"); + const double customValue = params.Get("custom_value"); + const size_t dimension = (size_t) params.Get("dimension"); + string strategy = params.Get("strategy"); - RequireParamInSet("strategy", { "custom", "mean", "median", + RequireParamInSet(params, "strategy", { "custom", "mean", "median", "listwise_deletion" }, true, "unknown imputation strategy"); - RequireAtLeastOnePassed({ "output_file" }, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_file" }, false, + "no output will be saved"); - if (!IO::HasParam("dimension")) + if (!params.Has("dimension")) { Log::Warn << "--dimension is not specified; the imputation will be " << "applied to all dimensions."<< endl; } if (strategy != "custom") - ReportIgnoredParam("custom_value", "not using custom imputation strategy"); + { + ReportIgnoredParam(params, "custom_value", "not using custom imputation " + "strategy"); + } else - RequireAtLeastOnePassed({ "custom_value" }, true, "must pass custom " - "imputation value when using 'custom' imputation strategy"); + { + RequireAtLeastOnePassed(params, { "custom_value" }, true, "must pass " + "custom imputation value when using 'custom' imputation strategy"); + } arma::mat input; // Policy tells how the DatasetMapper should map the values. @@ -125,7 +137,7 @@ static void mlpackMain() Log::Warn << "The file does not contain any user-defined missing " << "variables. The program did not perform any imputation." << endl; } - else if (IO::HasParam("dimension") && + else if (params.Has("dimension") && !(std::find(dirtyDimensions.begin(), dirtyDimensions.end(), dimension) != dirtyDimensions.end())) { @@ -135,8 +147,8 @@ static void mlpackMain() } else { - Timer::Start("imputation"); - if (IO::HasParam("dimension")) + timers.Start(("imputation"); + if (params.Has("dimension")) { // when --dimension is specified, // the program will apply the changes to only the given dimension. @@ -210,7 +222,7 @@ static void mlpackMain() << "exist!" << endl; } } - Timer::Stop("imputation"); + timers.Stop("imputation"); if (!outputFile.empty()) { diff --git a/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp b/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp index 2a15196989..adf5a3e9ea 100644 --- a/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp @@ -11,12 +11,18 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME preprocess_one_hot_encoding + #include #include #include // Program Name. -BINDING_NAME("One Hot Encoding"); +BINDING_USER_NAME("One Hot Encoding"); // Short description. BINDING_SHORT_DESC("A utility to do one-hot encoding on features of dataset."); @@ -59,13 +65,14 @@ using namespace mlpack::util; using namespace arma; using namespace std; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Load the data. - const arma::mat& data = IO::GetParam("input"); - vector& indices = IO::GetParam >("dimensions"); + const arma::mat& data = params.Get("input"); + vector& indices = params.Get >("dimensions"); vector copyIndices(indices.size()); - RequireParamValue>("dimensions", [data](std::vector x) + RequireParamValue>(params, "dimensions", + [data](std::vector x) { for (int dim : x) { @@ -75,14 +82,15 @@ static void mlpackMain() } } return true; - }, true, "dimensions must be greater than 0 " - "and less than the number of dimensions"); + }, true, "dimensions must be greater than 0 and less than the number of " + "dimensions"); + for (size_t i = 0; i < indices.size(); ++i) { copyIndices[i] = (size_t)indices[i]; } arma::mat output; data::OneHotEncoding(data, (arma::Col)(copyIndices), output); - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(output); + if (params.Has("output")) + params.Get("output") = std::move(output); } diff --git a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp index 1c4759f0a9..09f428c068 100644 --- a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME preprocess_scale + #include #include #include @@ -29,7 +35,7 @@ using namespace arma; using namespace std; // Program Name. -BINDING_NAME("Scale Data"); +BINDING_USER_NAME("Scale Data"); // Short description. BINDING_SHORT_DESC( @@ -110,37 +116,37 @@ PARAM_FLAG("inverse_scaling", "Inverse Scaling to get original dataset", "f"); PARAM_MODEL_IN(ScalingModel, "input_model", "Input Scaling model.", "m"); PARAM_MODEL_OUT(ScalingModel, "output_model", "Output scaling model.", "M"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Parse command line options. - const std::string scalerMethod = IO::GetParam("scaler_method"); + const std::string scalerMethod = params.Get("scaler_method"); - if (IO::GetParam("seed") == 0) + if (params.Get("seed") == 0) mlpack::math::RandomSeed(std::time(NULL)); else - mlpack::math::RandomSeed((size_t) IO::GetParam("seed")); + mlpack::math::RandomSeed((size_t) params.Get("seed")); // Make sure the user specified output filenames. - RequireAtLeastOnePassed({ "output", "output_model"}, false, + RequireAtLeastOnePassed(params, { "output", "output_model"}, false, "no output will be saved"); // Check scaler method. - RequireParamInSet("scaler_method", { "min_max_scaler", + RequireParamInSet(params, "scaler_method", { "min_max_scaler", "standard_scaler", "max_abs_scaler", "mean_normalization", "pca_whitening", "zca_whitening" }, true, "unknown scaler type"); // Load the data. - arma::mat& input = IO::GetParam("input"); + arma::mat& input = params.Get("input"); arma::mat output; ScalingModel* m; - Timer::Start("feature_scaling"); - if (IO::HasParam("input_model")) + timers.Start(("feature_scaling"); + if (params.Has("input_model")) { - m = IO::GetParam("input_model"); + m = params.Get("input_model"); } else { - m = new ScalingModel(IO::GetParam("min_value"), - IO::GetParam("max_value"), IO::GetParam("epsilon")); + m = new ScalingModel(params.Get("min_value"), + params.Get("max_value"), params.Get("epsilon")); if (scalerMethod == "standard_scaler") { @@ -180,13 +186,13 @@ static void mlpackMain() } } - if (!IO::HasParam("inverse_scaling")) + if (!params.Has("inverse_scaling")) { m->Transform(input, output); } else { - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) { delete m; throw std::runtime_error("Please provide a saved model."); @@ -195,9 +201,9 @@ static void mlpackMain() } // Save the output. - if (IO::HasParam("output")) - IO::GetParam("output") = std::move(output); - Timer::Stop("feature_scaling"); + if (params.Has("output")) + params.Get("output") = std::move(output); + timers.Stop("feature_scaling"); - IO::GetParam("output_model") = m; + params.Get("output_model") = m; } diff --git a/src/mlpack/methods/preprocess/preprocess_split_main.cpp b/src/mlpack/methods/preprocess/preprocess_split_main.cpp index 8b935e16db..1163c23747 100644 --- a/src/mlpack/methods/preprocess/preprocess_split_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_split_main.cpp @@ -11,12 +11,18 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME preprocess_split + #include #include #include // Program Name. -BINDING_NAME("Split Data"); +BINDING_USER_NAME("Split Data"); // Short description. BINDING_SHORT_DESC( @@ -105,87 +111,88 @@ using namespace mlpack::util; using namespace arma; using namespace std; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Parse command line options. - const double testRatio = IO::GetParam("test_ratio"); - const bool shuffleData = IO::GetParam("no_shuffle"); - const bool stratifyData = IO::GetParam("stratify_data"); + const double testRatio = params.Get("test_ratio"); + const bool shuffleData = params.Get("no_shuffle"); + const bool stratifyData = params.Get("stratify_data"); - if (IO::GetParam("seed") == 0) + if (params.Get("seed") == 0) mlpack::math::RandomSeed(std::time(NULL)); else - mlpack::math::RandomSeed((size_t) IO::GetParam("seed")); + mlpack::math::RandomSeed((size_t) params.Get("seed")); // Make sure the user specified output filenames. - RequireAtLeastOnePassed({ "training" }, false, "no training set will be " + RequireAtLeastOnePassed(params, { "training" }, false, "no training set will " + "be saved"); + RequireAtLeastOnePassed(params, { "test" }, false, "no test set will be " "saved"); - RequireAtLeastOnePassed({ "test" }, false, "no test set will be saved"); // Check on label parameters. - if (IO::HasParam("input_labels")) + if (params.Has("input_labels")) { - RequireAtLeastOnePassed({ "training_labels" }, false, "no training set " + RequireAtLeastOnePassed(params, { "training_labels" }, false, "no training " + "set labels will be saved"); + RequireAtLeastOnePassed(params, { "test_labels" }, false, "no test set " "labels will be saved"); - RequireAtLeastOnePassed({ "test_labels" }, false, "no test set labels will " - "be saved"); } else { - ReportIgnoredParam({{ "input_labels", true }}, "training_labels"); - ReportIgnoredParam({{ "input_labels", true }}, "test_labels"); + ReportIgnoredParam(params, {{ "input_labels", true }}, "training_labels"); + ReportIgnoredParam(params, {{ "input_labels", true }}, "test_labels"); } // Check test_ratio. - RequireParamValue("test_ratio", + RequireParamValue(params, "test_ratio", [](double x) { return x >= 0.0 && x <= 1.0; }, true, "test ratio must be between 0.0 and 1.0"); // Load the data. - arma::mat& data = IO::GetParam("input"); + arma::mat& data = params.Get("input"); // If parameters for labels exist, we must split the labels too. - if (IO::HasParam("input_labels")) + if (params.Has("input_labels")) { arma::Mat& labels = - IO::GetParam>("input_labels"); + params.Get>("input_labels"); arma::Row labelsRow = labels.row(0); - Timer::Start("splitting_data"); + timers.Start(("splitting_data"); const auto value = data::Split(data, labelsRow, testRatio, !shuffleData, stratifyData); - Timer::Stop("splitting_data"); + timers.Stop("splitting_data"); Log::Info << "Training data contains " << get<0>(value).n_cols << " points." << endl; Log::Info << "Test data contains " << get<1>(value).n_cols << " points." << endl; - if (IO::HasParam("training")) - IO::GetParam("training") = std::move(get<0>(value)); - if (IO::HasParam("test")) - IO::GetParam("test") = std::move(get<1>(value)); - if (IO::HasParam("training_labels")) - IO::GetParam>("training_labels") = + if (params.Has("training")) + params.Get("training") = std::move(get<0>(value)); + if (params.Has("test")) + params.Get("test") = std::move(get<1>(value)); + if (params.Has("training_labels")) + params.Get>("training_labels") = std::move(get<2>(value)); - if (IO::HasParam("test_labels")) - IO::GetParam>("test_labels") = + if (params.Has("test_labels")) + params.Get>("test_labels") = std::move(get<3>(value)); } else // We have no labels, so just split the dataset. { - Timer::Start("splitting_data"); + timers.Start(("splitting_data"); const auto value = data::Split(data, testRatio, !shuffleData); - Timer::Stop("splitting_data"); + timers.Stop("splitting_data"); Log::Info << "Training data contains " << get<0>(value).n_cols << " points." << endl; Log::Info << "Test data contains " << get<1>(value).n_cols << " points." << endl; - if (IO::HasParam("training")) - IO::GetParam("training") = std::move(get<0>(value)); - if (IO::HasParam("test")) - IO::GetParam("test") = std::move(get<1>(value)); + if (params.Has("training")) + params.Get("training") = std::move(get<0>(value)); + if (params.Has("test")) + params.Get("test") = std::move(get<1>(value)); } } diff --git a/src/mlpack/methods/radical/radical_main.cpp b/src/mlpack/methods/radical/radical_main.cpp index 1d520d2bcb..1b08d5593c 100644 --- a/src/mlpack/methods/radical/radical_main.cpp +++ b/src/mlpack/methods/radical/radical_main.cpp @@ -12,12 +12,18 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME radical + #include #include #include "radical.hpp" // Program Name. -BINDING_NAME("RADICAL"); +BINDING_USER_NAME("RADICAL"); // Short description. BINDING_SHORT_DESC( @@ -81,36 +87,36 @@ using namespace mlpack::util; using namespace std; using namespace arma; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Set random seed. - if (IO::GetParam("seed") != 0) - RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + RandomSeed((size_t) params.Get("seed")); else RandomSeed((size_t) std::time(NULL)); - RequireAtLeastOnePassed({ "output_ic", "output_unmixing" }, false, "no output" - " will be saved"); + RequireAtLeastOnePassed(params, { "output_ic", "output_unmixing" }, false, + "no output will be saved"); // Check validity of parameters. - RequireParamValue("replicates", [](int x) { return x > 0; }, true, - "number of replicates must be positive"); - RequireParamValue("noise_std_dev", [](double x) { return x >= 0.0; }, - true, "standard deviation of Gaussian noise must be greater than or equal" - " to 0"); - RequireParamValue("angles", [](int x) { return x > 0; }, true, + RequireParamValue(params, "replicates", [](int x) { return x > 0; }, + true, "number of replicates must be positive"); + RequireParamValue(params, "noise_std_dev", + [](double x) { return x >= 0.0; }, true, "standard deviation of Gaussian " + "noise must be greater than or equal to 0"); + RequireParamValue(params, "angles", [](int x) { return x > 0; }, true, "number of angles must be positive"); - RequireParamValue("sweeps", [](int x) { return x >= 0; }, true, + RequireParamValue(params, "sweeps", [](int x) { return x >= 0; }, true, "number of sweeps must be 0 or greater"); // Load the data. - mat matX = std::move(IO::GetParam("input")); + mat matX = std::move(params.Get("input")); // Load parameters. - double noiseStdDev = IO::GetParam("noise_std_dev"); - size_t nReplicates = IO::GetParam("replicates"); - size_t nAngles = IO::GetParam("angles"); - size_t nSweeps = IO::GetParam("sweeps"); + double noiseStdDev = params.Get("noise_std_dev"); + size_t nReplicates = params.Get("replicates"); + size_t nAngles = params.Get("angles"); + size_t nSweeps = params.Get("sweeps"); if (nSweeps == 0) { @@ -124,13 +130,13 @@ static void mlpackMain() rad.DoRadical(matX, matY, matW); // Save results. - if (IO::HasParam("output_ic")) - IO::GetParam("output_ic") = std::move(matY); + if (params.Has("output_ic")) + params.Get("output_ic") = std::move(matY); - if (IO::HasParam("output_unmixing")) - IO::GetParam("output_unmixing") = std::move(matW); + if (params.Has("output_unmixing")) + params.Get("output_unmixing") = std::move(matW); - if (IO::HasParam("objective")) + if (params.Has("objective")) { // Compute and print objective. mat matYT = trans(matY); diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index c73385a709..886b350d83 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -10,9 +10,16 @@ * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ #include +#include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME random_forest + +#include #include #include -#include using namespace mlpack; using namespace mlpack::tree; @@ -20,7 +27,7 @@ using namespace mlpack::util; using namespace std; // Program Name. -BINDING_NAME("Random forests"); +BINDING_USER_NAME("Random forests"); // Short description. BINDING_SHORT_DESC( @@ -160,83 +167,91 @@ PARAM_MODEL_IN(RandomForestModel, "input_model", "Pre-trained random forest to " PARAM_MODEL_OUT(RandomForestModel, "output_model", "Model to save trained " "random forest to.", "M"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Initialize random seed if needed. - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // Check for incompatible input parameters. - if (!IO::HasParam("warm_start")) - RequireOnlyOnePassed({ "training", "input_model" }, true); - else - // When warm_start is passed, training and input_model must also be passed. - RequireNoneOrAllPassed({"warm_start", "training", "input_model"}, true); - - ReportIgnoredParam({{ "training", false }}, "print_training_accuracy"); - ReportIgnoredParam({{ "test", false }}, "test_labels"); - - RequireAtLeastOnePassed({ "test", "output_model", "print_training_accuracy" }, - false, "the trained forest model will not be used or saved"); - - if (IO::HasParam("training")) + if (!params.Has("warm_start")) { - RequireAtLeastOnePassed({ "labels" }, true, "must pass labels when training" - " set given"); + RequireOnlyOnePassed(params, { "training", "input_model" }, true); + } + else + { + // When warm_start is passed, training and input_model must also be passed. + RequireNoneOrAllPassed(params, {"warm_start", "training", "input_model"}, + true); } - RequireParamValue("num_trees", [](int x) { return x > 0; }, true, + ReportIgnoredParam(params, {{ "training", false }}, + "print_training_accuracy"); + ReportIgnoredParam(params, {{ "test", false }}, "test_labels"); + + RequireAtLeastOnePassed(params, { "test", "output_model", + "print_training_accuracy" }, false, "the trained forest model will not " + "be used or saved"); + + if (params.Has("training")) + { + RequireAtLeastOnePassed(params, { "labels" }, true, "must pass labels when " + "training set given"); + } + + RequireParamValue(params, "num_trees", [](int x) { return x > 0; }, true, "number of trees in forest must be positive"); - ReportIgnoredParam({{ "test", false }}, "predictions"); - ReportIgnoredParam({{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); - RequireParamValue("minimum_leaf_size", [](int x) { return x > 0; }, true, - "minimum leaf size must be greater than 0"); - RequireParamValue("maximum_depth", [](int x) { return x >= 0; }, true, - "maximum depth must not be negative"); - RequireParamValue("subspace_dim", [](int x) { return x >= 0; }, true, - "subspace dimensionality must be nonnegative"); - RequireParamValue("minimum_gain_split", + RequireParamValue(params, "minimum_leaf_size", + [](int x) { return x > 0; }, true, "minimum leaf size must be greater " + "than 0"); + RequireParamValue(params, "maximum_depth", [](int x) { return x >= 0; }, + true, "maximum depth must not be negative"); + RequireParamValue(params, "subspace_dim", [](int x) { return x >= 0; }, + true, "subspace dimensionality must be nonnegative"); + RequireParamValue(params, "minimum_gain_split", [](double x) { return x >= 0.0; }, true, "minimum gain for splitting must be nonnegative"); - ReportIgnoredParam({{ "training", false }}, "num_trees"); - ReportIgnoredParam({{ "training", false }}, "minimum_leaf_size"); + ReportIgnoredParam(params, {{ "training", false }}, "num_trees"); + ReportIgnoredParam(params, {{ "training", false }}, "minimum_leaf_size"); RandomForestModel* rfModel; // Input model is loaded when we are either doing warm-started training or // else we are making predictions only or both. - if (IO::HasParam("input_model")) - rfModel = IO::GetParam("input_model"); + if (params.Has("input_model")) + rfModel = params.Get("input_model"); // Handles the case when we are training new forest from scratch. else rfModel = new RandomForestModel(); - if (IO::HasParam("training")) + if (params.Has("training")) { - Timer::Start("rf_training"); + timers.Start(("rf_training"); // Train the model on the given input data. - arma::mat data = std::move(IO::GetParam("training")); + arma::mat data = std::move(params.Get("training")); arma::Row labels = - std::move(IO::GetParam>("labels")); + std::move(params.Get>("labels")); // Make sure the subspace dimensionality is valid. - RequireParamValue("subspace_dim", + RequireParamValue(params, "subspace_dim", [data](int x) { return (size_t) x <= data.n_rows; }, true, "subspace " "dimensionality must not be greater than data dimensionality"); - const size_t numTrees = (size_t) IO::GetParam("num_trees"); + const size_t numTrees = (size_t) params.Get("num_trees"); const size_t minimumLeafSize = - (size_t) IO::GetParam("minimum_leaf_size"); - const size_t maxDepth = (size_t) IO::GetParam("maximum_depth"); - const double minimumGainSplit = IO::GetParam("minimum_gain_split"); - const size_t randomDims = (IO::GetParam("subspace_dim") == 0) ? + (size_t) params.Get("minimum_leaf_size"); + const size_t maxDepth = (size_t) params.Get("maximum_depth"); + const double minimumGainSplit = params.Get("minimum_gain_split"); + const size_t randomDims = (params.Get("subspace_dim") == 0) ? (size_t) std::sqrt(data.n_rows) : - (size_t) IO::GetParam("subspace_dim"); + (size_t) params.Get("subspace_dim"); MultipleRandomDimensionSelect mrds(randomDims); Log::Info << "Training random forest with " << numTrees << " trees..." @@ -246,14 +261,14 @@ static void mlpackMain() // Train the model. rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize, - minimumGainSplit, maxDepth, IO::HasParam("warm_start"), mrds); + minimumGainSplit, maxDepth, params.Has("warm_start"), mrds); - Timer::Stop("rf_training"); + timers.Stop("rf_training"); // Did we want training accuracy? - if (IO::HasParam("print_training_accuracy")) + if (params.Has("print_training_accuracy")) { - Timer::Start("rf_prediction"); + timers.Start(("rf_prediction"); arma::Row predictions; rfModel->rf.Classify(data, predictions); @@ -262,14 +277,14 @@ static void mlpackMain() Log::Info << correct << " of " << labels.n_elem << " correct on training" << " set (" << (double(correct) / double(labels.n_elem) * 100) << ")." << endl; - Timer::Stop("rf_prediction"); + timers.Stop("rf_prediction"); } } - if (IO::HasParam("test")) + if (params.Has("test")) { - arma::mat testData = std::move(IO::GetParam("test")); - Timer::Start("rf_prediction"); + arma::mat testData = std::move(params.Get("test")); + timers.Start(("rf_prediction"); // Get predictions and probabilities. arma::Row predictions; @@ -277,24 +292,24 @@ static void mlpackMain() rfModel->rf.Classify(testData, predictions, probabilities); // Did we want to calculate test accuracy? - if (IO::HasParam("test_labels")) + if (params.Has("test_labels")) { arma::Row testLabels = - std::move(IO::GetParam>("test_labels")); + std::move(params.Get>("test_labels")); const size_t correct = arma::accu(predictions == testLabels); Log::Info << correct << " of " << testLabels.n_elem << " correct on test" << " set (" << (double(correct) / double(testLabels.n_elem) * 100) << ")." << endl; - Timer::Stop("rf_prediction"); + timers.Stop("rf_prediction"); } // Save the outputs. - IO::GetParam("probabilities") = std::move(probabilities); - IO::GetParam>("predictions") = std::move(predictions); + params.Get("probabilities") = std::move(probabilities); + params.Get>("predictions") = std::move(predictions); } // Save the output model. - IO::GetParam("output_model") = rfModel; + params.Get("output_model") = rfModel; } diff --git a/src/mlpack/methods/range_search/range_search_main.cpp b/src/mlpack/methods/range_search/range_search_main.cpp index 81f1ef9e11..abe95342a0 100644 --- a/src/mlpack/methods/range_search/range_search_main.cpp +++ b/src/mlpack/methods/range_search/range_search_main.cpp @@ -13,6 +13,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME range_search + #include #include #include @@ -28,7 +34,7 @@ using namespace mlpack::metric; using namespace mlpack::util; // Program Name. -BINDING_NAME("Range Search"); +BINDING_USER_NAME("Range Search"); // Short description. BINDING_SHORT_DESC( @@ -114,62 +120,63 @@ PARAM_FLAG("naive", "If true, O(n^2) naive mode is used for computation.", "N"); PARAM_FLAG("single_mode", "If true, single-tree search is used (as opposed to " "dual-tree search).", "S"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. - RequireOnlyOnePassed({ "reference", "input_model" }, true); + RequireOnlyOnePassed(params, { "reference", "input_model" }, true); - ReportIgnoredParam({{ "input_model", true }}, "tree_type"); - ReportIgnoredParam({{ "input_model", true }}, "random_basis"); - ReportIgnoredParam({{ "input_model", true }}, "leaf_size"); - ReportIgnoredParam({{ "input_model", true }}, "naive"); + ReportIgnoredParam(params, {{ "input_model", true }}, "tree_type"); + ReportIgnoredParam(params, {{ "input_model", true }}, "random_basis"); + ReportIgnoredParam(params, {{ "input_model", true }}, "leaf_size"); + ReportIgnoredParam(params, {{ "input_model", true }}, "naive"); // The user must give something to do... - RequireAtLeastOnePassed({ "min", "max", "output_model" }, false, "no results " - "will be saved"); + RequireAtLeastOnePassed(params, { "min", "max", "output_model" }, false, + "no results will be saved"); // If the user specifies a range but not output files, they should be warned. - if (IO::HasParam("min") || IO::HasParam("max")) + if (params.Has("min") || params.Has("max")) { - RequireAtLeastOnePassed({ "neighbors_file", "distances_file" }, false, - "no range search results will be saved"); + RequireAtLeastOnePassed(params, { "neighbors_file", "distances_file" }, + false, "no range search results will be saved"); } - if (!IO::HasParam("min") && !IO::HasParam("max")) + if (!params.Has("min") && !params.Has("max")) { - ReportIgnoredParam("neighbors_file", "no range is specified for searching"); - ReportIgnoredParam("distances_file", "no range is specified for searching"); + ReportIgnoredParam(params, "neighbors_file", "no range is specified for " + "searching"); + ReportIgnoredParam(params, "distances_file", "no range is specified for " + "searching"); } - if (IO::HasParam("input_model") && - (IO::HasParam("min") || IO::HasParam("max"))) + if (params.Has("input_model") && (params.Has("min") || params.Has("max"))) { - RequireAtLeastOnePassed({ "query" }, true, "query set must be passed if " - "searching is to be done"); + RequireAtLeastOnePassed(params, { "query" }, true, "query set must be " + "passed if searching is to be done"); } // Sanity check on leaf size. - int lsInt = IO::GetParam("leaf_size"); - RequireParamValue("leaf_size", [](int x) { return x > 0; }, true, + int lsInt = params.Get("leaf_size"); + RequireParamValue(params, "leaf_size", [](int x) { return x > 0; }, true, "leaf size must be greater than 0"); // We either have to load the reference data, or we have to load the model. RSModel* rs; - const bool naive = IO::HasParam("naive"); - const bool singleMode = IO::HasParam("single_mode"); - if (IO::HasParam("reference")) + const bool naive = params.Has("naive"); + const bool singleMode = params.Has("single_mode"); + if (params.Has("reference")) { // Get all the parameters. - const string treeType = IO::GetParam("tree_type"); - RequireParamInSet("tree_type", { "kd", "cover", "r", "r-star", - "ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "vp", "rp", "max-rp", - "ub", "oct" }, true, "unknown tree type"); - const bool randomBasis = IO::HasParam("random_basis"); + const string treeType = params.Get("tree_type"); + RequireParamInSet(params, "tree_type", { "kd", "cover", "r", + "r-star", "ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "vp", "rp", + "max-rp", "ub", "oct" }, true, "unknown tree type"); + const bool randomBasis = params.Has("random_basis"); rs = new RSModel(); @@ -207,9 +214,9 @@ static void mlpackMain() rs->RandomBasis() = randomBasis; Log::Info << "Using reference data from " - << IO::GetPrintableParam("reference") << "." << endl; + << params.GetPrintable("reference") << "." << endl; - arma::mat referenceSet = std::move(IO::GetParam("reference")); + arma::mat referenceSet = std::move(params.Get("reference")); const size_t leafSize = size_t(lsInt); @@ -218,34 +225,34 @@ static void mlpackMain() else { // Load the model from file. - rs = IO::GetParam("input_model"); + rs = params.Get("input_model"); Log::Info << "Using range search model from '" - << IO::GetPrintableParam("input_model") << "' (" + << params.GetPrintable("input_model") << "' (" << "trained on " << rs->Dataset().n_rows << "x" << rs->Dataset().n_cols << " dataset)." << endl; // Adjust singleMode and naive if necessary. - rs->SingleMode() = IO::HasParam("single_mode"); - rs->Naive() = IO::HasParam("naive"); + rs->SingleMode() = params.Has("single_mode"); + rs->Naive() = params.Has("naive"); rs->LeafSize() = size_t(lsInt); } // Perform search, if desired. - if (IO::HasParam("min") || IO::HasParam("max")) + if (params.Has("min") || params.Has("max")) { - const double min = IO::GetParam("min"); - const double max = IO::HasParam("max") ? IO::GetParam("max") : + const double min = params.Get("min"); + const double max = params.Has("max") ? params.Get("max") : DBL_MAX; math::Range r(min, max); arma::mat queryData; - if (IO::HasParam("query")) + if (params.Has("query")) { Log::Info << "Using query data from " - << IO::GetPrintableParam("query") << "." << endl; - queryData = std::move(IO::GetParam("query")); + << params.GetPrintable("query") << "." << endl; + queryData = std::move(params.Get("query")); } // Naive mode overrides single mode. @@ -257,7 +264,7 @@ static void mlpackMain() vector> neighbors; vector> distances; - if (IO::HasParam("query")) + if (params.Has("query")) rs->Search(std::move(queryData), r, neighbors, distances); else rs->Search(r, neighbors, distances); @@ -265,9 +272,9 @@ static void mlpackMain() Log::Info << "Search complete." << endl; // Save output, if desired. We have to do this by hand. - if (IO::HasParam("distances_file")) + if (params.Has("distances_file")) { - const string distancesFile = IO::GetParam("distances_file"); + const string distancesFile = params.Get("distances_file"); fstream distancesStr(distancesFile.c_str(), fstream::out); if (!distancesStr.is_open()) { @@ -294,9 +301,9 @@ static void mlpackMain() } } - if (IO::HasParam("neighbors_file")) + if (params.Has("neighbors_file")) { - const string neighborsFile = IO::GetParam("neighbors_file"); + const string neighborsFile = params.Get("neighbors_file"); fstream neighborsStr(neighborsFile.c_str(), fstream::out); if (!neighborsStr.is_open()) { @@ -325,5 +332,5 @@ static void mlpackMain() } // Save the output model. - IO::GetParam("output_model") = rs; + params.Get("output_model") = rs; } diff --git a/src/mlpack/methods/rann/krann_main.cpp b/src/mlpack/methods/rann/krann_main.cpp index 0ed34fd0f2..8aaf9f42af 100644 --- a/src/mlpack/methods/rann/krann_main.cpp +++ b/src/mlpack/methods/rann/krann_main.cpp @@ -12,6 +12,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME krann + #include #include "ra_search.hpp" @@ -26,7 +32,7 @@ using namespace mlpack::metric; using namespace mlpack::util; // Program Name. -BINDING_NAME("K-Rank-Approximate-Nearest-Neighbors (kRANN)"); +BINDING_USER_NAME("K-Rank-Approximate-Nearest-Neighbors (kRANN)"); // Short description. BINDING_SHORT_DESC( @@ -118,68 +124,68 @@ PARAM_FLAG("first_leaf_exact", "The flag to trigger sampling only after " PARAM_INT_IN("single_sample_limit", "The limit on the maximum number of " "samples (and hence the largest node you can approximate).", "z", 20); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - math::RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + math::RandomSeed((size_t) params.Get("seed")); else math::RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. - RequireOnlyOnePassed({ "reference", "input_model" }, true); + RequireOnlyOnePassed(params, { "reference", "input_model" }, true); - ReportIgnoredParam({{ "input_model", true }}, "tree_type"); - ReportIgnoredParam({{ "input_model", true }}, "leaf_size"); - ReportIgnoredParam({{ "input_model", true }}, "random_basis"); - ReportIgnoredParam({{ "input_model", true }}, "naive"); + ReportIgnoredParam(params, {{ "input_model", true }}, "tree_type"); + ReportIgnoredParam(params, {{ "input_model", true }}, "leaf_size"); + ReportIgnoredParam(params, {{ "input_model", true }}, "random_basis"); + ReportIgnoredParam(params, {{ "input_model", true }}, "naive"); // The user should give something to do... - RequireAtLeastOnePassed({ "k", "output_model" }, false, "no results will be " - "saved"); + RequireAtLeastOnePassed(params, { "k", "output_model" }, false, + "no results will be saved"); // If the user specifies k but no output files, they should be warned. - if (IO::HasParam("k")) + if (params.Has("k")) { - RequireAtLeastOnePassed({ "neighbors", "distances" }, false, "no nearest " - "neighbor search results will be saved"); + RequireAtLeastOnePassed(params, { "neighbors", "distances" }, false, + "no nearest neighbor search results will be saved"); } // If the user specifies output files but no k, they should be warned. - ReportIgnoredParam({{ "k", false }}, "neighbors"); - ReportIgnoredParam({{ "k", false }}, "distances"); + ReportIgnoredParam(params, {{ "k", false }}, "neighbors"); + ReportIgnoredParam(params, {{ "k", false }}, "distances"); // Naive mode overrides single mode. - ReportIgnoredParam({{ "naive", true }}, "single_mode"); + ReportIgnoredParam(params, {{ "naive", true }}, "single_mode"); // Sanity check on leaf size. - const int lsInt = IO::GetParam("leaf_size"); - RequireParamValue("leaf_size", [](int x) { return x > 0; }, true, + const int lsInt = params.Get("leaf_size"); + RequireParamValue(params, "leaf_size", [](int x) { return x > 0; }, true, "leaf size must be greater than 0"); // Sanity check on tau. - RequireParamValue("tau", [](double x) { + RequireParamValue(params, "tau", [](double x) { return (x >= 0.0 && x <=100.0); }, true, "tau must be in range [0.0, 100.0]"); // Sanity check on alpha. - RequireParamValue("alpha", [](double x) { + RequireParamValue(params, "alpha", [](double x) { return (x >= 0.0 && x <=1.0); }, true, "alpha must be in range [0.0, 1.0]"); // We either have to load the reference data, or we have to load the model. RAModel* rann; - const bool naive = IO::HasParam("naive"); - const bool singleMode = IO::HasParam("single_mode"); - if (IO::HasParam("reference")) + const bool naive = params.Has("naive"); + const bool singleMode = params.Has("single_mode"); + if (params.Has("reference")) { rann = new RAModel(); // Get all the parameters. - const string treeType = IO::GetParam("tree_type"); - RequireParamInSet("tree_type", { "kd", "cover", "r", "r-star", "x", - "hilbert-r", "r-plus", "r-plus-plus", "ub", "oct" }, true, - "unknown tree type"); - const bool randomBasis = IO::HasParam("random_basis"); + const string treeType = params.Get("tree_type"); + RequireParamInSet(params, "tree_type", { "kd", "cover", "r", + "r-star", "x", "hilbert-r", "r-plus", "r-plus-plus", "ub", "oct" }, + true, "unknown tree type"); + const bool randomBasis = params.Has("random_basis"); RAModel::TreeTypes tree = RAModel::KD_TREE; if (treeType == "kd") @@ -207,48 +213,48 @@ static void mlpackMain() rann->RandomBasis() = randomBasis; Log::Info << "Using reference data from " - << IO::GetPrintableParam("reference") << "." << endl; - arma::mat referenceSet = std::move(IO::GetParam("reference")); + << params.GetPrintable("reference") << "." << endl; + arma::mat referenceSet = std::move(params.Get("reference")); rann->BuildModel(std::move(referenceSet), size_t(lsInt), naive, singleMode); } else { // Load the model from file. - rann = IO::GetParam("input_model"); + rann = params.Get("input_model"); Log::Info << "Using rank-approximate kNN model from '" - << IO::GetPrintableParam("input_model") << "' (trained on " + << params.GetPrintable("input_model") << "' (trained on " << rann->Dataset().n_rows << "x" << rann->Dataset().n_cols << " dataset)." << endl; // Adjust singleMode and naive if necessary. - rann->SingleMode() = IO::HasParam("single_mode"); - rann->Naive() = IO::HasParam("naive"); + rann->SingleMode() = params.Has("single_mode"); + rann->Naive() = params.Has("naive"); rann->LeafSize() = size_t(lsInt); } // Apply the parameters for search. - if (IO::HasParam("tau")) - rann->Tau() = IO::GetParam("tau"); - if (IO::HasParam("alpha")) - rann->Alpha() = IO::GetParam("alpha"); - if (IO::HasParam("single_sample_limit")) - rann->SingleSampleLimit() = IO::GetParam("single_sample_limit"); - rann->SampleAtLeaves() = IO::HasParam("sample_at_leaves"); - rann->FirstLeafExact() = IO::HasParam("sample_at_leaves"); + if (params.Has("tau")) + rann->Tau() = params.Get("tau"); + if (params.Has("alpha")) + rann->Alpha() = params.Get("alpha"); + if (params.Has("single_sample_limit")) + rann->SingleSampleLimit() = params.Get("single_sample_limit"); + rann->SampleAtLeaves() = params.Has("sample_at_leaves"); + rann->FirstLeafExact() = params.Has("sample_at_leaves"); // Perform search, if desired. - if (IO::HasParam("k")) + if (params.Has("k")) { - const size_t k = (size_t) IO::GetParam("k"); + const size_t k = (size_t) params.Get("k"); arma::mat queryData; - if (IO::HasParam("query")) + if (params.Has("query")) { - queryData = std::move(IO::GetParam("query")); + queryData = std::move(params.Get("query")); Log::Info << "Using query data from '" - << IO::GetPrintableParam("query") << "' (" + << params.GetPrintable("query") << "' (" << queryData.n_rows << "x" << queryData.n_cols << ")." << endl; if (queryData.n_rows != rann->Dataset().n_rows) { @@ -270,17 +276,17 @@ static void mlpackMain() arma::Mat neighbors; arma::mat distances; - if (IO::HasParam("query")) + if (params.Has("query")) rann->Search(std::move(queryData), k, neighbors, distances); else rann->Search(k, neighbors, distances); Log::Info << "Search complete." << endl; // Save output. - IO::GetParam>("neighbors") = std::move(neighbors); - IO::GetParam("distances") = std::move(distances); + params.Get>("neighbors") = std::move(neighbors); + params.Get("distances") = std::move(distances); } // Save the output model. - IO::GetParam("output_model") = rann; + params.Get("output_model") = rann; } diff --git a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp index 571b239187..1bd70bf85b 100644 --- a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp +++ b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp @@ -10,6 +10,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME softmax_regression + #include #include @@ -24,7 +30,7 @@ using namespace mlpack::regression; using namespace mlpack::util; // Program Name. -BINDING_NAME("Softmax Regression"); +BINDING_USER_NAME("Softmax Regression"); // Short description. BINDING_SHORT_DESC( @@ -138,30 +144,30 @@ void TestClassifyAcc(const size_t numClasses, const Model& model); template Model* TrainSoftmax(const size_t maxIterations); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - const int maxIterations = IO::GetParam("max_iterations"); + const int maxIterations = params.Get("max_iterations"); // One of inputFile and modelFile must be specified. - RequireOnlyOnePassed({ "input_model", "training" }, true); - if (IO::HasParam("training")) + RequireOnlyOnePassed(params, { "input_model", "training" }, true); + if (params.Has("training")) { RequireAtLeastOnePassed({ "labels" }, true, "if training data is specified," " labels must also be specified"); } - ReportIgnoredParam({{ "training", false }}, "labels"); - ReportIgnoredParam({{ "training", false }}, "max_iterations"); - ReportIgnoredParam({{ "training", false }}, "number_of_classes"); - ReportIgnoredParam({{ "training", false }}, "lambda"); - ReportIgnoredParam({{ "training", false }}, "no_intercept"); + ReportIgnoredParam(params, {{ "training", false }}, "labels"); + ReportIgnoredParam(params, {{ "training", false }}, "max_iterations"); + ReportIgnoredParam(params, {{ "training", false }}, "number_of_classes"); + ReportIgnoredParam(params, {{ "training", false }}, "lambda"); + ReportIgnoredParam(params, {{ "training", false }}, "no_intercept"); - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, - "maximum number of iterations must be greater than or equal to 0"); - RequireParamValue("lambda", [](double x) { return x >= 0.0; }, true, - "lambda penalty parameter must be greater than or equal to 0"); - RequireParamValue("number_of_classes", [](int x) { return x >= 0; }, - true, "number of classes must be greater than or " - "equal to 0 (equal to 0 in case of unspecified.)"); + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, + true, "maximum number of iterations must be greater than or equal to 0"); + RequireParamValue(params, "lambda", [](double x) { return x >= 0.0; }, + true, "lambda penalty parameter must be greater than or equal to 0"); + RequireParamValue(params, "number_of_classes", + [](int x) { return x >= 0; }, true, "number of classes must be greater " + "than or equal to 0 (equal to 0 in case of unspecified.)"); // Make sure we have an output file of some sort. RequireAtLeastOnePassed({ "output_model", "predictions" }, false, "no results" @@ -171,7 +177,7 @@ static void mlpackMain() TestClassifyAcc(sm->NumClasses(), *sm); - IO::GetParam("output_model") = sm; + params.Get("output_model") = sm; } size_t CalculateNumberOfClasses(const size_t numClasses, @@ -195,25 +201,25 @@ void TestClassifyAcc(size_t numClasses, const Model& model) using namespace mlpack; // If there is no test set, there is nothing to test on. - if (!IO::HasParam("test")) + if (!params.Has("test")) { - ReportIgnoredParam({{ "test", false }}, "test_labels"); - ReportIgnoredParam({{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "test_labels"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); return; } // Get the test dataset, and get predictions. - arma::mat testData = std::move(IO::GetParam("test")); + arma::mat testData = std::move(params.Get("test")); arma::Row predictLabels; model.Classify(testData, predictLabels); // Calculate accuracy, if desired. - if (IO::HasParam("test_labels")) + if (params.Has("test_labels")) { arma::Row testLabels = - std::move(IO::GetParam>("test_labels")); + std::move(params.Get>("test_labels")); if (testData.n_cols != testLabels.n_elem) { @@ -248,8 +254,8 @@ void TestClassifyAcc(size_t numClasses, const Model& model) << totalBingo << " of " << predictLabels.n_elem << ")." << endl; } // Save predictions, if desired. - if (IO::HasParam("predictions")) - IO::GetParam>("predictions") = std::move(predictLabels); + if (params.Has("predictions")) + params.Get>("predictions") = std::move(predictLabels); } template @@ -258,29 +264,29 @@ Model* TrainSoftmax(const size_t maxIterations) using namespace mlpack; Model* sm; - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { - sm = IO::GetParam("input_model"); + sm = params.Get("input_model"); } else { - arma::mat trainData = std::move(IO::GetParam("training")); + arma::mat trainData = std::move(params.Get("training")); arma::Row trainLabels = - std::move(IO::GetParam>("labels")); + std::move(params.Get>("labels")); if (trainData.n_cols != trainLabels.n_elem) Log::Fatal << "Samples of input_data should same as the size of " << "input_label." << endl; const size_t numClasses = CalculateNumberOfClasses( - (size_t) IO::GetParam("number_of_classes"), trainLabels); + (size_t) params.Get("number_of_classes"), trainLabels); - const bool intercept = IO::HasParam("no_intercept") ? false : true; + const bool intercept = params.Has("no_intercept") ? false : true; const size_t numBasis = 5; ens::L_BFGS optimizer(numBasis, maxIterations); sm = new Model(trainData, trainLabels, numClasses, - IO::GetParam("lambda"), intercept, std::move(optimizer)); + params.Get("lambda"), intercept, std::move(optimizer)); } return sm; } diff --git a/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp b/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp index 15753327b8..8af2603a07 100644 --- a/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp +++ b/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME sparse_coding + #include #include "sparse_coding.hpp" @@ -23,7 +29,7 @@ using namespace mlpack::sparse_coding; using namespace mlpack::util; // Program Name. -BINDING_NAME("Sparse Coding"); +BINDING_USER_NAME("Sparse Coding"); // Short description. BINDING_SHORT_DESC( @@ -124,101 +130,104 @@ PARAM_MATRIX_OUT("codes", "Matrix to save the output sparse codes of the test " PARAM_MATRIX_IN("test", "Optional matrix to be encoded by trained model.", "T"); -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { - if (IO::GetParam("seed") != 0) - RandomSeed((size_t) IO::GetParam("seed")); + if (params.Get("seed") != 0) + RandomSeed((size_t) params.Get("seed")); else RandomSeed((size_t) time(NULL)); // Check for parameter validity. - if (IO::HasParam("input_model") && IO::HasParam("initial_dictionary")) + if (params.Has("input_model") && params.Has("initial_dictionary")) { Log::Fatal << "Can only pass one of " << PRINT_PARAM_STRING("input_model") << " or " << PRINT_PARAM_STRING("initial_dictionary") << "!" << endl; } - if (IO::HasParam("training")) + if (params.Has("training")) { - RequireAtLeastOnePassed({ "atoms" }, true, "if training data is specified, " - "the number of atoms in the dictionary must also be specified"); + RequireAtLeastOnePassed(params, { "atoms" }, true, "if training data is " + "specified, the number of atoms in the dictionary must also be " + "specified"); } - RequireAtLeastOnePassed({ "codes", "dictionary", "output_model" }, false, - "no output will be saved"); + RequireAtLeastOnePassed(params, { "codes", "dictionary", "output_model" }, + false, "no output will be saved"); - ReportIgnoredParam({{ "test", false }}, "codes"); + ReportIgnoredParam(params, {{ "test", false }}, "codes"); - ReportIgnoredParam({{ "training", false }}, "atoms"); - ReportIgnoredParam({{ "training", false }}, "lambda1"); - ReportIgnoredParam({{ "training", false }}, "lambda2"); - ReportIgnoredParam({{ "training", false }}, "initial_dictionary"); - ReportIgnoredParam({{ "training", false }}, "max_iterations"); - ReportIgnoredParam({{ "training", false }}, "normalize"); - ReportIgnoredParam({{ "training", false }}, "objective_tolerance"); - ReportIgnoredParam({{ "training", false }}, "newton_tolerance"); + ReportIgnoredParam(params, {{ "training", false }}, "atoms"); + ReportIgnoredParam(params, {{ "training", false }}, "lambda1"); + ReportIgnoredParam(params, {{ "training", false }}, "lambda2"); + ReportIgnoredParam(params, {{ "training", false }}, "initial_dictionary"); + ReportIgnoredParam(params, {{ "training", false }}, "max_iterations"); + ReportIgnoredParam(params, {{ "training", false }}, "normalize"); + ReportIgnoredParam(params, {{ "training", false }}, "objective_tolerance"); + ReportIgnoredParam(params, {{ "training", false }}, "newton_tolerance"); - RequireParamValue("atoms", [](int x) { return x > 0; }, true, + RequireParamValue(params, "atoms", [](int x) { return x > 0; }, true, "number of atoms must be positive"); - RequireParamValue("lambda1", [](double x) { return x >= 0.0; }, true, - "lambda1 value must be nonnegative"); - RequireParamValue("lambda2", [](double x) { return x >= 0.0; }, true, - "lambda2 value must be nonnegative"); - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, - "maximum number of iterations must be nonnegative"); - RequireParamValue("objective_tolerance", + RequireParamValue(params, "lambda1", + [](double x) { return x >= 0.0; }, true, "lambda1 value must be " + "nonnegative"); + RequireParamValue(params, "lambda2", + [](double x) { return x >= 0.0; }, true, "lambda2 value must be " + "nonnegative"); + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, + true, "maximum number of iterations must be nonnegative"); + RequireParamValue(params, "objective_tolerance", [](double x) { return x >= 0.0; }, true, "objective function tolerance must be nonnegative"); - RequireParamValue("newton_tolerance", + RequireParamValue(params, "newton_tolerance", [](double x) { return x >= 0.0; }, true, "Newton method tolerance must be nonnegative"); // Do we have an existing model? SparseCoding* sc; - if (IO::HasParam("input_model")) - sc = IO::GetParam("input_model"); + if (params.Has("input_model")) + sc = params.Get("input_model"); else sc = new SparseCoding(0, 0.0); - if (IO::HasParam("training")) + if (params.Has("training")) { - mat matX = std::move(IO::GetParam("training")); + mat matX = std::move(params.Get("training")); // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) + if (params.Has("normalize")) { Log::Info << "Normalizing data before coding..." << endl; for (size_t i = 0; i < matX.n_cols; ++i) matX.col(i) /= norm(matX.col(i), 2); } - sc->Lambda1() = IO::GetParam("lambda1"); - sc->Lambda2() = IO::GetParam("lambda2"); - sc->MaxIterations() = (size_t) IO::GetParam("max_iterations"); - sc->Atoms() = (size_t) IO::GetParam("atoms"); - sc->ObjTolerance() = IO::GetParam("objective_tolerance"); - sc->NewtonTolerance() = IO::GetParam("newton_tolerance"); + sc->Lambda1() = params.Get("lambda1"); + sc->Lambda2() = params.Get("lambda2"); + sc->MaxIterations() = (size_t) params.Get("max_iterations"); + sc->Atoms() = (size_t) params.Get("atoms"); + sc->ObjTolerance() = params.Get("objective_tolerance"); + sc->NewtonTolerance() = params.Get("newton_tolerance"); // Inform the user if we are overwriting their model. - if (IO::HasParam("input_model")) + if (params.Has("input_model")) { Log::Info << "Using dictionary from existing model in '" - << IO::GetPrintableParam("input_model") + << params.GetPrintable("input_model") << "' as initial dictionary for training." << endl; sc->Train(matX); } - else if (IO::HasParam("initial_dictionary")) + else if (params.Has("initial_dictionary")) { // Load initial dictionary directly into sparse coding object. sc->Dictionary() = - std::move(IO::GetParam("initial_dictionary")); + std::move(params.Get("initial_dictionary")); // Validate size of initial dictionary. if (sc->Dictionary().n_cols != sc->Atoms()) { const size_t dictAtoms = sc->Dictionary().n_cols; const size_t atoms = sc->Atoms(); - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete sc; Log::Fatal << "The initial dictionary has " << dictAtoms << " atoms, but the number of atoms was specified to be " @@ -228,7 +237,7 @@ static void mlpackMain() if (sc->Dictionary().n_rows != matX.n_rows) { const size_t dim = sc->Dictionary().n_rows; - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete sc; Log::Fatal << "The initial dictionary has " << dim << " dimensions, but the data has " << matX.n_rows << " dimensions!" @@ -246,24 +255,24 @@ static void mlpackMain() } // Now, de we have any matrix to encode? - if (IO::HasParam("test")) + if (params.Has("test")) { - if (IO::GetParam("test").n_rows != sc->Dictionary().n_rows) + if (params.Get("test").n_rows != sc->Dictionary().n_rows) { const size_t dim = sc->Dictionary().n_rows; - if (!IO::HasParam("input_model")) + if (!params.Has("input_model")) delete sc; Log::Fatal << "Model was trained with a dimensionality of " << dim << ", but test data '" - << IO::GetPrintableParam("test") << "' have a " - << "dimensionality of " << IO::GetParam("test").n_rows + << params.GetPrintable("test") << "' have a " + << "dimensionality of " << params.Get("test").n_rows << "!" << endl; } - mat matY = std::move(IO::GetParam("test")); + mat matY = std::move(params.Get("test")); // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) + if (params.Has("normalize")) { Log::Info << "Normalizing test data before coding..." << endl; for (size_t i = 0; i < matY.n_cols; ++i) @@ -273,13 +282,13 @@ static void mlpackMain() mat codes; sc->Encode(matY, codes); - IO::GetParam("codes") = std::move(codes); + params.Get("codes") = std::move(codes); } // Did the user want to save the dictionary? Use an alias for the dictionary. - IO::GetParam("dictionary") = arma::mat(sc->Dictionary().memptr(), + params.Get("dictionary") = arma::mat(sc->Dictionary().memptr(), sc->Dictionary().n_rows, sc->Dictionary().n_cols, false, false); // Save the model. - IO::GetParam("output_model") = sc; + params.Get("output_model") = sc; } From 72e617bca913076dbbe0948aa1b5d2a7b5e0d448 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 1 Jul 2021 21:27:57 +0530 Subject: [PATCH 488/729] Missed semicolon --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index c754e9e7eb..bae167fffc 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -119,7 +119,7 @@ class SSELoss return std::pow(arma::accu(gradients), 2) / (arma::accu(hessians) + lambda); } -} +}; } // namespace ensemble } // namespace mlpack From f974f4e95ea48b7d1aebe6d5192e1a60f6b8b40f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 1 Jul 2021 21:59:16 +0530 Subject: [PATCH 489/729] Start compiling (hopefully) --- src/mlpack/methods/xgboost/CMakeLists.txt | 13 +++++++++++++ .../methods/xgboost/loss_functions/CMakeLists.txt | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/mlpack/methods/xgboost/CMakeLists.txt create mode 100644 src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt diff --git a/src/mlpack/methods/xgboost/CMakeLists.txt b/src/mlpack/methods/xgboost/CMakeLists.txt new file mode 100644 index 0000000000..63339c806e --- /dev/null +++ b/src/mlpack/methods/xgboost/CMakeLists.txt @@ -0,0 +1,13 @@ +# Define the files we need to compile. +# Anything not in this list will not be compiled into mlpack. +set(SOURCES +) + +# Add directory name to sources. +set(DIR_SRCS) +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() +# Append sources (with directory name) to list of all mlpack sources (used at +# the parent scope). +set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt b/src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt new file mode 100644 index 0000000000..30ffd3867e --- /dev/null +++ b/src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt @@ -0,0 +1,14 @@ +# Define the files we need to compile. +# Anything not in this list will not be compiled into mlpack. +set(SOURCES + sse_loss.hpp +) + +# Add directory name to sources. +set(DIR_SRCS) +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() +# Append sources (with directory name) to list of all mlpack sources (used at +# the parent scope). +set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE) From 44f76f0c96d98a05643badf36a05508bc83ce0ff Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 1 Jul 2021 21:59:34 +0530 Subject: [PATCH 490/729] write first test --- src/mlpack/tests/CMakeLists.txt | 1 + src/mlpack/tests/xgboost_test.cpp | 32 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/mlpack/tests/xgboost_test.cpp diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 2119879ab7..3bf2cc0532 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -128,6 +128,7 @@ add_executable(mlpack_test union_find_test.cpp vantage_point_tree_test.cpp wgan_test.cpp + xgboost_test.cpp main_tests/adaboost_test.cpp main_tests/approx_kfn_test.cpp main_tests/bayesian_linear_regression_test.cpp diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp new file mode 100644 index 0000000000..c34b973399 --- /dev/null +++ b/src/mlpack/tests/xgboost_test.cpp @@ -0,0 +1,32 @@ +/** + * @file tests/xgboost_test.cpp + * @author Rishabh Garg + * + * Tests for the XGBoost class and related classes. + * + * 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 "catch.hpp" +#include "serialization.hpp" + +using namespace mlpack; +using namespace mlpack::ensemble; + +/** + * Test that the initial prediction is calculated correctly for SSE loss. + */ +TEST_CASE("SSEInitialPredictionTest", "[XGBTest]") +{ + arma::vec values = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; + + double initPred = 5.5; + + SSELoss Loss; + REQUIRE(Loss.InitialPrediction(values) == initPred); +} From 2f729f551a85f73b0634dfa8e93b2d6a24bc25d2 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 1 Jul 2021 16:21:53 -0400 Subject: [PATCH 491/729] No need for a static function. --- src/mlpack/methods/linear_regression/linear_regression_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/linear_regression/linear_regression_main.cpp b/src/mlpack/methods/linear_regression/linear_regression_main.cpp index a01baf8e63..3af254363e 100644 --- a/src/mlpack/methods/linear_regression/linear_regression_main.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression_main.cpp @@ -114,7 +114,7 @@ PARAM_ROW_OUT("output_predictions", "If --test_file is specified, this " PARAM_DOUBLE_IN("lambda", "Tikhonov regularization for ridge regression. If 0," " the method reduces to linear regression.", "l", 0.0); -static void BINDING_NAME(util::Params& params, util::Timers& timer) +void BINDING_NAME(util::Params& params, util::Timers& timer) { const double lambda = params.Get("lambda"); From 4d4bb895a734beb60d987fe97aeb938f5b8452e6 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 1 Jul 2021 17:08:30 -0400 Subject: [PATCH 492/729] Fix compilation issues (there are still some warnings). --- src/mlpack/methods/CMakeLists.txt | 94 +++++++++---------- src/mlpack/methods/adaboost/adaboost_main.cpp | 17 ++-- .../methods/approx_kfn/approx_kfn_main.cpp | 10 +- src/mlpack/methods/cf/cf_main.cpp | 2 +- src/mlpack/methods/dbscan/dbscan_main.cpp | 30 +++--- src/mlpack/methods/det/det_main.cpp | 10 +- src/mlpack/methods/gmm/gmm_train_main.cpp | 14 +-- src/mlpack/methods/hmm/hmm_generate_main.cpp | 4 +- src/mlpack/methods/hmm/hmm_loglik_main.cpp | 5 +- src/mlpack/methods/hmm/hmm_model.hpp | 11 ++- src/mlpack/methods/hmm/hmm_train_main.cpp | 40 +++++--- src/mlpack/methods/hmm/hmm_viterbi_main.cpp | 5 +- .../hoeffding_trees/hoeffding_tree_main.cpp | 6 +- src/mlpack/methods/kmeans/kmeans_main.cpp | 82 +++++++++++----- .../logistic_regression_main.cpp | 2 +- src/mlpack/methods/lsh/lsh_main.cpp | 2 +- src/mlpack/methods/nmf/nmf_main.cpp | 23 +++-- src/mlpack/methods/pca/pca_main.cpp | 12 ++- .../preprocess/preprocess_binarize_main.cpp | 2 +- .../preprocess/preprocess_describe_main.cpp | 2 +- .../preprocess/preprocess_imputer_main.cpp | 2 +- .../preprocess/preprocess_scale_main.cpp | 2 +- .../preprocess/preprocess_split_main.cpp | 4 +- .../random_forest/random_forest_main.cpp | 6 +- .../softmax_regression_main.cpp | 25 +++-- 25 files changed, 242 insertions(+), 170 deletions(-) diff --git a/src/mlpack/methods/CMakeLists.txt b/src/mlpack/methods/CMakeLists.txt index 3e0fd695b4..4268a2e1bc 100644 --- a/src/mlpack/methods/CMakeLists.txt +++ b/src/mlpack/methods/CMakeLists.txt @@ -1,54 +1,54 @@ # Recurse into each method mlpack provides. set(DIRS # mvu # Note: this implementation of MVU does not work. See #189. - # adaboost - # amf - # ann - # approx_kfn - # bias_svd - # bayesian_linear_regression - # block_krylov_svd - # cf - # dbscan - # decision_tree - # det - # emst - # fastmks - # gmm - # hmm - # hoeffding_trees - # kde - # kernel_pca - # kmeans - # lars + adaboost + amf + ann + approx_kfn + bias_svd + bayesian_linear_regression + block_krylov_svd + cf + dbscan + decision_tree + det + emst + fastmks + gmm + hmm + hoeffding_trees + kde + kernel_pca + kmeans + lars linear_regression - # linear_svm - # lmnn - # local_coordinate_coding - # logistic_regression - # lsh - # matrix_completion - # mean_shift - # naive_bayes - # nca - # neighbor_search - # nmf - # nystroem_method - # pca - # perceptron - # preprocess - # quic_svd - # radical - # random_forest - # randomized_svd - # range_search - # rann - # regularized_svd - # reinforcement_learning - # softmax_regression - # sparse_autoencoder - # sparse_coding - # svdplusplus + linear_svm + lmnn + local_coordinate_coding + logistic_regression + lsh + matrix_completion + mean_shift + naive_bayes + nca + neighbor_search + nmf + nystroem_method + pca + perceptron + preprocess + quic_svd + radical + random_forest + randomized_svd + range_search + rann + regularized_svd + reinforcement_learning + softmax_regression + sparse_autoencoder + sparse_coding + svdplusplus ) foreach(dir ${DIRS}) diff --git a/src/mlpack/methods/adaboost/adaboost_main.cpp b/src/mlpack/methods/adaboost/adaboost_main.cpp index 705ae4db1a..d671294c71 100644 --- a/src/mlpack/methods/adaboost/adaboost_main.cpp +++ b/src/mlpack/methods/adaboost/adaboost_main.cpp @@ -179,13 +179,16 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) // If we gave an input model but no test set, issue a warning. if (params.Has("input_model")) - RequireAtLeastOnePassed({ "test" }, false, "no task will be performed"); + { + RequireAtLeastOnePassed(params, { "test" }, false, + "no task will be performed"); + } - RequireAtLeastOnePassed({ "output_model", "output", "predictions" }, false, - "no results will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "output", "predictions" }, + false, "no results will be saved"); // "output" will be removed in mlpack 4.0.0. - ReportIgnoredParam({{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); AdaBoostModel* m; if (params.Has("training")) @@ -229,7 +232,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) const size_t numClasses = m->Mappings().n_elem; Log::Info << numClasses << " classes in dataset." << endl; - timers.Start(("adaboost_training"); + timers.Start("adaboost_training"); m->Train(trainingData, labels, numClasses, iterations, tolerance); timers.Stop("adaboost_training"); } @@ -254,13 +257,13 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (params.Has("probabilities")) { - timers.Start(("adaboost_classification"); + timers.Start("adaboost_classification"); m->Classify(testingData, predictedLabels, probabilities); timers.Stop("adaboost_classification"); } else { - timers.Start(("adaboost_classification"); + timers.Start("adaboost_classification"); m->Classify(testingData, predictedLabels); timers.Stop("adaboost_classification"); } diff --git a/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp b/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp index 9be229e664..e230553b56 100644 --- a/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp +++ b/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp @@ -220,7 +220,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (params.Has("calculate_error")) { - RequireAtLeastOnePassed({ "exact_distances", "reference" }, true, + RequireAtLeastOnePassed(params, { "exact_distances", "reference" }, true, "if error is to be calculated, either precalculated exact distances or " "the reference set must be passed"); } @@ -250,7 +250,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (algorithm == "ds") { - timers.Start(("drusilla_select_construct"); + timers.Start("drusilla_select_construct"); Log::Info << "Building DrusillaSelect model..." << endl; m->type = 0; m->ds = DrusillaSelect<>(referenceSet, numTables, numProjections); @@ -258,7 +258,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) } else { - timers.Start(("qdafn_construct"); + timers.Start("qdafn_construct"); Log::Info << "Building QDAFN model..." << endl; m->type = 1; m->qdafn = QDAFN<>(referenceSet, numTables, numProjections); @@ -287,7 +287,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (m->type == 0) { - timers.Start(("drusilla_select_search"); + timers.Start("drusilla_select_search"); Log::Info << "Searching for " << k << " furthest neighbors with " << "DrusillaSelect..." << endl; m->ds.Search(set, k, neighbors, distances); @@ -295,7 +295,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) } else { - timers.Start(("qdafn_search"); + timers.Start("qdafn_search"); Log::Info << "Searching for " << k << " furthest neighbors with " << "QDAFN..." << endl; m->qdafn.Search(set, k, neighbors, distances); diff --git a/src/mlpack/methods/cf/cf_main.cpp b/src/mlpack/methods/cf/cf_main.cpp index 3cfec63e9c..3ca507d789 100644 --- a/src/mlpack/methods/cf/cf_main.cpp +++ b/src/mlpack/methods/cf/cf_main.cpp @@ -218,7 +218,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (!params.Has("query") && !params.Has("all_user_recommendations")) ReportIgnoredParam(params, "output", "no recommendations requested"); - RequireParamInSet("algorithm", { "NMF", "BatchSVD", + RequireParamInSet(params, "algorithm", { "NMF", "BatchSVD", "SVDIncompleteIncremental", "SVDCompleteIncremental", "RegSVD", "RandSVD", "BiasSVD", "SVDPP" }, true, "unknown algorithm"); diff --git a/src/mlpack/methods/dbscan/dbscan_main.cpp b/src/mlpack/methods/dbscan/dbscan_main.cpp index 50f58928de..d14535e773 100644 --- a/src/mlpack/methods/dbscan/dbscan_main.cpp +++ b/src/mlpack/methods/dbscan/dbscan_main.cpp @@ -107,7 +107,8 @@ PARAM_FLAG("naive", "If set, brute-force range search (not tree-based) " // Actually run the clustering, and process the output. template -void RunDBSCAN(RangeSearchType rs, +void RunDBSCAN(util::Params& params, + RangeSearchType rs, PointSelectionPolicy pointSelector = PointSelectionPolicy()) { if (params.Has("single_mode")) @@ -142,14 +143,15 @@ void RunDBSCAN(RangeSearchType rs, // Choose the point selection policy. template -void ChoosePointSelectionPolicy(RangeSearchType rs = RangeSearchType()) +void ChoosePointSelectionPolicy(util::Params& params, + RangeSearchType rs = RangeSearchType()) { const string selectionType = params.Get("selection_type"); if (selectionType == "ordered") - RunDBSCAN(rs); + RunDBSCAN(params, rs); else if (selectionType == "random") - RunDBSCAN(rs); + RunDBSCAN(params, rs); } void BINDING_NAME(util::Params& params, util::Timers& timers) @@ -175,54 +177,54 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (params.Has("naive")) { RangeSearch<> rs(true); - ChoosePointSelectionPolicy(rs); + ChoosePointSelectionPolicy(params, rs); } else { const string treeType = params.Get("tree_type"); if (treeType == "kd") { - ChoosePointSelectionPolicy>(); + ChoosePointSelectionPolicy>(params); } else if (treeType == "cover") { ChoosePointSelectionPolicy>(); + StandardCoverTree>>(params); } else if (treeType == "r") { ChoosePointSelectionPolicy>(); + RTree>>(params); } else if (treeType == "r-star") { ChoosePointSelectionPolicy>(); + RStarTree>>(params); } else if (treeType == "x") { ChoosePointSelectionPolicy>(); + XTree>>(params); } else if (treeType == "hilbert-r") { ChoosePointSelectionPolicy>(); + HilbertRTree>>(params); } else if (treeType == "r-plus") { ChoosePointSelectionPolicy>(); + RPlusTree>>(params); } else if (treeType == "r-plus-plus") { ChoosePointSelectionPolicy>(); + RPlusPlusTree>>(params); } else if (treeType == "ball") { ChoosePointSelectionPolicy>(); + BallTree>>(params); } } } diff --git a/src/mlpack/methods/det/det_main.cpp b/src/mlpack/methods/det/det_main.cpp index 940e92737f..f1d021c25d 100644 --- a/src/mlpack/methods/det/det_main.cpp +++ b/src/mlpack/methods/det/det_main.cpp @@ -147,12 +147,12 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) ReportIgnoredParam(params, {{ "test", false }}, "test_set_estimates"); - RequireParamValue("folds", [](int x) { return x >= 0; }, true, + RequireParamValue(params, "folds", [](int x) { return x >= 0; }, true, "folds must be non-negative"); - RequireParamValue("max_leaf_size", [](int x) { return x > 0; }, true, - "maximum leaf size must be positive"); - RequireParamValue("min_leaf_size", [](int x) { return x > 0; }, true, - "minimum leaf size must be positive"); + RequireParamValue(params, "max_leaf_size", [](int x) { return x > 0; }, + true, "maximum leaf size must be positive"); + RequireParamValue(params, "min_leaf_size", [](int x) { return x > 0; }, + true, "minimum leaf size must be positive"); // Are we training a DET or loading from file? DTree* tree; diff --git a/src/mlpack/methods/gmm/gmm_train_main.cpp b/src/mlpack/methods/gmm/gmm_train_main.cpp index 079068d794..25a86606e1 100644 --- a/src/mlpack/methods/gmm/gmm_train_main.cpp +++ b/src/mlpack/methods/gmm/gmm_train_main.cpp @@ -185,7 +185,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) // Do we need to add noise to the dataset? if (params.Has("noise")) { - timers.Start(("noise_addition"); + timers.Start("noise_addition"); const double noise = params.Get("noise"); dataPoints += noise * arma::randn(dataPoints.n_rows, dataPoints.n_cols); Log::Info << "Added zero-mean Gaussian noise with variance " << noise @@ -254,7 +254,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) dgmm.Weights() = gmm->Weights(); // Compute the parameters of the model using the EM algorithm. - timers.Start(("em"); + timers.Start("em"); EMFit em(maxIterations, tolerance, k); @@ -275,7 +275,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) else if (forcePositive) { // Compute the parameters of the model using the EM algorithm. - timers.Start(("em"); + timers.Start("em"); EMFit em(maxIterations, tolerance, k); likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); @@ -284,7 +284,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) else { // Compute the parameters of the model using the EM algorithm. - timers.Start(("em"); + timers.Start("em"); EMFit em(maxIterations, tolerance, k); likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); @@ -312,7 +312,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) dgmm.Weights() = gmm->Weights(); // Compute the parameters of the model using the EM algorithm. - timers.Start(("em"); + timers.Start("em"); EMFit, PositiveDefiniteConstraint, distribution::DiagonalGaussianDistribution> em(maxIterations, tolerance, KMeans<>(kmeansMaxIterations)); @@ -333,7 +333,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) else if (forcePositive) { // Compute the parameters of the model using the EM algorithm. - timers.Start(("em"); + timers.Start("em"); EMFit<> em(maxIterations, tolerance, KMeans<>(kmeansMaxIterations)); likelihood = gmm->Train(dataPoints, params.Get("trials"), false, em); @@ -342,7 +342,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) else { // Compute the parameters of the model using the EM algorithm. - timers.Start(("em"); + timers.Start("em"); KMeans<> k(kmeansMaxIterations); EMFit, NoConstraint> em(maxIterations, tolerance, k); likelihood = gmm->Train(dataPoints, params.Get("trials"), false, diff --git a/src/mlpack/methods/hmm/hmm_generate_main.cpp b/src/mlpack/methods/hmm/hmm_generate_main.cpp index 8aba1b0cf7..d7e3e6d5a6 100644 --- a/src/mlpack/methods/hmm/hmm_generate_main.cpp +++ b/src/mlpack/methods/hmm/hmm_generate_main.cpp @@ -91,7 +91,7 @@ PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); struct Generate { template - static void Apply(HMMType& hmm, void* /* extraInfo */) + static void Apply(util::Params& params, HMMType& hmm, void* /* extraInfo */) { mat observations; Row sequence; @@ -139,5 +139,5 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) // Load model, and perform the generation. HMMModel* hmm; hmm = std::move(params.Get("model")); - hmm->PerformAction(NULL); // No extra data required. + hmm->PerformAction(params, NULL); // No extra data required. } diff --git a/src/mlpack/methods/hmm/hmm_loglik_main.cpp b/src/mlpack/methods/hmm/hmm_loglik_main.cpp index 00788e1a15..cdf573882f 100644 --- a/src/mlpack/methods/hmm/hmm_loglik_main.cpp +++ b/src/mlpack/methods/hmm/hmm_loglik_main.cpp @@ -78,7 +78,7 @@ PARAM_DOUBLE_OUT("log_likelihood", "Log-likelihood of the sequence."); struct Loglik { template - static void Apply(HMMType& hmm, void* /* extraInfo */) + static void Apply(util::Params& params, HMMType& hmm, void* /* extraInfo */) { // Load the data sequence. mat dataSeq = std::move(params.Get("input")); @@ -108,5 +108,6 @@ struct Loglik void BINDING_NAME(util::Params& params, util::Timers& timers) { // Load model, and calculate the log-likelihood of the sequence. - params.Get("input_model")->PerformAction((void*) NULL); + params.Get("input_model")->PerformAction( + params, (void*) NULL); } diff --git a/src/mlpack/methods/hmm/hmm_model.hpp b/src/mlpack/methods/hmm/hmm_model.hpp index 7665397bdc..80cacf6a50 100644 --- a/src/mlpack/methods/hmm/hmm_model.hpp +++ b/src/mlpack/methods/hmm/hmm_model.hpp @@ -15,6 +15,7 @@ #include "hmm.hpp" #include #include +#include namespace mlpack { namespace hmm { @@ -164,16 +165,16 @@ class HMMModel */ template - void PerformAction(ExtraInfoType* x) + void PerformAction(util::Params& params, ExtraInfoType* x) { if (type == HMMType::DiscreteHMM) - ActionType::Apply(*discreteHMM, x); + ActionType::Apply(params, *discreteHMM, x); else if (type == HMMType::GaussianHMM) - ActionType::Apply(*gaussianHMM, x); + ActionType::Apply(params, *gaussianHMM, x); else if (type == HMMType::GaussianMixtureModelHMM) - ActionType::Apply(*gmmHMM, x); + ActionType::Apply(params, *gmmHMM, x); else if (type == HMMType::DiagonalGaussianMixtureModelHMM) - ActionType::Apply(*diagGMMHMM, x); + ActionType::Apply(params, *diagGMMHMM, x); } //! Serialize the model. diff --git a/src/mlpack/methods/hmm/hmm_train_main.cpp b/src/mlpack/methods/hmm/hmm_train_main.cpp index 198047524d..091d3c9d53 100644 --- a/src/mlpack/methods/hmm/hmm_train_main.cpp +++ b/src/mlpack/methods/hmm/hmm_train_main.cpp @@ -104,21 +104,22 @@ PARAM_DOUBLE_IN("tolerance", "Tolerance of the Baum-Welch algorithm.", "T", struct Init { template - static void Apply(HMMType& hmm, vector* trainSeq) + static void Apply(util::Params& params, HMMType& hmm, vector* trainSeq) { const size_t states = params.Get("states"); const double tolerance = params.Get("tolerance"); // Create the initialized-to-zero model. - Create(hmm, *trainSeq, states, tolerance); + Create(params, hmm, *trainSeq, states, tolerance); // Initializing the emission distribution depends on the distribution. // Therefore we have to use the helper functions. - RandomInitialize(hmm.Emission()); + RandomInitialize(params, hmm.Emission()); } //! Helper function to create discrete HMM. - static void Create(HMM& hmm, + static void Create(util::Params& params, + HMM& hmm, vector& trainSeq, size_t states, double tolerance) @@ -140,7 +141,8 @@ struct Init } //! Helper function to create Gaussian HMM. - static void Create(HMM& hmm, + static void Create(util::Params& params, + HMM& hmm, vector& trainSeq, size_t states, double tolerance) @@ -165,7 +167,8 @@ struct Init } //! Helper function to create GMM HMM. - static void Create(HMM& hmm, + static void Create(util::Params& params, + HMM& hmm, vector& trainSeq, size_t states, double tolerance) @@ -199,7 +202,8 @@ struct Init } //! Helper function to create Diagonal GMM HMM. - static void Create(HMM& hmm, + static void Create(util::Params& params, + HMM& hmm, vector& trainSeq, size_t states, double tolerance) @@ -233,7 +237,8 @@ struct Init } //! Helper function for discrete emission distributions. - static void RandomInitialize(vector& e) + static void RandomInitialize(util::Params& params, + vector& e) { for (size_t i = 0; i < e.size(); ++i) { @@ -243,7 +248,8 @@ struct Init } //! Helper function for Gaussian emission distributions. - static void RandomInitialize(vector& e) + static void RandomInitialize(util::Params& params, + vector& e) { for (size_t i = 0; i < e.size(); ++i) { @@ -256,7 +262,8 @@ struct Init } //! Helper function for GMM emission distributions. - static void RandomInitialize(vector& e) + static void RandomInitialize(util::Params& params, + vector& e) { for (size_t i = 0; i < e.size(); ++i) { @@ -279,7 +286,8 @@ struct Init } //! Helper function for Diagonal GMM emission distributions. - static void RandomInitialize(vector& e) + static void RandomInitialize(util::Params& params, + vector& e) { for (size_t i = 0; i < e.size(); ++i) { @@ -306,7 +314,9 @@ struct Init struct Train { template - static void Apply(HMMType& hmm, vector* trainSeqPtr) + static void Apply(util::Params& params, + HMMType& hmm, + vector* trainSeqPtr) { const bool batch = params.Has("batch"); const double tolerance = params.Get("tolerance"); @@ -533,7 +543,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) { hmm = params.Get("input_model"); - hmm->PerformAction>(&trainSeq); + hmm->PerformAction>(params, &trainSeq); } else { @@ -543,8 +553,8 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) // Catch any exceptions so that we can clean the model if needed. try { - hmm->PerformAction>(&trainSeq); - hmm->PerformAction>(&trainSeq); + hmm->PerformAction>(params, &trainSeq); + hmm->PerformAction>(params, &trainSeq); } catch (std::exception& e) { diff --git a/src/mlpack/methods/hmm/hmm_viterbi_main.cpp b/src/mlpack/methods/hmm/hmm_viterbi_main.cpp index affb5795b9..4e43542924 100644 --- a/src/mlpack/methods/hmm/hmm_viterbi_main.cpp +++ b/src/mlpack/methods/hmm/hmm_viterbi_main.cpp @@ -81,7 +81,7 @@ PARAM_UMATRIX_OUT("output", "File to save predicted state sequence to.", "o"); struct Viterbi { template - static void Apply(HMMType& hmm, void* /* extraInfo */) + static void Apply(util::Params& params, HMMType& hmm, void* /* extraInfo */) { // Load observations. mat dataSeq = std::move(params.Get("input")); @@ -115,5 +115,6 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) RequireAtLeastOnePassed(params, { "output" }, false, "no results will be saved"); - params.Get("input_model")->PerformAction((void*) NULL); + params.Get("input_model")->PerformAction( + params, (void*) NULL); } diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp index b678884f25..5784670a37 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp @@ -140,7 +140,7 @@ PARAM_INT_IN("observations_before_binning", "If the 'domingos' split strategy " // Convenience typedef. typedef tuple TupleType; -static void mlpackMain() +void BINDING_NAME(util::Params& params, util::Timers& timers) { // Check input parameters for validity. const string numericSplitStrategy = @@ -228,7 +228,7 @@ static void mlpackMain() // appropriate type of instantiated numeric split type. This is a little // bit ugly. Maybe there is a nicer way to get this numeric split // information to the trees, but this is ok for now. - timers.Start(("tree_training"); + timers.Start("tree_training"); // Do we need to initialize a model? if (!params.Has("input_model")) @@ -288,7 +288,7 @@ static void mlpackMain() arma::Row predictions; arma::rowvec probabilities; - timers.Start(("tree_testing"); + timers.Start("tree_testing"); model->Classify(testSet, predictions, probabilities); timers.Stop("tree_testing"); diff --git a/src/mlpack/methods/kmeans/kmeans_main.cpp b/src/mlpack/methods/kmeans/kmeans_main.cpp index 126df7b382..5640ffb273 100644 --- a/src/mlpack/methods/kmeans/kmeans_main.cpp +++ b/src/mlpack/methods/kmeans/kmeans_main.cpp @@ -168,18 +168,24 @@ PARAM_STRING_IN("algorithm", "Algorithm to use for the Lloyd iteration " // Given the type of initial partition policy, figure out the empty cluster // policy and run k-means. template -void FindEmptyClusterPolicy(const InitialPartitionPolicy& ipp); +void FindEmptyClusterPolicy(util::Params& params, + util::Timers& timers, + const InitialPartitionPolicy& ipp); // Given the initial partitionining policy and empty cluster policy, figure out // the Lloyd iteration step type and run k-means. template -void FindLloydStepType(const InitialPartitionPolicy& ipp); +void FindLloydStepType(util::Params& params, + util::Timers& timers, + const InitialPartitionPolicy& ipp); // Given the template parameters, sanitize/load input and run k-means. template class LloydStepType> -void RunKMeans(const InitialPartitionPolicy& ipp); +void RunKMeans(util::Params& params, + util::Timers& timers, + const InitialPartitionPolicy& ipp); void BINDING_NAME(util::Params& params, util::Timers& timers) { @@ -205,41 +211,58 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) "sample must be greater than 0.0 and less than or equal to 1.0"); const double percentage = params.Get("percentage"); - FindEmptyClusterPolicy(RefinedStart(samplings, percentage)); + FindEmptyClusterPolicy(params, timers, + RefinedStart(samplings, percentage)); } else if (params.Has("kmeans_plus_plus")) { - FindEmptyClusterPolicy( + FindEmptyClusterPolicy(params, timers, KMeansPlusPlusInitialization()); } else { - FindEmptyClusterPolicy(SampleInitialization()); + FindEmptyClusterPolicy(params, timers, + SampleInitialization()); } } // Given the type of initial partition policy, figure out the empty cluster // policy and run k-means. template -void FindEmptyClusterPolicy(const InitialPartitionPolicy& ipp) +void FindEmptyClusterPolicy(util::Params& params, + util::Timers& timers, + const InitialPartitionPolicy& ipp) { if (params.Has("allow_empty_clusters") || params.Has("kill_empty_clusters")) + { RequireOnlyOnePassed(params, { "allow_empty_clusters", "kill_empty_clusters" }, true); + } if (params.Has("allow_empty_clusters")) - FindLloydStepType(ipp); + { + FindLloydStepType(params, + timers, ipp); + } else if (params.Has("kill_empty_clusters")) - FindLloydStepType(ipp); + { + FindLloydStepType(params, timers, + ipp); + } else - FindLloydStepType(ipp); + { + FindLloydStepType(params, + timers, ipp); + } } // Given the initial partitionining policy and empty cluster policy, figure out // the Lloyd iteration step type and run k-means. template -void FindLloydStepType(const InitialPartitionPolicy& ipp) +void FindLloydStepType(util::Params& params, + util::Timers& timers, + const InitialPartitionPolicy& ipp) { RequireParamInSet(params, "algorithm", { "elkan", "hamerly", "pelleg-moore", "dualtree", "dualtree-covertree", "naive" }, true, @@ -247,27 +270,44 @@ void FindLloydStepType(const InitialPartitionPolicy& ipp) const string algorithm = params.Get("algorithm"); if (algorithm == "elkan") - RunKMeans(ipp); + { + RunKMeans(params, + timers, ipp); + } else if (algorithm == "hamerly") - RunKMeans(ipp); + { + RunKMeans( + params, timers, ipp); + } else if (algorithm == "pelleg-moore") + { RunKMeans(ipp); + PellegMooreKMeans>(params, timers, ipp); + } else if (algorithm == "dualtree") + { RunKMeans(ipp); + DefaultDualTreeKMeans>(params, timers, ipp); + } else if (algorithm == "dualtree-covertree") + { RunKMeans(ipp); + CoverTreeDualTreeKMeans>(params, timers, ipp); + } else if (algorithm == "naive") - RunKMeans(ipp); + { + RunKMeans(params, + timers, ipp); + } } // Given the template parameters, sanitize/load input and run k-means. template class LloydStepType> -void RunKMeans(const InitialPartitionPolicy& ipp) +void RunKMeans(util::Params& params, + util::Timers& timers, + const InitialPartitionPolicy& ipp) { // Now, do validation of input options. if (!params.Has("initial_centroids")) @@ -287,8 +327,8 @@ void RunKMeans(const InitialPartitionPolicy& ipp) << "centroids." << endl; } - RequireParamValue("max_iterations", [](int x) { return x >= 0; }, true, - "maximum iterations must be positive or 0 (for no limit)"); + RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, + true, "maximum iterations must be positive or 0 (for no limit)"); const int maxIterations = params.Get("max_iterations"); // Make sure we have an output file if we're not doing the work in-place. @@ -313,7 +353,7 @@ void RunKMeans(const InitialPartitionPolicy& ipp) Log::Info << "Using initial centroid guesses." << endl; } - timers.Start(("clustering"); + timers.Start("clustering"); KMeans("second_hash_size"); size_t bucketSize = params.Get("bucket_size"); - RequireOnlyOnePassed({ "input_model", "reference" }, true); + RequireOnlyOnePassed(params, { "input_model", "reference" }, true); RequireAtLeastOnePassed(params, { "neighbors", "distances", "output_model" }, false, "no results will be saved"); diff --git a/src/mlpack/methods/nmf/nmf_main.cpp b/src/mlpack/methods/nmf/nmf_main.cpp index a5faf8809e..8ffe846b0c 100644 --- a/src/mlpack/methods/nmf/nmf_main.cpp +++ b/src/mlpack/methods/nmf/nmf_main.cpp @@ -109,7 +109,10 @@ PARAM_STRING_IN("update_rules", "Update rules for each iteration; ( multdist | " PARAM_MATRIX_IN("initial_w", "Initial W matrix.", "p"); PARAM_MATRIX_IN("initial_h", "Initial H matrix.", "q"); -void LoadInitialWH(const bool bindingTransposed, arma::mat& w, arma::mat& h) +void LoadInitialWH(util::Params& params, + const bool bindingTransposed, + arma::mat& w, + arma::mat& h) { // Note that these datasets will typically be transposed on load, since we are // likely receiving it from a row-major language, but we get it in a @@ -129,7 +132,10 @@ void LoadInitialWH(const bool bindingTransposed, arma::mat& w, arma::mat& h) } } -void SaveWH(const bool bindingTransposed, arma::mat&& w, arma::mat&& h) +void SaveWH(util::Params& params, + const bool bindingTransposed, + arma::mat&& w, + arma::mat&& h) { // The same transposition applies when saving. if (bindingTransposed) @@ -145,7 +151,8 @@ void SaveWH(const bool bindingTransposed, arma::mat&& w, arma::mat&& h) } template -void ApplyFactorization(const arma::mat& V, +void ApplyFactorization(util::Params& params, + const arma::mat& V, const size_t r, arma::mat& W, arma::mat& H) @@ -158,7 +165,7 @@ void ApplyFactorization(const arma::mat& V, // Load input dataset. We know if the data is transposed based on the // BINDING_MATRIX_TRANSPOSED macro, which will be 'true' or 'false'. arma::mat initialW, initialH; - LoadInitialWH(BINDING_MATRIX_TRANSPOSED, initialW, initialH); + LoadInitialWH(params, BINDING_MATRIX_TRANSPOSED, initialW, initialH); if (params.Has("initial_w") && params.Has("initial_h")) { // Initialize W and H with given matrices @@ -239,22 +246,22 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) { Log::Info << "Performing NMF with multiplicative distance-based update " << "rules." << std::endl; - ApplyFactorization(V, r, W, H); + ApplyFactorization(params, V, r, W, H); } else if (updateRules == "multdiv") { Log::Info << "Performing NMF with multiplicative divergence-based update " << "rules." << std::endl; - ApplyFactorization(V, r, W, H); + ApplyFactorization(params, V, r, W, H); } else if (updateRules == "als") { Log::Info << "Performing NMF with alternating least squared update rules." << std::endl; - ApplyFactorization(V, r, W, H); + ApplyFactorization(params, V, r, W, H); } // Save results. Remember from our discussion in the comments earlier that we // may need to switch the names of the outputs. - SaveWH(BINDING_MATRIX_TRANSPOSED, std::move(W), std::move(H)); + SaveWH(params, BINDING_MATRIX_TRANSPOSED, std::move(W), std::move(H)); } diff --git a/src/mlpack/methods/pca/pca_main.cpp b/src/mlpack/methods/pca/pca_main.cpp index d3c27162a8..b552abf850 100644 --- a/src/mlpack/methods/pca/pca_main.cpp +++ b/src/mlpack/methods/pca/pca_main.cpp @@ -96,7 +96,8 @@ PARAM_STRING_IN("decomposition_method", "Method used for the principal " //! Run RunPCA on the specified dataset with the given decomposition method. template -void RunPCA(arma::mat& dataset, +void RunPCA(util::Params& params, + arma::mat& dataset, const size_t newDimension, const bool scale, const double varToRetain) @@ -163,20 +164,21 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) // Perform PCA. if (decompositionMethod == "exact") { - RunPCA(dataset, newDimension, scale, varToRetain); + RunPCA(params, dataset, newDimension, scale, varToRetain); } else if (decompositionMethod == "randomized") { - RunPCA(dataset, newDimension, scale, varToRetain); + RunPCA(params, dataset, newDimension, scale, + varToRetain); } else if (decompositionMethod == "randomized-block-krylov") { - RunPCA(dataset, newDimension, scale, + RunPCA(params, dataset, newDimension, scale, varToRetain); } else if (decompositionMethod == "quic") { - RunPCA(dataset, newDimension, scale, varToRetain); + RunPCA(params, dataset, newDimension, scale, varToRetain); } // Now save the results. diff --git a/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp b/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp index 171a0f02db..036c171f63 100644 --- a/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp @@ -112,7 +112,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) RequireParamValue(params, "dimension", [input](int x) { return size_t(x) < input.n_rows; }, true, error.str()); - timers.Start(("binarize"); + timers.Start("binarize"); if (params.Has("dimension")) { data::Binarize(input, output, threshold, dimension); diff --git a/src/mlpack/methods/preprocess/preprocess_describe_main.cpp b/src/mlpack/methods/preprocess/preprocess_describe_main.cpp index 72297d8f17..2e1ec4b047 100644 --- a/src/mlpack/methods/preprocess/preprocess_describe_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_describe_main.cpp @@ -201,7 +201,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) numberFormat += widthPrecision + "f"; } - timers.Start(("statistics"); + timers.Start("statistics"); // Print the headers. Log::Info << boost::format(stringFormat) % "dim" % "var" % "mean" % "std" % "median" % "min" % "max" diff --git a/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp b/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp index e85042db32..b602405b52 100644 --- a/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp @@ -147,7 +147,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) } else { - timers.Start(("imputation"); + timers.Start("imputation"); if (params.Has("dimension")) { // when --dimension is specified, diff --git a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp index 09f428c068..87a594708e 100644 --- a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp @@ -138,7 +138,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) arma::mat& input = params.Get("input"); arma::mat output; ScalingModel* m; - timers.Start(("feature_scaling"); + timers.Start("feature_scaling"); if (params.Has("input_model")) { m = params.Get("input_model"); diff --git a/src/mlpack/methods/preprocess/preprocess_split_main.cpp b/src/mlpack/methods/preprocess/preprocess_split_main.cpp index 1163c23747..1d3fcfb6ca 100644 --- a/src/mlpack/methods/preprocess/preprocess_split_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_split_main.cpp @@ -158,7 +158,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) params.Get>("input_labels"); arma::Row labelsRow = labels.row(0); - timers.Start(("splitting_data"); + timers.Start("splitting_data"); const auto value = data::Split(data, labelsRow, testRatio, !shuffleData, stratifyData); timers.Stop("splitting_data"); @@ -181,7 +181,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) } else // We have no labels, so just split the dataset. { - timers.Start(("splitting_data"); + timers.Start("splitting_data"); const auto value = data::Split(data, testRatio, !shuffleData); timers.Stop("splitting_data"); diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 886b350d83..007a2ea302 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -232,7 +232,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (params.Has("training")) { - timers.Start(("rf_training"); + timers.Start("rf_training"); // Train the model on the given input data. arma::mat data = std::move(params.Get("training")); @@ -268,7 +268,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) // Did we want training accuracy? if (params.Has("print_training_accuracy")) { - timers.Start(("rf_prediction"); + timers.Start("rf_prediction"); arma::Row predictions; rfModel->rf.Classify(data, predictions); @@ -284,7 +284,7 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) if (params.Has("test")) { arma::mat testData = std::move(params.Get("test")); - timers.Start(("rf_prediction"); + timers.Start("rf_prediction"); // Get predictions and probabilities. arma::Row predictions; diff --git a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp index 1bd70bf85b..d3ed250acd 100644 --- a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp +++ b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp @@ -138,11 +138,13 @@ size_t CalculateNumberOfClasses(const size_t numClasses, // Test the accuracy of the model. template -void TestClassifyAcc(const size_t numClasses, const Model& model); +void TestClassifyAcc(util::Params& params, + const size_t numClasses, + const Model& model); // Build the softmax model given the parameters. template -Model* TrainSoftmax(const size_t maxIterations); +Model* TrainSoftmax(util::Params& params, const size_t maxIterations); void BINDING_NAME(util::Params& params, util::Timers& timers) { @@ -152,8 +154,8 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) RequireOnlyOnePassed(params, { "input_model", "training" }, true); if (params.Has("training")) { - RequireAtLeastOnePassed({ "labels" }, true, "if training data is specified," - " labels must also be specified"); + RequireAtLeastOnePassed(params, { "labels" }, true, "if training data is " + "specified, labels must also be specified"); } ReportIgnoredParam(params, {{ "training", false }}, "labels"); ReportIgnoredParam(params, {{ "training", false }}, "max_iterations"); @@ -170,12 +172,13 @@ void BINDING_NAME(util::Params& params, util::Timers& timers) "than or equal to 0 (equal to 0 in case of unspecified.)"); // Make sure we have an output file of some sort. - RequireAtLeastOnePassed({ "output_model", "predictions" }, false, "no results" - " will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "predictions" }, false, + "no results will be saved"); - SoftmaxRegression* sm = TrainSoftmax(maxIterations); + SoftmaxRegression* sm = TrainSoftmax(params, + maxIterations); - TestClassifyAcc(sm->NumClasses(), *sm); + TestClassifyAcc(params, sm->NumClasses(), *sm); params.Get("output_model") = sm; } @@ -196,7 +199,9 @@ size_t CalculateNumberOfClasses(const size_t numClasses, } template -void TestClassifyAcc(size_t numClasses, const Model& model) +void TestClassifyAcc(util::Params& params, + const size_t numClasses, + const Model& model) { using namespace mlpack; @@ -259,7 +264,7 @@ void TestClassifyAcc(size_t numClasses, const Model& model) } template -Model* TrainSoftmax(const size_t maxIterations) +Model* TrainSoftmax(util::Params& params, const size_t maxIterations) { using namespace mlpack; From 68bb344cc13be667f4813efe0a1ecafb2d6ad298 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 1 Jul 2021 23:32:42 +0200 Subject: [PATCH 493/729] Fix some of them manually, but great solution Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/get_printable_type.hpp | 12 ++++++++---- src/mlpack/bindings/R/get_printable_type_impl.hpp | 14 +++++++++----- src/mlpack/bindings/R/get_r_type.hpp | 12 ++++++++---- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/mlpack/bindings/R/get_printable_type.hpp b/src/mlpack/bindings/R/get_printable_type.hpp index 4b19c21cdf..6ca4932fe1 100644 --- a/src/mlpack/bindings/R/get_printable_type.hpp +++ b/src/mlpack/bindings/R/get_printable_type.hpp @@ -50,10 +50,14 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, + const typename std::enable_if< + !std::is_same>::value>::type*); template<> diff --git a/src/mlpack/bindings/R/get_printable_type_impl.hpp b/src/mlpack/bindings/R/get_printable_type_impl.hpp index a163a615f5..88aa270199 100644 --- a/src/mlpack/bindings/R/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/R/get_printable_type_impl.hpp @@ -58,11 +58,15 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, - const typename std::enable_if>::value>::type*) + const typename std::enable_if< + !util::IsStdVector::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, + const typename std::enable_if< + !std::is_same>::value>::type*) { return "character"; } diff --git a/src/mlpack/bindings/R/get_r_type.hpp b/src/mlpack/bindings/R/get_r_type.hpp index d01559ea66..3e92bb717d 100644 --- a/src/mlpack/bindings/R/get_r_type.hpp +++ b/src/mlpack/bindings/R/get_r_type.hpp @@ -83,10 +83,14 @@ inline std::string GetRType( template<> inline std::string GetRType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, + const typename std::enable_if< + !std::is_same>::value>::type*) { return "character"; From 3f0a40fa107780dda5b4a68ce8f5e9f320677cda Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 1 Jul 2021 23:47:50 +0200 Subject: [PATCH 494/729] Do the first line with regexp Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/get_type.hpp | 3 ++- src/mlpack/bindings/go/get_go_type.hpp | 3 ++- src/mlpack/bindings/go/get_printable_type.hpp | 3 ++- src/mlpack/bindings/go/get_printable_type_impl.hpp | 3 ++- src/mlpack/bindings/go/get_type.hpp | 3 ++- src/mlpack/bindings/python/get_cython_type.hpp | 3 ++- src/mlpack/bindings/python/get_printable_type.hpp | 3 ++- src/mlpack/bindings/python/get_printable_type_impl.hpp | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mlpack/bindings/R/get_type.hpp b/src/mlpack/bindings/R/get_type.hpp index 574ec6674c..81d57b99c5 100644 --- a/src/mlpack/bindings/R/get_type.hpp +++ b/src/mlpack/bindings/R/get_type.hpp @@ -72,7 +72,8 @@ inline std::string GetType( template<> inline std::string GetType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if( template<> inline std::string GetGoType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if( template<> inline std::string GetType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*) { diff --git a/src/mlpack/bindings/python/get_cython_type.hpp b/src/mlpack/bindings/python/get_cython_type.hpp index 705b785758..ab3d09e633 100644 --- a/src/mlpack/bindings/python/get_cython_type.hpp +++ b/src/mlpack/bindings/python/get_cython_type.hpp @@ -53,7 +53,8 @@ inline std::string GetCythonType( template<> inline std::string GetCythonType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*) { diff --git a/src/mlpack/bindings/python/get_printable_type.hpp b/src/mlpack/bindings/python/get_printable_type.hpp index 41593e4681..f904fd09c6 100644 --- a/src/mlpack/bindings/python/get_printable_type.hpp +++ b/src/mlpack/bindings/python/get_printable_type.hpp @@ -50,7 +50,8 @@ inline std::string GetPrintableType( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if( template<> inline std::string GetPrintableType( util::ParamData& /* d */, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !util::isStdVector::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if Date: Fri, 2 Jul 2021 09:32:02 +0530 Subject: [PATCH 495/729] Move Sequential layers to LayerTypes (#3004) * Move layers to LayerTypes * remove extra line --- src/mlpack/methods/ann/layer/layer_types.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index d72cd1fa33..e3c97f0d08 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -222,6 +222,7 @@ template *, Linear3D*, LpPooling*, PixelShuffle*, @@ -234,8 +235,7 @@ using MoreTypes = boost::variant< ReinforceNormal*, Reparametrization*, Select*, - Sequential*, - Sequential*, + SpatialDropout*, Subview*, VRClassReward*, VirtualBatchNorm*, @@ -277,7 +277,6 @@ using LayerTypes = boost::variant< Dropout*, ELU*, FastLSTM*, - FlexibleReLU*, GRU*, HardTanH*, Join*, @@ -297,8 +296,9 @@ using LayerTypes = boost::variant< NoisyLinear*, Padding*, PReLU*, + Sequential*, + Sequential*, Softmax*, - SpatialDropout*, TransposedConvolution, NaiveConvolution, NaiveConvolution, arma::mat, arma::mat>*, From e664bb022b1a95f490fa11b63b2cf91aa0f3eece Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 14:49:10 +0200 Subject: [PATCH 496/729] Remove this boost pointer vector header. Why it is here in the first place? Signed-off-by: Omar Shrit --- src/mlpack/methods/ann/layer/concat.hpp | 2 -- src/mlpack/methods/ann/layer/concat_performance.hpp | 2 -- src/mlpack/methods/ann/layer/highway.hpp | 2 -- src/mlpack/methods/ann/layer/recurrent_attention.hpp | 1 - src/mlpack/methods/ann/layer/sequential.hpp | 2 -- 5 files changed, 9 deletions(-) diff --git a/src/mlpack/methods/ann/layer/concat.hpp b/src/mlpack/methods/ann/layer/concat.hpp index 13d29458cb..e693234f3e 100644 --- a/src/mlpack/methods/ann/layer/concat.hpp +++ b/src/mlpack/methods/ann/layer/concat.hpp @@ -19,8 +19,6 @@ #include "../visitor/delta_visitor.hpp" #include "../visitor/output_parameter_visitor.hpp" -#include - #include "layer_types.hpp" namespace mlpack { diff --git a/src/mlpack/methods/ann/layer/concat_performance.hpp b/src/mlpack/methods/ann/layer/concat_performance.hpp index b576430479..b7ddbe1625 100644 --- a/src/mlpack/methods/ann/layer/concat_performance.hpp +++ b/src/mlpack/methods/ann/layer/concat_performance.hpp @@ -14,8 +14,6 @@ #include -#include - #include "layer_types.hpp" namespace mlpack { diff --git a/src/mlpack/methods/ann/layer/highway.hpp b/src/mlpack/methods/ann/layer/highway.hpp index aa539a4972..526a434d23 100644 --- a/src/mlpack/methods/ann/layer/highway.hpp +++ b/src/mlpack/methods/ann/layer/highway.hpp @@ -15,8 +15,6 @@ #include -#include - #include "../visitor/delete_visitor.hpp" #include "../visitor/delta_visitor.hpp" #include "../visitor/output_height_visitor.hpp" diff --git a/src/mlpack/methods/ann/layer/recurrent_attention.hpp b/src/mlpack/methods/ann/layer/recurrent_attention.hpp index b8b4a55a89..63838dc479 100644 --- a/src/mlpack/methods/ann/layer/recurrent_attention.hpp +++ b/src/mlpack/methods/ann/layer/recurrent_attention.hpp @@ -13,7 +13,6 @@ #define MLPACK_METHODS_ANN_LAYER_RECURRENT_ATTENTION_HPP #include -#include #include "../visitor/delta_visitor.hpp" #include "../visitor/output_parameter_visitor.hpp" diff --git a/src/mlpack/methods/ann/layer/sequential.hpp b/src/mlpack/methods/ann/layer/sequential.hpp index ebf3c6fd6a..bd1857b1ba 100644 --- a/src/mlpack/methods/ann/layer/sequential.hpp +++ b/src/mlpack/methods/ann/layer/sequential.hpp @@ -15,8 +15,6 @@ #include -#include - #include "../visitor/delete_visitor.hpp" #include "../visitor/copy_visitor.hpp" #include "../visitor/delta_visitor.hpp" From 71bc9f6dad373e53c076f7cbd2d515ef2a9c8394 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 14:58:46 +0200 Subject: [PATCH 497/729] This one is dangerous.. Signed-off-by: Omar Shrit --- src/mlpack/tests/lrsdp_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/tests/lrsdp_test.cpp b/src/mlpack/tests/lrsdp_test.cpp index b2ac089997..0a2b79eb01 100644 --- a/src/mlpack/tests/lrsdp_test.cpp +++ b/src/mlpack/tests/lrsdp_test.cpp @@ -12,7 +12,6 @@ #include #include -#include #include "test_tools.hpp" using namespace mlpack; From 32806792738d55845491188f2fb666da0c836f50 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 15:45:30 +0200 Subject: [PATCH 498/729] Remove another headers Signed-off-by: Omar Shrit --- src/mlpack/methods/dbscan/dbscan.hpp | 1 - src/mlpack/methods/mean_shift/mean_shift.hpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/mlpack/methods/dbscan/dbscan.hpp b/src/mlpack/methods/dbscan/dbscan.hpp index 73c887027e..6658b7a99d 100644 --- a/src/mlpack/methods/dbscan/dbscan.hpp +++ b/src/mlpack/methods/dbscan/dbscan.hpp @@ -18,7 +18,6 @@ #include #include "random_point_selection.hpp" #include "ordered_point_selection.hpp" -#include namespace mlpack { namespace dbscan { diff --git a/src/mlpack/methods/mean_shift/mean_shift.hpp b/src/mlpack/methods/mean_shift/mean_shift.hpp index 7f382e4434..dab1f45c25 100644 --- a/src/mlpack/methods/mean_shift/mean_shift.hpp +++ b/src/mlpack/methods/mean_shift/mean_shift.hpp @@ -17,7 +17,6 @@ #include #include #include -#include namespace mlpack { namespace meanshift /** Mean shift clustering. */ { From af6254d49b4b3b889b6e315797a3179afdc7c43f Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 16:00:37 +0200 Subject: [PATCH 499/729] Remove another boost version header Signed-off-by: Omar Shrit --- src/mlpack/tests/test_catch_tools.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/tests/test_catch_tools.hpp b/src/mlpack/tests/test_catch_tools.hpp index 879cac8b49..7e2a0b4afe 100644 --- a/src/mlpack/tests/test_catch_tools.hpp +++ b/src/mlpack/tests/test_catch_tools.hpp @@ -13,7 +13,6 @@ #define MLPACK_TESTS_TEST_CATCH_TOOLS_HPP #include -#include #include "catch.hpp" From 5cbf8f81d7c7a6d1307e957e51398b7745c404e8 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 16:58:01 +0200 Subject: [PATCH 500/729] Fix std::is_same style issue Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/default_param.hpp | 3 ++- src/mlpack/bindings/R/default_param_impl.hpp | 3 ++- src/mlpack/bindings/cli/default_param.hpp | 3 ++- src/mlpack/bindings/cli/default_param_impl.hpp | 3 ++- src/mlpack/bindings/go/default_param.hpp | 3 ++- src/mlpack/bindings/go/default_param_impl.hpp | 3 ++- src/mlpack/bindings/julia/default_param.hpp | 3 ++- src/mlpack/bindings/julia/default_param_impl.hpp | 3 ++- src/mlpack/bindings/python/default_param.hpp | 3 ++- src/mlpack/bindings/python/default_param_impl.hpp | 3 ++- 10 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/mlpack/bindings/R/default_param.hpp b/src/mlpack/bindings/R/default_param.hpp index 8fdf41dfbf..651d976b9b 100644 --- a/src/mlpack/bindings/R/default_param.hpp +++ b/src/mlpack/bindings/R/default_param.hpp @@ -29,7 +29,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, - const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/R/default_param_impl.hpp b/src/mlpack/bindings/R/default_param_impl.hpp index 751834baca..8cf4110696 100644 --- a/src/mlpack/bindings/R/default_param_impl.hpp +++ b/src/mlpack/bindings/R/default_param_impl.hpp @@ -27,7 +27,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, - const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/cli/default_param.hpp b/src/mlpack/bindings/cli/default_param.hpp index 093a03c567..9b5edc9229 100644 --- a/src/mlpack/bindings/cli/default_param.hpp +++ b/src/mlpack/bindings/cli/default_param.hpp @@ -29,7 +29,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, - const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/cli/default_param_impl.hpp b/src/mlpack/bindings/cli/default_param_impl.hpp index b002e94611..33a9524e3f 100644 --- a/src/mlpack/bindings/cli/default_param_impl.hpp +++ b/src/mlpack/bindings/cli/default_param_impl.hpp @@ -27,7 +27,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, - const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/go/default_param.hpp b/src/mlpack/bindings/go/default_param.hpp index 4b967b270e..e2efe85d0a 100644 --- a/src/mlpack/bindings/go/default_param.hpp +++ b/src/mlpack/bindings/go/default_param.hpp @@ -29,7 +29,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, - const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/go/default_param_impl.hpp b/src/mlpack/bindings/go/default_param_impl.hpp index 4d3c0feca1..f33c6cccb3 100644 --- a/src/mlpack/bindings/go/default_param_impl.hpp +++ b/src/mlpack/bindings/go/default_param_impl.hpp @@ -27,7 +27,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, - const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/julia/default_param.hpp b/src/mlpack/bindings/julia/default_param.hpp index fca7d4a488..db714ccc5d 100644 --- a/src/mlpack/bindings/julia/default_param.hpp +++ b/src/mlpack/bindings/julia/default_param.hpp @@ -29,7 +29,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, - const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/julia/default_param_impl.hpp b/src/mlpack/bindings/julia/default_param_impl.hpp index f1a71e7cf2..216758df4f 100644 --- a/src/mlpack/bindings/julia/default_param_impl.hpp +++ b/src/mlpack/bindings/julia/default_param_impl.hpp @@ -27,7 +27,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, - const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/python/default_param.hpp b/src/mlpack/bindings/python/default_param.hpp index 36a6b19c32..cde42983bb 100644 --- a/src/mlpack/bindings/python/default_param.hpp +++ b/src/mlpack/bindings/python/default_param.hpp @@ -29,7 +29,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, - const typename std::enable_if::value>::type* = 0, + const typename std::enable_if::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/python/default_param_impl.hpp b/src/mlpack/bindings/python/default_param_impl.hpp index d953c2efb2..0fe60d8ee0 100644 --- a/src/mlpack/bindings/python/default_param_impl.hpp +++ b/src/mlpack/bindings/python/default_param_impl.hpp @@ -27,7 +27,8 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, - const typename std::enable_if::value>::type*, + const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { From 1beac191adbe216a151ef983c9a7d35a71bc15e7 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 17:11:37 +0200 Subject: [PATCH 501/729] Break line on HasSerialize Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/get_type.hpp | 3 ++- src/mlpack/bindings/go/get_go_type.hpp | 3 ++- src/mlpack/bindings/go/get_printable_type.hpp | 3 ++- src/mlpack/bindings/go/get_printable_type_impl.hpp | 3 ++- src/mlpack/bindings/go/get_type.hpp | 3 ++- src/mlpack/bindings/python/get_cython_type.hpp | 3 ++- src/mlpack/bindings/python/get_printable_type.hpp | 3 ++- src/mlpack/bindings/python/get_printable_type_impl.hpp | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mlpack/bindings/R/get_type.hpp b/src/mlpack/bindings/R/get_type.hpp index 81d57b99c5..a39ffc46cb 100644 --- a/src/mlpack/bindings/R/get_type.hpp +++ b/src/mlpack/bindings/R/get_type.hpp @@ -74,7 +74,8 @@ inline std::string GetType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type*) diff --git a/src/mlpack/bindings/go/get_go_type.hpp b/src/mlpack/bindings/go/get_go_type.hpp index 9dbaf67bb7..9fac01f417 100644 --- a/src/mlpack/bindings/go/get_go_type.hpp +++ b/src/mlpack/bindings/go/get_go_type.hpp @@ -75,7 +75,8 @@ inline std::string GetGoType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type*) diff --git a/src/mlpack/bindings/go/get_printable_type.hpp b/src/mlpack/bindings/go/get_printable_type.hpp index 4d4bb18ff7..4ec81417ce 100644 --- a/src/mlpack/bindings/go/get_printable_type.hpp +++ b/src/mlpack/bindings/go/get_printable_type.hpp @@ -52,7 +52,8 @@ inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type*); diff --git a/src/mlpack/bindings/go/get_printable_type_impl.hpp b/src/mlpack/bindings/go/get_printable_type_impl.hpp index 229c14cf8b..33e85f7c06 100644 --- a/src/mlpack/bindings/go/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/go/get_printable_type_impl.hpp @@ -61,7 +61,8 @@ inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type*) diff --git a/src/mlpack/bindings/go/get_type.hpp b/src/mlpack/bindings/go/get_type.hpp index 1d86f84879..5d7f736301 100644 --- a/src/mlpack/bindings/go/get_type.hpp +++ b/src/mlpack/bindings/go/get_type.hpp @@ -66,7 +66,8 @@ inline std::string GetType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*) { return "String"; diff --git a/src/mlpack/bindings/python/get_cython_type.hpp b/src/mlpack/bindings/python/get_cython_type.hpp index ab3d09e633..c9a21f1ed0 100644 --- a/src/mlpack/bindings/python/get_cython_type.hpp +++ b/src/mlpack/bindings/python/get_cython_type.hpp @@ -55,7 +55,8 @@ inline std::string GetCythonType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*) { return "string"; diff --git a/src/mlpack/bindings/python/get_printable_type.hpp b/src/mlpack/bindings/python/get_printable_type.hpp index f904fd09c6..eccd123b1a 100644 --- a/src/mlpack/bindings/python/get_printable_type.hpp +++ b/src/mlpack/bindings/python/get_printable_type.hpp @@ -52,7 +52,8 @@ inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type*); diff --git a/src/mlpack/bindings/python/get_printable_type_impl.hpp b/src/mlpack/bindings/python/get_printable_type_impl.hpp index 4f364e2d3c..836aa9fa1d 100644 --- a/src/mlpack/bindings/python/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/python/get_printable_type_impl.hpp @@ -60,7 +60,8 @@ inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< !util::isStdVector::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !data::HasSerialize::value>::type*, const typename std::enable_if::value>::type*, const typename std::enable_if>::value>::type*) From 0c7b38f17ebdeb007117db330bdbb094161bdcaf Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 17:17:05 +0200 Subject: [PATCH 502/729] Fix is_arma_type Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/get_type.hpp | 3 ++- src/mlpack/bindings/go/get_go_type.hpp | 3 ++- src/mlpack/bindings/go/get_printable_type.hpp | 3 ++- src/mlpack/bindings/go/get_printable_type_impl.hpp | 3 ++- src/mlpack/bindings/go/get_type.hpp | 3 ++- src/mlpack/bindings/python/get_cython_type.hpp | 3 ++- src/mlpack/bindings/python/get_printable_type.hpp | 3 ++- src/mlpack/bindings/python/get_printable_type_impl.hpp | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mlpack/bindings/R/get_type.hpp b/src/mlpack/bindings/R/get_type.hpp index a39ffc46cb..b9c6e93c80 100644 --- a/src/mlpack/bindings/R/get_type.hpp +++ b/src/mlpack/bindings/R/get_type.hpp @@ -76,7 +76,8 @@ inline std::string GetType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, const typename std::enable_if>::value>::type*) { diff --git a/src/mlpack/bindings/go/get_go_type.hpp b/src/mlpack/bindings/go/get_go_type.hpp index 9fac01f417..6d00610c47 100644 --- a/src/mlpack/bindings/go/get_go_type.hpp +++ b/src/mlpack/bindings/go/get_go_type.hpp @@ -77,7 +77,8 @@ inline std::string GetGoType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, const typename std::enable_if>::value>::type*) { diff --git a/src/mlpack/bindings/go/get_printable_type.hpp b/src/mlpack/bindings/go/get_printable_type.hpp index 4ec81417ce..0a9593b8cd 100644 --- a/src/mlpack/bindings/go/get_printable_type.hpp +++ b/src/mlpack/bindings/go/get_printable_type.hpp @@ -54,7 +54,8 @@ inline std::string GetPrintableType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, const typename std::enable_if>::value>::type*); diff --git a/src/mlpack/bindings/go/get_printable_type_impl.hpp b/src/mlpack/bindings/go/get_printable_type_impl.hpp index 33e85f7c06..3ef255dd8a 100644 --- a/src/mlpack/bindings/go/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/go/get_printable_type_impl.hpp @@ -63,7 +63,8 @@ inline std::string GetPrintableType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, const typename std::enable_if>::value>::type*) { diff --git a/src/mlpack/bindings/go/get_type.hpp b/src/mlpack/bindings/go/get_type.hpp index 5d7f736301..d6b6d6af88 100644 --- a/src/mlpack/bindings/go/get_type.hpp +++ b/src/mlpack/bindings/go/get_type.hpp @@ -68,7 +68,8 @@ inline std::string GetType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*) + const typename std::enable_if< + !arma::is_arma_type::value>::type*) { return "String"; } diff --git a/src/mlpack/bindings/python/get_cython_type.hpp b/src/mlpack/bindings/python/get_cython_type.hpp index c9a21f1ed0..087b97341e 100644 --- a/src/mlpack/bindings/python/get_cython_type.hpp +++ b/src/mlpack/bindings/python/get_cython_type.hpp @@ -57,7 +57,8 @@ inline std::string GetCythonType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*) + const typename std::enable_if< + !arma::is_arma_type::value>::type*) { return "string"; } diff --git a/src/mlpack/bindings/python/get_printable_type.hpp b/src/mlpack/bindings/python/get_printable_type.hpp index eccd123b1a..12e8783235 100644 --- a/src/mlpack/bindings/python/get_printable_type.hpp +++ b/src/mlpack/bindings/python/get_printable_type.hpp @@ -54,7 +54,8 @@ inline std::string GetPrintableType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, const typename std::enable_if>::value>::type*); diff --git a/src/mlpack/bindings/python/get_printable_type_impl.hpp b/src/mlpack/bindings/python/get_printable_type_impl.hpp index 836aa9fa1d..d6517c8139 100644 --- a/src/mlpack/bindings/python/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/python/get_printable_type_impl.hpp @@ -62,7 +62,8 @@ inline std::string GetPrintableType( !util::isStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, - const typename std::enable_if::value>::type*, + const typename std::enable_if< + !arma::is_arma_type::value>::type*, const typename std::enable_if>::value>::type*) { From a27700b0724b7ff5dc991e878533ee345b4f827a Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 17:31:05 +0200 Subject: [PATCH 503/729] Fix regexp error Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/default_param.hpp | 2 +- src/mlpack/bindings/R/default_param_impl.hpp | 2 +- src/mlpack/bindings/cli/default_param.hpp | 2 +- src/mlpack/bindings/cli/default_param_impl.hpp | 2 +- src/mlpack/bindings/go/default_param.hpp | 2 +- src/mlpack/bindings/go/default_param_impl.hpp | 2 +- src/mlpack/bindings/julia/default_param.hpp | 2 +- src/mlpack/bindings/julia/default_param_impl.hpp | 2 +- src/mlpack/bindings/python/default_param.hpp | 2 +- src/mlpack/bindings/python/default_param_impl.hpp | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mlpack/bindings/R/default_param.hpp b/src/mlpack/bindings/R/default_param.hpp index 651d976b9b..2006e2eb23 100644 --- a/src/mlpack/bindings/R/default_param.hpp +++ b/src/mlpack/bindings/R/default_param.hpp @@ -30,7 +30,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, + std::string>::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/R/default_param_impl.hpp b/src/mlpack/bindings/R/default_param_impl.hpp index 8cf4110696..5447d8738a 100644 --- a/src/mlpack/bindings/R/default_param_impl.hpp +++ b/src/mlpack/bindings/R/default_param_impl.hpp @@ -28,7 +28,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type*, + std::string>::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/cli/default_param.hpp b/src/mlpack/bindings/cli/default_param.hpp index 9b5edc9229..9be4b4c73d 100644 --- a/src/mlpack/bindings/cli/default_param.hpp +++ b/src/mlpack/bindings/cli/default_param.hpp @@ -30,7 +30,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, + std::string>::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/cli/default_param_impl.hpp b/src/mlpack/bindings/cli/default_param_impl.hpp index 33a9524e3f..b9defc6374 100644 --- a/src/mlpack/bindings/cli/default_param_impl.hpp +++ b/src/mlpack/bindings/cli/default_param_impl.hpp @@ -28,7 +28,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type*, + std::string>::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/go/default_param.hpp b/src/mlpack/bindings/go/default_param.hpp index e2efe85d0a..3ebdaae7b3 100644 --- a/src/mlpack/bindings/go/default_param.hpp +++ b/src/mlpack/bindings/go/default_param.hpp @@ -30,7 +30,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, + std::string>::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/go/default_param_impl.hpp b/src/mlpack/bindings/go/default_param_impl.hpp index f33c6cccb3..2458012966 100644 --- a/src/mlpack/bindings/go/default_param_impl.hpp +++ b/src/mlpack/bindings/go/default_param_impl.hpp @@ -28,7 +28,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type*, + std::string>::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/julia/default_param.hpp b/src/mlpack/bindings/julia/default_param.hpp index db714ccc5d..0d2b368381 100644 --- a/src/mlpack/bindings/julia/default_param.hpp +++ b/src/mlpack/bindings/julia/default_param.hpp @@ -30,7 +30,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, + std::string>::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/julia/default_param_impl.hpp b/src/mlpack/bindings/julia/default_param_impl.hpp index 216758df4f..667ecae5f4 100644 --- a/src/mlpack/bindings/julia/default_param_impl.hpp +++ b/src/mlpack/bindings/julia/default_param_impl.hpp @@ -28,7 +28,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type*, + std::string>::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { diff --git a/src/mlpack/bindings/python/default_param.hpp b/src/mlpack/bindings/python/default_param.hpp index cde42983bb..5f8bc32ea4 100644 --- a/src/mlpack/bindings/python/default_param.hpp +++ b/src/mlpack/bindings/python/default_param.hpp @@ -30,7 +30,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, const typename std::enable_if::value>::type* = 0, + std::string>::value>::type* = 0, const typename std::enable_if>::value>::type* = 0); diff --git a/src/mlpack/bindings/python/default_param_impl.hpp b/src/mlpack/bindings/python/default_param_impl.hpp index 0fe60d8ee0..543253c18b 100644 --- a/src/mlpack/bindings/python/default_param_impl.hpp +++ b/src/mlpack/bindings/python/default_param_impl.hpp @@ -28,7 +28,7 @@ std::string DefaultParamImpl( const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type* /* junk */, const typename std::enable_if::value>::type*, + std::string>::value>::type*, const typename std::enable_if>::value>::type* /* junk */) { From bbb8b4b640aaa7ed37f3afd1e7e3981edf111d32 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Fri, 2 Jul 2021 17:42:34 +0200 Subject: [PATCH 504/729] Fix IsStdVector Signed-off-by: Omar Shrit --- src/mlpack/bindings/R/get_type.hpp | 2 +- src/mlpack/bindings/go/get_go_type.hpp | 2 +- src/mlpack/bindings/go/get_printable_type.hpp | 2 +- src/mlpack/bindings/go/get_printable_type_impl.hpp | 2 +- src/mlpack/bindings/go/get_type.hpp | 2 +- src/mlpack/bindings/python/get_cython_type.hpp | 2 +- src/mlpack/bindings/python/get_printable_type.hpp | 2 +- src/mlpack/bindings/python/get_printable_type_impl.hpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mlpack/bindings/R/get_type.hpp b/src/mlpack/bindings/R/get_type.hpp index b9c6e93c80..55264eedb5 100644 --- a/src/mlpack/bindings/R/get_type.hpp +++ b/src/mlpack/bindings/R/get_type.hpp @@ -73,7 +73,7 @@ template<> inline std::string GetType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/go/get_go_type.hpp b/src/mlpack/bindings/go/get_go_type.hpp index 6d00610c47..4fc800ecbf 100644 --- a/src/mlpack/bindings/go/get_go_type.hpp +++ b/src/mlpack/bindings/go/get_go_type.hpp @@ -74,7 +74,7 @@ template<> inline std::string GetGoType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/go/get_printable_type.hpp b/src/mlpack/bindings/go/get_printable_type.hpp index 0a9593b8cd..5b2cadece3 100644 --- a/src/mlpack/bindings/go/get_printable_type.hpp +++ b/src/mlpack/bindings/go/get_printable_type.hpp @@ -51,7 +51,7 @@ template<> inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/go/get_printable_type_impl.hpp b/src/mlpack/bindings/go/get_printable_type_impl.hpp index 3ef255dd8a..cdbfe9feb5 100644 --- a/src/mlpack/bindings/go/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/go/get_printable_type_impl.hpp @@ -60,7 +60,7 @@ template<> inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/go/get_type.hpp b/src/mlpack/bindings/go/get_type.hpp index d6b6d6af88..828085d375 100644 --- a/src/mlpack/bindings/go/get_type.hpp +++ b/src/mlpack/bindings/go/get_type.hpp @@ -65,7 +65,7 @@ template<> inline std::string GetType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/python/get_cython_type.hpp b/src/mlpack/bindings/python/get_cython_type.hpp index 087b97341e..9809e1224e 100644 --- a/src/mlpack/bindings/python/get_cython_type.hpp +++ b/src/mlpack/bindings/python/get_cython_type.hpp @@ -54,7 +54,7 @@ template<> inline std::string GetCythonType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/python/get_printable_type.hpp b/src/mlpack/bindings/python/get_printable_type.hpp index 12e8783235..1d454b172a 100644 --- a/src/mlpack/bindings/python/get_printable_type.hpp +++ b/src/mlpack/bindings/python/get_printable_type.hpp @@ -51,7 +51,7 @@ template<> inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< diff --git a/src/mlpack/bindings/python/get_printable_type_impl.hpp b/src/mlpack/bindings/python/get_printable_type_impl.hpp index d6517c8139..5a903af575 100644 --- a/src/mlpack/bindings/python/get_printable_type_impl.hpp +++ b/src/mlpack/bindings/python/get_printable_type_impl.hpp @@ -59,7 +59,7 @@ template<> inline std::string GetPrintableType( util::ParamData& /* d */, const typename std::enable_if< - !util::isStdVector::value>::type*, + !util::IsStdVector::value>::type*, const typename std::enable_if< !data::HasSerialize::value>::type*, const typename std::enable_if< From aad6e626862bf344b48129fa9f61839acdfcf60e Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 2 Jul 2021 18:33:43 -0400 Subject: [PATCH 505/729] Fix PRINT_CALL binding name. --- src/mlpack/methods/lmnn/lmnn_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/lmnn/lmnn_main.cpp b/src/mlpack/methods/lmnn/lmnn_main.cpp index 3fdc6b8620..25cc6cf100 100644 --- a/src/mlpack/methods/lmnn/lmnn_main.cpp +++ b/src/mlpack/methods/lmnn/lmnn_main.cpp @@ -129,8 +129,8 @@ BINDING_EXAMPLE( "number of targets as 3 using BigBatch_SGD optimizer. A simple call for " "the same will look like: " "\n\n" + - PRINT_CALL("mlpack_lmnn", "input", "iris", "labels", "iris_labels", - "k", 3, "optimizer", "bbsgd", "output", "output") + + PRINT_CALL("lmnn", "input", "iris", "labels", "iris_labels", "k", 3, + "optimizer", "bbsgd", "output", "output") + "\n\n" "An another program call making use of range & regularization parameter " "with dataset having labels as last column can be made as: " From a74b925950e9b720755c86dccf3d737c67332aa8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 2 Jul 2021 18:34:47 -0400 Subject: [PATCH 506/729] Oops, there are two PRINT_CALL() calls. --- src/mlpack/methods/lmnn/lmnn_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/lmnn/lmnn_main.cpp b/src/mlpack/methods/lmnn/lmnn_main.cpp index 25cc6cf100..a0c9d701a5 100644 --- a/src/mlpack/methods/lmnn/lmnn_main.cpp +++ b/src/mlpack/methods/lmnn/lmnn_main.cpp @@ -135,7 +135,7 @@ BINDING_EXAMPLE( "An another program call making use of range & regularization parameter " "with dataset having labels as last column can be made as: " "\n\n" + - PRINT_CALL("mlpack_lmnn", "input", "letter_recognition", "k", 5, + PRINT_CALL("lmnn", "input", "letter_recognition", "k", 5, "range", 10, "regularization", 0.4, "output", "output")); // See also... From b1479b23a3bb545b97456e2bd178bfa705359ff8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 2 Jul 2021 21:10:02 -0400 Subject: [PATCH 507/729] Use BINDING_FUNCTION instead of BINDING_NAME. --- src/mlpack/bindings/python/print_pyx.cpp | 11 +++++++---- src/mlpack/core/util/mlpack_main.hpp | 6 ++++++ src/mlpack/core/util/param.hpp | 6 ++++++ src/mlpack/methods/adaboost/adaboost_main.cpp | 2 +- src/mlpack/methods/approx_kfn/approx_kfn_main.cpp | 2 +- .../bayesian_linear_regression_main.cpp | 2 +- src/mlpack/methods/cf/cf_main.cpp | 2 +- src/mlpack/methods/dbscan/dbscan_main.cpp | 2 +- .../methods/decision_tree/decision_tree_main.cpp | 2 +- src/mlpack/methods/det/det_main.cpp | 2 +- src/mlpack/methods/emst/emst_main.cpp | 2 +- src/mlpack/methods/fastmks/fastmks_main.cpp | 2 +- src/mlpack/methods/gmm/gmm_generate_main.cpp | 2 +- src/mlpack/methods/gmm/gmm_probability_main.cpp | 2 +- src/mlpack/methods/gmm/gmm_train_main.cpp | 2 +- src/mlpack/methods/hmm/hmm_generate_main.cpp | 2 +- src/mlpack/methods/hmm/hmm_loglik_main.cpp | 2 +- src/mlpack/methods/hmm/hmm_train_main.cpp | 2 +- src/mlpack/methods/hmm/hmm_viterbi_main.cpp | 2 +- .../methods/hoeffding_trees/hoeffding_tree_main.cpp | 2 +- src/mlpack/methods/kde/kde_main.cpp | 2 +- src/mlpack/methods/kernel_pca/kernel_pca_main.cpp | 2 +- src/mlpack/methods/kmeans/kmeans_main.cpp | 2 +- src/mlpack/methods/lars/lars_main.cpp | 2 +- .../linear_regression/linear_regression_main.cpp | 2 +- src/mlpack/methods/linear_svm/linear_svm_main.cpp | 2 +- src/mlpack/methods/lmnn/lmnn_main.cpp | 2 +- .../local_coordinate_coding_main.cpp | 2 +- .../logistic_regression/logistic_regression_main.cpp | 2 +- src/mlpack/methods/lsh/lsh_main.cpp | 2 +- src/mlpack/methods/mean_shift/mean_shift_main.cpp | 2 +- src/mlpack/methods/mvu/mvu_main.cpp | 2 +- src/mlpack/methods/naive_bayes/nbc_main.cpp | 2 +- src/mlpack/methods/nca/nca_main.cpp | 2 +- src/mlpack/methods/neighbor_search/kfn_main.cpp | 2 +- src/mlpack/methods/neighbor_search/knn_main.cpp | 2 +- src/mlpack/methods/nmf/nmf_main.cpp | 2 +- src/mlpack/methods/pca/pca_main.cpp | 2 +- src/mlpack/methods/perceptron/perceptron_main.cpp | 2 +- .../methods/preprocess/image_converter_main.cpp | 2 +- .../methods/preprocess/preprocess_binarize_main.cpp | 2 +- .../methods/preprocess/preprocess_describe_main.cpp | 2 +- .../methods/preprocess/preprocess_imputer_main.cpp | 2 +- .../preprocess/preprocess_one_hot_encoding_main.cpp | 2 +- .../methods/preprocess/preprocess_scale_main.cpp | 2 +- .../methods/preprocess/preprocess_split_main.cpp | 2 +- src/mlpack/methods/radical/radical_main.cpp | 2 +- .../methods/random_forest/random_forest_main.cpp | 2 +- src/mlpack/methods/range_search/range_search_main.cpp | 2 +- src/mlpack/methods/rann/krann_main.cpp | 2 +- .../softmax_regression/softmax_regression_main.cpp | 2 +- .../methods/sparse_coding/sparse_coding_main.cpp | 2 +- 52 files changed, 68 insertions(+), 53 deletions(-) diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 9e84539a75..e664c71e28 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -83,8 +83,10 @@ void PrintPYX(const util::BindingDetails& doc, cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, " << "ResetTimers, EnableTimers" << endl; cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl; - cout << "from preprocess_json_params import process_params_out, process_params_in" << endl; - cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON, SerializeInJSON" << endl; + cout << "from preprocess_json_params import process_params_out, " + << "process_params_in" << endl; + cout << "from serialization cimport SerializeIn, SerializeOut, " + << "SerializeOutJSON, SerializeInJSON" << endl; cout << endl; cout << "import numpy as np" << endl; cout << "cimport numpy as np" << endl; @@ -100,7 +102,8 @@ void PrintPYX(const util::BindingDetails& doc, // Import the program we will be using. cout << "cdef extern from \"<" << mainFilename << ">\" nogil:" << endl; - cout << " cdef void " << bindingName << "(Params, Timers)" << " nogil except +RuntimeError" << endl; + cout << " cdef void mlpack_" << bindingName << "(Params, Timers)" + << " nogil except +RuntimeError" << endl; cout << " " << endl; // Print any class definitions we need to have. std::set classes; @@ -241,7 +244,7 @@ void PrintPYX(const util::BindingDetails& doc, // Call the method. cout << " # Call the mlpack program." << endl; - cout << " " << bindingName << "(p, t)" << endl; + cout << " mlpack_" << bindingName << "(p, t)" << endl; // Do any output processing and return. cout << " # Initialize result dictionary." << endl; diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index dacc11d31f..5a67c3c51e 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -220,6 +220,12 @@ using Option = mlpack::bindings::python::PyOption; #include +// In Python, we want to call the binding function mlpack_() +// instead of just (), so we change the definition of +// BINDING_FUNCTION(). +#undef BINDING_FUNCTION +#define BINDING_FUNCTION(...) JOIN(mlpack_, BINDING_NAME)(__VA_ARGS__) + #ifndef BINDING_NAME #error "BINDING_NAME not defined!" #endif diff --git a/src/mlpack/core/util/param.hpp b/src/mlpack/core/util/param.hpp index 3c876e9c24..9cb0ebbbe7 100644 --- a/src/mlpack/core/util/param.hpp +++ b/src/mlpack/core/util/param.hpp @@ -43,6 +43,12 @@ using DatasetInfo = DatasetMapper; /** @endcond */ +/** + * Define the function to be called for a given binding. BINDING_NAME should be + * set before calling this. + */ +#define BINDING_FUNCTION(...) BINDING_NAME(__VA_ARGS__) + /** * Specify the user-friendly name of a binding. Only one instance of this macro * should be present per binding. BINDING_NAME should be set before calling diff --git a/src/mlpack/methods/adaboost/adaboost_main.cpp b/src/mlpack/methods/adaboost/adaboost_main.cpp index d671294c71..8b293fd573 100644 --- a/src/mlpack/methods/adaboost/adaboost_main.cpp +++ b/src/mlpack/methods/adaboost/adaboost_main.cpp @@ -152,7 +152,7 @@ PARAM_MODEL_IN(AdaBoostModel, "input_model", "Input AdaBoost model.", "m"); PARAM_MODEL_OUT(AdaBoostModel, "output_model", "Output trained AdaBoost model.", "M"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Check input parameters and issue warnings/errors as necessary. diff --git a/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp b/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp index e230553b56..7308fe48f3 100644 --- a/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp +++ b/src/mlpack/methods/approx_kfn/approx_kfn_main.cpp @@ -177,7 +177,7 @@ PARAM_MODEL_IN(ApproxKFNModel, "input_model", "File containing input model.", PARAM_MODEL_OUT(ApproxKFNModel, "output_model", "File to save output model to.", "M"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // We have to pass either a reference set or an input model. RequireOnlyOnePassed(params, { "reference", "input_model" }); diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp index 6964b75595..1fd150e9bc 100644 --- a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp @@ -133,7 +133,7 @@ PARAM_FLAG("center", "Center the data and fit the intercept if enabled.", "c"); PARAM_FLAG("scale", "Scale each feature by their standard deviations if " "enabled.", "s"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { bool center = params.Get("center"); bool scale = params.Get("scale"); diff --git a/src/mlpack/methods/cf/cf_main.cpp b/src/mlpack/methods/cf/cf_main.cpp index 3ca507d789..21055ba109 100644 --- a/src/mlpack/methods/cf/cf_main.cpp +++ b/src/mlpack/methods/cf/cf_main.cpp @@ -199,7 +199,7 @@ PARAM_STRING_IN("interpolation", "Algorithm used for weight interpolation.", PARAM_STRING_IN("neighbor_search", "Algorithm used for neighbor search.", "S", "euclidean"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") == 0) math::RandomSeed(std::time(NULL)); diff --git a/src/mlpack/methods/dbscan/dbscan_main.cpp b/src/mlpack/methods/dbscan/dbscan_main.cpp index d14535e773..ca5765e820 100644 --- a/src/mlpack/methods/dbscan/dbscan_main.cpp +++ b/src/mlpack/methods/dbscan/dbscan_main.cpp @@ -154,7 +154,7 @@ void ChoosePointSelectionPolicy(util::Params& params, RunDBSCAN(params, rs); } -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { RequireAtLeastOnePassed(params, { "assignments", "centroids" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/decision_tree/decision_tree_main.cpp b/src/mlpack/methods/decision_tree/decision_tree_main.cpp index 74117e3656..91349b05a4 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_main.cpp +++ b/src/mlpack/methods/decision_tree/decision_tree_main.cpp @@ -161,7 +161,7 @@ PARAM_MODEL_OUT(DecisionTreeModel, "output_model", "Output for trained decision" // Convenience typedef. typedef tuple TupleType; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Check parameters. RequireOnlyOnePassed(params, { "training", "input_model" }, true); diff --git a/src/mlpack/methods/det/det_main.cpp b/src/mlpack/methods/det/det_main.cpp index f1d021c25d..c701c53dff 100644 --- a/src/mlpack/methods/det/det_main.cpp +++ b/src/mlpack/methods/det/det_main.cpp @@ -125,7 +125,7 @@ PARAM_FLAG("volume_regularization", "This flag gives the used the option to use" "penalize low volume leaves.", "R"); */ -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Validate input parameters. RequireOnlyOnePassed(params, { "training", "input_model" }, true); diff --git a/src/mlpack/methods/emst/emst_main.cpp b/src/mlpack/methods/emst/emst_main.cpp index 7a868dcd1e..298cedeed4 100644 --- a/src/mlpack/methods/emst/emst_main.cpp +++ b/src/mlpack/methods/emst/emst_main.cpp @@ -98,7 +98,7 @@ using namespace mlpack::metric; using namespace mlpack::util; using namespace std; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { RequireAtLeastOnePassed(params, { "output" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/fastmks/fastmks_main.cpp b/src/mlpack/methods/fastmks/fastmks_main.cpp index 51cc43dea5..cb249ad078 100644 --- a/src/mlpack/methods/fastmks/fastmks_main.cpp +++ b/src/mlpack/methods/fastmks/fastmks_main.cpp @@ -111,7 +111,7 @@ PARAM_FLAG("single", "If true, single-tree search is used (as opposed to " PARAM_MATRIX_OUT("kernels", "Output matrix of kernels.", "p"); PARAM_UMATRIX_OUT("indices", "Output matrix of indices.", "i"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Validate command-line parameters. RequireOnlyOnePassed(params, { "reference", "input_model" }, true); diff --git a/src/mlpack/methods/gmm/gmm_generate_main.cpp b/src/mlpack/methods/gmm/gmm_generate_main.cpp index b52d89544c..1f1c9eecc9 100644 --- a/src/mlpack/methods/gmm/gmm_generate_main.cpp +++ b/src/mlpack/methods/gmm/gmm_generate_main.cpp @@ -67,7 +67,7 @@ PARAM_MATRIX_OUT("output", "Matrix to save output samples in.", "o"); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Parameter sanity checks. RequireAtLeastOnePassed(params, { "output" }, false, diff --git a/src/mlpack/methods/gmm/gmm_probability_main.cpp b/src/mlpack/methods/gmm/gmm_probability_main.cpp index 2d1468d34c..851670dc9a 100644 --- a/src/mlpack/methods/gmm/gmm_probability_main.cpp +++ b/src/mlpack/methods/gmm/gmm_probability_main.cpp @@ -67,7 +67,7 @@ PARAM_MATRIX_IN_REQ("input", "Input matrix to calculate probabilities of.", PARAM_MATRIX_OUT("output", "Matrix to store calculated probabilities in.", "o"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { RequireAtLeastOnePassed(params, { "output" }, false, "no results will be saved"); diff --git a/src/mlpack/methods/gmm/gmm_train_main.cpp b/src/mlpack/methods/gmm/gmm_train_main.cpp index 25a86606e1..e1ebf6a12c 100644 --- a/src/mlpack/methods/gmm/gmm_train_main.cpp +++ b/src/mlpack/methods/gmm/gmm_train_main.cpp @@ -151,7 +151,7 @@ PARAM_MODEL_IN(GMM, "input_model", "Initial input GMM model to start training " "with.", "m"); PARAM_MODEL_OUT(GMM, "output_model", "Output for trained GMM model.", "M"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Check parameters and load data. if (params.Get("seed") != 0) diff --git a/src/mlpack/methods/hmm/hmm_generate_main.cpp b/src/mlpack/methods/hmm/hmm_generate_main.cpp index d7e3e6d5a6..257bd46bad 100644 --- a/src/mlpack/methods/hmm/hmm_generate_main.cpp +++ b/src/mlpack/methods/hmm/hmm_generate_main.cpp @@ -125,7 +125,7 @@ struct Generate } }; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { RequireAtLeastOnePassed(params, { "output", "state" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/hmm/hmm_loglik_main.cpp b/src/mlpack/methods/hmm/hmm_loglik_main.cpp index cdf573882f..c671fe5b05 100644 --- a/src/mlpack/methods/hmm/hmm_loglik_main.cpp +++ b/src/mlpack/methods/hmm/hmm_loglik_main.cpp @@ -105,7 +105,7 @@ struct Loglik } }; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Load model, and calculate the log-likelihood of the sequence. params.Get("input_model")->PerformAction( diff --git a/src/mlpack/methods/hmm/hmm_train_main.cpp b/src/mlpack/methods/hmm/hmm_train_main.cpp index 091d3c9d53..0ba6550378 100644 --- a/src/mlpack/methods/hmm/hmm_train_main.cpp +++ b/src/mlpack/methods/hmm/hmm_train_main.cpp @@ -437,7 +437,7 @@ struct Train } }; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Set random seed. if (params.Get("seed") != 0) diff --git a/src/mlpack/methods/hmm/hmm_viterbi_main.cpp b/src/mlpack/methods/hmm/hmm_viterbi_main.cpp index 4e43542924..6ba70d986d 100644 --- a/src/mlpack/methods/hmm/hmm_viterbi_main.cpp +++ b/src/mlpack/methods/hmm/hmm_viterbi_main.cpp @@ -110,7 +110,7 @@ struct Viterbi } }; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { RequireAtLeastOnePassed(params, { "output" }, false, "no results will be saved"); diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp index 5784670a37..827471e1f4 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp @@ -140,7 +140,7 @@ PARAM_INT_IN("observations_before_binning", "If the 'domingos' split strategy " // Convenience typedef. typedef tuple TupleType; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Check input parameters for validity. const string numericSplitStrategy = diff --git a/src/mlpack/methods/kde/kde_main.cpp b/src/mlpack/methods/kde/kde_main.cpp index b2dad09aef..9ff2c04020 100644 --- a/src/mlpack/methods/kde/kde_main.cpp +++ b/src/mlpack/methods/kde/kde_main.cpp @@ -198,7 +198,7 @@ PARAM_COL_OUT("predictions", "Vector to store density predictions.", // Maybe, in the future, it could be interesting to implement different metrics. -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Get some parameters. const double bandwidth = params.Get("bandwidth"); diff --git a/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp b/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp index 574a7109ac..a5fc1e6acc 100644 --- a/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp +++ b/src/mlpack/methods/kernel_pca/kernel_pca_main.cpp @@ -190,7 +190,7 @@ void RunKPCA(arma::mat& dataset, } } -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { RequireAtLeastOnePassed(params, { "output" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/kmeans/kmeans_main.cpp b/src/mlpack/methods/kmeans/kmeans_main.cpp index 5640ffb273..67b60a8d79 100644 --- a/src/mlpack/methods/kmeans/kmeans_main.cpp +++ b/src/mlpack/methods/kmeans/kmeans_main.cpp @@ -187,7 +187,7 @@ void RunKMeans(util::Params& params, util::Timers& timers, const InitialPartitionPolicy& ipp); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Initialize random seed. if (params.Get("seed") != 0) diff --git a/src/mlpack/methods/lars/lars_main.cpp b/src/mlpack/methods/lars/lars_main.cpp index aa5308daed..4481408f6c 100644 --- a/src/mlpack/methods/lars/lars_main.cpp +++ b/src/mlpack/methods/lars/lars_main.cpp @@ -127,7 +127,7 @@ PARAM_DOUBLE_IN("lambda2", "Regularization parameter for l2-norm penalty.", "L", PARAM_FLAG("use_cholesky", "Use Cholesky decomposition during computation " "rather than explicitly computing the full Gram matrix.", "c"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { double lambda1 = params.Get("lambda1"); double lambda2 = params.Get("lambda2"); diff --git a/src/mlpack/methods/linear_regression/linear_regression_main.cpp b/src/mlpack/methods/linear_regression/linear_regression_main.cpp index 3af254363e..45b550e37d 100644 --- a/src/mlpack/methods/linear_regression/linear_regression_main.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression_main.cpp @@ -114,7 +114,7 @@ PARAM_ROW_OUT("output_predictions", "If --test_file is specified, this " PARAM_DOUBLE_IN("lambda", "Tikhonov regularization for ridge regression. If 0," " the method reduces to linear regression.", "l", 0.0); -void BINDING_NAME(util::Params& params, util::Timers& timer) +void BINDING_FUNCTION(util::Params& params, util::Timers& timer) { const double lambda = params.Get("lambda"); diff --git a/src/mlpack/methods/linear_svm/linear_svm_main.cpp b/src/mlpack/methods/linear_svm/linear_svm_main.cpp index 465ba970a5..c34deb0acf 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_main.cpp +++ b/src/mlpack/methods/linear_svm/linear_svm_main.cpp @@ -175,7 +175,7 @@ PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " "matrix is where the class probabilities for the test set will be saved.", "p"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/lmnn/lmnn_main.cpp b/src/mlpack/methods/lmnn/lmnn_main.cpp index a0c9d701a5..d2fcf8300f 100644 --- a/src/mlpack/methods/lmnn/lmnn_main.cpp +++ b/src/mlpack/methods/lmnn/lmnn_main.cpp @@ -235,7 +235,7 @@ double KNNAccuracy(const arma::mat& dataset, return ((double) count / dataset.n_cols) * 100; } -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp b/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp index 7785f571c1..ba1401db3f 100644 --- a/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp +++ b/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp @@ -122,7 +122,7 @@ PARAM_MATRIX_OUT("codes", "Output codes matrix.", "c"); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 0a1d180bf1..cbbf269cf2 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -177,7 +177,7 @@ PARAM_DOUBLE_IN("decision_boundary", "Decision boundary for prediction; if the " "logistic function for a point is less than the boundary, the class is " "taken to be 0; otherwise, the class is 1.", "d", 0.5); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Collect command-line options. const double lambda = params.Get("lambda"); diff --git a/src/mlpack/methods/lsh/lsh_main.cpp b/src/mlpack/methods/lsh/lsh_main.cpp index 3905ed8c9c..a46cd2765b 100644 --- a/src/mlpack/methods/lsh/lsh_main.cpp +++ b/src/mlpack/methods/lsh/lsh_main.cpp @@ -111,7 +111,7 @@ PARAM_INT_IN("bucket_size", "The size of a bucket in the second level hash.", "B", 500); PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/mean_shift/mean_shift_main.cpp b/src/mlpack/methods/mean_shift/mean_shift_main.cpp index c0b212583b..a5fbcd3855 100644 --- a/src/mlpack/methods/mean_shift/mean_shift_main.cpp +++ b/src/mlpack/methods/mean_shift/mean_shift_main.cpp @@ -98,7 +98,7 @@ PARAM_DOUBLE_IN("radius", "If the distance between two centroids is less than " "the given radius, one will be removed. A radius of 0 or less means an " "estimate will be calculated and used for the radius.", "r", 0); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { const double radius = params.Get("radius"); const int maxIterations = params.Get("max_iterations"); diff --git a/src/mlpack/methods/mvu/mvu_main.cpp b/src/mlpack/methods/mvu/mvu_main.cpp index 029f29c0f6..d287841bac 100644 --- a/src/mlpack/methods/mvu/mvu_main.cpp +++ b/src/mlpack/methods/mvu/mvu_main.cpp @@ -46,7 +46,7 @@ using namespace mlpack::util; using namespace arma; using namespace std; -void BINDING_NAME(util::Params& params, util::Timers& timers); +void BINDING_FUNCTION(util::Params& params, util::Timers& timers); { const string inputFile = params.Get("input_file"); const string outputFile = params.Get("output_file"); diff --git a/src/mlpack/methods/naive_bayes/nbc_main.cpp b/src/mlpack/methods/naive_bayes/nbc_main.cpp index ef7c0cf140..30a28a322d 100644 --- a/src/mlpack/methods/naive_bayes/nbc_main.cpp +++ b/src/mlpack/methods/naive_bayes/nbc_main.cpp @@ -143,7 +143,7 @@ PARAM_MATRIX_OUT("output_probs", "The matrix in which the predicted probability" PARAM_MATRIX_OUT("probabilities", "The matrix in which the predicted" " probability of labels for the test set will be written.", "p"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Check input parameters. RequireOnlyOnePassed(params, { "training", "input_model" }, true); diff --git a/src/mlpack/methods/nca/nca_main.cpp b/src/mlpack/methods/nca/nca_main.cpp index a317af66e7..c5dceaa007 100644 --- a/src/mlpack/methods/nca/nca_main.cpp +++ b/src/mlpack/methods/nca/nca_main.cpp @@ -149,7 +149,7 @@ using namespace mlpack::metric; using namespace mlpack::util; using namespace std; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/neighbor_search/kfn_main.cpp b/src/mlpack/methods/neighbor_search/kfn_main.cpp index 0903c8e1e7..f911cf50a3 100644 --- a/src/mlpack/methods/neighbor_search/kfn_main.cpp +++ b/src/mlpack/methods/neighbor_search/kfn_main.cpp @@ -121,7 +121,7 @@ PARAM_DOUBLE_IN("percentage", "If specified, will do approximate furthest " "neighbors will be at least (p*100) % of the distance as the true furthest " "neighbor.", "p", 1); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/neighbor_search/knn_main.cpp b/src/mlpack/methods/neighbor_search/knn_main.cpp index 98cc810af8..97b2bb96ea 100644 --- a/src/mlpack/methods/neighbor_search/knn_main.cpp +++ b/src/mlpack/methods/neighbor_search/knn_main.cpp @@ -129,7 +129,7 @@ PARAM_STRING_IN("algorithm", "Type of neighbor search: 'naive', 'single_tree', " PARAM_DOUBLE_IN("epsilon", "If specified, will do approximate nearest neighbor " "search with given relative error.", "e", 0); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/nmf/nmf_main.cpp b/src/mlpack/methods/nmf/nmf_main.cpp index 8ffe846b0c..232c5f1e92 100644 --- a/src/mlpack/methods/nmf/nmf_main.cpp +++ b/src/mlpack/methods/nmf/nmf_main.cpp @@ -213,7 +213,7 @@ void ApplyFactorization(util::Params& params, } } -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Initialize random seed. if (params.Get("seed") != 0) diff --git a/src/mlpack/methods/pca/pca_main.cpp b/src/mlpack/methods/pca/pca_main.cpp index b552abf850..6f0be01b88 100644 --- a/src/mlpack/methods/pca/pca_main.cpp +++ b/src/mlpack/methods/pca/pca_main.cpp @@ -124,7 +124,7 @@ void RunPCA(util::Params& params, dataset.n_rows << " dimensions)." << endl; } -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Load input dataset. arma::mat& dataset = params.Get("input"); diff --git a/src/mlpack/methods/perceptron/perceptron_main.cpp b/src/mlpack/methods/perceptron/perceptron_main.cpp index d66d706d74..efd68c5231 100644 --- a/src/mlpack/methods/perceptron/perceptron_main.cpp +++ b/src/mlpack/methods/perceptron/perceptron_main.cpp @@ -155,7 +155,7 @@ PARAM_UROW_OUT("output", "The matrix in which the predicted labels for the" PARAM_UROW_OUT("predictions", "The matrix in which the predicted labels for the" " test set will be written.", "P"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // First, get all parameters and validate them. const size_t maxIterations = (size_t) params.Get("max_iterations"); diff --git a/src/mlpack/methods/preprocess/image_converter_main.cpp b/src/mlpack/methods/preprocess/image_converter_main.cpp index 16c48bc954..75d7537696 100644 --- a/src/mlpack/methods/preprocess/image_converter_main.cpp +++ b/src/mlpack/methods/preprocess/image_converter_main.cpp @@ -86,7 +86,7 @@ PARAM_INT_IN("height", "Height of the images.", "H", 0); PARAM_FLAG("save", "Save a dataset as images.", "s"); PARAM_MATRIX_IN("dataset", "Input matrix to save as images.", "I"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Parse command line options. const vector fileNames = params.Get >("input"); diff --git a/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp b/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp index 036c171f63..5205802823 100644 --- a/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_binarize_main.cpp @@ -78,7 +78,7 @@ using namespace mlpack::util; using namespace arma; using namespace std; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { const size_t dimension = (size_t) params.Get("dimension"); const double threshold = params.Get("threshold"); diff --git a/src/mlpack/methods/preprocess/preprocess_describe_main.cpp b/src/mlpack/methods/preprocess/preprocess_describe_main.cpp index 2e1ec4b047..04faf5fe9c 100644 --- a/src/mlpack/methods/preprocess/preprocess_describe_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_describe_main.cpp @@ -176,7 +176,7 @@ double StandardError(const size_t size, const double& fStd) return fStd / sqrt(size); } -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { const size_t dimension = static_cast(params.Get("dimension")); const size_t precision = static_cast(params.Get("precision")); diff --git a/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp b/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp index b602405b52..6cffa8fe74 100644 --- a/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_imputer_main.cpp @@ -78,7 +78,7 @@ using namespace arma; using namespace std; using namespace data; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { const string inputFile = params.Get("input_file"); const string outputFile = params.Get("output_file"); diff --git a/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp b/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp index adf5a3e9ea..108f173fbc 100644 --- a/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp @@ -65,7 +65,7 @@ using namespace mlpack::util; using namespace arma; using namespace std; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Load the data. const arma::mat& data = params.Get("input"); diff --git a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp index 87a594708e..351421e89d 100644 --- a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp @@ -116,7 +116,7 @@ PARAM_FLAG("inverse_scaling", "Inverse Scaling to get original dataset", "f"); PARAM_MODEL_IN(ScalingModel, "input_model", "Input Scaling model.", "m"); PARAM_MODEL_OUT(ScalingModel, "output_model", "Output scaling model.", "M"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Parse command line options. const std::string scalerMethod = params.Get("scaler_method"); diff --git a/src/mlpack/methods/preprocess/preprocess_split_main.cpp b/src/mlpack/methods/preprocess/preprocess_split_main.cpp index 1d3fcfb6ca..d74801895c 100644 --- a/src/mlpack/methods/preprocess/preprocess_split_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_split_main.cpp @@ -111,7 +111,7 @@ using namespace mlpack::util; using namespace arma; using namespace std; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Parse command line options. const double testRatio = params.Get("test_ratio"); diff --git a/src/mlpack/methods/radical/radical_main.cpp b/src/mlpack/methods/radical/radical_main.cpp index 1b08d5593c..6f52dac94c 100644 --- a/src/mlpack/methods/radical/radical_main.cpp +++ b/src/mlpack/methods/radical/radical_main.cpp @@ -87,7 +87,7 @@ using namespace mlpack::util; using namespace std; using namespace arma; -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Set random seed. if (params.Get("seed") != 0) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 007a2ea302..d2663c8d09 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -167,7 +167,7 @@ PARAM_MODEL_IN(RandomForestModel, "input_model", "Pre-trained random forest to " PARAM_MODEL_OUT(RandomForestModel, "output_model", "Model to save trained " "random forest to.", "M"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Initialize random seed if needed. if (params.Get("seed") != 0) diff --git a/src/mlpack/methods/range_search/range_search_main.cpp b/src/mlpack/methods/range_search/range_search_main.cpp index abe95342a0..6454c07779 100644 --- a/src/mlpack/methods/range_search/range_search_main.cpp +++ b/src/mlpack/methods/range_search/range_search_main.cpp @@ -120,7 +120,7 @@ PARAM_FLAG("naive", "If true, O(n^2) naive mode is used for computation.", "N"); PARAM_FLAG("single_mode", "If true, single-tree search is used (as opposed to " "dual-tree search).", "S"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/rann/krann_main.cpp b/src/mlpack/methods/rann/krann_main.cpp index 8aaf9f42af..5dd6fad2bd 100644 --- a/src/mlpack/methods/rann/krann_main.cpp +++ b/src/mlpack/methods/rann/krann_main.cpp @@ -124,7 +124,7 @@ PARAM_FLAG("first_leaf_exact", "The flag to trigger sampling only after " PARAM_INT_IN("single_sample_limit", "The limit on the maximum number of " "samples (and hence the largest node you can approximate).", "z", 20); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp index d3ed250acd..5532b8ed76 100644 --- a/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp +++ b/src/mlpack/methods/softmax_regression/softmax_regression_main.cpp @@ -146,7 +146,7 @@ void TestClassifyAcc(util::Params& params, template Model* TrainSoftmax(util::Params& params, const size_t maxIterations); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { const int maxIterations = params.Get("max_iterations"); diff --git a/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp b/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp index 8af2603a07..bd236d129b 100644 --- a/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp +++ b/src/mlpack/methods/sparse_coding/sparse_coding_main.cpp @@ -130,7 +130,7 @@ PARAM_MATRIX_OUT("codes", "Matrix to save the output sparse codes of the test " PARAM_MATRIX_IN("test", "Optional matrix to be encoded by trained model.", "T"); -void BINDING_NAME(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) RandomSeed((size_t) params.Get("seed")); From 43d9c633c177e39101c626e7f07ed80d81149fef Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sat, 3 Jul 2021 08:29:30 +0530 Subject: [PATCH 508/729] removed `_py` from name --- src/mlpack/bindings/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/CMakeLists.txt b/src/mlpack/bindings/python/CMakeLists.txt index 50488f5c28..fc3a532c44 100644 --- a/src/mlpack/bindings/python/CMakeLists.txt +++ b/src/mlpack/bindings/python/CMakeLists.txt @@ -297,7 +297,7 @@ if (BUILD_PYTHON_BINDINGS) # Add the convenience import to __init__.py. Note that this happens during # configuration. file(APPEND ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/__init__.py - "from .${name} import ${name}_py\n") + "from .${name} import ${name}\n") endif () endmacro () From 6db1f6059b1ea80ad44060e8cc50ad15401a7c3a Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sat, 3 Jul 2021 08:32:36 +0530 Subject: [PATCH 509/729] changed functionName to be same as bindingName --- src/mlpack/bindings/python/print_pyx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 9e84539a75..de0bc5e7f3 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -35,7 +35,7 @@ void PrintPYX(const util::BindingDetails& doc, const string& mainFilename, const string& bindingName) { - std::string functionName = bindingName + "_py"; + std::string functionName = bindingName; util::Params params = IO::Parameters(bindingName); From b81c84c09389fc1d7c6f8d398c09f6b27c785f0a Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 3 Jul 2021 16:22:21 +0530 Subject: [PATCH 510/729] moved sse_loss.hpp to parent directory's CMakeLists.txt --- src/mlpack/methods/xgboost/CMakeLists.txt | 1 + .../methods/xgboost/loss_functions/CMakeLists.txt | 14 -------------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt diff --git a/src/mlpack/methods/xgboost/CMakeLists.txt b/src/mlpack/methods/xgboost/CMakeLists.txt index 63339c806e..37be5ee1d1 100644 --- a/src/mlpack/methods/xgboost/CMakeLists.txt +++ b/src/mlpack/methods/xgboost/CMakeLists.txt @@ -1,6 +1,7 @@ # Define the files we need to compile. # Anything not in this list will not be compiled into mlpack. set(SOURCES + loss_functions/sse_loss.hpp ) # Add directory name to sources. diff --git a/src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt b/src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt deleted file mode 100644 index 30ffd3867e..0000000000 --- a/src/mlpack/methods/xgboost/loss_functions/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Define the files we need to compile. -# Anything not in this list will not be compiled into mlpack. -set(SOURCES - sse_loss.hpp -) - -# Add directory name to sources. -set(DIR_SRCS) -foreach(file ${SOURCES}) - set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) -endforeach() -# Append sources (with directory name) to list of all mlpack sources (used at -# the parent scope). -set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE) From d082f9a866fe74f992e9ec7d8612118cc9274907 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 3 Jul 2021 16:56:52 +0530 Subject: [PATCH 511/729] Change enable_if statement to use cleaner syntax --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index bae167fffc..50e016524c 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -71,8 +71,7 @@ class SSELoss * values. This is used only for vectors. */ template::value || - arma::is_Row::value>> + class = std::enable_if_t> VecType Hessians(const VecType& /* observed */, const VecType& values) { VecType h(values.n_elem, arma::fill::ones); From 49542147407d4f6b4ef1a1126ab282f3be33e220 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Sat, 3 Jul 2021 23:03:03 +0530 Subject: [PATCH 512/729] this is not needed here --- src/mlpack/core/util/mlpack_main.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index f3338538a3..8f7d1fad4f 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -172,8 +172,7 @@ using Option = mlpack::bindings::tests::TestOption; * PRINT_PARAM_STRING() returns a string that contains the correct * language-specific representation of a parameter's name. */ -#define PRINT_PARAM_STRING(x) mlpack::bindings::python::ParamString( \ - STRINGIFY(BINDING_NAME), x) +#define PRINT_PARAM_STRING mlpack::bindings::python::ParamString /** * PRINT_PARAM_VALUE() returns a string that contains a correct From 9260f22734bffd00b61e38a80de016de4a050b59 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 00:06:51 +0530 Subject: [PATCH 513/729] First commit. Added bicubic interpolation --- .../ann/layer/bicubic_interpolation.hpp | 158 +++++++++++++++ .../ann/layer/bicubic_interpolation_impl.hpp | 191 ++++++++++++++++++ 2 files changed, 349 insertions(+) create mode 100644 src/mlpack/methods/ann/layer/bicubic_interpolation.hpp create mode 100644 src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp new file mode 100644 index 0000000000..8595bc4d57 --- /dev/null +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp @@ -0,0 +1,158 @@ +/** + * @file methods/ann/layer/bilinear_interpolation.hpp + * @author Kris Singh + * @author Shikhar Jaiswal + * + * 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_BILINEAR_INTERPOLATION_HPP +#define MLPACK_METHODS_ANN_LAYER_BILINEAR_INTERPOLATION_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Definition and Implementation of the Bilinear Interpolation Layer. + * + * Bilinear Interpolation is an mathematical technique, primarily used for + * scaling purposes. It is an extension of linear interpolation, for + * interpolating functions of two variables on a rectangular grid. The key + * idea is to perform linear interpolation first in one direction (e.g., along + * x-axis), and then again in the other direction (i.e., y-axis), on four + * different known points in the grid. This way, we represent any arbitrary + * point, present within the grid, as a function of those four points. + * + * @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 BilinearInterpolation +{ + public: + //! Create the Bilinear Interpolation object. + BilinearInterpolation(); + + /** + * The constructor for the Bilinear Interpolation. + * + * @param inRowSize Number of input rows. + * @param inColSize Number of input columns. + * @param outRowSize Number of output rows. + * @param outColSize Number of output columns. + * @param depth Number of input slices. + */ + BilinearInterpolation(const size_t inRowSize, + const size_t inColSize, + const size_t outRowSize, + const size_t outColSize, + const size_t depth); + + /** + * Forward pass through the layer. The layer interpolates + * the matrix using the given Bilinear Interpolation method. + * + * @param input The input matrix. + * @param output The resulting interpolated output matrix. + */ + template + void Forward(const arma::Mat& input, arma::Mat& 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. Since the layer does not have any learn-able parameters, + * we just have to down-sample the gradient to make its size compatible with + * the input size. + * + * @param * (input) The input matrix. + * @param gradient The computed backward gradient. + * @param output The resulting down-sampled output. + */ + template + void Backward(const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output); + + //! Get the output parameter. + OutputDataType const& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const& Delta() const { return delta; } + //! Modify the delta. + OutputDataType& Delta() { return delta; } + + //! Get the row size of the input. + size_t const& InRowSize() const { return inRowSize; } + //! Modify the row size of the input. + size_t& InRowSize() { return inRowSize; } + + //! Get the column size of the input. + size_t const& InColSize() const { return inColSize; } + //! Modify the column size of the input. + size_t& InColSize() { return inColSize; } + + //! Get the row size of the output. + size_t const& OutRowSize() const { return outRowSize; } + //! Modify the row size of the output. + size_t& OutRowSize() { return outRowSize; } + + //! Get the column size of the output. + size_t const& OutColSize() const { return outColSize; } + //! Modify the column size of the output. + size_t& OutColSize() { return outColSize; } + + //! Get the depth of the input. + size_t const& InDepth() const { return depth; } + //! Modify the depth of the input. + size_t& InDepth() { return depth; } + + //! Get the shape of the input. + size_t InputShape() const + { + return inRowSize; + } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& ar, const uint32_t /* version */); + + private: + //! Locally stored row size of the input. + size_t inRowSize; + //! Locally stored column size of the input. + size_t inColSize; + //! Locally stored row size of the output. + size_t outRowSize; + //! Locally stored column size of the input. + size_t outColSize; + //! Locally stored depth of the input. + size_t depth; + //! Locally stored number of input points. + size_t batchSize; + //! Locally-stored delta object. + OutputDataType delta; + //! Locally-stored output parameter object. + OutputDataType outputParameter; +}; // class BilinearInterpolation + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "bilinear_interpolation_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp new file mode 100644 index 0000000000..3621f099b3 --- /dev/null +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -0,0 +1,191 @@ +/** + * @file methods/ann/layer/bilinear_interpolation_impl.hpp + * @author Kris Singh + * @author Shikhar Jaiswal + * + * Implementation of the bilinear interpolation function as an individual layer. + * + * 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_BILINEAR_INTERPOLATION_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_BILINEAR_INTERPOLATION_IMPL_HPP + +// In case it hasn't yet been included. +#include "bilinear_interpolation.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + + +template +BilinearInterpolation:: +BilinearInterpolation(): + inRowSize(0), + inColSize(0), + outRowSize(0), + outColSize(0), + depth(0), + batchSize(0) +{ + // Nothing to do here. +} + +template +BilinearInterpolation:: +BilinearInterpolation( + const size_t inRowSize, + const size_t inColSize, + const size_t outRowSize, + const size_t outColSize, + const size_t depth): + inRowSize(inRowSize), + inColSize(inColSize), + outRowSize(outRowSize), + outColSize(outColSize), + depth(depth), + batchSize(0) +{ + // Nothing to do here. +} + +template +template +void BilinearInterpolation::Forward( + const arma::Mat& input, arma::Mat& output) +{ + batchSize = input.n_cols; + if (output.is_empty()) + output.set_size(outRowSize * outColSize * depth, batchSize); + else + { + assert(output.n_rows == outRowSize * outColSize * depth); + assert(output.n_cols == batchSize); + } + + assert(inRowSize >= 2); + assert(inColSize >= 2); + + arma::cube inputAsCube(const_cast&>(input).memptr(), + inRowSize, inColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), outRowSize, outColSize, + depth * batchSize, false, true); + + double scaleRow = (double) inRowSize / (double) outRowSize; + double scaleCol = (double) inColSize / (double) outColSize; + + arma::mat22 coeffs; + for (size_t i = 0; i < outRowSize; ++i) + { + size_t rOrigin = (size_t) std::floor(i * scaleRow); + if (rOrigin > inRowSize - 2) + rOrigin = inRowSize - 2; + + // Scaled distance of the interpolated point from the topmost row. + double deltaR = i * scaleRow - rOrigin; + if (deltaR > 1) + deltaR = 1.0; + for (size_t j = 0; j < outColSize; ++j) + { + // Scaled distance of the interpolated point from the leftmost column. + size_t cOrigin = (size_t) std::floor(j * scaleCol); + if (cOrigin > inColSize - 2) + cOrigin = inColSize - 2; + + double deltaC = j * scaleCol - cOrigin; + if (deltaC > 1) + deltaC = 1.0; + coeffs[0] = (1 - deltaR) * (1 - deltaC); + coeffs[1] = deltaR * (1 - deltaC); + coeffs[2] = (1 - deltaR) * deltaC; + coeffs[3] = deltaR * deltaC; + + for (size_t k = 0; k < depth * batchSize; ++k) + { + outputAsCube(i, j, k) = arma::accu(inputAsCube.slice(k).submat( + rOrigin, cOrigin, rOrigin + 1, cOrigin + 1) % coeffs); + } + } + } +} + +template +template +void BilinearInterpolation::Backward( + const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output) +{ + if (output.is_empty()) + output.set_size(inRowSize * inColSize * depth, batchSize); + else + { + assert(output.n_rows == inRowSize * inColSize * depth); + assert(output.n_cols == batchSize); + } + + assert(outRowSize >= 2); + assert(outColSize >= 2); + + arma::cube gradientAsCube(((arma::Mat&) gradient).memptr(), outRowSize, + outColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, + depth * batchSize, false, true); + + if (gradient.n_elem == output.n_elem) + { + outputAsCube = gradientAsCube; + } + else + { + double scaleRow = (double)(outRowSize) / inRowSize; + double scaleCol = (double)(outColSize) / inColSize; + + arma::mat22 coeffs; + for (size_t i = 0; i < inRowSize; ++i) + { + size_t rOrigin = (size_t) std::floor(i * scaleRow); + if (rOrigin > outRowSize - 2) + rOrigin = outRowSize - 2; + double deltaR = i * scaleRow - rOrigin; + for (size_t j = 0; j < inColSize; ++j) + { + size_t cOrigin = (size_t) std::floor(j * scaleCol); + + if (cOrigin > outColSize - 2) + cOrigin = outColSize - 2; + + double deltaC = j * scaleCol - cOrigin; + coeffs[0] = (1 - deltaR) * (1 - deltaC); + coeffs[1] = deltaR * (1 - deltaC); + coeffs[2] = (1 - deltaR) * deltaC; + coeffs[3] = deltaR * deltaC; + + for (size_t k = 0; k < depth * batchSize; ++k) + { + outputAsCube(i, j, k) = arma::accu(gradientAsCube.slice(k).submat( + rOrigin, cOrigin, rOrigin + 1, cOrigin + 1) % coeffs); + } + } + } + } +} + +template +template +void BilinearInterpolation::serialize( + Archive& ar, const uint32_t /* version */) +{ + ar(CEREAL_NVP(inRowSize)); + ar(CEREAL_NVP(inColSize)); + ar(CEREAL_NVP(outRowSize)); + ar(CEREAL_NVP(outColSize)); + ar(CEREAL_NVP(depth)); +} + +} // namespace ann +} // namespace mlpack + +#endif From a27e9881ae92411f9e53cbda86f374407b32bd0f Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 00:20:05 +0530 Subject: [PATCH 514/729] Added bicubic interpolation --- .../ann/layer/bicubic_interpolation.hpp | 64 +++- .../ann/layer/bicubic_interpolation_impl.hpp | 325 ++++++++++-------- 2 files changed, 228 insertions(+), 161 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp index 8595bc4d57..d8b9c09942 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp @@ -1,15 +1,14 @@ /** - * @file methods/ann/layer/bilinear_interpolation.hpp - * @author Kris Singh - * @author Shikhar Jaiswal + * @file methods/ann/layer/bicubic_interpolation.hpp + * @author Abhinav Anand * * 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_BILINEAR_INTERPOLATION_HPP -#define MLPACK_METHODS_ANN_LAYER_BILINEAR_INTERPOLATION_HPP +#ifndef MLPACK_METHODS_ANN_LAYER_BICUBIC_INTERPOLATION_HPP +#define MLPACK_METHODS_ANN_LAYER_BICUBIC_INTERPOLATION_HPP #include @@ -17,12 +16,12 @@ namespace mlpack { namespace ann /** Artificial Neural Network. */ { /** - * Definition and Implementation of the Bilinear Interpolation Layer. + * Definition and Implementation of the Bicubic Interpolation Layer. * - * Bilinear Interpolation is an mathematical technique, primarily used for - * scaling purposes. It is an extension of linear interpolation, for + * Bicubic Interpolation is an mathematical technique, primarily used for + * scaling purposes. It is an extension of cubic interpolation, for * interpolating functions of two variables on a rectangular grid. The key - * idea is to perform linear interpolation first in one direction (e.g., along + * idea is to perform cubic interpolation first in one direction (e.g., along * x-axis), and then again in the other direction (i.e., y-axis), on four * different known points in the grid. This way, we represent any arbitrary * point, present within the grid, as a function of those four points. @@ -36,14 +35,14 @@ template < typename InputDataType = arma::mat, typename OutputDataType = arma::mat > -class BilinearInterpolation +class BicubicInterpolation { public: - //! Create the Bilinear Interpolation object. - BilinearInterpolation(); + //! Create the Bicubic Interpolation object. + BicubicInterpolation(); /** - * The constructor for the Bilinear Interpolation. + * The constructor for the Bicubic Interpolation. * * @param inRowSize Number of input rows. * @param inColSize Number of input columns. @@ -51,15 +50,16 @@ class BilinearInterpolation * @param outColSize Number of output columns. * @param depth Number of input slices. */ - BilinearInterpolation(const size_t inRowSize, + BicubicInterpolation(const size_t inRowSize, const size_t inColSize, const size_t outRowSize, const size_t outColSize, - const size_t depth); + const size_t depth, + const double alpha); /** * Forward pass through the layer. The layer interpolates - * the matrix using the given Bilinear Interpolation method. + * the matrix using the given Bicubic Interpolation method. * * @param input The input matrix. * @param output The resulting interpolated output matrix. @@ -83,6 +83,12 @@ class BilinearInterpolation const arma::Mat& gradient, arma::Mat& output); + //! Get the size of the weights. + size_t WeightSize() const { return (inRowSize + 5) * (inColSize + 4); } + + template + arma::Mat GetKernalWeight(double a, eT delta); + //! Get the output parameter. OutputDataType const& OutputParameter() const { return outputParameter; } //! Modify the output parameter. @@ -93,6 +99,11 @@ class BilinearInterpolation //! Modify the delta. OutputDataType& Delta() { return delta; } + //! Get the parameters. + OutputDataType const& Parameters() const { return weights; } + //! Modify the parameters. + OutputDataType& Parameters() { return weights; } + //! Get the row size of the input. size_t const& InRowSize() const { return inRowSize; } //! Modify the row size of the input. @@ -118,6 +129,11 @@ class BilinearInterpolation //! Modify the depth of the input. size_t& InDepth() { return depth; } + //! Get the constant value to generate weight. + size_t const& Alpha() const { return alpha; } + //! Modify the constant value to generate weight. + size_t& Alpha() { return alpha; } + //! Get the shape of the input. size_t InputShape() const { @@ -131,6 +147,9 @@ class BilinearInterpolation void serialize(Archive& ar, const uint32_t /* version */); private: + //! Element Type of the input. + typedef typename OutputDataType::elem_type ElemType; + //! Locally stored row size of the input. size_t inRowSize; //! Locally stored column size of the input. @@ -141,18 +160,25 @@ class BilinearInterpolation size_t outColSize; //! Locally stored depth of the input. size_t depth; + //! Locally stored constant value to generate weight. + double alpha; //! Locally stored number of input points. size_t batchSize; //! Locally-stored delta object. OutputDataType delta; //! Locally-stored output parameter object. OutputDataType outputParameter; -}; // class BilinearInterpolation + //! Locally-stored weights parameter. + OutputDataType weights; + + // Locally-stored temp for padded output matrix. + arma::Mat temp; +}; // class BicubicInterpolation } // namespace ann } // namespace mlpack // Include implementation. -#include "bilinear_interpolation_impl.hpp" +#include "bicubic_interpolation_impl.hpp" -#endif +#endif \ No newline at end of file diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 3621f099b3..47d0bb67f5 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -1,37 +1,37 @@ /** - * @file methods/ann/layer/bilinear_interpolation_impl.hpp - * @author Kris Singh - * @author Shikhar Jaiswal + * @file methods/ann/layer/bicubic_interpolation_impl.hpp + * @author Abhinav Anand * - * Implementation of the bilinear interpolation function as an individual layer. + * Implementation of the Bicubic interpolation function as an individual layer. * * 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_BILINEAR_INTERPOLATION_IMPL_HPP -#define MLPACK_METHODS_ANN_LAYER_BILINEAR_INTERPOLATION_IMPL_HPP +#ifndef MLPACK_METHODS_ANN_LAYER_BBICUBIC_INTERPOLATION_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_BICUBIC_INTERPOLATION_IMPL_HPP // In case it hasn't yet been included. -#include "bilinear_interpolation.hpp" +#include "Bicubic_interpolation.hpp" namespace mlpack { namespace ann /** Artificial Neural Network. */ { template -BilinearInterpolation:: -BilinearInterpolation(): - inRowSize(0), - inColSize(0), - outRowSize(0), - outColSize(0), - depth(0), - batchSize(0) -{ +BicubicInterpolation:: +BicubicInterpolation(): + inRowSize(0), + inColSize(0), + outRowSize(0), + outColSize(0), + depth(0), + alpha(0.75), + batchSize(0) + { // Nothing to do here. -} + } template BilinearInterpolation:: @@ -40,152 +40,193 @@ BilinearInterpolation( const size_t inColSize, const size_t outRowSize, const size_t outColSize, - const size_t depth): - inRowSize(inRowSize), - inColSize(inColSize), - outRowSize(outRowSize), - outColSize(outColSize), - depth(depth), - batchSize(0) -{ - // Nothing to do here. -} + const size_t depth, + const double aplha): + inRowSize(inRowSize), + inColSize(inColSize), + outRowSize(outRowSize), + outColSize(outColSize), + depth(depth), + alpha(alpha), + batchSize(0) + { + weights.set_size(WeightSize(), 1); + temp = arma::mat(weights.memptr(), inRowSize + 4, inColSize + 4, false, false); + } +template + void GetKernalWeight(eT delta, arma::mat& coeffs) + { + coeffs(0) = ((A * (delta + 1) - 5 * A) * (delta + 1) + 8 * A) * (delta + 1) - 4 * A; + coeffs(1) = ((A + 2) * delta - (A + 3)) * delta * delta + 1; + coeffs(2) = ((A + 2) * (1 - delta) - (A + 3)) * (1 - delta) * (1 - delta) + 1; + coeffs(3) = 1 - coeffs[0] - coeffs[1] - coeffs[2]; + } template template -void BilinearInterpolation::Forward( - const arma::Mat& input, arma::Mat& output) -{ - batchSize = input.n_cols; - if (output.is_empty()) - output.set_size(outRowSize * outColSize * depth, batchSize); - else +void BicubicInterpolation::Forward( + const arma::Mat& input, arma::Mat& output) { - assert(output.n_rows == outRowSize * outColSize * depth); - assert(output.n_cols == batchSize); - } - - assert(inRowSize >= 2); - assert(inColSize >= 2); - - arma::cube inputAsCube(const_cast&>(input).memptr(), - inRowSize, inColSize, depth * batchSize, false, false); - arma::cube outputAsCube(output.memptr(), outRowSize, outColSize, - depth * batchSize, false, true); - - double scaleRow = (double) inRowSize / (double) outRowSize; - double scaleCol = (double) inColSize / (double) outColSize; - - arma::mat22 coeffs; - for (size_t i = 0; i < outRowSize; ++i) - { - size_t rOrigin = (size_t) std::floor(i * scaleRow); - if (rOrigin > inRowSize - 2) - rOrigin = inRowSize - 2; - - // Scaled distance of the interpolated point from the topmost row. - double deltaR = i * scaleRow - rOrigin; - if (deltaR > 1) - deltaR = 1.0; - for (size_t j = 0; j < outColSize; ++j) + batchSize = input.n_cols; + if (output.is_empty()) + output.set_size(outRowSize * outColSize * depth, batchSize); + else { - // Scaled distance of the interpolated point from the leftmost column. - size_t cOrigin = (size_t) std::floor(j * scaleCol); - if (cOrigin > inColSize - 2) - cOrigin = inColSize - 2; - - double deltaC = j * scaleCol - cOrigin; - if (deltaC > 1) - deltaC = 1.0; - coeffs[0] = (1 - deltaR) * (1 - deltaC); - coeffs[1] = deltaR * (1 - deltaC); - coeffs[2] = (1 - deltaR) * deltaC; - coeffs[3] = deltaR * deltaC; - - for (size_t k = 0; k < depth * batchSize; ++k) - { - outputAsCube(i, j, k) = arma::accu(inputAsCube.slice(k).submat( - rOrigin, cOrigin, rOrigin + 1, cOrigin + 1) % coeffs); - } + assert(output.n_rows == outRowSize * outColSize * depth); + assert(output.n_cols == batchSize); } - } -} -template -template -void BilinearInterpolation::Backward( - const arma::Mat& /*input*/, - const arma::Mat& gradient, - arma::Mat& output) -{ - if (output.is_empty()) - output.set_size(inRowSize * inColSize * depth, batchSize); - else - { - assert(output.n_rows == inRowSize * inColSize * depth); - assert(output.n_cols == batchSize); - } + assert(inRowSize >= 2); + assert(inColSize >= 2); - assert(outRowSize >= 2); - assert(outColSize >= 2); + const double scaleRow = (double) inRowSize / (double) outRowSize; + const double scaleCol = (double) inColSize / (double) outColSize; - arma::cube gradientAsCube(((arma::Mat&) gradient).memptr(), outRowSize, - outColSize, depth * batchSize, false, false); - arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, - depth * batchSize, false, true); + arma::cube inputAsCube(const_cast&>(input).memptr(), + inRowSize, inColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), outRowSize, outColSize, + depth * batchSize, false, true); - if (gradient.n_elem == output.n_elem) - { - outputAsCube = gradientAsCube; - } - else - { - double scaleRow = (double)(outRowSize) / inRowSize; - double scaleCol = (double)(outColSize) / inColSize; - - arma::mat22 coeffs; - for (size_t i = 0; i < inRowSize; ++i) + for (size_t k = 0; k < depth * batchSize; ++k) { - size_t rOrigin = (size_t) std::floor(i * scaleRow); - if (rOrigin > outRowSize - 2) - rOrigin = outRowSize - 2; - double deltaR = i * scaleRow - rOrigin; - for (size_t j = 0; j < inColSize; ++j) + // The input is padded on all sides using replication of the input boundary. + arma::mat grid = arma::mat(inRowSize + 4, inColSize + 4); + grid.zeros(); + grid(arma::span(2, inRowSize + 1), arma::span(2, inColSize + 1)) = inputAsCube.slice(k); + grid(arma::span(2, inRowSize + 1), 0) = grid(arma::span(2, inRowSize + 1), 2); + grid(arma::span(2, inRowSize + 1), 1) = grid(arma::span(2, inRowSize + 1), 2); + grid(arma::span(2, inRowSize + 1), inColSize + 2) = grid(arma::span(2, inRowSize + 1), inColSize + 1); + grid(arma::span(2, inRowSize + 1), inColSize + 3) = grid(arma::span(2, inRowSize + 1), inColSize + 1); + grid(0, arma::span(2, inColSize+ 1)) = grid(2, arma::span(2, inColSize + 1)); + grid(1, arma::span(2, inColSize + 1)) = grid(2, arma::span(2, inColSize + 1)); + grid(inRowSize + 2, arma::span(2, inColSize + 1)) = grid(inRowSize + 1, arma::span(2, inColSize + 1)); + grid(inRowSize + 3, arma::span(2, inColSize + 1)) = grid(inRowSize + 1, arma::span(2, inColSize + 1)); + grid(span(0, 1), span(0, 1)) += grid(2, 2); + grid(span(inRowSize + 2, inRowSize + 3), span(inColSize + 2, inColSize + 3)) += grid(inRowSize + 1, inColSize + 1); + grid(span(inRowSize + 2, inRowSize + 3), span(0, 1)) += grid(inRowSize + 1, 2); + grid(span(0, 1), span(inColSize + 2, inColSize + 3)) += grid(2, inColSize + 1); + + for (size_t i = 0; i < outRowSize; ++i) { - size_t cOrigin = (size_t) std::floor(j * scaleCol); - - if (cOrigin > outColSize - 2) - cOrigin = outColSize - 2; - - double deltaC = j * scaleCol - cOrigin; - coeffs[0] = (1 - deltaR) * (1 - deltaC); - coeffs[1] = deltaR * (1 - deltaC); - coeffs[2] = (1 - deltaR) * deltaC; - coeffs[3] = deltaR * deltaC; - - for (size_t k = 0; k < depth * batchSize; ++k) + double rOrigin = (i + 0.5) * scaleRow; + for (size_t j = 0; j < outColSize; ++j) { - outputAsCube(i, j, k) = arma::accu(gradientAsCube.slice(k).submat( - rOrigin, cOrigin, rOrigin + 1, cOrigin + 1) % coeffs); + arma::mat kernal = arma::mat(4, 4); + double cOrigin = (j + 0.5) * scaleCol; + // Bottom right corner of the kernal + const size_t cEnd = (size_t) std::floor(cOrigin + 1.5); + const size_t rEnd = (size_t) std::floor(rOrigin + 1.5); + kernal = grid(arma::span(rEnd - 3, rEnd), + arma::span(cEnd - 3, cEnd)); + + double fc = cOrigin - 0.5; + fc = fc - std::floor(fx); + double fr = rOrigin - 0.5; + fr = fr - std::floor(fr); + + arma::mat weightX = arma::mat(1, 4); + arma::mat weightY = arma::mat(4, 1); + GetKernalWeight(fx, weightX); + GetKernalWeight(fy, weightY); + + outputAsCube(i, j, k) = weightX * kernal * weightY; } } } } -} + +template +template +void BicubicInterpolation::Backward( + const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output) + { + if (output.is_empty()) + output.set_size(inRowSize * inColSize * depth, batchSize); + else + { + assert(output.n_rows == inRowSize * inColSize * depth); + assert(output.n_cols == batchSize); + } + + assert(outRowSize >= 2); + assert(outColSize >= 2); + + arma::cube gradientAsCube(((arma::Mat&) gradient).memptr(), outRowSize, + outColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, + depth * batchSize, false, true); + + if (gradient.n_elem == output.n_elem) + { + outputAsCube = gradientAsCube; + } + else + { + for (size_t k = 0; k < depth * batchSize; ++k) + { + temp.zeros(); + for (size_t i = 0; i < outRowSize; ++i) + { + double rOrigin = (i + 0.5) * scaleRow; + for (size_t j = 0; j < outColSize; ++j) + { + arma::mat kernal = arma::mat(4, 4); + double cOrigin = (j + 0.5) * scaleCol; + // Bottom right corner of the kernal + const size_t cEnd = (size_t) std::floor(cOrigin + 1.5); + const size_t rEnd = (size_t) std::floor(rOrigin + 1.5); + kernal = grid(arma::span(rEnd - 3, rEnd), + arma::span(cEnd - 3, cEnd)); + + double fc = cOrigin - 0.5; + fc = fc - std::floor(fx); + double fr = rOrigin - 0.5; + fr = fr - std::floor(fr); + + arma::mat weightX = arma::mat(1, 4); + arma::mat weightY = arma::mat(4, 1); + GetKernalWeight(fx, weightX); + GetKernalWeight(fy, weightY); + + temp(arma::span(rEnd - 1, rEnd), arma::span(cEnd - 1, cEnd)) += weightX * kernal * weightY; + } + } + // Adding the contribution of the corner points to the output matrix. + temp.row(2) += temp.row(0); + temp.row(2) += temp.row(1); + temp.row(inRowSize + 1) += temp.row(inRowSize + 2); + temp.row(inRowSize + 1) += temp.row(inRowSize + 3); + temp.col(2) += temp.col(0); + temp.col(2) += temp.col(1); + temp.col(inColSize + 1) += temp.col(inColSize + 2); + temp.col(inColSize + 1) += temp.col(inColSize + 3); + temp(2, ,2) += armma:accu(temp(span(0, 1), span(0, 1))); + temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(span(inRowSize + 2, inRowSize + 3), span(inColSize + 2, inColSize + 3))); + temp(inRowSize + 1, 2) += arma::accu(temp(span(inRowSize + 2, inRowSize + 3), span(0, 1))); + temp(2, inColSize + 1) += arma::accu(temp(span(0, 1), span(inColSize + 2, inColSize + 3))); + + + outputAsCube.slice(k) += temp(arma::span(2, inRowSize + 1), arma::span(2, inColSize + 1)); + } + } + } template template -void BilinearInterpolation::serialize( - Archive& ar, const uint32_t /* version */) -{ - ar(CEREAL_NVP(inRowSize)); - ar(CEREAL_NVP(inColSize)); - ar(CEREAL_NVP(outRowSize)); - ar(CEREAL_NVP(outColSize)); - ar(CEREAL_NVP(depth)); -} +void BicubicInterpolation::serialize( + Archive& ar, const uint32_t /* version */) + { + ar(CEREAL_NVP(inRowSize)); + ar(CEREAL_NVP(inColSize)); + ar(CEREAL_NVP(outRowSize)); + ar(CEREAL_NVP(outColSize)); + ar(CEREAL_NVP(depth)); + ar(CEREAL_NVP(alpha)); + } } // namespace ann } // namespace mlpack -#endif +#endif \ No newline at end of file From 2ba22eca3646b4bccb9d79a0b1da93c9ab6a67df Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 01:54:18 +0530 Subject: [PATCH 515/729] minor code quality changes --- src/mlpack/methods/ann/layer/CMakeLists.txt | 2 ++ src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 4 ++-- src/mlpack/methods/ann/layer/layer.hpp | 1 + src/mlpack/methods/ann/layer/layer_types.hpp | 4 +++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index d1eb91ff55..f48369ec7b 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -16,6 +16,8 @@ set(SOURCES base_layer.hpp batch_norm.hpp batch_norm_impl.hpp + bicubic_interpolation.hpp + bicubic_interpolation_impl.hpp bilinear_interpolation.hpp bilinear_interpolation_impl.hpp channel_shuffle.hpp diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 47d0bb67f5..dbe85d30d2 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -53,6 +53,7 @@ BilinearInterpolation( weights.set_size(WeightSize(), 1); temp = arma::mat(weights.memptr(), inRowSize + 4, inColSize + 4, false, false); } + template void GetKernalWeight(eT delta, arma::mat& coeffs) { @@ -206,8 +207,7 @@ void BicubicInterpolation::Backward( temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(span(inRowSize + 2, inRowSize + 3), span(inColSize + 2, inColSize + 3))); temp(inRowSize + 1, 2) += arma::accu(temp(span(inRowSize + 2, inRowSize + 3), span(0, 1))); temp(2, inColSize + 1) += arma::accu(temp(span(0, 1), span(inColSize + 2, inColSize + 3))); - - + outputAsCube.slice(k) += temp(arma::span(2, inRowSize + 1), arma::span(2, inColSize + 1)); } } diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index b2f598b985..00f740c393 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -20,6 +20,7 @@ #include "atrous_convolution.hpp" #include "base_layer.hpp" #include "batch_norm.hpp" +#include "bicubic_interpolation.hpp" #include "bilinear_interpolation.hpp" #include "c_relu.hpp" #include "celu.hpp" diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index d72cd1fa33..65dfeab5ea 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -242,7 +243,8 @@ using MoreTypes = boost::variant< RBF*, BaseLayer*, PositionalEncoding*, - ISRLU* + ISRLU*, + BicubicInterpolation* >; template From 92193c56a6813c9456057e9285ccd6fadcd1edac Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 01:57:25 +0530 Subject: [PATCH 516/729] minor constructor change --- src/mlpack/methods/ann/layer/bicubic_interpolation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp index d8b9c09942..2add0eea71 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp @@ -87,7 +87,7 @@ class BicubicInterpolation size_t WeightSize() const { return (inRowSize + 5) * (inColSize + 4); } template - arma::Mat GetKernalWeight(double a, eT delta); + void GetKernalWeight(eT delta, arma::mat& coeffs); //! Get the output parameter. OutputDataType const& OutputParameter() const { return outputParameter; } From 9fb629671e305c2847fb00dad875acb7d8a03377 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 18:23:05 +0530 Subject: [PATCH 517/729] added test case and minor fix --- .../ann/layer/bicubic_interpolation_impl.hpp | 36 +++++++++---------- src/mlpack/tests/ann_layer_test.cpp | 30 ++++++++++++++++ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index dbe85d30d2..4c9d78021a 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -27,7 +27,7 @@ BicubicInterpolation(): outRowSize(0), outColSize(0), depth(0), - alpha(0.75), + alpha(-0.75), batchSize(0) { // Nothing to do here. @@ -57,9 +57,9 @@ BilinearInterpolation( template void GetKernalWeight(eT delta, arma::mat& coeffs) { - coeffs(0) = ((A * (delta + 1) - 5 * A) * (delta + 1) + 8 * A) * (delta + 1) - 4 * A; - coeffs(1) = ((A + 2) * delta - (A + 3)) * delta * delta + 1; - coeffs(2) = ((A + 2) * (1 - delta) - (A + 3)) * (1 - delta) * (1 - delta) + 1; + coeffs(0) = ((alpha * (delta + 1) - 5 * alpha) * (delta + 1) + 8 * alpha) * (delta + 1) - 4 * alpha; + coeffs(1) = ((alpha + 2) * delta - (alpha + 3)) * delta * delta + 1; + coeffs(2) = ((alpha + 2) * (1 - delta) - (alpha + 3)) * (1 - delta) * (1 - delta) + 1; coeffs(3) = 1 - coeffs[0] - coeffs[1] - coeffs[2]; } @@ -115,8 +115,8 @@ void BicubicInterpolation::Forward( arma::mat kernal = arma::mat(4, 4); double cOrigin = (j + 0.5) * scaleCol; // Bottom right corner of the kernal - const size_t cEnd = (size_t) std::floor(cOrigin + 1.5); - const size_t rEnd = (size_t) std::floor(rOrigin + 1.5); + const size_t cEnd = (size_t) std::floor(cOrigin + 1.5) + 2; + const size_t rEnd = (size_t) std::floor(rOrigin + 1.5) + 2; kernal = grid(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)); @@ -125,12 +125,12 @@ void BicubicInterpolation::Forward( double fr = rOrigin - 0.5; fr = fr - std::floor(fr); - arma::mat weightX = arma::mat(1, 4); - arma::mat weightY = arma::mat(4, 1); - GetKernalWeight(fx, weightX); - GetKernalWeight(fy, weightY); + arma::mat weightR = arma::mat(1, 4); + arma::mat weightC = arma::mat(4, 1); + GetKernalWeight(fr, weightR); + GetKernalWeight(fc, weightC); - outputAsCube(i, j, k) = weightX * kernal * weightY; + outputAsCube(i, j, k) = weightR * kernal * weightC; } } } @@ -176,8 +176,8 @@ void BicubicInterpolation::Backward( arma::mat kernal = arma::mat(4, 4); double cOrigin = (j + 0.5) * scaleCol; // Bottom right corner of the kernal - const size_t cEnd = (size_t) std::floor(cOrigin + 1.5); - const size_t rEnd = (size_t) std::floor(rOrigin + 1.5); + const size_t cEnd = (size_t) std::floor(cOrigin + 1.5) + 2; + const size_t rEnd = (size_t) std::floor(rOrigin + 1.5) + 2; kernal = grid(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)); @@ -186,12 +186,12 @@ void BicubicInterpolation::Backward( double fr = rOrigin - 0.5; fr = fr - std::floor(fr); - arma::mat weightX = arma::mat(1, 4); - arma::mat weightY = arma::mat(4, 1); - GetKernalWeight(fx, weightX); - GetKernalWeight(fy, weightY); + arma::mat weightR = arma::mat(1, 4); + arma::mat weightC = arma::mat(4, 1); + GetKernalWeight(fr, weightR); + GetKernalWeight(fc, weightC); - temp(arma::span(rEnd - 1, rEnd), arma::span(cEnd - 1, cEnd)) += weightX * kernal * weightY; + temp(arma::span(rEnd - 1, rEnd), arma::span(cEnd - 1, cEnd)) += weightR * kernal * weightC; } } // Adding the contribution of the corner points to the output matrix. diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index cbc01b35a8..4b844ee64f 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2168,6 +2168,36 @@ TEST_CASE("BilinearInterpolationLayerParametersTest", "[ANNLayerTest]") REQUIRE(layer1.InDepth() == layer2.InDepth()); } +/* + * Simple test for the BicubicInterpolation layer + */ +TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") +{ + // Tested output against torch.nn.Upsample(mode="nearest") + arma::mat input, output, unzoomedOutput, expectedOutput; + size_t inRowSize = 2; + size_t inColSize = 2; + size_t outRowSize = 5; + size_t outColSize = 7; + size_t depth = 1; + input.zeros(inRowSize * inColSize * depth, 1); + input[0] = 10.0; + input[1] = 20.0; + input[2] = 30.0; + input[3] = 40.0; + BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, + depth); + + expectedOutput << 6.6880 << 7.3331 << 9.6973 << 12.7950 << 15.8927 << 18.2569 << 18.9020 << arma::endr + << 10.5330 << 11.1781 << 13.5423 << 16.6400 << 19.7377 << 22.1019 << 22.7470 << arma::endr + << 18.8930 << 19.5381 << 21.9023 << 25.0000 << 28.0977 << 30.4619 << 31.1070 << arma::endr + << 27.2530 << 27.8981 << 30.2623 << 33.3600 << 36.4577 << 38.8219 << 39.4670 << arma::endr + << 31.0980 << 31.7431 << 34.1073 << 37.2050 << 40.3027 << 42.6669 << 43.3120 << arma::endr; + expectedOutput.reshape(35, 1); + layer.Forward(input, output); + CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); +} + /** * Tests the BatchNorm Layer, compares the layers parameters with * the values from another implementation. From e642f4af9ff95df5c891e9cf5c50c8cce5ca9d0f Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 4 Jul 2021 18:31:57 +0530 Subject: [PATCH 518/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 4b844ee64f..286d0d1183 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2173,7 +2173,7 @@ TEST_CASE("BilinearInterpolationLayerParametersTest", "[ANNLayerTest]") */ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") { - // Tested output against torch.nn.Upsample(mode="nearest") + // Tested output against torch.nn.Upsample(mode="bicubic") arma::mat input, output, unzoomedOutput, expectedOutput; size_t inRowSize = 2; size_t inColSize = 2; From b0b255afdb9c5d10310547cbd52cd12034b29715 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 4 Jul 2021 18:38:54 +0530 Subject: [PATCH 519/729] Update bicubic_interpolation_impl.hpp --- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 4c9d78021a..4afb2a63a2 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -130,7 +130,7 @@ void BicubicInterpolation::Forward( GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - outputAsCube(i, j, k) = weightR * kernal * weightC; + outputAsCube(i, j, k) = (weightR * kernal * weightC)(0); } } } @@ -191,7 +191,7 @@ void BicubicInterpolation::Backward( GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - temp(arma::span(rEnd - 1, rEnd), arma::span(cEnd - 1, cEnd)) += weightR * kernal * weightC; + temp(arma::span(rEnd - 1, rEnd), arma::span(cEnd - 1, cEnd)) += (weightR * kernal * weightC)(0); } } // Adding the contribution of the corner points to the output matrix. @@ -229,4 +229,4 @@ void BicubicInterpolation::serialize( } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif From a5e69750a1acfc3dac8b669ef3a3f2edf2fb36ab Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 4 Jul 2021 19:30:36 +0530 Subject: [PATCH 520/729] Update bicubic_interpolation_impl.hpp --- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 4afb2a63a2..7c1af8cc1f 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -13,7 +13,7 @@ #define MLPACK_METHODS_ANN_LAYER_BICUBIC_INTERPOLATION_IMPL_HPP // In case it hasn't yet been included. -#include "Bicubic_interpolation.hpp" +#include "bicubic_interpolation.hpp" namespace mlpack { namespace ann /** Artificial Neural Network. */ { From bb68d4aa2db17165f6875cf6b3d9351682eb7459 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 20:13:48 +0530 Subject: [PATCH 521/729] minor change --- .../ann/layer/bicubic_interpolation_impl.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 4c9d78021a..12af090edf 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -102,10 +102,10 @@ void BicubicInterpolation::Forward( grid(1, arma::span(2, inColSize + 1)) = grid(2, arma::span(2, inColSize + 1)); grid(inRowSize + 2, arma::span(2, inColSize + 1)) = grid(inRowSize + 1, arma::span(2, inColSize + 1)); grid(inRowSize + 3, arma::span(2, inColSize + 1)) = grid(inRowSize + 1, arma::span(2, inColSize + 1)); - grid(span(0, 1), span(0, 1)) += grid(2, 2); - grid(span(inRowSize + 2, inRowSize + 3), span(inColSize + 2, inColSize + 3)) += grid(inRowSize + 1, inColSize + 1); - grid(span(inRowSize + 2, inRowSize + 3), span(0, 1)) += grid(inRowSize + 1, 2); - grid(span(0, 1), span(inColSize + 2, inColSize + 3)) += grid(2, inColSize + 1); + grid(arma::span(0, 1), arma::span(0, 1)) += grid(2, 2); + grid(arma::span(inRowSize + 2, inRowSize + 3), arma::span(inColSize + 2, inColSize + 3)) += grid(inRowSize + 1, inColSize + 1); + grid(arma::span(inRowSize + 2, inRowSize + 3), arma::span(0, 1)) += grid(inRowSize + 1, 2); + grid(arma::span(0, 1), arma::span(inColSize + 2, inColSize + 3)) += grid(2, inColSize + 1); for (size_t i = 0; i < outRowSize; ++i) { @@ -203,12 +203,12 @@ void BicubicInterpolation::Backward( temp.col(2) += temp.col(1); temp.col(inColSize + 1) += temp.col(inColSize + 2); temp.col(inColSize + 1) += temp.col(inColSize + 3); - temp(2, ,2) += armma:accu(temp(span(0, 1), span(0, 1))); - temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(span(inRowSize + 2, inRowSize + 3), span(inColSize + 2, inColSize + 3))); - temp(inRowSize + 1, 2) += arma::accu(temp(span(inRowSize + 2, inRowSize + 3), span(0, 1))); - temp(2, inColSize + 1) += arma::accu(temp(span(0, 1), span(inColSize + 2, inColSize + 3))); + temp(2, ,2) += armma:accu(temp(arma::span(0, 1), span(0, 1))); + temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(inColSize + 2, inColSize + 3))); + temp(inRowSize + 1, 2) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(0, 1))); + temp(2, inColSize + 1) += arma::accu(temp(arma::span(0, 1), arma::span(inColSize + 2, inColSize + 3))); - outputAsCube.slice(k) += temp(arma::span(2, inRowSize + 1), arma::span(2, inColSize + 1)); + outputAsCube.slice(k) += temp(arma::arma::span(2, inRowSize + 1), arma::arma::span(2, inColSize + 1)); } } } From 1cba74868df8febc2d4262c7491b0e6d52c2a55a Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 21:59:07 +0530 Subject: [PATCH 522/729] minor change --- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 92c6c2784c..53a0f0a629 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -191,7 +191,7 @@ void BicubicInterpolation::Backward( GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - temp(arma::span(rEnd - 1, rEnd), arma::span(cEnd - 1, cEnd)) += (weightR * kernal * weightC)(0); + temp(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)) += (weightR * gradientAsCube(i, j, k) * weightC); } } // Adding the contribution of the corner points to the output matrix. From bec391d4312b0a57f663cb14a674e00f90cf24e8 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 4 Jul 2021 22:32:56 +0530 Subject: [PATCH 523/729] Update bicubic_interpolation_impl.hpp --- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 53a0f0a629..570b1efe3a 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -173,13 +173,10 @@ void BicubicInterpolation::Backward( double rOrigin = (i + 0.5) * scaleRow; for (size_t j = 0; j < outColSize; ++j) { - arma::mat kernal = arma::mat(4, 4); double cOrigin = (j + 0.5) * scaleCol; // Bottom right corner of the kernal const size_t cEnd = (size_t) std::floor(cOrigin + 1.5) + 2; const size_t rEnd = (size_t) std::floor(rOrigin + 1.5) + 2; - kernal = grid(arma::span(rEnd - 3, rEnd), - arma::span(cEnd - 3, cEnd)); double fc = cOrigin - 0.5; fc = fc - std::floor(fx); From 1e23d53a1c831d7a041970148a838478504ccd8d Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sun, 4 Jul 2021 23:03:32 +0530 Subject: [PATCH 524/729] minor change --- .../ann/layer/bicubic_interpolation_impl.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 53a0f0a629..ccd46ec8ca 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -54,8 +54,9 @@ BilinearInterpolation( temp = arma::mat(weights.memptr(), inRowSize + 4, inColSize + 4, false, false); } +template template - void GetKernalWeight(eT delta, arma::mat& coeffs) +void BicubicInterpolation::GetKernalWeight(eT delta, arma::mat& coeffs) { coeffs(0) = ((alpha * (delta + 1) - 5 * alpha) * (delta + 1) + 8 * alpha) * (delta + 1) - 4 * alpha; coeffs(1) = ((alpha + 2) * delta - (alpha + 3)) * delta * delta + 1; @@ -121,7 +122,7 @@ void BicubicInterpolation::Forward( arma::span(cEnd - 3, cEnd)); double fc = cOrigin - 0.5; - fc = fc - std::floor(fx); + fc = fc - std::floor(fc); double fr = rOrigin - 0.5; fr = fr - std::floor(fr); @@ -130,7 +131,8 @@ void BicubicInterpolation::Forward( GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - outputAsCube(i, j, k) = (weightR * kernal * weightC)(0); + arma::mat val = weightR * kernal * weightC + outputAsCube(i, j, k) = val(0); } } } @@ -182,7 +184,7 @@ void BicubicInterpolation::Backward( arma::span(cEnd - 3, cEnd)); double fc = cOrigin - 0.5; - fc = fc - std::floor(fx); + fc = fc - std::floor(fc); double fr = rOrigin - 0.5; fr = fr - std::floor(fr); @@ -203,12 +205,12 @@ void BicubicInterpolation::Backward( temp.col(2) += temp.col(1); temp.col(inColSize + 1) += temp.col(inColSize + 2); temp.col(inColSize + 1) += temp.col(inColSize + 3); - temp(2, ,2) += armma:accu(temp(arma::span(0, 1), span(0, 1))); + temp(2, 2) += arma:accu(temp(arma::span(0, 1), arma::span(0, 1))); temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(inColSize + 2, inColSize + 3))); temp(inRowSize + 1, 2) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(0, 1))); temp(2, inColSize + 1) += arma::accu(temp(arma::span(0, 1), arma::span(inColSize + 2, inColSize + 3))); - outputAsCube.slice(k) += temp(arma::arma::span(2, inRowSize + 1), arma::arma::span(2, inColSize + 1)); + outputAsCube.slice(k) += temp(arma::span(2, inRowSize + 1), arma::span(2, inColSize + 1)); } } } From 66f7fd73e771e4e937a8d6846f56f52e86cd9e22 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Mon, 5 Jul 2021 00:17:13 +0530 Subject: [PATCH 525/729] minor change --- .../methods/ann/layer/bicubic_interpolation_impl.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 71ba732664..17206c595e 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -34,8 +34,8 @@ BicubicInterpolation(): } template -BilinearInterpolation:: -BilinearInterpolation( +BicubicInterpolation:: +BicubicInterpolation( const size_t inRowSize, const size_t inColSize, const size_t outRowSize, @@ -131,7 +131,7 @@ void BicubicInterpolation::Forward( GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - arma::mat val = weightR * kernal * weightC + arma::mat val = weightR * kernal * weightC; outputAsCube(i, j, k) = val(0); } } @@ -161,6 +161,9 @@ void BicubicInterpolation::Backward( arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, depth * batchSize, false, true); + const double scaleRow = (double) inRowSize / (double) outRowSize; + const double scaleCol = (double) inColSize / (double) outColSize; + if (gradient.n_elem == output.n_elem) { outputAsCube = gradientAsCube; @@ -202,7 +205,7 @@ void BicubicInterpolation::Backward( temp.col(2) += temp.col(1); temp.col(inColSize + 1) += temp.col(inColSize + 2); temp.col(inColSize + 1) += temp.col(inColSize + 3); - temp(2, 2) += arma:accu(temp(arma::span(0, 1), arma::span(0, 1))); + temp(2, 2) += arma::accu(temp(arma::span(0, 1), arma::span(0, 1))); temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(inColSize + 2, inColSize + 3))); temp(inRowSize + 1, 2) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(0, 1))); temp(2, inColSize + 1) += arma::accu(temp(arma::span(0, 1), arma::span(inColSize + 2, inColSize + 3))); From 3cdd4ac1e62b3213913956552b690fee3711e0b9 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Mon, 5 Jul 2021 01:08:32 +0530 Subject: [PATCH 526/729] Update bicubic_interpolation.hpp --- src/mlpack/methods/ann/layer/bicubic_interpolation.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp index 2add0eea71..e48286f0d3 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp @@ -130,9 +130,9 @@ class BicubicInterpolation size_t& InDepth() { return depth; } //! Get the constant value to generate weight. - size_t const& Alpha() const { return alpha; } + double const& Alpha() const { return alpha; } //! Modify the constant value to generate weight. - size_t& Alpha() { return alpha; } + double& Alpha() { return alpha; } //! Get the shape of the input. size_t InputShape() const @@ -181,4 +181,4 @@ class BicubicInterpolation // Include implementation. #include "bicubic_interpolation_impl.hpp" -#endif \ No newline at end of file +#endif From 30e22ded89e114c3400728f17ed21a620e7150fe Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 8 Jul 2021 18:39:02 -0400 Subject: [PATCH 527/729] Avoid namespace/method name conflict for test bindings. --- src/mlpack/core/util/mlpack_main.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index a610e2db67..09ed876aef 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -110,7 +110,7 @@ int main(int argc, char** argv) // A "total_time" timer is run by default for each mlpack program. timers.Start("total_time"); - BINDING_NAME(params, timers); + BINDING_FUNCTION(params, timers); timers.Stop("total_time"); // Print output options, print verbose information, save model parameters, @@ -157,9 +157,15 @@ using Option = mlpack::bindings::tests::TestOption; } } -// testName symbol should be defined in each binding test file #include +// For the tests, we want to call the binding function +// mlpack_test_() instead of just (), so we change +// the definition of BINDING_FUNCTION(). This is to avoid namespace/function +// ambiguities. +#undef BINDING_FUNCTION +#define BINDING_FUNCTION(...) JOIN(mlpack_test_, BINDING_NAME)(__VA_ARGS__) + #elif(BINDING_TYPE == BINDING_TYPE_PYX) // This is a Python binding. // Matrices are transposed on load/save. From 51597fb49ff5b99898fdd6a815f46aef69e9402c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 8 Jul 2021 18:39:10 -0400 Subject: [PATCH 528/729] Re-enable and adapt AdaBoostMainTest. --- src/mlpack/tests/CMakeLists.txt | 2 +- src/mlpack/tests/main_tests/adaboost_test.cpp | 133 ++++++++---------- .../tests/main_tests/main_test_fixture.hpp | 2 +- 3 files changed, 58 insertions(+), 79 deletions(-) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index f6cf78da7d..c43827612c 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -128,7 +128,7 @@ add_executable(mlpack_test union_find_test.cpp vantage_point_tree_test.cpp wgan_test.cpp -# main_tests/adaboost_test.cpp + main_tests/adaboost_test.cpp # main_tests/approx_kfn_test.cpp # main_tests/bayesian_linear_regression_test.cpp # main_tests/cf_test.cpp diff --git a/src/mlpack/tests/main_tests/adaboost_test.cpp b/src/mlpack/tests/main_tests/adaboost_test.cpp index 88a59f0501..90a6f151ab 100644 --- a/src/mlpack/tests/main_tests/adaboost_test.cpp +++ b/src/mlpack/tests/main_tests/adaboost_test.cpp @@ -2,44 +2,26 @@ * @file tests/main_tests/adaboost_test.cpp * @author Nikhil Goel * - * Test mlpackMain() of adaboost_main.cpp. + * Test RUN_BINDING() of adaboost_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "AdaBoost"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct AdaBoostTestFixture -{ - public: - AdaBoostTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~AdaBoostTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(AdaBoostTestFixture); /** * Check that number of output labels and number of input @@ -67,11 +49,11 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostOutputDimensionTest", SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of predicted labels is equal to the input test points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam>("output").n_rows == 1); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get>("output").n_rows == 1); } /** @@ -101,10 +83,10 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostProbabilitiesTest", SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); arma::mat probabilities; - probabilities = std::move(IO::GetParam("probabilities")); + probabilities = std::move(params.Get("probabilities")); REQUIRE(probabilities.n_cols == testSize); @@ -135,23 +117,21 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostModelReuseTest", SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("output")); + output = std::move(params.Get>("output")); - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + AdaBoostModel* model = params.Get("output_model"); + ResetSettings(); SetInputParam("test", std::move(testData)); - SetInputParam("input_model", - IO::GetParam("output_model")); + SetInputParam("input_model", model); - mlpackMain(); + RUN_BINDING(); // Check that initial output and output using saved model are same. - CheckMatrices(output, IO::GetParam>("output")); + CheckMatrices(output, params.Get>("output")); } /** @@ -168,7 +148,7 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostItrTest", SetInputParam("iterations", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -201,27 +181,25 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostWithoutLabelTest", SetInputParam("test", testData); - mlpackMain(); - - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("output")); + output = std::move(params.Get>("output")); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); trainData.shed_row(trainData.n_rows - 1); - // Now train Adaboost with labels provided. + // Now train AdaBoost with labels provided. SetInputParam("training", std::move(trainData)); SetInputParam("test", std::move(testData)); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Check that initial output and final output matrix are same. - CheckMatrices(output, IO::GetParam>("output")); + CheckMatrices(output, params.Get>("output")); } /** @@ -236,13 +214,13 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostTrainingDataOrModelTest", SetInputParam("training", std::move(trainData)); - mlpackMain(); + RUN_BINDING(); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -264,10 +242,10 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostOutputPredictionsTest", SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); - CheckMatrices(IO::GetParam>("output"), - IO::GetParam>("predictions")); + CheckMatrices(params.Get>("output"), + params.Get>("predictions")); } /** @@ -284,7 +262,7 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostWeakLearnerTest", SetInputParam("weak_learner", std::string("decision tree")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -310,26 +288,23 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostDiffWeakLearnerOutputTest", SetInputParam("labels", labels); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("output")); + output = std::move(params.Get>("output")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("training", trainData); SetInputParam("labels", labels); SetInputParam("test", testData); SetInputParam("weak_learner", std::string("perceptron")); - mlpackMain(); + RUN_BINDING(); arma::Row outputPerceptron; - outputPerceptron = std::move(IO::GetParam>("output")); + outputPerceptron = std::move(params.Get>("output")); REQUIRE(arma::accu(output != outputPerceptron) > 1); } @@ -363,17 +338,18 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostDiffItrTest", SetInputParam("weak_learner", std::string("perceptron")); SetInputParam("iterations", (int) 1); - mlpackMain(); + RUN_BINDING(); // Calculate accuracy. arma::Row output; - IO::GetParam("output_model")->Classify(testData, + params.Get("output_model")->Classify(testData, output); size_t correct = arma::accu(output == testLabels); double accuracy1 = (double(correct) / double(testLabels.n_elem) * 100); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Iterations = 10 SetInputParam("training", trainData); @@ -381,16 +357,17 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostDiffItrTest", SetInputParam("weak_learner", std::string("perceptron")); SetInputParam("iterations", (int) 10); - mlpackMain(); + RUN_BINDING(); // Calculate accuracy. - IO::GetParam("output_model")->Classify(testData, + params.Get("output_model")->Classify(testData, output); correct = arma::accu(output == testLabels); double accuracy10 = (double(correct) / double(testLabels.n_elem) * 100); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Iterations = 100 SetInputParam("training", trainData); @@ -398,10 +375,10 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostDiffItrTest", SetInputParam("weak_learner", std::string("perceptron")); SetInputParam("iterations", (int) 100); - mlpackMain(); + RUN_BINDING(); // Calculate accuracy. - IO::GetParam("output_model")->Classify(testData, + params.Get("output_model")->Classify(testData, output); correct = arma::accu(output == testLabels); @@ -439,43 +416,45 @@ TEST_CASE_METHOD(AdaBoostTestFixture, "AdaBoostDiffTolTest", SetInputParam("labels", labels); SetInputParam("tolerance", (double) 0.001); - mlpackMain(); + RUN_BINDING(); // Calculate accuracy. arma::Row output; - IO::GetParam("output_model")->Classify(testData, + params.Get("output_model")->Classify(testData, output); size_t correct = arma::accu(output == testLabels); double accuracy1 = (double(correct) / double(testLabels.n_elem) * 100); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // tolerance = 0.01 SetInputParam("training", trainData); SetInputParam("labels", labels); SetInputParam("tolerance", (double) 0.01); - mlpackMain(); + RUN_BINDING(); // Calculate accuracy. - IO::GetParam("output_model")->Classify(testData, + params.Get("output_model")->Classify(testData, output); correct = arma::accu(output == testLabels); double accuracy2 = (double(correct) / double(testLabels.n_elem) * 100); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // tolerance = 0.1 SetInputParam("training", trainData); SetInputParam("labels", labels); SetInputParam("tolerance", (double) 0.1); - mlpackMain(); + RUN_BINDING(); // Calculate accuracy. - IO::GetParam("output_model")->Classify(testData, + params.Get("output_model")->Classify(testData, output); correct = arma::accu(output == testLabels); diff --git a/src/mlpack/tests/main_tests/main_test_fixture.hpp b/src/mlpack/tests/main_tests/main_test_fixture.hpp index d4e184a2d5..d10ca21acb 100644 --- a/src/mlpack/tests/main_tests/main_test_fixture.hpp +++ b/src/mlpack/tests/main_tests/main_test_fixture.hpp @@ -41,7 +41,7 @@ * appropriately. This is generally done simply by including the binding's * `*_main.cpp` file. */ -#define RUN_BINDING() BINDING_NAME(params, timers) +#define RUN_BINDING() BINDING_FUNCTION(params, timers) /** * MainTestFixture is a base class for Catch fixtures for mlpack binding tests. From ac6b653f31c2387cf542f7cf242a5e21ec8d479e Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 8 Jul 2021 20:07:26 -0400 Subject: [PATCH 529/729] Adapt some more tests. --- src/mlpack/tests/CMakeLists.txt | 12 +- .../tests/main_tests/approx_kfn_test.cpp | 114 ++++---- .../bayesian_linear_regression_test.cpp | 51 ++-- src/mlpack/tests/main_tests/cf_test.cpp | 172 +++++------- src/mlpack/tests/main_tests/dbscan_test.cpp | 199 ++++++-------- .../tests/main_tests/decision_stump_test.cpp | 257 ------------------ .../tests/main_tests/decision_tree_test.cpp | 148 ++++------ src/mlpack/tests/main_tests/det_test.cpp | 136 ++++----- 8 files changed, 332 insertions(+), 757 deletions(-) delete mode 100644 src/mlpack/tests/main_tests/decision_stump_test.cpp diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index c43827612c..3e7257f333 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -129,12 +129,12 @@ add_executable(mlpack_test vantage_point_tree_test.cpp wgan_test.cpp main_tests/adaboost_test.cpp -# main_tests/approx_kfn_test.cpp -# main_tests/bayesian_linear_regression_test.cpp -# main_tests/cf_test.cpp -# main_tests/dbscan_test.cpp -# main_tests/decision_tree_test.cpp -# main_tests/det_test.cpp + main_tests/approx_kfn_test.cpp + main_tests/bayesian_linear_regression_test.cpp + main_tests/cf_test.cpp + main_tests/dbscan_test.cpp + main_tests/decision_tree_test.cpp + main_tests/det_test.cpp # main_tests/emst_test.cpp # main_tests/fastmks_test.cpp # main_tests/gmm_generate_test.cpp diff --git a/src/mlpack/tests/main_tests/approx_kfn_test.cpp b/src/mlpack/tests/main_tests/approx_kfn_test.cpp index 375bbe2678..2846589bd3 100644 --- a/src/mlpack/tests/main_tests/approx_kfn_test.cpp +++ b/src/mlpack/tests/main_tests/approx_kfn_test.cpp @@ -2,44 +2,26 @@ * @file tests/main_tests/approx_kfn_test.cpp * @author Namrata Mukhija * - * Test mlpackMain() of approx_kfn_main.cpp. + * Test RUN_BINDING() of approx_kfn_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "ApproxK-FurthestNeighbors"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct ApproxKFNTestFixture -{ - public: - ApproxKFNTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~ApproxKFNTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(ApproxKFNTestFixture); /** * Check that we can't specify both a reference set and an input model. @@ -60,7 +42,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNRefModelTest", // Input pre-trained model. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -78,7 +60,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNInvalidKTest", SetInputParam("k", (int) 81); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -96,15 +78,15 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNOutputDimensionTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check the neighbors matrix has 10 points for each of the 80 input points. - REQUIRE(IO::GetParam>("neighbors").n_rows == 10); - REQUIRE(IO::GetParam>("neighbors").n_cols == 80); + REQUIRE(params.Get>("neighbors").n_rows == 10); + REQUIRE(params.Get>("neighbors").n_cols == 80); // Check the distances matrix has 10 points for each of the 80 input points. - REQUIRE(IO::GetParam("distances").n_rows == 10); - REQUIRE(IO::GetParam("distances").n_cols == 80); + REQUIRE(params.Get("distances").n_rows == 10); + REQUIRE(params.Get("distances").n_cols == 80); } /** @@ -120,7 +102,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNInvalidAlgorithmTest", SetInputParam("algorithm", (string) "any_algo"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -138,7 +120,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNZeroNumProjTest", SetInputParam("num_projections", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -156,7 +138,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNegativeNumProjTest", SetInputParam("num_projections", (int) -5); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -174,7 +156,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNZeroNumTablesTest", SetInputParam("num_tables", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -192,7 +174,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNegativeNumTablesTest", SetInputParam("num_tables", (int) -5); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -213,31 +195,29 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNModelReuseTest", SetInputParam("query", queryData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); ApproxKFNModel* model = - new ApproxKFNModel(*IO::GetParam("output_model")); + new ApproxKFNModel(*params.Get("output_model")); - bindings::tests::CleanMemory(); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("input_model", model); SetInputParam("query", queryData); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); } /** @@ -257,16 +237,15 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNumTablesChangeTest", SetInputParam("num_projections", (int) 10); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the distances matrix after first training. arma::mat firstOutputDistances = - std::move(IO::GetParam("distances")); + std::move(params.Get("distances")); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Second setting. referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -278,11 +257,11 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNumTablesChangeTest", SetInputParam("num_projections", (int) 10); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the distances matrix after second training. arma::mat secondOutputDistances = - std::move(IO::GetParam("distances")); + std::move(params.Get("distances")); // Check that the size of distance matrices (FirstOutputDistances and // SecondOutputDistances) are not equal which ensures num_tables changes @@ -307,16 +286,16 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNumProjectionsChangeTest", SetInputParam("num_projections", (int) 4); SetInputParam("num_tables", (int) 3); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the distances matrix after first training. arma::mat firstOutputDistances = - std::move(IO::GetParam("distances")); + std::move(params.Get("distances")); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); + // Second setting. referenceData.randu(2, 80); // 80 points in 2 dimensions. SetInputParam("reference", std::move(referenceData)); @@ -327,11 +306,11 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNumProjectionsChangeTest", SetInputParam("num_tables", (int) 3); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the distances matrix after second training. arma::mat secondOutputDistances = - std::move(IO::GetParam("distances")); + std::move(params.Get("distances")); // Check that the size of distance matrices (FirstOutputDistances and // SecondOutputDistances) are not equal which ensures num_tables changes @@ -361,7 +340,7 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNExactDistDimensionTest", SetInputParam("exact_distances", std::move(exactDistances)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -381,18 +360,17 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNDifferentAlgoTest", SetInputParam("algorithm", (string) "ds"); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the distances and neighbors matrix after first training. arma::mat firstOutputDistances = - std::move(IO::GetParam("distances")); + std::move(params.Get("distances")); arma::Mat firstOutputNeighbors = - std::move(IO::GetParam>("neighbors")); + std::move(params.Get>("neighbors")); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Second solution. SetInputParam("reference", std::move(referenceData)); @@ -402,9 +380,9 @@ TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNDifferentAlgoTest", // Get the distances and neighbors matrix after second training. arma::mat secondOutputDistances = - std::move(IO::GetParam("distances")); + std::move(params.Get("distances")); arma::Mat secondOutputNeighbors = - std::move(IO::GetParam>("neighbors")); + std::move(params.Get>("neighbors")); // Check that the distance matrices (firstOutputDistances and // secondOutputDistances) and neighbor matrices (firstOutputNeighbors and diff --git a/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp b/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp index f8b455d25c..2340b4fbe2 100644 --- a/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp +++ b/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp @@ -2,44 +2,26 @@ * @file tests/main_tests/bayesian_linear_regression_test.cpp * @author Clement Mercier * - * Test mlpackMain() of bayesian_linear_regression_main.cpp. + * Test RUN_BINDING() of bayesian_linear_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "BayesianLinearRegression"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct BRTestFixture -{ - public: - BRTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~BRTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(BRTestFixture); /** * Check the center and scale options. @@ -57,10 +39,10 @@ TEST_CASE_METHOD(BRTestFixture, SetInputParam("responses", std::move(y)); SetInputParam("center", false); - mlpackMain(); + RUN_BINDING(); BayesianLinearRegression* estimator = - IO::GetParam("output_model"); + params.Get("output_model"); REQUIRE(estimator->DataOffset().n_elem == 0); REQUIRE(estimator->DataScale().n_elem == 0); @@ -88,20 +70,21 @@ TEST_CASE_METHOD(BRTestFixture, SetInputParam("input", std::move(matX)); SetInputParam("responses", std::move(y)); - mlpackMain(); + RUN_BINDING(); - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["responses"].wasPassed = false; + BayesianLinearRegression* mOut = + params.Get("output_model"); - SetInputParam("input_model", - IO::GetParam("output_model")); + ResetSettings(); + + SetInputParam("input_model", mOut); SetInputParam("test", std::move(matXtest)); - mlpackMain(); + RUN_BINDING(); arma::mat ytest = std::move(responses); // Check that initial output and output using saved model are same. - CheckMatrices(ytest, IO::GetParam("predictions")); + CheckMatrices(ytest, params.Get("predictions")); } /** @@ -129,21 +112,21 @@ TEST_CASE_METHOD(BRTestFixture, SetInputParam("responses", std::move(y)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Continue only with input passed. SetInputParam("input", std::move(matX)); - mlpackMain(); + RUN_BINDING(); // Now pass the previous trained model and one input matrix at the same time. // An error should occur. SetInputParam("input", std::move(matX)); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("test", std::move(matXtest)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/cf_test.cpp b/src/mlpack/tests/main_tests/cf_test.cpp index da1c8c77fc..226c1bfc9e 100644 --- a/src/mlpack/tests/main_tests/cf_test.cpp +++ b/src/mlpack/tests/main_tests/cf_test.cpp @@ -2,54 +2,27 @@ * @file cf_test.cpp * @author Wenhao Huang * - * Test mlpackMain() of cf_main.cpp + * Test RUN_BINDING() of cf_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "CollaborativeFiltering"; - #include -#include #include +#include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" #include "../catch.hpp" using namespace mlpack; using namespace arma; - -struct CFTestFixture -{ - public: - CFTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~CFTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -static void ResetSettings() -{ - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(CFTestFixture); /** * Ensure the rank is non-negative. @@ -65,7 +38,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFRankBoundTest", SetInputParam("training", std::move(dataset)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -83,7 +56,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFMinResidueBoundTest", SetInputParam("training", std::move(dataset)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -101,7 +74,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFMaxIterationsBoundTest", SetInputParam("training", std::move(dataset)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -121,14 +94,14 @@ TEST_CASE_METHOD(CFTestFixture, "CFRecommendationsBoundTest", SetInputParam("max_iterations", int(5)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // recommendations should not be negative. SetInputParam("recommendations", int(-1)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -147,21 +120,21 @@ TEST_CASE_METHOD(CFTestFixture, "CFNeighborhoodBoundTest", SetInputParam("training", std::move(dataset)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // neighborhood should not be negative. SetInputParam("neighborhood", int(-1)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // neighborhood should not be larger than the number of users. SetInputParam("neighborhood", int(userNum + 1)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -181,7 +154,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFAlgorithmBoundTest", SetInputParam("training", std::move(dataset)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -205,12 +178,10 @@ TEST_CASE_METHOD(CFTestFixture, "CFModelReuseTest", SetInputParam("max_iterations", int(10)); SetInputParam("algorithm", algorithm); - mlpackMain(); + RUN_BINDING(); - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["max_iterations"].wasPassed = false; - IO::GetSingleton().Parameters()["algorithm"].wasPassed = false; + CFModel* m = params.Get("output_model"); + ResetSettings(); // Reuse the model to get recommendations. size_t recommendations = 3; @@ -220,12 +191,11 @@ TEST_CASE_METHOD(CFTestFixture, "CFModelReuseTest", SetInputParam("query", std::move(query)); SetInputParam("recommendations", int(recommendations)); - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); - const Mat& output = IO::GetParam>("output"); + const Mat& output = params.Get>("output"); REQUIRE(output.n_rows == recommendations); REQUIRE(output.n_cols == querySize); @@ -246,9 +216,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFAllUserRecommendationsTest", SetInputParam("max_iterations", int(10)); SetInputParam("all_user_recommendations", true); - mlpackMain(); + RUN_BINDING(); - const Mat& output = IO::GetParam>("output"); + const Mat& output = params.Get>("output"); REQUIRE(output.n_cols == userNum); } @@ -268,9 +238,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFRankTest", SetInputParam("max_iterations", int(10)); SetInputParam("algorithm", std::string("NMF")); - mlpackMain(); + RUN_BINDING(); - const CFModel* outputModel = IO::GetParam("output_model"); + const CFModel* outputModel = params.Get("output_model"); CFType& cf = dynamic_cast&>(*(outputModel->CF())).CF(); @@ -296,9 +266,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFMinResidueTest", // The execution of CF algorithm depends on initial random seed. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - outputModel = IO::GetParam("output_model"); + outputModel = params.Get("output_model"); // By default the main program use NMFPolicy. CFType& cf = dynamic_cast("output_model"); + outputModel = params.Get("output_model"); // By default the main program use NMFPolicy. CFType& cf2 = dynamic_cast("output_model"); + outputModel = params.Get("output_model"); // By default, the main program use NMFPolicy. CFType& cf = dynamic_cast("output_model"); + outputModel = params.Get("output_model"); // By default, the main program use NMFPolicy. CFType& cf2 = dynamic_cast("output_model"); + outputModel = params.Get("output_model"); // By default, the main program use NMFPolicy. CFType& cf = dynamic_cast("output_model"); + outputModel = params.Get("output_model"); // By default the main program use NMFPolicy. CFType& cf2 = dynamic_cast output1 = IO::GetParam>("output"); + const arma::Mat output1 = params.Get>("output"); ResetSettings(); @@ -464,9 +434,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFNeighborhoodTest", // The execution of CF algorithm depends on initial random seed. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output2 = IO::GetParam>("output"); + const arma::Mat output2 = params.Get>("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); @@ -491,7 +461,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFInterpolationAlgorithmBoundTest", SetInputParam("query", query); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -517,42 +487,39 @@ TEST_CASE_METHOD(CFTestFixture, "CFInterpolationTest", SetInputParam("interpolation", std::string("average")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output1 = IO::GetParam>("output"); + const arma::Mat output1 = params.Get>("output"); REQUIRE(output1.n_rows == 5); REQUIRE(output1.n_cols == 7); - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["max_iterations"].wasPassed = false; - IO::GetSingleton().Parameters()["algorithm"].wasPassed = false; + CFModel* m = params.Get("output_model"); + ResetSettings(); // Using regression interpolation algorithm. - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); SetInputParam("query", query); SetInputParam("interpolation", std::string("regression")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output2 = IO::GetParam>("output"); + const arma::Mat output2 = params.Get>("output"); REQUIRE(output2.n_rows == 5); REQUIRE(output2.n_cols == 7); // Using similarity interpolation algorithm. SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + std::move(params.Get("output_model"))); SetInputParam("query", query); SetInputParam("interpolation", std::string("similarity")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output3 = IO::GetParam>("output"); + const arma::Mat output3 = params.Get>("output"); REQUIRE(output3.n_rows == 5); REQUIRE(output3.n_cols == 7); @@ -581,7 +548,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFNeighborSearchAlgorithmBoundTest", SetInputParam("query", query); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -607,42 +574,39 @@ TEST_CASE_METHOD(CFTestFixture, "CFNeighborSearchTest", SetInputParam("neighbor_search", std::string("euclidean")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output1 = IO::GetParam>("output"); + const arma::Mat output1 = params.Get>("output"); REQUIRE(output1.n_rows == 5); REQUIRE(output1.n_cols == 7); - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["max_iterations"].wasPassed = false; - IO::GetSingleton().Parameters()["algorithm"].wasPassed = false; + CFModel* m = params.Get("output_model"); + ResetSettings(); // Using cosine neighbor search algorithm. - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); SetInputParam("query", query); SetInputParam("neighbor_search", std::string("cosine")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output2 = IO::GetParam>("output"); + const arma::Mat output2 = params.Get>("output"); REQUIRE(output2.n_rows == 5); REQUIRE(output2.n_cols == 7); // Using pearson neighbor search algorithm. SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + std::move(params.Get("output_model"))); SetInputParam("query", query); SetInputParam("neighbor_search", std::string("pearson")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output3 = IO::GetParam>("output"); + const arma::Mat output3 = params.Get>("output"); REQUIRE(output3.n_rows == 5); REQUIRE(output3.n_cols == 7); @@ -674,7 +638,7 @@ TEST_CASE_METHOD(CFTestFixture, "CFNormalizationBoundTest", SetInputParam("query", query); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -702,9 +666,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFNormalizationTest", SetInputParam("normalization", std::string("none")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output1 = IO::GetParam>("output"); + const arma::Mat output1 = params.Get>("output"); REQUIRE(output1.n_rows == 5); REQUIRE(output1.n_cols == 7); @@ -721,9 +685,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFNormalizationTest", SetInputParam("normalization", std::string("item_mean")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output2 = IO::GetParam>("output"); + const arma::Mat output2 = params.Get>("output"); REQUIRE(output2.n_rows == 5); REQUIRE(output2.n_cols == 7); @@ -740,9 +704,9 @@ TEST_CASE_METHOD(CFTestFixture, "CFNormalizationTest", SetInputParam("normalization", std::string("z_score")); SetInputParam("recommendations", 5); - mlpackMain(); + RUN_BINDING(); - const arma::Mat output3 = IO::GetParam>("output"); + const arma::Mat output3 = params.Get>("output"); REQUIRE(output3.n_rows == 5); REQUIRE(output3.n_cols == 7); diff --git a/src/mlpack/tests/main_tests/dbscan_test.cpp b/src/mlpack/tests/main_tests/dbscan_test.cpp index ead1975c25..ccaf02c85e 100644 --- a/src/mlpack/tests/main_tests/dbscan_test.cpp +++ b/src/mlpack/tests/main_tests/dbscan_test.cpp @@ -2,44 +2,26 @@ * @file tests/main_tests/dbscan_test.cpp * @author Nikhil Goel * - * Test mlpackMain() of dbscan_main.cpp. + * Test RUN_BINDING() of dbscan_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "DBSCAN"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct DBSCANTestFixture -{ - public: - DBSCANTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~DBSCANTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(DBSCANTestFixture); /** * Check that number of output labels and number of input @@ -56,13 +38,13 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANOutputDimensionTest", SetInputParam("input", inputData); - mlpackMain(); + RUN_BINDING(); // Check that number of predicted labels is equal to the input test points. - REQUIRE(IO::GetParam>("assignments").n_cols == inputSize); - REQUIRE(IO::GetParam>("assignments").n_rows == 1); - REQUIRE(IO::GetParam("centroids").n_rows == 4); - REQUIRE(IO::GetParam("centroids").n_cols >= 1); + REQUIRE(params.Get>("assignments").n_cols == inputSize); + REQUIRE(params.Get>("assignments").n_rows == 1); + REQUIRE(params.Get("centroids").n_rows == 4); + REQUIRE(params.Get("centroids").n_cols >= 1); } /** @@ -79,7 +61,7 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANEpsilonTest", SetInputParam("epsilon", (double) -0.5); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -97,7 +79,7 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANMinSizeTest", SetInputParam("min_size", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -116,10 +98,10 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANClusterNumberTest", SetInputParam("min_size", (int) 1); SetInputParam("epsilon", (double) 0.1); - mlpackMain(); + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("assignments")); + output = std::move(params.Get>("assignments")); for (size_t i = 0; i < output.n_elem; ++i) REQUIRE(output[i] < inputData.n_cols); @@ -139,23 +121,21 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANDiffEpsilonTest", SetInputParam("input", inputData); SetInputParam("epsilon", (double) 1.0); - mlpackMain(); + RUN_BINDING(); arma::Row output1; - output1 = std::move(IO::GetParam>("assignments")); + output1 = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("epsilon", (double) 0.5); - mlpackMain(); + RUN_BINDING(); arma::Row output2; - output2 = std::move(IO::GetParam>("assignments")); + output2 = std::move(params.Get>("assignments")); REQUIRE(arma::accu(output1 != output2) > 1); } @@ -175,25 +155,22 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANDiffMinSizeTest", SetInputParam("epsilon", (double) 0.4); SetInputParam("min_size", (int) 5); - mlpackMain(); + RUN_BINDING(); arma::Row output1; - output1 = std::move(IO::GetParam>("assignments")); + output1 = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; - IO::GetSingleton().Parameters()["min_size"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("epsilon", (double) 0.5); SetInputParam("min_size", (int) 40); - mlpackMain(); + RUN_BINDING(); arma::Row output2; - output2 = std::move(IO::GetParam>("assignments")); + output2 = std::move(params.Get>("assignments")); REQUIRE(arma::accu(output1 != output2) > 1); } @@ -214,7 +191,7 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANTreeTypeTest", SetInputParam("tree_type", std::string("binary")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -234,130 +211,114 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANDiffTreeTypeTest", SetInputParam("input", inputData); SetInputParam("tree_type", std::string("kd")); - mlpackMain(); + RUN_BINDING(); arma::Row kdOutput; - kdOutput = std::move(IO::GetParam>("assignments")); + kdOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = r tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("r")); - mlpackMain(); + RUN_BINDING(); arma::Row rOutput; - rOutput = std::move(IO::GetParam>("assignments")); + rOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree type = r-star tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("r-star")); - mlpackMain(); + RUN_BINDING(); arma::Row rStarOutput; - rStarOutput = std::move(IO::GetParam>("assignments")); + rStarOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = x tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("x")); - mlpackMain(); + RUN_BINDING(); arma::Row xOutput; - xOutput = std::move(IO::GetParam>("assignments")); + xOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = hilbert-r tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("hilbert-r")); - mlpackMain(); + RUN_BINDING(); arma::Row hilbertROutput; - hilbertROutput = std::move(IO::GetParam>("assignments")); + hilbertROutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = r-plus tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("r-plus")); - mlpackMain(); + RUN_BINDING(); arma::Row rPlusOutput; - rPlusOutput = std::move(IO::GetParam>("assignments")); + rPlusOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = r-plus-plus tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("r-plus-plus")); - mlpackMain(); + RUN_BINDING(); arma::Row rPlusPlusOutput; - rPlusPlusOutput = std::move(IO::GetParam>("assignments")); + rPlusPlusOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = cover tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("cover")); - mlpackMain(); + RUN_BINDING(); arma::Row coverOutput; - coverOutput = std::move(IO::GetParam>("assignments")); + coverOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Tree Type = ball tree. SetInputParam("input", inputData); SetInputParam("tree_type", std::string("ball")); - mlpackMain(); + RUN_BINDING(); arma::Row ballOutput; - ballOutput = std::move(IO::GetParam>("assignments")); + ballOutput = std::move(params.Get>("assignments")); CheckMatrices(kdOutput, rOutput); CheckMatrices(kdOutput, rStarOutput); @@ -382,22 +343,21 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANSingleTreeTest", SetInputParam("input", inputData); - mlpackMain(); + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("assignments")); + output = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("single_mode", true); - mlpackMain(); + RUN_BINDING(); arma::Row singleModeOutput; - singleModeOutput = std::move(IO::GetParam>("assignments")); + singleModeOutput = std::move(params.Get>("assignments")); CheckMatrices(output, singleModeOutput); } @@ -415,22 +375,21 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANNaiveSearchTest", SetInputParam("input", inputData); - mlpackMain(); + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("assignments")); + output = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("naive", true); - mlpackMain(); + RUN_BINDING(); arma::Row naiveOutput; - naiveOutput = std::move(IO::GetParam>("assignments")); + naiveOutput = std::move(params.Get>("assignments")); CheckMatrices(output, naiveOutput); } @@ -451,27 +410,23 @@ TEST_CASE_METHOD(DBSCANTestFixture, "DBSCANRandomSelectionFlagTest", SetInputParam("min_size", 1); SetInputParam("selection_type", std::string("ordered")); - mlpackMain(); + RUN_BINDING(); arma::Row orderedOutput; - orderedOutput = std::move(IO::GetParam>("assignments")); + orderedOutput = std::move(params.Get>("assignments")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; - IO::GetSingleton().Parameters()["min_size"].wasPassed = false; - IO::GetSingleton().Parameters()["selection_type"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("epsilon", (double) 0.358); SetInputParam("min_size", 1); SetInputParam("selection_type", std::string("random")); - mlpackMain(); + RUN_BINDING(); arma::Row randomOutput; - randomOutput = std::move(IO::GetParam>("assignments")); + randomOutput = std::move(params.Get>("assignments")); REQUIRE(arma::accu(orderedOutput != randomOutput) > 0); } diff --git a/src/mlpack/tests/main_tests/decision_stump_test.cpp b/src/mlpack/tests/main_tests/decision_stump_test.cpp deleted file mode 100644 index 8919a7b973..0000000000 --- a/src/mlpack/tests/main_tests/decision_stump_test.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/** - * @file tests/main_tests/decision_stump_test.cpp - * @author Manish Kumar - * - * Test mlpackMain() of decision_stump_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 - -#include -static const std::string testName = "DecisionStump"; - -#include -#include -#include "test_helper.hpp" - -#include "../test_catch_tools.hpp" -#include "../catch.hpp" - -using namespace mlpack; - -struct DecisionStumpTestFixture -{ - public: - DecisionStumpTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~DecisionStumpTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -/** - * Ensure that we get desired dimensions when both training - * data and labels are passed. - */ -TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpOutputDimensionTest", - "[DecisionStumpMainTest][BindingTests]") -{ - arma::mat inputData; - if (!data::Load("trainSet.csv", inputData)) - FAIL("Cannot load train dataset trainSet.csv!"); - - // Get the labels out. - arma::Row labels(inputData.n_cols); - for (size_t i = 0; i < inputData.n_cols; ++i) - labels[i] = inputData(inputData.n_rows - 1, i); - - // Delete the last row containing labels from input dataset. - inputData.shed_row(inputData.n_rows - 1); - - arma::mat testData; - if (!data::Load("testSet.csv", testData)) - FAIL("Cannot load test dataset testSet.csv!"); - - // Delete the last row containing labels from test dataset. - testData.shed_row(testData.n_rows - 1); - - size_t testSize = testData.n_cols; - - // Input training data. - SetInputParam("training", std::move(inputData)); - SetInputParam("labels", std::move(labels)); - - // Input test data. - SetInputParam("test", std::move(testData)); - - mlpackMain(); - - // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - - // Check prediction have only single row. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); -} - -/** - * Check that last row of input file is used as labels - * when labels are not passed specifically and results - * are same from both label and labeless models. - */ -TEST_CASE_METHOD(DecisionStumpTestFixture, - "DecisionStumpLabelsLessDimensionTest", - "[DecisionStumpMainTest][BindingTests]") -{ - // Train DS without providing labels. - arma::mat inputData; - if (!data::Load("trainSet.csv", inputData)) - FAIL("Cannot load train dataset trainSet.csv!"); - - // Get the labels out. - arma::Row labels(inputData.n_cols); - for (size_t i = 0; i < inputData.n_cols; ++i) - labels[i] = inputData(inputData.n_rows - 1, i); - - arma::mat testData; - if (!data::Load("testSet.csv", testData)) - FAIL("Cannot load test dataset testSet.csv!"); - - // Delete the last row containing labels from test dataset. - testData.shed_row(testData.n_rows - 1); - - size_t testSize = testData.n_cols; - - // Input training data. - SetInputParam("training", inputData); - - // Input test data. - SetInputParam("test", testData); - - mlpackMain(); - - // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - - // Check prediction have only single row. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - - // Reset data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - - // Store outputs. - arma::Row predictions; - predictions = std::move(IO::GetParam>("predictions")); - - // Delete the previous model. - bindings::tests::CleanMemory(); - - // Now train DS with labels provided. - - // Delete last row of inputData. - inputData.shed_row(inputData.n_rows - 1); - - // Input training data. - SetInputParam("training", std::move(inputData)); - SetInputParam("test", std::move(testData)); - // Pass Labels. - SetInputParam("labels", std::move(labels)); - - mlpackMain(); - - // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - - // Check prediction have only single row. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - - // Check that initial output and final output matrix - // from two models are same. - CheckMatrices(predictions, IO::GetParam>("predictions")); -} - -/** - * Ensure that saved model can be used again. - */ -TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpModelReuseTest", - "[DecisionStumpMainTest][BindingTests]") -{ - arma::mat inputData; - if (!data::Load("trainSet.csv", inputData)) - FAIL("Cannot load train dataset trainSet.csv!"); - - arma::mat testData; - if (!data::Load("testSet.csv", testData)) - FAIL("Cannot load test dataset testSet.csv!"); - - // Delete the last row containing labels from test dataset. - testData.shed_row(testData.n_rows - 1); - - size_t testSize = testData.n_cols; - - // Input training data. - SetInputParam("training", std::move(inputData)); - - // Input test data. - SetInputParam("test", testData); - - mlpackMain(); - - arma::Row predictions; - predictions = std::move(IO::GetParam>("predictions")); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - - // Input trained model. - SetInputParam("test", std::move(testData)); - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); - - mlpackMain(); - - // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - - // Check predictions have only single row. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - - // Check that initial predictions and final predicitons matrix - // using saved model are same. - CheckMatrices(predictions, IO::GetParam>("predictions")); -} - -/** - * Ensure that bucket_size is always positive. - */ -TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpBucketSizeTest", - "[DecisionStumpMainTest][BindingTests]") -{ - arma::mat inputData; - if (!data::Load("trainSet.csv", inputData)) - FAIL("Cannot load train dataset trainSet.csv!"); - - // Input training data. - SetInputParam("training", std::move(inputData)); - SetInputParam("bucket_size", (int) 0); - - Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); - Log::Fatal.ignoreInput = false; -} - -/** - * Make sure only one of training data or pre-trained model is passed. - */ -TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpTrainingVerTest", - "[DecisionStumpMainTest][BindingTests]") -{ - arma::mat inputData; - if (!data::Load("trainSet.csv", inputData)) - FAIL("Cannot load train dataset trainSet.csv!"); - - // Input training data. - SetInputParam("training", std::move(inputData)); - - mlpackMain(); - - // Input pre-trained model. - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); - - Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); - Log::Fatal.ignoreInput = false; -} diff --git a/src/mlpack/tests/main_tests/decision_tree_test.cpp b/src/mlpack/tests/main_tests/decision_tree_test.cpp index a7c7ae9fa4..dce07b9005 100644 --- a/src/mlpack/tests/main_tests/decision_tree_test.cpp +++ b/src/mlpack/tests/main_tests/decision_tree_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/decision_tree_test.cpp * @author Manish Kumar * - * Test mlpackMain() of decision_tree_main.cpp. + * Test RUN_BINDING() of decision_tree_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 @@ -12,11 +12,9 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "DecisionTree"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" @@ -24,28 +22,7 @@ static const std::string testName = "DecisionTree"; using namespace mlpack; using namespace data; -struct DecisionTreeTestFixture -{ - public: - DecisionTreeTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~DecisionTreeTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -void ResetDTSettings() -{ - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(DecisionTreeTestFixture); /** * Check that number of output points and @@ -80,16 +57,16 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeOutputDimensionTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 3); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 3); } /** @@ -126,16 +103,16 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 6); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 6); } /** @@ -164,7 +141,7 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeMinimumLeafSizeTest", SetInputParam("minimum_leaf_size", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -195,7 +172,7 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, SetInputParam("maximum_depth", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -225,7 +202,7 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionMinimumGainSplitTest", SetInputParam("minimum_gain_split", 1.5); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -257,10 +234,10 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionRegularisationTest", // Input test data. SetInputParam("test", std::make_tuple(info, inputData)); arma::Row pred; - mlpackMain(); - pred = std::move(IO::GetParam>("predictions")); + RUN_BINDING(); + pred = std::move(params.Get>("predictions")); - bindings::tests::CleanMemory(); + CleanMemory(); // Input training data. SetInputParam("training", std::make_tuple(info, inputData)); @@ -272,8 +249,8 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionRegularisationTest", // Input test data. SetInputParam("test", std::make_tuple(info, inputData)); arma::Row predRegularised; - mlpackMain(); - predRegularised = std::move(IO::GetParam>("predictions")); + RUN_BINDING(); + predRegularised = std::move(params.Get>("predictions")); size_t count = 0; REQUIRE(pred.n_elem == predRegularised.n_elem); @@ -318,38 +295,34 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionModelReuseTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); arma::Row predictions; arma::mat probabilities; - predictions = std::move(IO::GetParam>("predictions")); - probabilities = std::move(IO::GetParam("probabilities")); + predictions = std::move(params.Get>("predictions")); + probabilities = std::move(params.Get("probabilities")); + DecisionTreeModel* m = params.Get("output_model"); - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["weights"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + ResetSettings(); // Input trained model. SetInputParam("test", std::make_tuple(info, testData)); - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predicitions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 3); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 3); // Check that initial predictions and predictions using saved model are same. - CheckMatrices(predictions, IO::GetParam>("predictions")); - CheckMatrices(probabilities, IO::GetParam("probabilities")); + CheckMatrices(predictions, params.Get>("predictions")); + CheckMatrices(probabilities, params.Get("probabilities")); } /** @@ -375,18 +348,18 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeTrainingVerTest", SetInputParam("labels", std::move(labels)); SetInputParam("weights", std::move(weights)); - mlpackMain(); + RUN_BINDING(); - DecisionTreeModel* model = IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + DecisionTreeModel* model = params.Get("output_model"); + params.Get("output_model") = NULL; - bindings::tests::CleanMemory(); + CleanMemory(); // Input pre-trained model. SetInputParam("input_model", model); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -422,42 +395,37 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionModelCategoricalReuseTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); arma::Row predictions; arma::mat probabilities; - predictions = std::move(IO::GetParam>("predictions")); - probabilities = std::move(IO::GetParam("probabilities")); + predictions = std::move(params.Get>("predictions")); + probabilities = std::move(params.Get("probabilities")); - DecisionTreeModel* model = IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + DecisionTreeModel* model = params.Get("output_model"); + params.Get("output_model") = NULL; - bindings::tests::CleanMemory(); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["weights"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Input trained model. SetInputParam("test", std::make_tuple(info, testData)); SetInputParam("input_model", model); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predicitions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 6); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 6); // Check that initial predictions and predictions using saved model are same. - CheckMatrices(predictions, IO::GetParam>("predictions")); - CheckMatrices(probabilities, IO::GetParam("probabilities")); + CheckMatrices(predictions, params.Get>("predictions")); + CheckMatrices(probabilities, params.Get("probabilities")); } /** @@ -491,13 +459,13 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeMaximumDepthTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. arma::Row predictions; - predictions = std::move(IO::GetParam>("predictions")); + predictions = std::move(params.Get>("predictions")); - bindings::tests::CleanMemory(); + CleanMemory(); // Input training data. SetInputParam("training", std::make_tuple(info, inputData)); @@ -508,8 +476,8 @@ TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeMaximumDepthTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); CheckMatricesNotEqual(predictions, - IO::GetParam>("predictions")); + params.Get>("predictions")); } diff --git a/src/mlpack/tests/main_tests/det_test.cpp b/src/mlpack/tests/main_tests/det_test.cpp index f84dfd56ff..01a7e75bdb 100644 --- a/src/mlpack/tests/main_tests/det_test.cpp +++ b/src/mlpack/tests/main_tests/det_test.cpp @@ -2,45 +2,26 @@ * @file det_test.cpp * @author Manish Kumar * - * Test mlpackMain() of det_main.cpp + * Test RUN_BINDING() of det_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "DET"; - #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct DETTestFixture -{ - public: - DETTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~DETTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(DETTestFixture); /** * Check that number of output training_set_estimates and number of input data @@ -61,16 +42,16 @@ TEST_CASE_METHOD(DETTestFixture, "DETOutputDimensionTest", SetInputParam("training", trainingData); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Check the training_set_estimates has 100 points. - REQUIRE(IO::GetParam("training_set_estimates").n_rows == 1); - REQUIRE(IO::GetParam("training_set_estimates").n_cols == + REQUIRE(params.Get("training_set_estimates").n_rows == 1); + REQUIRE(params.Get("training_set_estimates").n_cols == trainingData.n_cols); // Check the test_set_estimates has 40 points. - REQUIRE(IO::GetParam("test_set_estimates").n_rows == 1); - REQUIRE(IO::GetParam("test_set_estimates").n_cols == + REQUIRE(params.Get("test_set_estimates").n_rows == 1); + REQUIRE(params.Get("test_set_estimates").n_cols == testData.n_cols); } @@ -91,10 +72,10 @@ TEST_CASE_METHOD(DETTestFixture, "DETParamBoundTest", SetInputParam("max_leaf_size", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); // Test for min_leaf_size. @@ -102,10 +83,10 @@ TEST_CASE_METHOD(DETTestFixture, "DETParamBoundTest", SetInputParam("min_leaf_size", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); // Test for folds. @@ -113,7 +94,7 @@ TEST_CASE_METHOD(DETTestFixture, "DETParamBoundTest", SetInputParam("folds", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -135,24 +116,24 @@ TEST_CASE_METHOD(DETTestFixture, "DETModelReuseTest", SetInputParam("training", std::move(trainingData)); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::mat trainingSetEstimates = - IO::GetParam("training_set_estimates"); - arma::mat testSetEstimates = IO::GetParam("test_set_estimates"); + params.Get("training_set_estimates"); + arma::mat testSetEstimates = params.Get("test_set_estimates"); - IO::GetSingleton().Parameters()["training"].wasPassed = false; + DTree<>* m = new DTree<>(*params.Get*>("output_model")); + CleanMemory(); + ResetSettings(); - SetInputParam("input_model", IO::GetParam*>("output_model")); - SetInputParam("test", std::move(testData)); + SetInputParam("input_model", m); + SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Check that initial estimates and final estimate using saved model are same. - CheckMatrices(trainingSetEstimates, - IO::GetParam("training_set_estimates")); CheckMatrices(testSetEstimates, - IO::GetParam("test_set_estimates")); + params.Get("test_set_estimates")); } /** @@ -176,11 +157,11 @@ TEST_CASE_METHOD(DETTestFixture, "DETViDimensionTest", SetInputParam("training", std::move(trainingData)); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check the number of output points equals number of input features. - REQUIRE(IO::GetParam("vi").n_rows == 1); - REQUIRE(IO::GetParam("vi").n_cols == testRows); + REQUIRE(params.Get("vi").n_rows == 1); + REQUIRE(params.Get("vi").n_cols == testRows); } /** @@ -195,12 +176,15 @@ TEST_CASE_METHOD(DETTestFixture, "DETModelValidityTest", SetInputParam("training", std::move(trainingData)); - mlpackMain(); + RUN_BINDING(); - SetInputParam("input_model", IO::GetParam*>("output_model")); + DTree<>* m = params.Get*>("output_model"); + ResetSettings(); + + SetInputParam("input_model", m); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -222,13 +206,13 @@ TEST_CASE_METHOD(DETTestFixture, "DETDiffMinLeafTest", SetInputParam("training", trainingData); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::mat trainingSetEstimates = - IO::GetParam("training_set_estimates"); - arma::mat testSetEstimates = IO::GetParam("test_set_estimates"); + params.Get("training_set_estimates"); + arma::mat testSetEstimates = params.Get("test_set_estimates"); - bindings::tests::CleanMemory(); + CleanMemory(); // Train model using min_leaf_size equals to 10. @@ -236,16 +220,16 @@ TEST_CASE_METHOD(DETTestFixture, "DETDiffMinLeafTest", SetInputParam("test", std::move(testData)); SetInputParam("min_leaf_size", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check that initial estimates and final estimates using two models are // different. REQUIRE(arma::accu(trainingSetEstimates == - IO::GetParam("training_set_estimates")) < + params.Get("training_set_estimates")) < trainingSetEstimates.n_elem); REQUIRE(arma::accu(testSetEstimates == - IO::GetParam("test_set_estimates")) < + params.Get("test_set_estimates")) < testSetEstimates.n_elem); } @@ -267,13 +251,13 @@ TEST_CASE_METHOD(DETTestFixture, "DETDiffMaxLeafTest", SetInputParam("training", trainingData); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::mat trainingSetEstimates = - IO::GetParam("training_set_estimates"); - arma::mat testSetEstimates = IO::GetParam("test_set_estimates"); + params.Get("training_set_estimates"); + arma::mat testSetEstimates = params.Get("test_set_estimates"); - bindings::tests::CleanMemory(); + CleanMemory(); // Train model using max_leaf_size equals to 40. @@ -281,16 +265,16 @@ TEST_CASE_METHOD(DETTestFixture, "DETDiffMaxLeafTest", SetInputParam("test", std::move(testData)); SetInputParam("max_leaf_size", (int) 40); - mlpackMain(); + RUN_BINDING(); // Check that initial estimates and final estimates using two models are // different. REQUIRE(arma::accu(trainingSetEstimates == - IO::GetParam("training_set_estimates")) < + params.Get("training_set_estimates")) < trainingSetEstimates.n_elem); REQUIRE(arma::accu(testSetEstimates == - IO::GetParam("test_set_estimates")) < + params.Get("test_set_estimates")) < testSetEstimates.n_elem); } @@ -312,13 +296,13 @@ TEST_CASE_METHOD(DETTestFixture, "DETDiffFoldsTest", SetInputParam("training", trainingData); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::mat trainingSetEstimates = - IO::GetParam("training_set_estimates"); - arma::mat testSetEstimates = IO::GetParam("test_set_estimates"); + params.Get("training_set_estimates"); + arma::mat testSetEstimates = params.Get("test_set_estimates"); - bindings::tests::CleanMemory(); + CleanMemory(); // Train model using folds equals to 20. @@ -326,16 +310,16 @@ TEST_CASE_METHOD(DETTestFixture, "DETDiffFoldsTest", SetInputParam("test", std::move(testData)); SetInputParam("folds", (int) 20); - mlpackMain(); + RUN_BINDING(); // Check that initial estimates and final estimates using two models are // different. REQUIRE(arma::accu(trainingSetEstimates == - IO::GetParam("training_set_estimates")) < + params.Get("training_set_estimates")) < trainingSetEstimates.n_elem); REQUIRE(arma::accu(testSetEstimates == - IO::GetParam("test_set_estimates")) < + params.Get("test_set_estimates")) < testSetEstimates.n_elem); } @@ -357,13 +341,13 @@ TEST_CASE_METHOD(DETTestFixture, "DETSkipPruningTest", SetInputParam("training", trainingData); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::mat trainingSetEstimates = - IO::GetParam("training_set_estimates"); - arma::mat testSetEstimates = IO::GetParam("test_set_estimates"); + params.Get("training_set_estimates"); + arma::mat testSetEstimates = params.Get("test_set_estimates"); - bindings::tests::CleanMemory(); + CleanMemory(); // Train model by bypassing pruning process. @@ -371,15 +355,15 @@ TEST_CASE_METHOD(DETTestFixture, "DETSkipPruningTest", SetInputParam("test", std::move(testData)); SetInputParam("skip_pruning", (bool) true); - mlpackMain(); + RUN_BINDING(); // Check that initial estimates and final estimates using two models are // different. REQUIRE(arma::accu(trainingSetEstimates == - IO::GetParam("training_set_estimates")) < + params.Get("training_set_estimates")) < trainingSetEstimates.n_elem); REQUIRE(arma::accu(testSetEstimates == - IO::GetParam("test_set_estimates")) < + params.Get("test_set_estimates")) < testSetEstimates.n_elem); } From 68ba3c3baafd98c2c835eff71f51f4f32942b91d Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 9 Jul 2021 17:13:47 -0400 Subject: [PATCH 530/729] Adapt tests through krann_test.cpp. --- src/mlpack/methods/hmm/hmm_train_main.cpp | 10 +- src/mlpack/tests/CMakeLists.txt | 36 +- src/mlpack/tests/main_tests/emst_test.cpp | 48 +-- src/mlpack/tests/main_tests/fastmks_test.cpp | 333 ++++++++---------- .../tests/main_tests/gmm_generate_test.cpp | 35 +- .../tests/main_tests/gmm_probability_test.cpp | 39 +- .../tests/main_tests/gmm_train_test.cpp | 196 +++++------ .../tests/main_tests/hmm_generate_test.cpp | 95 ++--- .../tests/main_tests/hmm_loglik_test.cpp | 36 +- .../tests/main_tests/hmm_test_utils.hpp | 8 +- .../tests/main_tests/hmm_train_test.cpp | 162 ++++----- .../tests/main_tests/hmm_viterbi_test.cpp | 51 +-- .../tests/main_tests/hoeffding_tree_test.cpp | 247 ++++++------- .../tests/main_tests/image_converter_test.cpp | 56 ++- src/mlpack/tests/main_tests/kde_test.cpp | 211 +++++------ .../tests/main_tests/kernel_pca_test.cpp | 110 +++--- src/mlpack/tests/main_tests/kfn_test.cpp | 259 ++++++-------- src/mlpack/tests/main_tests/kmeans_test.cpp | 126 +++---- src/mlpack/tests/main_tests/knn_test.cpp | 247 ++++++------- src/mlpack/tests/main_tests/krann_test.cpp | 178 +++++----- 20 files changed, 1064 insertions(+), 1419 deletions(-) diff --git a/src/mlpack/methods/hmm/hmm_train_main.cpp b/src/mlpack/methods/hmm/hmm_train_main.cpp index 0ba6550378..a6adbbe7f7 100644 --- a/src/mlpack/methods/hmm/hmm_train_main.cpp +++ b/src/mlpack/methods/hmm/hmm_train_main.cpp @@ -118,7 +118,7 @@ struct Init } //! Helper function to create discrete HMM. - static void Create(util::Params& params, + static void Create(util::Params& /* params */, HMM& hmm, vector& trainSeq, size_t states, @@ -141,7 +141,7 @@ struct Init } //! Helper function to create Gaussian HMM. - static void Create(util::Params& params, + static void Create(util::Params& /* params */, HMM& hmm, vector& trainSeq, size_t states, @@ -237,7 +237,7 @@ struct Init } //! Helper function for discrete emission distributions. - static void RandomInitialize(util::Params& params, + static void RandomInitialize(util::Params& /* params */, vector& e) { for (size_t i = 0; i < e.size(); ++i) @@ -248,7 +248,7 @@ struct Init } //! Helper function for Gaussian emission distributions. - static void RandomInitialize(util::Params& params, + static void RandomInitialize(util::Params& /* params */, vector& e) { for (size_t i = 0; i < e.size(); ++i) @@ -437,7 +437,7 @@ struct Train } }; -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { // Set random seed. if (params.Get("seed") != 0) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 3e7257f333..f161ca689c 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -135,24 +135,24 @@ add_executable(mlpack_test main_tests/dbscan_test.cpp main_tests/decision_tree_test.cpp main_tests/det_test.cpp -# main_tests/emst_test.cpp -# main_tests/fastmks_test.cpp -# main_tests/gmm_generate_test.cpp -# main_tests/gmm_probability_test.cpp -# main_tests/gmm_train_test.cpp -# main_tests/hmm_generate_test.cpp -# main_tests/hmm_loglik_test.cpp -# main_tests/hmm_test_utils.hpp -# main_tests/hmm_train_test.cpp -# main_tests/hmm_viterbi_test.cpp -# main_tests/hoeffding_tree_test.cpp -# main_tests/image_converter_test.cpp -# main_tests/kde_test.cpp -# main_tests/kernel_pca_test.cpp -# main_tests/kfn_test.cpp -# main_tests/kmeans_test.cpp -# main_tests/knn_test.cpp -# main_tests/krann_test.cpp + main_tests/emst_test.cpp + main_tests/fastmks_test.cpp + main_tests/gmm_generate_test.cpp + main_tests/gmm_probability_test.cpp + main_tests/gmm_train_test.cpp + main_tests/hmm_generate_test.cpp + main_tests/hmm_loglik_test.cpp + main_tests/hmm_test_utils.hpp + main_tests/hmm_train_test.cpp + main_tests/hmm_viterbi_test.cpp + main_tests/hoeffding_tree_test.cpp + main_tests/image_converter_test.cpp + main_tests/kde_test.cpp + main_tests/kernel_pca_test.cpp + main_tests/kfn_test.cpp + main_tests/kmeans_test.cpp + main_tests/knn_test.cpp + main_tests/krann_test.cpp main_tests/linear_regression_test.cpp # main_tests/lmnn_test.cpp # main_tests/linear_svm_test.cpp diff --git a/src/mlpack/tests/main_tests/emst_test.cpp b/src/mlpack/tests/main_tests/emst_test.cpp index aaf9a6669c..b39ff2d51d 100644 --- a/src/mlpack/tests/main_tests/emst_test.cpp +++ b/src/mlpack/tests/main_tests/emst_test.cpp @@ -2,22 +2,19 @@ * @file tests/main_tests/emst_test.cpp * @author Manish Kumar * - * Test mlpackMain() of emst_main.cpp. + * Test RUN_BINDING() of emst_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "EMST"; #include #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" #include "../catch.hpp" @@ -25,22 +22,7 @@ static const std::string testName = "EMST"; using namespace mlpack; -struct EMSTTestFixture -{ - public: - EMSTTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~EMSTTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(EMSTTestFixture); /** * Make sure that Output has 3 Dimensions and @@ -57,12 +39,12 @@ TEST_CASE_METHOD(EMSTTestFixture, "EMSTOutputDimensionTest", SetInputParam("input", std::move(x)); SetInputParam("leaf_size", (int) 2); - mlpackMain(); + RUN_BINDING(); // Now check that the output has 3 dimensions. - REQUIRE(IO::GetParam("output").n_rows == 3); + REQUIRE(params.Get("output").n_rows == 3); // Check number of output points. - REQUIRE(IO::GetParam("output").n_cols == 999); + REQUIRE(params.Get("output").n_cols == 999); } /** @@ -80,12 +62,12 @@ TEST_CASE_METHOD(EMSTTestFixture, "EMSTNaiveOutputDimensionTest", SetInputParam("input", std::move(x)); SetInputParam("naive", true); - mlpackMain(); + RUN_BINDING(); // Now check that the output has 3 dimensions. - REQUIRE(IO::GetParam("output").n_rows == 3); + REQUIRE(params.Get("output").n_rows == 3); // Check number of output points. - REQUIRE(IO::GetParam("output").n_cols == 999); + REQUIRE(params.Get("output").n_cols == 999); } /** @@ -103,7 +85,7 @@ TEST_CASE_METHOD(EMSTTestFixture, "EMSTInvalidLeafSizeTest", SetInputParam("leaf_size", (int) -1); // Invalid leaf size. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -121,13 +103,13 @@ TEST_CASE_METHOD(EMSTTestFixture, "EMSTFirstTwoOutputRowsIntegerTest", SetInputParam("input", std::move(x)); SetInputParam("leaf_size", (int) 2); - for (size_t i = 0; i < IO::GetParam("output").n_cols; ++i) + for (size_t i = 0; i < params.Get("output").n_cols; ++i) { - REQUIRE(IO::GetParam("output")(0, i) == - Approx(boost::math::iround(IO::GetParam("output")(0, i))). + REQUIRE(params.Get("output")(0, i) == + Approx(boost::math::iround(params.Get("output")(0, i))). epsilon(1e-7)); - REQUIRE(IO::GetParam("output")(1, i) == - Approx(boost::math::iround(IO::GetParam("output")(1, i))). + REQUIRE(params.Get("output")(1, i) == + Approx(boost::math::iround(params.Get("output")(1, i))). epsilon(1e-7)); } } diff --git a/src/mlpack/tests/main_tests/fastmks_test.cpp b/src/mlpack/tests/main_tests/fastmks_test.cpp index 81f6fcc3ed..bd7d85ca1c 100644 --- a/src/mlpack/tests/main_tests/fastmks_test.cpp +++ b/src/mlpack/tests/main_tests/fastmks_test.cpp @@ -3,44 +3,26 @@ * @author Yashwant Singh * @author Prabhat Sharma * - * Test mlpackMain() of fastmks_main.cpp. + * Test RUN_BINDING() of fastmks_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "FastMaxKernelSearch"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct FastMKSTestFixture -{ - public: - FastMKSTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~FastMKSTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(FastMKSTestFixture); /* * Check that we can't provide reference and query matrices @@ -64,7 +46,7 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSEqualDimensionTest", SetInputParam("k", (int) 4); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::invalid_argument); + REQUIRE_THROWS_AS(RUN_BINDING(), std::invalid_argument); Log::Fatal.ignoreInput = false; } @@ -83,7 +65,7 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSInvalidKTest", SetInputParam("k", (int) 51); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::invalid_argument); + REQUIRE_THROWS_AS(RUN_BINDING(), std::invalid_argument); Log::Fatal.ignoreInput = false; } @@ -99,7 +81,7 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSZeroKTest", SetInputParam("k", (int) 0); // Invalid when reference is specified. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -121,7 +103,7 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSInvalidKQueryDataTest", SetInputParam("k", (int) 51); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::invalid_argument); + REQUIRE_THROWS_AS(RUN_BINDING(), std::invalid_argument); Log::Fatal.ignoreInput = false; } @@ -138,16 +120,17 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSRefModelTest", SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); + + FastMKSModel* m = params.Get("output_model"); + ResetSettings(); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; SetInputParam("reference", std::move(referenceData)); // Input pre-trained model. - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -167,7 +150,7 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSInvalidKernelTest", SetInputParam("kernel", std::move(kernelName)); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -185,15 +168,15 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSOutputDimensionTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check the indices matrix has 10 points for each input point. - REQUIRE(IO::GetParam>("indices").n_rows == 10); - REQUIRE(IO::GetParam>("indices").n_cols == 100); + REQUIRE(params.Get>("indices").n_rows == 10); + REQUIRE(params.Get>("indices").n_cols == 100); // Check the kernel matrix has 10 points for each input point. - REQUIRE(IO::GetParam("kernels").n_rows == 10); - REQUIRE(IO::GetParam("kernels").n_cols == 100); + REQUIRE(params.Get("kernels").n_rows == 10); + REQUIRE(params.Get("kernels").n_cols == 100); } /** @@ -211,29 +194,27 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSModelReuseTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("query", queryData); - mlpackMain(); + RUN_BINDING(); arma::Mat indices; arma::mat kernel; FastMKSModel* output_model; - indices = std::move(IO::GetParam>("indices")); - kernel = std::move(IO::GetParam("kernels")); - output_model = std::move(IO::GetParam("output_model")); + indices = std::move(params.Get>("indices")); + kernel = std::move(params.Get("kernels")); + output_model = std::move(params.Get("output_model")); - // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("input_model", output_model); SetInputParam("query", queryData); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CheckMatrices(indices, IO::GetParam>("indices")); - CheckMatrices(kernel, IO::GetParam("kernels")); + CheckMatrices(indices, params.Get>("indices")); + CheckMatrices(kernel, params.Get("kernels")); } /* @@ -250,28 +231,24 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSQueryRefTest", SetInputParam("query", referenceData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat indices; arma::mat kernel; - indices = std::move(IO::GetParam>("indices")); - kernel = std::move(IO::GetParam("kernels")); - - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; + indices = std::move(params.Get>("indices")); + kernel = std::move(params.Get("kernels")); + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); SetInputParam("query", referenceData); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); - CheckMatrices(indices, - IO::GetParam>("indices")); - CheckMatrices(kernel, - IO::GetParam("kernels")); + CheckMatrices(indices, params.Get>("indices")); + CheckMatrices(kernel, params.Get("kernels")); } /* @@ -287,29 +264,25 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSNaiveModeTest", SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat indices; arma::mat kernel; - indices = std::move(IO::GetParam>("indices")); - kernel = std::move(IO::GetParam("kernels")); + indices = std::move(params.Get>("indices")); + kernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); SetInputParam("naive", true); - mlpackMain(); + RUN_BINDING(); - CheckMatrices(indices, - IO::GetParam>("indices")); - CheckMatrices(kernel, - IO::GetParam("kernels")); + CheckMatrices(indices, params.Get>("indices")); + CheckMatrices(kernel, params.Get("kernels")); } /* @@ -325,28 +298,24 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSTreeTest", SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat indices; arma::mat kernel; - indices = std::move(IO::GetParam>("indices")); - kernel = std::move(IO::GetParam("kernels")); + indices = std::move(params.Get>("indices")); + kernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); SetInputParam("single", true); - mlpackMain(); + RUN_BINDING(); - CheckMatrices(indices, - IO::GetParam>("indices")); - CheckMatrices(kernel, - IO::GetParam("kernels")); + CheckMatrices(indices, params.Get>("indices")); + CheckMatrices(kernel, params.Get("kernels")); } /* @@ -364,28 +333,26 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSBasisTest", SetInputParam("k", (int) 10); SetInputParam("base", 3.0); - mlpackMain(); + RUN_BINDING(); arma::Mat indices; arma::mat kernel; - indices = std::move(IO::GetParam>("indices")); - kernel = std::move(IO::GetParam("kernels")); + indices = std::move(params.Get>("indices")); + kernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); SetInputParam("base", 4.0); - mlpackMain(); + RUN_BINDING(); arma::Mat newindices; arma::mat newkernel; - newindices = std::move(IO::GetParam>("indices")); - newkernel = std::move(IO::GetParam("kernels")); + newindices = std::move(params.Get>("indices")); + newkernel = std::move(params.Get("kernels")); CheckMatrices(indices, newindices); CheckMatrices(kernel, newkernel); @@ -406,7 +373,7 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSBaseTest", SetInputParam("base", 0.0); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -453,30 +420,28 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSKernelTest", SetInputParam("query", queryData); SetInputParam("kernel", kerneltypes[i]); } - mlpackMain(); + RUN_BINDING(); if (i == 0) { indicesCompare = - std::move(IO::GetParam>("indices")); - kernelsCompare = std::move(IO::GetParam("kernels")); + std::move(params.Get>("indices")); + kernelsCompare = std::move(params.Get("kernels")); } else { - indices = std::move(IO::GetParam>("indices")); - kernels = std::move(IO::GetParam("kernels")); + indices = std::move(params.Get>("indices")); + kernels = std::move(params.Get("kernels")); CheckMatricesNotEqual(indicesCompare, indices); CheckMatricesNotEqual(kernelsCompare, kernels); } // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; - IO::GetSingleton().Parameters()["kernel"].wasPassed = false; + ResetSettings(); if (i != nofkerneltypes - 1) - bindings::tests::CleanMemory(); + CleanMemory(); } } @@ -491,63 +456,54 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSOffsetTest", // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - SetInputParam("kernel", (string)"polynomial"); + SetInputParam("kernel", (string) "polynomial"); SetInputParam("offset", 1.0); - mlpackMain(); + RUN_BINDING(); arma::mat polyKernel; - polyKernel = std::move(IO::GetParam("kernels")); + polyKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["offset"].wasPassed = false; - IO::GetParam("input_model") = NULL; - IO::GetParam("output_model") = NULL; + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "polynomial"); SetInputParam("offset", 4.0); - mlpackMain(); + RUN_BINDING(); - CheckMatricesNotEqual(polyKernel, - IO::GetParam("kernels")); + CheckMatricesNotEqual(polyKernel, params.Get("kernels")); - bindings::tests::CleanMemory(); + CleanMemory(); arma::mat inputData; if (!data::Load("data_3d_mixed.txt", inputData)) FAIL("Cannot load test dataset data_3d_ind.txt!"); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["kernel"].wasPassed = false; - IO::GetSingleton().Parameters()["offset"].wasPassed = false; - IO::GetParam("input_model") = NULL; - IO::GetParam("output_model") = NULL; + ResetSettings(); SetInputParam("reference", inputData); - SetInputParam("kernel", (std::string)"hyptan"); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (std::string) "hyptan"); SetInputParam("offset", 1.0); - mlpackMain(); + RUN_BINDING(); arma::mat hyptanKernel; - hyptanKernel = std::move(IO::GetParam("kernels")); + hyptanKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["offset"].wasPassed = false; - IO::GetParam("input_model") = NULL; - IO::GetParam("output_model") = NULL; + CleanMemory(); + ResetSettings(); SetInputParam("reference", inputData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (std::string) "hyptan"); SetInputParam("offset", 4.0); - mlpackMain(); + RUN_BINDING(); - CheckMatricesNotEqual(hyptanKernel, - IO::GetParam("kernels")); + CheckMatricesNotEqual(hyptanKernel, params.Get("kernels")); } /** @@ -561,26 +517,25 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSDegreeTest", // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - SetInputParam("kernel", (string)"polynomial"); + SetInputParam("kernel", (string) "polynomial"); SetInputParam("degree", 2.0); // Default value. - mlpackMain(); + RUN_BINDING(); arma::mat polyKernel; - polyKernel = std::move(IO::GetParam("kernels")); + polyKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["degree"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "polynomial"); SetInputParam("degree", 4.0); - mlpackMain(); + RUN_BINDING(); - CheckMatricesNotEqual(polyKernel, - IO::GetParam("kernels")); + CheckMatricesNotEqual(polyKernel, params.Get("kernels")); } /** @@ -596,26 +551,25 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSScaleTest", // Random input, some k <= number of reference points. SetInputParam("reference", inputData); SetInputParam("k", (int) 10); - SetInputParam("kernel", (std::string)"hyptan"); + SetInputParam("kernel", (std::string) "hyptan"); SetInputParam("scale", 1.0); // Default value. - mlpackMain(); + RUN_BINDING(); arma::mat hyptanKernel; - hyptanKernel = std::move(IO::GetParam("kernels")); + hyptanKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["scale"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", inputData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (std::string) "hyptan"); SetInputParam("scale", 1.5); - mlpackMain(); + RUN_BINDING(); - CheckMatricesNotEqual(hyptanKernel, - IO::GetParam("kernels")); + CheckMatricesNotEqual(hyptanKernel, params.Get("kernels")); } /** @@ -631,80 +585,73 @@ TEST_CASE_METHOD(FastMKSTestFixture, "FastMKSBandwidthTest", // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - SetInputParam("kernel", (string)"gaussian"); + SetInputParam("kernel", (string) "gaussian"); SetInputParam("bandwidth", 1.0); // Default value. - mlpackMain(); + RUN_BINDING(); arma::mat gaussianKernel; - gaussianKernel = std::move(IO::GetParam("kernels")); + gaussianKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["bandwidth"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "gaussian"); SetInputParam("bandwidth", 4.0); - mlpackMain(); - CheckMatricesNotEqual(gaussianKernel, - IO::GetParam("kernels")); + RUN_BINDING(); + CheckMatricesNotEqual(gaussianKernel, params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["bandwidth"].wasPassed = false; - IO::GetSingleton().Parameters()["kernel"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); - SetInputParam("kernel", (string)"epanechnikov"); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "epanechnikov"); SetInputParam("bandwidth", 1.0); // Default value. - mlpackMain(); + RUN_BINDING(); arma::mat epanKernel; - epanKernel = std::move(IO::GetParam("kernels")); + epanKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["bandwidth"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "epanechnikov"); SetInputParam("bandwidth", 4.0); - mlpackMain(); - CheckMatricesNotEqual(epanKernel, - IO::GetParam("kernels")); + RUN_BINDING(); + CheckMatricesNotEqual(epanKernel, params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["bandwidth"].wasPassed = false; - IO::GetSingleton().Parameters()["kernel"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); - SetInputParam("kernel", (string)"triangular"); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "triangular"); SetInputParam("bandwidth", 1.0); // Default value. - mlpackMain(); + RUN_BINDING(); arma::mat triKernel; - triKernel = std::move(IO::GetParam("kernels")); + triKernel = std::move(params.Get("kernels")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["bandwidth"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); + SetInputParam("k", (int) 10); + SetInputParam("kernel", (string) "triangular"); SetInputParam("bandwidth", 4.0); - mlpackMain(); + RUN_BINDING(); - CheckMatricesNotEqual(triKernel, - IO::GetParam("kernels")); + CheckMatricesNotEqual(triKernel, params.Get("kernels")); } diff --git a/src/mlpack/tests/main_tests/gmm_generate_test.cpp b/src/mlpack/tests/main_tests/gmm_generate_test.cpp index fe41ded07e..e712464ad7 100644 --- a/src/mlpack/tests/main_tests/gmm_generate_test.cpp +++ b/src/mlpack/tests/main_tests/gmm_generate_test.cpp @@ -2,43 +2,26 @@ * @file tests/main_tests/gmm_generate_test.cpp * @author Yashwant Singh * - * Test mlpackMain() of gmm_generate_main.cpp. + * Test RUN_BINDING() of gmm_generate_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "GmmGenerate"; #include #include #include +#include "main_test_fixture.hpp" -#include "test_helper.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct GmmGenerateTestFixture -{ - public: - GmmGenerateTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~GmmGenerateTestFixture() - { - // Clear the settings. - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(GmmGenerateTestFixture); // Checking that Samples must greater than 0. TEST_CASE_METHOD(GmmGenerateTestFixture, "GmmGenerateSamplesTest", @@ -53,8 +36,11 @@ TEST_CASE_METHOD(GmmGenerateTestFixture, "GmmGenerateSamplesTest", Log::Fatal.ignoreInput = true; SetInputParam("samples", 0); // Invalid - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; + + // Avoid double free (the fixture will try to delete the input model). + params.Get("input_model") = NULL; } // Checking dimensionality of output. @@ -68,10 +54,13 @@ TEST_CASE_METHOD(GmmGenerateTestFixture, "GmmGenerateDimensionality", SetInputParam("input_model", &gmm); SetInputParam("samples", (int) 10); - mlpackMain(); + RUN_BINDING(); - arma::mat output = std::move(IO::GetParam("output")); + arma::mat output = std::move(params.Get("output")); REQUIRE(output.n_rows == gmm.Dimensionality()); REQUIRE(output.n_cols == (int) 10); + + // Avoid double free (the fixture will try to delete the input model). + params.Get("input_model") = NULL; } diff --git a/src/mlpack/tests/main_tests/gmm_probability_test.cpp b/src/mlpack/tests/main_tests/gmm_probability_test.cpp index c4949b484a..7e3dfe380b 100644 --- a/src/mlpack/tests/main_tests/gmm_probability_test.cpp +++ b/src/mlpack/tests/main_tests/gmm_probability_test.cpp @@ -2,49 +2,25 @@ * @file tests/main_tests/gmm_probability_test.cpp * @author Yashwant Singh * - * Test mlpackMain() of gmm_probability_main.cpp. + * Test RUN_BINDING() of gmm_probability_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "GmmProbability"; #include #include #include - -#include "test_helper.hpp" +#include "main_test_fixture.hpp" #include "../catch.hpp" using namespace mlpack; -struct GmmProbabilityTestFixture -{ - public: - GmmProbabilityTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~GmmProbabilityTestFixture() - { - // Clear the settings. - IO::ClearSettings(); - } -}; - -void ResetGmmProbabilitySetting() -{ - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(GmmProbabilityTestFixture); // Checking the input and output dimensionality. TEST_CASE_METHOD(GmmProbabilityTestFixture, "GmmProbabilityDimensionality", @@ -60,8 +36,11 @@ TEST_CASE_METHOD(GmmProbabilityTestFixture, "GmmProbabilityDimensionality", SetInputParam("input", std::move(inputPoints)); SetInputParam("input_model", &gmm); - mlpackMain(); + RUN_BINDING(); - REQUIRE(IO::GetParam("output").n_cols == 5); - REQUIRE(IO::GetParam("output").n_rows == 1); + REQUIRE(params.Get("output").n_cols == 5); + REQUIRE(params.Get("output").n_rows == 1); + + // Avoid double free (the fixture will try to delete the input model). + params.Get("input_model") = NULL; } diff --git a/src/mlpack/tests/main_tests/gmm_train_test.cpp b/src/mlpack/tests/main_tests/gmm_train_test.cpp index 3a77342e70..7546ccbe58 100644 --- a/src/mlpack/tests/main_tests/gmm_train_test.cpp +++ b/src/mlpack/tests/main_tests/gmm_train_test.cpp @@ -2,51 +2,26 @@ * @file tests/main_tests/gmm_train_test.cpp * @author Yashwant Singh * - * Test mlpackMain() of gmm_train_main.cpp. + * Test RUN_BINDING() of gmm_train_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. */ - -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "GmmTrain"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct GmmTrainTestFixture -{ - public: - GmmTrainTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~GmmTrainTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -void ResetGmmTrainSetting() -{ - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(GmmTrainTestFixture); inline bool CheckDifferent(GMM* gmm1, GMM* gmm2) { @@ -84,7 +59,7 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainValidGaussianTest", SetInputParam("gaussians", 0); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -101,9 +76,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainOutputModelGaussianTest", SetInputParam("gaussians", (int) 2); SetInputParam("trials", (int) 2); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); REQUIRE(gmm->Gaussians() == (int) 2); } @@ -119,7 +94,7 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainMaxIterationsTest", SetInputParam("max_iterations", (int)-1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -134,7 +109,7 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainPositiveTrialsTest", SetInputParam("trials", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -149,10 +124,10 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GMMRefinedStartPercentageTest", Log::Fatal.ignoreInput = true; SetInputParam("percentage", (double) 2.0); // Invalid - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); SetInputParam("percentage", (double) -1.0); // Invalid - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -168,7 +143,7 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainSamplings", SetInputParam("samplings", (int) 0); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -181,19 +156,19 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainNumberOfGaussian", SetInputParam("input", inputData); SetInputParam("gaussians", (int) 2); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + + ResetSettings(); SetInputParam("input_model", gmm); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - SetInputParam("input", std::move(inputData)); + SetInputParam("gaussians", (int) 2); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(gmm1->Gaussians() == (int) 2); } @@ -208,19 +183,20 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainNoForcePositiveTest", SetInputParam("gaussians", (int) 1); SetInputParam("no_force_positive", true); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + + ResetSettings(); SetInputParam("input_model", gmm); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - SetInputParam("input", std::move(inputData)); + SetInputParam("gaussians", (int) 1); + SetInputParam("no_force_positive", true); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(gmm1->Gaussians() == (int) 1); } @@ -239,11 +215,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainNoiseTest", SetInputParam("gaussians", (int) 2); SetInputParam("noise", (double) 0.0); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(inputData)); SetInputParam("gaussians", (int) 2); @@ -251,9 +229,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainNoiseTest", math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(CheckDifferent(gmm, gmm1)); @@ -281,11 +259,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainTrialsTest", SetInputParam("max_iterations", (int) 1); SetInputParam("kmeans_max_iterations", (int) 1); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("gaussians", (int) 5); @@ -295,9 +275,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainTrialsTest", math::CustomRandomSeed(trial); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); success = CheckDifferent(gmm, gmm1); @@ -306,7 +286,7 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainTrialsTest", if (success) break; - bindings::tests::CleanMemory(); + CleanMemory(); } REQUIRE(success == true); @@ -326,11 +306,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainDiffMaxIterationsTest", SetInputParam("max_iterations", (int) 1); SetInputParam("kmeans_max_iterations", (int) 1); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(inputData)); SetInputParam("gaussians", (int) 3); @@ -340,9 +322,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainDiffMaxIterationsTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(CheckDifferent(gmm, gmm1)); @@ -370,11 +352,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainDiffKmeansMaxIterationsTest", SetInputParam("max_iterations", (int) 1); SetInputParam("kmeans_max_iterations", (int) 1); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(inputData)); SetInputParam("gaussians", (int) 3); @@ -384,11 +368,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainDiffKmeansMaxIterationsTest", math::CustomRandomSeed(trial); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); success = CheckDifferent(gmm, gmm1); @@ -398,7 +384,7 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainDiffKmeansMaxIterationsTest", if (success) break; - bindings::tests::CleanMemory(); + CleanMemory(); } REQUIRE(success == true); @@ -420,11 +406,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainPercentageTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(inputData)); SetInputParam("gaussians", (int) 2); @@ -434,9 +422,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainPercentageTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(CheckDifferent(gmm, gmm1)); @@ -459,11 +447,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainSamplingsTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(inputData)); SetInputParam("gaussians", (int) 8); @@ -473,9 +463,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainSamplingsTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(CheckDifferent(gmm, gmm1)); @@ -496,11 +486,13 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainToleranceTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + params.Get("output_model") = NULL; - ResetGmmTrainSetting(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(inputData)); SetInputParam("gaussians", (int) 2); @@ -508,9 +500,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainToleranceTest", mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); REQUIRE(CheckDifferent(gmm, gmm1)); @@ -526,29 +518,29 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainModelReuseTest", SetInputParam("input", inputData); SetInputParam("gaussians", (int) 2); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); + + ResetSettings(); SetInputParam("input_model", gmm); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - SetInputParam("input", inputData); + SetInputParam("gaussians", (int) 2); - mlpackMain(); + RUN_BINDING(); - GMM* gmm1 = IO::GetParam("output_model"); + GMM* gmm1 = params.Get("output_model"); + + ResetSettings(); SetInputParam("input_model", gmm1); - - IO::GetSingleton().Parameters()["input"].wasPassed = false; - SetInputParam("input", std::move(inputData)); + SetInputParam("gaussians", (int) 2); - mlpackMain(); + RUN_BINDING(); - GMM* gmm2 = IO::GetParam("output_model"); + GMM* gmm2 = params.Get("output_model"); REQUIRE(gmm1 == gmm2); } @@ -563,9 +555,9 @@ TEST_CASE_METHOD(GmmTrainTestFixture, "GmmTrainDiagCovariance", SetInputParam("gaussians", (int) 2); SetInputParam("diagonal_covariance", true); - mlpackMain(); + RUN_BINDING(); - GMM* gmm = IO::GetParam("output_model"); + GMM* gmm = params.Get("output_model"); arma::uvec sortedIndices = sort_index(gmm->Weights()); diff --git a/src/mlpack/tests/main_tests/hmm_generate_test.cpp b/src/mlpack/tests/main_tests/hmm_generate_test.cpp index daf1f1bd36..f9c425aca7 100644 --- a/src/mlpack/tests/main_tests/hmm_generate_test.cpp +++ b/src/mlpack/tests/main_tests/hmm_generate_test.cpp @@ -2,24 +2,22 @@ * @file tests/main_tests/hmm_generate_test.cpp * @author Daivik Nema * - * Test mlpackMain() of hmm_generate_main.cpp + * Test RUN_BINDING() of hmm_generate_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "HMMGenerate"; #include -#include -#include "test_helper.hpp" #include #include #include +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" @@ -28,22 +26,7 @@ static const std::string testName = "HMMGenerate"; using namespace mlpack; -struct HMMGenerateTestFixture -{ - public: - HMMGenerateTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~HMMGenerateTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(HMMGenerateTestFixture); TEST_CASE_METHOD(HMMGenerateTestFixture, "HMMGenerateDiscreteHMMCheckDimensionsTest", @@ -56,8 +39,8 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, // Initialize and train a discrete HMM model. HMMModel* h = new HMMModel(DiscreteHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Now that we have a trained HMM model, we can use it to generate a sequence // of states and observations - using the hmm_generate utility. @@ -68,21 +51,21 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, SetInputParam("length", length); // Call to hmm_generate_main. - mlpackMain(); + RUN_BINDING(); // Get the generated observation sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::mat obsSeq = IO::GetParam("output"); - REQUIRE(obsSeq.n_cols == (size_t)length); - REQUIRE(obsSeq.n_rows == (size_t)1); - REQUIRE(obsSeq.n_elem == (size_t)length); + arma::mat obsSeq = params.Get("output"); + REQUIRE(obsSeq.n_cols == (size_t) length); + REQUIRE(obsSeq.n_rows == (size_t) 1); + REQUIRE(obsSeq.n_elem == (size_t) length); // Get the generated state sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::Mat stateSeq = IO::GetParam>("state"); - REQUIRE(stateSeq.n_cols == (size_t)length); - REQUIRE(stateSeq.n_rows == (size_t)1); - REQUIRE(stateSeq.n_elem == (size_t)length); + arma::Mat stateSeq = params.Get>("state"); + REQUIRE(stateSeq.n_cols == (size_t) length); + REQUIRE(stateSeq.n_rows == (size_t) 1); + REQUIRE(stateSeq.n_elem == (size_t) length); } TEST_CASE_METHOD(HMMGenerateTestFixture, @@ -96,8 +79,8 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, // Initialize and train a gaussian HMM model. HMMModel* h = new HMMModel(GaussianHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Now that we have a trained HMM model, we can use it to generate a sequence // of states and observations - using the hmm_generate utility. @@ -108,21 +91,21 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, SetInputParam("length", length); // Call to hmm_generate_main. - mlpackMain(); + RUN_BINDING(); // Get the generated observation sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::mat obsSeq = IO::GetParam("output"); - REQUIRE(obsSeq.n_cols == (size_t)length); - REQUIRE(obsSeq.n_rows == (size_t)1); - REQUIRE(obsSeq.n_elem == (size_t)length); + arma::mat obsSeq = params.Get("output"); + REQUIRE(obsSeq.n_cols == (size_t) length); + REQUIRE(obsSeq.n_rows == (size_t) 1); + REQUIRE(obsSeq.n_elem == (size_t) length); // Get the generated state sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::Mat stateSeq = IO::GetParam>("state"); - REQUIRE(stateSeq.n_cols == (size_t)length); - REQUIRE(stateSeq.n_rows == (size_t)1); - REQUIRE(stateSeq.n_elem == (size_t)length); + arma::Mat stateSeq = params.Get>("state"); + REQUIRE(stateSeq.n_cols == (size_t) length); + REQUIRE(stateSeq.n_rows == (size_t) 1); + REQUIRE(stateSeq.n_elem == (size_t) length); } TEST_CASE_METHOD(HMMGenerateTestFixture, @@ -158,18 +141,18 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, SetInputParam("length", length); // Call to hmm_generate_main - mlpackMain(); + RUN_BINDING(); // Get the generated observation sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::mat obsSeq = IO::GetParam("output"); + arma::mat obsSeq = params.Get("output"); REQUIRE(obsSeq.n_cols == (size_t) length); REQUIRE(obsSeq.n_rows == (size_t) 2); REQUIRE(obsSeq.n_elem == (size_t) length * 2); // Get the generated state sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::Mat stateSeq = IO::GetParam>("state"); + arma::Mat stateSeq = params.Get>("state"); REQUIRE(stateSeq.n_cols == (size_t) length); REQUIRE(stateSeq.n_rows == (size_t) 1); REQUIRE(stateSeq.n_elem == (size_t) length); @@ -208,18 +191,18 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, SetInputParam("length", length); // Call to hmm_generate_main. - mlpackMain(); + RUN_BINDING(); // Get the generated observation sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::mat obsSeq = IO::GetParam("output"); + arma::mat obsSeq = params.Get("output"); REQUIRE(obsSeq.n_cols == (size_t) length); REQUIRE(obsSeq.n_rows == (size_t) 2); REQUIRE(obsSeq.n_elem == (size_t) length * 2); // Get the generated state sequence. Ensure that the generated sequence // has the correct length (as provided in the input). - arma::Mat stateSeq = IO::GetParam>("state"); + arma::Mat stateSeq = params.Get>("state"); REQUIRE(stateSeq.n_cols == (size_t) length); REQUIRE(stateSeq.n_rows == (size_t) 1); REQUIRE(stateSeq.n_elem == (size_t) length); @@ -236,8 +219,8 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, // Initialize and train a HMM model. HMMModel* h = new HMMModel(DiscreteHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Set the params for the hmm_generate invocation // Note that the length is negative - we expect that a runtime error will be @@ -247,7 +230,7 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, SetInputParam("length", length); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -262,8 +245,8 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, // Initialize and train a HMM model. HMMModel* h = new HMMModel(DiscreteHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Set the params for the hmm_generate invocation // Note that the start state is invalid - we expect that a runtime error will @@ -275,6 +258,6 @@ TEST_CASE_METHOD(HMMGenerateTestFixture, SetInputParam("start_state", startState); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/hmm_loglik_test.cpp b/src/mlpack/tests/main_tests/hmm_loglik_test.cpp index a13606fb92..4c3521063b 100644 --- a/src/mlpack/tests/main_tests/hmm_loglik_test.cpp +++ b/src/mlpack/tests/main_tests/hmm_loglik_test.cpp @@ -2,24 +2,22 @@ * @file tests/main_tests/hmm_loglik_test.cpp * @author Daivik Nema * - * Test mlpackMain() of hmm_loglik_main.cpp + * Test RUN_BINDING() of hmm_loglik_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "HMMLoglik"; #include -#include -#include "test_helper.hpp" #include #include #include +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" @@ -28,22 +26,7 @@ static const std::string testName = "HMMLoglik"; using namespace mlpack; -struct HMMLoglikTestFixture -{ - public: - HMMLoglikTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~HMMLoglikTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(HMMLoglikTestFixture); TEST_CASE_METHOD(HMMLoglikTestFixture, "HMMLoglikOutputNegativeTest", "[HMMLoglikMainTest][BindingTests]") @@ -55,17 +38,16 @@ TEST_CASE_METHOD(HMMLoglikTestFixture, "HMMLoglikOutputNegativeTest", // Initialize and train an HMM model. HMMModel* h = new HMMModel(DiscreteHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); - + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Set the params for the hmm_loglik invocation SetInputParam("input_model", h); SetInputParam("input", inp); - mlpackMain(); + RUN_BINDING(); - double loglik = IO::GetParam("log_likelihood"); + double loglik = params.Get("log_likelihood"); // Since the log of a probability <= 0 ... REQUIRE(loglik <= 0); diff --git a/src/mlpack/tests/main_tests/hmm_test_utils.hpp b/src/mlpack/tests/main_tests/hmm_test_utils.hpp index da6a531300..0e3a99830a 100644 --- a/src/mlpack/tests/main_tests/hmm_test_utils.hpp +++ b/src/mlpack/tests/main_tests/hmm_test_utils.hpp @@ -21,7 +21,9 @@ struct InitHMMModel { template - static void Apply(HMMType& hmm, vector* trainSeq) + static void Apply(util::Params& /* params */, + HMMType& hmm, + vector* trainSeq) { const size_t states = 2; @@ -202,7 +204,9 @@ struct InitHMMModel struct TrainHMMModel { template - static void Apply(HMMType& hmm, vector* trainSeq) + static void Apply(util::Params& /* params */, + HMMType& hmm, + vector* trainSeq) { // For now, perform unsupervised (Baum-Welch) training. hmm.Train(*trainSeq); diff --git a/src/mlpack/tests/main_tests/hmm_train_test.cpp b/src/mlpack/tests/main_tests/hmm_train_test.cpp index a743724c46..d12317bf8c 100644 --- a/src/mlpack/tests/main_tests/hmm_train_test.cpp +++ b/src/mlpack/tests/main_tests/hmm_train_test.cpp @@ -2,46 +2,28 @@ * @file tests/main_tests/hmm_train_test.cpp * @author Daivik Nema * - * Test mlpackMain() of hmm_train_main.cpp. + * Test RUN_BINDING() of hmm_train_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. */ -#include -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "HMMTrain"; #include -#include -#include "test_helper.hpp" -#include #include +#include +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct HMMTrainMainTestFixture -{ - public: - HMMTrainMainTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~HMMTrainMainTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(HMMTrainMainTestFixture); inline void FileExists(std::string fileName) { @@ -210,7 +192,7 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainStatesTest", SetInputParam("type", std::move(hmmType)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -230,7 +212,7 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainToleranceNonNegative", SetInputParam("tolerance", tol); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -249,7 +231,7 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainTypeTest", SetInputParam("type", std::move(hmmType)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -269,7 +251,7 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainGaussianTest", SetInputParam("gaussians", gaussians); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -289,7 +271,7 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainDiagonalGaussianTest", SetInputParam("gaussians", gaussians); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -311,23 +293,28 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainReuseDiscreteModelTest", data::Load(inputLabFileName, trainLab); REQUIRE(trainObs.n_rows == trainLab.n_rows); - SetInputParam("input_file", std::move(inputObsFileName)); - SetInputParam("labels_file", std::move(inputLabFileName)); - SetInputParam("type", std::move(hmmType)); + SetInputParam("input_file", inputObsFileName); + SetInputParam("labels_file", inputLabFileName); + SetInputParam("type", hmmType); SetInputParam("states", states); - mlpackMain(); + RUN_BINDING(); - HMMModel h1 = *(IO::GetParam("output_model")); + HMMModel h1 = *(params.Get("output_model")); + params.Get("output_model") = NULL; - SetInputParam("input_model", IO::GetParam("output_model")); + CleanMemory(); + ResetSettings(); - IO::GetSingleton().Parameters()["type"].wasPassed = false; - IO::GetSingleton().Parameters()["states"].wasPassed = false; + SetInputParam("input_model", &h1); + SetInputParam("input_file", std::move(inputObsFileName)); + SetInputParam("labels_file", std::move(inputLabFileName)); - mlpackMain(); + RUN_BINDING(); - HMMModel h2 = *(IO::GetParam("output_model")); + HMMModel h2 = *(params.Get("output_model")); + + ResetSettings(); ApproximatelyEqual(h1, h2); } @@ -346,23 +333,25 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainReuseGaussianModelTest", arma::mat trainObs; data::Load(inputObsFileName, trainObs); - SetInputParam("input_file", std::move(inputObsFileName)); + SetInputParam("input_file", inputObsFileName); SetInputParam("type", std::move(hmmType)); SetInputParam("states", states); - mlpackMain(); + RUN_BINDING(); - HMMModel h1 = *(IO::GetParam("output_model")); + HMMModel h1 = *(params.Get("output_model")); - SetInputParam("input_model", IO::GetParam("output_model")); + ResetSettings(); + + SetInputParam("input_model", &h1); + SetInputParam("input_file", std::move(inputObsFileName)); SetInputParam("tolerance", 1e10); - IO::GetSingleton().Parameters()["type"].wasPassed = false; - IO::GetSingleton().Parameters()["states"].wasPassed = false; + RUN_BINDING(); - mlpackMain(); + HMMModel h2 = *(params.Get("output_model")); - HMMModel h2 = *(IO::GetParam("output_model")); + ResetSettings(); ApproximatelyEqual(h1, h2); } @@ -376,25 +365,27 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainNoLabelsReuseModelTest", int seed = 0; FileExists(inputObsFileName); - SetInputParam("input_file", std::move(inputObsFileName)); + SetInputParam("input_file", inputObsFileName); SetInputParam("states", states); SetInputParam("type", std::move(hmmType)); SetInputParam("seed", seed); // This call will train HMM using Baum-Welch training - mlpackMain(); + RUN_BINDING(); - HMMModel h1 = *(IO::GetParam("output_model")); + HMMModel h1 = *(params.Get("output_model")); - SetInputParam("input_model", IO::GetParam("output_model")); + ResetSettings(); - IO::GetSingleton().Parameters()["type"].wasPassed = false; - IO::GetSingleton().Parameters()["states"].wasPassed = false; + SetInputParam("input_model", &h1); + SetInputParam("input_file", std::move(inputObsFileName)); // Train again using Baum Welch - mlpackMain(); + RUN_BINDING(); - HMMModel h2 = *(IO::GetParam("output_model")); + HMMModel h2 = *(params.Get("output_model")); + + ResetSettings(); ApproximatelyEqual(h1, h2); } @@ -412,21 +403,21 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainBatchModeTest", SetInputParam("labels_file", std::move(labelsFileName)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; SetInputParam("states", states); SetInputParam("type", std::move(hmmType)); SetInputParam("batch", (bool) true); - mlpackMain(); + RUN_BINDING(); // Now pass an observations file with extra non-existent filenames observationsFileName = "corrupt-observations-1.txt"; SetInputParam("input_file", std::move(observationsFileName)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Now a mismatch between #observation files and #label files @@ -434,7 +425,7 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainBatchModeTest", SetInputParam("input_file", std::move(observationsFileName)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -452,28 +443,28 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainRetrainTest1", SetInputParam("states", states); SetInputParam("seed", seed); - mlpackMain(); + RUN_BINDING(); - HMMModel h1 = *(IO::GetParam("output_model")); + HMMModel h1 = *(params.Get("output_model")); + arma::mat h1Transition = h1.DiscreteHMM()->Transition(); std::string inputObsFile2 = "obs4.csv"; - - IO::GetSingleton().Parameters()["input_file"].wasPassed = false; - IO::GetSingleton().Parameters()["type"].wasPassed = false; - IO::GetSingleton().Parameters()["states"].wasPassed = false; - FileExists(inputObsFile2); + + ResetSettings(); + SetInputParam("input_file", std::move(inputObsFile2)); - SetInputParam("input_model", IO::GetParam("output_model")); + SetInputParam("input_model", &h1); - mlpackMain(); + RUN_BINDING(); - HMMModel h2 = *(IO::GetParam("output_model")); + HMMModel h2 = *(params.Get("output_model")); + + ResetSettings(); REQUIRE(h1.Type() == h2.Type()); // Since we know that type of HMMs is discrete - CheckMatricesDiffer(h1.DiscreteHMM()->Transition(), - h2.DiscreteHMM()->Transition(), 1e-50); + CheckMatricesDiffer(h1Transition, h2.DiscreteHMM()->Transition(), 1e-50); } // Attempt to retrain but increase states the second time round @@ -489,23 +480,24 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainRetrainTest2", SetInputParam("type", std::move(type)); SetInputParam("states", states); - mlpackMain(); + RUN_BINDING(); - HMMModel h1 = *(IO::GetParam("output_model")); + HMMModel h1 = *(params.Get("output_model")); std::string inputObsFile2 = "obs3.csv"; std::string inputLabFile2 = "lab1_corrupt.csv"; + ResetSettings(); + SetInputParam("input_file", std::move(inputObsFile2)); // Provide a labels file with more states than initially specified SetInputParam("labels_file", std::move(inputLabFile2)); - SetInputParam("input_model", IO::GetParam("output_model")); + SetInputParam("input_model", &h1); - IO::GetSingleton().Parameters()["type"].wasPassed = false; - IO::GetSingleton().Parameters()["states"].wasPassed = false; + ResetSettings(); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -522,26 +514,28 @@ TEST_CASE_METHOD(HMMTrainMainTestFixture, "HMMTrainRetrainTest3", SetInputParam("type", std::move(type)); SetInputParam("states", states); - mlpackMain(); + RUN_BINDING(); - HMMModel h1 = *(IO::GetParam("output_model")); + HMMModel h1 = *(params.Get("output_model")); std::string inputObsFile2 = "obs2.csv"; std::string inputLabFile2 = "lab2.csv"; type = "gaussian"; + ResetSettings(); + SetInputParam("input_file", std::move(inputObsFile2)); SetInputParam("labels_file", std::move(inputLabFile2)); SetInputParam("type", std::move(type)); - SetInputParam("input_model", IO::GetParam("output_model")); + SetInputParam("input_model", &h1); - IO::GetSingleton().Parameters()["states"].wasPassed = false; - - mlpackMain(); + RUN_BINDING(); // Note that when emission type is changed -- like in this test, a warning // is printed stating that the new type is being ignored (no error is raised) - HMMModel h2 = *(IO::GetParam("output_model")); + HMMModel h2 = *(params.Get("output_model")); + + ResetSettings(); REQUIRE(h1.Type() == DiscreteHMM); REQUIRE(h2.Type() == DiscreteHMM); diff --git a/src/mlpack/tests/main_tests/hmm_viterbi_test.cpp b/src/mlpack/tests/main_tests/hmm_viterbi_test.cpp index bb6a5beafd..a95dd68bd4 100644 --- a/src/mlpack/tests/main_tests/hmm_viterbi_test.cpp +++ b/src/mlpack/tests/main_tests/hmm_viterbi_test.cpp @@ -2,24 +2,22 @@ * @file tests/main_tests/hmm_viterbi_test.cpp * @author Daivik Nema * - * Test mlpackMain() of hmm_viterbi_main.cpp + * Test RUN_BINDING() of hmm_viterbi_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "HMMViterbi"; #include -#include -#include "test_helper.hpp" #include #include #include +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" @@ -28,22 +26,7 @@ static const std::string testName = "HMMViterbi"; using namespace mlpack; -struct HMMViterbiTestFixture -{ - public: - HMMViterbiTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~HMMViterbiTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(HMMViterbiTestFixture); TEST_CASE_METHOD(HMMViterbiTestFixture, "HMMViterbiDiscreteHMMCheckDimensionsTest", @@ -56,8 +39,8 @@ TEST_CASE_METHOD(HMMViterbiTestFixture, // Initialize and train a discrete HMM model. HMMModel* h = new HMMModel(DiscreteHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Now that we have a trained HMM model, we can use it to predict the state // sequence for a given observation sequence - using the Viterbi algorithm. @@ -67,10 +50,10 @@ TEST_CASE_METHOD(HMMViterbiTestFixture, SetInputParam("input", inp); // Call to hmm_viterbi_main. - mlpackMain(); + RUN_BINDING(); // Get the output of viterbi inference. - arma::Mat out = IO::GetParam >("output"); + arma::Mat out = params.Get >("output"); // Output sequence length must be the same as input sequence length and // there should only be one row (since states are single dimensional values). @@ -89,8 +72,8 @@ TEST_CASE_METHOD(HMMViterbiTestFixture, // Initialize and train a gaussian HMM model. HMMModel* h = new HMMModel(GaussianHMM); - h->PerformAction>(&trainSeq); - h->PerformAction>(&trainSeq); + h->PerformAction>(params, &trainSeq); + h->PerformAction>(params, &trainSeq); // Now that we have a trained HMM model, we can use it to predict the state // sequence for a given observation sequence - using the Viterbi algorithm. @@ -100,10 +83,10 @@ TEST_CASE_METHOD(HMMViterbiTestFixture, SetInputParam("input", inp); // Call to hmm_viterbi_main. - mlpackMain(); + RUN_BINDING(); // Get the output of viterbi inference. - arma::Mat out = IO::GetParam >("output"); + arma::Mat out = params.Get >("output"); // Output sequence length must be the same as input sequence length and // there should only be one row (since states are single dimensional values). @@ -167,10 +150,10 @@ TEST_CASE_METHOD(HMMViterbiTestFixture, SetInputParam("input", observations); // Call to hmm_viterbi_main. - mlpackMain(); + RUN_BINDING(); // Get the output of viterbi inference. - arma::Mat out = IO::GetParam >("output"); + arma::Mat out = params.Get >("output"); // Output sequence length must be the same as input sequence length and // there should only be one row (since states are single dimensional values). @@ -234,10 +217,10 @@ TEST_CASE_METHOD(HMMViterbiTestFixture, SetInputParam("input", observations); // Call to hmm_viterbi_main. - mlpackMain(); + RUN_BINDING(); // Get the output of viterbi inference. - arma::Mat out = IO::GetParam >("output"); + arma::Mat out = params.Get >("output"); // Output sequence length must be the same as input sequence length and // there should only be one row (since states are single dimensional values). diff --git a/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp b/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp index 16ae37175b..a2f74ea5d0 100644 --- a/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp +++ b/src/mlpack/tests/main_tests/hoeffding_tree_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/hoeffding_tree_test.cpp * @author Haritha Nair * - * Test mlpackMain() of hoeffding_tree_main.cpp. + * Test RUN_BINDING() of hoeffding_tree_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 @@ -12,11 +12,9 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "HoeffdingTree"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" @@ -24,22 +22,7 @@ static const std::string testName = "HoeffdingTree"; using namespace mlpack; using namespace data; -struct HoeffdingTreeTestFixture -{ - public: - HoeffdingTreeTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~HoeffdingTreeTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(HoeffdingTreeTestFixture); /** * Check that number of output points and @@ -70,15 +53,15 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingTreeOutputDimensionTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals 1 for probabilities and predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 1); } /** @@ -111,15 +94,15 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals 1 for probabilities and predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 1); } /** @@ -155,27 +138,25 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingTreeLabelLessTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 1); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 1); arma::Row predictions; arma::mat probabilities; - predictions = std::move(IO::GetParam>("predictions")); - probabilities = std::move(IO::GetParam("probabilities")); + predictions = std::move(params.Get>("predictions")); + probabilities = std::move(params.Get("probabilities")); - bindings::tests::CleanMemory(); + // Reset passed parameters. + ResetSettings(); + CleanMemory(); inputData.shed_row(inputData.n_rows - 1); @@ -185,21 +166,21 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingTreeLabelLessTest", // Pass Labels. SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals 1 for probabilities and predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 1); // Check that initial and current predictions are same. CheckMatrices( - predictions, IO::GetParam>("predictions")); + predictions, params.Get>("predictions")); CheckMatrices( - probabilities, IO::GetParam("probabilities")); + probabilities, params.Get("probabilities")); } /** @@ -230,41 +211,42 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingModelReuseTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); + RUN_BINDING(); arma::Row predictions; arma::mat probabilities; - predictions = std::move(IO::GetParam>("predictions")); - probabilities = std::move(IO::GetParam("probabilities")); + predictions = std::move(params.Get>("predictions")); + probabilities = std::move(params.Get("probabilities")); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + HoeffdingTreeModel* m = params.Get("output_model"); + ResetSettings(); if (!data::Load("vc2_test.csv", testData, info)) FAIL("Cannot load test dataset vc2.csv!"); // Input trained model. SetInputParam("test", std::make_tuple(info, testData)); - SetInputParam("input_model", - IO::GetParam("output_model")); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals 1 for probabilities and predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 1); // Check that initial predictions and predictions using saved model are same. CheckMatrices( - predictions, IO::GetParam>("predictions")); + predictions, params.Get>("predictions")); CheckMatrices( - probabilities, IO::GetParam("probabilities")); + probabilities, params.Get("probabilities")); + + ResetSettings(); + delete m; } /** @@ -295,41 +277,42 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingModelCategoricalReuseTest", // Input test data. SetInputParam("test", std::make_tuple(info, testData)); - mlpackMain(); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + RUN_BINDING(); arma::Row predictions; arma::mat probabilities; - predictions = std::move(IO::GetParam>("predictions")); - probabilities = std::move(IO::GetParam("probabilities")); + predictions = std::move(params.Get>("predictions")); + probabilities = std::move(params.Get("probabilities")); + + // Reset passed parameters. + HoeffdingTreeModel* m = params.Get("output_model"); + ResetSettings(); if (!data::Load("braziltourism_test.arff", testData, info)) FAIL("Cannot load test dataset braziltourism_test.arff!"); // Input trained model. SetInputParam("test", std::make_tuple(info, testData)); - SetInputParam("input_model", - IO::GetParam("output_model")); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals 1 for probabilities and predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 1); // Check that initial predictions and predictions using saved model are same. CheckMatrices( - predictions, IO::GetParam>("predictions")); + predictions, params.Get>("predictions")); CheckMatrices( - probabilities, IO::GetParam("probabilities")); + probabilities, params.Get("probabilities")); + + ResetSettings(); + delete m; } /** @@ -362,18 +345,13 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMinSamplesTest", SetInputParam("min_samples", 10); SetInputParam("confidence", 0.25); - mlpackMain(); + RUN_BINDING(); + + nodes = (params.Get("output_model"))->NumNodes(); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - IO::GetSingleton().Parameters()["min_samples"].wasPassed = false; - IO::GetSingleton().Parameters()["confidence"].wasPassed = false; - - nodes = (IO::GetParam("output_model"))->NumNodes(); - - bindings::tests::CleanMemory(); + ResetSettings(); + CleanMemory(); if (!data::Load("vc2.csv", inputData, info)) FAIL("Cannot load train dataset vc2.csv!"); @@ -394,10 +372,10 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMinSamplesTest", SetInputParam("min_samples", 2000); SetInputParam("confidence", 0.25); - mlpackMain(); + RUN_BINDING(); // Check that small min_samples creates larger model. - REQUIRE((IO::GetParam("output_model"))->NumNodes() < + REQUIRE((params.Get("output_model"))->NumNodes() < (size_t) nodes); } @@ -431,18 +409,13 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMaxSamplesTest", SetInputParam("max_samples", 50000); SetInputParam("confidence", 0.95); - mlpackMain(); + RUN_BINDING(); + + nodes = (params.Get("output_model"))->NumNodes(); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - IO::GetSingleton().Parameters()["max_samples"].wasPassed = false; - IO::GetSingleton().Parameters()["confidence"].wasPassed = false; - - nodes = (IO::GetParam("output_model"))->NumNodes(); - - bindings::tests::CleanMemory(); + ResetSettings(); + CleanMemory(); if (!data::Load("vc2.csv", inputData, info)) FAIL("Cannot load train dataset vc2.csv!"); @@ -463,11 +436,11 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMaxSamplesTest", SetInputParam("max_samples", 5); SetInputParam("confidence", 0.95); - mlpackMain(); + RUN_BINDING(); // Check that large max_samples creates smaller model. REQUIRE((size_t) nodes < - (IO::GetParam("output_model"))->NumNodes()); + (params.Get("output_model"))->NumNodes()); } /** @@ -499,18 +472,14 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingConfidenceTest", SetInputParam("confidence", 0.95); - mlpackMain(); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - IO::GetSingleton().Parameters()["confidence"].wasPassed = false; + RUN_BINDING(); // Model with high confidence. - nodes = (IO::GetParam("output_model"))->NumNodes(); + nodes = (params.Get("output_model"))->NumNodes(); - bindings::tests::CleanMemory(); + // Reset passed parameters. + ResetSettings(); + CleanMemory(); if (!data::Load("vc2.csv", inputData, info)) FAIL("Cannot load train dataset vc2.csv!"); @@ -531,10 +500,10 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingConfidenceTest", // Model with low confidence. SetInputParam("confidence", 0.25); - mlpackMain(); + RUN_BINDING(); // Check that higher confidence creates smaller tree. REQUIRE((size_t) nodes < - (IO::GetParam("output_model"))->NumNodes()); + (params.Get("output_model"))->NumNodes()); } /** @@ -566,18 +535,14 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingPassesTest", SetInputParam("passes", 1); - mlpackMain(); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - IO::GetSingleton().Parameters()["passes"].wasPassed = false; + RUN_BINDING(); // Model with smaller number of passes. - nodes = (IO::GetParam("output_model"))->NumNodes(); + nodes = (params.Get("output_model"))->NumNodes(); - bindings::tests::CleanMemory(); + // Reset passed parameters. + ResetSettings(); + CleanMemory(); if (!data::Load("vc2.csv", inputData, info)) FAIL("Cannot load train dataset vc2.csv!"); @@ -598,11 +563,11 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingPassesTest", // Model with larger number of passes. SetInputParam("passes", 100); - mlpackMain(); + RUN_BINDING(); // Check that model with larger number of passes has greater number of nodes. REQUIRE((size_t) nodes < - (IO::GetParam("output_model"))->NumNodes()); + (params.Get("output_model"))->NumNodes()); } /** @@ -637,11 +602,11 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, SetInputParam("confidence", 0.25); - mlpackMain(); + RUN_BINDING(); // Check that number of children is 2. REQUIRE( - (IO::GetParam("output_model"))->NumNodes() - 1 == 2); + (params.Get("output_model"))->NumNodes() - 1 == 2); } /** @@ -676,20 +641,14 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, SetInputParam("max_samples", 50); SetInputParam("bins", 20); - mlpackMain(); - - // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; - IO::GetSingleton().Parameters()["max_samples"].wasPassed = false; - IO::GetSingleton().Parameters()["numeric_split_strategy"].wasPassed = false; - IO::GetSingleton().Parameters()["bins"].wasPassed = false; + RUN_BINDING(); // Initial model. - nodes = (IO::GetParam("output_model"))->NumNodes(); + nodes = (params.Get("output_model"))->NumNodes(); - bindings::tests::CleanMemory(); + // Reset passed parameters. + ResetSettings(); + CleanMemory(); if (!data::Load("vc2.csv", inputData, info)) FAIL("Cannot load train dataset vc2.csv!"); @@ -711,10 +670,10 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, SetInputParam("max_samples", 50); SetInputParam("bins", 10); - mlpackMain(); + RUN_BINDING(); // Check that both models have different number of nodes. - CHECK((IO::GetParam("output_model"))->NumNodes() != + CHECK((params.Get("output_model"))->NumNodes() != (size_t) nodes); } @@ -757,9 +716,9 @@ TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingBinningTest", SetInputParam("observations_before_binning", 100); SetInputParam("confidence", 0.25); - mlpackMain(); + RUN_BINDING(); // Check that no splitting has happened. - REQUIRE((IO::GetParam("output_model"))->NumNodes() + REQUIRE((params.Get("output_model"))->NumNodes() == 1); } diff --git a/src/mlpack/tests/main_tests/image_converter_test.cpp b/src/mlpack/tests/main_tests/image_converter_test.cpp index f51f87c886..b92f5f4530 100644 --- a/src/mlpack/tests/main_tests/image_converter_test.cpp +++ b/src/mlpack/tests/main_tests/image_converter_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/image_converter_test.cpp * @author Jeffin Sam * - * Test mlpackMain() of load_save_image_main.cpp. + * Test RUN_BINDING() of load_save_image_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 @@ -12,47 +12,31 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "ImageConverter"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" - using namespace mlpack; -struct ImageConverterTestFixture -{ - public: - ImageConverterTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~ImageConverterTestFixture() - { - // Clear the settings. - remove("test_image777.png"); - remove("test_image999.png"); - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(ImageConverterTestFixture); TEST_CASE_METHOD(ImageConverterTestFixture, "LoadImageTest", "[ImageConverterMainTest][BindingTests]") { SetInputParam>("input", {"test_image.png", "test_image.png"}); - mlpackMain(); - arma::mat output = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output = params.Get("output"); // width * height * channels. REQUIRE(output.n_rows == 50 * 50 * 3); REQUIRE(output.n_cols == 2); + + remove("test_image777.png"); + remove("test_image999.png"); } TEST_CASE_METHOD(ImageConverterTestFixture, "SaveImageTest", @@ -67,10 +51,9 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "SaveImageTest", SetInputParam("channels", 3); SetInputParam("save", true); SetInputParam("dataset", testimage); - mlpackMain(); + RUN_BINDING(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); SetInputParam>("input", {"test_image777.png", "test_image999.png"}); @@ -78,12 +61,15 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "SaveImageTest", SetInputParam("width", 5); SetInputParam("channels", 3); - mlpackMain(); - arma::mat output = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output = params.Get("output"); 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-7)); + + remove("test_image777.png"); + remove("test_image999.png"); } /** @@ -103,7 +89,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "IncompleteTest", SetInputParam("dataset", testimage); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -125,7 +111,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidInputTest", SetInputParam("channels", 3); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -146,7 +132,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidWidthTest", SetInputParam("channels", 3); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -167,7 +153,7 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "InvalidChannelTest", SetInputParam("channels", -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -183,6 +169,6 @@ TEST_CASE_METHOD(ImageConverterTestFixture, "EmptyInputTest", SetInputParam("channels", 50); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/kde_test.cpp b/src/mlpack/tests/main_tests/kde_test.cpp index 325130c928..b1453826fc 100644 --- a/src/mlpack/tests/main_tests/kde_test.cpp +++ b/src/mlpack/tests/main_tests/kde_test.cpp @@ -2,55 +2,31 @@ * @file tests/main_tests/kde_test.cpp * @author Roberto Hueso * - * Test mlpackMain() of kde_main.cpp + * Test RUN_BINDING() of kde_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "KDE"; - #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../catch.hpp" using namespace mlpack; -struct KDETestFixture -{ - public: - KDETestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~KDETestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -void ResetKDESettings() -{ - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(KDETestFixture); /** - * Ensure that the estimations we get for KDEMain, are the same as the ones we - * get from the KDE class without any wrappers. Requires normalization. - **/ + * Ensure that the estimations we get for KDEMain, are the same as the ones we + * get from the KDE class without any wrappers. Requires normalization. + */ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianRTreeResultsMain", "[KDEMainTest][BindingTests]") { @@ -81,9 +57,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianRTreeResultsMain", SetInputParam("rel_error", relError); SetInputParam("bandwidth", kernelBandwidth); - mlpackMain(); + RUN_BINDING(); - mainEstimations = std::move(IO::GetParam("predictions")); + mainEstimations = std::move(params.Get("predictions")); // Check whether results are equal. for (size_t i = 0; i < query.n_cols; ++i) @@ -91,9 +67,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianRTreeResultsMain", } /** - * Ensure that the estimations we get for KDEMain, are the same as the ones we - * get from the KDE class without any wrappers. Doesn't require normalization. - **/ + * Ensure that the estimations we get for KDEMain, are the same as the ones we + * get from the KDE class without any wrappers. Doesn't require normalization. + */ TEST_CASE_METHOD(KDETestFixture, "KDETriangularBallTreeResultsMain", "[KDEMainTest][BindingTests]") { @@ -122,9 +98,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDETriangularBallTreeResultsMain", SetInputParam("rel_error", relError); SetInputParam("bandwidth", kernelBandwidth); - mlpackMain(); + RUN_BINDING(); - mainEstimations = std::move(IO::GetParam("predictions")); + mainEstimations = std::move(params.Get("predictions")); // Check whether results are equal. for (size_t i = 0; i < query.n_cols; ++i) @@ -132,9 +108,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDETriangularBallTreeResultsMain", } /** - * Ensure that the estimations we get for KDEMain, are the same as the ones we - * get from the KDE class without any wrappers in the monochromatic case. - **/ + * Ensure that the estimations we get for KDEMain, are the same as the ones we + * get from the KDE class without any wrappers in the monochromatic case. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMonoResultsMain", "[KDEMainTest][BindingTests]") { @@ -164,9 +140,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMonoResultsMain", SetInputParam("rel_error", relError); SetInputParam("bandwidth", kernelBandwidth); - mlpackMain(); + RUN_BINDING(); - mainEstimations = std::move(IO::GetParam("predictions")); + mainEstimations = std::move(params.Get("predictions")); // Check whether results are equal. for (size_t i = 0; i < reference.n_cols; ++i) @@ -175,19 +151,19 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMonoResultsMain", /** * Ensuring that absence of input data is checked. - **/ + */ TEST_CASE_METHOD(KDETestFixture, "KDENoInputData", "[KDEMainTest][BindingTests]") { // No input data is not provided. Should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Check result has as many densities as query points. - **/ + */ TEST_CASE_METHOD(KDETestFixture, "KDEOutputSize", "[KDEMainTest][BindingTests]") { @@ -200,14 +176,14 @@ TEST_CASE_METHOD(KDETestFixture, "KDEOutputSize", SetInputParam("reference", reference); SetInputParam("query", query); - mlpackMain(); + RUN_BINDING(); // Check number of output elements. - REQUIRE(IO::GetParam("predictions").size() == samples); + REQUIRE(params.Get("predictions").size() == samples); } /** * Check that saved model can be reused. - **/ + */ TEST_CASE_METHOD(KDETestFixture, "KDEModelReuse", "[KDEMainTest][BindingTests]") { @@ -223,19 +199,24 @@ TEST_CASE_METHOD(KDETestFixture, "KDEModelReuse", SetInputParam("bandwidth", 2.4); SetInputParam("rel_error", 0.05); - mlpackMain(); + RUN_BINDING(); - arma::vec oldEstimations = std::move(IO::GetParam("predictions")); + arma::vec oldEstimations = std::move(params.Get("predictions")); + + KDEModel* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Change parameters and load model. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; SetInputParam("query", query); - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); + SetInputParam("bandwidth", 2.4); + SetInputParam("rel_error", 0.05); - mlpackMain(); + RUN_BINDING(); - arma::vec newEstimations = std::move(IO::GetParam("predictions")); + arma::vec newEstimations = std::move(params.Get("predictions")); // Check estimations are the same. for (size_t i = 0; i < samples; ++i) @@ -243,9 +224,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEModelReuse", } /** - * Ensure that the estimations we get for KDEMain, are the same as the ones we - * get from the KDE class without any wrappers using single-tree mode. - **/ + * Ensure that the estimations we get for KDEMain, are the same as the ones we + * get from the KDE class without any wrappers using single-tree mode. + */ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianSingleKDTreeResultsMain", "[KDEMainTest][BindingTests]") { @@ -276,9 +257,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianSingleKDTreeResultsMain", SetInputParam("rel_error", relError); SetInputParam("bandwidth", kernelBandwidth); - mlpackMain(); + RUN_BINDING(); - mainEstimations = std::move(IO::GetParam("predictions")); + mainEstimations = std::move(params.Get("predictions")); // Check whether results are equal. for (size_t i = 0; i < query.n_cols; ++i) @@ -286,8 +267,8 @@ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianSingleKDTreeResultsMain", } /** - * Ensure we get an exception when an invalid kernel is specified. - **/ + * Ensure we get an exception when an invalid kernel is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidKernel", "[KDEMainTest][BindingTests]") { @@ -300,13 +281,13 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidKernel", SetInputParam("kernel", std::string("linux")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid tree is specified. - **/ + * Ensure we get an exception when an invalid tree is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidTree", "[KDEMainTest][BindingTests]") { @@ -319,13 +300,13 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidTree", SetInputParam("tree", std::string("olive")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid algorithm is specified. - **/ + * Ensure we get an exception when an invalid algorithm is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidAlgorithm", "[KDEMainTest][BindingTests]") { @@ -338,14 +319,14 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidAlgorithm", SetInputParam("algorithm", std::string("bogosort")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when both reference and input_model are - * specified. - **/ + * Ensure we get an exception when both reference and input_model are + * specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainReferenceAndModel", "[KDEMainTest][BindingTests]") { @@ -359,13 +340,13 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainReferenceAndModel", SetInputParam("input_model", model); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid absolute error is specified. - **/ + * Ensure we get an exception when an invalid absolute error is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidAbsoluteError", "[KDEMainTest][BindingTests]") { @@ -379,17 +360,17 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidAbsoluteError", Log::Fatal.ignoreInput = true; // Invalid value. SetInputParam("abs_error", -0.1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Valid value. SetInputParam("abs_error", 5.8); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid relative error is specified. - **/ + * Ensure we get an exception when an invalid relative error is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidRelativeError", "[KDEMainTest][BindingTests]") { @@ -403,22 +384,22 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidRelativeError", Log::Fatal.ignoreInput = true; // Invalid under 0. SetInputParam("rel_error", -0.1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Invalid over 1. SetInputParam("rel_error", 1.1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Valid value. SetInputParam("rel_error", 0.3); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid Monte Carlo probability is - * specified. - **/ + * Ensure we get an exception when an invalid Monte Carlo probability is + * specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCProbability", "[KDEMainTest][BindingTests]") { @@ -434,22 +415,22 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCProbability", Log::Fatal.ignoreInput = true; // Invalid under 0. SetInputParam("mc_probability", -0.1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Invalid over 1. SetInputParam("mc_probability", 1.1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Valid value. SetInputParam("mc_probability", 0.3); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid Monte Carlo initial sample size - * is specified. - **/ + * Ensure we get an exception when an invalid Monte Carlo initial sample size + * is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCInitialSampleSize", "[KDEMainTest][BindingTests]") { @@ -465,22 +446,22 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCInitialSampleSize", Log::Fatal.ignoreInput = true; // Invalid under 0. SetInputParam("initial_sample_size", -1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Invalid 0. SetInputParam("initial_sample_size", 0); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Valid value. SetInputParam("initial_sample_size", 20); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid Monte Carlo entry coefficient - * is specified. - **/ + * Ensure we get an exception when an invalid Monte Carlo entry coefficient + * is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCEntryCoef", "[KDEMainTest][BindingTests]") { @@ -496,18 +477,18 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCEntryCoef", Log::Fatal.ignoreInput = true; // Invalid under 1. SetInputParam("mc_entry_coef", 0.5); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Valid greater than 1. SetInputParam("mc_entry_coef", 1.1); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); Log::Fatal.ignoreInput = false; } /** - * Ensure we get an exception when an invalid Monte Carlo break coefficient - * is specified. - **/ + * Ensure we get an exception when an invalid Monte Carlo break coefficient + * is specified. + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCBreakCoef", "[KDEMainTest][BindingTests]") { @@ -523,23 +504,23 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainInvalidMCBreakCoef", Log::Fatal.ignoreInput = true; // Invalid under 0. SetInputParam("mc_break_coef", -0.5); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Valid between 0 and 1. SetInputParam("mc_break_coef", 0.3); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); // Invalid greater than 1. SetInputParam("mc_break_coef", 1.1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** - * Ensure when --monte_carlo flag is true, then KDEMain actually uses Monte - * Carlo estimations. Since this test has a random component, it might fail - * (although it's unlikely). - **/ + * Ensure when --monte_carlo flag is true, then KDEMain actually uses Monte + * Carlo estimations. Since this test has a random component, it might fail + * (although it's unlikely). + */ TEST_CASE_METHOD(KDETestFixture, "KDEMainMonteCarloFlag", "[KDEMainTest][BindingTests]") { @@ -558,16 +539,16 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMainMonteCarloFlag", SetInputParam("monte_carlo", true); // Compute estimations 1. - mlpackMain(); - estimations1 = std::move(IO::GetParam("predictions")); + RUN_BINDING(); + estimations1 = std::move(params.Get("predictions")); - delete IO::GetParam("output_model"); + delete params.Get("output_model"); // Compute estimations 2. SetInputParam("reference", reference); SetInputParam("query", query); - mlpackMain(); - estimations2 = std::move(IO::GetParam("predictions")); + RUN_BINDING(); + estimations2 = std::move(params.Get("predictions")); // Check whether results are equal. differences = arma::abs(estimations1 - estimations2); diff --git a/src/mlpack/tests/main_tests/kernel_pca_test.cpp b/src/mlpack/tests/main_tests/kernel_pca_test.cpp index 733a388a7b..fe47219454 100644 --- a/src/mlpack/tests/main_tests/kernel_pca_test.cpp +++ b/src/mlpack/tests/main_tests/kernel_pca_test.cpp @@ -2,50 +2,26 @@ * @file tests/main_tests/kernel_pca_test.cpp * @author Saksham Bansal * - * Test mlpackMain() of kernel_pca_main.cpp. + * Test RUN_BINDING() of kernel_pca_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "KernelPrincipalComponentsAnalysis"; #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct KernelPCATestFixture -{ - public: - KernelPCATestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~KernelPCATestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -static void ResetSettings() -{ - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(KernelPCATestFixture); /** * Make sure that all valid kernels return correct output dimension. @@ -60,17 +36,18 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCADimensionTest", for (std::string& kernel : kernels) { + CleanMemory(); ResetSettings(); arma::mat x = arma::randu(5, 5); // Random input, new dimensionality of 3. SetInputParam("input", std::move(x)); SetInputParam("new_dimensionality", (int) 3); SetInputParam("kernel", kernel); - mlpackMain(); + RUN_BINDING(); // Now check that the output has 3 dimensions. - REQUIRE(IO::GetParam("output").n_rows == 3); - REQUIRE(IO::GetParam("output").n_cols == 5); + REQUIRE(params.Get("output").n_rows == 3); + REQUIRE(params.Get("output").n_cols == 5); } } @@ -86,7 +63,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCANoKernelTest", SetInputParam("new_dimensionality", (int) 3); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -103,7 +80,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCAInvalidKernelTest", SetInputParam("kernel", (std::string) "badName"); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -119,11 +96,11 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCA0DimensionalityTest", SetInputParam("input", std::move(x)); SetInputParam("new_dimensionality", (int) 0); SetInputParam("kernel", (std::string) "gaussian"); - mlpackMain(); + RUN_BINDING(); // Now check that the output has same dimensions as input. - REQUIRE(IO::GetParam("output").n_rows == 5); - REQUIRE(IO::GetParam("output").n_cols == 5); + REQUIRE(params.Get("output").n_rows == 5); + REQUIRE(params.Get("output").n_cols == 5); } /** @@ -138,14 +115,14 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCACenterTest", SetInputParam("input", x); SetInputParam("new_dimensionality", (int) 3); SetInputParam("kernel", (std::string) "linear"); - mlpackMain(); - arma::mat output1 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output1 = params.Get("output"); // Get output after centering the dataset. SetInputParam("input", std::move(x)); SetInputParam("center", true); - mlpackMain(); - arma::mat output2 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output2 = params.Get("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); @@ -164,7 +141,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCATooHighNewDimensionalityTest", SetInputParam("kernel", (std::string) "linear"); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -180,7 +157,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCANoInputTest", SetInputParam("kernel", (std::string) "linear"); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -199,7 +176,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCABadSamplingTest", SetInputParam("sampling", (std::string) "badName"); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -216,6 +193,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCABandWidthTest", for (std::string& kernel : kernels) { + CleanMemory(); ResetSettings(); arma::mat x = arma::randu(5, 5); @@ -225,15 +203,15 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCABandWidthTest", SetInputParam("kernel", kernel); SetInputParam("bandwidth", (double) 1); - mlpackMain(); - arma::mat output1 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output1 = params.Get("output"); // Get output using bandwidth 2. SetInputParam("input", std::move(x)); SetInputParam("bandwidth", (double) 2); - mlpackMain(); - arma::mat output2 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output2 = params.Get("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); @@ -252,6 +230,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCAOffsetTest", for (std::string& kernel : kernels) { + CleanMemory(); ResetSettings(); arma::mat x = arma::randu(5, 100); @@ -260,14 +239,14 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCAOffsetTest", SetInputParam("kernel", kernel); SetInputParam("offset", (double) 0.01); - mlpackMain(); - arma::mat output1 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output1 = params.Get("output"); SetInputParam("input", std::move(x)); SetInputParam("offset", (double) 0.1); - mlpackMain(); - arma::mat output2 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output2 = params.Get("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); @@ -287,14 +266,14 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCADegreeTest", SetInputParam("kernel", (std::string) "polynomial"); SetInputParam("degree", (double) 2); - mlpackMain(); - arma::mat output1 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output1 = params.Get("output"); SetInputParam("input", std::move(x)); SetInputParam("degree", (double) 3); - mlpackMain(); - arma::mat output2 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output2 = params.Get("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); @@ -313,14 +292,14 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCAKernelScaleTest", SetInputParam("kernel", (std::string) "hyptan"); SetInputParam("kernel_scale", (double) 2); - mlpackMain(); - arma::mat output1 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output1 = params.Get("output"); SetInputParam("input", std::move(x)); SetInputParam("kernel_scale", (double) 3); - mlpackMain(); - arma::mat output2 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output2 = params.Get("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); @@ -332,6 +311,7 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCAKernelScaleTest", TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCASamplingSchemeTest", "[KernelPCAMainTest][BindingTests]") { + CleanMemory(); ResetSettings(); arma::mat x = arma::randu(5, 500); @@ -342,21 +322,21 @@ TEST_CASE_METHOD(KernelPCATestFixture, "KernelPCASamplingSchemeTest", SetInputParam("nystroem_method", true); SetInputParam("sampling", (std::string) "kmeans"); - mlpackMain(); + RUN_BINDING(); - arma::mat output1 = IO::GetParam("output"); + arma::mat output1 = params.Get("output"); SetInputParam("input", x); SetInputParam("sampling", (std::string) "random"); - mlpackMain(); - arma::mat output2 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output2 = params.Get("output"); SetInputParam("input", x); SetInputParam("sampling", (std::string) "ordered"); - mlpackMain(); - arma::mat output3 = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output3 = params.Get("output"); // The resulting matrices should be different. REQUIRE(arma::any(arma::vectorise(output1 != output2))); diff --git a/src/mlpack/tests/main_tests/kfn_test.cpp b/src/mlpack/tests/main_tests/kfn_test.cpp index 2446c85fce..9a9eb323fb 100644 --- a/src/mlpack/tests/main_tests/kfn_test.cpp +++ b/src/mlpack/tests/main_tests/kfn_test.cpp @@ -3,44 +3,26 @@ * @author Atharva Khandait * @author Heet Sankesara * - * Test mlpackMain() of kfn_main.cpp. + * Test RUN_BINDING() of kfn_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "K-FurthestNeighborsSearch"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct KFNTestFixture -{ - public: - KFNTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~KFNTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(KFNTestFixture); /* * Check that we can't provide reference and query matrices @@ -64,7 +46,7 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNEqualDimensionTest", SetInputParam("k", (int) 10); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -83,26 +65,19 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidKTest", SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); - // SetInputParam("reference", referenceData); - // SetInputParam("k", (int) 0); // Invalid. - - // REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); - - // IO::GetSingleton().Parameters()["reference"].wasPassed = false; - // IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) -1); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -125,7 +100,7 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidKQueryDataTest", SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -143,7 +118,7 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNLeafSizeTest", SetInputParam("leaf_size", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -160,14 +135,14 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNRefModelTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Input pre-trained model. SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + std::move(params.Get("output_model"))); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -186,7 +161,7 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidTreeTypeTest", SetInputParam("tree_type", (string) "min-rp"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -205,7 +180,7 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidAlgoTest", SetInputParam("algorithm", (string) "triple_tree"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -224,23 +199,21 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidEpsilonTest", SetInputParam("epsilon", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("epsilon", (double) 2); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("epsilon", (double) 1); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -259,23 +232,21 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidPercentageTest", SetInputParam("percentage", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["percentage"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("percentage", (double) 0); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("percentage", (double) 2); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -293,15 +264,15 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNOutputDimensionTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check the neighbors matrix has 4 points for each input point. - REQUIRE(IO::GetParam>("neighbors").n_rows == 10); - REQUIRE(IO::GetParam>("neighbors").n_cols == 100); + REQUIRE(params.Get>("neighbors").n_rows == 10); + REQUIRE(params.Get>("neighbors").n_cols == 100); // Check the distances matrix has 4 points for each input point. - REQUIRE(IO::GetParam("distances").n_rows == 10); - REQUIRE(IO::GetParam("distances").n_cols == 100); + REQUIRE(params.Get("distances").n_rows == 10); + REQUIRE(params.Get("distances").n_cols == 100); } /** @@ -321,30 +292,30 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNModelReuseTest", SetInputParam("query", queryData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); - - // bindings::tests::CleanMemory(); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; + KFNModel* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); SetInputParam("query", queryData); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); } /* @@ -362,27 +333,25 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNDifferentEpsilonTest", SetInputParam("k", (int) 10); SetInputParam("epsilon", (double) 0.2); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("epsilon", (double) 0.8); - mlpackMain(); + RUN_BINDING(); CheckMatricesNotEqual(neighbors, - IO::GetParam>("neighbors")); + params.Get>("neighbors")); CheckMatricesNotEqual(distances, - IO::GetParam("distances")); + params.Get("distances")); } /* @@ -400,27 +369,25 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNDifferentPercentageTest", SetInputParam("k", (int) 10); SetInputParam("percentage", (double) 0.2); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["percentage"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("percentage", (double) 0.8); - mlpackMain(); + RUN_BINDING(); CheckMatricesNotEqual(neighbors, - IO::GetParam>("neighbors")); + params.Get>("neighbors")); CheckMatricesNotEqual(distances, - IO::GetParam("distances")); + params.Get("distances")); } /* @@ -436,28 +403,27 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNRandomBasisTest", // Random input, some k <= number of reference points. SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - IO::SetPassed("random_basis"); + SetInputParam("random_basis", true); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); - REQUIRE(IO::GetParam("output_model")->RandomBasis() == true); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); + REQUIRE(params.Get("output_model")->RandomBasis() == true); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["random_basis"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); - REQUIRE(IO::GetParam("output_model")->RandomBasis() == false); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); + REQUIRE(params.Get("output_model")->RandomBasis() == false); } /* @@ -474,22 +440,23 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNTrueNeighborDistanceTest", SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; SetInputParam("reference", referenceData); SetInputParam("true_neighbors", neighbors); SetInputParam("true_distances", distances); SetInputParam("epsilon", (double) 0.5); + SetInputParam("k", (int) 10); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); // True output matrices have incorrect shape. arma::Mat dummyNeighbors; @@ -497,19 +464,18 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNTrueNeighborDistanceTest", dummyNeighbors.randu(20, 100); dummyDistances.randu(20, 100); - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["true_neighbors"].wasPassed = false; - IO::GetSingleton().Parameters()["true_distances"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("true_neighbors", std::move(dummyNeighbors)); SetInputParam("true_distances", std::move(dummyDistances)); + SetInputParam("k", (int) 10); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -529,9 +495,6 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNAllAlgorithmsTest", arma::mat queryData; queryData.randu(3, 90); // 90 points in 3 dimensions. - // Keep some k <= number of reference points same over all. - SetInputParam("k", (int) 10); - arma::Mat neighborsCompare; arma::mat distancesCompare; @@ -545,31 +508,30 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNAllAlgorithmsTest", SetInputParam("reference", referenceData); SetInputParam("query", queryData); SetInputParam("algorithm", algorithms[i]); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); if (i == 0) { neighborsCompare = std::move - (IO::GetParam>("neighbors")); - distancesCompare = std::move(IO::GetParam("distances")); + (params.Get>("neighbors")); + distancesCompare = std::move(params.Get("distances")); } else { - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); CheckMatrices(neighborsCompare, neighbors); CheckMatrices(distancesCompare, distances); } - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; - IO::GetSingleton().Parameters()["algorithm"].wasPassed = false; + ResetSettings(); } } @@ -590,9 +552,6 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNAllTreeTypesTest", arma::mat queryData; queryData.randu(3, 90); // 90 points in 3 dimensions. - // Keep some k <= number of reference points same over all. - SetInputParam("k", (int) 10); - arma::Mat neighborsCompare; arma::mat distancesCompare; @@ -606,31 +565,30 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNAllTreeTypesTest", SetInputParam("reference", referenceData); SetInputParam("query", queryData); SetInputParam("tree_type", treetypes[i]); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); if (i == 0) { neighborsCompare = std::move( - IO::GetParam>("neighbors")); - distancesCompare = std::move(IO::GetParam("distances")); + params.Get>("neighbors")); + distancesCompare = std::move(params.Get("distances")); } else { - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); CheckMatrices(neighborsCompare, neighbors); CheckMatrices(distancesCompare, distances); } - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + ResetSettings(); } } @@ -648,23 +606,22 @@ TEST_CASE_METHOD(KFNTestFixture, "KFNDifferentLeafSizes", SetInputParam("k", (int) 10); SetInputParam("leaf_size", (int) 1); - mlpackMain(); + RUN_BINDING(); - REQUIRE(IO::GetParam("output_model")->LeafSize() == (int) 1); - - bindings::tests::CleanMemory(); + REQUIRE(params.Get("output_model")->LeafSize() == (int) 1); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); SetInputParam("leaf_size", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - REQUIRE(IO::GetParam("output_model")->LeafSize() == (int) 10); + REQUIRE(params.Get("output_model")->LeafSize() == (int) 10); } diff --git a/src/mlpack/tests/main_tests/kmeans_test.cpp b/src/mlpack/tests/main_tests/kmeans_test.cpp index f1d4b5882d..e62f0d6e1a 100644 --- a/src/mlpack/tests/main_tests/kmeans_test.cpp +++ b/src/mlpack/tests/main_tests/kmeans_test.cpp @@ -2,49 +2,26 @@ * @file tests/main_tests/kmeans_test.cpp * @author Prabhat Sharma * - * Test mlpackMain() of kmeans_main.cpp + * Test RUN_BINDING() of kmeans_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "Kmeans"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct KmTestFixture -{ - public: - KmTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~KmTestFixture() - { - // Clear the settings. - IO::ClearSettings(); - } -}; - -void ResetKmSettings() -{ - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(KmTestFixture); /** * Checking that number of Clusters are non negative @@ -60,7 +37,7 @@ TEST_CASE_METHOD(KmTestFixture, "NonNegativeClustersTest", SetInputParam("clusters", (int) -1); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -80,7 +57,7 @@ TEST_CASE_METHOD(KmTestFixture, "AutoDetectClusterTest", SetInputParam("clusters", (int) 0); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -103,7 +80,7 @@ TEST_CASE_METHOD(KmTestFixture, "RefinedStartPercentageTest", SetInputParam("percentage", std::move(P)); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -126,7 +103,7 @@ TEST_CASE_METHOD(KmTestFixture, "NonNegativePercentageTest", SetInputParam("percentage", P); // Invalid Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -148,12 +125,12 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringSizeCheck", SetInputParam("input", std::move(inputData)); SetInputParam("clusters", c); - mlpackMain(); + RUN_BINDING(); - REQUIRE(IO::GetParam("output").n_rows == row+1); - REQUIRE(IO::GetParam("output").n_cols == col); - REQUIRE(IO::GetParam("centroid").n_rows == row); - REQUIRE(IO::GetParam("centroid").n_cols == (arma::uword) c); + REQUIRE(params.Get("output").n_rows == row+1); + REQUIRE(params.Get("output").n_cols == col); + REQUIRE(params.Get("centroid").n_rows == row); + REQUIRE(params.Get("centroid").n_cols == (arma::uword) c); } /** @@ -174,12 +151,12 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringSizeCheckLabelOnly", SetInputParam("clusters", c); SetInputParam("labels_only", true); - mlpackMain(); + RUN_BINDING(); - REQUIRE(IO::GetParam("output").n_rows == 1); - REQUIRE(IO::GetParam("output").n_cols == col); - REQUIRE(IO::GetParam("centroid").n_rows == row); - REQUIRE(IO::GetParam("centroid").n_cols == (arma::uword) c); + REQUIRE(params.Get("output").n_rows == 1); + REQUIRE(params.Get("output").n_cols == col); + REQUIRE(params.Get("centroid").n_rows == row); + REQUIRE(params.Get("centroid").n_cols == (arma::uword) c); } @@ -203,12 +180,13 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringEmptyClustersCheck", SetInputParam("max_iterations", iterations); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat normalOutput; - normalOutput = std::move(IO::GetParam("centroid")); + normalOutput = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("clusters", c); @@ -217,12 +195,13 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringEmptyClustersCheck", SetInputParam("max_iterations", iterations); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat allowEmptyOutput; - allowEmptyOutput = std::move(IO::GetParam("centroid")); + allowEmptyOutput = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); SetInputParam("input", inputData); SetInputParam("clusters", c); @@ -231,12 +210,13 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringEmptyClustersCheck", SetInputParam("max_iterations", iterations); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat killEmptyOutput; - killEmptyOutput = std::move(IO::GetParam("centroid")); + killEmptyOutput = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); if (killEmptyOutput.n_elem == allowEmptyOutput.n_elem) { @@ -266,8 +246,8 @@ TEST_CASE_METHOD(KmTestFixture, "KmClusteringResultSizeCheck", SetInputParam("clusters", c); SetInputParam("in_place", true); - mlpackMain(); - arma::mat processedInput = IO::GetParam("output"); + RUN_BINDING(); + arma::mat processedInput = params.Get("output"); // here input is actually accessed through output // due to a little trick in kmeans_main @@ -288,7 +268,7 @@ TEST_CASE_METHOD(KmTestFixture, "KmClustersNotDefined", SetInputParam("input", std::move(inputData)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -314,14 +294,15 @@ TEST_CASE_METHOD(KmTestFixture, "AlgorithmsSimilarTest", SetInputParam("labels_only", true); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat naiveOutput; arma::mat naiveCentroid; - naiveOutput = std::move(IO::GetParam("output")); - naiveCentroid = std::move(IO::GetParam("centroid")); + naiveOutput = std::move(params.Get("output")); + naiveCentroid = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); algo = "elkan"; @@ -331,14 +312,15 @@ TEST_CASE_METHOD(KmTestFixture, "AlgorithmsSimilarTest", SetInputParam("labels_only", true); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat elkanOutput; arma::mat elkanCentroid; - elkanOutput = std::move(IO::GetParam("output")); - elkanCentroid = std::move(IO::GetParam("centroid")); + elkanOutput = std::move(params.Get("output")); + elkanCentroid = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); algo = "hamerly"; @@ -348,14 +330,15 @@ TEST_CASE_METHOD(KmTestFixture, "AlgorithmsSimilarTest", SetInputParam("labels_only", true); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat hamerlyOutput; arma::mat hamerlyCentroid; - hamerlyOutput = std::move(IO::GetParam("output")); - hamerlyCentroid = std::move(IO::GetParam("centroid")); + hamerlyOutput = std::move(params.Get("output")); + hamerlyCentroid = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); algo = "dualtree"; @@ -365,14 +348,15 @@ TEST_CASE_METHOD(KmTestFixture, "AlgorithmsSimilarTest", SetInputParam("labels_only", true); SetInputParam("initial_centroids", initCentroid); - mlpackMain(); + RUN_BINDING(); arma::mat dualTreeOutput; arma::mat dualTreeCentroid; - dualTreeOutput = std::move(IO::GetParam("output")); - dualTreeCentroid = std::move(IO::GetParam("centroid")); + dualTreeOutput = std::move(params.Get("output")); + dualTreeCentroid = std::move(params.Get("centroid")); - ResetKmSettings(); + CleanMemory(); + ResetSettings(); algo = "dualtree-covertree"; @@ -382,12 +366,12 @@ TEST_CASE_METHOD(KmTestFixture, "AlgorithmsSimilarTest", SetInputParam("labels_only", true); SetInputParam("initial_centroids", std::move(initCentroid)); - mlpackMain(); + RUN_BINDING(); arma::mat dualCoverTreeOutput; arma::mat dualCoverTreeCentroid; - dualCoverTreeOutput = std::move(IO::GetParam("output")); - dualCoverTreeCentroid = std::move(IO::GetParam("centroid")); + dualCoverTreeOutput = std::move(params.Get("output")); + dualCoverTreeCentroid = std::move(params.Get("centroid")); // Checking all the algorithms return same assignments CheckMatrices(naiveOutput, hamerlyOutput); diff --git a/src/mlpack/tests/main_tests/knn_test.cpp b/src/mlpack/tests/main_tests/knn_test.cpp index f6096b2d80..e91381f62d 100644 --- a/src/mlpack/tests/main_tests/knn_test.cpp +++ b/src/mlpack/tests/main_tests/knn_test.cpp @@ -3,44 +3,26 @@ * @author Atharva Khandait * @author Heet Sankesara * - * Test mlpackMain() of knn_main.cpp. + * Test RUN_BINDING() of knn_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "K-NearestNeighborsSearch"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct KNNTestFixture -{ - public: - KNNTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~KNNTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(KNNTestFixture); /* * Check that we can't provide reference and query matrices @@ -64,7 +46,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNEqualDimensionTest", SetInputParam("k", (int) 10); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -83,15 +65,15 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidKTest", SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) -1); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -114,7 +96,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidKQueryDataTest", SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -132,7 +114,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNLeafSizeTest", SetInputParam("leaf_size", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -149,14 +131,14 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNRefModelTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Input pre-trained model. SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + std::move(params.Get("output_model"))); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -175,7 +157,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidTreeTypeTest", SetInputParam("tree_type", (string) "min-rp"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -194,7 +176,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidAlgoTest", SetInputParam("algorithm", (string) "triple_tree"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -213,7 +195,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidEpsilonTest", SetInputParam("epsilon", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -232,7 +214,7 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidTauTest", SetInputParam("tau", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -253,16 +235,16 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidRhoTest", SetInputParam("rho", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["rho"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("rho", (double) 1.5); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -280,15 +262,15 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNOutputDimensionTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check the neighbors matrix has 10 points for each input point. - REQUIRE(IO::GetParam>("neighbors").n_rows == 10); - REQUIRE(IO::GetParam>("neighbors").n_cols == 100); + REQUIRE(params.Get>("neighbors").n_rows == 10); + REQUIRE(params.Get>("neighbors").n_cols == 100); // Check the distances matrix has 10 points for each input point. - REQUIRE(IO::GetParam("distances").n_rows == 10); - REQUIRE(IO::GetParam("distances").n_cols == 100); + REQUIRE(params.Get("distances").n_rows == 10); + REQUIRE(params.Get("distances").n_cols == 100); } /** @@ -308,29 +290,31 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNModelReuseTest", SetInputParam("query", queryData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; KNNModel* output_model; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); - output_model = std::move(IO::GetParam("output_model")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); + output_model = std::move(params.Get("output_model")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("input_model", output_model); SetInputParam("query", queryData); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); } /* @@ -350,27 +334,25 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentTauTest", SetInputParam("tau", (double) 0.2); SetInputParam("algorithm", (string) "greedy"); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["tau"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("tau", (double) 0.8); - mlpackMain(); + RUN_BINDING(); CheckMatricesNotEqual(neighbors, - IO::GetParam>("neighbors")); + params.Get>("neighbors")); CheckMatricesNotEqual(distances, - IO::GetParam("distances")); + params.Get("distances")); } /* @@ -391,27 +373,25 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentRhoTest", SetInputParam("rho", (double) 0.01); SetInputParam("algorithm", (string) "greedy"); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["rho"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("rho", (double) 0.99); - mlpackMain(); + RUN_BINDING(); CheckMatricesNotEqual(neighbors, - IO::GetParam>("neighbors")); + params.Get>("neighbors")); CheckMatricesNotEqual(distances, - IO::GetParam("distances")); + params.Get("distances")); } /* @@ -429,27 +409,25 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentEpsilonTest", SetInputParam("k", (int) 10); SetInputParam("epsilon", (double) 0.2); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("epsilon", (double) 0.8); - mlpackMain(); + RUN_BINDING(); CheckMatricesNotEqual(neighbors, - IO::GetParam>("neighbors")); + params.Get>("neighbors")); CheckMatricesNotEqual(distances, - IO::GetParam("distances")); + params.Get("distances")); } /* @@ -466,28 +444,28 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNRandomBasisTest", SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); SetInputParam("algorithm", (string) "dual_tree"); - IO::SetPassed("random_basis"); + SetInputParam("random_basis", true); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); - REQUIRE(IO::GetParam("output_model")->RandomBasis() == true); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); + REQUIRE(params.Get("output_model")->RandomBasis() == true); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["random_basis"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); + SetInputParam("k", (int) 10); + SetInputParam("algorithm", (string) "dual_tree"); - mlpackMain(); + RUN_BINDING(); - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); - REQUIRE(IO::GetParam("output_model")->RandomBasis() == false); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); + REQUIRE(params.Get("output_model")->RandomBasis() == false); } /* @@ -504,23 +482,23 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNTrueNeighborDistanceTest", SetInputParam("reference", referenceData); SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); - bindings::tests::CleanMemory(); - - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", referenceData); SetInputParam("true_neighbors", neighbors); SetInputParam("true_distances", distances); SetInputParam("epsilon", (double) 0.5); + SetInputParam("k", (int) 10); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); // True output matrices have incorrect shape. arma::Mat dummyNeighbors; @@ -528,16 +506,17 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNTrueNeighborDistanceTest", dummyNeighbors.randu(100, 20); dummyDistances.randu(100, 20); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["true_neighbors"].wasPassed = false; - IO::GetSingleton().Parameters()["true_distances"].wasPassed = false; + CleanMemory(); + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("true_neighbors", std::move(dummyNeighbors)); SetInputParam("true_distances", std::move(dummyDistances)); + SetInputParam("epsilon", (double) 0.5); + SetInputParam("k", (int) 10); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -557,9 +536,6 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNAllAlgorithmsTest", arma::mat queryData; queryData.randu(3, 90); // 90 points in 3 dimensions. - // Keep some k <= number of reference points same over all. - SetInputParam("k", (int) 10); - arma::Mat neighborsCompare; arma::mat distancesCompare; @@ -573,31 +549,30 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNAllAlgorithmsTest", SetInputParam("reference", referenceData); SetInputParam("query", queryData); SetInputParam("algorithm", algorithms[i]); + SetInputParam("k", (int) 10); - mlpackMain(); + RUN_BINDING(); if (i == 0) { neighborsCompare = std::move( - IO::GetParam>("neighbors")); - distancesCompare = std::move(IO::GetParam("distances")); + params.Get>("neighbors")); + distancesCompare = std::move(params.Get("distances")); } else { - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); CheckMatrices(neighborsCompare, neighbors); CheckMatrices(distancesCompare, distances); } - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; - IO::GetSingleton().Parameters()["algorithm"].wasPassed = false; + ResetSettings(); } } @@ -619,9 +594,6 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNAllTreeTypesTest", arma::mat queryData; queryData.randu(3, 90); // 90 points in 3 dimensions. - // Keep some k <= number of reference points same over all. - SetInputParam("k", (int) 15); - arma::Mat neighborsCompare; arma::mat distancesCompare; @@ -635,31 +607,30 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNAllTreeTypesTest", SetInputParam("reference", referenceData); SetInputParam("query", queryData); SetInputParam("tree_type", treetypes[i]); + SetInputParam("k", (int) 15); - mlpackMain(); + RUN_BINDING(); if (i == 0) { neighborsCompare = std::move( - IO::GetParam>("neighbors")); - distancesCompare = std::move(IO::GetParam("distances")); + params.Get>("neighbors")); + distancesCompare = std::move(params.Get("distances")); } else { - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); CheckMatrices(neighborsCompare, neighbors); CheckMatrices(distancesCompare, distances); } - delete IO::GetParam("output_model"); - IO::GetParam("output_model") = NULL; + delete params.Get("output_model"); + params.Get("output_model") = NULL; // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; - IO::GetSingleton().Parameters()["tree_type"].wasPassed = false; + ResetSettings(); } } @@ -677,24 +648,24 @@ TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentLeafSizes", SetInputParam("k", (int) 10); SetInputParam("leaf_size", (int) 1); - mlpackMain(); + RUN_BINDING(); KNNModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 10); SetInputParam("leaf_size", (int) 10); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. REQUIRE(output_model->LeafSize() == (int) 1); - REQUIRE(IO::GetParam("output_model")->LeafSize() == (int) 10); + REQUIRE(params.Get("output_model")->LeafSize() == (int) 10); delete output_model; } diff --git a/src/mlpack/tests/main_tests/krann_test.cpp b/src/mlpack/tests/main_tests/krann_test.cpp index 57cb0905d6..379a68b820 100644 --- a/src/mlpack/tests/main_tests/krann_test.cpp +++ b/src/mlpack/tests/main_tests/krann_test.cpp @@ -3,41 +3,26 @@ * @author Ryan Curtin * @author Utkarsh Rai * - * Test mlpackMain() of krann_main.cpp. + * Test RUN_BINDING() of krann_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "K-RankApproximateNearestNeighborsSearch"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct KRANNTestFixture -{ - KRANNTestFixture() - { - IO::RestoreSettings(testName); - } - - ~KRANNTestFixture() - { - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(KRANNTestFixture); /* * Check that we can't provide reference and query matrices @@ -61,7 +46,7 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNEqualDimensionTest", SetInputParam("k", (int) 5); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -80,32 +65,29 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNInvalidKTest", SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); SetInputParam("reference", referenceData); SetInputParam("k", (int) -1); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 6); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); // Test on empty reference matrix since referenceData has been moved. SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 5); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -128,32 +110,29 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNInvalidKQueryDataTest", SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); SetInputParam("reference", referenceData); SetInputParam("k", (int) -1); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 6); // Invalid. - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["k"].wasPassed = false; + ResetSettings(); // Test on empty reference marix since referenceData has been moved. SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 5); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -171,7 +150,7 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNLeafSizeTest", SetInputParam("leaf_size", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -188,14 +167,14 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNRefModelTest", SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) 5); - mlpackMain(); + RUN_BINDING(); // Input pre-trained model. SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + std::move(params.Get("output_model"))); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -214,7 +193,7 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNInvalidTreeTypeTest", SetInputParam("tree_type", (string) "min-rp"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -233,7 +212,7 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNInvalidTauTest", SetInputParam("tau", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -252,15 +231,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNOutputDimensionTest", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check the neighbors matrix has 5 points for each input point. - REQUIRE(IO::GetParam>("neighbors").n_rows == 5); - REQUIRE(IO::GetParam>("neighbors").n_cols == 100); + REQUIRE(params.Get>("neighbors").n_rows == 5); + REQUIRE(params.Get>("neighbors").n_cols == 100); // Check the distances matrix has 10 points for each input point. - REQUIRE(IO::GetParam("distances").n_rows == 5); - REQUIRE(IO::GetParam("distances").n_cols == 100); + REQUIRE(params.Get("distances").n_rows == 5); + REQUIRE(params.Get("distances").n_cols == 100); } /** @@ -281,30 +260,32 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNModelReuseTest", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); arma::Mat neighbors; arma::mat distances; RAModel* output_model; - neighbors = std::move(IO::GetParam>("neighbors")); - distances = std::move(IO::GetParam("distances")); - output_model = std::move(IO::GetParam("output_model")); + neighbors = std::move(params.Get>("neighbors")); + distances = std::move(params.Get("distances")); + output_model = std::move(params.Get("output_model")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["query"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("input_model", output_model); SetInputParam("query", queryData); + SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); } /** @@ -322,13 +303,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentLeafSizes", SetInputParam("leaf_size", (int) 1); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); RAModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("reference", std::move(referenceData)); @@ -336,12 +319,12 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentLeafSizes", SetInputParam("leaf_size", (int) 10); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. CHECK(output_model->LeafSize() == (int) 1); - CHECK(IO::GetParam("output_model")->LeafSize() == (int) 10); + CHECK(params.Get("output_model")->LeafSize() == (int) 10); delete output_model; } @@ -359,13 +342,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentTau", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); RAModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset the passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Changing value of tau and keeping everything else unchanged. SetInputParam("reference", std::move(referenceData)); @@ -373,12 +358,12 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentTau", SetInputParam("tau", (double) 10); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal CHECK(output_model->Tau() == (double) 5); - CHECK(IO::GetParam("output_model")->Tau() == + CHECK(params.Get("output_model")->Tau() == (double) 10); delete output_model; } @@ -397,13 +382,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentAlpha", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); RAModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset the passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Changing value of tau and keeping everything else unchanged. SetInputParam("reference", std::move(referenceData)); @@ -411,12 +398,12 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentAlpha", SetInputParam("alpha", (double) 0.80); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal CHECK(output_model->Alpha() == (double) 0.95); - CHECK(IO::GetParam("output_model")->Alpha() == + CHECK(params.Get("output_model")->Alpha() == (double) 0.80); delete output_model; } @@ -435,13 +422,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentTreeType", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); RAModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset the passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Changing value of tau and keeping everything else unchanged. SetInputParam("reference", std::move(referenceData)); @@ -449,13 +438,13 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentTreeType", SetInputParam("tree_type", (string) "ub"); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal const bool check = output_model->TreeType() == 0; CHECK(check == true); - CHECK(IO::GetParam("output_model")->TreeType() == + CHECK(params.Get("output_model")->TreeType() == 8); delete output_model; } @@ -474,13 +463,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentSingleSampleLimit", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); RAModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("reference", std::move(referenceData)); @@ -488,11 +479,11 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentSingleSampleLimit", SetInputParam("single_sample_limit", (int)15); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CHECK(IO::GetParam("output_model")->SingleSampleLimit() == + CHECK(params.Get("output_model")->SingleSampleLimit() == (int) 15); CHECK(output_model->SingleSampleLimit() == (int) 20); delete output_model; @@ -512,13 +503,15 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentSampleAtLeaves", SetInputParam("k", (int) 5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); RAModel* output_model; - output_model = std::move(IO::GetParam("output_model")); + output_model = std::move(params.Get("output_model")); // Reset passed parameters. - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input saved model, pass the same query and keep k unchanged. SetInputParam("reference", std::move(referenceData)); @@ -526,11 +519,11 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNDifferentSampleAtLeaves", SetInputParam("sample_at_leaves", (bool) true); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output matrices and the output matrices using // saved model are equal. - CHECK(IO::GetParam("output_model")->SampleAtLeaves() == + CHECK(params.Get("output_model")->SampleAtLeaves() == (bool) true); CHECK(output_model->SampleAtLeaves() == (bool) false); delete output_model; @@ -550,14 +543,13 @@ TEST_CASE_METHOD(KRANNTestFixture, "KRANNInvalidAlphaTest", SetInputParam("alpha", (double) 1.2); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - IO::GetSingleton().Parameters()["alpha"].wasPassed = false; + ResetSettings(); SetInputParam("reference", std::move(referenceData)); SetInputParam("alpha", (double) -1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } From 5a321c6a77f99df79aab6d9f94c285c5f609cf6a Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Sat, 10 Jul 2021 23:48:53 +0530 Subject: [PATCH 531/729] Update bicubic_interpolation.hpp --- src/mlpack/methods/ann/layer/bicubic_interpolation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp index e48286f0d3..21b4402e02 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp @@ -55,7 +55,7 @@ class BicubicInterpolation const size_t outRowSize, const size_t outColSize, const size_t depth, - const double alpha); + const double alpha = -0.75); /** * Forward pass through the layer. The layer interpolates From b04da87bf42bcb27c2106b055f6bd67e6dd33dff Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Sat, 10 Jul 2021 15:32:40 -0400 Subject: [PATCH 532/729] Convert the rest of the main tests. --- src/mlpack/tests/CMakeLists.txt | 42 +-- .../tests/main_tests/linear_svm_test.cpp | 209 ++++++------ src/mlpack/tests/main_tests/lmnn_test.cpp | 301 ++++++++---------- .../local_coordinate_coding_test.cpp | 121 ++++--- .../main_tests/logistic_regression_test.cpp | 185 +++++------ src/mlpack/tests/main_tests/lsh_test.cpp | 171 +++++----- .../tests/main_tests/mean_shift_test.cpp | 79 ++--- src/mlpack/tests/main_tests/nbc_test.cpp | 155 ++++----- src/mlpack/tests/main_tests/nca_test.cpp | 146 ++++----- src/mlpack/tests/main_tests/nmf_test.cpp | 106 +++--- src/mlpack/tests/main_tests/pca_test.cpp | 45 +-- .../tests/main_tests/perceptron_test.cpp | 115 +++---- .../main_tests/preprocess_binarize_test.cpp | 42 +-- .../main_tests/preprocess_imputer_test.cpp | 56 ++-- .../preprocess_one_hot_encode_test.cpp | 42 +-- .../main_tests/preprocess_scale_test.cpp | 191 ++++++----- .../main_tests/preprocess_split_test.cpp | 112 +++---- src/mlpack/tests/main_tests/radical_test.cpp | 97 +++--- .../tests/main_tests/random_forest_test.cpp | 156 +++++---- .../tests/main_tests/range_search_test.cpp | 111 +++---- .../main_tests/softmax_regression_test.cpp | 112 +++---- .../tests/main_tests/sparse_coding_test.cpp | 211 ++++++------ 22 files changed, 1216 insertions(+), 1589 deletions(-) diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index f161ca689c..b86ec11328 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -154,27 +154,27 @@ add_executable(mlpack_test main_tests/knn_test.cpp main_tests/krann_test.cpp main_tests/linear_regression_test.cpp -# main_tests/lmnn_test.cpp -# main_tests/linear_svm_test.cpp -# 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/nca_test.cpp -# main_tests/nmf_test.cpp -# main_tests/pca_test.cpp -# main_tests/perceptron_test.cpp -# main_tests/preprocess_binarize_test.cpp -# main_tests/preprocess_imputer_test.cpp -# main_tests/preprocess_one_hot_encode_test.cpp -# main_tests/preprocess_scale_test.cpp -# main_tests/preprocess_split_test.cpp -# main_tests/radical_test.cpp -# main_tests/random_forest_test.cpp -# main_tests/softmax_regression_test.cpp -# main_tests/sparse_coding_test.cpp -# main_tests/range_search_test.cpp + main_tests/linear_svm_test.cpp + main_tests/lmnn_test.cpp + 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/nca_test.cpp + main_tests/nmf_test.cpp + main_tests/pca_test.cpp + main_tests/perceptron_test.cpp + main_tests/preprocess_binarize_test.cpp + main_tests/preprocess_imputer_test.cpp + main_tests/preprocess_one_hot_encode_test.cpp + main_tests/preprocess_scale_test.cpp + main_tests/preprocess_split_test.cpp + main_tests/radical_test.cpp + main_tests/random_forest_test.cpp + main_tests/range_search_test.cpp + main_tests/softmax_regression_test.cpp + main_tests/sparse_coding_test.cpp main_tests/main_test_fixture.hpp ) diff --git a/src/mlpack/tests/main_tests/linear_svm_test.cpp b/src/mlpack/tests/main_tests/linear_svm_test.cpp index 18a3d2f098..e62680967c 100644 --- a/src/mlpack/tests/main_tests/linear_svm_test.cpp +++ b/src/mlpack/tests/main_tests/linear_svm_test.cpp @@ -2,45 +2,27 @@ * @file tests/main_tests/linear_svm_test.cpp * @author Yashwant Singh Parihar * - * Test mlpackMain() of logistic_regression_main.cpp + * Test RUN_BINDING() 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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "LinearSVM"; - #include -#include #include -#include "test_helper.hpp" +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct LinearSVMTestFixture -{ - public: - LinearSVMTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~LinearSVMTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(LinearSVMTestFixture); /** * Ensure that trainingSet are necessarily passed when training. @@ -56,7 +38,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNoTrainingData", // Training data is not provided. Should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -85,11 +67,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMOutputDimensionTest", SetInputParam("test", std::move(testData)); // Training the model. - mlpackMain(); + RUN_BINDING(); // Get the output predictions of the test data. const arma::Row& testLabels = - IO::GetParam>("predictions"); + params.Get>("predictions"); // Output predictions size must match the test data set size. REQUIRE(testLabels.n_rows == 1); @@ -115,7 +97,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMCheckLabelsSizeTest", // Labels with incorrect size. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -134,16 +116,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMLabelsRepresentationTest", // The first solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the output. const arma::Row testLabels1 = - std::move(IO::GetParam>("predictions")); + std::move(params.Get>("predictions")); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Now train by providing labels as extra parameter. arma::mat trainData2({{1.0, 2.0, 3.0}, {1.0, 4.0, 9.0}}); @@ -155,11 +136,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMLabelsRepresentationTest", // The second solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // get the output const arma::Row& testLabels2 = - IO::GetParam>("predictions"); + params.Get>("predictions"); // Both solutions should be equal. CheckMatrices(testLabels1, testLabels2); @@ -188,29 +169,27 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMModelReuseTest", SetInputParam("test", testData); // First solution - mlpackMain(); + RUN_BINDING(); // Get the output model obtained from training. LinearSVMModel* model = - IO::GetParam("output_model"); + params.Get("output_model"); // Get the output. const arma::Row& testLabels1 = - std::move(IO::GetParam>("predictions")); + std::move(params.Get>("predictions")); // Reset the data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + ResetSettings(); SetInputParam("input_model", model); SetInputParam("test", std::move(testData)); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the output. const arma::Row& testLabels2 = - IO::GetParam>("predictions"); + params.Get>("predictions"); // Both solutions should be equal. CheckMatrices(testLabels1, testLabels2); @@ -237,7 +216,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMCheckDimOfTestData", // Dimensionality of test data is wrong. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -260,22 +239,21 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMCheckDimOfTestData2", SetInputParam("training", std::move(trainData)); // Training the model. - mlpackMain(); + RUN_BINDING(); // Get the output model obtained from training. LinearSVMModel* model = - IO::GetParam("output_model"); + params.Get("output_model"); // Reset the data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; + ResetSettings(); SetInputParam("input_model", model); SetInputParam("test", std::move(testData)); // Test data dimensionality is wrong. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -299,7 +277,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNonNegativeMaxIterationTest", // Maximum iterations is negative. It should a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -323,7 +301,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNonNegativeLambdaTest", // Lambda is negative. It should a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -348,7 +326,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, // Number of classes is negative. It should a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -372,7 +350,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNonNegativeToleranceTest", // Tolerance is negative. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -396,7 +374,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNonNegativeDeltaTest", // Delta is negative. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -420,7 +398,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNonNegativeEpochsTest", // Epochs is negative. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -444,7 +422,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMZeroNumberOfClassesTest", // Number of classes for optimizer is only one. // It should throw a invalid_argument error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::invalid_argument); + REQUIRE_THROWS_AS(RUN_BINDING(), std::invalid_argument); Log::Fatal.ignoreInput = false; } @@ -467,7 +445,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMOptimizerTest", SetInputParam("optimizer", std::string("hello")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -491,16 +469,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffMaxIterationsTest", // First solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -508,11 +485,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffMaxIterationsTest", // Second solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -538,16 +515,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffLambdaTest", // First solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -555,11 +531,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffLambdaTest", // Second solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -585,16 +561,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffDeltaTest", // First solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -602,11 +577,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffDeltaTest", // Second solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -631,16 +606,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffInterceptTest", // First solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -648,11 +622,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffInterceptTest", // Second solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -683,16 +657,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffInterceptTestWithPsgd", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -705,11 +678,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffInterceptTestWithPsgd", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -736,7 +709,7 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMNonNegativeStepSizeTest", // Step size for optimizer is negative. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -765,16 +738,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffEpochsTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -787,11 +759,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffEpochsTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -823,16 +795,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffStepSizeTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -846,11 +817,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffStepSizeTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -882,16 +853,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffToleranceTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -905,11 +875,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffToleranceTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); @@ -935,16 +905,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffOptimizerTest", // First solution. mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::mat parameters1 = std::move( - IO::GetParam("output_model")->svm.Parameters()); + params.Get("output_model")->svm.Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainData)); SetInputParam("labels", std::move(trainLabels)); @@ -956,11 +925,11 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMDiffOptimizerTest", #endif mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. const arma::mat& parameters2 = - IO::GetParam("output_model")->svm.Parameters(); + params.Get("output_model")->svm.Parameters(); // Both solutions should be not equal. CheckMatricesNotEqual(parameters1, parameters2); diff --git a/src/mlpack/tests/main_tests/lmnn_test.cpp b/src/mlpack/tests/main_tests/lmnn_test.cpp index 3c2118b4b9..06274aeec1 100644 --- a/src/mlpack/tests/main_tests/lmnn_test.cpp +++ b/src/mlpack/tests/main_tests/lmnn_test.cpp @@ -2,47 +2,28 @@ * @file tests/main_tests/lmnn_test.cpp * @author Manish Kumar * - * Test mlpackMain() of lmnn_main.cpp. + * Test RUN_BINDING() of lmnn_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. */ - -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "LMNN"; #include #include #include - -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct LMNNTestFixture -{ - public: - LMNNTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~LMNNTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(LMNNTestFixture); /** * Ensure that, when labels are implicitily given with input, @@ -59,21 +40,20 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNExplicitImplicitLabelsTest", SetInputParam("input", inputData); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows - 1); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows - 1); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows - 1); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); // Reset Settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Now check that when labels are explicitely given, the last column // of input is not treated as labels. @@ -87,16 +67,16 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNExplicitImplicitLabelsTest", SetInputParam("input", inputData); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); } @@ -122,58 +102,56 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNOptimizerTest", // when that is fixed. SetInputParam("optimizer", std::string("amsgrad")); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); // Reset rettings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Input random data points. SetInputParam("input", inputData); SetInputParam("labels", labels); SetInputParam("optimizer", std::string("sgd")); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); - // Reset rettings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + // Reset settings. + ResetSettings(); // Input random data points. SetInputParam("input", inputData); SetInputParam("labels", std::move(labels)); SetInputParam("optimizer", std::string("lbfgs")); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); } @@ -201,16 +179,16 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNValidDistanceTest", SetInputParam("labels", std::move(labels)); SetInputParam("distance", std::move(distance)); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows - 1); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows - 1); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); } @@ -238,16 +216,16 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNValidDistanceTest2", SetInputParam("labels", std::move(labels)); SetInputParam("distance", std::move(distance)); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); } @@ -275,16 +253,16 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNInvalidDistanceTest", SetInputParam("labels", std::move(labels)); SetInputParam("distance", std::move(distance)); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("output").n_cols == + REQUIRE(params.Get("output").n_cols == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_rows == + REQUIRE(params.Get("transformed_data").n_rows == inputData.n_rows); - REQUIRE(IO::GetParam("transformed_data").n_cols == + REQUIRE(params.Get("transformed_data").n_cols == inputData.n_cols); } @@ -306,7 +284,7 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNNumTargetsTest", // Check that an error is thrown. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -331,14 +309,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffNormalizationTest", SetInputParam("linear_scan", true); SetInputParam("tolerance", 0.01); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); - // Reset rettings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + // Reset settings. + ResetSettings(); // Use the same input but set normalize to false. SetInputParam("input", std::move(inputData)); @@ -347,11 +324,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffNormalizationTest", SetInputParam("linear_scan", true); SetInputParam("tolerance", 0.01); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -375,14 +352,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffStepSizeTest", SetInputParam("step_size", (double) 0.01); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set parameters using the same input but with a larger step_size. SetInputParam("input", std::move(inputData)); @@ -390,12 +366,12 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffStepSizeTest", SetInputParam("step_size", (double) 20.5); SetInputParam("linear_scan", (bool) true); - mlpackMain(); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + RUN_BINDING(); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -418,25 +394,24 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffToleranceTest", SetInputParam("tolerance", (double) 1e-6); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set parameters using the same input but with a larger tolerance. SetInputParam("input", std::move(inputData)); SetInputParam("tolerance", (double) 0.3); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -460,14 +435,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffBatchSizeTest", SetInputParam("batch_size", (int) 20); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set parameters using the same input but with a larger batch_size. SetInputParam("input", std::move(inputData)); @@ -475,11 +449,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffBatchSizeTest", SetInputParam("batch_size", (int) 30); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -504,14 +478,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffNumTargetsTest", SetInputParam("k", 1); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set different parameters. SetInputParam("input", std::move(inputData)); @@ -519,11 +492,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffNumTargetsTest", SetInputParam("k", 5); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -548,14 +521,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffRegularizationTest", SetInputParam("linear_scan", (bool) true); SetInputParam("regularization", 1.0); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set different parameters. SetInputParam("input", std::move(inputData)); @@ -563,11 +535,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffRegularizationTest", SetInputParam("linear_scan", (bool) true); SetInputParam("regularization", 0.1); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -591,14 +563,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffRangeTest", SetInputParam("labels", labels); SetInputParam("linear_scan", (bool) true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set different parameters. SetInputParam("input", std::move(inputData)); @@ -606,11 +577,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffRangeTest", SetInputParam("linear_scan", (bool) true); SetInputParam("range", 100); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -637,14 +608,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffMaxIterationTest", SetInputParam("k", 5); SetInputParam("max_iterations", (int) 2); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set parameters using the same input but with a larger max_iterations. SetInputParam("input", std::move(inputData)); @@ -654,11 +624,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffMaxIterationTest", SetInputParam("k", 5); SetInputParam("max_iterations", (int) 500); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -683,14 +653,13 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffPassesTest", SetInputParam("linear_scan", (bool) true); SetInputParam("passes", (int) 2); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); - arma::mat transformedData = IO::GetParam("transformed_data"); + arma::mat output = params.Get("output"); + arma::mat transformedData = params.Get("transformed_data"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Set parameters using the same input but with a larger passes. SetInputParam("input", std::move(inputData)); @@ -698,11 +667,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNDiffPassesTest", SetInputParam("linear_scan", (bool) true); SetInputParam("passes", (int) 6); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); - REQUIRE(arma::accu(IO::GetParam("transformed_data") != + REQUIRE(arma::accu(params.Get("output") != output) > 0); + REQUIRE(arma::accu(params.Get("transformed_data") != transformedData) > 0); } @@ -730,12 +699,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("k", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for range value. @@ -745,12 +713,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("range", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for batch size value. @@ -760,12 +727,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("batch_size", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for regularization value. @@ -775,12 +741,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("regularization", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for step size value. @@ -790,12 +755,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("step_size", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for max iterations value. @@ -805,12 +769,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("max_iterations", (int) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for passes value. @@ -820,12 +783,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("passes", (int) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for max iterations value. @@ -835,12 +797,11 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("rank", (int) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + ResetSettings(); // Test for tolerance value. @@ -850,6 +811,6 @@ TEST_CASE_METHOD(LMNNTestFixture, "LMNNBoundsTest", SetInputParam("tolerance", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp b/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp index 31b24013db..23c3cd0635 100644 --- a/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp +++ b/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp @@ -2,44 +2,27 @@ * @file tests/main_tests/local_coordinate_coding_test.cpp * @author Bhavya Bahl * - * Test mlpackMain() of local_coordinate_coding_main.cpp. + * Test RUN_BINDING() of local_coordinate_coding_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "LocalCoordinateCoding"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct LCCTestFixture -{ - public: - LCCTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~LCCTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(LCCTestFixture); /** * Ensure that the dimensions of encoded test points @@ -59,13 +42,13 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCDimensionsTest", SetInputParam("atoms", atoms); SetInputParam("max_iterations", (int) 2); - mlpackMain(); + RUN_BINDING(); // Check that the output has correct dimensions. - REQUIRE(IO::GetParam("codes").n_rows == (arma::uword) atoms); - REQUIRE(IO::GetParam("codes").n_cols == (arma::uword) cols); - REQUIRE(IO::GetParam("dictionary").n_rows == (arma::uword) rows); - REQUIRE(IO::GetParam("dictionary").n_cols == (arma::uword) atoms); + REQUIRE(params.Get("codes").n_rows == (arma::uword) atoms); + REQUIRE(params.Get("codes").n_cols == (arma::uword) cols); + REQUIRE(params.Get("dictionary").n_rows == (arma::uword) rows); + REQUIRE(params.Get("dictionary").n_cols == (arma::uword) atoms); } /** @@ -83,25 +66,25 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCOutputModelTest", SetInputParam("atoms", (int) 10); SetInputParam("max_iterations", (int) 2); - mlpackMain(); + RUN_BINDING(); // Get the encoded output and dictionary after training. - arma::mat initCodes = std::move(IO::GetParam("codes")); - arma::mat initDict = std::move(IO::GetParam("dictionary")); + arma::mat initCodes = std::move(params.Get("codes")); + arma::mat initDict = std::move(params.Get("dictionary")); LocalCoordinateCoding* outputModel = - std::move(IO::GetParam("output_model")); + std::move(params.Get("output_model")); - IO::Parameters()["training"].wasPassed = false; + ResetSettings(); SetInputParam("input_model", std::move(outputModel)); SetInputParam("test", std::move(t)); - mlpackMain(); + RUN_BINDING(); // Compare the output after reusing the trained model // to the original matrices. - CheckMatrices(initCodes, IO::GetParam("codes")); - CheckMatrices(initDict, IO::GetParam("dictionary")); + CheckMatrices(initCodes, params.Get("codes")); + CheckMatrices(initDict, params.Get("dictionary")); } /** @@ -119,7 +102,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCInitDictTrainTest", SetInputParam("atoms", (int) 2); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -138,7 +121,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCInitDictAtomTest", SetInputParam("atoms", (int) 3); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -162,7 +145,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainAndTestDataDimTest", SetInputParam("test", std::move(t)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -179,16 +162,16 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainAndInputModelTest", SetInputParam("atoms", (int) 10); SetInputParam("max_iterations", (int) 2); - mlpackMain(); + RUN_BINDING(); LocalCoordinateCoding* outputModel = - std::move(IO::GetParam("output_model")); + std::move(params.Get("output_model")); // No need to input training data again. SetInputParam("input_model", std::move(outputModel)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -208,16 +191,16 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainedModelDimTest", SetInputParam("atoms", (int) 10); SetInputParam("max_iterations", (int) 2); - mlpackMain(); + RUN_BINDING(); LocalCoordinateCoding* outputModel = - std::move(IO::GetParam("output_model")); + std::move(params.Get("output_model")); SetInputParam("input_model", std::move(outputModel)); SetInputParam("test", std::move(t)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -233,10 +216,10 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCAtomsBoundTest", SetInputParam("atoms", (int) 5); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); SetInputParam("atoms", (int) -1); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -252,7 +235,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCNegativeLambdaTest", SetInputParam("lambda", -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -268,7 +251,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCNegativeToleranceTest", SetInputParam("tolerance", -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -291,11 +274,12 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCNormalizationTest", SetInputParam("max_iterations", 2); SetInputParam("test", t); - mlpackMain(); + RUN_BINDING(); - arma::mat codes = std::move(IO::GetParam("codes")); + arma::mat codes = std::move(params.Get("codes")); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(x)); SetInputParam("atoms", (int) 2); @@ -304,10 +288,10 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCNormalizationTest", SetInputParam("test", std::move(t)); SetInputParam("normalize", (bool) 1); - mlpackMain(); + RUN_BINDING(); double normDiff = - arma::norm(IO::GetParam("codes") - codes, "fro"); + arma::norm(params.Get("codes") - codes, "fro"); REQUIRE(normDiff > delta); } @@ -332,10 +316,11 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCMaxIterTest", SetInputParam("max_iterations", 2); SetInputParam("test", t); - mlpackMain(); - arma::mat codes = std::move(IO::GetParam("codes")); + RUN_BINDING(); + arma::mat codes = std::move(params.Get("codes")); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(x)); SetInputParam("atoms", (int) 2); @@ -343,10 +328,10 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCMaxIterTest", SetInputParam("max_iterations", (int) 4); SetInputParam("test", std::move(t)); - mlpackMain(); + RUN_BINDING(); double normDiff = - arma::norm(IO::GetParam("codes") - codes, "fro"); + arma::norm(params.Get("codes") - codes, "fro"); REQUIRE(normDiff > delta); } @@ -370,10 +355,11 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCToleranceTest", SetInputParam("test", t); SetInputParam("tolerance", (double) 0.01); - mlpackMain(); - arma::mat codes = std::move(IO::GetParam("codes")); + RUN_BINDING(); + arma::mat codes = std::move(params.Get("codes")); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(x)); SetInputParam("atoms", (int) 2); @@ -381,10 +367,10 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCToleranceTest", SetInputParam("test", std::move(t)); SetInputParam("tolerance", (double) 100.0); - mlpackMain(); + RUN_BINDING(); double normDiff = - arma::norm(IO::GetParam("codes") - codes, "fro"); + arma::norm(params.Get("codes") - codes, "fro"); REQUIRE(normDiff > delta); } @@ -408,10 +394,11 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCLambdaTest", SetInputParam("test", t); SetInputParam("lambda", (double) 0.0); - mlpackMain(); - arma::mat codes = std::move(IO::GetParam("codes")); + RUN_BINDING(); + arma::mat codes = std::move(params.Get("codes")); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(x)); SetInputParam("atoms", (int) 2); @@ -419,10 +406,10 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCLambdaTest", SetInputParam("test", std::move(t)); SetInputParam("lambda", (double) 1.0); - mlpackMain(); + RUN_BINDING(); double normDiff = - arma::norm(IO::GetParam("codes") - codes, "fro"); + arma::norm(params.Get("codes") - codes, "fro"); REQUIRE(normDiff > delta); } diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index 85ee5d5b32..6bf3a3c847 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -2,46 +2,27 @@ * @file logistic_regression_test.cpp * @author B Kartheek Reddy * - * Test mlpackMain() of logistic_regression_main.cpp + * Test RUN_BINDING() 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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "LogisticRegression"; - #include -#include #include -#include "test_helper.hpp" +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; - -struct LogisticRegressionTestFixture -{ - public: - LogisticRegressionTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~LogisticRegressionTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(LogisticRegressionTestFixture); /** * Ensuring that absence of training data is checked. @@ -58,7 +39,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, // Training data is not provided. Should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -78,7 +59,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, // Labels to the training data is not provided. It should throw // a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -103,11 +84,11 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", SetInputParam("test", std::move(testX)); // Training the model. - mlpackMain(); + RUN_BINDING(); // Get the output predictions of the test data. - const arma::Row &testY = - IO::GetParam>("predictions"); + const arma::Row& testY = + params.Get>("predictions"); // Output predictions size must match the test data set size. REQUIRE(testY.n_rows == 1); @@ -135,7 +116,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, // Labels with incorrect size. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -154,16 +135,15 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, SetInputParam("test", testX); // The first solution. - mlpackMain(); + RUN_BINDING(); // Get the output. const arma::Row testY1 = - std::move(IO::GetParam>("predictions")); + std::move(params.Get>("predictions")); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Now train by providing labels as extra parameter. arma::mat trainX2({{1.0, 2.0, 3.0}, {1.0, 4.0, 9.0}}); @@ -174,11 +154,11 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, SetInputParam("test", std::move(testX)); // The second solution. - mlpackMain(); + RUN_BINDING(); // get the output - const arma::Row &testY2 = - IO::GetParam>("predictions"); + const arma::Row& testY2 = + params.Get>("predictions"); // Both solutions should be equal. CheckMatrices(testY1, testY2); @@ -209,29 +189,27 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, SetInputParam("test", testX); // First solution - mlpackMain(); + RUN_BINDING(); // Get the output model obtained from training. LogisticRegression<>* model = - IO::GetParam*>("output_model"); + params.Get*>("output_model"); // Get the output. const arma::Row testY1 = - std::move(IO::GetParam>("predictions")); + std::move(params.Get>("predictions")); // Reset the data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + ResetSettings(); SetInputParam("input_model", model); SetInputParam("test", std::move(testX)); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the output. - const arma::Row &testY2 = - IO::GetParam>("predictions"); + const arma::Row& testY2 = + params.Get>("predictions"); // Both solutions must be equal. CheckMatrices(testY1, testY2); @@ -261,7 +239,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData", // Dimensionality of test data is wrong. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -284,15 +262,14 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", SetInputParam("labels", std::move(trainY)); // Training the model. - mlpackMain(); + RUN_BINDING(); // Get the output model obtained from training. LogisticRegression<>* model = - IO::GetParam*>("output_model"); + params.Get*>("output_model"); // Reset the data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; + ResetSettings(); // Test data with Wrong dimensionality. arma::mat testX = arma::randu(D - 1, M); @@ -301,7 +278,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", // Test data dimensionality is wrong. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -327,7 +304,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, // Training data contains more than two classes. It should throw // a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -353,7 +330,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, // Maximum iterations is negative. It should a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -379,7 +356,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", // Step size for optimizer is negative. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -404,7 +381,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", // Tolerance is negative. It should throw a runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -428,28 +405,27 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", SetInputParam("max_iterations", int(1)); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(IO::GetParam*>("output_model") + std::move(params.Get*>("output_model") ->Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); SetInputParam("max_iterations", int(100)); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - IO::GetParam*>("output_model")->Parameters(); + const arma::rowvec& parameters2 = + params.Get*>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal // which ensures Max Iteration changes the output model. @@ -481,28 +457,27 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", SetInputParam("lambda", double(0)); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(IO::GetParam*>("output_model") + std::move(params.Get*>("output_model") ->Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); SetInputParam("lambda", double(1000)); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - IO::GetParam*>("output_model")->Parameters(); + const arma::rowvec& parameters2 = + params.Get*>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal // which ensures lambda changes the output model. @@ -535,17 +510,16 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", SetInputParam("step_size", double(0.02)); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(IO::GetParam*>("output_model") + std::move(params.Get*>("output_model") ->Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -553,11 +527,11 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", SetInputParam("step_size", double(1.02)); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - IO::GetParam*>("output_model")->Parameters(); + const arma::rowvec& parameters2 = + params.Get*>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal // which ensures Step Size changes the output model. @@ -590,17 +564,15 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", SetInputParam("max_iterations", int(1000)); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after first training. - const arma::rowvec parameters1 = - std::move(IO::GetParam*>("output_model") - ->Parameters()); + const arma::rowvec parameters1 = std::move( + params.Get*>("output_model")->Parameters()); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -608,16 +580,16 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", SetInputParam("max_iterations", int(1000)); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - IO::GetParam*>("output_model")->Parameters(); + const arma::rowvec& parameters2 = + params.Get*>("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. - if (arma::all((parameters1-parameters2) == 0)) + if (arma::all((parameters1 - parameters2) == 0)) { FAIL("parameters1 and parameters2 are equal. \ Parameter(Step Size) has no effect on the output"); @@ -648,16 +620,15 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", SetInputParam("test", testX); // First solution. - mlpackMain(); + RUN_BINDING(); // Get the output after first training. const arma::Row output1 = - IO::GetParam>("predictions"); + params.Get>("predictions"); // Reset the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -665,11 +636,11 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", SetInputParam("test", testX); // Second solution. - mlpackMain(); + RUN_BINDING(); // Get the output after second training. - const arma::Row &output2 = - IO::GetParam>("predictions"); + const arma::Row& output2 = + params.Get>("predictions"); // Check that the output changed when the decision boundary moved. REQUIRE(arma::accu(output1 != output2) > 0); @@ -693,15 +664,15 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROPtionConsistencyTest", SetInputParam("test", testX); // The solution. - mlpackMain(); + RUN_BINDING(); // Get the output from 'predictions' parameter const arma::Row testY1 = - IO::GetParam>("predictions"); + params.Get>("predictions"); // Get output from 'output' parameter const arma::Row testY2 = - std::move(IO::GetParam>("output")); + std::move(params.Get>("output")); // Both solutions must be equal. CheckMatrices(testY1, testY2); @@ -725,15 +696,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROPtionConsistencyTest2", SetInputParam("test", testX); // The solution. - mlpackMain(); + RUN_BINDING(); // Get the output from 'predictions' parameter - const arma::mat testY1 = - IO::GetParam("output_probabilities"); + const arma::mat testY1 = params.Get("output_probabilities"); // Get output from 'output' parameter - const arma::mat testY2 = - std::move(IO::GetParam("probabilities")); + const arma::mat testY2 = std::move(params.Get("probabilities")); // Both solutions must be equal. CheckMatrices(testY1, testY2); diff --git a/src/mlpack/tests/main_tests/lsh_test.cpp b/src/mlpack/tests/main_tests/lsh_test.cpp index 2a4db08110..c18fef63ae 100644 --- a/src/mlpack/tests/main_tests/lsh_test.cpp +++ b/src/mlpack/tests/main_tests/lsh_test.cpp @@ -2,44 +2,27 @@ * @file tests/main_tests/lsh_test.cpp * @author Manish Kumar * - * Test mlpackMain() of lsh_main.cpp. + * Test RUN_BINDING() of lsh_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "LSH"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct LSHTestFixture -{ - public: - LSHTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~LSHTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(LSHTestFixture); /** * Check that output neighbors and distances have valid dimensions. @@ -52,15 +35,15 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHOutputDimensionTest", SetInputParam("reference", std::move(reference)); SetInputParam("k", (int) 6); - mlpackMain(); + RUN_BINDING(); // Check the neighbors matrix has 6 points for each of the 100 input points. - REQUIRE(IO::GetParam>("neighbors").n_rows == 6); - REQUIRE(IO::GetParam>("neighbors").n_cols == 100); + REQUIRE(params.Get>("neighbors").n_rows == 6); + REQUIRE(params.Get>("neighbors").n_cols == 100); // Check the distances matrix has 6 points for each of the 100 input points. - REQUIRE(IO::GetParam("distances").n_rows == 6); - REQUIRE(IO::GetParam("distances").n_cols == 100); + REQUIRE(params.Get("distances").n_rows == 6); + REQUIRE(params.Get("distances").n_cols == 100); } /** @@ -79,10 +62,11 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHParamValidityTest", SetInputParam("bucket_size", (int) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Test for second_hash_size. @@ -91,10 +75,11 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHParamValidityTest", SetInputParam("second_hash_size", (int) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Test for number of nearest neighbors. @@ -102,7 +87,7 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHParamValidityTest", SetInputParam("k", (int) -2); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -117,12 +102,12 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHModelValidityTest", SetInputParam("reference", std::move(reference)); SetInputParam("k", (int) 6); - mlpackMain(); + RUN_BINDING(); - SetInputParam("input_model", IO::GetParam*>("output_model")); + SetInputParam("input_model", params.Get*>("output_model")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -138,12 +123,13 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffTablesTest", SetInputParam("k", (int) 6); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train model using tables equals to 40. @@ -152,14 +138,14 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffTablesTest", SetInputParam("tables", (int) 40); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs using two models are // different. REQUIRE(arma::accu(neighbors == - IO::GetParam>("neighbors")) < neighbors.n_elem); + params.Get>("neighbors")) < neighbors.n_elem); REQUIRE(arma::accu(distances == - IO::GetParam("distances")) < distances.n_elem); + params.Get("distances")) < distances.n_elem); } /** @@ -174,12 +160,13 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffProjectionsTest", SetInputParam("k", (int) 6); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train model using projections equals to 30. @@ -188,14 +175,14 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffProjectionsTest", SetInputParam("projections", (int) 30); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs using two models are // different. REQUIRE(arma::accu(neighbors == - IO::GetParam>("neighbors")) < neighbors.n_elem); + params.Get>("neighbors")) < neighbors.n_elem); REQUIRE(arma::accu(distances == - IO::GetParam("distances")) < distances.n_elem); + params.Get("distances")) < distances.n_elem); } /** @@ -210,12 +197,13 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffHashWidthTest", SetInputParam("k", (int) 6); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train model using hash_width equals to 0.5. @@ -224,14 +212,14 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffHashWidthTest", SetInputParam("hash_width", (double) 0.5); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs using two models are // different. REQUIRE(arma::accu(neighbors == - IO::GetParam>("neighbors")) < neighbors.n_elem); + params.Get>("neighbors")) < neighbors.n_elem); REQUIRE(arma::accu(distances == - IO::GetParam("distances")) < distances.n_elem); + params.Get("distances")) < distances.n_elem); } /** @@ -247,27 +235,31 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffNumProbesTest", SetInputParam("query", query); SetInputParam("k", (int) 6); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + LSHSearch<>* m = params.Get*>("output_model"); + params.Get*>("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Train model using num_probes equals to 5. - SetInputParam("input_model", IO::GetParam*>("output_model")); + SetInputParam("input_model", m); SetInputParam("query", std::move(query)); SetInputParam("num_probes", (int) 5); + SetInputParam("k", (int) 6); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs using two models are // different. REQUIRE(arma::accu(neighbors == - IO::GetParam>("neighbors")) < neighbors.n_elem); + params.Get>("neighbors")) < neighbors.n_elem); REQUIRE(arma::accu(distances == - IO::GetParam("distances")) < distances.n_elem); + params.Get("distances")) < distances.n_elem); } /** @@ -282,12 +274,13 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffSecondHashSizeTest", SetInputParam("k", (int) 6); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train model using second_hash_size equals to 5000. @@ -296,14 +289,14 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffSecondHashSizeTest", SetInputParam("second_hash_size", (int) 5000); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs using two models are // different. REQUIRE(arma::accu(neighbors == - IO::GetParam>("neighbors")) < neighbors.n_elem); + params.Get>("neighbors")) < neighbors.n_elem); REQUIRE(arma::accu(distances == - IO::GetParam("distances")) < distances.n_elem); + params.Get("distances")) < distances.n_elem); } /** @@ -318,12 +311,13 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffBucketSizeTest", SetInputParam("k", (int) 6); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train model using bucket_size equals to 1000. @@ -332,14 +326,14 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHDiffBucketSizeTest", SetInputParam("bucket_size", (int) 1); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs using the two models are // different. REQUIRE(arma::accu(neighbors == - IO::GetParam>("neighbors")) < neighbors.n_elem); + params.Get>("neighbors")) < neighbors.n_elem); REQUIRE(arma::accu(distances == - IO::GetParam("distances")) < distances.n_elem); + params.Get("distances")) < distances.n_elem); } /** @@ -355,22 +349,27 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHModelReuseTest", SetInputParam("query", query); SetInputParam("k", (int) 6); - mlpackMain(); + RUN_BINDING(); - arma::Mat neighbors = IO::GetParam>("neighbors"); - arma::mat distances = IO::GetParam("distances"); + arma::Mat neighbors = params.Get>("neighbors"); + arma::mat distances = params.Get("distances"); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + LSHSearch<>* m = params.Get*>("output_model"); + params.Get*>("output_model") = NULL; - SetInputParam("input_model", IO::GetParam*>("output_model")); + CleanMemory(); + ResetSettings(); + + SetInputParam("input_model", m); SetInputParam("query", std::move(query)); + SetInputParam("k", (int) 6); - mlpackMain(); + RUN_BINDING(); // Check that initial query outputs and final outputs using saved model are // same. - CheckMatrices(neighbors, IO::GetParam>("neighbors")); - CheckMatrices(distances, IO::GetParam("distances")); + CheckMatrices(neighbors, params.Get>("neighbors")); + CheckMatrices(distances, params.Get("distances")); } /** @@ -389,6 +388,6 @@ TEST_CASE_METHOD(LSHTestFixture, "LSHModelTrueNighborsDimTest", SetInputParam("k", (int) 6); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/mean_shift_test.cpp b/src/mlpack/tests/main_tests/mean_shift_test.cpp index 867eb4ec1e..af51d0fba7 100644 --- a/src/mlpack/tests/main_tests/mean_shift_test.cpp +++ b/src/mlpack/tests/main_tests/mean_shift_test.cpp @@ -2,52 +2,26 @@ * @file tests/main_tests/mean_shift_test.cpp * @author Tan Jun An * - * Test mlpackMain() of mean_shift_main.cpp. + * Test RUN_BINDING() of mean_shift_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "MeanShift"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct MeanShiftTestFixture -{ - public: - MeanShiftTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~MeanShiftTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -static void ResetSettings() -{ - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(MeanShiftTestFixture); /** * Ensure that the output has 1 extra row for the labels and @@ -63,12 +37,12 @@ TEST_CASE_METHOD( // Input random data points. SetInputParam("input", std::move(x)); - mlpackMain(); + RUN_BINDING(); // Now check that the output has 1 extra row for labels. - REQUIRE(IO::GetParam("output").n_rows == 3 + 1); + REQUIRE(params.Get("output").n_rows == 3 + 1); // Check number of output points are the same. - REQUIRE(IO::GetParam("output").n_cols == 100); + REQUIRE(params.Get("output").n_cols == 100); } /** @@ -86,12 +60,12 @@ TEST_CASE_METHOD( SetInputParam("input", std::move(x)); SetInputParam("labels_only", true); - mlpackMain(); + RUN_BINDING(); // Check that there is only 1 row containing all the labels. - REQUIRE(IO::GetParam("output").n_rows == 1); + REQUIRE(params.Get("output").n_rows == 1); // Check number of output points are the same. - REQUIRE(IO::GetParam("output").n_cols == 100); + REQUIRE(params.Get("output").n_cols == 100); } /** @@ -115,13 +89,13 @@ TEST_CASE_METHOD( SetInputParam("input", std::move(x)); SetInputParam("in_place", true); - mlpackMain(); + RUN_BINDING(); // Now check that the output has 1 extra row for labels. - REQUIRE(IO::GetParam("output").n_rows == + REQUIRE(params.Get("output").n_rows == (arma::uword) (numRows + 1)); // Check number of output points are the same. - REQUIRE(IO::GetParam("output").n_cols == (arma::uword) numCols); + REQUIRE(params.Get("output").n_cols == (arma::uword) numCols); } /** @@ -141,10 +115,11 @@ TEST_CASE_METHOD( // Set a very small max_iterations. SetInputParam("max_iterations", (int) 1); - mlpackMain(); + RUN_BINDING(); - const int numCentroids1 = IO::GetParam("centroid").n_cols; + const int numCentroids1 = params.Get("centroid").n_cols; + CleanMemory(); ResetSettings(); // Input same random data points. @@ -154,9 +129,9 @@ TEST_CASE_METHOD( // Set the force_convergence flag on. SetInputParam("force_convergence", true); - mlpackMain(); + RUN_BINDING(); - const int numCentroids2 = IO::GetParam("centroid").n_cols; + const int numCentroids2 = params.Get("centroid").n_cols; // Resulting number of centroids should be different. REQUIRE(numCentroids1 != numCentroids2); } @@ -178,10 +153,11 @@ TEST_CASE_METHOD( // Set a small radius. SetInputParam("radius", (double) 0.1); - mlpackMain(); + RUN_BINDING(); - const int numCentroids1 = IO::GetParam("centroid").n_cols; + const int numCentroids1 = params.Get("centroid").n_cols; + CleanMemory(); ResetSettings(); // Input same random data points. @@ -189,9 +165,9 @@ TEST_CASE_METHOD( // Set a larger radius. SetInputParam("radius", (double) 1.0); - mlpackMain(); + RUN_BINDING(); - const int numCentroids2 = IO::GetParam("centroid").n_cols; + const int numCentroids2 = params.Get("centroid").n_cols; // Resulting number of centroids should be different. REQUIRE(numCentroids1 != numCentroids2); } @@ -213,10 +189,11 @@ TEST_CASE_METHOD( // Set a small max_iterations. SetInputParam("max_iterations", (int) 4); - mlpackMain(); + RUN_BINDING(); - const int numCentroids1 = IO::GetParam("centroid").n_cols; + const int numCentroids1 = params.Get("centroid").n_cols; + CleanMemory(); ResetSettings(); // Input same random data points. @@ -224,9 +201,9 @@ TEST_CASE_METHOD( // Set a larger max_iterations. SetInputParam("max_iterations", (int) 20); - mlpackMain(); + RUN_BINDING(); - const int numCentroids2 = IO::GetParam("centroid").n_cols; + const int numCentroids2 = params.Get("centroid").n_cols; // Resulting number of centroids should be different. REQUIRE(numCentroids1 != numCentroids2); } @@ -247,6 +224,6 @@ TEST_CASE_METHOD( SetInputParam("max_iterations", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/nbc_test.cpp b/src/mlpack/tests/main_tests/nbc_test.cpp index 36c2d548d0..9ac51837ee 100644 --- a/src/mlpack/tests/main_tests/nbc_test.cpp +++ b/src/mlpack/tests/main_tests/nbc_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/nbc_test.cpp * @author Manish Kumar * - * Test mlpackMain() of nbc_main.cpp. + * Test RUN_BINDING() of nbc_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 @@ -12,33 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "NBC"; - #include #include -#include "test_helper.hpp" + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct NBCTestFixture -{ - public: - NBCTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~NBCTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(NBCTestFixture); /** * Ensure that we get desired dimensions when both training @@ -75,15 +59,15 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCOutputDimensionTest", // Input test data. SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam("output_probs").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get("output_probs").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - REQUIRE(IO::GetParam("output_probs").n_rows == 2); + REQUIRE(params.Get>("output").n_rows == 1); + REQUIRE(params.Get("output_probs").n_rows == 2); } /** @@ -119,27 +103,25 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCLabelsLessDimensionTest", // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam("output_probs").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get("output_probs").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - REQUIRE(IO::GetParam("output_probs").n_rows == 2); - - // Reset data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + REQUIRE(params.Get>("output").n_rows == 1); + REQUIRE(params.Get("output_probs").n_rows == 2); // Store outputs. arma::Row output; arma::mat output_probs; - output = std::move(IO::GetParam>("output")); - output_probs = std::move(IO::GetParam("output_probs")); + output = std::move(params.Get>("output")); + output_probs = std::move(params.Get("output_probs")); - bindings::tests::CleanMemory(); + // Reset data passed. + CleanMemory(); + ResetSettings(); // Now train NBC with labels provided. @@ -151,20 +133,20 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCLabelsLessDimensionTest", // Pass Labels. SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam("output_probs").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get("output_probs").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - REQUIRE(IO::GetParam("output_probs").n_rows == 2); + REQUIRE(params.Get>("output").n_rows == 1); + REQUIRE(params.Get("output_probs").n_rows == 2); // Check that initial output and final output matrix // from two models are same. - CheckMatrices(output, IO::GetParam>("output")); - CheckMatrices(output_probs, IO::GetParam("output_probs")); + CheckMatrices(output, params.Get>("output")); + CheckMatrices(output_probs, params.Get("output_probs")); } /** @@ -192,36 +174,37 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCModelReuseTest", // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::Row output; arma::mat output_probs; - output = std::move(IO::GetParam>("output")); - output_probs = std::move(IO::GetParam("output_probs")); + output = std::move(params.Get>("output")); + output_probs = std::move(params.Get("output_probs")); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + NBCModel* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input trained model. SetInputParam("test", std::move(testData)); - SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam("output_probs").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get("output_probs").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - REQUIRE(IO::GetParam("output_probs").n_rows == 2); + REQUIRE(params.Get>("output").n_rows == 1); + REQUIRE(params.Get("output_probs").n_rows == 2); // Check that initial output and final output // matrix using saved model are same. - CheckMatrices(output, IO::GetParam>("output")); - CheckMatrices(output_probs, IO::GetParam("output_probs")); + CheckMatrices(output, params.Get>("output")); + CheckMatrices(output_probs, params.Get("output_probs")); } /** @@ -237,14 +220,14 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCTrainingVerTest", // Input training data. SetInputParam("training", std::move(inputData)); - mlpackMain(); + RUN_BINDING(); // Input pre-trained model. SetInputParam("input_model", - std::move(IO::GetParam("output_model"))); + std::move(params.Get("output_model"))); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -276,28 +259,24 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCIncrementalVarianceTest", SetInputParam("test", testData); SetInputParam("incremental_variance", (bool) true); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam("output_probs").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get("output_probs").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - REQUIRE(IO::GetParam("output_probs").n_rows == 2); - - bindings::tests::CleanMemory(); - - // Reset data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["incremental_variance"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + REQUIRE(params.Get>("output").n_rows == 1); + REQUIRE(params.Get("output_probs").n_rows == 2); // Store outputs. arma::Row output; arma::mat output_probs; - output = std::move(IO::GetParam>("output")); - output_probs = std::move(IO::GetParam("output_probs")); + output = std::move(params.Get>("output")); + output_probs = std::move(params.Get("output_probs")); + + CleanMemory(); + ResetSettings(); // Now train NBC without incremental_variance. @@ -306,20 +285,20 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCIncrementalVarianceTest", SetInputParam("test", std::move(testData)); SetInputParam("incremental_variance", (bool) false); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); - REQUIRE(IO::GetParam("output_probs").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); + REQUIRE(params.Get("output_probs").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - REQUIRE(IO::GetParam("output_probs").n_rows == 2); + REQUIRE(params.Get>("output").n_rows == 1); + REQUIRE(params.Get("output_probs").n_rows == 2); // Check that initial output and final output matrix // from two models are same. - CheckMatrices(output, IO::GetParam>("output")); - CheckMatrices(output_probs, IO::GetParam("output_probs")); + CheckMatrices(output, params.Get>("output")); + CheckMatrices(output_probs, params.Get("output_probs")); } /** @@ -356,15 +335,15 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCOptionConsistencyTest", // Input test data. SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Get the output from the 'output' parameter. const arma::Row testY1 = - std::move(IO::GetParam>("output")); + std::move(params.Get>("output")); // Get output from 'predictions' parameter. const arma::Row testY2 = - IO::GetParam>("predictions"); + params.Get>("predictions"); // Both solutions must be equal. CheckMatrices(testY1, testY2); @@ -405,15 +384,15 @@ TEST_CASE_METHOD(NBCTestFixture, "NBCOptionConsistencyTest2", // Input test data. SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Get the output probabilites which is a deprecated parameter. const arma::mat testY1 = - std::move(IO::GetParam("output_probs")); + std::move(params.Get("output_probs")); // Get probabilities from 'predictions' parameter. const arma::mat testY2 = - IO::GetParam("probabilities"); + params.Get("probabilities"); // Both solutions must be equal. CheckMatrices(testY1, testY2); diff --git a/src/mlpack/tests/main_tests/nca_test.cpp b/src/mlpack/tests/main_tests/nca_test.cpp index 414148ebf9..709aedb117 100644 --- a/src/mlpack/tests/main_tests/nca_test.cpp +++ b/src/mlpack/tests/main_tests/nca_test.cpp @@ -2,48 +2,28 @@ * @file tests/main_tests/nca_test.cpp * @author Yasmine Dumouchel * - * Test mlpackMain() of nca_main.cpp. + * Test RUN_BINDING() of nca_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. */ - -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "nca"; #include #include #include #include -#include +#include "main_test_fixture.hpp" -#include "test_helper.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct NCATestFixture -{ - public: - NCATestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~NCATestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(NCATestFixture); /** * Ensure that, when labels are implicitily given with input, @@ -59,16 +39,16 @@ TEST_CASE_METHOD(NCATestFixture, "NCAExplicitImplicitLabelsTest", SetInputParam("input", std::move(x)); - mlpackMain(); + RUN_BINDING(); // Check that last row was treated as label by checking that // the output has 1 less row. - REQUIRE(IO::GetParam("output").n_rows == 2); - REQUIRE(IO::GetParam("output").n_cols == 2); + REQUIRE(params.Get("output").n_rows == 2); + REQUIRE(params.Get("output").n_cols == 2); // Reset Settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Now check that when labels are explicitely given, the last column // of input is not treated as labels. @@ -79,11 +59,11 @@ TEST_CASE_METHOD(NCATestFixture, "NCAExplicitImplicitLabelsTest", SetInputParam("input", std::move(y)); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == 2); - REQUIRE(IO::GetParam("output").n_cols == 2); + REQUIRE(params.Get("output").n_rows == 2); + REQUIRE(params.Get("output").n_cols == 2); } /** @@ -103,11 +83,11 @@ TEST_CASE_METHOD(NCATestFixture, "NCALBFGSTest", SetInputParam("labels", std::move(labels)); SetInputParam("optimizer", std::string("lbfgs")); - mlpackMain(); + RUN_BINDING(); // Check that final output has expected number of rows and colums. - REQUIRE(IO::GetParam("output").n_rows == 3); - REQUIRE(IO::GetParam("output").n_cols == 3); + REQUIRE(params.Get("output").n_rows == 3); + REQUIRE(params.Get("output").n_cols == 3); } /** @@ -127,7 +107,7 @@ TEST_CASE_METHOD(NCATestFixture, "NCALabelSizeTest", // Check that an error is thrown. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -152,13 +132,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCANormalizationTest", SetInputParam("linear_scan", true); SetInputParam("tolerance", 0.01); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset rettings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); arma::mat inputData2; if (!data::Load("vc2.csv", inputData2)) @@ -175,10 +155,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCANormalizationTest", SetInputParam("linear_scan", true); SetInputParam("tolerance", 0.01); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); + REQUIRE(arma::accu(params.Get("output") != output) > 0); } /** @@ -198,13 +178,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentStepSizeTest", SetInputParam("step_size", (double) 1.2); SetInputParam("linear_scan", true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Same dataset. arma::mat y = "-0.1 -0.1 -0.1 0.1 0.1 0.1;" @@ -217,10 +197,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentStepSizeTest", SetInputParam("step_size", (double) 20.5); SetInputParam("linear_scan", true); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); + REQUIRE(arma::accu(params.Get("output") != output) > 0); } /** @@ -251,13 +231,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentToleranceTest", SetInputParam("max_iterations", (int) 0); SetInputParam("tolerance", (double) 1e-8); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Set parameters using the same input but with a larger tolerance. SetInputParam("input", std::move(y)); @@ -266,10 +246,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentToleranceTest", SetInputParam("max_iterations", (int) 0); SetInputParam("tolerance", (double) 100.0); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - success = (arma::accu(IO::GetParam("output") != output) > 0); + success = (arma::accu(params.Get("output") != output) > 0); if (success) break; @@ -297,13 +277,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentBatchSizeTest", SetInputParam("batch_size", (int) 2); SetInputParam("linear_scan", true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Input the same dataset. arma::mat y = "-0.1 -0.1 -0.1 0.1 0.1 0.1;" @@ -317,10 +297,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentBatchSizeTest", SetInputParam("batch_size", (int) 3); SetInputParam("linear_scan", true); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); + REQUIRE(arma::accu(params.Get("output") != output) > 0); } /** @@ -339,13 +319,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCALinearScanTest", SetInputParam("labels", labels); SetInputParam("optimizer", std::string("sgd")); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Input the same dataset. arma::mat y = "-0.1 -0.1 -0.1 0.1 0.1 0.1;" @@ -358,10 +338,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCALinearScanTest", SetInputParam("optimizer", std::string("sgd")); SetInputParam("linear_scan", false); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - REQUIRE(arma::accu(IO::GetParam("output") != output) > 0); + REQUIRE(arma::accu(params.Get("output") != output) > 0); } /** @@ -380,13 +360,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCALinearScanTest2", SetInputParam("labels", labels); SetInputParam("linear_scan", true); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset Settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Set same parameter using the same data. arma::mat y = "-0.1 -0.1 -0.1 0.1 0.1 0.1;" @@ -396,10 +376,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCALinearScanTest2", SetInputParam("input", std::move(y)); SetInputParam("labels", labels2); SetInputParam("linear_scan", true); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are equal. - CheckMatrices(output, IO::GetParam("output")); + CheckMatrices(output, params.Get("output")); } /** @@ -430,13 +410,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentNumBasisTest", SetInputParam("optimizer", std::string("lbfgs")); SetInputParam("num_basis", (int) 5); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset Settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Set parameters with a smaller num_basis. SetInputParam("input", std::move(y)); @@ -444,10 +424,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentNumBasisTest", SetInputParam("optimizer", std::string("lbfgs")); SetInputParam("num_basis", (int) 1); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - success = (arma::accu(IO::GetParam("output") != output) > 0); + success = (arma::accu(params.Get("output") != output) > 0); if (success) break; @@ -485,13 +465,13 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentMaxIterationTest", SetInputParam("optimizer", std::string("lbfgs")); SetInputParam("max_iterations", (int) 3); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); // Reset settings. - IO::ClearSettings(); - IO::RestoreSettings(testName); + CleanMemory(); + ResetSettings(); // Set parameters using the same input but with a larger max_iterations. SetInputParam("input", std::move(y)); @@ -499,10 +479,10 @@ TEST_CASE_METHOD(NCATestFixture, "NCADifferentMaxIterationTest", SetInputParam("optimizer", std::string("lbfgs")); SetInputParam("max_iterations", (int) 500); - mlpackMain(); + RUN_BINDING(); // Check that the output matrices are different. - success = (arma::accu(IO::GetParam("output") != output) > 0); + success = (arma::accu(params.Get("output") != output) > 0); if (success) break; diff --git a/src/mlpack/tests/main_tests/nmf_test.cpp b/src/mlpack/tests/main_tests/nmf_test.cpp index 0a111c53b3..b516588dcb 100644 --- a/src/mlpack/tests/main_tests/nmf_test.cpp +++ b/src/mlpack/tests/main_tests/nmf_test.cpp @@ -2,53 +2,27 @@ * @file nmf_test.cpp * @author Wenhao Huang * - * Test mlpackMain() of nmf_main.cpp + * Test RUN_BINDING() of nmf_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "NonNegativeMatrixFactorization"; - #include -#include #include -#include "test_helper.hpp" +#include + +#include "main_test_fixture.hpp" #include "../catch.hpp" using namespace mlpack; using namespace arma; - -struct NMFTestFixture -{ - public: - NMFTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~NMFTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -static void ResetSettings() -{ - bindings::tests::CleanMemory(); - IO::ClearSettings(); - IO::RestoreSettings(testName); -} +BINDING_TEST_FIXTURE(NMFTestFixture); /** * Ensure the resulting matrices W, H have expected shape. @@ -65,11 +39,11 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMultdistShapeTest", SetInputParam("rank", r); // Perform NMF. - mlpackMain(); + RUN_BINDING(); // Get resulting matrices. - const mat& w = IO::GetParam("w"); - const mat& h = IO::GetParam("h"); + const mat& w = params.Get("w"); + const mat& h = params.Get("h"); // Check the shapes of W and H. REQUIRE(w.n_rows == 8); @@ -93,11 +67,11 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMultdivShapeTest", SetInputParam("rank", r); // Perform NMF. - mlpackMain(); + RUN_BINDING(); // Get resulting matrices. - const mat& w = IO::GetParam("w"); - const mat& h = IO::GetParam("h"); + const mat& w = params.Get("w"); + const mat& h = params.Get("h"); // Check the shapes of W and H. REQUIRE(w.n_rows == 8); @@ -121,11 +95,11 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFAlsShapeTest", SetInputParam("rank", r); // Perform NMF. - mlpackMain(); + RUN_BINDING(); // Get resulting matrices. - const mat& w = IO::GetParam("w"); - const mat& h = IO::GetParam("h"); + const mat& w = params.Get("w"); + const mat& h = params.Get("h"); // Check the shapes of W and H. REQUIRE(w.n_rows == 8); @@ -149,7 +123,7 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFRankBoundTest", SetInputParam("rank", r); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Rank should not be 0. @@ -157,7 +131,7 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFRankBoundTest", SetInputParam("rank", r); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -176,7 +150,7 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMaxIterartionBoundTest", SetInputParam("rank", r); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -196,7 +170,7 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFUpdateRuleTest", SetInputParam("rank", r); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -219,11 +193,12 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMinResidueTest", SetInputParam("initial_w", initialW); SetInputParam("initial_h", initialH); - mlpackMain(); + RUN_BINDING(); - const mat w1 = IO::GetParam("w"); - const mat h1 = IO::GetParam("h"); + const mat w1 = params.Get("w"); + const mat h1 = params.Get("h"); + CleanMemory(); ResetSettings(); // Set a smaller min_residue. @@ -233,10 +208,10 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMinResidueTest", SetInputParam("initial_w", initialW); SetInputParam("initial_h", initialH); - mlpackMain(); + RUN_BINDING(); - const mat w2 = IO::GetParam("w"); - const mat h2 = IO::GetParam("h"); + const mat w2 = params.Get("w"); + const mat h2 = params.Get("h"); // The resulting matrices should be different. REQUIRE(arma::norm(w1 - w2) > 1e-5); @@ -264,11 +239,12 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMaxIterationTest", SetInputParam("initial_w", initialW); SetInputParam("initial_h", initialH); - mlpackMain(); + RUN_BINDING(); - const mat w1 = IO::GetParam("w"); - const mat h1 = IO::GetParam("h"); + const mat w1 = params.Get("w"); + const mat h1 = params.Get("h"); + CleanMemory(); ResetSettings(); // Set a smaller max_iterations. @@ -280,10 +256,10 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFMaxIterationTest", SetInputParam("initial_w", initialW); SetInputParam("initial_h", initialH); - mlpackMain(); + RUN_BINDING(); - const mat w2 = IO::GetParam("w"); - const mat h2 = IO::GetParam("h"); + const mat w2 = params.Get("w"); + const mat h2 = params.Get("h"); // The resulting matrices should be different. REQUIRE(arma::norm(w1 - w2) > 1e-5); @@ -306,10 +282,10 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFWHGivenInitTest", SetInputParam("initial_w", initialW); SetInputParam("initial_h", initialH); - mlpackMain(); + RUN_BINDING(); - const mat w = IO::GetParam("w"); - const mat h = IO::GetParam("h"); + const mat w = params.Get("w"); + const mat h = params.Get("h"); // Check the shapes of W and H. REQUIRE(w.n_rows == 10); @@ -332,10 +308,10 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFWGivenInitTest", SetInputParam("rank", r); SetInputParam("initial_w", initialW); - mlpackMain(); + RUN_BINDING(); - const mat w = IO::GetParam("w"); - const mat h = IO::GetParam("h"); + const mat w = params.Get("w"); + const mat h = params.Get("h"); // Check the shapes of W and H. REQUIRE(w.n_rows == 10); @@ -358,10 +334,10 @@ TEST_CASE_METHOD(NMFTestFixture, "NMFHGivenInitTest", SetInputParam("rank", r); SetInputParam("initial_h", initialH); - mlpackMain(); + RUN_BINDING(); - const mat w = IO::GetParam("w"); - const mat h = IO::GetParam("h"); + const mat w = params.Get("w"); + const mat h = params.Get("h"); // Check the shapes of W and H. REQUIRE(w.n_rows == 10); diff --git a/src/mlpack/tests/main_tests/pca_test.cpp b/src/mlpack/tests/main_tests/pca_test.cpp index dfc018103c..008e047381 100644 --- a/src/mlpack/tests/main_tests/pca_test.cpp +++ b/src/mlpack/tests/main_tests/pca_test.cpp @@ -2,43 +2,26 @@ * @file tests/main_tests/pca_test.cpp * @author Ryan Curtin * - * Test mlpackMain() of pca_main.cpp. + * Test RUN_BINDING() of pca_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "PrincipalComponentAnalysis"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../catch.hpp" using namespace mlpack; -struct PCATestFixture -{ - public: - PCATestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~PCATestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(PCATestFixture); /** * Make sure that if we ask for a dataset in 3 dimensions back, we get it. @@ -52,11 +35,11 @@ TEST_CASE_METHOD(PCATestFixture, "PCADimensionTest", SetInputParam("input", std::move(x)); SetInputParam("new_dimensionality", (int) 3); - mlpackMain(); + RUN_BINDING(); // Now check that the output has 3 dimensions. - REQUIRE(IO::GetParam("output").n_rows == 3); - REQUIRE(IO::GetParam("output").n_cols == 5); + REQUIRE(params.Get("output").n_rows == 3); + REQUIRE(params.Get("output").n_cols == 5); } /** @@ -73,11 +56,11 @@ TEST_CASE_METHOD(PCATestFixture, "PCAVarRetainTest", SetInputParam("scale", true); SetInputParam("new_dimensionality", (int) 3); // Should be ignored. - mlpackMain(); + RUN_BINDING(); // Check that the output has 5 dimensions. - REQUIRE(IO::GetParam("output").n_rows == 4); - REQUIRE(IO::GetParam("output").n_cols == 5); + REQUIRE(params.Get("output").n_rows == 4); + REQUIRE(params.Get("output").n_cols == 5); } /** @@ -93,11 +76,11 @@ TEST_CASE_METHOD(PCATestFixture, "PCANoVarRetainTest", SetInputParam("scale", true); SetInputParam("new_dimensionality", (int) 3); // Should be ignored. - mlpackMain(); + RUN_BINDING(); // Check that the output has 1 dimensions. - REQUIRE(IO::GetParam("output").n_rows == 1); - REQUIRE(IO::GetParam("output").n_cols == 5); + REQUIRE(params.Get("output").n_rows == 1); + REQUIRE(params.Get("output").n_cols == 5); } /** @@ -112,6 +95,6 @@ TEST_CASE_METHOD(PCATestFixture, "PCATooHighNewDimensionalityTest", SetInputParam("new_dimensionality", (int) 7); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/perceptron_test.cpp b/src/mlpack/tests/main_tests/perceptron_test.cpp index 8e8b6a8087..423939f27c 100644 --- a/src/mlpack/tests/main_tests/perceptron_test.cpp +++ b/src/mlpack/tests/main_tests/perceptron_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/perceptron_test.cpp * @author Manish Kumar * - * Test mlpackMain() of perceptron_main.cpp. + * Test RUN_BINDING() of perceptron_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 @@ -12,33 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "Perceptron"; - #include #include -#include "test_helper.hpp" + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct PerceptronTestFixture -{ - public: - PerceptronTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~PerceptronTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(PerceptronTestFixture); /** * Ensure that we get desired dimensions when both training @@ -75,13 +59,13 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronOutputDimensionTest", // Input test data. SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); + REQUIRE(params.Get>("output").n_rows == 1); } /** @@ -117,25 +101,23 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronLabelsLessDimensionTest", // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); - - // Reset data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + REQUIRE(params.Get>("output").n_rows == 1); inputData.shed_row(inputData.n_rows - 1); // Store outputs. arma::Row output; - output = std::move(IO::GetParam>("output")); + output = std::move(params.Get>("output")); - bindings::tests::CleanMemory(); + // Reset data passed. + CleanMemory(); + ResetSettings(); // Now train perceptron with labels provided. @@ -145,17 +127,17 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronLabelsLessDimensionTest", // Pass Labels. SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); + REQUIRE(params.Get>("output").n_rows == 1); // Check that initial output and final output matrix // from two models are same. - CheckMatrices(output, IO::GetParam>("output")); + CheckMatrices(output, params.Get>("output")); } /** @@ -185,11 +167,11 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronOutputPredictionsCheck", SetInputParam("labels", std::move(labelsX1)); // Training model using first training dataset. - mlpackMain(); + RUN_BINDING(); // Check that the outputs are the same. - CheckMatrices(IO::GetParam>("output"), - IO::GetParam>("predictions")); + CheckMatrices(params.Get>("output"), + params.Get>("predictions")); } /** @@ -217,31 +199,32 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronModelReuseTest", // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::Row output; - output = std::move(IO::GetParam>("output")); + output = std::move(params.Get>("output")); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + PerceptronModel* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input trained model. SetInputParam("test", std::move(testData)); - SetInputParam("input_model", - IO::GetParam("output_model")); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("output").n_cols == testSize); + REQUIRE(params.Get>("output").n_cols == testSize); // Check output have only single row. - REQUIRE(IO::GetParam>("output").n_rows == 1); + REQUIRE(params.Get>("output").n_rows == 1); // Check that initial output and final output matrix // using saved model are same. - CheckMatrices(output, IO::GetParam>("output")); + CheckMatrices(output, params.Get>("output")); } /** @@ -259,7 +242,7 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronMaxItrTest", SetInputParam("max_iterations", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -290,15 +273,15 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronReTrainWithWrongClasses", SetInputParam("labels", std::move(labelsX1)); // Training model using first training dataset. - mlpackMain(); + RUN_BINDING(); // Get the output model obtained after training. - PerceptronModel* model = - IO::GetParam("output_model"); + PerceptronModel* model = params.Get("output_model"); + params.Get("output_model") = NULL; // Reset the data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Creating training data with five classes. constexpr int D = 3; @@ -316,7 +299,7 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronReTrainWithWrongClasses", // Re-training an existing model of 3 classes // with training data of 5 classes. It should give runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -345,7 +328,7 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronWrongDimOfTestData", // Test data set with wrong dimensionality. It should give runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -369,7 +352,7 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronWrongResponseSizeTest", // Labels for training data have wrong size. It should give runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -387,7 +370,7 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronNoResponsesTest", // No labels for training data. It should give runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -404,7 +387,7 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronNoTrainingDataTest", // No training data. It should give runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -428,15 +411,15 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronWrongDimOfTestData2", SetInputParam("labels", std::move(trainY)); // Training the model. - mlpackMain(); + RUN_BINDING(); // Get the output model obtained after the training. - PerceptronModel* model = - IO::GetParam("output_model"); + PerceptronModel* model = params.Get("output_model"); + params.Get("output_model") = NULL; // Reset the data passed. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Test data with Wrong dimensionality. arma::mat testX = arma::randu(D - 1, M); @@ -445,6 +428,6 @@ TEST_CASE_METHOD(PerceptronTestFixture, "PerceptronWrongDimOfTestData2", // Wrong dimensionality of test data. It should give runtime error. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/preprocess_binarize_test.cpp b/src/mlpack/tests/main_tests/preprocess_binarize_test.cpp index a4025685b9..7b82ecb7f9 100644 --- a/src/mlpack/tests/main_tests/preprocess_binarize_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_binarize_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/preprocess_binarize_test.cpp * @author Manish Kumar * - * Test mlpackMain() of preprocess_binarize_main.cpp. + * Test RUN_BINDING() of preprocess_binarize_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 @@ -12,33 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "PreprocessBinarize"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct PreprocessBinarizeTestFixture -{ - public: - PreprocessBinarizeTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~PreprocessBinarizeTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(PreprocessBinarizeTestFixture); /** * Check that input and output have same dimensions. @@ -58,11 +42,11 @@ TEST_CASE_METHOD( SetInputParam("threshold", (double) 0.5); SetInputParam("dimension", (int) 1); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("output").n_rows == 2); - REQUIRE(IO::GetParam("output").n_cols == inputSize); + REQUIRE(params.Get("output").n_rows == 2); + REQUIRE(params.Get("output").n_cols == inputSize); } /** @@ -79,7 +63,7 @@ TEST_CASE_METHOD( SetInputParam("dimension", (int) -2); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -97,7 +81,7 @@ TEST_CASE_METHOD( SetInputParam("dimension", (int) 6); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -114,10 +98,10 @@ TEST_CASE_METHOD( SetInputParam("threshold", (double) 5.0); SetInputParam("dimension", (int) 1); - mlpackMain(); + RUN_BINDING(); arma::mat output; - output = std::move(IO::GetParam("output")); + output = std::move(params.Get("output")); // All values dimension should remain unchanged. REQUIRE(output(0, 0) == Approx(7.0).epsilon(1e-7)); @@ -147,10 +131,10 @@ TEST_CASE_METHOD( SetInputParam("input", std::move(inputData)); SetInputParam("threshold", (double) 5.0); - mlpackMain(); + RUN_BINDING(); arma::mat output; - output = std::move(IO::GetParam("output")); + output = std::move(params.Get("output")); // All values should be binarized according to the threshold. REQUIRE(output(0, 0) == Approx(1.0).epsilon(1e-7)); diff --git a/src/mlpack/tests/main_tests/preprocess_imputer_test.cpp b/src/mlpack/tests/main_tests/preprocess_imputer_test.cpp index 1b073e3c36..a397a7ef76 100644 --- a/src/mlpack/tests/main_tests/preprocess_imputer_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_imputer_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/preprocess_imputer_test.cpp * @author Manish Kumar * - * Test mlpackMain() of preprocess_imputer_main.cpp. + * Test RUN_BINDING() of preprocess_imputer_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 @@ -12,35 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "PreprocessImputer"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" -#include - using namespace mlpack; -struct PreprocessImputerTestFixture -{ - public: - PreprocessImputerTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~PreprocessImputerTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(PreprocessImputerTestFixture); /** * Check that input and output have same dimensions @@ -68,37 +50,45 @@ TEST_CASE_METHOD( // Check for mean strategy. SetInputParam("strategy", (std::string) "mean"); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - data::Load(IO::GetParam("output_file"), outputData); + data::Load(params.Get("output_file"), outputData); REQUIRE(outputData.n_cols == inputSize); REQUIRE(outputData.n_rows == 3); // Input Dimension. // Reset passed strategy. - IO::GetSingleton().Parameters()["strategy"].wasPassed = false; + ResetSettings(); // Check for median strategy. + SetInputParam("input_file", (std::string) "preprocess_imputer_test.csv"); + SetInputParam("missing_value", (std::string) "nan"); + SetInputParam("output_file", + (std::string) "preprocess_imputer_output_test.csv"); SetInputParam("strategy", (std::string) "median"); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - data::Load(IO::GetParam("output_file"), outputData); + data::Load(params.Get("output_file"), outputData); REQUIRE(outputData.n_cols == inputSize); REQUIRE(outputData.n_rows == 3); // Input Dimension. // Reset passed strategy. - IO::GetSingleton().Parameters()["strategy"].wasPassed = false; + ResetSettings(); // Check for custom strategy. + SetInputParam("input_file", (std::string) "preprocess_imputer_test.csv"); + SetInputParam("missing_value", (std::string) "nan"); + SetInputParam("output_file", + (std::string) "preprocess_imputer_output_test.csv"); SetInputParam("strategy", (std::string) "custom"); SetInputParam("custom_value", (double) 75.12); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - data::Load(IO::GetParam("output_file"), outputData); + data::Load(params.Get("output_file"), outputData); REQUIRE(outputData.n_cols == inputSize); REQUIRE(outputData.n_rows == 3); // Input Dimension. } @@ -136,11 +126,11 @@ TEST_CASE_METHOD( SetInputParam("output_file", (std::string) "preprocess_imputer_output_test.csv"); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. arma::mat outputData; - data::Load(IO::GetParam("output_file"), outputData); + data::Load(params.Get("output_file"), outputData); REQUIRE(outputData.n_cols + countNaN == inputSize); REQUIRE(outputData.n_rows == 3); // Input Dimension. } @@ -162,6 +152,6 @@ TEST_CASE_METHOD( SetInputParam("strategy", (std::string) "notmean"); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } diff --git a/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp b/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp index 1fd257dad8..4991a0d28b 100644 --- a/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/preprocess_one_hot_encode_test.cpp * @author Jeffin Sam * - * Test mlpackMain() of preprocess_one_hot_encoding_main.cpp. + * Test RUN_BINDING() of preprocess_one_hot_encoding_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 @@ -12,33 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "PreprocessOneHotEncoding"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct PreprocessOneHotEncodingTestFixture -{ - public: - PreprocessOneHotEncodingTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~PreprocessOneHotEncodingTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(PreprocessOneHotEncodingTestFixture); /** * Test one hot encoding binding. @@ -65,9 +49,9 @@ TEST_CASE_METHOD( SetInputParam("input", dataset); SetInputParam>("dimensions", {1, 3}); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); REQUIRE(matrix.n_cols == output.n_cols); REQUIRE(matrix.n_rows == output.n_rows); CheckMatrices(output, matrix); @@ -86,7 +70,7 @@ TEST_CASE_METHOD( SetInputParam>("dimensions", {1, 3}); // This will throw an error since dimensions are bigger than the matrix. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -106,9 +90,9 @@ TEST_CASE_METHOD( SetInputParam("input", dataset); SetInputParam>("dimensions", {}); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); REQUIRE(dataset.n_cols == output.n_cols); REQUIRE(dataset.n_rows == output.n_rows); CheckMatrices(output, dataset); @@ -132,7 +116,7 @@ TEST_CASE_METHOD( SetInputParam>("dimensions", {10000}); // Error since dimensions are bigger than matrix. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -153,7 +137,7 @@ TEST_CASE_METHOD( SetInputParam("input", dataset); SetInputParam>("dimensions", {-10000}); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -168,9 +152,9 @@ TEST_CASE_METHOD( SetInputParam("input", dataset); SetInputParam>("dimensions", {}); - mlpackMain(); + RUN_BINDING(); - arma::mat output = IO::GetParam("output"); + arma::mat output = params.Get("output"); REQUIRE(dataset.n_cols == output.n_cols); REQUIRE(dataset.n_rows == output.n_rows); CheckMatrices(output, dataset); diff --git a/src/mlpack/tests/main_tests/preprocess_scale_test.cpp b/src/mlpack/tests/main_tests/preprocess_scale_test.cpp index 1e8561280e..2e5d516b0d 100644 --- a/src/mlpack/tests/main_tests/preprocess_scale_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_scale_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/preprocess_scale_test.cpp * @author Jeffin Sam * - * Test mlpackMain() of preprocess_scale_main.cpp. + * Test RUN_BINDING() of preprocess_scale_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 @@ -12,37 +12,20 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "PreprocessScale"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct PreprocessScaleTestFixture -{ - public: - static arma::mat dataset; - PreprocessScaleTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } +BINDING_TEST_FIXTURE(PreprocessScaleTestFixture); - ~PreprocessScaleTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; - -arma::mat PreprocessScaleTestFixture::dataset = "-1 -0.5 0 1;" - "2 6 10 18;"; +arma::mat scaleMainDataset = "-1 -0.5 0 1;" + "2 6 10 18;"; /** * Check that two different scalers give two different output. @@ -52,20 +35,21 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "TwoScalerTest", { // Input custom data points. std::string method = "max_abs_scaler"; - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - mlpackMain(); - arma::mat maxAbsScalerOutput = IO::GetParam("output"); + RUN_BINDING(); + arma::mat maxAbsScalerOutput = params.Get("output"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); method = "standard_scaler"; - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); - mlpackMain(); - arma::mat standardScalerOutput = IO::GetParam("output"); + RUN_BINDING(); + arma::mat standardScalerOutput = params.Get("output"); CheckMatricesNotEqual(standardScalerOutput, maxAbsScalerOutput); } @@ -79,23 +63,24 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "TwoOptionTest", { std::string method = "min_max_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - mlpackMain(); - arma::mat output = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output = params.Get("output"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); SetInputParam("min_value", 2); SetInputParam("max_value", 4); - mlpackMain(); - arma::mat output_with_param = IO::GetParam("output"); + RUN_BINDING(); + arma::mat outputWithParam = params.Get("output"); - CheckMatricesNotEqual(output, output_with_param); + CheckMatricesNotEqual(output, outputWithParam); } /** @@ -106,22 +91,23 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "UnrelatedOptionTest", { std::string method = "standard_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - mlpackMain(); - arma::mat scaled = IO::GetParam("output"); + RUN_BINDING(); + arma::mat scaled = params.Get("output"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); SetInputParam("min_value", 2); SetInputParam("max_value", 4); SetInputParam("epsilon", 0.005); - mlpackMain(); - arma::mat output = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output = params.Get("output"); CheckMatrices(scaled, output); } @@ -134,20 +120,20 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "InverseScalingTest", { std::string method = "zca_whitening"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); - mlpackMain(); - arma::mat scaled = IO::GetParam("output"); + RUN_BINDING(); + arma::mat scaled = params.Get("output"); SetInputParam("input", scaled); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - mlpackMain(); - arma::mat output = IO::GetParam("output"); - CheckMatrices(dataset, output); + RUN_BINDING(); + arma::mat output = params.Get("output"); + CheckMatrices(scaleMainDataset, output); } /** @@ -158,18 +144,18 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "SavedModelTest", { std::string method = "pca_whitening"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); - mlpackMain(); - arma::mat scaled = IO::GetParam("output"); + RUN_BINDING(); + arma::mat scaled = params.Get("output"); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); - mlpackMain(); - arma::mat output = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output = params.Get("output"); CheckMatrices(scaled, output); } @@ -181,20 +167,21 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "EpsilonTest", { std::string method = "pca_whitening"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - mlpackMain(); - arma::mat scaled = IO::GetParam("output"); + RUN_BINDING(); + arma::mat scaled = params.Get("output"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("epsilon", 1.0); - mlpackMain(); - arma::mat output = IO::GetParam("output"); + RUN_BINDING(); + arma::mat output = params.Get("output"); CheckMatricesNotEqual(scaled, output); } @@ -207,11 +194,11 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "InvalidEpsilonTest", { std::string method = "pca_whitening"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); SetInputParam("epsilon", -1.0); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); } /** @@ -222,12 +209,12 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "InvalidRangeTest", { std::string method = "min_max_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); SetInputParam("min_value", 4); SetInputParam("max_value", 2); - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); } /** @@ -238,13 +225,13 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "InvalidScalerTest", { std::string method = "invalid_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", std::move(method)); SetInputParam("min_value", 4); SetInputParam("max_value", 2); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -256,15 +243,15 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "StandardScalerBindingTest", { std::string method = "standard_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); } /** @@ -275,15 +262,15 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "MaxAbsScalerBindingTest", { std::string method = "max_abs_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); } /** @@ -294,17 +281,17 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "MinMaxScalerBindingTest", { std::string method = "min_max_scaler"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); SetInputParam("min_value", 2); SetInputParam("max_value", 4); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); } /** @@ -315,16 +302,16 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "PCAScalerBindingTest", { std::string method = "pca_whitening"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); SetInputParam("epsilon", 1.0); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); } /** @@ -335,16 +322,16 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "ZCAScalerBindingTest", { std::string method = "zca_whitening"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); SetInputParam("epsilon", 1.0); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); } /** @@ -355,13 +342,13 @@ TEST_CASE_METHOD(PreprocessScaleTestFixture, "MeanNormalizationBindingTest", { std::string method = "mean_normalization"; // Input custom data points. - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("scaler_method", method); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); SetInputParam("scaler_method", std::move(method)); - SetInputParam("input", dataset); + SetInputParam("input", scaleMainDataset); SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); SetInputParam("inverse_scaling", true); - REQUIRE_NOTHROW(mlpackMain()); + REQUIRE_NOTHROW(RUN_BINDING()); } diff --git a/src/mlpack/tests/main_tests/preprocess_split_test.cpp b/src/mlpack/tests/main_tests/preprocess_split_test.cpp index 40e6296197..5ff203ce9a 100644 --- a/src/mlpack/tests/main_tests/preprocess_split_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_split_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/preprocess_split_test.cpp * @author Manish Kumar * - * Test mlpackMain() of preprocess_split_main.cpp. + * Test RUN_BINDING() of preprocess_split_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 @@ -12,35 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "PreprocessSplit"; - #include #include -#include "test_helper.hpp" +#include "main_test_fixture.hpp" + #include "../test_catch_tools.hpp" #include "../catch.hpp" -#include - using namespace mlpack; -struct PreprocessSplitTestFixture -{ - public: - PreprocessSplitTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~PreprocessSplitTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(PreprocessSplitTestFixture); /** * Check that desired output dimensions are received for both input data and @@ -68,18 +50,18 @@ TEST_CASE_METHOD(PreprocessSplitTestFixture, "PreprocessSplitDimensionTest", // Input test_ratio. SetInputParam("test_ratio", (double) 0.1); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == + REQUIRE(params.Get("training").n_cols == std::ceil(0.9 * inputSize)); - REQUIRE(IO::GetParam("test").n_cols == + REQUIRE(params.Get("test").n_cols == std::floor(0.1 * inputSize)); REQUIRE( - IO::GetParam>("training_labels").n_cols == + params.Get>("training_labels").n_cols == std::ceil(0.9 * labelSize)); - REQUIRE(IO::GetParam>("test_labels").n_cols == + REQUIRE(params.Get>("test_labels").n_cols == std::floor(0.1 * labelSize)); } @@ -106,12 +88,12 @@ TEST_CASE_METHOD( // Input test_ratio. SetInputParam("test_ratio", (double) 0.1); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == + REQUIRE(params.Get("training").n_cols == std::ceil(0.9 * inputSize)); - REQUIRE(IO::GetParam("test").n_cols == + REQUIRE(params.Get("test").n_cols == std::floor(0.1 * inputSize)); } @@ -136,7 +118,7 @@ TEST_CASE_METHOD(PreprocessSplitTestFixture, "PreprocessSplitTestRatioTest", SetInputParam("test_ratio", (double) -0.2); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -165,16 +147,16 @@ TEST_CASE_METHOD( SetInputParam("test_ratio", (double) 0.0); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == + REQUIRE(params.Get("training").n_cols == (arma::uword) inputSize); - REQUIRE(IO::GetParam("test").n_cols == 0); + REQUIRE(params.Get("test").n_cols == 0); - REQUIRE(IO::GetParam>("training_labels").n_cols == + REQUIRE(params.Get>("training_labels").n_cols == (arma::uword) labelSize); - REQUIRE(IO::GetParam>("test_labels").n_cols == 0); + REQUIRE(params.Get>("test_labels").n_cols == 0); } /** @@ -202,14 +184,14 @@ TEST_CASE_METHOD( SetInputParam("test_ratio", (double) 1.0); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == 0); - REQUIRE(IO::GetParam("test").n_cols == (arma::uword) inputSize); + REQUIRE(params.Get("training").n_cols == 0); + REQUIRE(params.Get("test").n_cols == (arma::uword) inputSize); - REQUIRE(IO::GetParam>("training_labels").n_cols == 0); - REQUIRE(IO::GetParam>("test_labels").n_cols == + REQUIRE(params.Get>("training_labels").n_cols == 0); + REQUIRE(params.Get>("test_labels").n_cols == (arma::uword) labelSize); } @@ -234,16 +216,16 @@ TEST_CASE_METHOD( // Input test_ratio. SetInputParam("test_ratio", (double) 0.1); SetInputParam("no_shuffle", true); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == + REQUIRE(params.Get("training").n_cols == std::ceil(0.9 * inputSize)); - REQUIRE(IO::GetParam("test").n_cols == + REQUIRE(params.Get("test").n_cols == std::floor(0.1 * inputSize)); - arma::mat concat = arma::join_rows(IO::GetParam("training"), - IO::GetParam("test")); + arma::mat concat = arma::join_rows(params.Get("training"), + params.Get("test")); CheckMatrices(inputData, concat); } @@ -274,16 +256,16 @@ TEST_CASE_METHOD( SetInputParam("test_ratio", (double) 0.0); SetInputParam("stratify_data", true); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == + REQUIRE(params.Get("training").n_cols == (arma::uword) inputSize); - REQUIRE(IO::GetParam("test").n_cols == 0); + REQUIRE(params.Get("test").n_cols == 0); - REQUIRE(IO::GetParam>("training_labels").n_cols == + REQUIRE(params.Get>("training_labels").n_cols == (arma::uword) labelSize); - REQUIRE(IO::GetParam>("test_labels").n_cols == 0); + REQUIRE(params.Get>("test_labels").n_cols == 0); } /** @@ -313,14 +295,14 @@ TEST_CASE_METHOD( SetInputParam("test_ratio", (double) 1.0); SetInputParam("stratify_data", true); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == 0); - REQUIRE(IO::GetParam("test").n_cols == (arma::uword) inputSize); + REQUIRE(params.Get("training").n_cols == 0); + REQUIRE(params.Get("test").n_cols == (arma::uword) inputSize); - REQUIRE(IO::GetParam>("training_labels").n_cols == 0); - REQUIRE(IO::GetParam>("test_labels").n_cols == + REQUIRE(params.Get>("training_labels").n_cols == 0); + REQUIRE(params.Get>("test_labels").n_cols == (arma::uword) labelSize); } @@ -354,24 +336,24 @@ TEST_CASE_METHOD( SetInputParam("test_ratio", (double) 0.3); SetInputParam("stratify_data", true); - mlpackMain(); + RUN_BINDING(); // Now check that the output has desired dimensions. - REQUIRE(IO::GetParam("training").n_cols == 145); - REQUIRE(IO::GetParam("test").n_cols == 62); + REQUIRE(params.Get("training").n_cols == 145); + REQUIRE(params.Get("test").n_cols == 62); // Checking for specific label counts in the output. REQUIRE(static_cast(find( - IO::GetParam>("training_labels") == 0)).n_rows == 28); + params.Get>("training_labels") == 0)).n_rows == 28); REQUIRE(static_cast(find( - IO::GetParam>("training_labels") == 1)).n_rows == 70); + params.Get>("training_labels") == 1)).n_rows == 70); REQUIRE(static_cast(find( - IO::GetParam>("training_labels") == 2)).n_rows == 47); + params.Get>("training_labels") == 2)).n_rows == 47); REQUIRE(static_cast(find( - IO::GetParam>("test_labels") == 0)).n_rows == 12); + params.Get>("test_labels") == 0)).n_rows == 12); REQUIRE(static_cast(find( - IO::GetParam>("test_labels") == 1)).n_rows == 30); + params.Get>("test_labels") == 1)).n_rows == 30); REQUIRE(static_cast(find( - IO::GetParam>("test_labels") == 2)).n_rows == 20); + params.Get>("test_labels") == 2)).n_rows == 20); } diff --git a/src/mlpack/tests/main_tests/radical_test.cpp b/src/mlpack/tests/main_tests/radical_test.cpp index 56e3f4c28d..0f1770a274 100644 --- a/src/mlpack/tests/main_tests/radical_test.cpp +++ b/src/mlpack/tests/main_tests/radical_test.cpp @@ -2,43 +2,26 @@ * @file tests/main_tests/radical_test.cpp * @author Manish Kumar * - * Test mlpackMain() of radical_main.cpp. + * Test RUN_BINDING() of radical_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "Radical"; #include #include -#include "test_helper.hpp" #include +#include "main_test_fixture.hpp" + #include "../catch.hpp" using namespace mlpack; -struct RadicalTestFixture -{ - public: - RadicalTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~RadicalTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(RadicalTestFixture); /** * Check that output Y and W matrix have valid dimensions. @@ -50,15 +33,15 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalOutputDimensionTest", SetInputParam("input", std::move(input)); - mlpackMain(); + RUN_BINDING(); // Check dimension of Y matrix. - REQUIRE(IO::GetParam("output_ic").n_rows == 5); - REQUIRE(IO::GetParam("output_ic").n_cols == 3); + REQUIRE(params.Get("output_ic").n_rows == 5); + REQUIRE(params.Get("output_ic").n_cols == 3); // Check dimension of W matrix. - REQUIRE(IO::GetParam("output_unmixing").n_rows == 5); - REQUIRE(IO::GetParam("output_unmixing").n_cols == 5); + REQUIRE(params.Get("output_unmixing").n_rows == 5); + REQUIRE(params.Get("output_unmixing").n_cols == 5); } /** @@ -76,10 +59,11 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalBoundsTest", SetInputParam("replicates", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Test for noise_std_dev. @@ -87,10 +71,11 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalBoundsTest", SetInputParam("noise_std_dev", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Test for angles. @@ -98,10 +83,11 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalBoundsTest", SetInputParam("angles", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Test for sweeps. @@ -109,7 +95,7 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalBoundsTest", SetInputParam("sweeps", (int) -2); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -129,20 +115,21 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalDiffNoiseStdDevTest", SetInputParam("input", input); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::mat Y = IO::GetParam("output_ic"); + arma::mat Y = params.Get("output_ic"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(input)); SetInputParam("noise_std_dev", (double) 0.01); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output and final output using two models are different. - REQUIRE(arma::accu(Y == IO::GetParam("output_ic")) < Y.n_elem); + REQUIRE(arma::accu(Y == params.Get("output_ic")) < Y.n_elem); } /** @@ -160,20 +147,21 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalDiffReplicatesTest", SetInputParam("input", input); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::mat Y = IO::GetParam("output_ic"); + arma::mat Y = params.Get("output_ic"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(input)); SetInputParam("replicates", (int) 10); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output and final output using two models are different. - REQUIRE(arma::accu(Y == IO::GetParam("output_ic")) < Y.n_elem); + REQUIRE(arma::accu(Y == params.Get("output_ic")) < Y.n_elem); } /** @@ -191,20 +179,21 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalDiffAnglesTest", SetInputParam("input", input); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::mat Y = IO::GetParam("output_ic"); + arma::mat Y = params.Get("output_ic"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("input", std::move(input)); SetInputParam("angles", (int) 20); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output and final output using two models are different. - REQUIRE(arma::accu(Y == IO::GetParam("output_ic")) < Y.n_elem); + REQUIRE(arma::accu(Y == params.Get("output_ic")) < Y.n_elem); } /** @@ -222,18 +211,20 @@ TEST_CASE_METHOD(RadicalTestFixture, "RadicalDiffSweepsTest", SetInputParam("input", input); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); - arma::mat Y = IO::GetParam("output_ic"); + arma::mat Y = params.Get("output_ic"); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); + ResetSettings(); SetInputParam("input", std::move(input)); SetInputParam("sweeps", (int) 2); mlpack::math::FixedRandomSeed(); - mlpackMain(); + RUN_BINDING(); // Check that initial output and final output using two models are different. - REQUIRE(arma::accu(Y == IO::GetParam("output_ic")) < Y.n_elem); + REQUIRE(arma::accu(Y == params.Get("output_ic")) < Y.n_elem); } diff --git a/src/mlpack/tests/main_tests/random_forest_test.cpp b/src/mlpack/tests/main_tests/random_forest_test.cpp index eea8d696bb..0aa75df31e 100644 --- a/src/mlpack/tests/main_tests/random_forest_test.cpp +++ b/src/mlpack/tests/main_tests/random_forest_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/random_forest_test.cpp * @author Manish Kumar * - * Test mlpackMain() of random_forest_main.cpp. + * Test RUN_BINDING() of random_forest_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 @@ -12,33 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "RandomForest"; - #include #include -#include "test_helper.hpp" + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct RandomForestTestFixture -{ - public: - RandomForestTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~RandomForestTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(RandomForestTestFixture); /** * Check that number of output points and number of input @@ -68,16 +52,16 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestOutputDimensionTest", // Input test data. SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predictions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 3); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 3); } /** @@ -107,37 +91,37 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestModelReuseTest", // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::Row predictions; arma::mat probabilities; - predictions = std::move(IO::GetParam>("predictions")); - probabilities = std::move(IO::GetParam("probabilities")); + predictions = std::move(params.Get>("predictions")); + probabilities = std::move(params.Get("probabilities")); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + RandomForestModel* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input trained model. SetInputParam("test", std::move(testData)); - SetInputParam("input_model", - IO::GetParam("output_model")); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); - REQUIRE(IO::GetParam("probabilities").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); + REQUIRE(params.Get("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predicitions. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); - REQUIRE(IO::GetParam("probabilities").n_rows == 3); + REQUIRE(params.Get>("predictions").n_rows == 1); + REQUIRE(params.Get("probabilities").n_rows == 3); // Check that initial predictions and predictions using saved model are same. - CheckMatrices(predictions, IO::GetParam>("predictions")); - CheckMatrices(probabilities, IO::GetParam("probabilities")); + CheckMatrices(predictions, params.Get>("predictions")); + CheckMatrices(probabilities, params.Get("probabilities")); } /** @@ -157,7 +141,7 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestNumOfTreesTest", SetInputParam("num_trees", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -178,7 +162,7 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestMinimumLeafSizeTest", SetInputParam("minimum_leaf_size", (int) 0); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -199,7 +183,7 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestMaximumDepthTest", SetInputParam("maximum_depth", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -222,14 +206,14 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingVerTest", SetInputParam("training", std::move(inputData)); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Input pre-trained model. SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -270,14 +254,15 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMinLeafSizeTest", SetInputParam("labels", labels); SetInputParam("minimum_leaf_size", (int) 20); - mlpackMain(); + RUN_BINDING(); // Calculate training accuracy. RandomForestModel* rf1 = - std::move(IO::GetParam("output_model")); - IO::GetParam("output_model") = NULL; + std::move(params.Get("output_model")); + params.Get("output_model") = NULL; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train for minimum leaf size 10. @@ -286,13 +271,14 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMinLeafSizeTest", SetInputParam("labels", labels); SetInputParam("minimum_leaf_size", (int) 10); - mlpackMain(); + RUN_BINDING(); RandomForestModel* rf2 = - std::move(IO::GetParam("output_model")); - IO::GetParam("output_model") = NULL; + std::move(params.Get("output_model")); + params.Get("output_model") = NULL; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train for minimum leaf size 1. @@ -301,11 +287,11 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMinLeafSizeTest", SetInputParam("labels", labels); SetInputParam("minimum_leaf_size", (int) 1); - mlpackMain(); + RUN_BINDING(); RandomForestModel* rf3 = - std::move(IO::GetParam("output_model")); - IO::GetParam("output_model") = NULL; + std::move(params.Get("output_model")); + params.Get("output_model") = NULL; // Check that each tree is different. for (size_t i = 0; i < rf1->rf.NumTrees(); ++i) @@ -349,12 +335,13 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffNumTreeTest", SetInputParam("num_trees", (int) 1); SetInputParam("minimum_leaf_size", (int) 1); - mlpackMain(); + RUN_BINDING(); const size_t numTrees1 = - IO::GetParam("output_model")->rf.NumTrees(); + params.Get("output_model")->rf.NumTrees(); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train for num_trees 5. @@ -364,12 +351,13 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffNumTreeTest", SetInputParam("num_trees", (int) 5); SetInputParam("minimum_leaf_size", (int) 1); - mlpackMain(); + RUN_BINDING(); const size_t numTrees2 = - IO::GetParam("output_model")->rf.NumTrees(); + params.Get("output_model")->rf.NumTrees(); - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train for num_trees 10. @@ -379,10 +367,10 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffNumTreeTest", SetInputParam("num_trees", (int) 10); SetInputParam("minimum_leaf_size", (int) 1); - mlpackMain(); + RUN_BINDING(); const size_t numTrees3 = - IO::GetParam("output_model")->rf.NumTrees(); + params.Get("output_model")->rf.NumTrees(); REQUIRE(numTrees1 != numTrees2); REQUIRE(numTrees2 != numTrees3); @@ -408,27 +396,29 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMaxDepthTest", SetInputParam("labels", labels); SetInputParam("maximum_depth", (int) 1); - mlpackMain(); + RUN_BINDING(); // Calculate training accuracy. RandomForestModel* rf1 = - std::move(IO::GetParam("output_model")); - IO::GetParam("output_model") = NULL; + std::move(params.Get("output_model")); + params.Get("output_model") = NULL; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Input training data. SetInputParam("training", inputData); SetInputParam("labels", labels); SetInputParam("maximum_depth", (int) 2); - mlpackMain(); + RUN_BINDING(); RandomForestModel* rf2 = - std::move(IO::GetParam("output_model")); - IO::GetParam("output_model") = NULL; + std::move(params.Get("output_model")); + params.Get("output_model") = NULL; - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); // Train for minimum leaf size 1. @@ -437,11 +427,11 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestDiffMaxDepthTest", SetInputParam("labels", labels); SetInputParam("maximum_depth", (int) 3); - mlpackMain(); + RUN_BINDING(); RandomForestModel* rf3 = - std::move(IO::GetParam("output_model")); - IO::GetParam("output_model") = NULL; + std::move(params.Get("output_model")); + params.Get("output_model") = NULL; // Check that each tree is different. for (size_t i = 0; i < rf1->rf.NumTrees(); ++i) @@ -474,13 +464,13 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestTrainingModelWarmStart", SetInputParam("training", std::move(inputData)); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Setting warm_start flag. SetInputParam("warm_start", false); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -503,11 +493,11 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart", SetInputParam("training", inputData); SetInputParam("labels", labels); - mlpackMain(); + RUN_BINDING(); // Old number of trees in the model. size_t oldNumTrees = - IO::GetParam("output_model")->rf.NumTrees(); + params.Get("output_model")->rf.NumTrees(); // Input training data. SetInputParam("training", std::move(inputData)); @@ -516,12 +506,12 @@ TEST_CASE_METHOD(RandomForestTestFixture, "RandomForestWarmStart", // Input pre-trained model. SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); - mlpackMain(); + RUN_BINDING(); size_t newNumTrees = - IO::GetParam("output_model")->rf.NumTrees(); + params.Get("output_model")->rf.NumTrees(); REQUIRE(oldNumTrees + 10 == newNumTrees); } diff --git a/src/mlpack/tests/main_tests/range_search_test.cpp b/src/mlpack/tests/main_tests/range_search_test.cpp index c7c6ce9596..ffcf798bc6 100644 --- a/src/mlpack/tests/main_tests/range_search_test.cpp +++ b/src/mlpack/tests/main_tests/range_search_test.cpp @@ -2,42 +2,26 @@ * @file tests/main_tests/range_search_test.cpp * @author Niteya Shah * - * Test mlpackMain() of range_search_main.cpp. + * Test RUN_BINDING() of range_search_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "RangeSearchMain"; #include #include -#include "test_helper.hpp" #include + #include "range_search_utils.hpp" +#include "main_test_fixture.hpp" #include "../catch.hpp" using namespace mlpack; -struct RangeSearchTestFixture -{ - public: - RangeSearchTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - ~RangeSearchTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(RangeSearchTestFixture); /** * Check that we have to specify a reference set or input model. @@ -46,7 +30,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchNoReference", "[RangeSearchMainTest][BindingTests]") { Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -83,13 +67,21 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchInputModelNoQuery", SetInputParam("distances_file", distanceFile); SetInputParam("neighbors_file", neighborsFile); - mlpackMain(); + RUN_BINDING(); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; - SetInputParam("input_model", move(IO::GetParam("output_model"))); + RSModel* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); + + SetInputParam("input_model", m); + SetInputParam("min", minVal); + SetInputParam("max", maxVal); + SetInputParam("distances_file", distanceFile); + SetInputParam("neighbors_file", neighborsFile); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; remove(neighborsFile.c_str()); @@ -118,7 +110,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchDifferentTree", SetInputParam("tree_type", wrongTreeType); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; remove(neighborsFile.c_str()); @@ -148,13 +140,13 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchBothReferenceAndModel", SetInputParam("neighbors_file", neighborsFile); SetInputParam("query", queryData); - mlpackMain(); + RUN_BINDING(); - SetInputParam("input_model", move(IO::GetParam("output_model"))); + SetInputParam("input_model", move(params.Get("output_model"))); SetInputParam("query", move(queryData)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; remove(neighborsFile.c_str()); @@ -198,7 +190,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchTest", SetInputParam("distances_file", distanceFile); SetInputParam("neighbors_file", neighborsFile); - mlpackMain(); + RUN_BINDING(); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); @@ -243,7 +235,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSeachTestwithQuery", SetInputParam("distances_file", distanceFile); SetInputParam("neighbors_file", neighborsFile); - mlpackMain(); + RUN_BINDING(); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); @@ -281,18 +273,21 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "ModelCheck", SetInputParam("neighbors_file", neighborsFile); SetInputParam("query", queryData); - mlpackMain(); + RUN_BINDING(); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); - RSModel* outputModel = IO::GetParam("output_model"); - IO::GetSingleton().Parameters()["reference"].wasPassed = false; + RSModel* outputModel = params.Get("output_model"); + params.Get("output_model") = NULL; + + CleanMemory(); + ResetSettings(); SetInputParam("input_model", outputModel); SetInputParam("query", move(queryData)); - mlpackMain(); + RUN_BINDING(); neighborsTemp = ReadData(neighborsFile); distancetemp = ReadData(distanceFile); @@ -301,7 +296,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "ModelCheck", CheckMatrices(distances, distancetemp); REQUIRE(ModelToString(outputModel) == - ModelToString(IO::GetParam("output_model"))); + ModelToString(params.Get("output_model"))); remove(neighborsFile.c_str()); remove(distanceFile.c_str()); @@ -335,9 +330,9 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "LeafValueTesting", SetInputParam("leaf_size", leafSizes[0]); // The default leaf size is 20. - mlpackMain(); + RUN_BINDING(); - RSModel* outputModel1 = IO::GetParam("output_model"); + RSModel* outputModel1 = params.Get("output_model"); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); @@ -350,7 +345,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "LeafValueTesting", SetInputParam("distances_file", distanceFile); SetInputParam("neighbors_file", neighborsFile); - mlpackMain(); + RUN_BINDING(); neighborsTemp = ReadData(neighborsFile); distancestemp = ReadData(distanceFile); @@ -359,10 +354,10 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "LeafValueTesting", CheckMatrices(distances, distancestemp); REQUIRE(ModelToString(outputModel1) != - ModelToString(IO::GetParam("output_model"))); + ModelToString(params.Get("output_model"))); if (i != leafSizes.size() - 1) - delete IO::GetParam("output_model"); + delete params.Get("output_model"); } delete outputModel1; @@ -404,11 +399,11 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "TreeTypeTesting", SetInputParam("reference", inputData); SetInputParam("query", queryData); - mlpackMain(); + RUN_BINDING(); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); - RSModel* outputModel1 = IO::GetParam("output_model"); + RSModel* outputModel1 = params.Get("output_model"); for (size_t i = 1; i < trees.size(); ++i) { @@ -425,7 +420,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "TreeTypeTesting", SetInputParam("reference", inputData); SetInputParam("tree_type", trees[i]); - mlpackMain(); + RUN_BINDING(); neighborsTemp = ReadData(neighborsFile); distancestemp = ReadData(distanceFile); @@ -433,10 +428,10 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "TreeTypeTesting", CheckMatrices(neighbors, neighborsTemp); CheckMatrices(distances, distancestemp); REQUIRE(ModelToString(outputModel1) != - ModelToString(IO::GetParam("output_model"))); + ModelToString(params.Get("output_model"))); if (i != trees.size() - 1) - delete IO::GetParam("output_model"); + delete params.Get("output_model"); } delete outputModel1; @@ -468,9 +463,9 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RandomBasisTesting", SetInputParam("neighbors_file", neighborsFile); SetInputParam("reference", inputData); - mlpackMain(); + RUN_BINDING(); - RSModel* outputModel = move(IO::GetParam("output_model")); + RSModel* outputModel = move(params.Get("output_model")); SetInputParam("min", minVal); SetInputParam("max", maxVal); @@ -479,10 +474,10 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RandomBasisTesting", SetInputParam("reference", inputData); SetInputParam("random_basis", true); - mlpackMain(); + RUN_BINDING(); REQUIRE(ModelToString(outputModel) != - ModelToString(IO::GetParam("output_model"))); + ModelToString(params.Get("output_model"))); delete outputModel; @@ -515,11 +510,11 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "NaiveModeTest", SetInputParam("neighbors_file", neighborsFile); SetInputParam("reference", inputData); - mlpackMain(); + RUN_BINDING(); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); - RSModel* outputModel = move(IO::GetParam("output_model")); + RSModel* outputModel = move(params.Get("output_model")); SetInputParam("min", minVal); SetInputParam("max", maxVal); @@ -528,7 +523,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "NaiveModeTest", SetInputParam("reference", inputData); SetInputParam("naive", true); - mlpackMain(); + RUN_BINDING(); neighborsTemp = ReadData(neighborsFile); distancestemp = ReadData(distanceFile); @@ -537,7 +532,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "NaiveModeTest", CheckMatrices(distances, distancestemp); REQUIRE(ModelToString(outputModel) != - ModelToString(IO::GetParam("output_model"))); + ModelToString(params.Get("output_model"))); delete outputModel; @@ -570,11 +565,11 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "SingleModeTest", SetInputParam("neighbors_file", neighborsFile); SetInputParam("reference", inputData); - mlpackMain(); + RUN_BINDING(); neighbors = ReadData(neighborsFile); distances = ReadData(distanceFile); - RSModel* outputModel = move(IO::GetParam("output_model")); + RSModel* outputModel = move(params.Get("output_model")); SetInputParam("min", minVal); SetInputParam("max", maxVal); @@ -583,7 +578,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "SingleModeTest", SetInputParam("reference", inputData); SetInputParam("single_mode", true); - mlpackMain(); + RUN_BINDING(); neighborsTemp = ReadData(neighborsFile); distancestemp = ReadData(distanceFile); @@ -591,7 +586,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "SingleModeTest", CheckMatrices(neighbors, neighborsTemp); CheckMatrices(distances, distancestemp); REQUIRE(ModelToString(outputModel) != - ModelToString(IO::GetParam("output_model"))); + ModelToString(params.Get("output_model"))); delete outputModel; diff --git a/src/mlpack/tests/main_tests/softmax_regression_test.cpp b/src/mlpack/tests/main_tests/softmax_regression_test.cpp index 5f64c7a315..5dea07ca49 100644 --- a/src/mlpack/tests/main_tests/softmax_regression_test.cpp +++ b/src/mlpack/tests/main_tests/softmax_regression_test.cpp @@ -2,7 +2,7 @@ * @file tests/main_tests/softmax_regression_test.cpp * @author Manish Kumar * - * Test mlpackMain() of softmax_regression_main.cpp. + * Test RUN_BINDING() of softmax_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 @@ -12,33 +12,17 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -static const std::string testName = "SoftmaxRegression"; - #include #include -#include "test_helper.hpp" + +#include "main_test_fixture.hpp" #include "../test_catch_tools.hpp" #include "../catch.hpp" using namespace mlpack; -struct SoftmaxRegressionTestFixture -{ - public: - SoftmaxRegressionTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~SoftmaxRegressionTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(SoftmaxRegressionTestFixture); /** * Ensure that we get desired dimensions when both training @@ -77,13 +61,13 @@ TEST_CASE_METHOD( // Input test data. SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); // Check prediction have only single row. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); } /** @@ -102,7 +86,7 @@ TEST_CASE_METHOD( SetInputParam("training", std::move(inputData)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -142,32 +126,32 @@ TEST_CASE_METHOD( // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); arma::Row predictions; - predictions = std::move(IO::GetParam>("predictions")); + predictions = std::move(params.Get>("predictions")); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + SoftmaxRegression* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Input trained model. SetInputParam("test", std::move(testData)); - SetInputParam("input_model", - IO::GetParam("output_model")); + SetInputParam("input_model", m); - mlpackMain(); + RUN_BINDING(); // Check that number of output points are equal to number of input points. - REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(params.Get>("predictions").n_cols == testSize); // Check predictions have only single row. - REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(params.Get>("predictions").n_rows == 1); // Check that initial predictions and final predicitons matrix // using saved model are same. - CheckMatrices(predictions, IO::GetParam>("predictions")); + CheckMatrices(predictions, params.Get>("predictions")); } /** @@ -195,7 +179,7 @@ TEST_CASE_METHOD( SetInputParam("max_iterations", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -224,7 +208,7 @@ TEST_CASE_METHOD( SetInputParam("lambda", (double) -0.1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -254,7 +238,7 @@ TEST_CASE_METHOD( SetInputParam("number_of_classes", (int) -1); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -282,14 +266,14 @@ TEST_CASE_METHOD( SetInputParam("training", std::move(inputData)); SetInputParam("labels", std::move(labels)); - mlpackMain(); + RUN_BINDING(); // Input pre-trained model. SetInputParam("input_model", - IO::GetParam("output_model")); + params.Get("output_model")); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -330,18 +314,15 @@ TEST_CASE_METHOD( // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store output parameters. arma::mat modelParam; - modelParam = IO::GetParam("output_model")->Parameters(); - - bindings::tests::CleanMemory(); + modelParam = params.Get("output_model")->Parameters(); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Train SR for lamda 0.9. @@ -351,14 +332,14 @@ TEST_CASE_METHOD( SetInputParam("lambda", (double) 0.9); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial parameters and final parameters matrix // using saved model are different. for (size_t i = 0; i < modelParam.n_elem; ++i) { REQUIRE(modelParam[i] != - IO::GetParam("output_model")->Parameters()[i]); + params.Get("output_model")->Parameters()[i]); } } @@ -399,18 +380,15 @@ TEST_CASE_METHOD( // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store output parameters. arma::mat modelParam; - modelParam = IO::GetParam("output_model")->Parameters(); - - bindings::tests::CleanMemory(); + modelParam = params.Get("output_model")->Parameters(); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Train SR for lamda 0.9. @@ -420,14 +398,14 @@ TEST_CASE_METHOD( SetInputParam("max_iterations", (int) 1000); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial parameters and final parameters matrix // using saved model are different. for (size_t i = 0; i < modelParam.n_elem; ++i) { REQUIRE(modelParam[i] != - IO::GetParam("output_model")->Parameters()[i]); + params.Get("output_model")->Parameters()[i]); } } @@ -468,19 +446,15 @@ TEST_CASE_METHOD( // Input test data. SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store output parameters. arma::mat modelParam; - modelParam = IO::GetParam("output_model")->Parameters(); - - bindings::tests::CleanMemory(); + modelParam = params.Get("output_model")->Parameters(); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; - IO::GetSingleton().Parameters()["labels"].wasPassed = false; - IO::GetSingleton().Parameters()["no_intercept"].wasPassed = false; - IO::GetSingleton().Parameters()["test"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Train SR for no_intercept. @@ -489,11 +463,11 @@ TEST_CASE_METHOD( SetInputParam("labels", std::move(labels)); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial parameters has 1 more parameter than // final parameters matrix. REQUIRE( - IO::GetParam("output_model")->Parameters().n_cols == + params.Get("output_model")->Parameters().n_cols == modelParam.n_cols + 1); } diff --git a/src/mlpack/tests/main_tests/sparse_coding_test.cpp b/src/mlpack/tests/main_tests/sparse_coding_test.cpp index 49eedb92b8..ac6e4aa3c5 100644 --- a/src/mlpack/tests/main_tests/sparse_coding_test.cpp +++ b/src/mlpack/tests/main_tests/sparse_coding_test.cpp @@ -2,44 +2,27 @@ * @file tests/main_tests/sparse_coding_test.cpp * @author Manish Kumar * - * Test mlpackMain() of sparse_coding_main.cpp. + * Test RUN_BINDING() of sparse_coding_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. */ -#include - #define BINDING_TYPE BINDING_TYPE_TEST -static const std::string testName = "SparseCoding"; #include #include #include -#include "test_helper.hpp" + +#include "main_test_fixture.hpp" #include "../catch.hpp" #include "../test_catch_tools.hpp" using namespace mlpack; -struct SparseCodingTestFixture -{ - public: - SparseCodingTestFixture() - { - // Cache in the options for this program. - IO::RestoreSettings(testName); - } - - ~SparseCodingTestFixture() - { - // Clear the settings. - bindings::tests::CleanMemory(); - IO::ClearSettings(); - } -}; +BINDING_TEST_FIXTURE(SparseCodingTestFixture); /** * Helper function to load datasets. @@ -74,21 +57,21 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingOutputDimensionTest", SetInputParam("max_iterations", (int) 100); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output dictionary points are equals number of atoms. - REQUIRE(IO::GetParam("dictionary").n_cols == 2); + REQUIRE(params.Get("dictionary").n_cols == 2); // Check that number of output dictionary rows equal number of input rows // which equal 4 for each data point. - REQUIRE(IO::GetParam("dictionary").n_rows == 4); + REQUIRE(params.Get("dictionary").n_rows == 4); // Check that number of output points are equal to number of test points. // Test file contains 63 data points. - REQUIRE(IO::GetParam("codes").n_cols == 63); + REQUIRE(params.Get("codes").n_cols == 63); // Check that number of output codes rows equal number of atoms. - REQUIRE(IO::GetParam("codes").n_rows == 2); + REQUIRE(params.Get("codes").n_rows == 2); } /** @@ -114,18 +97,17 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingNormalizationTest", SetInputParam("normalize", (bool) true); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for normalization set to false. // Reset passed parameters. - bindings::tests::CleanMemory(); - IO::GetSingleton().Parameters()["normalize"].wasPassed = false; + CleanMemory(); + ResetSettings(); // Normalize train dataset. for (size_t i = 0; i < inputData.n_cols; ++i) @@ -142,12 +124,12 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingNormalizationTest", SetInputParam("max_iterations", (int) 100); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are same. - CheckMatrices(dictionary, IO::GetParam("dictionary")); - CheckMatrices(codes, IO::GetParam("codes")); + CheckMatrices(dictionary, params.Get("dictionary")); + CheckMatrices(codes, params.Get("codes")); } /** @@ -170,55 +152,59 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingBoundsTest", SetInputParam("lambda1", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Test for L2 value. // Input training data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", inputData); SetInputParam("atoms", (int) 10); SetInputParam("lambda2", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Test for max_iterations. // Input training data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", inputData); SetInputParam("atoms", (int) 10); SetInputParam("max_iterations", (int) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Test for objective_tolerance. // Input training data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", inputData); SetInputParam("atoms", (int) 10); SetInputParam("objective_tolerance", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Test for newton_tolerance. // Input training data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", inputData); SetInputParam("atoms", (int) 10); SetInputParam("newton_tolerance", (double) -1.0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; // Test for atoms. @@ -228,7 +214,7 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingBoundsTest", SetInputParam("atoms", (int) 0); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -246,7 +232,7 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingReqAtomsTest", SetInputParam("training", std::move(inputData)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -269,7 +255,7 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingModelVerTest", SetInputParam("initial_dictionary", std::move(initialDictionary)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -293,7 +279,7 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingAtomsVerTest", SetInputParam("max_iterations", (int) 100); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -321,7 +307,7 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingRowsVerTest", SetInputParam("normalize", (bool) true); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -348,7 +334,7 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDataDimensionalityTest", SetInputParam("test", std::move(testData)); Log::Fatal.ignoreInput = true; - REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -369,45 +355,46 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingModelReuseTest", SetInputParam("normalize", (bool) true); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = - std::move(IO::GetParam("dictionary")); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = std::move(params.Get("dictionary")); + arma::mat codes = std::move(params.Get("codes")); // Reset passed parameters. - IO::GetSingleton().Parameters()["training"].wasPassed = false; + SparseCoding* m = params.Get("output_model"); + params.Get("output_model") = NULL; + CleanMemory(); + ResetSettings(); // Test the correctness of trained model. // Input data. SetInputParam("max_iterations", (int) 100); - SetInputParam("input_model", IO::GetParam("output_model")); + SetInputParam("input_model", m); SetInputParam("normalize", (bool) true); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that number of output dictionary points are equals number of atoms. - REQUIRE(IO::GetParam("dictionary").n_cols == 2); + REQUIRE(params.Get("dictionary").n_cols == 2); // Check that number of output dictionary rows equal number of input rows // which equal 4 for each data point. - REQUIRE(IO::GetParam("dictionary").n_rows == 4); + REQUIRE(params.Get("dictionary").n_rows == 4); // Check that number of output points are equal to number of test points. // Test file contains 63 data points. - REQUIRE(IO::GetParam("codes").n_cols == 63); + REQUIRE(params.Get("codes").n_cols == 63); // Check that number of output codes rows equal number of atoms. - REQUIRE(IO::GetParam("codes").n_rows == 2); + REQUIRE(params.Get("codes").n_rows == 2); // Check that initial outputs and final outputs // using two models model are same. - CheckMatrices(dictionary, IO::GetParam("dictionary")); - CheckMatrices(codes, IO::GetParam("codes")); + CheckMatrices(dictionary, params.Get("dictionary")); + CheckMatrices(codes, params.Get("codes")); } /** @@ -433,17 +420,17 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffMaxItrTest", SetInputParam("normalize", (bool) true); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for max_iterations equals to 100. // Input data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(inputData)); SetInputParam("atoms", (int) 2); SetInputParam("initial_dictionary", std::move(initialDictionary)); @@ -451,15 +438,15 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffMaxItrTest", SetInputParam("normalize", (bool) true); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are different. REQUIRE(arma::accu(dictionary == - IO::GetParam("dictionary")) < dictionary.n_elem); + params.Get("dictionary")) < dictionary.n_elem); REQUIRE(arma::accu(codes == - IO::GetParam("codes")) < codes.n_elem); + params.Get("codes")) < codes.n_elem); } /** @@ -483,31 +470,31 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffObjToleranceTest", SetInputParam("initial_dictionary", initialDictionary); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for objective_tolerance equals to 10000.0. // Input data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(inputData)); SetInputParam("atoms", (int) 2); SetInputParam("initial_dictionary", std::move(initialDictionary)); SetInputParam("objective_tolerance", (double) 10000.0); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are different. REQUIRE(arma::accu(dictionary == - IO::GetParam("dictionary")) < dictionary.n_elem); + params.Get("dictionary")) < dictionary.n_elem); REQUIRE(arma::accu(codes == - IO::GetParam("codes")) < codes.n_elem); + params.Get("codes")) < codes.n_elem); } /** @@ -532,32 +519,32 @@ TEST_CASE_METHOD(SparseCodingTestFixture, SetInputParam("initial_dictionary", initialDictionary); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for newton_tolerance equals to 10000.0. // Input data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(inputData)); SetInputParam("atoms", (int) 2); SetInputParam("initial_dictionary", std::move(initialDictionary)); SetInputParam("newton_tolerance", (double) 10000.0); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are different. REQUIRE(arma::accu(dictionary == - IO::GetParam("dictionary")) < dictionary.n_elem); + params.Get("dictionary")) < dictionary.n_elem); REQUIRE(arma::accu(codes == - IO::GetParam("codes")) < codes.n_elem); + params.Get("codes")) < codes.n_elem); } /** @@ -581,32 +568,32 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffL1Test", SetInputParam("initial_dictionary", initialDictionary); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for lambda1 equals to 10000.0. // Input data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(inputData)); SetInputParam("atoms", (int) 2); SetInputParam("initial_dictionary", std::move(initialDictionary)); SetInputParam("lambda1", (double) 10000.0); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are different. REQUIRE(arma::accu(dictionary == - IO::GetParam("dictionary")) < dictionary.n_elem); + params.Get("dictionary")) < dictionary.n_elem); REQUIRE(arma::accu(codes == - IO::GetParam("codes")) < codes.n_elem); + params.Get("codes")) < codes.n_elem); } /** @@ -630,32 +617,32 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffL2Test", SetInputParam("initial_dictionary", initialDictionary); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for lambda2 equals to 10000.0. // Input data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(inputData)); SetInputParam("atoms", (int) 2); SetInputParam("initial_dictionary", std::move(initialDictionary)); SetInputParam("lambda2", (double) 10000.0); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are different. REQUIRE(arma::accu(dictionary == - IO::GetParam("dictionary")) < dictionary.n_elem); + params.Get("dictionary")) < dictionary.n_elem); REQUIRE(arma::accu(codes == - IO::GetParam("codes")) < codes.n_elem); + params.Get("codes")) < codes.n_elem); } /** @@ -680,17 +667,17 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffL1L2Test", SetInputParam("initial_dictionary", initialDictionary); SetInputParam("test", testData); - mlpackMain(); + RUN_BINDING(); // Store outputs. - arma::mat dictionary = IO::GetParam("dictionary"); - arma::mat codes = - std::move(IO::GetParam("codes")); + arma::mat dictionary = params.Get("dictionary"); + arma::mat codes = std::move(params.Get("codes")); // Train for lambda1 EQUALS 0.0 & lambda2 equals to 10000.0. // Input data. - bindings::tests::CleanMemory(); + CleanMemory(); + ResetSettings(); SetInputParam("training", std::move(inputData)); SetInputParam("atoms", (int) 2); SetInputParam("initial_dictionary", std::move(initialDictionary)); @@ -698,13 +685,13 @@ TEST_CASE_METHOD(SparseCodingTestFixture, "SparseCodingDiffL1L2Test", SetInputParam("lambda2", (double) 10000.0); SetInputParam("test", std::move(testData)); - mlpackMain(); + RUN_BINDING(); // Check that initial outputs and final outputs // using two models model are different. REQUIRE(arma::accu(dictionary == - IO::GetParam("dictionary")) < dictionary.n_elem); + params.Get("dictionary")) < dictionary.n_elem); REQUIRE(arma::accu(codes == - IO::GetParam("codes")) < codes.n_elem); + params.Get("codes")) < codes.n_elem); } From 8b87f1306e48570be01556f3ca9b46a0635021ec Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sun, 11 Jul 2021 14:51:10 +0530 Subject: [PATCH 533/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 286d0d1183..28303c8c6c 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2195,7 +2195,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") << 31.0980 << 31.7431 << 34.1073 << 37.2050 << 40.3027 << 42.6669 << 43.3120 << arma::endr; expectedOutput.reshape(35, 1); layer.Forward(input, output); - CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); + CheckMatrices(output, expectedOutput, 1e-4); } /** From b061ef44d4c964f5d8d3030cfdccdd0830a03b32 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Mon, 12 Jul 2021 02:22:06 +0530 Subject: [PATCH 534/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 28303c8c6c..1b3850a6c5 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2180,13 +2180,13 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") size_t outRowSize = 5; size_t outColSize = 7; size_t depth = 1; + double alpha = -0.75; input.zeros(inRowSize * inColSize * depth, 1); input[0] = 10.0; input[1] = 20.0; input[2] = 30.0; input[3] = 40.0; - BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, - depth); + BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth, alpha); expectedOutput << 6.6880 << 7.3331 << 9.6973 << 12.7950 << 15.8927 << 18.2569 << 18.9020 << arma::endr << 10.5330 << 11.1781 << 13.5423 << 16.6400 << 19.7377 << 22.1019 << 22.7470 << arma::endr From 42071e92be63221da73a620de5beac0a5c537a9c Mon Sep 17 00:00:00 2001 From: Aakash kaushik Date: Mon, 12 Jul 2021 09:36:46 +0530 Subject: [PATCH 535/729] Addition of ReLU6 (#3009) * relu6 files added * add into layer's cmake * added tests * applied suggestions * comment about torch values in tests --- src/mlpack/methods/ann/layer/CMakeLists.txt | 2 + src/mlpack/methods/ann/layer/layer.hpp | 1 + src/mlpack/methods/ann/layer/layer_types.hpp | 3 + src/mlpack/methods/ann/layer/relu6.hpp | 103 ++++++++++++++++++ src/mlpack/methods/ann/layer/relu6_impl.hpp | 77 +++++++++++++ .../tests/activation_functions_test.cpp | 47 ++++++++ 6 files changed, 233 insertions(+) create mode 100644 src/mlpack/methods/ann/layer/relu6.hpp create mode 100644 src/mlpack/methods/ann/layer/relu6_impl.hpp diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index d1eb91ff55..e5d21d215a 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -99,6 +99,8 @@ set(SOURCES recurrent_attention_impl.hpp reinforce_normal.hpp reinforce_normal_impl.hpp + relu6.hpp + relu6_impl.hpp reparametrization.hpp reparametrization_impl.hpp radial_basis_function.hpp diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index b2f598b985..abc246f7f4 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -64,6 +64,7 @@ #include "recurrent_attention.hpp" #include "recurrent.hpp" #include "reinforce_normal.hpp" +#include "relu6.hpp" #include "reparametrization.hpp" #include "select.hpp" #include "sequential.hpp" diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index e3c97f0d08..4a5a202e67 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ template class FastLSTM; template class VRClassReward; template class Concatenate; template class Padding; +template class ReLU6; template*, RecurrentAttention*, ReinforceNormal*, + ReLU6*, Reparametrization*, Select*, SpatialDropout*, diff --git a/src/mlpack/methods/ann/layer/relu6.hpp b/src/mlpack/methods/ann/layer/relu6.hpp new file mode 100644 index 0000000000..1a9c0a2ff7 --- /dev/null +++ b/src/mlpack/methods/ann/layer/relu6.hpp @@ -0,0 +1,103 @@ +/** + * @file methods/ann/layer/relu6.hpp + * @author Aakash kaushik + * + * For more information, kindly refer to the following paper. + * + * @code + * @article{Andrew G2017, + * author = {Andrew G. Howard, Menglong Zhu, Bo Chen, Dmitry Kalenichenko, + * Weijun Wang, Tobias Weyand, Marco Andreetto, Hartwig Adam}, + * title = {MobileNets: Efficient Convolutional Neural Networks for Mobile + * Vision Applications}, + * year = {2017}, + * url = {https://arxiv.org/pdf/1704.04861} + * } + * @endcode + * + * 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_RELU6_HPP +#define MLPACK_METHODS_ANN_LAYER_RELU6_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * @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 +class ReLU6 +{ + public: + + /** + * Create the ReLU6 object. + */ + ReLU6(); + + /** + * 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 + 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 + void Backward(const DataType& input, const DataType& gy, DataType& g); + + //! Get the output parameter. + OutputDataType const& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const& Delta() const { return delta; } + //! Modify the delta. + OutputDataType& Delta() { return delta; } + + //! Get size of weights. + size_t WeightSize() const { return 0; } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& ar, const uint32_t /* version */); + + private: + //! Locally-stored output parameter object. + OutputDataType outputParameter; + + //! Locally-stored delta object. + OutputDataType delta; +}; // class ReLU6 + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "relu6_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/relu6_impl.hpp b/src/mlpack/methods/ann/layer/relu6_impl.hpp new file mode 100644 index 0000000000..d65dfd8998 --- /dev/null +++ b/src/mlpack/methods/ann/layer/relu6_impl.hpp @@ -0,0 +1,77 @@ +/** + * @file methods/ann/layer/relu6_impl.hpp + * @author Aakash kaushik + * + * For more information, kindly refer to the following paper. + * + * @code + * @article{Andrew G2017, + * author = {Andrew G. Howard, Menglong Zhu, Bo Chen, Dmitry Kalenichenko, + * Weijun Wang, Tobias Weyand, Marco Andreetto, Hartwig Adam}, + * title = {MobileNets: Efficient Convolutional Neural Networks for Mobile + * Vision Applications}, + * year = {2017}, + * url = {https://arxiv.org/pdf/1704.04861} + * } + * @endcode + * + * 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_RELU6_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_RELU6_IMPL_HPP + +// In case it hasn't yet been included. +#include "relu6.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +template +ReLU6::ReLU6() +{ + // Nothing to do here. +} + +template +template +void ReLU6::Forward( + const InputType& input, OutputType& output) +{ + OutputType outputTemp(arma::size(input)); + outputTemp.fill(6.0); + output = arma::zeros(arma::size(input)); + output = arma::min(arma::max(output, input), outputTemp); +} + +template +template +void ReLU6::Backward( + const DataType& input, const DataType& gy, DataType& g) +{ + DataType derivative(arma::size(gy)); + derivative.fill(0.0); + for (size_t i = 0; i < input.n_elem; ++i) + { + if (input(i) < 6 && input(i) > 0) + derivative(i) = 1.0; + } + + g = gy % derivative; +} + +template +template +void ReLU6::serialize( + Archive& ar, + const uint32_t /* version */) +{ + // Nothing to do here. +} + +} // namespace ann +} // namespace mlpack + +#endif diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index b60855d9b4..1c4458c4f9 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -704,6 +704,53 @@ void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, } } +/** + * Implementation of the ReLU6 activation function derivative test. The function + * is implemented as ReLU6 layer in the file relu6.hpp. + * + * @param input Input data used for evaluating the ReLU6 activation function. + * @param target Target data used to evaluate the ReLU6 activation. + */ +void CheckReLU6Correct(const arma::colvec input, + const arma::colvec ActivationTarget, + const arma::colvec DerivativeTarget) +{ + // Initialize ReLU6 object. + ReLU6<> relu6; + + // Test the calculation of the derivatives using the entire vector as input. + arma::colvec derivatives, activations; + + // This error vector will be set to 1 to get the derivatives. + arma::colvec error = arma::ones(input.n_elem); + relu6.Forward(input, activations); + for (size_t i = 0; i < activations.n_elem; ++i) + { + REQUIRE(activations.at(i) == Approx(ActivationTarget.at(i)).epsilon(1e-5)); + } + relu6.Backward(activations, error, derivatives); + for (size_t i = 0; i < derivatives.n_elem; ++i) + { + REQUIRE(derivatives.at(i) == Approx(DerivativeTarget.at(i)).epsilon(1e-5)); + } +} + +/** + * Basic test of the ReLU6 function. + */ +TEST_CASE("ReLU6FunctionTest", "[ActivationFunctionsTest]") +{ + const arma::colvec activationData("-2.0 3.0 0.0 6.0 24.0"); + + // desiredActivations taken from PyTorch. + const arma::colvec desiredActivations("0.0 3.0 0.0 6.0 6.0"); + + // desiredDerivatives taken from PyTorch. + const arma::colvec desiredDerivatives("0.0 1.0 0.0 0.0 0.0"); + + CheckReLU6Correct(activationData, desiredActivations, desiredDerivatives); +} + /** * Basic test of the tanh function. */ From 80a094e5453ada62170f3c5683c29e23b2923948 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 6 Apr 2021 00:22:14 +0530 Subject: [PATCH 536/729] Added mad gain implementation and tests --- src/mlpack/methods/decision_tree/mad_gain.hpp | 187 ++++++++++++++++++ src/mlpack/tests/decision_tree_test.cpp | 48 +++++ 2 files changed, 235 insertions(+) create mode 100644 src/mlpack/methods/decision_tree/mad_gain.hpp diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp new file mode 100644 index 0000000000..065de37dcb --- /dev/null +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -0,0 +1,187 @@ +/** + * @file methods/decision_tree/mse_gain.hpp + * @author Rishabh Garg + * + * The mean absolute deviation gain class, a fitness funtion for regression + * based decision trees. + * + * 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 informatio +n. + */ +#ifndef MLPACK_METHODS_DECISION_TREE_MAD_GAIN_HPP +#define MLPACK_METHODS_DECISION_TREE_MAD_GAIN_HPP + +#include + +namespace mlpack { +namespace tree { + +/** + * The MAD (Mean absolute deviation) gain, is a measure of set purity based on + * the deviation of dependent values present in the node. This is same thing as + * negation of deviation of dependent variable from the mean in the node as we + * will try to maximize this quantity to maximize gain (and thus reduce + * absolute deviation of a set). +*/ +class MADGain +{ + public: + /** + * Evaluate the mean absolute deviation gain from begin to end index. Note + * that gain can be slightly greater than 0 due to floating-point + * representation issues. Thus if you are checking for perfect fit, be sure + * to use 'gain >= 0.0'. Not 'gain == 0.0'. The labels should always be of + * type arma::Row or arma::rowvec. + * + * @param labels Set of labels to evaluate MAD gain on. + * @param weights Weight of labels. + * @param begin Start index. + * @param end End index. + */ + template + static double Evaluate(const arma::rowvec& labels, + const WeightVecType& weights, + const size_t begin, + const size_t end) + { + double mad = 0.0; + + if (UseWeights) + { + double accWeights[4] = { 0.0, 0.0, 0.0, 0.0 }; + double weightedMean[4] = { 0.0, 0.0, 0.0, 0.0 }; + + // SIMD loop: sums four elements simultaneously (if the compiler manages + // to vectorize the loop). + for (size_t i = begin + 3; i < end; i += 4) + { + const double weight1 = weights[i - 3]; + const double weight2 = weights[i - 2]; + const double weight3 = weights[i - 1]; + const double weight4 = weights[i]; + + weightedMean[0] += weight1 * labels[i - 3]; + weightedMean[1] += weight2 * labels[i - 2]; + weightedMean[2] += weight3 * labels[i - 1]; + weightedMean[3] += weight4 * labels[i]; + + accWeights[0] += weight1; + accWeights[1] += weight2; + accWeights[2] += weight3; + accWeights[3] += weight4; + } + + // Handle leftovers. + if ((end - begin) % 4 == 1) + { + const double weight1 = weights[end - 1]; + weightedMean[0] += weight1 * labels[end - 1]; + accWeights[0] += weight1; + } + else if ((end - begin) % 4 == 2) + { + const double weight1 = weights[end - 2]; + const double weight2 = weights[end - 1]; + + weightedMean[0] += weight1 * labels[end - 2]; + weightedMean[1] += weight2 * labels[end - 1]; + + accWeights[0] += weight1; + accWeights[1] += weight2; + } + else if ((end - begin) % 4 == 3) + { + const double weight1 = weights[end - 3]; + const double weight2 = weights[end - 2]; + const double weight3 = weights[end - 1]; + + weightedMean[0] += weight1 * labels[end - 3]; + weightedMean[1] += weight2 * labels[end - 2]; + weightedMean[2] += weight1 * labels[end - 1]; + + accWeights[0] += weight1; + accWeights[1] += weight2; + accWeights[2] += weight3; + } + + accWeights[0] += accWeights[1] + accWeights[2] + accWeights[3]; + weightedMean[0] += weightedMean[1] + weightedMean[2] + weightedMean[3]; + + // Catch edge case: if there are no weights, the impurity is zero. + if (accWeights[0] == 0.0) + return 0.0; + + for (size_t i = begin; i < end; ++i) + { + const double f = weights[i] * (std::abs(labels[i] - weightedMean[0])); + mad += f / accWeights[0]; + } + } + else + { + double mean[4] = { 0.0, 0.0, 0.0, 0.0 }; + + // SIMD loop: add counts for four elements simultaneously (if the compiler + // manages to vectorize the loop). + for (size_t i = begin + 3; i < end; i += 4) + { + mean[0] += labels[i - 3]; + mean[1] += labels[i - 2]; + mean[2] += labels[i - 1]; + mean[3] += labels[i]; + } + + // Handle leftovers. + if (labels.n_elem % 4 == 1) + { + mean[0] += labels[end - 1]; + } + else if (labels.n_elem % 4 == 2) + { + mean[0] += labels[end - 2]; + mean[1] += labels[end - 1]; + } + else if (labels.n_elem % 4 == 3) + { + mean[0] += labels[end - 3]; + mean[1] += labels[end - 2]; + mean[2] += labels[end - 1]; + } + + mean[0] += mean[1] + mean[2] + mean[3]; + + for (size_t i = begin; i < end; ++i) + mad += std::abs(labels[i] - mean[0]); + + mad /= (double) (end - begin); + } + + return -mad; + } + + /** + * Evaluate the MAD gain on the complete vector. + * + * @param labels Set of labels to evaluate MAD gain on. + * @param weights Weights associated to each label. + */ + template + static double Evaluate(const arma::rowvec& labels, + const WeightVecType& weights) + { + // Corner case: if there are no elements, the impurity is zero. + if (labels.n_elem == 0) + return 0.0; + + return Evaluate(labels, weights, 0, labels.n_elem); + } + +}; + +} // namespace tree +} // namespace mlpack + +#endif diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index d0bc624ca3..d14bc5fc3a 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -24,6 +24,54 @@ using namespace mlpack; using namespace mlpack::tree; using namespace mlpack::distribution; +/** + * Make sure the MSE gain is zero when the labels are perfect. + */ +TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights(10, arma::fill::ones); + arma::rowvec labels; + labels.ones(10); + + REQUIRE(MADGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} + +/** + * Make sure that for a normal distribution of labels, + * MAD_gain = mean of absolute values of the distribution. + */ +TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") +{ + arma::rowvec weights(10, arma::fill::ones); + arma::rowvec labels(10, arma::fill::randn); // Mean = 0. + + // Theoretical gain. + const double theoreticalGain = 0.0; + for (size_t i = 0; i < labels.n_elem; ++i) + theoreticalGain += std::abs(labels[i]); + theoreticalGain /= (double) labels.n_elem; + + // Calculated gain. + const double calculatedGain = MADGain::Evaluate(labels, weights); + + REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); +} + +/** + * The MAD gain of an empty vector is 0. + */ +TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights = arma::ones(10); + arma::rowvec predictors; + REQUIRE(MADGain::Evaluate(predictors, weights) == + Approx(0.0).margin(1e-5)); + + REQUIRE(MADGain::Evaluate(predictors, weights) == + Approx(0.0).margin(1e-5)); +} + /** * Make sure the Gini gain is zero when the labels are perfect. */ From 8d3a7d7799db1ed040e668f91c17be73aabaab7d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 6 Apr 2021 00:51:45 +0530 Subject: [PATCH 537/729] Added forgotten import and fixed test --- src/mlpack/tests/decision_tree_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index d14bc5fc3a..8aaa7194e2 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -47,9 +48,9 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") arma::rowvec labels(10, arma::fill::randn); // Mean = 0. // Theoretical gain. - const double theoreticalGain = 0.0; + double theoreticalGain = 0.0; for (size_t i = 0; i < labels.n_elem; ++i) - theoreticalGain += std::abs(labels[i]); + theoreticalGain -= std::abs(labels[i]); theoreticalGain /= (double) labels.n_elem; // Calculated gain. From 0c265ccffe2b56b4a39330144fcc0cbd6926d8be Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 6 Apr 2021 11:09:41 +0530 Subject: [PATCH 538/729] Fixed implementation bug and normal distribution test --- src/mlpack/methods/decision_tree/mad_gain.hpp | 4 ++++ src/mlpack/tests/decision_tree_test.cpp | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 065de37dcb..1f3e460a77 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -109,6 +109,8 @@ class MADGain accWeights[0] += accWeights[1] + accWeights[2] + accWeights[3]; weightedMean[0] += weightedMean[1] + weightedMean[2] + weightedMean[3]; + weightedMean[0] /= (double) (end - begin); + std::cout << "WeightedMean: " << weightedMean[0] << std::endl; // Catch edge case: if there are no weights, the impurity is zero. if (accWeights[0] == 0.0) @@ -152,6 +154,8 @@ class MADGain } mean[0] += mean[1] + mean[2] + mean[3]; + mean[0] /= (double) (end - begin); + std::cout << "Mean: " << mean[0] << std::endl; for (size_t i = begin; i < end; ++i) mad += std::abs(labels[i] - mean[0]); diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 8aaa7194e2..ab8aa094ae 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -39,13 +39,13 @@ TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") } /** - * Make sure that for a normal distribution of labels, - * MAD_gain = mean of absolute values of the distribution. + * Make sure that when mean of labels is zero, MAD_gain = mean of + * absolute values of the distribution. */ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") { arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels(10, arma::fill::randn); // Mean = 0. + arma::rowvec labels = { 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; // Mean = 0. // Theoretical gain. double theoreticalGain = 0.0; From d8634ca0836f65cc3040c538874e7e81110337a1 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 8 Apr 2021 19:37:59 +0530 Subject: [PATCH 539/729] Fixed logic error in calculating weighted mean --- src/mlpack/methods/decision_tree/mad_gain.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 1f3e460a77..0643e4d01d 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -109,13 +109,13 @@ class MADGain accWeights[0] += accWeights[1] + accWeights[2] + accWeights[3]; weightedMean[0] += weightedMean[1] + weightedMean[2] + weightedMean[3]; - weightedMean[0] /= (double) (end - begin); - std::cout << "WeightedMean: " << weightedMean[0] << std::endl; // Catch edge case: if there are no weights, the impurity is zero. if (accWeights[0] == 0.0) return 0.0; + weightedMean[0] /= accWeights[0]; + for (size_t i = begin; i < end; ++i) { const double f = weights[i] * (std::abs(labels[i] - weightedMean[0])); @@ -155,7 +155,6 @@ class MADGain mean[0] += mean[1] + mean[2] + mean[3]; mean[0] /= (double) (end - begin); - std::cout << "Mean: " << mean[0] << std::endl; for (size_t i = begin; i < end; ++i) mad += std::abs(labels[i] - mean[0]); From 24cd615fc6c6b584b70ca7462130768655a47f7f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 8 Apr 2021 22:08:11 +0530 Subject: [PATCH 540/729] Implemented SIMD sum in utils.hpp --- src/mlpack/methods/decision_tree/utils.hpp | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/mlpack/methods/decision_tree/utils.hpp diff --git a/src/mlpack/methods/decision_tree/utils.hpp b/src/mlpack/methods/decision_tree/utils.hpp new file mode 100644 index 0000000000..d7da7cbd16 --- /dev/null +++ b/src/mlpack/methods/decision_tree/utils.hpp @@ -0,0 +1,130 @@ +/** + * @file methods/decision_tree/utils.hpp + * @author Rishabh Garg + * + * Various utility functions used in decision tree implementation. + * + * 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_DECISION_TREE_UTILS_HPP +#define MLPACK_METHODS_DECISION_TREE_UTILS_HPP + +/** + * Calculates the weighted sum and total weight of labels. + */ +void WeightedSum(const arma::rowvec& labels, + const arma::rowvec& weights, + const size_t begin, + const size_t end, + double& accWeights, + double& weightedMean) +{ + double totalWeights[4] = { 0.0, 0.0, 0.0, 0.0 }; + double weightedSum[4] = { 0.0, 0.0, 0.0, 0.0 }; + + // SIMD loop: sums four elements simultaneously (if the compiler manages + // to vectorize the loop). + for (size_t i = begin + 3; i < end; i += 4) + { + const double weight1 = weights[i - 3]; + const double weight2 = weights[i - 2]; + const double weight3 = weights[i - 1]; + const double weight4 = weights[i]; + + weightedSum[0] += weight1 * labels[i - 3]; + weightedSum[1] += weight2 * labels[i - 2]; + weightedSum[2] += weight3 * labels[i - 1]; + weightedSum[3] += weight4 * labels[i]; + + totalWeights[0] += weight1; + totalWeights[1] += weight2; + totalWeights[2] += weight3; + totalWeights[3] += weight4; + } + + // Handle leftovers. + if ((end - begin) % 4 == 1) + { + const double weight1 = weights[end - 1]; + weightedSum[0] += weight1 * labels[end - 1]; + totalWeights[0] += weight1; + } + else if ((end - begin) % 4 == 2) + { + const double weight1 = weights[end - 2]; + const double weight2 = weights[end - 1]; + + weightedSum[0] += weight1 * labels[end - 2]; + weightedSum[1] += weight2 * labels[end - 1]; + + totalWeights[0] += weight1; + totalWeights[1] += weight2; + } + else if ((end - begin) % 4 == 3) + { + const double weight1 = weights[end - 3]; + const double weight2 = weights[end - 2]; + const double weight3 = weights[end - 1]; + + weightedSum[0] += weight1 * labels[end - 3]; + weightedSum[1] += weight2 * labels[end - 2]; + weightedSum[2] += weight1 * labels[end - 1]; + + totalWeights[0] += weight1; + totalWeights[1] += weight2; + totalWeights[2] += weight3; + } + + totalWeights[0] += totalWeights[1] + totalWeights[2] + totalWeights[3]; + weightedSum[0] += weightedSum[1] + weightedSum[2] + weightedSum[3]; + + accWeights = totalWeights[0]; + weightedMean = weightedSum[0]; +} + +/** + * Sums up the labels vector. + */ +void Sum(const arma::rowvec& labels, + const size_t begin, + const size_t end, + double& mean) +{ + double total[4] = { 0.0, 0.0, 0.0, 0.0 }; + + // SIMD loop: add counts for four elements simultaneously (if the compiler + // manages to vectorize the loop). + for (size_t i = begin + 3; i < end; i += 4) + { + total[0] += labels[i - 3]; + total[1] += labels[i - 2]; + total[2] += labels[i - 1]; + total[3] += labels[i]; + } + + // Handle leftovers. + if (labels.n_elem % 4 == 1) + { + total[0] += labels[end - 1]; + } + else if (labels.n_elem % 4 == 2) + { + total[0] += labels[end - 2]; + total[1] += labels[end - 1]; + } + else if (labels.n_elem % 4 == 3) + { + total[0] += labels[end - 3]; + total[1] += labels[end - 2]; + total[2] += labels[end - 1]; + } + + total[0] += total[1] + total[2] + total[3]; + + mean = total[0]; +} + +#endif From e47962f18c165e67397765ba66ea6db3f71382bd Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 8 Apr 2021 22:10:18 +0530 Subject: [PATCH 541/729] Refactored mad_gain to use utils.hpp --- src/mlpack/methods/decision_tree/mad_gain.hpp | 107 +++--------------- 1 file changed, 13 insertions(+), 94 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 0643e4d01d..32102a5de3 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -15,6 +15,7 @@ n. #define MLPACK_METHODS_DECISION_TREE_MAD_GAIN_HPP #include +#include "utils.hpp" namespace mlpack { namespace tree { @@ -51,113 +52,31 @@ class MADGain if (UseWeights) { - double accWeights[4] = { 0.0, 0.0, 0.0, 0.0 }; - double weightedMean[4] = { 0.0, 0.0, 0.0, 0.0 }; + double accWeights = 0.0; + double weightedMean = 0.0; - // SIMD loop: sums four elements simultaneously (if the compiler manages - // to vectorize the loop). - for (size_t i = begin + 3; i < end; i += 4) - { - const double weight1 = weights[i - 3]; - const double weight2 = weights[i - 2]; - const double weight3 = weights[i - 1]; - const double weight4 = weights[i]; - - weightedMean[0] += weight1 * labels[i - 3]; - weightedMean[1] += weight2 * labels[i - 2]; - weightedMean[2] += weight3 * labels[i - 1]; - weightedMean[3] += weight4 * labels[i]; - - accWeights[0] += weight1; - accWeights[1] += weight2; - accWeights[2] += weight3; - accWeights[3] += weight4; - } - - // Handle leftovers. - if ((end - begin) % 4 == 1) - { - const double weight1 = weights[end - 1]; - weightedMean[0] += weight1 * labels[end - 1]; - accWeights[0] += weight1; - } - else if ((end - begin) % 4 == 2) - { - const double weight1 = weights[end - 2]; - const double weight2 = weights[end - 1]; - - weightedMean[0] += weight1 * labels[end - 2]; - weightedMean[1] += weight2 * labels[end - 1]; - - accWeights[0] += weight1; - accWeights[1] += weight2; - } - else if ((end - begin) % 4 == 3) - { - const double weight1 = weights[end - 3]; - const double weight2 = weights[end - 2]; - const double weight3 = weights[end - 1]; - - weightedMean[0] += weight1 * labels[end - 3]; - weightedMean[1] += weight2 * labels[end - 2]; - weightedMean[2] += weight1 * labels[end - 1]; - - accWeights[0] += weight1; - accWeights[1] += weight2; - accWeights[2] += weight3; - } - - accWeights[0] += accWeights[1] + accWeights[2] + accWeights[3]; - weightedMean[0] += weightedMean[1] + weightedMean[2] + weightedMean[3]; + WeightedSum(labels, weights, begin, end, accWeights, weightedMean); // Catch edge case: if there are no weights, the impurity is zero. - if (accWeights[0] == 0.0) + if (accWeights == 0.0) return 0.0; - weightedMean[0] /= accWeights[0]; + weightedMean /= accWeights; for (size_t i = begin; i < end; ++i) { - const double f = weights[i] * (std::abs(labels[i] - weightedMean[0])); - mad += f / accWeights[0]; + mad += weights[i] * (std::abs(labels[i] - weightedMean)); + } + mad /= accWeights; } - } else { - double mean[4] = { 0.0, 0.0, 0.0, 0.0 }; - - // SIMD loop: add counts for four elements simultaneously (if the compiler - // manages to vectorize the loop). - for (size_t i = begin + 3; i < end; i += 4) - { - mean[0] += labels[i - 3]; - mean[1] += labels[i - 2]; - mean[2] += labels[i - 1]; - mean[3] += labels[i]; - } - - // Handle leftovers. - if (labels.n_elem % 4 == 1) - { - mean[0] += labels[end - 1]; - } - else if (labels.n_elem % 4 == 2) - { - mean[0] += labels[end - 2]; - mean[1] += labels[end - 1]; - } - else if (labels.n_elem % 4 == 3) - { - mean[0] += labels[end - 3]; - mean[1] += labels[end - 2]; - mean[2] += labels[end - 1]; - } - - mean[0] += mean[1] + mean[2] + mean[3]; - mean[0] /= (double) (end - begin); + double mean = 0.0; + Sum(labels, begin, end, mean); + mean /= (double) (end - begin); for (size_t i = begin; i < end; ++i) - mad += std::abs(labels[i] - mean[0]); + mad += std::abs(labels[i] - mean); mad /= (double) (end - begin); } From be9ff3437e684d1f7857a5ba3db498785aa9c0b5 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 8 Apr 2021 22:11:28 +0530 Subject: [PATCH 542/729] Implemented MSE gain --- src/mlpack/methods/decision_tree/mse_gain.hpp | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/mlpack/methods/decision_tree/mse_gain.hpp diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp new file mode 100644 index 0000000000..7d2b3fa488 --- /dev/null +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -0,0 +1,104 @@ +/** + * @file methods/decision_tree/mse_gain.hpp + * @author Rishabh Garg + * + * The mean squared error gain class, which is a fitness funtion for + * regression based decision trees. + * + * 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_DECISION_TREE_MSE_GAIN_HPP +#define MLPACK_METHODS_DECISION_TREE_MSE_GAIN_HPP + +#include +#include "utils.hpp" + +namespace mlpack { +namespace tree { + +/** + * The MSE (Mean squared error) gain, is a measure of set purity based on the + * variance of response values present in the node. This is same thing as + * negation of variance of dependent variable in the node as we will try to + * maximize this quantity to maximize gain (and thus reduce variance of a set). + */ +class MSEGain +{ + public: + /** + * Evaluate the mean squared error gain of labls from begin to end index. + * Note that gain can be slightly greater than 0 due to floating-point + * representation issues. Thus if you are checking for perfect fit, be + * sure to use 'gain >= 0.0' and not 'gain == 0.0'. The labels vector should + * always be of type arma::Row or arma::rowvec. + * + * @param labels Set of labels to evaluate MAD gain on. + * @param weights Weight of labels. + * @param begin Start index. + * @param end End index. + */ + template + static double Evaluate(const arma::rowvec& labels, + const WeightVecType& weights, + const size_t begin, + const size_t end) + { + double mse = 0.0; + + if (UseWeights) + { + double accWeights = 0.0; + double weightedMean = 0.0; + WeightedSum(labels, weights, begin, end, accWeights, weightedMean); + + // Catch edge case: if there are no weights, the impurity is zero. + if (accWeights == 0.0) + return 0.0; + + weightedMean /= accWeights; + + for (size_t i = begin; i < end; ++i) + mse += weights[i] * std::pow(labels[i] - weightedMean, 2); + + mse /= accWeights; + } + else + { + double mean = 0.0; + Sum(labels, begin, end, mean); + mean /= (double) (end - begin); + + for (size_t i = begin; i < end; ++i) + mse += std::pow(labels[i] - mean, 2); + + mse /= (double) (end - begin); + } + + return -mse; + } + + /** + * Evaluate the MSE gain on the complete vector. + * + * @param labels Set of labels to evaluate MAD gain on. + * @param weights Weights associated to each label. + */ + template + static double Evaluate(const arma::rowvec& labels, + const WeightVecType& weights) + { + // Corner case: if there are no elements, the impurity is zero. + if (labels.n_elem == 0) + return 0.0; + + return Evaluate(labels, weights, 0, labels.n_elem); + } +}; + +} // namespace tree +} // namespace mlpack + +#endif From b7d4c25c329aeca9bfda1e4ed5c383e16c4915c6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 8 Apr 2021 22:11:47 +0530 Subject: [PATCH 543/729] Implemented tests for MSE gain --- src/mlpack/tests/decision_tree_test.cpp | 52 +++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index ab8aa094ae..20689256e0 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,51 @@ using namespace mlpack::distribution; /** * Make sure the MSE gain is zero when the labels are perfect. */ +TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights(10, arma::fill::ones); + arma::rowvec labels; + labels.ones(10); + + REQUIRE(MSEGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} + +/** + * Make sure that the MSE gain is equal to negative of variance. + */ +TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights(100, arma::fill::ones); + arma::rowvec labels(100, arma::fill::randn); + + // Theoretical gain. + double theoreticalGain = - arma::var(labels) * 99.0 / 100.0; + + // Calculated gain. + const double calculatedGain = MSEGain::Evaluate(labels, weights); + + REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-9)); + std::cout << "MSEGain\n"; +} + +/** + * The MSE gain of an empty vector is 0. + */ +TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights = arma::ones(10); + arma::rowvec labels; + REQUIRE(MSEGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); + + REQUIRE(MSEGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} + +/** + * Make sure the MAD gain is zero when the labels are perfect. + */ TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") { arma::rowvec weights(10, arma::fill::ones); @@ -65,11 +111,11 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressionTest]") { arma::rowvec weights = arma::ones(10); - arma::rowvec predictors; - REQUIRE(MADGain::Evaluate(predictors, weights) == + arma::rowvec labels; + REQUIRE(MADGain::Evaluate(labels, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MADGain::Evaluate(predictors, weights) == + REQUIRE(MADGain::Evaluate(labels, weights) == Approx(0.0).margin(1e-5)); } From 415ac24c50d1fc0c842e6448c402661d4c698004 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 8 Apr 2021 22:13:59 +0530 Subject: [PATCH 544/729] Removed print statement --- src/mlpack/tests/decision_tree_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 20689256e0..67c926ef04 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -54,7 +54,6 @@ TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") const double calculatedGain = MSEGain::Evaluate(labels, weights); REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-9)); - std::cout << "MSEGain\n"; } /** From 2690c2c489cc031a5a476dd98e77562ac053027f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 13:08:03 +0530 Subject: [PATCH 545/729] Removed documentation of ElemType --- src/mlpack/methods/decision_tree/decision_tree.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree.hpp b/src/mlpack/methods/decision_tree/decision_tree.hpp index df81dc61ad..f73720d6db 100644 --- a/src/mlpack/methods/decision_tree/decision_tree.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree.hpp @@ -31,11 +31,6 @@ namespace tree { * * The class inherits from the auxiliary split information in order to prevent * an empty auxiliary split information struct from taking any extra size. - * - * Note that `ElemType` is a template parameter controlling the type that is - * used to store split information. In general, you would want to set this to - * be the same as the type of the data that you will be using, but it's not - * required to do that. */ template class NumericSplitType = BestBinaryNumericSplit, From 13311bb25c09fde4d4a109e96c8fce474ec3a40b Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 13:33:37 +0530 Subject: [PATCH 546/729] Added constructors --- src/mlpack/methods/decision_tree/decision_tree_regressor.hpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/mlpack/methods/decision_tree/decision_tree_regressor.hpp diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp new file mode 100644 index 0000000000..e69de29bb2 From a030a556d50bb045e9e3735d844148475f21dcb6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 13:34:19 +0530 Subject: [PATCH 547/729] Added constructors --- .../decision_tree/decision_tree_regressor.hpp | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index e69de29bb2..1134e293a1 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -0,0 +1,235 @@ +/** + * @file methods/decision_tree/decision_tree_regressor.hpp + * @author Rishabh Garg + * + * The decision tree regressor class. Its behavior can be controlled via the + * template arguments. + * + * 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_DECISION_TREE_DECISION_TREE_REGRESSOR_HPP +#define MLPACK_METHODS_DECISION_TREE_DECISION_TREE_REGRESSOR_HPP + +#include +#include "mad_gain.hpp" +#include "mse_gain.hpp" +#include "best_binary_numeric_split.hpp" +#include "all_categorical_split.hpp" +#include "all_dimension_select.hpp" +#include + + +namespace mlpack { +namespace tree { + +/** + * This class implements a generic decision tree learner. Its behavior can be + * controlled via its template arguments. + * + * The class inherits from the auxiliary split information in order to prevent + * an empty auxiliary split information struct from taking any extra size. + */ +template class NumericSplitType = BestBinaryNumericSplit, + template class CategoricalSplitType = AllCategoricalSplit, + typename DimensionSelectionType = AllDimensionSelect, + bool NoRecursion = false> +class DecisionTreeRegressor : + public NumericSplitType::AuxiliarySplitInfo, + public CategoricalSplitType::AuxiliarySplitInfo +{ + public: + //! Allow access to the numeric split type. + typedef NumericSplitType NumericSplit; + //! Allow access to the categorical split type. + typedef CategoricalSplitType CategoricalSplit; + //! Allow access to the dimension selection type. + typedef DimensionSelectionType DimensionSelection; + + /** + * Construct a decision tree without training it. It will be a leaf node. + */ + DecisionTreeRegressor(); + + /** + * Construct the decision tree on the given data and labels, where the data + * can be both numeric and categorical. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data or labels are no longer needed to avoid copies. + * + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension of the dataset. + * @param labels Labels for each training point. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + */ + template + DecisionTreeRegressor(MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType()); + + /** + * Construct the decision tree on the given data and labels, assuming that + * the data is all of the numeric type. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data or labels are no longer needed to avoid copies. + * + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + */ + template + DecisionTreeRegressor(MatType data, + LabelsType labels, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType()); + + /** + * Construct the decision tree on the given data and labels with weights, + * where the data can be both numeric and categorical. Setting minimumLeafSize + * and minimumGainSplit too small may cause the tree to overfit, but setting + * them too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension of the dataset. + * @param labels Labels for each training point. + * @param weights The weight list of given label. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + */ + template + DecisionTreeRegressor( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); + + /** + * Construct the decision tree on the given data and labels with weights, + * assuming that the data is all of the numeric type. Setting minimumLeafSize + * and minimumGainSplit too small may cause the tree to overfit, but setting + * them too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param weights The Weight list of given labels. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + */ + template + DecisionTreeRegressor( + MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); + + /** + * Take ownership of another decision tree and train on the given data and + * labels with weights, where the data can be both numeric and categorical. + * Setting minimumLeafSize and minimumGainSplit too small may cause the + * tree to overfit, but setting them too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param other Tree to take ownership of. + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension of the dataset. + * @param labels Labels for each training point. + * @param weights The weight list of given label. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + */ + template + DecisionTreeRegressor( + const DecisionTreeRegressor& other, + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const std::enable_if_t::type>::value>* = 0); + + /** + * Take ownership of another decision tree and train on the given data and labels + * with weights, assuming that the data is all of the numeric type. Setting + * minimumLeafSize and minimumGainSplit too small may cause the tree to + * overfit, but setting them too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * @param other Tree to take ownership of. + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param weights The Weight list of given labels. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + */ + template + DecisionTreeRegressor( + const DecisionTreeRegressor& other, + MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); + +}; + + +} // namespace tree +} // namespace mlpack + +// Include implementation. +#include "decision_tree_regressor_impl.hpp" + +#endif From 03a3f378d27ff692a78f9ec5a9a66e03b6f1ad23 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 13:36:16 +0530 Subject: [PATCH 548/729] Added copy and move ctors and dtor --- .../decision_tree/decision_tree_regressor.hpp | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 1134e293a1..8911e8c79f 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -223,6 +223,40 @@ class DecisionTreeRegressor : const std::enable_if_t::type>::value>* = 0); + /** + * Copy another tree. This may use a lot of memory---be sure that it's what + * you want to do. + * + * @param other Tree to copy. + */ + DecisionTreeRegressor(const DecisionTreeRegressor& other); + + /** + * Take ownership of another tree. + * + * @param other Tree to take ownership of. + */ + DecisionTreeRegressor(DecisionTreeRegressor&& other); + + /** + * Copy another tree. This may use a lot of memory---be sure that it's what + * you want to do. + * + * @param other Tree to copy. + */ + DecisionTreeRegressor& operator=(const DecisionTreeRegressor& other); + + /** + * Take ownership of another tree. + * + * @param other Tree to take ownership of. + */ + DecisionTreeRegressor& operator=(DecisionTreeRegressor&& other); + + /** + * Clean up memory. + */ + ~DecisionTreeRegressor(); }; From 0dd0715b5f06da2085d76e58ff834e26bb9149fb Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:09:25 +0530 Subject: [PATCH 549/729] Implemented ctors and dtor --- .../decision_tree_regressor_impl.hpp | 427 ++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp new file mode 100644 index 0000000000..9ba0623341 --- /dev/null +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -0,0 +1,427 @@ +/** + * @file methods/decision_tree/decision_tree_regressor_impl.hpp + * @author Rishabh Garg + * + * Implementation of decision tree regressor 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_DECISION_TREE_DECISION_TREE_REGRESSOR_IMPL_HPP +#define MLPACK_METHODS_DECISION_TREE_DECISION_TREE_REGRESSOR_IMPL_HPP + +#include "decision_tree_regressor.hpp" + +namespace mlpack { +namespace tree { + +//! Construct, don't train. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +DecisionTreeRegressor::DecisionTreeRegressor() : + splitDimension(0), + dimensionTypeOrMajorityClass(0), + classProbabilities(numClasses) +{ + // Initialize utility vector. + classProbabilities.fill(1.0 / (double) numClasses); +} + +//! Construct and train without weight. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +DecisionTreeRegressor::DecisionTreeRegressor( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector) +{ + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + arma::rowvec weights; // Fake weights, not used. + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + weights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Construct and train without weight on numeric data. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +DecisionTreeRegressor::DecisionTreeRegressor( + MatType data, + LabelsType labels, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector) +{ + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + arma::rowvec weights; // Fake weights, not used. + Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, weights, + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); +} + +//! Construct and train with weights. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +DecisionTreeRegressor::DecisionTreeRegressor( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t::type>::value>*) +{ + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the weighted Train() method. + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Construct and train on numeric data with weights. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +DecisionTreeRegressor::DecisionTreeRegressor( + MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t< + arma::is_arma_type< + typename std::remove_reference< + WeightsType>::type>::value>*) +{ + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the weighted Train() method. + Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights, + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); +} + +//! Take ownership of another tree and train with weights. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +DecisionTreeRegressor::DecisionTreeRegressor( + const DecisionTreeRegressor& other, + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t numClasses, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const std::enable_if_t::type>::value>*): + NumericAuxiliarySplitInfo(other), + CategoricalAuxiliarySplitInfo(other) +{ + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Pass off work to the weighted Train() method. + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + tmpWeights, minimumLeafSize, minimumGainSplit); +} + +//! Take ownership of another tree and train with weights. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +DecisionTreeRegressor::DecisionTreeRegressor( + const DecisionTreeRegressor& other, + MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t::type>::value>*): + NumericAuxiliarySplitInfo(other), + CategoricalAuxiliarySplitInfo(other) // other info does need to copy +{ + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the weighted Train() method. + Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights, + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); +} + +//! Copy another tree. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +DecisionTreeRegressor::DecisionTreeRegressor( + const DecisionTreeRegressor& other) : + NumericAuxiliarySplitInfo(other), + CategoricalAuxiliarySplitInfo(other), + splitDimension(other.splitDimension), + dimensionTypeOrMajorityClass(other.dimensionTypeOrMajorityClass), + classProbabilities(other.classProbabilities) +{ + // Copy each child. + for (size_t i = 0; i < other.children.size(); ++i) + children.push_back(new DecisionTreeRegressor(*other.children[i])); +} + +//! Take ownership of another tree. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +DecisionTreeRegressor::DecisionTreeRegressor( + DecisionTreeRegressor&& other) : + NumericAuxiliarySplitInfo(std::move(other)), + CategoricalAuxiliarySplitInfo(std::move(other)), + children(std::move(other.children)), + splitDimension(other.splitDimension), + dimensionTypeOrMajorityClass(other.dimensionTypeOrMajorityClass), + classProbabilities(std::move(other.classProbabilities)) +{ + // Reset the other object. + other.classProbabilities.ones(1); // One class, P(1) = 1. +} + +//! Copy another tree. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +DecisionTreeRegressor& +DecisionTreeRegressor::operator=(const DecisionTreeRegressor& other) +{ + if (this == &other) + return *this; // Nothing to copy. + + // Clean memory if needed. + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; + children.clear(); + + // Copy everything from the other tree. + splitDimension = other.splitDimension; + dimensionTypeOrMajorityClass = other.dimensionTypeOrMajorityClass; + classProbabilities = other.classProbabilities; + + // Copy the children. + for (size_t i = 0; i < other.children.size(); ++i) + children.push_back(new DecisionTree(*other.children[i])); + + // Copy the auxiliary info. + NumericAuxiliarySplitInfo::operator=(other); + CategoricalAuxiliarySplitInfo::operator=(other); + + return *this; +} + +//! Take ownership of another tree. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +DecisionTreeRegressor& +DecisionTreeRegressor::operator=(DecisionTreeRegressor&& other) +{ + if (this == &other) + return *this; // Nothing to move. + + // Clean memory if needed. + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; + children.clear(); + + // Take ownership of the other tree's components. + children = std::move(other.children); + splitDimension = other.splitDimension; + dimensionTypeOrMajorityClass = other.dimensionTypeOrMajorityClass; + classProbabilities = std::move(other.classProbabilities); + + // Reset the class probabilities of the other object. + other.classProbabilities.ones(1); // One class, P(1) = 1. + + // Take ownership of the auxiliary info. + NumericAuxiliarySplitInfo::operator=(std::move(other)); + CategoricalAuxiliarySplitInfo::operator=(std::move(other)); + + return *this; +} + +//! Clean up memory. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +DecisionTreeRegressor::~DecisionTreeRegressor() +{ + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; +} + + +} // namespace tree +} // namespace mlpack + +#endif From a2c9cd0c2d177e0150b7830b8514972efcb6ef0d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:52:37 +0530 Subject: [PATCH 550/729] Added Train overloads --- .../decision_tree/decision_tree_regressor.hpp | 116 ++++++++++++ .../decision_tree_regressor_impl.hpp | 170 ++++++++++++++++++ 2 files changed, 286 insertions(+) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 8911e8c79f..17358d07a6 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -257,6 +257,122 @@ class DecisionTreeRegressor : * Clean up memory. */ ~DecisionTreeRegressor(); + + /** + * Train the decision tree on the given data. This will overwrite the + * existing model. The data may have numeric and categorical types, specified + * by the datasetInfo parameter. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data or labels are no longer needed to avoid copies. + * + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension. + * @param labels Labels for each training point. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType()); + + /** + * Train the decision tree on the given data, assuming that all dimensions are + * numeric. This will overwrite the given model. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data or labels are no longer needed to avoid copies. + * + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + LabelsType labels, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType()); + + /** + * Train the decision tree on the given weighted data. This will overwrite + * the existing model. The data may have numeric and categorical types, + * specified by the datasetInfo parameter. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension. + * @param labels Labels for each training point. + * @param weights Weights of all the labels + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); + + /** + * Train the decision tree on the given weighted data, assuming that all + * dimensions are numeric. This will overwrite the given model. Setting + * minimumLeafSize and minimumGainSplit too small may cause the tree to + * overfit, but setting them too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param weights Weights of all the labels + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); }; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 9ba0623341..1145b110e0 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -420,6 +420,176 @@ DecisionTreeRegressor class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + arma::rowvec weights; // Fake weights, not used. + return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, + numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Train on the given data, assuming all dimensions are numeric. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + LabelsType labels, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + arma::rowvec weights; // Fake weights, not used. + return Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, + weights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Train on the given weighted data. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t< + arma::is_arma_type< + typename std::remove_reference< + WeightsType>::type>::value>*) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, + numClasses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Train on the given weighted all numeric data. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t< + arma::is_arma_type< + typename std::remove_reference< + WeightsType>::type>::value>*) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + return Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, + tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + } // namespace tree } // namespace mlpack From 37559821bf21993c3bfbeadbb6f7decd655dee6f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 23:48:36 +0530 Subject: [PATCH 551/729] Refactored AllCategoricalSplit --- .../decision_tree/all_categorical_split.hpp | 10 ++++----- .../all_categorical_split_impl.hpp | 18 +++++++-------- .../decision_tree/decision_tree_impl.hpp | 6 +++-- src/mlpack/tests/decision_tree_test.cpp | 22 +++++++++---------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index faa8f16c6b..09f717c155 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -47,23 +47,23 @@ class AllCategoricalSplit * @param weights Weights associated with labels. * @param minimumLeafSize Minimum number of points in a leaf node for * splitting. - * @param classProbabilities Class probabilities vector, which may be filled - * with split information a successful split. + * @param splitInfo Stores split information on a successful split. * @param minimumGainSplit Minimum gain split. * @param aux Auxiliary split information, which may be modified on a * successful split. */ - template + template static double SplitIfBetter( const double bestGain, const VecType& data, const size_t numCategories, - const arma::Row& labels, + const arma::Row& labels, + const size_t begin, const size_t numClasses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::vec& classProbabilities, + double& splitInfo, AuxiliarySplitInfo& aux); /** diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 00135625ab..87da7b3d22 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -16,17 +16,18 @@ namespace mlpack { namespace tree { template -template +template double AllCategoricalSplit::SplitIfBetter( const double bestGain, const VecType& data, const size_t numCategories, - const arma::Row& labels, + const arma::Row& labels, + const size_t begin, const size_t numClasses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::vec& classProbabilities, + double& splitInfo, AuxiliarySplitInfo& /* aux */) { // Count the number of elements in each potential child. @@ -58,7 +59,7 @@ double AllCategoricalSplit::SplitIfBetter( // Calculate the gain of the split. First we have to calculate the labels // that would be assigned to each child. arma::uvec childPositions(numCategories, arma::fill::zeros); - std::vector> childLabels(numCategories); + std::vector> childLabels(numCategories); std::vector> childWeights(numCategories); for (size_t i = 0; i < numCategories; ++i) { @@ -75,12 +76,12 @@ double AllCategoricalSplit::SplitIfBetter( if (UseWeights) { - childLabels[category][childPositions[category]] = labels[i]; + childLabels[category][childPositions[category]] = labels[begin + i]; childWeights[category][childPositions[category]++] = weights[i]; } else { - childLabels[category][childPositions[category]++] = labels[i]; + childLabels[category][childPositions[category]++] = labels[begin + i]; } } @@ -99,9 +100,8 @@ double AllCategoricalSplit::SplitIfBetter( if (overallGain > bestGain + minimumGainSplit + epsilon) { - // This is better, so set up the class probabilities vector and return. - classProbabilities.set_size(1); - classProbabilities[0] = numCategories; + // This is better, so store it in splitInfo and return. + splitInfo = numCategories; return overallGain; } diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index e4cd77851b..8f04e9f57c 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -642,15 +642,17 @@ double DecisionTree(bestGain, data.cols(begin, begin + count - 1).row(i), datasetInfo.NumMappings(i), - labels.subvec(begin, begin + count - 1), + labels, + begin, numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, minimumGainSplit, - classProbabilities, + classProbabilities[0], *this); } else if (datasetInfo.Type(i) == data::Datatype::numeric) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 67c926ef04..45eb350523 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -583,17 +583,17 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); weights.ones(); - arma::vec classProbabilities; + arma::vec classProbabilities(1); AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 4, labels, 3, weights, 3, 1e-7, classProbabilities, + bestGain, values, 4, labels, 0, 3, weights, 3, 1e-7, classProbabilities[0], aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, values, 4, - labels, 3, weights, 3, 1e-7, classProbabilities, aux); + labels, 0, 3, weights, 3, 1e-7, classProbabilities[0], aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -619,18 +619,17 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); weights.ones(); - arma::vec classProbabilities; + arma::vec classProbabilities(1); AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 4, labels, 3, weights, 4, 1e-7, classProbabilities, - aux); + bestGain, values, 4, labels, 0, 3, weights, 4, 1e-7, + classProbabilities[0], aux); // Make sure it's not split. REQUIRE(gain == DBL_MAX); - REQUIRE(classProbabilities.n_elem == 0); } /** @@ -652,22 +651,21 @@ TEST_CASE("AllCategoricalSplitNoGainTest", "[DecisionTreeTest]") labels[i + 2] = 2; } - arma::vec classProbabilities; + arma::vec classProbabilities(1); AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 10, labels, 3, weights, 10, 1e-7, - classProbabilities, aux); + bestGain, values, 10, labels, 0, 3, weights, 10, 1e-7, + classProbabilities[0], aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, values, 10, - labels, 3, weights, 10, 1e-7, classProbabilities, aux); + labels, 0, 3, weights, 10, 1e-7, classProbabilities[0], aux); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); - REQUIRE(classProbabilities.n_elem == 0); } /** From e3579871afb47311fa7f36b1f12f8801864cd215 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Apr 2021 00:11:47 +0530 Subject: [PATCH 552/729] Refactored AllCategoricalSplit patch 2 --- .../decision_tree/all_categorical_split.hpp | 14 +++++++------- .../decision_tree/all_categorical_split_impl.hpp | 6 +++--- .../methods/decision_tree/decision_tree_impl.hpp | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index 09f717c155..25b8ffcefd 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -34,9 +34,9 @@ class AllCategoricalSplit /** * Check if we can split a node. If we can split a node in a way that * improves on 'bestGain', then we return the improved gain. Otherwise we - * return the value 'bestGain'. If a split is made, then classProbabilities - * and aux may be modified. For this particular split type, aux will be empty - * and classProbabilities will hold one element---the number of children. + * return the value 'bestGain'. If a split is made, then splitInfo and + * aux may be modified. For this particular split type, aux will be empty + * and splitInfo will store the number of children of the node. * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). @@ -69,23 +69,23 @@ class AllCategoricalSplit /** * Return the number of children in the split. * - * @param classProbabilities Auxiliary information for the split. + * @param splitInfo Auxiliary information for the split. * @param * (aux) Auxiliary information for the split (Unused). */ - static size_t NumChildren(const arma::vec& classProbabilities, + static size_t NumChildren(const double& splitInfo, const AuxiliarySplitInfo& /* aux */); /** * Calculate the direction a point should percolate to. * * @param point the Point to use. - * @param classProbabilities Column Vector of class probabilities. + * @param splitInfo Auxiliary information for the split. * @param * (aux) Auxiliary information for the split (Unused). */ template static size_t CalculateDirection( const ElemType& point, - const arma::vec& classProbabilities, + const double& splitInfo, const AuxiliarySplitInfo& /* aux */); }; diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 87da7b3d22..f7191a035b 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -111,17 +111,17 @@ double AllCategoricalSplit::SplitIfBetter( template size_t AllCategoricalSplit::NumChildren( - const arma::vec& classProbabilities, + const double& splitInfo, const AuxiliarySplitInfo& /* aux */) { - return size_t(classProbabilities[0]); + return (size_t) splitInfo; } template template size_t AllCategoricalSplit::CalculateDirection( const ElemType& point, - const arma::vec& /* classProbabilities */, + const double& /* splitInfo */, const AuxiliarySplitInfo& /* aux */) { return (size_t) point; diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index 8f04e9f57c..e6d5b63fb5 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -692,7 +692,7 @@ double DecisionTree Date: Sat, 10 Apr 2021 00:25:56 +0530 Subject: [PATCH 553/729] Improved documentation --- src/mlpack/methods/decision_tree/all_categorical_split.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index 25b8ffcefd..ec7924bb76 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -20,7 +20,9 @@ namespace tree { /** * The AllCategoricalSplit is a splitting function that will split categorical - * features into many children: one child for each category. + * features into many children: one child for each category. This is a generic + * splitting strategy and can be used for both regression and classification + * trees. * * @tparam FitnessFunction Fitness function to evaluate gain with. */ @@ -43,6 +45,7 @@ class AllCategoricalSplit * @param data The dimension of data points to check for a split in. * @param numCategories Number of categories in the categorical data. * @param labels Labels for each point. + * @param begin Start index of labels. * @param numClasses Number of classes in the dataset. * @param weights Weights associated with labels. * @param minimumLeafSize Minimum number of points in a leaf node for From ff85e20b96425a57a40131d27cedc146ee932c85 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Apr 2021 22:49:07 +0530 Subject: [PATCH 554/729] Shifted regression tree tests to new file --- src/mlpack/tests/CMakeLists.txt | 1 + .../tests/decision_tree_regressor_test.cpp | 117 ++++++++++++++++++ src/mlpack/tests/decision_tree_test.cpp | 94 -------------- 3 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 src/mlpack/tests/decision_tree_regressor_test.cpp diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 2119879ab7..33b10aa735 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable(mlpack_test cv_test.cpp dbscan_test.cpp dcgan_test.cpp + decision_tree_regressor_test.cpp decision_tree_test.cpp det_test.cpp distribution_test.cpp diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp new file mode 100644 index 0000000000..d7ccb7e3b9 --- /dev/null +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -0,0 +1,117 @@ +/** + * @file tests/decision_tree_regressor_test.cpp + * @author Rishabh Garg + * + * Tests for the DecisionTreeRegressor class and related classes. + * + * 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 +#include + +#include "catch.hpp" +#include "serialization.hpp" +#include "mock_categorical_data.hpp" + +using namespace mlpack; +using namespace mlpack::tree; +using namespace mlpack::distribution; + +/** + * Make sure the MSE gain is zero when the labels are perfect. + */ +TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights(10, arma::fill::ones); + arma::rowvec labels; + labels.ones(10); + + REQUIRE(MSEGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} + +/** + * Make sure that the MSE gain is equal to negative of variance. + */ +TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights(100, arma::fill::ones); + arma::rowvec labels(100, arma::fill::randn); + + // Theoretical gain. + double theoreticalGain = - arma::var(labels) * 99.0 / 100.0; + + // Calculated gain. + const double calculatedGain = MSEGain::Evaluate(labels, weights); + + REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-9)); +} + +/** + * The MSE gain of an empty vector is 0. + */ +TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights = arma::ones(10); + arma::rowvec labels; + REQUIRE(MSEGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); + + REQUIRE(MSEGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} + +/** + * Make sure the MAD gain is zero when the labels are perfect. + */ +TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights(10, arma::fill::ones); + arma::rowvec labels; + labels.ones(10); + + REQUIRE(MADGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} + +/** + * Make sure that when mean of labels is zero, MAD_gain = mean of + * absolute values of the distribution. + */ +TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") +{ + arma::rowvec weights(10, arma::fill::ones); + arma::rowvec labels = { 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; // Mean = 0. + + // Theoretical gain. + double theoreticalGain = 0.0; + for (size_t i = 0; i < labels.n_elem; ++i) + theoreticalGain -= std::abs(labels[i]); + theoreticalGain /= (double) labels.n_elem; + + // Calculated gain. + const double calculatedGain = MADGain::Evaluate(labels, weights); + + REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); +} + +/** + * The MAD gain of an empty vector is 0. + */ +TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressionTest]") +{ + arma::rowvec weights = arma::ones(10); + arma::rowvec labels; + REQUIRE(MADGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); + + REQUIRE(MADGain::Evaluate(labels, weights) == + Approx(0.0).margin(1e-5)); +} diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 45eb350523..06fda9fb1f 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include #include @@ -26,98 +24,6 @@ using namespace mlpack; using namespace mlpack::tree; using namespace mlpack::distribution; -/** - * Make sure the MSE gain is zero when the labels are perfect. - */ -TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressionTest]") -{ - arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels; - labels.ones(10); - - REQUIRE(MSEGain::Evaluate(labels, weights) == - Approx(0.0).margin(1e-5)); -} - -/** - * Make sure that the MSE gain is equal to negative of variance. - */ -TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") -{ - arma::rowvec weights(100, arma::fill::ones); - arma::rowvec labels(100, arma::fill::randn); - - // Theoretical gain. - double theoreticalGain = - arma::var(labels) * 99.0 / 100.0; - - // Calculated gain. - const double calculatedGain = MSEGain::Evaluate(labels, weights); - - REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-9)); -} - -/** - * The MSE gain of an empty vector is 0. - */ -TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressionTest]") -{ - arma::rowvec weights = arma::ones(10); - arma::rowvec labels; - REQUIRE(MSEGain::Evaluate(labels, weights) == - Approx(0.0).margin(1e-5)); - - REQUIRE(MSEGain::Evaluate(labels, weights) == - Approx(0.0).margin(1e-5)); -} - -/** - * Make sure the MAD gain is zero when the labels are perfect. - */ -TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") -{ - arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels; - labels.ones(10); - - REQUIRE(MADGain::Evaluate(labels, weights) == - Approx(0.0).margin(1e-5)); -} - -/** - * Make sure that when mean of labels is zero, MAD_gain = mean of - * absolute values of the distribution. - */ -TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") -{ - arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels = { 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; // Mean = 0. - - // Theoretical gain. - double theoreticalGain = 0.0; - for (size_t i = 0; i < labels.n_elem; ++i) - theoreticalGain -= std::abs(labels[i]); - theoreticalGain /= (double) labels.n_elem; - - // Calculated gain. - const double calculatedGain = MADGain::Evaluate(labels, weights); - - REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); -} - -/** - * The MAD gain of an empty vector is 0. - */ -TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressionTest]") -{ - arma::rowvec weights = arma::ones(10); - arma::rowvec labels; - REQUIRE(MADGain::Evaluate(labels, weights) == - Approx(0.0).margin(1e-5)); - - REQUIRE(MADGain::Evaluate(labels, weights) == - Approx(0.0).margin(1e-5)); -} - /** * Make sure the Gini gain is zero when the labels are perfect. */ From f541fe20b0c173cc6f11e7583866b904ddac32f2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 11 Apr 2021 00:03:57 +0530 Subject: [PATCH 555/729] Added ignored numClasses to MSE and MAD gains --- src/mlpack/methods/decision_tree/mad_gain.hpp | 3 ++- src/mlpack/methods/decision_tree/mse_gain.hpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 32102a5de3..d64d566eff 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -1,5 +1,5 @@ /** - * @file methods/decision_tree/mse_gain.hpp + * @file methods/decision_tree/mad_gain.hpp * @author Rishabh Garg * * The mean absolute deviation gain class, a fitness funtion for regression @@ -92,6 +92,7 @@ class MADGain */ template static double Evaluate(const arma::rowvec& labels, + const size_t /* numClasses */, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 7d2b3fa488..e12ae34ae4 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -88,6 +88,7 @@ class MSEGain */ template static double Evaluate(const arma::rowvec& labels, + const size_t /* numClasses */, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. From 2d20ce9099847e89f084478894df981ce0805f5a Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 11 Apr 2021 00:19:08 +0530 Subject: [PATCH 556/729] Added tests for AllCategoricalSplit for regression --- .../tests/decision_tree_regressor_test.cpp | 126 ++++++++++++++++-- 1 file changed, 112 insertions(+), 14 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index d7ccb7e3b9..a4438ac635 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -27,20 +27,20 @@ using namespace mlpack::distribution; /** * Make sure the MSE gain is zero when the labels are perfect. */ -TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressionTest]") +TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights(10, arma::fill::ones); arma::rowvec labels; labels.ones(10); - REQUIRE(MSEGain::Evaluate(labels, weights) == + REQUIRE(MSEGain::Evaluate(labels, 0, weights) == Approx(0.0).margin(1e-5)); } /** * Make sure that the MSE gain is equal to negative of variance. */ -TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") +TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights(100, arma::fill::ones); arma::rowvec labels(100, arma::fill::randn); @@ -49,7 +49,7 @@ TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") double theoreticalGain = - arma::var(labels) * 99.0 / 100.0; // Calculated gain. - const double calculatedGain = MSEGain::Evaluate(labels, weights); + const double calculatedGain = MSEGain::Evaluate(labels, 0, weights); REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-9)); } @@ -57,27 +57,27 @@ TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressionTest]") /** * The MSE gain of an empty vector is 0. */ -TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressionTest]") +TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); arma::rowvec labels; - REQUIRE(MSEGain::Evaluate(labels, weights) == + REQUIRE(MSEGain::Evaluate(labels, 0, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(labels, weights) == + REQUIRE(MSEGain::Evaluate(labels, 0, weights) == Approx(0.0).margin(1e-5)); } /** * Make sure the MAD gain is zero when the labels are perfect. */ -TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") +TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights(10, arma::fill::ones); arma::rowvec labels; labels.ones(10); - REQUIRE(MADGain::Evaluate(labels, weights) == + REQUIRE(MADGain::Evaluate(labels, 0, weights) == Approx(0.0).margin(1e-5)); } @@ -85,7 +85,7 @@ TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressionTest]") * Make sure that when mean of labels is zero, MAD_gain = mean of * absolute values of the distribution. */ -TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") +TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressorTest") { arma::rowvec weights(10, arma::fill::ones); arma::rowvec labels = { 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; // Mean = 0. @@ -97,7 +97,7 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") theoreticalGain /= (double) labels.n_elem; // Calculated gain. - const double calculatedGain = MADGain::Evaluate(labels, weights); + const double calculatedGain = MADGain::Evaluate(labels, 0, weights); REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); } @@ -105,13 +105,111 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressionTest") /** * The MAD gain of an empty vector is 0. */ -TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressionTest]") +TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); arma::rowvec labels; - REQUIRE(MADGain::Evaluate(labels, weights) == + REQUIRE(MADGain::Evaluate(labels, 0, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MADGain::Evaluate(labels, weights) == + REQUIRE(MADGain::Evaluate(labels, 0, weights) == Approx(0.0).margin(1e-5)); } + +/** + * Check that AllCategoricalSplit will split when the split is obviously + * better. + */ +TEST_CASE("AllCategoricalSplitSimpleSplitTest1", "[DecisionTreeRegressorTest]") +{ + arma::vec predictor(100); + arma::rowvec labels(100); + arma::rowvec weights(labels.n_elem); + weights.ones(); + + for (size_t i = 0; i < 100; i+=2) + { + predictor[i] = 0; + labels[i] = 5.0; + predictor[i + 1] = 1; + labels[i + 1] = 100; + } + + double splitInfo; + AllCategoricalSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double gain = AllCategoricalSplit::SplitIfBetter( + bestGain, predictor, 2, labels, 0, 0, weights, 3, 1e-7, splitInfo, aux); + const double weightedGain = + AllCategoricalSplit::SplitIfBetter(bestGain, predictor, 2, + labels, 0, 0, weights, 3, 1e-7, splitInfo, aux); + + // Make sure that a split was made. + REQUIRE(gain > bestGain); + + REQUIRE(gain == weightedGain); + + // Make sure that splitInfo now hold the number of children. + REQUIRE((size_t) splitInfo == 2); +} + +/** + * Make sure that AllCategoricalSplit respects the minimum number of samples + * required to split. + */ +TEST_CASE("AllCategoricalSplitMinSamplesTest1", "[DecisionTreeRegressorTest]") +{ + arma::rowvec predictors = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3}; + arma::rowvec labels = {0, 0, 0, 2, 2, 2, 1, 1, 1, 2, 2, 2}; + arma::rowvec weights(labels.n_elem); + weights.ones(); + + double splitInfo; + AllCategoricalSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double gain = AllCategoricalSplit::SplitIfBetter( + bestGain, predictors, 4, labels, 0, 0, weights, 4, 1e-7, splitInfo, aux); + + // Make sure it's not split. + REQUIRE(gain == DBL_MAX); +} + +/** + * Check that no split is made when it doesn't get us anything. + */ +TEST_CASE("AllCategoricalSplitNoGainTest1", "[DecisionTreeRegressorTest]") +{ + arma::rowvec predictors(300); + arma::rowvec labels(300); + arma::rowvec weights = arma::ones(300); + + for (size_t i = 0; i < 300; i += 3) + { + predictors[i] = int(i / 3) % 10; + labels[i] = -0.5; + predictors[i + 1] = int(i / 3) % 10; + labels[i + 1] = 0; + predictors[i + 2] = int(i / 3) % 10; + labels[i + 2] = 0.5; + } + + double splitInfo; + AllCategoricalSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double gain = AllCategoricalSplit::SplitIfBetter( + bestGain, predictors, 10, labels, 0, 0, weights, 10, 1e-7, + splitInfo, aux); + const double weightedGain = + AllCategoricalSplit::SplitIfBetter(bestGain, predictors, + 10, labels, 0, 0, predictors, 10, 1e-7, splitInfo, aux); + + // Make sure that there was no split. + REQUIRE(gain == DBL_MAX); + REQUIRE(gain == weightedGain); +} From 722df85864a507cf10db717fab4153dbe657223f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 11 Apr 2021 01:02:55 +0530 Subject: [PATCH 557/729] Refactored BestBinaryNumericSplit --- .../best_binary_numeric_split.hpp | 11 +++++----- .../best_binary_numeric_split_impl.hpp | 19 ++++++++---------- .../decision_tree/decision_tree_impl.hpp | 20 ++++++++++--------- src/mlpack/tests/decision_tree_test.cpp | 18 ++++++++--------- 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index ab081c84fc..e8975ee75a 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -49,8 +49,7 @@ class BestBinaryNumericSplit * @param minimumLeafSize Minimum number of points in a leaf node for * splitting. * @param minimumGainSplit Minimum gain split. - * @param classProbabilities Class probabilities vector, which may be filled - * with split information a successful split. + * @param splitInfo Stores split information on a successful split. * @param aux Auxiliary split information, which may be modified on a * successful split. */ @@ -63,13 +62,13 @@ class BestBinaryNumericSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::vec& classProbabilities, + double& splitInfo, AuxiliarySplitInfo& aux); /** * Returns 2, since the binary split always has two children. */ - static size_t NumChildren(const arma::vec& /* classProbabilities */, + static size_t NumChildren(const double& /* splitInfo */, const AuxiliarySplitInfo& /* aux */) { return 2; @@ -79,13 +78,13 @@ class BestBinaryNumericSplit * Given a point, calculate which child it should go to (left or right). * * @param point Point to calculate direction of. - * @param classProbabilities Auxiliary information for the split. + * @param splitInfo Auxiliary information for the split. * @param * (aux) Auxiliary information for the split (Unused). */ template static size_t CalculateDirection( const ElemType& point, - const arma::vec& classProbabilities, + const double& splitInfo, const AuxiliarySplitInfo& /* aux */); }; diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 14bd0e3fb9..c0ad1f1f46 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -25,7 +25,7 @@ double BestBinaryNumericSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::vec& classProbabilities, + double& splitInfo, AuxiliarySplitInfo& /* aux */) { // First sanity check: if we don't have enough points, we can't split. @@ -151,12 +151,10 @@ double BestBinaryNumericSplit::SplitIfBetter( // Corner case: is this the best possible split? if (gain >= 0.0) { - // We can take a shortcut: no split will be better than this, so just take - // this one. - classProbabilities.set_size(1); - // The actual split value will be halfway between the value at index - 1 - // and index. - classProbabilities[0] = (data[sortedIndices[index - 1]] + + // We can take a shortcut: no split will be better than this, so just + // take this one. The actual split value will be halfway between the + // value at index - 1 and index. + splitInfo = (data[sortedIndices[index - 1]] + data[sortedIndices[index]]) / 2.0; return gain; @@ -165,8 +163,7 @@ double BestBinaryNumericSplit::SplitIfBetter( { // We still have a better split. bestFoundGain = gain; - classProbabilities.set_size(1); - classProbabilities[0] = (data[sortedIndices[index - 1]] + + splitInfo = (data[sortedIndices[index - 1]] + data[sortedIndices[index]]) / 2.0; improved = true; } @@ -189,10 +186,10 @@ template template size_t BestBinaryNumericSplit::CalculateDirection( const ElemType& point, - const arma::vec& classProbabilities, + const double& splitInfo, const AuxiliarySplitInfo& /* aux */) { - if (point <= classProbabilities[0]) + if (point <= splitInfo) return 0; // Go left. else return 1; // Go right. diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index e6d5b63fb5..b897530b3f 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -636,13 +636,13 @@ double DecisionTree(bestGain, data.cols(begin, begin + count - 1).row(i), datasetInfo.NumMappings(i), @@ -664,7 +664,7 @@ double DecisionTree childAssignments(count); @@ -709,7 +709,7 @@ double DecisionTree::NumClasses() const { - // Recurse to the nearest child and return the number of elements in the + // Recurse to the nearest leaf and return the number of elements in the // probability vector. if (children.size() == 0) return classProbabilities.n_elem; diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 06fda9fb1f..2f63872f23 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -288,17 +288,17 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); weights.ones(); - arma::vec classProbabilities; + arma::vec classProbabilities(1); BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities[0], aux); const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 3, 1e-7, classProbabilities, aux); + labels, 2, weights, 3, 1e-7, classProbabilities[0], aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -326,23 +326,22 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); arma::rowvec weights(labels.n_elem); - arma::vec classProbabilities; + arma::vec classProbabilities(1); BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); // This should make no difference because it won't split at all. const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 8, 1e-7, classProbabilities, aux); + labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); - REQUIRE(classProbabilities.n_elem == 0); } /** @@ -362,18 +361,17 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities; + arma::vec classProbabilities(1); BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities[0], aux); // Make sure there was no split. REQUIRE(gain == DBL_MAX); - REQUIRE(classProbabilities.n_elem == 0); } /** From 7e336ad118220ceaf72ee08680e7746534b9333c Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 12 Apr 2021 22:57:48 +0530 Subject: [PATCH 558/729] Fixed implementation bug in calculating sum of subvector --- src/mlpack/methods/decision_tree/utils.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/decision_tree/utils.hpp b/src/mlpack/methods/decision_tree/utils.hpp index d7da7cbd16..1928803e88 100644 --- a/src/mlpack/methods/decision_tree/utils.hpp +++ b/src/mlpack/methods/decision_tree/utils.hpp @@ -106,16 +106,16 @@ void Sum(const arma::rowvec& labels, } // Handle leftovers. - if (labels.n_elem % 4 == 1) + if ((end - begin) % 4 == 1) { total[0] += labels[end - 1]; } - else if (labels.n_elem % 4 == 2) + else if ((end - begin) % 4 == 2) { total[0] += labels[end - 2]; total[1] += labels[end - 1]; } - else if (labels.n_elem % 4 == 3) + else if ((end - begin) % 4 == 3) { total[0] += labels[end - 3]; total[1] += labels[end - 2]; From 536c5f9880c30b32f2f89443a5ed9f956855113b Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 12 Apr 2021 23:05:21 +0530 Subject: [PATCH 559/729] Implemented best binary split for regression --- .../best_binary_numeric_split.hpp | 41 +++++++-- .../best_binary_numeric_split_impl.hpp | 89 +++++++++++++++++++ 2 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index e8975ee75a..5211f69f8d 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -33,12 +33,10 @@ class BestBinaryNumericSplit /** * Check if we can split a node. If we can split a node in a way that * improves on 'bestGain', then we return the improved gain. Otherwise we - * return the value 'bestGain'. If a split is made, then classProbabilities - * and aux may be modified. + * return the value 'bestGain'. If a split is made, then splitInfo and aux + * may be modified. * - * It's not necessary that `ElemType` is the same as the type of the data in - * `VecType`---if they are different, casting will be done to store the - * auxiliary information. + * It is used only for classification tasks. * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). @@ -65,6 +63,39 @@ class BestBinaryNumericSplit double& splitInfo, AuxiliarySplitInfo& aux); + /** + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then splitInfo and aux + * may be modified. + * + * It is used only for regression tasks. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param labels Labels for each point. + * @param numClasses Number of classes in the dataset. + * @param weights Weights associated with labels. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param minimumGainSplit Minimum gain split. + * @param splitInfo Stores split information on a successful split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + */ + template + static double SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const size_t numClasses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& aux); + /** * Returns 2, since the binary split always has two children. */ diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index c0ad1f1f46..386f032875 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -182,6 +182,95 @@ double BestBinaryNumericSplit::SplitIfBetter( return bestFoundGain; } +template +template +double BestBinaryNumericSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const size_t numClasses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& /* aux */) +{ + // First sanity check: if we don't have enough points, we can't split. + if (data.n_elem < (minimumLeafSize * 2)) + return DBL_MAX; + if (bestGain == 0.0) + return DBL_MAX; // It can't be outperformed. + + // Next, sort the data. + arma::uvec sortedIndices = arma::sort_index(data); + arma::Row sortedLabels(labels.n_elem); + arma::rowvec sortedWeights; + for (size_t i = 0; i < sortedLabels.n_elem; ++i) + sortedLabels[i] = labels[sortedIndices[i]]; + + // Sanity check: if the first element is the same as the last, we can't split + // in this dimension. + if (data[sortedIndices[0]] == data[sortedIndices[sortedIndices.n_elem - 1]]) + return DBL_MAX; + + // Only initialize if we are using weights. + if (UseWeights) + { + sortedWeights.set_size(sortedLabels.n_elem); + // The weights must keep the same order as the labels. + for (size_t i = 0; i < sortedLabels.n_elem; ++i) + sortedWeights[i] = weights[sortedIndices[i]]; + } + + double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); + bool improved = false; + // Force a minimum leaf size of 1 (empty children don't make sense). + const size_t minimum = std::max(minimumLeafSize, (size_t) 1); + + // Loop through all possible split points, choosing the best one. + for (size_t index = minimum; index < data.n_elem - minimum + 1; ++index) + { + // Make sure that the value has changed. + if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) + continue; + + // Calculate the gain for the left and right child. + const double leftGain = FitnessFunction::template Evaluate(sortedLabels, + sortedWeights, 0, index); + const double rightGain = FitnessFunction::template Evaluate(sortedLabels, + sortedWeights, index, labels.n_elem); + + double gain = leftGain + rightGain; + + // Corner case: is this the best possible split? + if (gain >= 0.0) + { + // We can take a shortcut: no split will be better than this, so just + // take this one. The actual split value will be halfway between the + // value at index - 1 and index. + splitInfo = (data[sortedIndices[index - 1]] + + data[sortedIndices[index]]) / 2.0; + + return gain; + } + if (gain > bestFoundGain) + { + // We still have a better split. + bestFoundGain = gain; + splitInfo = (data[sortedIndices[index - 1]] + + data[sortedIndices[index]]) / 2.0; + improved = true; + } + } + + // If we didn't improve, return the original gain exactly as we got it + // (without introducing floating point errors). + if (!improved) + return DBL_MAX; + + return bestFoundGain; +} + template template size_t BestBinaryNumericSplit::CalculateDirection( From ab4f3c3646262a3a10360b3cea86979032a69558 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 12 Apr 2021 23:05:59 +0530 Subject: [PATCH 560/729] Added tests for best binary split --- .../tests/decision_tree_regressor_test.cpp | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index a4438ac635..b020009a1e 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -213,3 +213,96 @@ TEST_CASE("AllCategoricalSplitNoGainTest1", "[DecisionTreeRegressorTest]") REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); } + +/** + * Check that the BestBinaryNumericSplit will split on an obviously splittable + * dimension. + */ +TEST_CASE("BestBinaryNumericSplitSimpleSplitTest1", "[DecisionTreeRegressorTest]") +{ + arma::rowvec predictors = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; + arma::rowvec labels = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; + arma::rowvec weights(labels.n_elem); + weights.ones(); + + double splitInfo; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MADGain::Evaluate(labels, 0, weights); + const double gain = BestBinaryNumericSplit::SplitIfBetter( + bestGain, predictors, labels, 0, weights, 3, 1e-7, splitInfo, + aux); + const double weightedGain = + BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, + labels, 0, weights, 3, 1e-7, splitInfo, aux); + + // Make sure that a split was made. + REQUIRE(gain > bestGain); + + // Make sure weight works and is not different than the unweighted one. + REQUIRE(gain == weightedGain); + + // The class probabilities, for this split, hold the splitting point, which + // should be between 4 and 5. + REQUIRE(splitInfo > 0.4); + REQUIRE(splitInfo < 0.5); + std::cout << "Done\n"; +} + +/** + * Check that the BestBinaryNumericSplit won't split if not enough points are + * given. + */ +TEST_CASE("BestBinaryNumericSplitMinSamplesTest1", "[DecisionTreeRegressorTest]") +{ + arma::rowvec predictors = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; + arma::rowvec labels = { 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; + arma::rowvec weights(labels.n_elem); + + double splitInfo; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double gain = BestBinaryNumericSplit::SplitIfBetter( + bestGain, predictors, labels, 0, weights, 8, 1e-7, splitInfo, aux); + // This should make no difference because it won't split at all. + const double weightedGain = + BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, + labels, 0, weights, 8, 1e-7, splitInfo, aux); + + // Make sure that no split was made. + REQUIRE(gain == DBL_MAX); + REQUIRE(gain == weightedGain); +} + +/** + * Check that the BestBinaryNumericSplit doesn't split a dimension that gives no + * gain. + */ +TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") +{ + arma::rowvec predictors(100); + arma::rowvec labels(100); + arma::rowvec weights; + for (size_t i = 0; i < 100; i += 2) + { + predictors[i] = i; + labels[i] = 0.0; + predictors[i + 1] = i; + labels[i + 1] = 1.0; + } + + double splitInfo; + BestBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double gain = BestBinaryNumericSplit::SplitIfBetter( + bestGain, predictors, labels, 0, weights, 10, 1e-7, splitInfo, + aux); + + // Make sure there was no split. + REQUIRE(gain == DBL_MAX); +} From c4e3d1fcc3ae88cc23b3c7201c1c86305d8e4c18 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 3 May 2021 11:33:38 +0530 Subject: [PATCH 561/729] Add TODO for optimization in BestBinaryNumericSplit for regression --- .../methods/decision_tree/best_binary_numeric_split_impl.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 386f032875..45f4551600 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -234,6 +234,11 @@ double BestBinaryNumericSplit::SplitIfBetter( if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) continue; + /* TODO: The following function calculates the gain for each split each time from scratch + This can be greatly improved using advanced techniques like prefix sum and + prefix sum of squares etc. This will have drastic effects on runtime and is + definitely something we would want in future. + */ // Calculate the gain for the left and right child. const double leftGain = FitnessFunction::template Evaluate(sortedLabels, sortedWeights, 0, index); From c6f0d2945743652b30f8119add9f1980e0306f66 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 3 May 2021 13:35:49 +0530 Subject: [PATCH 562/729] Make LabelsType a new template parameter and use subvec for labels --- .../methods/decision_tree/all_categorical_split.hpp | 5 ++--- .../decision_tree/all_categorical_split_impl.hpp | 11 +++++------ .../methods/decision_tree/decision_tree_impl.hpp | 3 +-- src/mlpack/tests/decision_tree_regressor_test.cpp | 10 +++++----- src/mlpack/tests/decision_tree_test.cpp | 10 +++++----- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index ec7924bb76..f929e506c1 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -55,13 +55,12 @@ class AllCategoricalSplit * @param aux Auxiliary split information, which may be modified on a * successful split. */ - template + template static double SplitIfBetter( const double bestGain, const VecType& data, const size_t numCategories, - const arma::Row& labels, - const size_t begin, + const LabelsType& labels, const size_t numClasses, const WeightVecType& weights, const size_t minimumLeafSize, diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index f7191a035b..754a092737 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -16,13 +16,12 @@ namespace mlpack { namespace tree { template -template +template double AllCategoricalSplit::SplitIfBetter( const double bestGain, const VecType& data, const size_t numCategories, - const arma::Row& labels, - const size_t begin, + const LabelsType& labels, const size_t numClasses, const WeightVecType& weights, const size_t minimumLeafSize, @@ -59,7 +58,7 @@ double AllCategoricalSplit::SplitIfBetter( // Calculate the gain of the split. First we have to calculate the labels // that would be assigned to each child. arma::uvec childPositions(numCategories, arma::fill::zeros); - std::vector> childLabels(numCategories); + std::vector> childLabels(numCategories); std::vector> childWeights(numCategories); for (size_t i = 0; i < numCategories; ++i) { @@ -76,12 +75,12 @@ double AllCategoricalSplit::SplitIfBetter( if (UseWeights) { - childLabels[category][childPositions[category]] = labels[begin + i]; + childLabels[category][childPositions[category]] = labels[i]; childWeights[category][childPositions[category]++] = weights[i]; } else { - childLabels[category][childPositions[category]++] = labels[begin + i]; + childLabels[category][childPositions[category]++] = labels[i]; } } diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index b897530b3f..0c5d106002 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -646,8 +646,7 @@ double DecisionTree(bestGain, data.cols(begin, begin + count - 1).row(i), datasetInfo.NumMappings(i), - labels, - begin, + labels.subvec(begin, begin + count - 1), numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index b020009a1e..c8a4db9d03 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -141,10 +141,10 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest1", "[DecisionTreeRegressorTest]") // Call the method to do the splitting. const double bestGain = MSEGain::Evaluate(labels, 0, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictor, 2, labels, 0, 0, weights, 3, 1e-7, splitInfo, aux); + bestGain, predictor, 2, labels, 0, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictor, 2, - labels, 0, 0, weights, 3, 1e-7, splitInfo, aux); + labels, 0, weights, 3, 1e-7, splitInfo, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -172,7 +172,7 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest1", "[DecisionTreeRegressorTest]") // Call the method to do the splitting. const double bestGain = MSEGain::Evaluate(labels, 0, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 4, labels, 0, 0, weights, 4, 1e-7, splitInfo, aux); + bestGain, predictors, 4, labels, 0, weights, 4, 1e-7, splitInfo, aux); // Make sure it's not split. REQUIRE(gain == DBL_MAX); @@ -203,11 +203,11 @@ TEST_CASE("AllCategoricalSplitNoGainTest1", "[DecisionTreeRegressorTest]") // Call the method to do the splitting. const double bestGain = MSEGain::Evaluate(labels, 0, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 10, labels, 0, 0, weights, 10, 1e-7, + bestGain, predictors, 10, labels, 0, weights, 10, 1e-7, splitInfo, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictors, - 10, labels, 0, 0, predictors, 10, 1e-7, splitInfo, aux); + 10, labels, 0, predictors, 10, 1e-7, splitInfo, aux); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 2f63872f23..d02a49f75a 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -493,11 +493,11 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest", "[DecisionTreeTest]") // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 4, labels, 0, 3, weights, 3, 1e-7, classProbabilities[0], + bestGain, values, 4, labels, 3, weights, 3, 1e-7, classProbabilities[0], aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, values, 4, - labels, 0, 3, weights, 3, 1e-7, classProbabilities[0], aux); + labels, 3, weights, 3, 1e-7, classProbabilities[0], aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -529,7 +529,7 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest", "[DecisionTreeTest]") // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 4, labels, 0, 3, weights, 4, 1e-7, + bestGain, values, 4, labels, 3, weights, 4, 1e-7, classProbabilities[0], aux); // Make sure it's not split. @@ -561,11 +561,11 @@ TEST_CASE("AllCategoricalSplitNoGainTest", "[DecisionTreeTest]") // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 10, labels, 0, 3, weights, 10, 1e-7, + bestGain, values, 10, labels, 3, weights, 10, 1e-7, classProbabilities[0], aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, values, 10, - labels, 0, 3, weights, 10, 1e-7, classProbabilities[0], aux); + labels, 3, weights, 10, 1e-7, classProbabilities[0], aux); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); From 0449ace9228ce944ce8d3908dddd86d86e9aaefe Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 3 May 2021 13:41:49 +0530 Subject: [PATCH 563/729] Update documentation --- src/mlpack/methods/decision_tree/all_categorical_split.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index f929e506c1..2ac91b099a 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -45,7 +45,6 @@ class AllCategoricalSplit * @param data The dimension of data points to check for a split in. * @param numCategories Number of categories in the categorical data. * @param labels Labels for each point. - * @param begin Start index of labels. * @param numClasses Number of classes in the dataset. * @param weights Weights associated with labels. * @param minimumLeafSize Minimum number of points in a leaf node for From dcc96c056ce9d07a3bddfd50999e58c360f7dc25 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 10 May 2021 14:30:37 +0530 Subject: [PATCH 564/729] Amend RandomBinaryNumericSplit signature to support regression --- .../random_binary_numeric_split.hpp | 18 ++++++++---------- .../random_binary_numeric_split_impl.hpp | 9 ++++----- src/mlpack/tests/decision_tree_test.cpp | 14 ++++++-------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index d7ab4732f8..98e1772ca7 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -34,7 +34,7 @@ class RandomBinaryNumericSplit /** * Check if we can split a node. If we can split a node in a way that * improves on 'bestGain', then we return the improved gain. Otherwise we - * return the value 'bestGain'. If a split is made, then classProbabilities + * return the value 'bestGain'. If a split is made, then splitInfo * and aux may be modified. * * @code @@ -66,8 +66,7 @@ class RandomBinaryNumericSplit * @param minimumLeafSize Minimum number of points in a leaf node for * splitting. * @param minimumGainSplit Minimum gain split. - * @param classProbabilities Class probabilities vector, which may be filled - * with split information a successful split. + * @param splitInfo Stores split information on a successful split. * @param aux Auxiliary split information, which may be modified on a * successful split. * @param splitIfBetterGain When set to true, it will split only when gain is @@ -83,19 +82,18 @@ class RandomBinaryNumericSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::vec& classProbabilities, + double& splitInfo, AuxiliarySplitInfo& aux, const bool splitIfBetterGain = false); /** * Returns 2, since the binary split always has two children. * - * @param classProbabilities Class probabilities vector, which may be filled - * with split information a successful split. (Not used here.) + * @param splitInfo Auxiliary information for the split. * @param aux Auxiliary split information, which may be modified on a - * successful split. (Not used here.) + * successful split. */ - static size_t NumChildren(const arma::vec& /* classProbabilities */, + static size_t NumChildren(const double& /* splitInfo */, const AuxiliarySplitInfo& /* aux */) { return 2; @@ -105,13 +103,13 @@ class RandomBinaryNumericSplit * Given a point, calculate which child it should go to (left or right). * * @param point Point to calculate direction of. - * @param classProbabilities Auxiliary information for the split. + * @param splitInfo Auxiliary information for the split. * @param * (aux) Auxiliary information for the split (Unused). */ template static size_t CalculateDirection( const ElemType& point, - const arma::vec& classProbabilities, + const double& splitInfo, const AuxiliarySplitInfo& /* aux */); }; diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 555113970c..4b5b792b13 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -27,7 +27,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - arma::vec& classProbabilities, + double& splitInfo, AuxiliarySplitInfo& /* aux */, const bool splitIfBetterGain) { @@ -125,8 +125,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( if (gain < bestFoundGain && splitIfBetterGain) return DBL_MAX; - classProbabilities.set_size(1); - classProbabilities(0) = randomPivot; + splitInfo = randomPivot; if (UseWeights) gain /= totalWeight; @@ -140,10 +139,10 @@ template template size_t RandomBinaryNumericSplit::CalculateDirection( const ElemType& point, - const arma::vec& classProbabilities, + const double& splitInfo, const AuxiliarySplitInfo& /* aux */) { - if (point <= classProbabilities(0)) + if (point <= splitInfo) return 0; // Go left. else return 1; // Go right. diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index d02a49f75a..efd728fb72 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -384,23 +384,22 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); arma::rowvec weights(labels.n_elem); - arma::vec classProbabilities; + arma::vec classProbabilities(1); RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); // This should make no difference because it won't split at all. const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 8, 1e-7, classProbabilities, aux); + labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); - REQUIRE(classProbabilities.n_elem == 0); } /** @@ -420,18 +419,17 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities; + arma::vec classProbabilities(1); RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities[0], aux, true); // Make sure there was no split. REQUIRE(gain == DBL_MAX); - REQUIRE(classProbabilities.n_elem == 0); } /** @@ -451,7 +449,7 @@ TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities, classProbabilities1; + arma::vec classProbabilities(1), classProbabilities1(1); BestBinaryNumericSplit::AuxiliarySplitInfo aux; RandomBinaryNumericSplit::AuxiliarySplitInfo aux1; From be81c14a52b50bc8fcf34417fb21fa8a81e9f8ef Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 11 May 2021 10:02:24 +0530 Subject: [PATCH 565/729] Implement DecisionTreeRegressor --- .../decision_tree/decision_tree_regressor.hpp | 138 +++++ .../decision_tree_regressor_impl.hpp | 516 +++++++++++++++++- 2 files changed, 625 insertions(+), 29 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 17358d07a6..55f6816f7e 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -373,6 +373,144 @@ class DecisionTreeRegressor : DimensionSelectionType(), const std::enable_if_t::type>::value>* = 0); + + /** + * Make prediction for the given point, using the entire tree. The predicted + * label is returned. + * + * @param point Point to predict. + */ + template + double Predict(const VecType& point) const; + + /** + * Make prediction for the given points, using the entire tree. The predicted + * labels for each point are stored in the given vector. + * + * @param data Set of points to predict. + * @param predictions This will be filled with predictions for each point. + */ + template + void Predict(const MatType& data, + arma::Row& predictions) const; + + /** + * Serialize the tree. + */ + template + void serialize(Archive& ar, const uint32_t /* version */); + + //! Get the number of children. + size_t NumChildren() const { return children.size(); } + + //! Get the child of the given index. + const DecisionTreeRegressor& Child(const size_t i) const { return *children[i]; } + //! Modify the child of the given index (be careful!). + DecisionTreeRegressor& Child(const size_t i) { return *children[i]; } + + //! Get the split dimension (only meaningful if this is a non-leaf in a + //! trained tree). + size_t SplitDimension() const { return splitDimension; } + + /** + * Given a point and that this node is not a leaf, calculate the index of the + * child node this point would go towards. This method is primarily used by + * the Predict() function, but it can be used in a standalone sense too. + * + * @param point Point to predict. + */ + template + size_t CalculateDirection(const VecType& point) const; + + private: + //! The vector of children. + std::vector children; + //! The dimension this node splits on. + size_t splitDimension; + //! The type of the dimension that we have split on (only meaningful if this + //! is a non-leaf in a trained tree). + size_t dimensionType; + /** + * This variable may hold different things. If the node has no children, then + * it is guaranteed to hold the prediction label for that node. If the node + * has children, then it may be used arbitrarily by the split type's + * CalculateDirection() and SplitIfBetter() function. In this case, it stores + * the point at which the split was made. + */ + double splitPointOrPrediction; + + //! Note that this class will also hold the members of the NumericSplit and + //! CategoricalSplit AuxiliarySplitInfo classes, since it inherits from them. + //! We'll define some convenience typedefs here. + typedef typename NumericSplit::AuxiliarySplitInfo + NumericAuxiliarySplitInfo; + typedef typename CategoricalSplit::AuxiliarySplitInfo + CategoricalAuxiliarySplitInfo; + + /** + * Calculate the prediction label for the leaf nodes. + */ + template + void CalculatePrediction(const LabelsType& labels, + const WeightsType& weights); + + /** + * Corresponding to the public Train() method, this method is designed for + * avoiding unnecessary copies during training. This function is called to + * train children. + * + * @param data Dataset to train on. + * @param begin Index of the starting point in the dataset that belongs to + * this node. + * @param count Number of points in this node. + * @param datasetInfo Type information for each dimension. + * @param labels Labels for each training point. + * @param numClasses Number of classes in the dataset. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @return The final entropy of decision tree. + */ + template + double Train(MatType& data, + const size_t begin, + const size_t count, + const data::DatasetInfo& datasetInfo, + LabelsType& labels, + const size_t numClasses, + arma::rowvec& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType& dimensionSelector); + + /** + * Corresponding to the public Train() method, this method is designed for + * avoiding unnecessary copies during training. This method is called for + * training children. + * + * @param data Dataset to train on. + * @param begin Index of the starting point in the dataset that belongs to + * this node. + * @param count Number of points in this node. + * @param labels Labels for each training point. + * @param numClasses Number of classes in the dataset. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @return The final entropy of decision tree. + */ + template + double Train(MatType& data, + const size_t begin, + const size_t count, + LabelsType& labels, + const size_t numClasses, + arma::rowvec& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType& dimensionSelector); }; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 1145b110e0..606518ba3c 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -13,6 +13,7 @@ #define MLPACK_METHODS_DECISION_TREE_DECISION_TREE_REGRESSOR_IMPL_HPP #include "decision_tree_regressor.hpp" +#include "utils.hpp" namespace mlpack { namespace tree { @@ -29,11 +30,10 @@ DecisionTreeRegressor::DecisionTreeRegressor() : splitDimension(0), - dimensionTypeOrMajorityClass(0), - classProbabilities(numClasses) + dimensionType(0), + splitPointOrPrediction(0.0) { - // Initialize utility vector. - classProbabilities.fill(1.0 / (double) numClasses); + // Nothing to do here. } //! Construct and train without weight. @@ -68,7 +68,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -104,7 +104,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, weights, + Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -144,7 +144,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -186,7 +186,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights, + Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -206,7 +206,6 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit); } @@ -268,7 +267,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights, + Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -288,8 +287,8 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, - numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, + 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -494,7 +489,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, + return Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -541,7 +536,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, - numClasses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -585,11 +580,474 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, + return Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } +//! Train on the given data. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType& data, + const size_t begin, + const size_t count, + const data::DatasetInfo& datasetInfo, + LabelsType& labels, + const size_t numClasses, + arma::rowvec& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType& dimensionSelector) +{ + // Clear children if needed. + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; + children.clear(); + + // Look through the list of dimensions and obtain the gain of the best split. + // We'll cache the best numeric and categorical split auxiliary information in + // numericAux and categoricalAux (and clear them later if we make no split), + double bestGain = FitnessFunction::template Evaluate( + labels.subvec(begin, begin + count - 1), + numClasses, + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + size_t bestDim = datasetInfo.Dimensionality(); // This means "no split". + const size_t end = dimensionSelector.End(); + + if (maximumDepth != 1) + { + for (size_t i = dimensionSelector.Begin(); i != end; + i = dimensionSelector.Next()) + { + double dimGain = -DBL_MAX; + if (datasetInfo.Type(i) == data::Datatype::categorical) + { + dimGain = CategoricalSplit::template SplitIfBetter(bestGain, + data.cols(begin, begin + count - 1).row(i), + datasetInfo.NumMappings(i), + labels.subvec(begin, begin + count - 1), + numClasses, + UseWeights ? weights.subvec(begin, begin + count - 1) : weights, + minimumLeafSize, + minimumGainSplit, + splitPointOrPrediction, + *this); + } + else if (datasetInfo.Type(i) == data::Datatype::numeric) + { + dimGain = NumericSplit::template SplitIfBetter(bestGain, + data.cols(begin, begin + count - 1).row(i), + labels.subvec(begin, begin + count - 1), + numClasses, + UseWeights ? weights.subvec(begin, begin + count - 1) : weights, + minimumLeafSize, + minimumGainSplit, + splitPointOrPrediction, + *this); + } + + // If the splitter reported that it did not split, move to the next + // dimension. + if (dimGain == DBL_MAX) + continue; + + // Was there an improvement? If so mark that it's the new best dimension. + bestDim = i; + bestGain = dimGain; + + // If the gain is the best possible, no need to keep looking. + if (bestGain >= 0.0) + break; + } + } + + // Did we split or not? If so, then split the data and create the children. + if (bestDim != datasetInfo.Dimensionality()) + { + dimensionType = (size_t) datasetInfo.Type(bestDim); + splitDimension = bestDim; + + // Get the number of children we will have. + size_t numChildren = 0; + if (datasetInfo.Type(bestDim) == data::Datatype::categorical) + numChildren = CategoricalSplit::NumChildren(splitPointOrPrediction, *this); + else + numChildren = NumericSplit::NumChildren(splitPointOrPrediction, *this); + + // Calculate all child assignments. + arma::Row childAssignments(count); + if (datasetInfo.Type(bestDim) == data::Datatype::categorical) + { + for (size_t j = begin; j < begin + count; ++j) + childAssignments[j - begin] = CategoricalSplit::CalculateDirection( + data(bestDim, j), splitPointOrPrediction, *this); + } + else + { + for (size_t j = begin; j < begin + count; ++j) + { + childAssignments[j - begin] = NumericSplit::CalculateDirection( + data(bestDim, j), splitPointOrPrediction, *this); + } + } + + // Figure out counts of children. + arma::Row childCounts(numChildren, arma::fill::zeros); + for (size_t i = begin; i < begin + count; ++i) + childCounts[childAssignments[i - begin]]++; + + // Initialize bestGain if recursive split is allowed. + if (!NoRecursion) + { + bestGain = 0.0; + } + + // Split into children. + size_t currentCol = begin; + for (size_t i = 0; i < numChildren; ++i) + { + size_t currentChildBegin = currentCol; + for (size_t j = currentChildBegin; j < begin + count; ++j) + { + if (childAssignments[j - begin] == i) + { + childAssignments.swap_cols(currentCol - begin, j - begin); + data.swap_cols(currentCol, j); + labels.swap_cols(currentCol, j); + if (UseWeights) + weights.swap_cols(currentCol, j); + ++currentCol; + } + } + + // Now build the child recursively. + DecisionTreeRegressor* child = new DecisionTreeRegressor(); + if (NoRecursion) + { + child->Train(data, currentChildBegin, + currentCol - currentChildBegin, datasetInfo, labels, numClasses, + weights, currentCol - currentChildBegin, minimumGainSplit, + maximumDepth - 1, dimensionSelector); + } + else + { + // During recursion entropy of child node may change. + double childGain = child->Train(data, currentChildBegin, + currentCol - currentChildBegin, datasetInfo, labels, numClasses, + weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, + dimensionSelector); + bestGain += double(childCounts[i]) / double(count) * (-childGain); + } + children.push_back(child); + } + } + else + { + // Clear auxiliary info objects. + NumericAuxiliarySplitInfo::operator=(NumericAuxiliarySplitInfo()); + CategoricalAuxiliarySplitInfo::operator=(CategoricalAuxiliarySplitInfo()); + + // Calculate prediction label because we are a leaf. + CalculatePrediction( + labels.subvec(begin, begin + count - 1), + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + } + + return -bestGain; +} + +//! Train on the given data, assuming all dimensions are numeric. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType& data, + const size_t begin, + const size_t count, + LabelsType& labels, + const size_t numClasses, + arma::rowvec& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType& dimensionSelector) +{ + // Clear children if needed. + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; + children.clear(); + + // We won't be using these members, so reset them. + CategoricalAuxiliarySplitInfo::operator=(CategoricalAuxiliarySplitInfo()); + + // Look through the list of dimensions and obtain the best split. We'll cache + // the best numeric split auxiliary information in numericAux (and clear it + // later if we don't make a split), and use classProbabilities as auxiliary + // information. Later we'll overwrite classProbabilities to the empirical + // class probabilities if we do not split. + double bestGain = FitnessFunction::template Evaluate( + labels.subvec(begin, begin + count - 1), + numClasses, + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + size_t bestDim = data.n_rows; // This means "no split". + + if (maximumDepth != 1) + { + for (size_t i = dimensionSelector.Begin(); i != dimensionSelector.End(); + i = dimensionSelector.Next()) + { + const double dimGain = NumericSplitType::template + SplitIfBetter(bestGain, + data.cols(begin, begin + count - 1).row(i), + labels.cols(begin, begin + count - 1), + numClasses, + UseWeights ? + weights.cols(begin, begin + count - 1) : + weights, + minimumLeafSize, + minimumGainSplit, + splitPointOrPrediction, + *this); + + // If the splitter did not report that it improved, then move to the next + // dimension. + if (dimGain == DBL_MAX) + continue; + + bestDim = i; + bestGain = dimGain; + + // If the gain is the best possible, no need to keep looking. + if (bestGain >= 0.0) + break; + } + } + + // Did we split or not? If so, then split the data and create the children. + if (bestDim != data.n_rows) + { + // We know that the split is numeric. + size_t numChildren = NumericSplit::NumChildren(splitPointOrPrediction, *this); + splitDimension = bestDim; + dimensionType = (size_t) data::Datatype::numeric; + + // Calculate all child assignments. + arma::Row childAssignments(count); + + for (size_t j = begin; j < begin + count; ++j) + { + childAssignments[j - begin] = NumericSplit::CalculateDirection( + data(bestDim, j), splitPointOrPrediction, *this); + } + + // Calculate counts of children in each node. + arma::Row childCounts(numChildren); + childCounts.zeros(); + for (size_t j = begin; j < begin + count; ++j) + childCounts[childAssignments[j - begin]]++; + + // Initialize bestGain if recursive split is allowed. + if (!NoRecursion) + { + bestGain = 0.0; + } + + size_t currentCol = begin; + for (size_t i = 0; i < numChildren; ++i) + { + size_t currentChildBegin = currentCol; + for (size_t j = currentChildBegin; j < begin + count; ++j) + { + if (childAssignments[j - begin] == i) + { + childAssignments.swap_cols(currentCol - begin, j - begin); + data.swap_cols(currentCol, j); + labels.swap_cols(currentCol, j); + if (UseWeights) + weights.swap_cols(currentCol, j); + ++currentCol; + } + } + + // Now build the child recursively. + DecisionTreeRegressor* child = new DecisionTreeRegressor(); + if (NoRecursion) + { + child->Train(data, currentChildBegin, + currentCol - currentChildBegin, labels, numClasses, weights, + currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, + dimensionSelector); + } + else + { + // During recursion entropy of child node may change. + double childGain = child->Train(data, currentChildBegin, + currentCol - currentChildBegin, labels, numClasses, weights, + minimumLeafSize, minimumGainSplit, maximumDepth - 1, + dimensionSelector); + bestGain += double(childCounts[i]) / double(count) * (-childGain); + } + children.push_back(child); + } + } + else + { + // We won't be needing these members, so reset them. + NumericAuxiliarySplitInfo::operator=(NumericAuxiliarySplitInfo()); + + // Calculate prediction label because we are a leaf. + CalculatePrediction( + labels.subvec(begin, begin + count - 1), + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + } + + return -bestGain; +} + +//! Return the prediction. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Predict(const VecType& point) const +{ + if (children.size() == 0) + { + // Return cached prediction. + return splitPointOrPrediction; + } + + return children[CalculateDirection(point)]->Predict(point); +} + +//! Return the predictions for a set of points. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +void DecisionTreeRegressor::Predict(const MatType& data, arma::Row& predictions) const +{ + predictions.set_size(data.n_cols); + // If the tree's root is leaf. + if (children.size() == 0) + { + predictions.fill(splitPointOrPrediction); + return; + } + + // Loop over each point. + for (size_t i = 0; i < data.n_cols; ++i) + predictions[i] = Predict(data.col(i)); +} + +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +void DecisionTreeRegressor::CalculatePrediction(const LabelsType& labels, const WeightsType& weights) +{ + if (UseWeights) + { + double accWeights, weightedSum; + WeightedSum(labels, weights, 0, labels.n_elem, accWeights, weightedSum); + splitPointOrPrediction = weightedSum / accWeights; + } + else + { + double sum; + Sum(labels, 0, labels.n_elem, sum); + splitPointOrPrediction = sum / labels.n_elem; + } +} + +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +size_t DecisionTreeRegressor::CalculateDirection(const VecType& point) const +{ + if ((data::Datatype) dimensionType == data::Datatype::categorical) + return CategoricalSplit::CalculateDirection(point[splitDimension], + splitPointOrPrediction, *this); + else + return NumericSplit::CalculateDirection(point[splitDimension], + splitPointOrPrediction, *this); +} + +//! Serialize the tree. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +void DecisionTreeRegressor::serialize(Archive& ar, const uint32_t /* version */) +{ + // Clean memory if needed. + if (cereal::is_loading()) + { + for (size_t i = 0; i < children.size(); ++i) + delete children[i]; + children.clear(); + } + // Serialize the children first. + ar(CEREAL_VECTOR_POINTER(children)); + + // Now serialize the rest of the object. + ar(CEREAL_NVP(splitDimension)); + ar(CEREAL_NVP(dimensionType)); + ar(CEREAL_NVP(splitPointOrPrediction)); +} + } // namespace tree } // namespace mlpack From a3fc8d9fe6c5cdec2fa92f0ec6445242e2de6f55 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 11 May 2021 10:02:47 +0530 Subject: [PATCH 566/729] Add to CMakeLists.txt --- src/mlpack/methods/decision_tree/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/methods/decision_tree/CMakeLists.txt b/src/mlpack/methods/decision_tree/CMakeLists.txt index 4072a5097d..d36b3d3681 100644 --- a/src/mlpack/methods/decision_tree/CMakeLists.txt +++ b/src/mlpack/methods/decision_tree/CMakeLists.txt @@ -4,6 +4,8 @@ set(SOURCES all_dimension_select.hpp decision_tree.hpp decision_tree_impl.hpp + decision_tree_regressor.hpp + decision_tree_regressor_impl.hpp all_categorical_split.hpp all_categorical_split_impl.hpp best_binary_numeric_split.hpp From 4f000d5894034dff308abb33fb8c21f24920e6cc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 11 May 2021 10:03:56 +0530 Subject: [PATCH 567/729] Add evaluation metrics for testing --- src/mlpack/tests/test_function_tools.hpp | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index f6c2f06a8a..eb891361e9 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -15,6 +15,7 @@ #include #include +#include using namespace mlpack; using namespace mlpack::distribution; @@ -80,4 +81,54 @@ inline void LogisticRegressionTestData(arma::mat& data, } } +inline void LoadBostonHousingDataset(arma::mat& trainData, + arma::mat& testData, + arma::Row& trainLabels, + arma::Row& testLabels, + data::DatasetInfo& info) +{ + arma::mat dataset; + arma::Row labels; + + if (!data::Load("boston_housing_price.csv", dataset, info)) + FAIL("Cannot load test dataset boston_housing_price.csv!"); + if (!data::Load("boston_housing_price_labels.csv", labels)) + FAIL("Cannot load test dataset boston_housing_price_labels.csv!"); + + data::Split(dataset, labels, trainData, testData, + trainLabels, testLabels, 0.3); +} + +inline double RMSE(const arma::Row& predictions, + const arma::Row& trueLabels) +{ + double rmse = 0.0; + for (size_t i = 0; i < predictions.n_elem; ++i) + { + rmse += std::pow(predictions[i] - trueLabels[i], 2); + } + rmse /= predictions.n_elem; + rmse = sqrt(rmse); + return rmse; +} + +/** + * Calculates the R2 score of the predictions with true labels. + */ +inline double R2Score(const arma::Row& predictions, + const arma::Row& trueLabels) +{ + double mean = arma::mean(trueLabels); + double SStot = 0.0; + double SSres = 0.0; + for (size_t i = 0; i < predictions.n_elem; ++i) + SSres += std::pow(predictions[i] - trueLabels[i], 2); + for (size_t i = 0; i < predictions.n_elem; ++i) + { + SStot += std::pow(trueLabels[i] - mean, 2); + } + + return 1 - SSres / SStot; +} + #endif From c2c85f0250b260738dc0571702ecd3ec38f57983 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 11 May 2021 10:04:21 +0530 Subject: [PATCH 568/729] Add initial tests --- .../tests/data/boston_housing_price.csv | 507 ++++++++++++++++++ .../data/boston_housing_price_labels.csv | 507 ++++++++++++++++++ .../tests/decision_tree_regressor_test.cpp | 492 ++++++++++++++++- 3 files changed, 1505 insertions(+), 1 deletion(-) create mode 100644 src/mlpack/tests/data/boston_housing_price.csv create mode 100644 src/mlpack/tests/data/boston_housing_price_labels.csv diff --git a/src/mlpack/tests/data/boston_housing_price.csv b/src/mlpack/tests/data/boston_housing_price.csv new file mode 100644 index 0000000000..5c0d211062 --- /dev/null +++ b/src/mlpack/tests/data/boston_housing_price.csv @@ -0,0 +1,507 @@ +0,1,2,3,4,5,6,7,8,9,10,11,12 +0.00632,18.0,2.31,0,0.538,6.575,65.2,4.09,1,296.0,15.3,396.9,4.98 +0.02731,0.0,7.07,0,0.469,6.421,78.9,4.9671,2,242.0,17.8,396.9,9.14 +0.02729,0.0,7.07,0,0.469,7.185,61.1,4.9671,2,242.0,17.8,392.83,4.03 +0.03237,0.0,2.18,0,0.458,6.998,45.8,6.0622,3,222.0,18.7,394.63,2.94 +0.06905,0.0,2.18,0,0.458,7.147,54.2,6.0622,3,222.0,18.7,396.9,5.33 +0.02985,0.0,2.18,0,0.458,6.43,58.7,6.0622,3,222.0,18.7,394.12,5.21 +0.08829,12.5,7.87,0,0.524,6.012,66.6,5.5605,5,311.0,15.2,395.6,12.43 +0.14455,12.5,7.87,0,0.524,6.172,96.1,5.9505,5,311.0,15.2,396.9,19.15 +0.21124,12.5,7.87,0,0.524,5.631,100.0,6.0821,5,311.0,15.2,386.63,29.93 +0.17004,12.5,7.87,0,0.524,6.004,85.9,6.5921,5,311.0,15.2,386.71,17.1 +0.22489,12.5,7.87,0,0.524,6.377,94.3,6.3467,5,311.0,15.2,392.52,20.45 +0.11747,12.5,7.87,0,0.524,6.009,82.9,6.2267,5,311.0,15.2,396.9,13.27 +0.09378,12.5,7.87,0,0.524,5.889,39.0,5.4509,5,311.0,15.2,390.5,15.71 +0.62976,0.0,8.14,0,0.538,5.949,61.8,4.7075,4,307.0,21.0,396.9,8.26 +0.63796,0.0,8.14,0,0.538,6.096,84.5,4.4619,4,307.0,21.0,380.02,10.26 +0.62739,0.0,8.14,0,0.538,5.834,56.5,4.4986,4,307.0,21.0,395.62,8.47 +1.05393,0.0,8.14,0,0.538,5.935,29.3,4.4986,4,307.0,21.0,386.85,6.58 +0.7842,0.0,8.14,0,0.538,5.99,81.7,4.2579,4,307.0,21.0,386.75,14.67 +0.80271,0.0,8.14,0,0.538,5.456,36.6,3.7965,4,307.0,21.0,288.99,11.69 +0.7258,0.0,8.14,0,0.538,5.727,69.5,3.7965,4,307.0,21.0,390.95,11.28 +1.25179,0.0,8.14,0,0.538,5.57,98.1,3.7979,4,307.0,21.0,376.57,21.02 +0.85204,0.0,8.14,0,0.538,5.965,89.2,4.0123,4,307.0,21.0,392.53,13.83 +1.23247,0.0,8.14,0,0.538,6.142,91.7,3.9769,4,307.0,21.0,396.9,18.72 +0.98843,0.0,8.14,0,0.538,5.813,100.0,4.0952,4,307.0,21.0,394.54,19.88 +0.75026,0.0,8.14,0,0.538,5.924,94.1,4.3996,4,307.0,21.0,394.33,16.3 +0.84054,0.0,8.14,0,0.538,5.599,85.7,4.4546,4,307.0,21.0,303.42,16.51 +0.67191,0.0,8.14,0,0.538,5.813,90.3,4.682,4,307.0,21.0,376.88,14.81 +0.95577,0.0,8.14,0,0.538,6.047,88.8,4.4534,4,307.0,21.0,306.38,17.28 +0.77299,0.0,8.14,0,0.538,6.495,94.4,4.4547,4,307.0,21.0,387.94,12.8 +1.00245,0.0,8.14,0,0.538,6.674,87.3,4.239,4,307.0,21.0,380.23,11.98 +1.13081,0.0,8.14,0,0.538,5.713,94.1,4.233,4,307.0,21.0,360.17,22.6 +1.35472,0.0,8.14,0,0.538,6.072,100.0,4.175,4,307.0,21.0,376.73,13.04 +1.38799,0.0,8.14,0,0.538,5.95,82.0,3.99,4,307.0,21.0,232.6,27.71 +1.15172,0.0,8.14,0,0.538,5.701,95.0,3.7872,4,307.0,21.0,358.77,18.35 +1.61282,0.0,8.14,0,0.538,6.096,96.9,3.7598,4,307.0,21.0,248.31,20.34 +0.06417,0.0,5.96,0,0.499,5.933,68.2,3.3603,5,279.0,19.2,396.9,9.68 +0.09744,0.0,5.96,0,0.499,5.841,61.4,3.3779,5,279.0,19.2,377.56,11.41 +0.08014,0.0,5.96,0,0.499,5.85,41.5,3.9342,5,279.0,19.2,396.9,8.77 +0.17505,0.0,5.96,0,0.499,5.966,30.2,3.8473,5,279.0,19.2,393.43,10.13 +0.02763,75.0,2.95,0,0.428,6.595,21.8,5.4011,3,252.0,18.3,395.63,4.32 +0.03359,75.0,2.95,0,0.428,7.024,15.8,5.4011,3,252.0,18.3,395.62,1.98 +0.12744,0.0,6.91,0,0.448,6.77,2.9,5.7209,3,233.0,17.9,385.41,4.84 +0.1415,0.0,6.91,0,0.448,6.169,6.6,5.7209,3,233.0,17.9,383.37,5.81 +0.15936,0.0,6.91,0,0.448,6.211,6.5,5.7209,3,233.0,17.9,394.46,7.44 +0.12269,0.0,6.91,0,0.448,6.069,40.0,5.7209,3,233.0,17.9,389.39,9.55 +0.17142,0.0,6.91,0,0.448,5.682,33.8,5.1004,3,233.0,17.9,396.9,10.21 +0.18836,0.0,6.91,0,0.448,5.786,33.3,5.1004,3,233.0,17.9,396.9,14.15 +0.22927,0.0,6.91,0,0.448,6.03,85.5,5.6894,3,233.0,17.9,392.74,18.8 +0.25387,0.0,6.91,0,0.448,5.399,95.3,5.87,3,233.0,17.9,396.9,30.81 +0.21977,0.0,6.91,0,0.448,5.602,62.0,6.0877,3,233.0,17.9,396.9,16.2 +0.08873,21.0,5.64,0,0.439,5.963,45.7,6.8147,4,243.0,16.8,395.56,13.45 +0.04337,21.0,5.64,0,0.439,6.115,63.0,6.8147,4,243.0,16.8,393.97,9.43 +0.0536,21.0,5.64,0,0.439,6.511,21.1,6.8147,4,243.0,16.8,396.9,5.28 +0.04981,21.0,5.64,0,0.439,5.998,21.4,6.8147,4,243.0,16.8,396.9,8.43 +0.0136,75.0,4.0,0,0.41,5.888,47.6,7.3197,3,469.0,21.1,396.9,14.8 +0.01311,90.0,1.22,0,0.403,7.249,21.9,8.6966,5,226.0,17.9,395.93,4.81 +0.02055,85.0,0.74,0,0.41,6.383,35.7,9.1876,2,313.0,17.3,396.9,5.77 +0.01432,100.0,1.32,0,0.411,6.816,40.5,8.3248,5,256.0,15.1,392.9,3.95 +0.15445,25.0,5.13,0,0.453,6.145,29.2,7.8148,8,284.0,19.7,390.68,6.86 +0.10328,25.0,5.13,0,0.453,5.927,47.2,6.932,8,284.0,19.7,396.9,9.22 +0.14932,25.0,5.13,0,0.453,5.741,66.2,7.2254,8,284.0,19.7,395.11,13.15 +0.17171,25.0,5.13,0,0.453,5.966,93.4,6.8185,8,284.0,19.7,378.08,14.44 +0.11027,25.0,5.13,0,0.453,6.456,67.8,7.2255,8,284.0,19.7,396.9,6.73 +0.1265,25.0,5.13,0,0.453,6.762,43.4,7.9809,8,284.0,19.7,395.58,9.5 +0.01951,17.5,1.38,0,0.4161,7.104,59.5,9.2229,3,216.0,18.6,393.24,8.05 +0.03584,80.0,3.37,0,0.398,6.29,17.8,6.6115,4,337.0,16.1,396.9,4.67 +0.04379,80.0,3.37,0,0.398,5.787,31.1,6.6115,4,337.0,16.1,396.9,10.24 +0.05789,12.5,6.07,0,0.409,5.878,21.4,6.498,4,345.0,18.9,396.21,8.1 +0.13554,12.5,6.07,0,0.409,5.594,36.8,6.498,4,345.0,18.9,396.9,13.09 +0.12816,12.5,6.07,0,0.409,5.885,33.0,6.498,4,345.0,18.9,396.9,8.79 +0.08826,0.0,10.81,0,0.413,6.417,6.6,5.2873,4,305.0,19.2,383.73,6.72 +0.15876,0.0,10.81,0,0.413,5.961,17.5,5.2873,4,305.0,19.2,376.94,9.88 +0.09164,0.0,10.81,0,0.413,6.065,7.8,5.2873,4,305.0,19.2,390.91,5.52 +0.19539,0.0,10.81,0,0.413,6.245,6.2,5.2873,4,305.0,19.2,377.17,7.54 +0.07896,0.0,12.83,0,0.437,6.273,6.0,4.2515,5,398.0,18.7,394.92,6.78 +0.09512,0.0,12.83,0,0.437,6.286,45.0,4.5026,5,398.0,18.7,383.23,8.94 +0.10153,0.0,12.83,0,0.437,6.279,74.5,4.0522,5,398.0,18.7,373.66,11.97 +0.08707,0.0,12.83,0,0.437,6.14,45.8,4.0905,5,398.0,18.7,386.96,10.27 +0.05646,0.0,12.83,0,0.437,6.232,53.7,5.0141,5,398.0,18.7,386.4,12.34 +0.08387,0.0,12.83,0,0.437,5.874,36.6,4.5026,5,398.0,18.7,396.06,9.1 +0.04113,25.0,4.86,0,0.426,6.727,33.5,5.4007,4,281.0,19.0,396.9,5.29 +0.04462,25.0,4.86,0,0.426,6.619,70.4,5.4007,4,281.0,19.0,395.63,7.22 +0.03659,25.0,4.86,0,0.426,6.302,32.2,5.4007,4,281.0,19.0,396.9,6.72 +0.03551,25.0,4.86,0,0.426,6.167,46.7,5.4007,4,281.0,19.0,390.64,7.51 +0.05059,0.0,4.49,0,0.449,6.389,48.0,4.7794,3,247.0,18.5,396.9,9.62 +0.05735,0.0,4.49,0,0.449,6.63,56.1,4.4377,3,247.0,18.5,392.3,6.53 +0.05188,0.0,4.49,0,0.449,6.015,45.1,4.4272,3,247.0,18.5,395.99,12.86 +0.07151,0.0,4.49,0,0.449,6.121,56.8,3.7476,3,247.0,18.5,395.15,8.44 +0.0566,0.0,3.41,0,0.489,7.007,86.3,3.4217,2,270.0,17.8,396.9,5.5 +0.05302,0.0,3.41,0,0.489,7.079,63.1,3.4145,2,270.0,17.8,396.06,5.7 +0.04684,0.0,3.41,0,0.489,6.417,66.1,3.0923,2,270.0,17.8,392.18,8.81 +0.03932,0.0,3.41,0,0.489,6.405,73.9,3.0921,2,270.0,17.8,393.55,8.2 +0.04203,28.0,15.04,0,0.464,6.442,53.6,3.6659,4,270.0,18.2,395.01,8.16 +0.02875,28.0,15.04,0,0.464,6.211,28.9,3.6659,4,270.0,18.2,396.33,6.21 +0.04294,28.0,15.04,0,0.464,6.249,77.3,3.615,4,270.0,18.2,396.9,10.59 +0.12204,0.0,2.89,0,0.445,6.625,57.8,3.4952,2,276.0,18.0,357.98,6.65 +0.11504,0.0,2.89,0,0.445,6.163,69.6,3.4952,2,276.0,18.0,391.83,11.34 +0.12083,0.0,2.89,0,0.445,8.069,76.0,3.4952,2,276.0,18.0,396.9,4.21 +0.08187,0.0,2.89,0,0.445,7.82,36.9,3.4952,2,276.0,18.0,393.53,3.57 +0.0686,0.0,2.89,0,0.445,7.416,62.5,3.4952,2,276.0,18.0,396.9,6.19 +0.14866,0.0,8.56,0,0.52,6.727,79.9,2.7778,5,384.0,20.9,394.76,9.42 +0.11432,0.0,8.56,0,0.52,6.781,71.3,2.8561,5,384.0,20.9,395.58,7.67 +0.22876,0.0,8.56,0,0.52,6.405,85.4,2.7147,5,384.0,20.9,70.8,10.63 +0.21161,0.0,8.56,0,0.52,6.137,87.4,2.7147,5,384.0,20.9,394.47,13.44 +0.1396,0.0,8.56,0,0.52,6.167,90.0,2.421,5,384.0,20.9,392.69,12.33 +0.13262,0.0,8.56,0,0.52,5.851,96.7,2.1069,5,384.0,20.9,394.05,16.47 +0.1712,0.0,8.56,0,0.52,5.836,91.9,2.211,5,384.0,20.9,395.67,18.66 +0.13117,0.0,8.56,0,0.52,6.127,85.2,2.1224,5,384.0,20.9,387.69,14.09 +0.12802,0.0,8.56,0,0.52,6.474,97.1,2.4329,5,384.0,20.9,395.24,12.27 +0.26363,0.0,8.56,0,0.52,6.229,91.2,2.5451,5,384.0,20.9,391.23,15.55 +0.10793,0.0,8.56,0,0.52,6.195,54.4,2.7778,5,384.0,20.9,393.49,13.0 +0.10084,0.0,10.01,0,0.547,6.715,81.6,2.6775,6,432.0,17.8,395.59,10.16 +0.12329,0.0,10.01,0,0.547,5.913,92.9,2.3534,6,432.0,17.8,394.95,16.21 +0.22212,0.0,10.01,0,0.547,6.092,95.4,2.548,6,432.0,17.8,396.9,17.09 +0.14231,0.0,10.01,0,0.547,6.254,84.2,2.2565,6,432.0,17.8,388.74,10.45 +0.17134,0.0,10.01,0,0.547,5.928,88.2,2.4631,6,432.0,17.8,344.91,15.76 +0.13158,0.0,10.01,0,0.547,6.176,72.5,2.7301,6,432.0,17.8,393.3,12.04 +0.15098,0.0,10.01,0,0.547,6.021,82.6,2.7474,6,432.0,17.8,394.51,10.3 +0.13058,0.0,10.01,0,0.547,5.872,73.1,2.4775,6,432.0,17.8,338.63,15.37 +0.14476,0.0,10.01,0,0.547,5.731,65.2,2.7592,6,432.0,17.8,391.5,13.61 +0.06899,0.0,25.65,0,0.581,5.87,69.7,2.2577,2,188.0,19.1,389.15,14.37 +0.07165,0.0,25.65,0,0.581,6.004,84.1,2.1974,2,188.0,19.1,377.67,14.27 +0.09299,0.0,25.65,0,0.581,5.961,92.9,2.0869,2,188.0,19.1,378.09,17.93 +0.15038,0.0,25.65,0,0.581,5.856,97.0,1.9444,2,188.0,19.1,370.31,25.41 +0.09849,0.0,25.65,0,0.581,5.879,95.8,2.0063,2,188.0,19.1,379.38,17.58 +0.16902,0.0,25.65,0,0.581,5.986,88.4,1.9929,2,188.0,19.1,385.02,14.81 +0.38735,0.0,25.65,0,0.581,5.613,95.6,1.7572,2,188.0,19.1,359.29,27.26 +0.25915,0.0,21.89,0,0.624,5.693,96.0,1.7883,4,437.0,21.2,392.11,17.19 +0.32543,0.0,21.89,0,0.624,6.431,98.8,1.8125,4,437.0,21.2,396.9,15.39 +0.88125,0.0,21.89,0,0.624,5.637,94.7,1.9799,4,437.0,21.2,396.9,18.34 +0.34006,0.0,21.89,0,0.624,6.458,98.9,2.1185,4,437.0,21.2,395.04,12.6 +1.19294,0.0,21.89,0,0.624,6.326,97.7,2.271,4,437.0,21.2,396.9,12.26 +0.59005,0.0,21.89,0,0.624,6.372,97.9,2.3274,4,437.0,21.2,385.76,11.12 +0.32982,0.0,21.89,0,0.624,5.822,95.4,2.4699,4,437.0,21.2,388.69,15.03 +0.97617,0.0,21.89,0,0.624,5.757,98.4,2.346,4,437.0,21.2,262.76,17.31 +0.55778,0.0,21.89,0,0.624,6.335,98.2,2.1107,4,437.0,21.2,394.67,16.96 +0.32264,0.0,21.89,0,0.624,5.942,93.5,1.9669,4,437.0,21.2,378.25,16.9 +0.35233,0.0,21.89,0,0.624,6.454,98.4,1.8498,4,437.0,21.2,394.08,14.59 +0.2498,0.0,21.89,0,0.624,5.857,98.2,1.6686,4,437.0,21.2,392.04,21.32 +0.54452,0.0,21.89,0,0.624,6.151,97.9,1.6687,4,437.0,21.2,396.9,18.46 +0.2909,0.0,21.89,0,0.624,6.174,93.6,1.6119,4,437.0,21.2,388.08,24.16 +1.62864,0.0,21.89,0,0.624,5.019,100.0,1.4394,4,437.0,21.2,396.9,34.41 +3.32105,0.0,19.58,1,0.871,5.403,100.0,1.3216,5,403.0,14.7,396.9,26.82 +4.0974,0.0,19.58,0,0.871,5.468,100.0,1.4118,5,403.0,14.7,396.9,26.42 +2.77974,0.0,19.58,0,0.871,4.903,97.8,1.3459,5,403.0,14.7,396.9,29.29 +2.37934,0.0,19.58,0,0.871,6.13,100.0,1.4191,5,403.0,14.7,172.91,27.8 +2.15505,0.0,19.58,0,0.871,5.628,100.0,1.5166,5,403.0,14.7,169.27,16.65 +2.36862,0.0,19.58,0,0.871,4.926,95.7,1.4608,5,403.0,14.7,391.71,29.53 +2.33099,0.0,19.58,0,0.871,5.186,93.8,1.5296,5,403.0,14.7,356.99,28.32 +2.73397,0.0,19.58,0,0.871,5.597,94.9,1.5257,5,403.0,14.7,351.85,21.45 +1.6566,0.0,19.58,0,0.871,6.122,97.3,1.618,5,403.0,14.7,372.8,14.1 +1.49632,0.0,19.58,0,0.871,5.404,100.0,1.5916,5,403.0,14.7,341.6,13.28 +1.12658,0.0,19.58,1,0.871,5.012,88.0,1.6102,5,403.0,14.7,343.28,12.12 +2.14918,0.0,19.58,0,0.871,5.709,98.5,1.6232,5,403.0,14.7,261.95,15.79 +1.41385,0.0,19.58,1,0.871,6.129,96.0,1.7494,5,403.0,14.7,321.02,15.12 +3.53501,0.0,19.58,1,0.871,6.152,82.6,1.7455,5,403.0,14.7,88.01,15.02 +2.44668,0.0,19.58,0,0.871,5.272,94.0,1.7364,5,403.0,14.7,88.63,16.14 +1.22358,0.0,19.58,0,0.605,6.943,97.4,1.8773,5,403.0,14.7,363.43,4.59 +1.34284,0.0,19.58,0,0.605,6.066,100.0,1.7573,5,403.0,14.7,353.89,6.43 +1.42502,0.0,19.58,0,0.871,6.51,100.0,1.7659,5,403.0,14.7,364.31,7.39 +1.27346,0.0,19.58,1,0.605,6.25,92.6,1.7984,5,403.0,14.7,338.92,5.5 +1.46336,0.0,19.58,0,0.605,7.489,90.8,1.9709,5,403.0,14.7,374.43,1.73 +1.83377,0.0,19.58,1,0.605,7.802,98.2,2.0407,5,403.0,14.7,389.61,1.92 +1.51902,0.0,19.58,1,0.605,8.375,93.9,2.162,5,403.0,14.7,388.45,3.32 +2.24236,0.0,19.58,0,0.605,5.854,91.8,2.422,5,403.0,14.7,395.11,11.64 +2.924,0.0,19.58,0,0.605,6.101,93.0,2.2834,5,403.0,14.7,240.16,9.81 +2.01019,0.0,19.58,0,0.605,7.929,96.2,2.0459,5,403.0,14.7,369.3,3.7 +1.80028,0.0,19.58,0,0.605,5.877,79.2,2.4259,5,403.0,14.7,227.61,12.14 +2.3004,0.0,19.58,0,0.605,6.319,96.1,2.1,5,403.0,14.7,297.09,11.1 +2.44953,0.0,19.58,0,0.605,6.402,95.2,2.2625,5,403.0,14.7,330.04,11.32 +1.20742,0.0,19.58,0,0.605,5.875,94.6,2.4259,5,403.0,14.7,292.29,14.43 +2.3139,0.0,19.58,0,0.605,5.88,97.3,2.3887,5,403.0,14.7,348.13,12.03 +0.13914,0.0,4.05,0,0.51,5.572,88.5,2.5961,5,296.0,16.6,396.9,14.69 +0.09178,0.0,4.05,0,0.51,6.416,84.1,2.6463,5,296.0,16.6,395.5,9.04 +0.08447,0.0,4.05,0,0.51,5.859,68.7,2.7019,5,296.0,16.6,393.23,9.64 +0.06664,0.0,4.05,0,0.51,6.546,33.1,3.1323,5,296.0,16.6,390.96,5.33 +0.07022,0.0,4.05,0,0.51,6.02,47.2,3.5549,5,296.0,16.6,393.23,10.11 +0.05425,0.0,4.05,0,0.51,6.315,73.4,3.3175,5,296.0,16.6,395.6,6.29 +0.06642,0.0,4.05,0,0.51,6.86,74.4,2.9153,5,296.0,16.6,391.27,6.92 +0.0578,0.0,2.46,0,0.488,6.98,58.4,2.829,3,193.0,17.8,396.9,5.04 +0.06588,0.0,2.46,0,0.488,7.765,83.3,2.741,3,193.0,17.8,395.56,7.56 +0.06888,0.0,2.46,0,0.488,6.144,62.2,2.5979,3,193.0,17.8,396.9,9.45 +0.09103,0.0,2.46,0,0.488,7.155,92.2,2.7006,3,193.0,17.8,394.12,4.82 +0.10008,0.0,2.46,0,0.488,6.563,95.6,2.847,3,193.0,17.8,396.9,5.68 +0.08308,0.0,2.46,0,0.488,5.604,89.8,2.9879,3,193.0,17.8,391.0,13.98 +0.06047,0.0,2.46,0,0.488,6.153,68.8,3.2797,3,193.0,17.8,387.11,13.15 +0.05602,0.0,2.46,0,0.488,7.831,53.6,3.1992,3,193.0,17.8,392.63,4.45 +0.07875,45.0,3.44,0,0.437,6.782,41.1,3.7886,5,398.0,15.2,393.87,6.68 +0.12579,45.0,3.44,0,0.437,6.556,29.1,4.5667,5,398.0,15.2,382.84,4.56 +0.0837,45.0,3.44,0,0.437,7.185,38.9,4.5667,5,398.0,15.2,396.9,5.39 +0.09068,45.0,3.44,0,0.437,6.951,21.5,6.4798,5,398.0,15.2,377.68,5.1 +0.06911,45.0,3.44,0,0.437,6.739,30.8,6.4798,5,398.0,15.2,389.71,4.69 +0.08664,45.0,3.44,0,0.437,7.178,26.3,6.4798,5,398.0,15.2,390.49,2.87 +0.02187,60.0,2.93,0,0.401,6.8,9.9,6.2196,1,265.0,15.6,393.37,5.03 +0.01439,60.0,2.93,0,0.401,6.604,18.8,6.2196,1,265.0,15.6,376.7,4.38 +0.01381,80.0,0.46,0,0.422,7.875,32.0,5.6484,4,255.0,14.4,394.23,2.97 +0.04011,80.0,1.52,0,0.404,7.287,34.1,7.309,2,329.0,12.6,396.9,4.08 +0.04666,80.0,1.52,0,0.404,7.107,36.6,7.309,2,329.0,12.6,354.31,8.61 +0.03768,80.0,1.52,0,0.404,7.274,38.3,7.309,2,329.0,12.6,392.2,6.62 +0.0315,95.0,1.47,0,0.403,6.975,15.3,7.6534,3,402.0,17.0,396.9,4.56 +0.01778,95.0,1.47,0,0.403,7.135,13.9,7.6534,3,402.0,17.0,384.3,4.45 +0.03445,82.5,2.03,0,0.415,6.162,38.4,6.27,2,348.0,14.7,393.77,7.43 +0.02177,82.5,2.03,0,0.415,7.61,15.7,6.27,2,348.0,14.7,395.38,3.11 +0.0351,95.0,2.68,0,0.4161,7.853,33.2,5.118,4,224.0,14.7,392.78,3.81 +0.02009,95.0,2.68,0,0.4161,8.034,31.9,5.118,4,224.0,14.7,390.55,2.88 +0.13642,0.0,10.59,0,0.489,5.891,22.3,3.9454,4,277.0,18.6,396.9,10.87 +0.22969,0.0,10.59,0,0.489,6.326,52.5,4.3549,4,277.0,18.6,394.87,10.97 +0.25199,0.0,10.59,0,0.489,5.783,72.7,4.3549,4,277.0,18.6,389.43,18.06 +0.13587,0.0,10.59,1,0.489,6.064,59.1,4.2392,4,277.0,18.6,381.32,14.66 +0.43571,0.0,10.59,1,0.489,5.344,100.0,3.875,4,277.0,18.6,396.9,23.09 +0.17446,0.0,10.59,1,0.489,5.96,92.1,3.8771,4,277.0,18.6,393.25,17.27 +0.37578,0.0,10.59,1,0.489,5.404,88.6,3.665,4,277.0,18.6,395.24,23.98 +0.21719,0.0,10.59,1,0.489,5.807,53.8,3.6526,4,277.0,18.6,390.94,16.03 +0.14052,0.0,10.59,0,0.489,6.375,32.3,3.9454,4,277.0,18.6,385.81,9.38 +0.28955,0.0,10.59,0,0.489,5.412,9.8,3.5875,4,277.0,18.6,348.93,29.55 +0.19802,0.0,10.59,0,0.489,6.182,42.4,3.9454,4,277.0,18.6,393.63,9.47 +0.0456,0.0,13.89,1,0.55,5.888,56.0,3.1121,5,276.0,16.4,392.8,13.51 +0.07013,0.0,13.89,0,0.55,6.642,85.1,3.4211,5,276.0,16.4,392.78,9.69 +0.11069,0.0,13.89,1,0.55,5.951,93.8,2.8893,5,276.0,16.4,396.9,17.92 +0.11425,0.0,13.89,1,0.55,6.373,92.4,3.3633,5,276.0,16.4,393.74,10.5 +0.35809,0.0,6.2,1,0.507,6.951,88.5,2.8617,8,307.0,17.4,391.7,9.71 +0.40771,0.0,6.2,1,0.507,6.164,91.3,3.048,8,307.0,17.4,395.24,21.46 +0.62356,0.0,6.2,1,0.507,6.879,77.7,3.2721,8,307.0,17.4,390.39,9.93 +0.6147,0.0,6.2,0,0.507,6.618,80.8,3.2721,8,307.0,17.4,396.9,7.6 +0.31533,0.0,6.2,0,0.504,8.266,78.3,2.8944,8,307.0,17.4,385.05,4.14 +0.52693,0.0,6.2,0,0.504,8.725,83.0,2.8944,8,307.0,17.4,382.0,4.63 +0.38214,0.0,6.2,0,0.504,8.04,86.5,3.2157,8,307.0,17.4,387.38,3.13 +0.41238,0.0,6.2,0,0.504,7.163,79.9,3.2157,8,307.0,17.4,372.08,6.36 +0.29819,0.0,6.2,0,0.504,7.686,17.0,3.3751,8,307.0,17.4,377.51,3.92 +0.44178,0.0,6.2,0,0.504,6.552,21.4,3.3751,8,307.0,17.4,380.34,3.76 +0.537,0.0,6.2,0,0.504,5.981,68.1,3.6715,8,307.0,17.4,378.35,11.65 +0.46296,0.0,6.2,0,0.504,7.412,76.9,3.6715,8,307.0,17.4,376.14,5.25 +0.57529,0.0,6.2,0,0.507,8.337,73.3,3.8384,8,307.0,17.4,385.91,2.47 +0.33147,0.0,6.2,0,0.507,8.247,70.4,3.6519,8,307.0,17.4,378.95,3.95 +0.44791,0.0,6.2,1,0.507,6.726,66.5,3.6519,8,307.0,17.4,360.2,8.05 +0.33045,0.0,6.2,0,0.507,6.086,61.5,3.6519,8,307.0,17.4,376.75,10.88 +0.52058,0.0,6.2,1,0.507,6.631,76.5,4.148,8,307.0,17.4,388.45,9.54 +0.51183,0.0,6.2,0,0.507,7.358,71.6,4.148,8,307.0,17.4,390.07,4.73 +0.08244,30.0,4.93,0,0.428,6.481,18.5,6.1899,6,300.0,16.6,379.41,6.36 +0.09252,30.0,4.93,0,0.428,6.606,42.2,6.1899,6,300.0,16.6,383.78,7.37 +0.11329,30.0,4.93,0,0.428,6.897,54.3,6.3361,6,300.0,16.6,391.25,11.38 +0.10612,30.0,4.93,0,0.428,6.095,65.1,6.3361,6,300.0,16.6,394.62,12.4 +0.1029,30.0,4.93,0,0.428,6.358,52.9,7.0355,6,300.0,16.6,372.75,11.22 +0.12757,30.0,4.93,0,0.428,6.393,7.8,7.0355,6,300.0,16.6,374.71,5.19 +0.20608,22.0,5.86,0,0.431,5.593,76.5,7.9549,7,330.0,19.1,372.49,12.5 +0.19133,22.0,5.86,0,0.431,5.605,70.2,7.9549,7,330.0,19.1,389.13,18.46 +0.33983,22.0,5.86,0,0.431,6.108,34.9,8.0555,7,330.0,19.1,390.18,9.16 +0.19657,22.0,5.86,0,0.431,6.226,79.2,8.0555,7,330.0,19.1,376.14,10.15 +0.16439,22.0,5.86,0,0.431,6.433,49.1,7.8265,7,330.0,19.1,374.71,9.52 +0.19073,22.0,5.86,0,0.431,6.718,17.5,7.8265,7,330.0,19.1,393.74,6.56 +0.1403,22.0,5.86,0,0.431,6.487,13.0,7.3967,7,330.0,19.1,396.28,5.9 +0.21409,22.0,5.86,0,0.431,6.438,8.9,7.3967,7,330.0,19.1,377.07,3.59 +0.08221,22.0,5.86,0,0.431,6.957,6.8,8.9067,7,330.0,19.1,386.09,3.53 +0.36894,22.0,5.86,0,0.431,8.259,8.4,8.9067,7,330.0,19.1,396.9,3.54 +0.04819,80.0,3.64,0,0.392,6.108,32.0,9.2203,1,315.0,16.4,392.89,6.57 +0.03548,80.0,3.64,0,0.392,5.876,19.1,9.2203,1,315.0,16.4,395.18,9.25 +0.01538,90.0,3.75,0,0.394,7.454,34.2,6.3361,3,244.0,15.9,386.34,3.11 +0.61154,20.0,3.97,0,0.647,8.704,86.9,1.801,5,264.0,13.0,389.7,5.12 +0.66351,20.0,3.97,0,0.647,7.333,100.0,1.8946,5,264.0,13.0,383.29,7.79 +0.65665,20.0,3.97,0,0.647,6.842,100.0,2.0107,5,264.0,13.0,391.93,6.9 +0.54011,20.0,3.97,0,0.647,7.203,81.8,2.1121,5,264.0,13.0,392.8,9.59 +0.53412,20.0,3.97,0,0.647,7.52,89.4,2.1398,5,264.0,13.0,388.37,7.26 +0.52014,20.0,3.97,0,0.647,8.398,91.5,2.2885,5,264.0,13.0,386.86,5.91 +0.82526,20.0,3.97,0,0.647,7.327,94.5,2.0788,5,264.0,13.0,393.42,11.25 +0.55007,20.0,3.97,0,0.647,7.206,91.6,1.9301,5,264.0,13.0,387.89,8.1 +0.76162,20.0,3.97,0,0.647,5.56,62.8,1.9865,5,264.0,13.0,392.4,10.45 +0.7857,20.0,3.97,0,0.647,7.014,84.6,2.1329,5,264.0,13.0,384.07,14.79 +0.57834,20.0,3.97,0,0.575,8.297,67.0,2.4216,5,264.0,13.0,384.54,7.44 +0.5405,20.0,3.97,0,0.575,7.47,52.6,2.872,5,264.0,13.0,390.3,3.16 +0.09065,20.0,6.96,1,0.464,5.92,61.5,3.9175,3,223.0,18.6,391.34,13.65 +0.29916,20.0,6.96,0,0.464,5.856,42.1,4.429,3,223.0,18.6,388.65,13.0 +0.16211,20.0,6.96,0,0.464,6.24,16.3,4.429,3,223.0,18.6,396.9,6.59 +0.1146,20.0,6.96,0,0.464,6.538,58.7,3.9175,3,223.0,18.6,394.96,7.73 +0.22188,20.0,6.96,1,0.464,7.691,51.8,4.3665,3,223.0,18.6,390.77,6.58 +0.05644,40.0,6.41,1,0.447,6.758,32.9,4.0776,4,254.0,17.6,396.9,3.53 +0.09604,40.0,6.41,0,0.447,6.854,42.8,4.2673,4,254.0,17.6,396.9,2.98 +0.10469,40.0,6.41,1,0.447,7.267,49.0,4.7872,4,254.0,17.6,389.25,6.05 +0.06127,40.0,6.41,1,0.447,6.826,27.6,4.8628,4,254.0,17.6,393.45,4.16 +0.07978,40.0,6.41,0,0.447,6.482,32.1,4.1403,4,254.0,17.6,396.9,7.19 +0.21038,20.0,3.33,0,0.4429,6.812,32.2,4.1007,5,216.0,14.9,396.9,4.85 +0.03578,20.0,3.33,0,0.4429,7.82,64.5,4.6947,5,216.0,14.9,387.31,3.76 +0.03705,20.0,3.33,0,0.4429,6.968,37.2,5.2447,5,216.0,14.9,392.23,4.59 +0.06129,20.0,3.33,1,0.4429,7.645,49.7,5.2119,5,216.0,14.9,377.07,3.01 +0.01501,90.0,1.21,1,0.401,7.923,24.8,5.885,1,198.0,13.6,395.52,3.16 +0.00906,90.0,2.97,0,0.4,7.088,20.8,7.3073,1,285.0,15.3,394.72,7.85 +0.01096,55.0,2.25,0,0.389,6.453,31.9,7.3073,1,300.0,15.3,394.72,8.23 +0.01965,80.0,1.76,0,0.385,6.23,31.5,9.0892,1,241.0,18.2,341.6,12.93 +0.03871,52.5,5.32,0,0.405,6.209,31.3,7.3172,6,293.0,16.6,396.9,7.14 +0.0459,52.5,5.32,0,0.405,6.315,45.6,7.3172,6,293.0,16.6,396.9,7.6 +0.04297,52.5,5.32,0,0.405,6.565,22.9,7.3172,6,293.0,16.6,371.72,9.51 +0.03502,80.0,4.95,0,0.411,6.861,27.9,5.1167,4,245.0,19.2,396.9,3.33 +0.07886,80.0,4.95,0,0.411,7.148,27.7,5.1167,4,245.0,19.2,396.9,3.56 +0.03615,80.0,4.95,0,0.411,6.63,23.4,5.1167,4,245.0,19.2,396.9,4.7 +0.08265,0.0,13.92,0,0.437,6.127,18.4,5.5027,4,289.0,16.0,396.9,8.58 +0.08199,0.0,13.92,0,0.437,6.009,42.3,5.5027,4,289.0,16.0,396.9,10.4 +0.12932,0.0,13.92,0,0.437,6.678,31.1,5.9604,4,289.0,16.0,396.9,6.27 +0.05372,0.0,13.92,0,0.437,6.549,51.0,5.9604,4,289.0,16.0,392.85,7.39 +0.14103,0.0,13.92,0,0.437,5.79,58.0,6.32,4,289.0,16.0,396.9,15.84 +0.06466,70.0,2.24,0,0.4,6.345,20.1,7.8278,5,358.0,14.8,368.24,4.97 +0.05561,70.0,2.24,0,0.4,7.041,10.0,7.8278,5,358.0,14.8,371.58,4.74 +0.04417,70.0,2.24,0,0.4,6.871,47.4,7.8278,5,358.0,14.8,390.86,6.07 +0.03537,34.0,6.09,0,0.433,6.59,40.4,5.4917,7,329.0,16.1,395.75,9.5 +0.09266,34.0,6.09,0,0.433,6.495,18.4,5.4917,7,329.0,16.1,383.61,8.67 +0.1,34.0,6.09,0,0.433,6.982,17.7,5.4917,7,329.0,16.1,390.43,4.86 +0.05515,33.0,2.18,0,0.472,7.236,41.1,4.022,7,222.0,18.4,393.68,6.93 +0.05479,33.0,2.18,0,0.472,6.616,58.1,3.37,7,222.0,18.4,393.36,8.93 +0.07503,33.0,2.18,0,0.472,7.42,71.9,3.0992,7,222.0,18.4,396.9,6.47 +0.04932,33.0,2.18,0,0.472,6.849,70.3,3.1827,7,222.0,18.4,396.9,7.53 +0.49298,0.0,9.9,0,0.544,6.635,82.5,3.3175,4,304.0,18.4,396.9,4.54 +0.3494,0.0,9.9,0,0.544,5.972,76.7,3.1025,4,304.0,18.4,396.24,9.97 +2.63548,0.0,9.9,0,0.544,4.973,37.8,2.5194,4,304.0,18.4,350.45,12.64 +0.79041,0.0,9.9,0,0.544,6.122,52.8,2.6403,4,304.0,18.4,396.9,5.98 +0.26169,0.0,9.9,0,0.544,6.023,90.4,2.834,4,304.0,18.4,396.3,11.72 +0.26938,0.0,9.9,0,0.544,6.266,82.8,3.2628,4,304.0,18.4,393.39,7.9 +0.3692,0.0,9.9,0,0.544,6.567,87.3,3.6023,4,304.0,18.4,395.69,9.28 +0.25356,0.0,9.9,0,0.544,5.705,77.7,3.945,4,304.0,18.4,396.42,11.5 +0.31827,0.0,9.9,0,0.544,5.914,83.2,3.9986,4,304.0,18.4,390.7,18.33 +0.24522,0.0,9.9,0,0.544,5.782,71.7,4.0317,4,304.0,18.4,396.9,15.94 +0.40202,0.0,9.9,0,0.544,6.382,67.2,3.5325,4,304.0,18.4,395.21,10.36 +0.47547,0.0,9.9,0,0.544,6.113,58.8,4.0019,4,304.0,18.4,396.23,12.73 +0.1676,0.0,7.38,0,0.493,6.426,52.3,4.5404,5,287.0,19.6,396.9,7.2 +0.18159,0.0,7.38,0,0.493,6.376,54.3,4.5404,5,287.0,19.6,396.9,6.87 +0.35114,0.0,7.38,0,0.493,6.041,49.9,4.7211,5,287.0,19.6,396.9,7.7 +0.28392,0.0,7.38,0,0.493,5.708,74.3,4.7211,5,287.0,19.6,391.13,11.74 +0.34109,0.0,7.38,0,0.493,6.415,40.1,4.7211,5,287.0,19.6,396.9,6.12 +0.19186,0.0,7.38,0,0.493,6.431,14.7,5.4159,5,287.0,19.6,393.68,5.08 +0.30347,0.0,7.38,0,0.493,6.312,28.9,5.4159,5,287.0,19.6,396.9,6.15 +0.24103,0.0,7.38,0,0.493,6.083,43.7,5.4159,5,287.0,19.6,396.9,12.79 +0.06617,0.0,3.24,0,0.46,5.868,25.8,5.2146,4,430.0,16.9,382.44,9.97 +0.06724,0.0,3.24,0,0.46,6.333,17.2,5.2146,4,430.0,16.9,375.21,7.34 +0.04544,0.0,3.24,0,0.46,6.144,32.2,5.8736,4,430.0,16.9,368.57,9.09 +0.05023,35.0,6.06,0,0.4379,5.706,28.4,6.6407,1,304.0,16.9,394.02,12.43 +0.03466,35.0,6.06,0,0.4379,6.031,23.3,6.6407,1,304.0,16.9,362.25,7.83 +0.05083,0.0,5.19,0,0.515,6.316,38.1,6.4584,5,224.0,20.2,389.71,5.68 +0.03738,0.0,5.19,0,0.515,6.31,38.5,6.4584,5,224.0,20.2,389.4,6.75 +0.03961,0.0,5.19,0,0.515,6.037,34.5,5.9853,5,224.0,20.2,396.9,8.01 +0.03427,0.0,5.19,0,0.515,5.869,46.3,5.2311,5,224.0,20.2,396.9,9.8 +0.03041,0.0,5.19,0,0.515,5.895,59.6,5.615,5,224.0,20.2,394.81,10.56 +0.03306,0.0,5.19,0,0.515,6.059,37.3,4.8122,5,224.0,20.2,396.14,8.51 +0.05497,0.0,5.19,0,0.515,5.985,45.4,4.8122,5,224.0,20.2,396.9,9.74 +0.06151,0.0,5.19,0,0.515,5.968,58.5,4.8122,5,224.0,20.2,396.9,9.29 +0.01301,35.0,1.52,0,0.442,7.241,49.3,7.0379,1,284.0,15.5,394.74,5.49 +0.02498,0.0,1.89,0,0.518,6.54,59.7,6.2669,1,422.0,15.9,389.96,8.65 +0.02543,55.0,3.78,0,0.484,6.696,56.4,5.7321,5,370.0,17.6,396.9,7.18 +0.03049,55.0,3.78,0,0.484,6.874,28.1,6.4654,5,370.0,17.6,387.97,4.61 +0.03113,0.0,4.39,0,0.442,6.014,48.5,8.0136,3,352.0,18.8,385.64,10.53 +0.06162,0.0,4.39,0,0.442,5.898,52.3,8.0136,3,352.0,18.8,364.61,12.67 +0.0187,85.0,4.15,0,0.429,6.516,27.7,8.5353,4,351.0,17.9,392.43,6.36 +0.01501,80.0,2.01,0,0.435,6.635,29.7,8.344,4,280.0,17.0,390.94,5.99 +0.02899,40.0,1.25,0,0.429,6.939,34.5,8.7921,1,335.0,19.7,389.85,5.89 +0.06211,40.0,1.25,0,0.429,6.49,44.4,8.7921,1,335.0,19.7,396.9,5.98 +0.0795,60.0,1.69,0,0.411,6.579,35.9,10.7103,4,411.0,18.3,370.78,5.49 +0.07244,60.0,1.69,0,0.411,5.884,18.5,10.7103,4,411.0,18.3,392.33,7.79 +0.01709,90.0,2.02,0,0.41,6.728,36.1,12.1265,5,187.0,17.0,384.46,4.5 +0.04301,80.0,1.91,0,0.413,5.663,21.9,10.5857,4,334.0,22.0,382.8,8.05 +0.10659,80.0,1.91,0,0.413,5.936,19.5,10.5857,4,334.0,22.0,376.04,5.57 +8.98296,0.0,18.1,1,0.77,6.212,97.4,2.1222,24,666.0,20.2,377.73,17.6 +3.8497,0.0,18.1,1,0.77,6.395,91.0,2.5052,24,666.0,20.2,391.34,13.27 +5.20177,0.0,18.1,1,0.77,6.127,83.4,2.7227,24,666.0,20.2,395.43,11.48 +4.26131,0.0,18.1,0,0.77,6.112,81.3,2.5091,24,666.0,20.2,390.74,12.67 +4.54192,0.0,18.1,0,0.77,6.398,88.0,2.5182,24,666.0,20.2,374.56,7.79 +3.83684,0.0,18.1,0,0.77,6.251,91.1,2.2955,24,666.0,20.2,350.65,14.19 +3.67822,0.0,18.1,0,0.77,5.362,96.2,2.1036,24,666.0,20.2,380.79,10.19 +4.22239,0.0,18.1,1,0.77,5.803,89.0,1.9047,24,666.0,20.2,353.04,14.64 +3.47428,0.0,18.1,1,0.718,8.78,82.9,1.9047,24,666.0,20.2,354.55,5.29 +4.55587,0.0,18.1,0,0.718,3.561,87.9,1.6132,24,666.0,20.2,354.7,7.12 +3.69695,0.0,18.1,0,0.718,4.963,91.4,1.7523,24,666.0,20.2,316.03,14.0 +13.5222,0.0,18.1,0,0.631,3.863,100.0,1.5106,24,666.0,20.2,131.42,13.33 +4.89822,0.0,18.1,0,0.631,4.97,100.0,1.3325,24,666.0,20.2,375.52,3.26 +5.66998,0.0,18.1,1,0.631,6.683,96.8,1.3567,24,666.0,20.2,375.33,3.73 +6.53876,0.0,18.1,1,0.631,7.016,97.5,1.2024,24,666.0,20.2,392.05,2.96 +9.2323,0.0,18.1,0,0.631,6.216,100.0,1.1691,24,666.0,20.2,366.15,9.53 +8.26725,0.0,18.1,1,0.668,5.875,89.6,1.1296,24,666.0,20.2,347.88,8.88 +11.1081,0.0,18.1,0,0.668,4.906,100.0,1.1742,24,666.0,20.2,396.9,34.77 +18.4982,0.0,18.1,0,0.668,4.138,100.0,1.137,24,666.0,20.2,396.9,37.97 +19.6091,0.0,18.1,0,0.671,7.313,97.9,1.3163,24,666.0,20.2,396.9,13.44 +15.288,0.0,18.1,0,0.671,6.649,93.3,1.3449,24,666.0,20.2,363.02,23.24 +9.82349,0.0,18.1,0,0.671,6.794,98.8,1.358,24,666.0,20.2,396.9,21.24 +23.6482,0.0,18.1,0,0.671,6.38,96.2,1.3861,24,666.0,20.2,396.9,23.69 +17.8667,0.0,18.1,0,0.671,6.223,100.0,1.3861,24,666.0,20.2,393.74,21.78 +88.9762,0.0,18.1,0,0.671,6.968,91.9,1.4165,24,666.0,20.2,396.9,17.21 +15.8744,0.0,18.1,0,0.671,6.545,99.1,1.5192,24,666.0,20.2,396.9,21.08 +9.18702,0.0,18.1,0,0.7,5.536,100.0,1.5804,24,666.0,20.2,396.9,23.6 +7.99248,0.0,18.1,0,0.7,5.52,100.0,1.5331,24,666.0,20.2,396.9,24.56 +20.0849,0.0,18.1,0,0.7,4.368,91.2,1.4395,24,666.0,20.2,285.83,30.63 +16.8118,0.0,18.1,0,0.7,5.277,98.1,1.4261,24,666.0,20.2,396.9,30.81 +24.3938,0.0,18.1,0,0.7,4.652,100.0,1.4672,24,666.0,20.2,396.9,28.28 +22.5971,0.0,18.1,0,0.7,5.0,89.5,1.5184,24,666.0,20.2,396.9,31.99 +14.3337,0.0,18.1,0,0.7,4.88,100.0,1.5895,24,666.0,20.2,372.92,30.62 +8.15174,0.0,18.1,0,0.7,5.39,98.9,1.7281,24,666.0,20.2,396.9,20.85 +6.96215,0.0,18.1,0,0.7,5.713,97.0,1.9265,24,666.0,20.2,394.43,17.11 +5.29305,0.0,18.1,0,0.7,6.051,82.5,2.1678,24,666.0,20.2,378.38,18.76 +11.5779,0.0,18.1,0,0.7,5.036,97.0,1.77,24,666.0,20.2,396.9,25.68 +8.64476,0.0,18.1,0,0.693,6.193,92.6,1.7912,24,666.0,20.2,396.9,15.17 +13.3598,0.0,18.1,0,0.693,5.887,94.7,1.7821,24,666.0,20.2,396.9,16.35 +8.71675,0.0,18.1,0,0.693,6.471,98.8,1.7257,24,666.0,20.2,391.98,17.12 +5.87205,0.0,18.1,0,0.693,6.405,96.0,1.6768,24,666.0,20.2,396.9,19.37 +7.67202,0.0,18.1,0,0.693,5.747,98.9,1.6334,24,666.0,20.2,393.1,19.92 +38.3518,0.0,18.1,0,0.693,5.453,100.0,1.4896,24,666.0,20.2,396.9,30.59 +9.91655,0.0,18.1,0,0.693,5.852,77.8,1.5004,24,666.0,20.2,338.16,29.97 +25.0461,0.0,18.1,0,0.693,5.987,100.0,1.5888,24,666.0,20.2,396.9,26.77 +14.2362,0.0,18.1,0,0.693,6.343,100.0,1.5741,24,666.0,20.2,396.9,20.32 +9.59571,0.0,18.1,0,0.693,6.404,100.0,1.639,24,666.0,20.2,376.11,20.31 +24.8017,0.0,18.1,0,0.693,5.349,96.0,1.7028,24,666.0,20.2,396.9,19.77 +41.5292,0.0,18.1,0,0.693,5.531,85.4,1.6074,24,666.0,20.2,329.46,27.38 +67.9208,0.0,18.1,0,0.693,5.683,100.0,1.4254,24,666.0,20.2,384.97,22.98 +20.7162,0.0,18.1,0,0.659,4.138,100.0,1.1781,24,666.0,20.2,370.22,23.34 +11.9511,0.0,18.1,0,0.659,5.608,100.0,1.2852,24,666.0,20.2,332.09,12.13 +7.40389,0.0,18.1,0,0.597,5.617,97.9,1.4547,24,666.0,20.2,314.64,26.4 +14.4383,0.0,18.1,0,0.597,6.852,100.0,1.4655,24,666.0,20.2,179.36,19.78 +51.1358,0.0,18.1,0,0.597,5.757,100.0,1.413,24,666.0,20.2,2.6,10.11 +14.0507,0.0,18.1,0,0.597,6.657,100.0,1.5275,24,666.0,20.2,35.05,21.22 +18.811,0.0,18.1,0,0.597,4.628,100.0,1.5539,24,666.0,20.2,28.79,34.37 +28.6558,0.0,18.1,0,0.597,5.155,100.0,1.5894,24,666.0,20.2,210.97,20.08 +45.7461,0.0,18.1,0,0.693,4.519,100.0,1.6582,24,666.0,20.2,88.27,36.98 +18.0846,0.0,18.1,0,0.679,6.434,100.0,1.8347,24,666.0,20.2,27.25,29.05 +10.8342,0.0,18.1,0,0.679,6.782,90.8,1.8195,24,666.0,20.2,21.57,25.79 +25.9406,0.0,18.1,0,0.679,5.304,89.1,1.6475,24,666.0,20.2,127.36,26.64 +73.5341,0.0,18.1,0,0.679,5.957,100.0,1.8026,24,666.0,20.2,16.45,20.62 +11.8123,0.0,18.1,0,0.718,6.824,76.5,1.794,24,666.0,20.2,48.45,22.74 +11.0874,0.0,18.1,0,0.718,6.411,100.0,1.8589,24,666.0,20.2,318.75,15.02 +7.02259,0.0,18.1,0,0.718,6.006,95.3,1.8746,24,666.0,20.2,319.98,15.7 +12.0482,0.0,18.1,0,0.614,5.648,87.6,1.9512,24,666.0,20.2,291.55,14.1 +7.05042,0.0,18.1,0,0.614,6.103,85.1,2.0218,24,666.0,20.2,2.52,23.29 +8.79212,0.0,18.1,0,0.584,5.565,70.6,2.0635,24,666.0,20.2,3.65,17.16 +15.8603,0.0,18.1,0,0.679,5.896,95.4,1.9096,24,666.0,20.2,7.68,24.39 +12.2472,0.0,18.1,0,0.584,5.837,59.7,1.9976,24,666.0,20.2,24.65,15.69 +37.6619,0.0,18.1,0,0.679,6.202,78.7,1.8629,24,666.0,20.2,18.82,14.52 +7.36711,0.0,18.1,0,0.679,6.193,78.1,1.9356,24,666.0,20.2,96.73,21.52 +9.33889,0.0,18.1,0,0.679,6.38,95.6,1.9682,24,666.0,20.2,60.72,24.08 +8.49213,0.0,18.1,0,0.584,6.348,86.1,2.0527,24,666.0,20.2,83.45,17.64 +10.0623,0.0,18.1,0,0.584,6.833,94.3,2.0882,24,666.0,20.2,81.33,19.69 +6.44405,0.0,18.1,0,0.584,6.425,74.8,2.2004,24,666.0,20.2,97.95,12.03 +5.58107,0.0,18.1,0,0.713,6.436,87.9,2.3158,24,666.0,20.2,100.19,16.22 +13.9134,0.0,18.1,0,0.713,6.208,95.0,2.2222,24,666.0,20.2,100.63,15.17 +11.1604,0.0,18.1,0,0.74,6.629,94.6,2.1247,24,666.0,20.2,109.85,23.27 +14.4208,0.0,18.1,0,0.74,6.461,93.3,2.0026,24,666.0,20.2,27.49,18.05 +15.1772,0.0,18.1,0,0.74,6.152,100.0,1.9142,24,666.0,20.2,9.32,26.45 +13.6781,0.0,18.1,0,0.74,5.935,87.9,1.8206,24,666.0,20.2,68.95,34.02 +9.39063,0.0,18.1,0,0.74,5.627,93.9,1.8172,24,666.0,20.2,396.9,22.88 +22.0511,0.0,18.1,0,0.74,5.818,92.4,1.8662,24,666.0,20.2,391.45,22.11 +9.72418,0.0,18.1,0,0.74,6.406,97.2,2.0651,24,666.0,20.2,385.96,19.52 +5.66637,0.0,18.1,0,0.74,6.219,100.0,2.0048,24,666.0,20.2,395.69,16.59 +9.96654,0.0,18.1,0,0.74,6.485,100.0,1.9784,24,666.0,20.2,386.73,18.85 +12.8023,0.0,18.1,0,0.74,5.854,96.6,1.8956,24,666.0,20.2,240.52,23.79 +10.6718,0.0,18.1,0,0.74,6.459,94.8,1.9879,24,666.0,20.2,43.06,23.98 +6.28807,0.0,18.1,0,0.74,6.341,96.4,2.072,24,666.0,20.2,318.01,17.79 +9.92485,0.0,18.1,0,0.74,6.251,96.6,2.198,24,666.0,20.2,388.52,16.44 +9.32909,0.0,18.1,0,0.713,6.185,98.7,2.2616,24,666.0,20.2,396.9,18.13 +7.52601,0.0,18.1,0,0.713,6.417,98.3,2.185,24,666.0,20.2,304.21,19.31 +6.71772,0.0,18.1,0,0.713,6.749,92.6,2.3236,24,666.0,20.2,0.32,17.44 +5.44114,0.0,18.1,0,0.713,6.655,98.2,2.3552,24,666.0,20.2,355.29,17.73 +5.09017,0.0,18.1,0,0.713,6.297,91.8,2.3682,24,666.0,20.2,385.09,17.27 +8.24809,0.0,18.1,0,0.713,7.393,99.3,2.4527,24,666.0,20.2,375.87,16.74 +9.51363,0.0,18.1,0,0.713,6.728,94.1,2.4961,24,666.0,20.2,6.68,18.71 +4.75237,0.0,18.1,0,0.713,6.525,86.5,2.4358,24,666.0,20.2,50.92,18.13 +4.66883,0.0,18.1,0,0.713,5.976,87.9,2.5806,24,666.0,20.2,10.48,19.01 +8.20058,0.0,18.1,0,0.713,5.936,80.3,2.7792,24,666.0,20.2,3.5,16.94 +7.75223,0.0,18.1,0,0.713,6.301,83.7,2.7831,24,666.0,20.2,272.21,16.23 +6.80117,0.0,18.1,0,0.713,6.081,84.4,2.7175,24,666.0,20.2,396.9,14.7 +4.81213,0.0,18.1,0,0.713,6.701,90.0,2.5975,24,666.0,20.2,255.23,16.42 +3.69311,0.0,18.1,0,0.713,6.376,88.4,2.5671,24,666.0,20.2,391.43,14.65 +6.65492,0.0,18.1,0,0.713,6.317,83.0,2.7344,24,666.0,20.2,396.9,13.99 +5.82115,0.0,18.1,0,0.713,6.513,89.9,2.8016,24,666.0,20.2,393.82,10.29 +7.83932,0.0,18.1,0,0.655,6.209,65.4,2.9634,24,666.0,20.2,396.9,13.22 +3.1636,0.0,18.1,0,0.655,5.759,48.2,3.0665,24,666.0,20.2,334.4,14.13 +3.77498,0.0,18.1,0,0.655,5.952,84.7,2.8715,24,666.0,20.2,22.01,17.15 +4.42228,0.0,18.1,0,0.584,6.003,94.5,2.5403,24,666.0,20.2,331.29,21.32 +15.5757,0.0,18.1,0,0.58,5.926,71.0,2.9084,24,666.0,20.2,368.74,18.13 +13.0751,0.0,18.1,0,0.58,5.713,56.7,2.8237,24,666.0,20.2,396.9,14.76 +4.34879,0.0,18.1,0,0.58,6.167,84.0,3.0334,24,666.0,20.2,396.9,16.29 +4.03841,0.0,18.1,0,0.532,6.229,90.7,3.0993,24,666.0,20.2,395.33,12.87 +3.56868,0.0,18.1,0,0.58,6.437,75.0,2.8965,24,666.0,20.2,393.37,14.36 +4.64689,0.0,18.1,0,0.614,6.98,67.6,2.5329,24,666.0,20.2,374.68,11.66 +8.05579,0.0,18.1,0,0.584,5.427,95.4,2.4298,24,666.0,20.2,352.58,18.14 +6.39312,0.0,18.1,0,0.584,6.162,97.4,2.206,24,666.0,20.2,302.76,24.1 +4.87141,0.0,18.1,0,0.614,6.484,93.6,2.3053,24,666.0,20.2,396.21,18.68 +15.0234,0.0,18.1,0,0.614,5.304,97.3,2.1007,24,666.0,20.2,349.48,24.91 +10.233,0.0,18.1,0,0.614,6.185,96.7,2.1705,24,666.0,20.2,379.7,18.03 +14.3337,0.0,18.1,0,0.614,6.229,88.0,1.9512,24,666.0,20.2,383.32,13.11 +5.82401,0.0,18.1,0,0.532,6.242,64.7,3.4242,24,666.0,20.2,396.9,10.74 +5.70818,0.0,18.1,0,0.532,6.75,74.9,3.3317,24,666.0,20.2,393.07,7.74 +5.73116,0.0,18.1,0,0.532,7.061,77.0,3.4106,24,666.0,20.2,395.28,7.01 +2.81838,0.0,18.1,0,0.532,5.762,40.3,4.0983,24,666.0,20.2,392.92,10.42 +2.37857,0.0,18.1,0,0.583,5.871,41.9,3.724,24,666.0,20.2,370.73,13.34 +3.67367,0.0,18.1,0,0.583,6.312,51.9,3.9917,24,666.0,20.2,388.62,10.58 +5.69175,0.0,18.1,0,0.583,6.114,79.8,3.5459,24,666.0,20.2,392.68,14.98 +4.83567,0.0,18.1,0,0.583,5.905,53.2,3.1523,24,666.0,20.2,388.22,11.45 +0.15086,0.0,27.74,0,0.609,5.454,92.7,1.8209,4,711.0,20.1,395.09,18.06 +0.18337,0.0,27.74,0,0.609,5.414,98.3,1.7554,4,711.0,20.1,344.05,23.97 +0.20746,0.0,27.74,0,0.609,5.093,98.0,1.8226,4,711.0,20.1,318.43,29.68 +0.10574,0.0,27.74,0,0.609,5.983,98.8,1.8681,4,711.0,20.1,390.11,18.07 +0.11132,0.0,27.74,0,0.609,5.983,83.5,2.1099,4,711.0,20.1,396.9,13.35 +0.17331,0.0,9.69,0,0.585,5.707,54.0,2.3817,6,391.0,19.2,396.9,12.01 +0.27957,0.0,9.69,0,0.585,5.926,42.6,2.3817,6,391.0,19.2,396.9,13.59 +0.17899,0.0,9.69,0,0.585,5.67,28.8,2.7986,6,391.0,19.2,393.29,17.6 +0.2896,0.0,9.69,0,0.585,5.39,72.9,2.7986,6,391.0,19.2,396.9,21.14 +0.26838,0.0,9.69,0,0.585,5.794,70.6,2.8927,6,391.0,19.2,396.9,14.1 +0.23912,0.0,9.69,0,0.585,6.019,65.3,2.4091,6,391.0,19.2,396.9,12.92 +0.17783,0.0,9.69,0,0.585,5.569,73.5,2.3999,6,391.0,19.2,395.77,15.1 +0.22438,0.0,9.69,0,0.585,6.027,79.7,2.4982,6,391.0,19.2,396.9,14.33 +0.06263,0.0,11.93,0,0.573,6.593,69.1,2.4786,1,273.0,21.0,391.99,9.67 +0.04527,0.0,11.93,0,0.573,6.12,76.7,2.2875,1,273.0,21.0,396.9,9.08 +0.06076,0.0,11.93,0,0.573,6.976,91.0,2.1675,1,273.0,21.0,396.9,5.64 +0.10959,0.0,11.93,0,0.573,6.794,89.3,2.3889,1,273.0,21.0,393.45,6.48 +0.04741,0.0,11.93,0,0.573,6.03,80.8,2.505,1,273.0,21.0,396.9,7.88 diff --git a/src/mlpack/tests/data/boston_housing_price_labels.csv b/src/mlpack/tests/data/boston_housing_price_labels.csv new file mode 100644 index 0000000000..fd7ad517aa --- /dev/null +++ b/src/mlpack/tests/data/boston_housing_price_labels.csv @@ -0,0 +1,507 @@ +0 +24.0 +21.6 +34.7 +33.4 +36.2 +28.7 +22.9 +27.1 +16.5 +18.9 +15.0 +18.9 +21.7 +20.4 +18.2 +19.9 +23.1 +17.5 +20.2 +18.2 +13.6 +19.6 +15.2 +14.5 +15.6 +13.9 +16.6 +14.8 +18.4 +21.0 +12.7 +14.5 +13.2 +13.1 +13.5 +18.9 +20.0 +21.0 +24.7 +30.8 +34.9 +26.6 +25.3 +24.7 +21.2 +19.3 +20.0 +16.6 +14.4 +19.4 +19.7 +20.5 +25.0 +23.4 +18.9 +35.4 +24.7 +31.6 +23.3 +19.6 +18.7 +16.0 +22.2 +25.0 +33.0 +23.5 +19.4 +22.0 +17.4 +20.9 +24.2 +21.7 +22.8 +23.4 +24.1 +21.4 +20.0 +20.8 +21.2 +20.3 +28.0 +23.9 +24.8 +22.9 +23.9 +26.6 +22.5 +22.2 +23.6 +28.7 +22.6 +22.0 +22.9 +25.0 +20.6 +28.4 +21.4 +38.7 +43.8 +33.2 +27.5 +26.5 +18.6 +19.3 +20.1 +19.5 +19.5 +20.4 +19.8 +19.4 +21.7 +22.8 +18.8 +18.7 +18.5 +18.3 +21.2 +19.2 +20.4 +19.3 +22.0 +20.3 +20.5 +17.3 +18.8 +21.4 +15.7 +16.2 +18.0 +14.3 +19.2 +19.6 +23.0 +18.4 +15.6 +18.1 +17.4 +17.1 +13.3 +17.8 +14.0 +14.4 +13.4 +15.6 +11.8 +13.8 +15.6 +14.6 +17.8 +15.4 +21.5 +19.6 +15.3 +19.4 +17.0 +15.6 +13.1 +41.3 +24.3 +23.3 +27.0 +50.0 +50.0 +50.0 +22.7 +25.0 +50.0 +23.8 +23.8 +22.3 +17.4 +19.1 +23.1 +23.6 +22.6 +29.4 +23.2 +24.6 +29.9 +37.2 +39.8 +36.2 +37.9 +32.5 +26.4 +29.6 +50.0 +32.0 +29.8 +34.9 +37.0 +30.5 +36.4 +31.1 +29.1 +50.0 +33.3 +30.3 +34.6 +34.9 +32.9 +24.1 +42.3 +48.5 +50.0 +22.6 +24.4 +22.5 +24.4 +20.0 +21.7 +19.3 +22.4 +28.1 +23.7 +25.0 +23.3 +28.7 +21.5 +23.0 +26.7 +21.7 +27.5 +30.1 +44.8 +50.0 +37.6 +31.6 +46.7 +31.5 +24.3 +31.7 +41.7 +48.3 +29.0 +24.0 +25.1 +31.5 +23.7 +23.3 +22.0 +20.1 +22.2 +23.7 +17.6 +18.5 +24.3 +20.5 +24.5 +26.2 +24.4 +24.8 +29.6 +42.8 +21.9 +20.9 +44.0 +50.0 +36.0 +30.1 +33.8 +43.1 +48.8 +31.0 +36.5 +22.8 +30.7 +50.0 +43.5 +20.7 +21.1 +25.2 +24.4 +35.2 +32.4 +32.0 +33.2 +33.1 +29.1 +35.1 +45.4 +35.4 +46.0 +50.0 +32.2 +22.0 +20.1 +23.2 +22.3 +24.8 +28.5 +37.3 +27.9 +23.9 +21.7 +28.6 +27.1 +20.3 +22.5 +29.0 +24.8 +22.0 +26.4 +33.1 +36.1 +28.4 +33.4 +28.2 +22.8 +20.3 +16.1 +22.1 +19.4 +21.6 +23.8 +16.2 +17.8 +19.8 +23.1 +21.0 +23.8 +23.1 +20.4 +18.5 +25.0 +24.6 +23.0 +22.2 +19.3 +22.6 +19.8 +17.1 +19.4 +22.2 +20.7 +21.1 +19.5 +18.5 +20.6 +19.0 +18.7 +32.7 +16.5 +23.9 +31.2 +17.5 +17.2 +23.1 +24.5 +26.6 +22.9 +24.1 +18.6 +30.1 +18.2 +20.6 +17.8 +21.7 +22.7 +22.6 +25.0 +19.9 +20.8 +16.8 +21.9 +27.5 +21.9 +23.1 +50.0 +50.0 +50.0 +50.0 +50.0 +13.8 +13.8 +15.0 +13.9 +13.3 +13.1 +10.2 +10.4 +10.9 +11.3 +12.3 +8.8 +7.2 +10.5 +7.4 +10.2 +11.5 +15.1 +23.2 +9.7 +13.8 +12.7 +13.1 +12.5 +8.5 +5.0 +6.3 +5.6 +7.2 +12.1 +8.3 +8.5 +5.0 +11.9 +27.9 +17.2 +27.5 +15.0 +17.2 +17.9 +16.3 +7.0 +7.2 +7.5 +10.4 +8.8 +8.4 +16.7 +14.2 +20.8 +13.4 +11.7 +8.3 +10.2 +10.9 +11.0 +9.5 +14.5 +14.1 +16.1 +14.3 +11.7 +13.4 +9.6 +8.7 +8.4 +12.8 +10.5 +17.1 +18.4 +15.4 +10.8 +11.8 +14.9 +12.6 +14.1 +13.0 +13.4 +15.2 +16.1 +17.8 +14.9 +14.1 +12.7 +13.5 +14.9 +20.0 +16.4 +17.7 +19.5 +20.2 +21.4 +19.9 +19.0 +19.1 +19.1 +20.1 +19.9 +19.6 +23.2 +29.8 +13.8 +13.3 +16.7 +12.0 +14.6 +21.4 +23.0 +23.7 +25.0 +21.8 +20.6 +21.2 +19.1 +20.6 +15.2 +7.0 +8.1 +13.6 +20.1 +21.8 +24.5 +23.1 +19.7 +18.3 +21.2 +17.5 +16.8 +22.4 +20.6 +23.9 +22.0 +11.9 diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index c8a4db9d03..05031b3f29 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -10,7 +10,7 @@ * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ #include -#include +#include #include #include #include @@ -19,6 +19,7 @@ #include "catch.hpp" #include "serialization.hpp" #include "mock_categorical_data.hpp" +#include "test_function_tools.hpp" using namespace mlpack; using namespace mlpack::tree; @@ -306,3 +307,492 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") // Make sure there was no split. REQUIRE(gain == DBL_MAX); } + +/** + * A basic construction of the decision tree---ensure that we can create the + * tree and that it split at least once. + */ +TEST_CASE("BasicConstructionTest_", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } + + // Use default parameters. + DecisionTreeRegressor<> d(dataset, labels); + + // Now require that we have some children. + REQUIRE(d.NumChildren() > 0); +} + +/** + * Construct a tree with weighted labels. + */ +TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } + arma::rowvec weights(labels.n_elem); + weights.ones(); + + // Use default parameters. + DecisionTreeRegressor<> wd(dataset, labels, weights); + DecisionTreeRegressor<> d(dataset, labels); + + // Now require that we have some children. + REQUIRE(wd.NumChildren() > 0); + REQUIRE(wd.NumChildren() == d.NumChildren()); +} + +/** + * Construct the decision tree on numeric data only and see that we can fit it + * exactly and achieve perfect performance on the training set. + */ +TEST_CASE("PerfectTrainingSet_", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } + + DecisionTreeRegressor<> d(dataset, labels, 1, 0.0); // Minimum leaf size of 1. + + // Make sure that we can get perfect accuracy on the training set. + for (size_t i = 0; i < 100; ++i) + { + double prediction; + prediction = d.Predict(dataset.col(i)); + + REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + } +} + +/** + * Construct the decision tree with weighted labels + */ +TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") +{ + // Completely random dataset with no structure. + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } + arma::rowvec weights(labels.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, labels, weights, 1, 0.0); + + // This part of code is dupliacte with no weighted one. + for (size_t i = 0; i < 100; ++i) + { + size_t prediction; + prediction = d.Predict(dataset.col(i)); + + REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + } +} + +/** + * Test that the decision tree generalizes reasonably. + */ +TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::Row trainLabels, testLabels; + LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + + // Initialize an all-ones weight matrix. + arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + + // Build decision tree. + DecisionTreeRegressor<> d(trainData, info, trainLabels); + DecisionTreeRegressor<> wd(trainData, info, trainLabels, weights); + + // Get the predicted test labels. + arma::Row predictions; + d.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out rmse. + double rmse = RMSE(predictions, testLabels); + + REQUIRE(rmse < 9.21); + std::cout << predictions << std::endl << testLabels; + + // Reset the prediction. + predictions.zeros(); + wd.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out the rmse. + double wdrmse = RMSE(predictions, testLabels); + + REQUIRE(wdrmse < 9.21); +} + +/** + * Test that the decision tree generalizes reasonably when built on float data. + */ +TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::Row trainLabels, testLabels; + LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + + // Initialize an all-ones weight matrix. + arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + + // Build decision tree. + DecisionTreeRegressor<> d(trainData, trainLabels); + DecisionTreeRegressor<> wd(trainData, trainLabels, weights); + + // Get the predicted test labels. + arma::Row predictions; + d.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out the rmse. + double rmse = RMSE(predictions, testLabels); + + REQUIRE(rmse < 9.21); + std::cout << R2Score(predictions, testLabels) std::endl; + + // Reset the prediction. + predictions.zeros(); + wd.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out the rmse. + double wdrmse = RMSE(predictions, testLabels); + + REQUIRE(wdrmse < 9.21); +} + +// /** +// * Test that we can build a decision tree on a simple categorical dataset. +// */ +// TEST_CASE("CategoricalBuildTest", "[DecisionTreeTest]") +// { +// arma::mat d; +// arma::Row l; +// data::DatasetInfo di; +// MockCategoricalData(d, l, di); + +// // Split into a training set and a test set. +// arma::mat trainingData = d.cols(0, 1999); +// arma::mat testData = d.cols(2000, 3999); +// arma::Row trainingLabels = l.subvec(0, 1999); +// arma::Row testLabels = l.subvec(2000, 3999); + +// // Build the tree. +// DecisionTree<> tree(trainingData, di, trainingLabels, 5, 10); + +// // Now evaluate the accuracy of the tree. +// arma::Row predictions; +// tree.Classify(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); +// size_t correct = 0; +// for (size_t i = 0; i < testData.n_cols; ++i) +// if (testLabels[i] == predictions[i]) +// ++correct; + +// // Make sure we got at least 70% accuracy. +// const double correctPct = double(correct) / double(testData.n_cols); +// REQUIRE(correctPct > 0.70); +// } + +// /** +// * Test that we can build a decision tree with weights on a simple categorical +// * dataset. +// */ +// TEST_CASE("CategoricalBuildTestWithWeight", "[DecisionTreeTest]") +// { +// arma::mat d; +// arma::Row l; +// data::DatasetInfo di; +// MockCategoricalData(d, l, di); + +// // Split into a training set and a test set. +// arma::mat trainingData = d.cols(0, 1999); +// arma::mat testData = d.cols(2000, 3999); +// arma::Row trainingLabels = l.subvec(0, 1999); +// arma::Row testLabels = l.subvec(2000, 3999); + +// arma::Row weights = arma::ones>( +// trainingLabels.n_elem); + +// // Build the tree. +// DecisionTree<> tree(trainingData, di, trainingLabels, 5, weights, 10); + +// // Now evaluate the accuracy of the tree. +// arma::Row predictions; +// tree.Classify(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); +// size_t correct = 0; +// for (size_t i = 0; i < testData.n_cols; ++i) +// if (testLabels[i] == predictions[i]) +// ++correct; + +// // Make sure we got at least 70% accuracy. +// const double correctPct = double(correct) / double(testData.n_cols); +// REQUIRE(correctPct > 0.70); +// } + +/** + * Test that we can build a decision tree using weighted data (where the + * low-weighted data is random noise), and that the tree still builds correctly + * enough to get good results. + */ +TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::Row trainLabels, testLabels; + LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + + // Add some noise. + arma::mat noise(trainData.n_rows, 500, arma::fill::randu); + arma::Row noiseLabels(500); + for (size_t i = 0; i < noiseLabels.n_elem; ++i) + noiseLabels[i] = 15 + math::Random(0, 10); // Random label. + + // Concatenate data matrices. + arma::mat data = arma::join_rows(trainData, noise); + arma::Row fullLabels = arma::join_rows(trainLabels, noiseLabels); + + // Now set weights. + arma::rowvec weights(trainData.n_cols + 500); + for (size_t i = 0; i < trainData.n_cols; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) + weights[i] = math::Random(0.0, 0.01); // Low weights for false points. + + // Now build the decision tree. I think the syntax is right here. + DecisionTreeRegressor<> d(data, fullLabels, weights); + + // Now we can check that we get good performance on the VC2 test set. + arma::Row predictions; + d.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out the accuracy. + double rmse = RMSE(predictions, testLabels); + + REQUIRE(rmse < 9.21); +} + +// /** +// * Test that we can build a decision tree on a simple categorical dataset using +// * weights, with low-weight noise added. +// */ +// TEST_CASE("CategoricalWeightedBuildTest", "[DecisionTreeTest]") +// { +// arma::mat d; +// arma::Row l; +// data::DatasetInfo di; +// MockCategoricalData(d, l, di); + +// // Split into a training set and a test set. +// arma::mat trainingData = d.cols(0, 1999); +// arma::mat testData = d.cols(2000, 3999); +// arma::Row trainingLabels = l.subvec(0, 1999); +// arma::Row testLabels = l.subvec(2000, 3999); + +// // Now create random points. +// arma::mat randomNoise(4, 2000); +// arma::Row randomLabels(2000); +// for (size_t i = 0; i < 2000; ++i) +// { +// randomNoise(0, i) = math::Random(); +// randomNoise(1, i) = math::Random(); +// randomNoise(2, i) = math::RandInt(4); +// randomNoise(3, i) = math::RandInt(2); +// randomLabels[i] = math::RandInt(5); +// } + +// // Generate weights. +// arma::rowvec weights(4000); +// for (size_t i = 0; i < 2000; ++i) +// weights[i] = math::Random(0.9, 1.0); +// for (size_t i = 2000; i < 4000; ++i) +// weights[i] = math::Random(0.0, 0.001); + +// arma::mat fullData = arma::join_rows(trainingData, randomNoise); +// arma::Row fullLabels = arma::join_rows(trainingLabels, randomLabels); + +// // Build the tree. +// DecisionTree<> tree(fullData, di, fullLabels, 5, weights, 10); + +// // Now evaluate the accuracy of the tree. +// arma::Row predictions; +// tree.Classify(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); +// size_t correct = 0; +// for (size_t i = 0; i < testData.n_cols; ++i) +// if (testLabels[i] == predictions[i]) +// ++correct; + +// // Make sure we got at least 70% accuracy. +// const double correctPct = double(correct) / double(testData.n_cols); +// REQUIRE(correctPct > 0.70); +// } + +// /** +// * Test that we can build a decision tree using weighted data (where the +// * low-weighted data is random noise) with information gain, and that the tree +// * still builds correctly enough to get good results. +// */ +// TEST_CASE("WeightedDecisionTreeInformationGainTest_", +// "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset; +// arma::Row labels; +// if (!data::Load("vc2.csv", dataset)) +// FAIL("Cannot load test dataset vc2.csv!"); +// if (!data::Load("vc2_labels.txt", labels)) +// FAIL("Cannot load labels for vc2_labels.txt!"); + +// // Add some noise. +// arma::mat noise(dataset.n_rows, 1000, arma::fill::randu); +// arma::Row noiseLabels(1000); +// for (size_t i = 0; i < noiseLabels.n_elem; ++i) +// noiseLabels[i] = math::Random(0, 3); // Random label. + +// // Concatenate data matrices. +// arma::mat data = arma::join_rows(dataset, noise); +// arma::Row fullLabels = arma::join_rows(labels, noiseLabels); + +// // Now set weights. +// arma::rowvec weights(dataset.n_cols + 1000); +// for (size_t i = 0; i < dataset.n_cols; ++i) +// weights[i] = math::Random(0.9, 1.0); +// for (size_t i = dataset.n_cols; i < dataset.n_cols + 1000; ++i) +// weights[i] = math::Random(0.0, 0.01); // Low weights for false points. + +// // Now build the decision tree. I think the syntax is right here. +// DecisionTreeRegressor d(data, fullLabels, weights); + +// // Now we can check that we get good performance on the VC2 test set. +// arma::mat testData; +// arma::Row testLabels; +// if (!data::Load("vc2_test.csv", testData)) +// FAIL("Cannot load test dataset vc2_test.csv!"); +// if (!data::Load("vc2_test_labels.txt", testLabels)) +// FAIL("Cannot load labels for vc2_test_labels.txt!"); + +// arma::Row predictions; +// d.Predict(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); + +// // Figure out the accuracy. +// double accuracy = R2Score(predictions, testLabels); + +// REQUIRE(accuracy > 0.75); +// } + +// /** +// * Test that we can build a decision tree using information gain on a simple +// * categorical dataset using weights, with low-weight noise added. +// */ +// TEST_CASE("CategoricalInformationGainWeightedBuildTest", "[DecisionTreeTest]") +// { +// arma::mat d; +// arma::Row l; +// data::DatasetInfo di; +// MockCategoricalData(d, l, di); + +// // Split into a training set and a test set. +// arma::mat trainingData = d.cols(0, 1999); +// arma::mat testData = d.cols(2000, 3999); +// arma::Row trainingLabels = l.subvec(0, 1999); +// arma::Row testLabels = l.subvec(2000, 3999); + +// // Now create random points. +// arma::mat randomNoise(4, 2000); +// arma::Row randomLabels(2000); +// for (size_t i = 0; i < 2000; ++i) +// { +// randomNoise(0, i) = math::Random(); +// randomNoise(1, i) = math::Random(); +// randomNoise(2, i) = math::RandInt(4); +// randomNoise(3, i) = math::RandInt(2); +// randomLabels[i] = math::RandInt(5); +// } + +// // Generate weights. +// arma::rowvec weights(4000); +// for (size_t i = 0; i < 2000; ++i) +// weights[i] = math::Random(0.9, 1.0); +// for (size_t i = 2000; i < 4000; ++i) +// weights[i] = math::Random(0.0, 0.001); + +// arma::mat fullData = arma::join_rows(trainingData, randomNoise); +// arma::Row fullLabels = arma::join_rows(trainingLabels, randomLabels); + +// // Build the tree. +// DecisionTree tree(fullData, di, fullLabels, 5, weights, 10); + +// // Now evaluate the accuracy of the tree. +// arma::Row predictions; +// tree.Classify(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); +// size_t correct = 0; +// for (size_t i = 0; i < testData.n_cols; ++i) +// if (testLabels[i] == predictions[i]) +// ++correct; + +// // Make sure we got at least 70% accuracy. +// const double correctPct = double(correct) / double(testData.n_cols); +// REQUIRE(correctPct > 0.70); +// } From 64fde38ae8510fdeaf39a10a3103434454c9cde2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 28 May 2021 18:26:51 +0530 Subject: [PATCH 569/729] Testing for bug in implementation --- .../decision_tree_regressor_impl.hpp | 5 + .../tests/decision_tree_regressor_test.cpp | 482 +++++++++++------- 2 files changed, 310 insertions(+), 177 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 606518ba3c..f902a3c2fe 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -761,6 +761,7 @@ double DecisionTreeRegressor( labels.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + } return -bestGain; @@ -828,6 +829,7 @@ double DecisionTreeRegressor( labels.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + std::cout << "Number of poiints in leaf: " << count << std::endl; } return -bestGain; diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 05031b3f29..ef273b1921 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -312,204 +312,332 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") * A basic construction of the decision tree---ensure that we can create the * tree and that it split at least once. */ -TEST_CASE("BasicConstructionTest_", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); - for (size_t i = 0; i < 50; ++i) - { - dataset(3, i) = i; - labels[i] = 0.0; - } - for (size_t i = 50; i < 100; ++i) - { - dataset(3, i) = i; - labels[i] = 1.0; - } +// TEST_CASE("BasicConstructionTest_", "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset(10, 100, arma::fill::randu); +// arma::Row labels(100); +// for (size_t i = 0; i < 50; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 0.0; +// } +// for (size_t i = 50; i < 100; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 1.0; +// } - // Use default parameters. - DecisionTreeRegressor<> d(dataset, labels); +// // Use default parameters. +// DecisionTreeRegressor<> d(dataset, labels); - // Now require that we have some children. - REQUIRE(d.NumChildren() > 0); -} +// // Now require that we have some children. +// REQUIRE(d.NumChildren() > 0); +// } /** * Construct a tree with weighted labels. */ -TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); - for (size_t i = 0; i < 50; ++i) - { - dataset(3, i) = i; - labels[i] = 0.0; - } - for (size_t i = 50; i < 100; ++i) - { - dataset(3, i) = i; - labels[i] = 1.0; - } - arma::rowvec weights(labels.n_elem); - weights.ones(); +// TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset(10, 100, arma::fill::randu); +// arma::Row labels(100); +// for (size_t i = 0; i < 50; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 0.0; +// } +// for (size_t i = 50; i < 100; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 1.0; +// } +// arma::rowvec weights(labels.n_elem); +// weights.ones(); - // Use default parameters. - DecisionTreeRegressor<> wd(dataset, labels, weights); - DecisionTreeRegressor<> d(dataset, labels); +// // Use default parameters. +// DecisionTreeRegressor<> wd(dataset, labels, weights); +// DecisionTreeRegressor<> d(dataset, labels); - // Now require that we have some children. - REQUIRE(wd.NumChildren() > 0); - REQUIRE(wd.NumChildren() == d.NumChildren()); -} +// // Now require that we have some children. +// REQUIRE(wd.NumChildren() > 0); +// REQUIRE(wd.NumChildren() == d.NumChildren()); +// } /** * Construct the decision tree on numeric data only and see that we can fit it * exactly and achieve perfect performance on the training set. */ -TEST_CASE("PerfectTrainingSet_", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); - for (size_t i = 0; i < 50; ++i) - { - dataset(3, i) = i; - labels[i] = 0.0; - } - for (size_t i = 50; i < 100; ++i) - { - dataset(3, i) = i; - labels[i] = 1.0; - } +// TEST_CASE("PerfectTrainingSet_", "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset(10, 100, arma::fill::randu); +// arma::Row labels(100); +// for (size_t i = 0; i < 50; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 0.0; +// } +// for (size_t i = 50; i < 100; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 1.0; +// } - DecisionTreeRegressor<> d(dataset, labels, 1, 0.0); // Minimum leaf size of 1. +// DecisionTreeRegressor<> d(dataset, labels, 1, 0.0); // Minimum leaf size of 1. - // Make sure that we can get perfect accuracy on the training set. - for (size_t i = 0; i < 100; ++i) - { - double prediction; - prediction = d.Predict(dataset.col(i)); +// // Make sure that we can get perfect accuracy on the training set. +// for (size_t i = 0; i < 100; ++i) +// { +// double prediction; +// prediction = d.Predict(dataset.col(i)); - REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); - } -} +// REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); +// } +// } /** * Construct the decision tree with weighted labels */ -TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") -{ - // Completely random dataset with no structure. - arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); - for (size_t i = 0; i < 50; ++i) - { - dataset(3, i) = i; - labels[i] = 0.0; - } - for (size_t i = 50; i < 100; ++i) - { - dataset(3, i) = i; - labels[i] = 1.0; - } - arma::rowvec weights(labels.n_elem); - weights.ones(); +// TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") +// { +// // Completely random dataset with no structure. +// arma::mat dataset(10, 100, arma::fill::randu); +// arma::Row labels(100); +// for (size_t i = 0; i < 50; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 0.0; +// } +// for (size_t i = 50; i < 100; ++i) +// { +// dataset(3, i) = i; +// labels[i] = 1.0; +// } + // arma::rowvec weights(labels.n_elem); + // weights.ones(); - // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, labels, weights, 1, 0.0); + // // Minimum leaf size of 1. + // DecisionTreeRegressor<> d(dataset, labels, weights, 1, 0.0); - // This part of code is dupliacte with no weighted one. - for (size_t i = 0; i < 100; ++i) - { - size_t prediction; - prediction = d.Predict(dataset.col(i)); + // // This part of code is dupliacte with no weighted one. + // for (size_t i = 0; i < 100; ++i) + // { + // size_t prediction; + // prediction = d.Predict(dataset.col(i)); - REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); - } -} + // REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + // } +// } /** * Test that the decision tree generalizes reasonably. */ -TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") -{ - // Loading data. - data::DatasetInfo info; - arma::mat trainData, testData; - arma::Row trainLabels, testLabels; - LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); +// TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") +// { +// // Loading data. +// data::DatasetInfo info; +// arma::mat trainData, testData; +// arma::Row trainLabels, testLabels; +// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); - // Initialize an all-ones weight matrix. - arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); +// // Initialize an all-ones weight matrix. +// arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); - // Build decision tree. - DecisionTreeRegressor<> d(trainData, info, trainLabels); - DecisionTreeRegressor<> wd(trainData, info, trainLabels, weights); +// // Build decision tree. +// DecisionTreeRegressor<> d(trainData, info, trainLabels, 1, 1e-7, 20); +// DecisionTreeRegressor<> wd(trainData, info, trainLabels, weights, 1, 1e-7, 20); - // Get the predicted test labels. - arma::Row predictions; - d.Predict(testData, predictions); +// // Get the predicted test labels. +// arma::Row predictions; +// d.Predict(testData, predictions); - REQUIRE(predictions.n_elem == testData.n_cols); +// REQUIRE(predictions.n_elem == testData.n_cols); - // Figure out rmse. - double rmse = RMSE(predictions, testLabels); +// // Figure out rmse. +// double rmse = RMSE(predictions, testLabels); - REQUIRE(rmse < 9.21); - std::cout << predictions << std::endl << testLabels; +// REQUIRE(rmse < 9.21); +// // std::cout << predictions << std::endl << testLabels; +// arma::Row trainPred; +// d.Predict(trainData, trainPred); +// std::cout << trainPred; - // Reset the prediction. - predictions.zeros(); - wd.Predict(testData, predictions); +// DecisionTreeRegressor<> dt = d; +// // Print number of childrens; +// std::cout << dt.Child(0).NumChildren() << std::endl; +// std::cout << dt.Child(1).NumChildren() << std::endl; - REQUIRE(predictions.n_elem == testData.n_cols); +// // Reset the prediction. +// predictions.zeros(); +// wd.Predict(testData, predictions); - // Figure out the rmse. - double wdrmse = RMSE(predictions, testLabels); +// REQUIRE(predictions.n_elem == testData.n_cols); - REQUIRE(wdrmse < 9.21); -} +// // Figure out the rmse. +// double wdrmse = RMSE(predictions, testLabels); + +// REQUIRE(wdrmse < 9.21); +// } /** * Test that the decision tree generalizes reasonably when built on float data. */ -TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") +// TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") +// { +// // Loading data. +// data::DatasetInfo info; +// arma::mat trainData, testData; +// arma::Row trainLabels, testLabels; +// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + +// // Initialize an all-ones weight matrix. +// arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + +// // Build decision tree. +// DecisionTreeRegressor<> d(trainData, trainLabels); +// DecisionTreeRegressor<> wd(trainData, trainLabels, weights); + +// // Get the predicted test labels. +// arma::Row predictions; +// d.Predict(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); + +// // Figure out the rmse. +// double rmse = RMSE(predictions, testLabels); + +// REQUIRE(rmse < 9.21); +// std::cout << R2Score(predictions, testLabels) << std::endl; + +// // Reset the prediction. +// predictions.zeros(); +// wd.Predict(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); + +// // Figure out the rmse. +// double wdrmse = RMSE(predictions, testLabels); + +// REQUIRE(wdrmse < 9.21); +// } + +TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]") { - // Loading data. - data::DatasetInfo info; - arma::mat trainData, testData; - arma::Row trainLabels, testLabels; - LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + arma::mat dataset(10, 500, arma::fill::randu); + arma::Row labels(500); - // Initialize an all-ones weight matrix. - arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + for (size_t i = 0; i < 100; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + for (size_t i = 100; i < 200; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 200; i < 300; i++) + { + dataset(3, i) = i; + labels(i) = 2.0; + } + for (size_t i = 300; i < 400; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 400; i < 500; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } - // Build decision tree. - DecisionTreeRegressor<> d(trainData, trainLabels); - DecisionTreeRegressor<> wd(trainData, trainLabels, weights); + arma::rowvec weights(labels.n_elem); + weights.ones(); - // Get the predicted test labels. - arma::Row predictions; - d.Predict(testData, predictions); + // Minimum leaf size of 1. + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + std::cout << "****************End****************\n"; +} - REQUIRE(predictions.n_elem == testData.n_cols); +TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 250, arma::fill::randu); + arma::Row labels(500); - // Figure out the rmse. - double rmse = RMSE(predictions, testLabels); + for (size_t i = 0; i < 50; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + for (size_t i = 50; i < 100; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 100; i < 150; i++) + { + dataset(3, i) = i; + labels(i) = 2.0; + } + for (size_t i = 150; i < 200; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 200; i < 250; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } - REQUIRE(rmse < 9.21); - std::cout << R2Score(predictions, testLabels) std::endl; + arma::rowvec weights(labels.n_elem); + weights.ones(); - // Reset the prediction. - predictions.zeros(); - wd.Predict(testData, predictions); + // Minimum leaf size of 1. + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + std::cout << "****************End****************\n"; +} - REQUIRE(predictions.n_elem == testData.n_cols); +TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 500, arma::fill::randu); + arma::Row labels(500); - // Figure out the rmse. - double wdrmse = RMSE(predictions, testLabels); + for (size_t i = 0; i < 100; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + for (size_t i = 100; i < 200; i++) + { + dataset(3, i) = i; + labels(i) = 5.0; + } + for (size_t i = 200; i < 300; i++) + { + dataset(3, i) = i; + labels(i) = 10.0; + } + for (size_t i = 300; i < 400; i++) + { + dataset(3, i) = i; + labels(i) = 15.0; + } + for (size_t i = 400; i < 500; i++) + { + dataset(3, i) = i; + labels(i) = 20.0; + } - REQUIRE(wdrmse < 9.21); + arma::rowvec weights(labels.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + std::cout << "****************End****************\n"; } // /** @@ -589,45 +717,45 @@ TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") * low-weighted data is random noise), and that the tree still builds correctly * enough to get good results. */ -TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") -{ - // Loading data. - data::DatasetInfo info; - arma::mat trainData, testData; - arma::Row trainLabels, testLabels; - LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); +// TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") +// { +// // Loading data. +// data::DatasetInfo info; +// arma::mat trainData, testData; +// arma::Row trainLabels, testLabels; +// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); - // Add some noise. - arma::mat noise(trainData.n_rows, 500, arma::fill::randu); - arma::Row noiseLabels(500); - for (size_t i = 0; i < noiseLabels.n_elem; ++i) - noiseLabels[i] = 15 + math::Random(0, 10); // Random label. +// // Add some noise. +// arma::mat noise(trainData.n_rows, 500, arma::fill::randu); +// arma::Row noiseLabels(500); +// for (size_t i = 0; i < noiseLabels.n_elem; ++i) +// noiseLabels[i] = 15 + math::Random(0, 10); // Random label. - // Concatenate data matrices. - arma::mat data = arma::join_rows(trainData, noise); - arma::Row fullLabels = arma::join_rows(trainLabels, noiseLabels); +// // Concatenate data matrices. +// arma::mat data = arma::join_rows(trainData, noise); +// arma::Row fullLabels = arma::join_rows(trainLabels, noiseLabels); - // Now set weights. - arma::rowvec weights(trainData.n_cols + 500); - for (size_t i = 0; i < trainData.n_cols; ++i) - weights[i] = math::Random(0.9, 1.0); - for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) - weights[i] = math::Random(0.0, 0.01); // Low weights for false points. +// // Now set weights. +// arma::rowvec weights(trainData.n_cols + 500); +// for (size_t i = 0; i < trainData.n_cols; ++i) +// weights[i] = math::Random(0.9, 1.0); +// for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) +// weights[i] = math::Random(0.0, 0.01); // Low weights for false points. - // Now build the decision tree. I think the syntax is right here. - DecisionTreeRegressor<> d(data, fullLabels, weights); +// // Now build the decision tree. I think the syntax is right here. +// DecisionTreeRegressor<> d(data, fullLabels, weights); - // Now we can check that we get good performance on the VC2 test set. - arma::Row predictions; - d.Predict(testData, predictions); +// // Now we can check that we get good performance on the VC2 test set. +// arma::Row predictions; +// d.Predict(testData, predictions); - REQUIRE(predictions.n_elem == testData.n_cols); +// REQUIRE(predictions.n_elem == testData.n_cols); - // Figure out the accuracy. - double rmse = RMSE(predictions, testLabels); +// // Figure out the accuracy. +// double rmse = RMSE(predictions, testLabels); - REQUIRE(rmse < 9.21); -} +// REQUIRE(rmse < 9.21); +// } // /** // * Test that we can build a decision tree on a simple categorical dataset using From aa78c26d7ab1f3dd6d8ba719592b56a17572f269 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 1 Jun 2021 22:23:55 +0530 Subject: [PATCH 570/729] Added more debugging code --- .../decision_tree/decision_tree_regressor.hpp | 6 +- .../decision_tree_regressor_impl.hpp | 63 +++++++++++-------- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 55f6816f7e..fcdc1f17c8 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -482,7 +482,8 @@ class DecisionTreeRegressor : const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector); + DimensionSelectionType& dimensionSelector, + int& numLeaves); /** * Corresponding to the public Train() method, this method is designed for @@ -510,7 +511,8 @@ class DecisionTreeRegressor : const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector); + DimensionSelectionType& dimensionSelector, + int& numLeaves); }; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index f902a3c2fe..689aa7453f 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -65,12 +65,13 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Construct and train without weight on numeric data. @@ -101,11 +102,12 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Construct and train with weights. @@ -142,11 +144,12 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Construct and train on numeric data with weights. @@ -184,10 +187,11 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Take ownership of another tree and train with weights. @@ -265,10 +269,11 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Copy another tree. @@ -447,12 +452,12 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, leaves); } //! Train on the given data, assuming all dimensions are numeric. @@ -486,12 +491,13 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Train on the given weighted data. @@ -533,11 +539,12 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Train on the given weighted all numeric data. @@ -578,11 +585,12 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, leaves); + std::cout << "NumLeaves: " << leaves << std::endl; } //! Train on the given data. @@ -607,7 +615,8 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, datasetInfo, labels, numClasses, weights, currentCol - currentChildBegin, minimumGainSplit, - maximumDepth - 1, dimensionSelector); + maximumDepth - 1, dimensionSelector, numLeaves); } else { @@ -745,7 +754,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, datasetInfo, labels, numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, - dimensionSelector); + dimensionSelector, numLeaves); bestGain += double(childCounts[i]) / double(count) * (-childGain); } children.push_back(child); @@ -761,6 +770,7 @@ double DecisionTreeRegressor( labels.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + numLeaves++; } @@ -788,7 +798,8 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, labels, numClasses, weights, currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, - dimensionSelector); + dimensionSelector, numLeaves); } else { @@ -905,7 +916,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, labels, numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, - dimensionSelector); + dimensionSelector, numLeaves); bestGain += double(childCounts[i]) / double(count) * (-childGain); } children.push_back(child); @@ -920,7 +931,9 @@ double DecisionTreeRegressor( labels.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); - std::cout << "Number of poiints in leaf: " << count << std::endl; + std::cout << "Number of points in leaf: " << count << + " Prediction: " << splitPointOrPrediction << std::endl; + numLeaves++; } return -bestGain; From b6145adab8a28f5c6c10a3a0fd28beb11c617f4d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 1 Jun 2021 22:25:14 +0530 Subject: [PATCH 571/729] Add hand created dataset for testing --- .../tests/decision_tree_regressor_test.cpp | 308 +++++++++--------- 1 file changed, 161 insertions(+), 147 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index ef273b1921..201491e7b3 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -431,52 +431,52 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") /** * Test that the decision tree generalizes reasonably. */ -// TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") -// { -// // Loading data. -// data::DatasetInfo info; -// arma::mat trainData, testData; -// arma::Row trainLabels, testLabels; -// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); +TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::Row trainLabels, testLabels; + LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + std::cout << "Shape: "<< trainData.n_rows << " " << trainData.n_cols << std::endl; -// // Initialize an all-ones weight matrix. -// arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + // Initialize an all-ones weight matrix. + arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); -// // Build decision tree. -// DecisionTreeRegressor<> d(trainData, info, trainLabels, 1, 1e-7, 20); -// DecisionTreeRegressor<> wd(trainData, info, trainLabels, weights, 1, 1e-7, 20); + // Build decision tree. + DecisionTreeRegressor d(trainData, info, trainLabels, 1, 1e-7, 0); + DecisionTreeRegressor wd(trainData, info, trainLabels, weights, 1, 1e-7, 0); -// // Get the predicted test labels. -// arma::Row predictions; -// d.Predict(testData, predictions); + // Get the predicted test labels. + arma::Row predictions; + d.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); -// // Figure out rmse. -// double rmse = RMSE(predictions, testLabels); + // Figure out rmse. + double rmse = RMSE(predictions, testLabels); -// REQUIRE(rmse < 9.21); -// // std::cout << predictions << std::endl << testLabels; -// arma::Row trainPred; -// d.Predict(trainData, trainPred); -// std::cout << trainPred; + REQUIRE(rmse < 9.21); + // std::cout << predictions << std::endl << testLabels; + arma::Row trainPred; + d.Predict(trainData, trainPred); + std::cout << trainPred; -// DecisionTreeRegressor<> dt = d; -// // Print number of childrens; -// std::cout << dt.Child(0).NumChildren() << std::endl; -// std::cout << dt.Child(1).NumChildren() << std::endl; + std::cout << "Train RMSE: " << RMSE(trainLabels, trainPred) << std::endl; -// // Reset the prediction. -// predictions.zeros(); -// wd.Predict(testData, predictions); + // DecisionTreeRegressor<> dt = d; -// REQUIRE(predictions.n_elem == testData.n_cols); + // Reset the prediction. + predictions.zeros(); + wd.Predict(testData, predictions); -// // Figure out the rmse. -// double wdrmse = RMSE(predictions, testLabels); + REQUIRE(predictions.n_elem == testData.n_cols); -// REQUIRE(wdrmse < 9.21); -// } + // Figure out the rmse. + double wdrmse = RMSE(predictions, testLabels); + + REQUIRE(wdrmse < 9.21); +} /** * Test that the decision tree generalizes reasonably when built on float data. @@ -520,123 +520,137 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") // REQUIRE(wdrmse < 9.21); // } -TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset(10, 500, arma::fill::randu); - arma::Row labels(500); +// TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset(10, 500, arma::fill::randu); +// arma::Row labels(500); - for (size_t i = 0; i < 100; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - for (size_t i = 100; i < 200; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 200; i < 300; i++) - { - dataset(3, i) = i; - labels(i) = 2.0; - } - for (size_t i = 300; i < 400; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 400; i < 500; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } +// for (size_t i = 0; i < 100; i++) +// { +// dataset(3, i) = i; +// labels(i) = 0.0; +// } +// for (size_t i = 100; i < 200; i++) +// { +// dataset(3, i) = i; +// labels(i) = 1.0; +// } +// for (size_t i = 200; i < 300; i++) +// { +// dataset(3, i) = i; +// labels(i) = 2.0; +// } +// for (size_t i = 300; i < 400; i++) +// { +// dataset(3, i) = i; +// labels(i) = 1.0; +// } +// for (size_t i = 400; i < 500; i++) +// { +// dataset(3, i) = i; +// labels(i) = 0.0; +// } + +// arma::rowvec weights(labels.n_elem); +// weights.ones(); + +// // Minimum leaf size of 1. +// std::cout << "****************Start**************\n"; +// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); +// std::cout << "****************End****************\n"; +// } + +// TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset(10, 250, arma::fill::randu); +// arma::Row labels(500); + +// for (size_t i = 0; i < 50; i++) +// { +// dataset(3, i) = i; +// labels(i) = 0.0; +// } +// for (size_t i = 50; i < 100; i++) +// { +// dataset(3, i) = i; +// labels(i) = 1.0; +// } +// for (size_t i = 100; i < 150; i++) +// { +// dataset(3, i) = i; +// labels(i) = 2.0; +// } +// for (size_t i = 150; i < 200; i++) +// { +// dataset(3, i) = i; +// labels(i) = 1.0; +// } +// for (size_t i = 200; i < 250; i++) +// { +// dataset(3, i) = i; +// labels(i) = 0.0; +// } + +// arma::rowvec weights(labels.n_elem); +// weights.ones(); + +// // Minimum leaf size of 1. +// std::cout << "****************Start**************\n"; +// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); +// std::cout << "****************End****************\n"; +// } + +// TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]") +// { +// arma::mat dataset(10, 500, arma::fill::randu); +// arma::Row labels(500); + +// for (size_t i = 0; i < 100; i++) +// { +// dataset(3, i) = i; +// labels(i) = 0.0; +// } +// for (size_t i = 100; i < 200; i++) +// { +// dataset(3, i) = i; +// labels(i) = 5.0; +// } +// for (size_t i = 200; i < 300; i++) +// { +// dataset(3, i) = i; +// labels(i) = 10.0; +// } +// for (size_t i = 300; i < 400; i++) +// { +// dataset(3, i) = i; +// labels(i) = 15.0; +// } +// for (size_t i = 400; i < 500; i++) +// { +// dataset(3, i) = i; +// labels(i) = 20.0; +// } + +// arma::rowvec weights(labels.n_elem); +// weights.ones(); + +// // Minimum leaf size of 1. +// std::cout << "****************Start**************\n"; +// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); +// std::cout << "****************End****************\n"; +// } + +TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") +{ + // drug dosage (in mg). + arma::mat dataset = {{2, 3, 5, 10, 14, 16, 20, 22, 28, 30, 32, 35, 39}}; + // percentage effectiveness. + arma::rowvec labels = {0, 0, 0, 5, 99, 99, 99, 95, 55, 45, 7, 0, 0}; arma::rowvec weights(labels.n_elem); weights.ones(); - - // Minimum leaf size of 1. std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); - std::cout << "****************End****************\n"; -} - -TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset(10, 250, arma::fill::randu); - arma::Row labels(500); - - for (size_t i = 0; i < 50; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - for (size_t i = 50; i < 100; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 100; i < 150; i++) - { - dataset(3, i) = i; - labels(i) = 2.0; - } - for (size_t i = 150; i < 200; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 200; i < 250; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - - arma::rowvec weights(labels.n_elem); - weights.ones(); - - // Minimum leaf size of 1. - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); - std::cout << "****************End****************\n"; -} - -TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset(10, 500, arma::fill::randu); - arma::Row labels(500); - - for (size_t i = 0; i < 100; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - for (size_t i = 100; i < 200; i++) - { - dataset(3, i) = i; - labels(i) = 5.0; - } - for (size_t i = 200; i < 300; i++) - { - dataset(3, i) = i; - labels(i) = 10.0; - } - for (size_t i = 300; i < 400; i++) - { - dataset(3, i) = i; - labels(i) = 15.0; - } - for (size_t i = 400; i < 500; i++) - { - dataset(3, i) = i; - labels(i) = 20.0; - } - - arma::rowvec weights(labels.n_elem); - weights.ones(); - - // Minimum leaf size of 1. - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 5); std::cout << "****************End****************\n"; } From b5c72f126801ab5ac892bfc979fafad672d7f944 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 12 Jun 2021 17:47:59 +0530 Subject: [PATCH 572/729] Fixed MSEgain computation --- src/mlpack/methods/decision_tree/mse_gain.hpp | 2 - .../tests/decision_tree_regressor_test.cpp | 143 +++++++++--------- 2 files changed, 73 insertions(+), 72 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index e12ae34ae4..340aee99a9 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -73,8 +73,6 @@ class MSEGain for (size_t i = begin; i < end; ++i) mse += std::pow(labels[i] - mean, 2); - - mse /= (double) (end - begin); } return -mse; diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 201491e7b3..ad95a3b891 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -38,23 +38,6 @@ TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressorTest]") Approx(0.0).margin(1e-5)); } -/** - * Make sure that the MSE gain is equal to negative of variance. - */ -TEST_CASE("MSEGainVarianceTest", "[DecisionTreeRegressorTest]") -{ - arma::rowvec weights(100, arma::fill::ones); - arma::rowvec labels(100, arma::fill::randn); - - // Theoretical gain. - double theoreticalGain = - arma::var(labels) * 99.0 / 100.0; - - // Calculated gain. - const double calculatedGain = MSEGain::Evaluate(labels, 0, weights); - - REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-9)); -} - /** * The MSE gain of an empty vector is 0. */ @@ -248,7 +231,6 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest1", "[DecisionTreeRegressorTest] // should be between 4 and 5. REQUIRE(splitInfo > 0.4); REQUIRE(splitInfo < 0.5); - std::cout << "Done\n"; } /** @@ -431,51 +413,72 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") /** * Test that the decision tree generalizes reasonably. */ -TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") +// TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") +// { +// const size_t minLeafSize = 1; +// const double minGainSplit = 1e-7; +// const size_t depth = 2; + +// // Loading data. +// data::DatasetInfo info; +// arma::mat trainData, testData; +// arma::Row trainLabels, testLabels; +// arma::rowvec weights = arma::ones(355); +// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); +// std::cout << "Shape: "<< trainData.n_rows << " " << trainData.n_cols << std::endl; +// // for(size_t i = 0; i < info.Dimensionality(); i++) +// // { +// // std::cout << info.Type(i) << " "; +// // } +// // std::cout << std::endl; + +// // Build decision tree. +// DecisionTreeRegressor d(trainData, info, trainLabels, minLeafSize, minGainSplit, depth); + +// // Get the predicted test labels. +// arma::Row predictions; +// d.Predict(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); + +// // Figure out rmse. +// double rmse = RMSE(predictions, testLabels); + +// // REQUIRE(rmse < 9.21); +// // std::cout << predictions << std::endl << testLabels; +// arma::Row trainPred; +// d.Predict(trainData, trainPred); +// // std::cout << trainPred; + +// // double splitInfo; +// // BestBinaryNumericSplit::AuxiliarySplitInfo aux; +// // const double bestGain = MSEGain::Evaluate(trainLabels, 0, weights); +// // const double gain = BestBinaryNumericSplit::SplitIfBetter( +// // bestGain, trainData.row(7), trainLabels, 0, weights, minLeafSize, minGainSplit, +// // splitInfo, aux); +// // std::cout << "splitInfo: " << splitInfo << std::endl; +// // std::cout << "gain: " << gain << std::endl; + +// std::cout << "Train RMSE: " << RMSE(trainLabels, trainPred) << std::endl; +// } + +TEST_CASE("DecisionTreeRegressorEnergyTest", "[DecisionTreeRegressorTest]") { - // Loading data. - data::DatasetInfo info; - arma::mat trainData, testData; - arma::Row trainLabels, testLabels; - LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); - std::cout << "Shape: "<< trainData.n_rows << " " << trainData.n_cols << std::endl; + arma::mat m; + if (!data::Load("energydata_complete.csv", m)) + FAIL("Cannot load dataset energydata_complete.csv!"); - // Initialize an all-ones weight matrix. - arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + arma::rowvec r = m.row(0); + m.shed_row(0); - // Build decision tree. - DecisionTreeRegressor d(trainData, info, trainLabels, 1, 1e-7, 0); - DecisionTreeRegressor wd(trainData, info, trainLabels, weights, 1, 1e-7, 0); + DecisionTreeRegressor<> d(m, r, 1, 0.0, 4); - // Get the predicted test labels. - arma::Row predictions; - d.Predict(testData, predictions); + arma::rowvec p; + d.Predict(m, p); + arma::rowvec weights = arma::ones(r.n_elem); - REQUIRE(predictions.n_elem == testData.n_cols); - - // Figure out rmse. - double rmse = RMSE(predictions, testLabels); - - REQUIRE(rmse < 9.21); - // std::cout << predictions << std::endl << testLabels; - arma::Row trainPred; - d.Predict(trainData, trainPred); - std::cout << trainPred; - - std::cout << "Train RMSE: " << RMSE(trainLabels, trainPred) << std::endl; - - // DecisionTreeRegressor<> dt = d; - - // Reset the prediction. - predictions.zeros(); - wd.Predict(testData, predictions); - - REQUIRE(predictions.n_elem == testData.n_cols); - - // Figure out the rmse. - double wdrmse = RMSE(predictions, testLabels); - - REQUIRE(wdrmse < 9.21); + const double mse = arma::accu(arma::square(p - r)) / p.n_elem; + REQUIRE(mse < 0.5); } /** @@ -640,19 +643,19 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") // std::cout << "****************End****************\n"; // } -TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") -{ - // drug dosage (in mg). - arma::mat dataset = {{2, 3, 5, 10, 14, 16, 20, 22, 28, 30, 32, 35, 39}}; - // percentage effectiveness. - arma::rowvec labels = {0, 0, 0, 5, 99, 99, 99, 95, 55, 45, 7, 0, 0}; +// TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") +// { +// // drug dosage (in mg). +// arma::mat dataset = {{2, 3, 5, 10, 14, 16, 20, 22, 28, 30, 32, 35, 39}}; +// // percentage effectiveness. +// arma::rowvec labels = {0, 0, 0, 5, 99, 99, 99, 95, 55, 45, 7, 0, 0}; - arma::rowvec weights(labels.n_elem); - weights.ones(); - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 5); - std::cout << "****************End****************\n"; -} +// arma::rowvec weights(labels.n_elem); +// weights.ones(); +// std::cout << "****************Start**************\n"; +// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 5); +// std::cout << "****************End****************\n"; +// } // /** // * Test that we can build a decision tree on a simple categorical dataset. From 8e4b891c82e6bc850c537eec1c1de6f2803371ef Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 12 Jun 2021 19:40:13 +0530 Subject: [PATCH 573/729] fixed failing test after merging master --- src/mlpack/tests/decision_tree_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index efd728fb72..987b77179d 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -459,12 +459,12 @@ TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") { // Call BestBinaryNumericSplit to do the splitting. (void) BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities[0], aux); // Call RandomBinaryNumericSplit to do the splitting. (void) RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1, + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1[0], aux1); if (classProbabilities[0] == classProbabilities1[0]) From 271e90130ecdf9f6f07d56c7b4f34f6e7bb45cd4 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 12 Jun 2021 19:41:12 +0530 Subject: [PATCH 574/729] Weighted gain computation in BestBinaryNumericSplit --- .../best_binary_numeric_split_impl.hpp | 42 ++++++++++++++++++- src/mlpack/methods/decision_tree/mse_gain.hpp | 2 + .../tests/decision_tree_regressor_test.cpp | 4 +- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 45f4551600..06abf935d6 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -227,9 +227,34 @@ double BestBinaryNumericSplit::SplitIfBetter( // Force a minimum leaf size of 1 (empty children don't make sense). const size_t minimum = std::max(minimumLeafSize, (size_t) 1); + double totalWeight = 0.0; + double totalLeftWeight = 0.0; + double totalRightWeight = 0.0; + + if (UseWeights) + { + totalWeight = arma::accu(sortedWeights); + bestFoundGain *= totalWeight; + + for (size_t i = 0; i < minimum - 1; ++i) + totalLeftWeight += sortedWeights[i]; + + for (size_t i = minimum - 1; i < data.n_elem; ++i) + totalRightWeight += sortedWeights[i]; + } + else + { + bestFoundGain *= data.n_elem; + } + // Loop through all possible split points, choosing the best one. for (size_t index = minimum; index < data.n_elem - minimum + 1; ++index) { + if (UseWeights) + { + totalLeftWeight += sortedWeights[index - 1]; + totalRightWeight -= sortedWeights[index - 1]; + } // Make sure that the value has changed. if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) continue; @@ -245,7 +270,17 @@ double BestBinaryNumericSplit::SplitIfBetter( const double rightGain = FitnessFunction::template Evaluate(sortedLabels, sortedWeights, index, labels.n_elem); - double gain = leftGain + rightGain; + double gain; + if (UseWeights) + { + gain = totalLeftWeight * leftGain + totalRightWeight * rightGain; + } + else + { + // Calculate the gain at this split point. + gain = double(index) * leftGain + + double(sortedLabels.n_elem - index) * rightGain; + } // Corner case: is this the best possible split? if (gain >= 0.0) @@ -273,6 +308,11 @@ double BestBinaryNumericSplit::SplitIfBetter( if (!improved) return DBL_MAX; + if (UseWeights) + bestFoundGain /= totalWeight; + else + bestFoundGain /= data.n_elem; + return bestFoundGain; } diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 340aee99a9..e12ae34ae4 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -73,6 +73,8 @@ class MSEGain for (size_t i = begin; i < end; ++i) mse += std::pow(labels[i] - mean, 2); + + mse /= (double) (end - begin); } return -mse; diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index ad95a3b891..496c6ab2a3 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -471,14 +471,14 @@ TEST_CASE("DecisionTreeRegressorEnergyTest", "[DecisionTreeRegressorTest]") arma::rowvec r = m.row(0); m.shed_row(0); - DecisionTreeRegressor<> d(m, r, 1, 0.0, 4); + DecisionTreeRegressor<> d(m, r, 1, 0.0, 0); arma::rowvec p; d.Predict(m, p); arma::rowvec weights = arma::ones(r.n_elem); const double mse = arma::accu(arma::square(p - r)) / p.n_elem; - REQUIRE(mse < 0.5); + REQUIRE(mse == Approx(0.0).epsilon(1e-4)); } /** From c174f68d0fdc8112c9cdfa68217a550a86a5ff8d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 13 Jun 2021 14:41:10 +0530 Subject: [PATCH 575/729] Reorganised tests and added tests to ensure gain correctness by hand calculating the values --- .../decision_tree_regressor_impl.hpp | 6 +- .../tests/decision_tree_regressor_test.cpp | 723 +++++++++--------- src/mlpack/tests/test_function_tools.hpp | 15 + 3 files changed, 398 insertions(+), 346 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 689aa7453f..1a76a2d363 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -840,7 +840,7 @@ double DecisionTreeRegressor(labels, 0, weights) == + Approx(gain).margin(1e-5)); + REQUIRE(MSEGain::Evaluate(labels, 0, weights) == + Approx(weightedGain).margin(1e-5)); +} + /** * Make sure the MAD gain is zero when the labels are perfect. */ @@ -100,11 +118,29 @@ TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressorTest]") Approx(0.0).margin(1e-5)); } +/** + * Making sure that MAD gain is evaluated correctly by doing calculation by + * hand. + */ +TEST_CASE("MADGainHandCalculation", "[DecisionTreeRegressorTest]") +{ + arma::rowvec labels = {4., 2., 3., 4., 13., 6., 20., 8., 9., 10.}; + arma::rowvec weights = {0.3, 0.3, 0.3, 0.3, 0.3, 0.7, 0.7, 0.7, 0.7, 0.7}; + + // Hand calculated gain values. + const double gain = -4.1; + const double weightedGain = -3.8592; + REQUIRE(MADGain::Evaluate(labels, 0, weights) == + Approx(gain).margin(1e-5)); + REQUIRE(MADGain::Evaluate(labels, 0, weights) == + Approx(weightedGain).margin(1e-5)); +} + /** * Check that AllCategoricalSplit will split when the split is obviously * better. */ -TEST_CASE("AllCategoricalSplitSimpleSplitTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("AllCategoricalSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") { arma::vec predictor(100); arma::rowvec labels(100); @@ -143,7 +179,7 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest1", "[DecisionTreeRegressorTest]") * Make sure that AllCategoricalSplit respects the minimum number of samples * required to split. */ -TEST_CASE("AllCategoricalSplitMinSamplesTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("AllCategoricalSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3}; arma::rowvec labels = {0, 0, 0, 2, 2, 2, 1, 1, 1, 2, 2, 2}; @@ -165,7 +201,7 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest1", "[DecisionTreeRegressorTest]") /** * Check that no split is made when it doesn't get us anything. */ -TEST_CASE("AllCategoricalSplitNoGainTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("AllCategoricalSplitNoGainTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors(300); arma::rowvec labels(300); @@ -202,7 +238,7 @@ TEST_CASE("AllCategoricalSplitNoGainTest1", "[DecisionTreeRegressorTest]") * Check that the BestBinaryNumericSplit will split on an obviously splittable * dimension. */ -TEST_CASE("BestBinaryNumericSplitSimpleSplitTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; arma::rowvec labels = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; @@ -237,7 +273,7 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest1", "[DecisionTreeRegressorTest] * Check that the BestBinaryNumericSplit won't split if not enough points are * given. */ -TEST_CASE("BestBinaryNumericSplitMinSamplesTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; arma::rowvec labels = { 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; @@ -264,7 +300,7 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest1", "[DecisionTreeRegressorTest]" * Check that the BestBinaryNumericSplit doesn't split a dimension that gives no * gain. */ -TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors(100); arma::rowvec labels(100); @@ -294,369 +330,122 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest1", "[DecisionTreeRegressorTest]") * A basic construction of the decision tree---ensure that we can create the * tree and that it split at least once. */ -// TEST_CASE("BasicConstructionTest_", "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset(10, 100, arma::fill::randu); -// arma::Row labels(100); -// for (size_t i = 0; i < 50; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 0.0; -// } -// for (size_t i = 50; i < 100; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 1.0; -// } +TEST_CASE("BasicConstructionTest_", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } -// // Use default parameters. -// DecisionTreeRegressor<> d(dataset, labels); + // Use default parameters. + DecisionTreeRegressor<> d(dataset, labels); -// // Now require that we have some children. -// REQUIRE(d.NumChildren() > 0); -// } + // Now require that we have some children. + REQUIRE(d.NumChildren() > 0); +} /** * Construct a tree with weighted labels. */ -// TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset(10, 100, arma::fill::randu); -// arma::Row labels(100); -// for (size_t i = 0; i < 50; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 0.0; -// } -// for (size_t i = 50; i < 100; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 1.0; -// } -// arma::rowvec weights(labels.n_elem); -// weights.ones(); +TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } + arma::rowvec weights(labels.n_elem); + weights.ones(); -// // Use default parameters. -// DecisionTreeRegressor<> wd(dataset, labels, weights); -// DecisionTreeRegressor<> d(dataset, labels); + // Use default parameters. + DecisionTreeRegressor<> wd(dataset, labels, weights); + DecisionTreeRegressor<> d(dataset, labels); -// // Now require that we have some children. -// REQUIRE(wd.NumChildren() > 0); -// REQUIRE(wd.NumChildren() == d.NumChildren()); -// } + // Now require that we have some children. + REQUIRE(wd.NumChildren() > 0); + REQUIRE(wd.NumChildren() == d.NumChildren()); +} /** * Construct the decision tree on numeric data only and see that we can fit it * exactly and achieve perfect performance on the training set. */ -// TEST_CASE("PerfectTrainingSet_", "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset(10, 100, arma::fill::randu); -// arma::Row labels(100); -// for (size_t i = 0; i < 50; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 0.0; -// } -// for (size_t i = 50; i < 100; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 1.0; -// } +TEST_CASE("PerfectTrainingSet_", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } -// DecisionTreeRegressor<> d(dataset, labels, 1, 0.0); // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, labels, 1, 0.0); // Minimum leaf size of 1. -// // Make sure that we can get perfect accuracy on the training set. -// for (size_t i = 0; i < 100; ++i) -// { -// double prediction; -// prediction = d.Predict(dataset.col(i)); + // Make sure that we can get perfect accuracy on the training set. + for (size_t i = 0; i < 100; ++i) + { + double prediction; + prediction = d.Predict(dataset.col(i)); -// REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); -// } -// } + REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + } +} /** * Construct the decision tree with weighted labels */ -// TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") -// { -// // Completely random dataset with no structure. -// arma::mat dataset(10, 100, arma::fill::randu); -// arma::Row labels(100); -// for (size_t i = 0; i < 50; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 0.0; -// } -// for (size_t i = 50; i < 100; ++i) -// { -// dataset(3, i) = i; -// labels[i] = 1.0; -// } - // arma::rowvec weights(labels.n_elem); - // weights.ones(); - - // // Minimum leaf size of 1. - // DecisionTreeRegressor<> d(dataset, labels, weights, 1, 0.0); - - // // This part of code is dupliacte with no weighted one. - // for (size_t i = 0; i < 100; ++i) - // { - // size_t prediction; - // prediction = d.Predict(dataset.col(i)); - - // REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); - // } -// } - -/** - * Test that the decision tree generalizes reasonably. - */ -// TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") -// { -// const size_t minLeafSize = 1; -// const double minGainSplit = 1e-7; -// const size_t depth = 2; - -// // Loading data. -// data::DatasetInfo info; -// arma::mat trainData, testData; -// arma::Row trainLabels, testLabels; -// arma::rowvec weights = arma::ones(355); -// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); -// std::cout << "Shape: "<< trainData.n_rows << " " << trainData.n_cols << std::endl; -// // for(size_t i = 0; i < info.Dimensionality(); i++) -// // { -// // std::cout << info.Type(i) << " "; -// // } -// // std::cout << std::endl; - -// // Build decision tree. -// DecisionTreeRegressor d(trainData, info, trainLabels, minLeafSize, minGainSplit, depth); - -// // Get the predicted test labels. -// arma::Row predictions; -// d.Predict(testData, predictions); - -// REQUIRE(predictions.n_elem == testData.n_cols); - -// // Figure out rmse. -// double rmse = RMSE(predictions, testLabels); - -// // REQUIRE(rmse < 9.21); -// // std::cout << predictions << std::endl << testLabels; -// arma::Row trainPred; -// d.Predict(trainData, trainPred); -// // std::cout << trainPred; - -// // double splitInfo; -// // BestBinaryNumericSplit::AuxiliarySplitInfo aux; -// // const double bestGain = MSEGain::Evaluate(trainLabels, 0, weights); -// // const double gain = BestBinaryNumericSplit::SplitIfBetter( -// // bestGain, trainData.row(7), trainLabels, 0, weights, minLeafSize, minGainSplit, -// // splitInfo, aux); -// // std::cout << "splitInfo: " << splitInfo << std::endl; -// // std::cout << "gain: " << gain << std::endl; - -// std::cout << "Train RMSE: " << RMSE(trainLabels, trainPred) << std::endl; -// } - -TEST_CASE("DecisionTreeRegressorEnergyTest", "[DecisionTreeRegressorTest]") +TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") { - arma::mat m; - if (!data::Load("energydata_complete.csv", m)) - FAIL("Cannot load dataset energydata_complete.csv!"); + // Completely random dataset with no structure. + arma::mat dataset(10, 100, arma::fill::randu); + arma::Row labels(100); + for (size_t i = 0; i < 50; ++i) + { + dataset(3, i) = i; + labels[i] = 0.0; + } + for (size_t i = 50; i < 100; ++i) + { + dataset(3, i) = i; + labels[i] = 1.0; + } + arma::rowvec weights(labels.n_elem); + weights.ones(); - arma::rowvec r = m.row(0); - m.shed_row(0); + // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, labels, weights, 1, 0.0); - DecisionTreeRegressor<> d(m, r, 1, 0.0, 0); + // This part of code is dupliacte with no weighted one. + for (size_t i = 0; i < 100; ++i) + { + size_t prediction; + prediction = d.Predict(dataset.col(i)); - arma::rowvec p; - d.Predict(m, p); - arma::rowvec weights = arma::ones(r.n_elem); - - const double mse = arma::accu(arma::square(p - r)) / p.n_elem; - REQUIRE(mse == Approx(0.0).epsilon(1e-4)); + REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + } } -/** - * Test that the decision tree generalizes reasonably when built on float data. - */ -// TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") -// { -// // Loading data. -// data::DatasetInfo info; -// arma::mat trainData, testData; -// arma::Row trainLabels, testLabels; -// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); - -// // Initialize an all-ones weight matrix. -// arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); - -// // Build decision tree. -// DecisionTreeRegressor<> d(trainData, trainLabels); -// DecisionTreeRegressor<> wd(trainData, trainLabels, weights); - -// // Get the predicted test labels. -// arma::Row predictions; -// d.Predict(testData, predictions); - -// REQUIRE(predictions.n_elem == testData.n_cols); - -// // Figure out the rmse. -// double rmse = RMSE(predictions, testLabels); - -// REQUIRE(rmse < 9.21); -// std::cout << R2Score(predictions, testLabels) << std::endl; - -// // Reset the prediction. -// predictions.zeros(); -// wd.Predict(testData, predictions); - -// REQUIRE(predictions.n_elem == testData.n_cols); - -// // Figure out the rmse. -// double wdrmse = RMSE(predictions, testLabels); - -// REQUIRE(wdrmse < 9.21); -// } - -// TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset(10, 500, arma::fill::randu); -// arma::Row labels(500); - -// for (size_t i = 0; i < 100; i++) -// { -// dataset(3, i) = i; -// labels(i) = 0.0; -// } -// for (size_t i = 100; i < 200; i++) -// { -// dataset(3, i) = i; -// labels(i) = 1.0; -// } -// for (size_t i = 200; i < 300; i++) -// { -// dataset(3, i) = i; -// labels(i) = 2.0; -// } -// for (size_t i = 300; i < 400; i++) -// { -// dataset(3, i) = i; -// labels(i) = 1.0; -// } -// for (size_t i = 400; i < 500; i++) -// { -// dataset(3, i) = i; -// labels(i) = 0.0; -// } - -// arma::rowvec weights(labels.n_elem); -// weights.ones(); - -// // Minimum leaf size of 1. -// std::cout << "****************Start**************\n"; -// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); -// std::cout << "****************End****************\n"; -// } - -// TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset(10, 250, arma::fill::randu); -// arma::Row labels(500); - -// for (size_t i = 0; i < 50; i++) -// { -// dataset(3, i) = i; -// labels(i) = 0.0; -// } -// for (size_t i = 50; i < 100; i++) -// { -// dataset(3, i) = i; -// labels(i) = 1.0; -// } -// for (size_t i = 100; i < 150; i++) -// { -// dataset(3, i) = i; -// labels(i) = 2.0; -// } -// for (size_t i = 150; i < 200; i++) -// { -// dataset(3, i) = i; -// labels(i) = 1.0; -// } -// for (size_t i = 200; i < 250; i++) -// { -// dataset(3, i) = i; -// labels(i) = 0.0; -// } - -// arma::rowvec weights(labels.n_elem); -// weights.ones(); - -// // Minimum leaf size of 1. -// std::cout << "****************Start**************\n"; -// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); -// std::cout << "****************End****************\n"; -// } - -// TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset(10, 500, arma::fill::randu); -// arma::Row labels(500); - -// for (size_t i = 0; i < 100; i++) -// { -// dataset(3, i) = i; -// labels(i) = 0.0; -// } -// for (size_t i = 100; i < 200; i++) -// { -// dataset(3, i) = i; -// labels(i) = 5.0; -// } -// for (size_t i = 200; i < 300; i++) -// { -// dataset(3, i) = i; -// labels(i) = 10.0; -// } -// for (size_t i = 300; i < 400; i++) -// { -// dataset(3, i) = i; -// labels(i) = 15.0; -// } -// for (size_t i = 400; i < 500; i++) -// { -// dataset(3, i) = i; -// labels(i) = 20.0; -// } - -// arma::rowvec weights(labels.n_elem); -// weights.ones(); - -// // Minimum leaf size of 1. -// std::cout << "****************Start**************\n"; -// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); -// std::cout << "****************End****************\n"; -// } - -// TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") -// { -// // drug dosage (in mg). -// arma::mat dataset = {{2, 3, 5, 10, 14, 16, 20, 22, 28, 30, 32, 35, 39}}; -// // percentage effectiveness. -// arma::rowvec labels = {0, 0, 0, 5, 99, 99, 99, 95, 55, 45, 7, 0, 0}; - -// arma::rowvec weights(labels.n_elem); -// weights.ones(); -// std::cout << "****************Start**************\n"; -// DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 5); -// std::cout << "****************End****************\n"; -// } - // /** // * Test that we can build a decision tree on a simple categorical dataset. // */ @@ -941,3 +730,251 @@ TEST_CASE("DecisionTreeRegressorEnergyTest", "[DecisionTreeRegressorTest]") // const double correctPct = double(correct) / double(testData.n_cols); // REQUIRE(correctPct > 0.70); // } + +/** + * Test that the decision tree generalizes reasonably. + */ +TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") +{ + + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::Row trainLabels, testLabels; + arma::rowvec weights = arma::ones(355); + LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + + // Build decision tree. + DecisionTreeRegressor d(trainData, info, trainLabels); + + // Get the predicted test labels. + arma::Row predictions; + d.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out rmse. + double rmse = RMSE(predictions, testLabels); + + // REQUIRE(rmse < 9.21); + // std::cout << predictions << std::endl << testLabels; + arma::Row trainPred; + d.Predict(trainData, trainPred); + // std::cout << trainPred; + + std::cout << "Train RMSE: " << RMSE(trainLabels, trainPred) << std::endl; +} + +/** + * Test that the decision tree generalizes reasonably when built on float data. + */ +// TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") +// { +// // Loading data. +// data::DatasetInfo info; +// arma::mat trainData, testData; +// arma::Row trainLabels, testLabels; +// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + +// // Initialize an all-ones weight matrix. +// arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + +// // Build decision tree. +// DecisionTreeRegressor<> d(trainData, trainLabels); +// DecisionTreeRegressor<> wd(trainData, trainLabels, weights); + +// // Get the predicted test labels. +// arma::Row predictions; +// d.Predict(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); + +// // Figure out the rmse. +// double rmse = RMSE(predictions, testLabels); + +// REQUIRE(rmse < 9.21); +// std::cout << R2Score(predictions, testLabels) << std::endl; + +// // Reset the prediction. +// predictions.zeros(); +// wd.Predict(testData, predictions); + +// REQUIRE(predictions.n_elem == testData.n_cols); + +// // Figure out the rmse. +// double wdrmse = RMSE(predictions, testLabels); + +// REQUIRE(wdrmse < 9.21); +// } + +// TEST_CASE("DecisionTreeRegressorEnergyTest", "[DecisionTreeRegressorTest]") +// { +// arma::mat m; +// if (!data::Load("energydata_complete.csv", m)) +// FAIL("Cannot load dataset energydata_complete.csv!"); + +// arma::rowvec r = m.row(0); +// m.shed_row(0); + +// DecisionTreeRegressor<> d(m, r, 1, 0.0, 0); + +// arma::rowvec p; +// d.Predict(m, p); + +// const double mse = arma::accu(arma::square(p - r)) / p.n_elem; +// REQUIRE(mse == Approx(0.0).epsilon(1e-4)); +// } + +TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 500, arma::fill::randu); + arma::Row labels(500); + + for (size_t i = 0; i < 100; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + for (size_t i = 100; i < 200; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 200; i < 300; i++) + { + dataset(3, i) = i; + labels(i) = 2.0; + } + for (size_t i = 300; i < 400; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 400; i < 500; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + + arma::rowvec weights(labels.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + arma::rowvec preds; + d.Predict(dataset, preds); + + const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; + REQUIRE(mse == Approx(0.0).epsilon(1e-4)); + std::cout << "****************End****************\n"; +} + +TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 250, arma::fill::randu); + arma::Row labels(500); + + for (size_t i = 0; i < 50; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + for (size_t i = 50; i < 100; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 100; i < 150; i++) + { + dataset(3, i) = i; + labels(i) = 2.0; + } + for (size_t i = 150; i < 200; i++) + { + dataset(3, i) = i; + labels(i) = 1.0; + } + for (size_t i = 200; i < 250; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + + arma::rowvec weights(labels.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + arma::rowvec preds; + d.Predict(dataset, preds); + + const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; + REQUIRE(mse == Approx(0.0).epsilon(1e-4)); + std::cout << "****************End****************\n"; +} + +TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset(10, 500, arma::fill::randu); + arma::Row labels(500); + + for (size_t i = 0; i < 100; i++) + { + dataset(3, i) = i; + labels(i) = 0.0; + } + for (size_t i = 100; i < 200; i++) + { + dataset(3, i) = i; + labels(i) = 5.0; + } + for (size_t i = 200; i < 300; i++) + { + dataset(3, i) = i; + labels(i) = 10.0; + } + for (size_t i = 300; i < 400; i++) + { + dataset(3, i) = i; + labels(i) = 15.0; + } + for (size_t i = 400; i < 500; i++) + { + dataset(3, i) = i; + labels(i) = 20.0; + } + + arma::rowvec weights(labels.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + arma::rowvec preds; + d.Predict(dataset, preds); + + const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; + REQUIRE(mse == Approx(0.0).epsilon(1e-4)); + std::cout << "****************End****************\n"; +} + +TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") +{ + // drug dosage (in mg). + arma::mat dataset = {{2, 3, 5, 10, 14, 16, 20, 22, 28, 30, 32, 35, 39}}; + // percentage effectiveness. + arma::rowvec labels = {0, 0, 0, 5, 99, 99, 99, 95, 55, 45, 7, 0, 0}; + + arma::rowvec weights(labels.n_elem); + weights.ones(); + std::cout << "****************Start**************\n"; + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 5); + arma::rowvec preds; + d.Predict(dataset, preds); + + const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; + REQUIRE(mse == Approx(0.0).epsilon(1e-4)); + std::cout << "****************End****************\n"; +} diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index eb891361e9..693c3ec469 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -97,6 +97,21 @@ inline void LoadBostonHousingDataset(arma::mat& trainData, data::Split(dataset, labels, trainData, testData, trainLabels, testLabels, 0.3); + // info.Type(3) = data::Datatype::categorical; + // info.Type(8) = data::Datatype::categorical; + + // info.MapString("0", 3); + // info.MapString("1", 3); + // info.MapString("1", 8); + // info.MapString("2", 8); + // info.MapString("3", 8); + // info.MapString("4", 8); + // info.MapString("5", 8); + // info.MapString("6", 8); + // info.MapString("7", 8); + // info.MapString("8", 8); + // info.MapString("24", 8); + // std::cout << arma::unique(trainData.row(8)); } inline double RMSE(const arma::Row& predictions, From 57572aa876091968ce481e976e772f9830dee6a1 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 14 Jun 2021 08:27:54 +0530 Subject: [PATCH 576/729] Removed numLeaves from BestBinaryNumericSplit --- .../decision_tree/best_binary_numeric_split.hpp | 2 -- .../decision_tree/best_binary_numeric_split_impl.hpp | 1 - .../decision_tree/decision_tree_regressor_impl.hpp | 2 -- src/mlpack/tests/decision_tree_regressor_test.cpp | 11 +++++------ 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 5211f69f8d..207aac1f2a 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -75,7 +75,6 @@ class BestBinaryNumericSplit * better than this). * @param data The dimension of data points to check for a split in. * @param labels Labels for each point. - * @param numClasses Number of classes in the dataset. * @param weights Weights associated with labels. * @param minimumLeafSize Minimum number of points in a leaf node for * splitting. @@ -89,7 +88,6 @@ class BestBinaryNumericSplit const double bestGain, const VecType& data, const arma::Row& labels, - const size_t numClasses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 06abf935d6..fb9e23fb5d 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -188,7 +188,6 @@ double BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, const arma::Row& labels, - const size_t numClasses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 1a76a2d363..320470df08 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -657,7 +657,6 @@ double DecisionTreeRegressor(bestGain, data.cols(begin, begin + count - 1).row(i), labels.subvec(begin, begin + count - 1), - numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, minimumGainSplit, @@ -829,7 +828,6 @@ double DecisionTreeRegressor(bestGain, data.cols(begin, begin + count - 1).row(i), labels.cols(begin, begin + count - 1), - numClasses, UseWeights ? weights.cols(begin, begin + count - 1) : weights, diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 0175d744e9..bbf6a458c4 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -251,11 +251,10 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", "[DecisionTreeRegressorTest] // Call the method to do the splitting. const double bestGain = MADGain::Evaluate(labels, 0, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, labels, 0, weights, 3, 1e-7, splitInfo, - aux); + bestGain, predictors, labels, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, - labels, 0, weights, 3, 1e-7, splitInfo, aux); + labels, weights, 3, 1e-7, splitInfo, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -285,11 +284,11 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", "[DecisionTreeRegressorTest]" // Call the method to do the splitting. const double bestGain = MSEGain::Evaluate(labels, 0, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, labels, 0, weights, 8, 1e-7, splitInfo, aux); + bestGain, predictors, labels, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, - labels, 0, weights, 8, 1e-7, splitInfo, aux); + labels, weights, 8, 1e-7, splitInfo, aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); @@ -319,7 +318,7 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") // Call the method to do the splitting. const double bestGain = MSEGain::Evaluate(labels, 0, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, labels, 0, weights, 10, 1e-7, splitInfo, + bestGain, predictors, labels, weights, 10, 1e-7, splitInfo, aux); // Make sure there was no split. From fdb90df2d36886cbb467b50aa9ebe8c267e7f8d6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 14 Jun 2021 08:52:15 +0530 Subject: [PATCH 577/729] Reverted splitInfo to arma::vec for old decision tree for numric splits --- .../best_binary_numeric_split.hpp | 2 +- .../best_binary_numeric_split_impl.hpp | 8 ++-- .../decision_tree/decision_tree_impl.hpp | 4 +- .../random_binary_numeric_split.hpp | 2 +- .../random_binary_numeric_split_impl.hpp | 5 ++- src/mlpack/tests/decision_tree_test.cpp | 38 ++++++++++--------- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 207aac1f2a..d2e052f4dd 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -60,7 +60,7 @@ class BestBinaryNumericSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - double& splitInfo, + arma::vec& splitInfo, AuxiliarySplitInfo& aux); /** diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index fb9e23fb5d..ff84a5496f 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -25,7 +25,7 @@ double BestBinaryNumericSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - double& splitInfo, + arma::vec& splitInfo, AuxiliarySplitInfo& /* aux */) { // First sanity check: if we don't have enough points, we can't split. @@ -154,7 +154,8 @@ double BestBinaryNumericSplit::SplitIfBetter( // We can take a shortcut: no split will be better than this, so just // take this one. The actual split value will be halfway between the // value at index - 1 and index. - splitInfo = (data[sortedIndices[index - 1]] + + splitInfo.set_size(1); + splitInfo[0] = (data[sortedIndices[index - 1]] + data[sortedIndices[index]]) / 2.0; return gain; @@ -163,7 +164,8 @@ double BestBinaryNumericSplit::SplitIfBetter( { // We still have a better split. bestFoundGain = gain; - splitInfo = (data[sortedIndices[index - 1]] + + splitInfo.set_size(1); + splitInfo[0] = (data[sortedIndices[index - 1]] + data[sortedIndices[index]]) / 2.0; improved = true; } diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index 0c5d106002..e085fee9a4 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -663,7 +663,7 @@ double DecisionTree::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - double& splitInfo, + arma::vec& splitInfo, AuxiliarySplitInfo& /* aux */, const bool splitIfBetterGain) { @@ -125,7 +125,8 @@ double RandomBinaryNumericSplit::SplitIfBetter( if (gain < bestFoundGain && splitIfBetterGain) return DBL_MAX; - splitInfo = randomPivot; + splitInfo.set_size(1); + splitInfo[0] = randomPivot; if (UseWeights) gain /= totalWeight; diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 987b77179d..54213e417f 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -288,17 +288,16 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); weights.ones(); - arma::vec classProbabilities(1); + arma::vec classProbabilities; BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities[0], - aux); + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities, aux); const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 3, 1e-7, classProbabilities[0], aux); + labels, 2, weights, 3, 1e-7, classProbabilities, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -326,22 +325,23 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); arma::rowvec weights(labels.n_elem); - arma::vec classProbabilities(1); + arma::vec classProbabilities; BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities[0], + bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities, aux); // This should make no difference because it won't split at all. const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); + labels, 2, weights, 8, 1e-7, classProbabilities, aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); + // REQUIRE(classProbabilities.n_elem == 0); **TODO** } /** @@ -361,17 +361,18 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities(1); + arma::vec classProbabilities; BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities[0], + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, aux); // Make sure there was no split. REQUIRE(gain == DBL_MAX); + // REQUIRE(classProbabilities.n_elem == 0); **TODO** } /** @@ -384,22 +385,22 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); arma::rowvec weights(labels.n_elem); - arma::vec classProbabilities(1); + arma::vec classProbabilities; RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities[0], - aux); + bestGain, values, labels, 2, weights, 8, 1e-7, classProbabilities, aux); // This should make no difference because it won't split at all. const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); + labels, 2, weights, 8, 1e-7, classProbabilities, aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); + // REQUIRE(classProbabilities.n_elem == 0); **TODO** } /** @@ -419,17 +420,18 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities(1); + arma::vec classProbabilities; RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities[0], + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, aux, true); // Make sure there was no split. REQUIRE(gain == DBL_MAX); + // REQUIRE(classProbabilities.n_elem == 0); **TODO** } /** @@ -449,7 +451,7 @@ TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities(1), classProbabilities1(1); + arma::vec classProbabilities, classProbabilities1; BestBinaryNumericSplit::AuxiliarySplitInfo aux; RandomBinaryNumericSplit::AuxiliarySplitInfo aux1; @@ -459,12 +461,12 @@ TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") { // Call BestBinaryNumericSplit to do the splitting. (void) BestBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities[0], + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities, aux); // Call RandomBinaryNumericSplit to do the splitting. (void) RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1[0], + bestGain, values, labels, 2, weights, 3, 1e-7, classProbabilities1, aux1); if (classProbabilities[0] == classProbabilities1[0]) From 6e34bc02c6cfbb44981ab70bb1d0150bdf823c99 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 14 Jun 2021 17:40:53 +0530 Subject: [PATCH 578/729] Add random numeric splitting strategy for regression tree --- .../decision_tree/decision_tree_regressor.hpp | 1 + .../random_binary_numeric_split.hpp | 38 ++++++ .../random_binary_numeric_split_impl.hpp | 119 ++++++++++++++++++ .../tests/decision_tree_regressor_test.cpp | 85 +++++++++++++ 4 files changed, 243 insertions(+) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index fcdc1f17c8..2e8d117f83 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -18,6 +18,7 @@ #include "mse_gain.hpp" #include "best_binary_numeric_split.hpp" #include "all_categorical_split.hpp" +#include "random_binary_numeric_split.hpp" #include "all_dimension_select.hpp" #include diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 8380f79fca..98d1f13787 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -37,6 +37,8 @@ class RandomBinaryNumericSplit * return the value 'bestGain'. If a split is made, then splitInfo * and aux may be modified. * + * It is used only for classification tasks. + * * @code * @article{10.1007/s10994-006-6226-1, * author = {Geurts, Pierre and Ernst, Damien and Wehenkel, Louis}, @@ -86,6 +88,42 @@ class RandomBinaryNumericSplit AuxiliarySplitInfo& aux, const bool splitIfBetterGain = false); + /** + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then splitInfo + * and aux may be modified. + * + * It is used only for regression tasks. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param labels Labels for each point. + * @param numClasses Number of classes in the dataset. + * @param weights Weights associated with labels. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param minimumGainSplit Minimum gain split. + * @param splitInfo Stores split information on a successful split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + * @param splitIfBetterGain When set to true, it will split only when gain is + * better than the current best gain. Otherwise, it always makes a + * split regardless of gain. + */ + template + static double SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& aux, + const bool splitIfBetterGain = false); + /** * Returns 2, since the binary split always has two children. * diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 9bb18e158c..2bd09bc53b 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -136,6 +136,125 @@ double RandomBinaryNumericSplit::SplitIfBetter( return gain; } +template +template +double RandomBinaryNumericSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::Row& labels, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& /* aux */, + const bool splitIfBetterGain) +{ + double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); + // Forcing a minimum leaf size of 1 (empty children don't make sense). + const size_t minimum = std::max(minimumLeafSize, (size_t) 1); + + // First sanity check: if we don't have enough points, we can't split. + if (data.n_elem < (minimum * 2)) + return DBL_MAX; + if (bestGain == 0.0) + return DBL_MAX; // It can't be outperformed. + + typename VecType::elem_type maxValue = arma::max(data); + typename VecType::elem_type minValue = arma::min(data); + + // Sanity check: if the maximum element is the same as the minimum, we + // can't split in this dimension. + if (maxValue == minValue) + return DBL_MAX; + + double totalWeight = 0.0; + double totalLeftWeight = 0.0; + double totalRightWeight = 0.0; + if (UseWeights) + { + totalWeight = arma::accu(weights); + bestFoundGain *= totalWeight; + } + else + { + bestFoundGain *= data.n_elem; + } + + // Picking a random pivot to split the dimension. + double randomPivot = math::Random(minValue, maxValue); + + // We need to count the number of points for each leaf. + size_t leftLeafSize = 0; + size_t rightLeafSize = 0; + for (size_t i = 0; i < data.n_elem; ++i) + { + if (UseWeights) + { + if (data[i] < randomPivot) + totalLeftWeight += weights[i]; + else + totalRightWeight += weights[i]; + } + + if (data[i] < randomPivot) + ++leftLeafSize; + else + ++rightLeafSize; + } + + // Splitting data to compute gain. + arma::rowvec leftLabels(leftLeafSize), rightLabels(rightLeafSize); + arma::rowvec leftWeights, rightWeights; + if (UseWeights) + { + leftWeights.set_size(leftLeafSize); + rightWeights.set_size(rightLeafSize); + } + + size_t l = 0, r = 0; + for(size_t i = 0; i < data.n_elem; ++i) + { + if (UseWeights) + { + if (data[i] < randomPivot) + leftWeights[l] = weights[i]; + else + rightWeights[r] = weights[i]; + } + if (data[i] < randomPivot) + leftLabels[l++] = labels[i]; + else + rightLabels[r++] = labels[i]; + } + + // Calculate the gain for the left and right child. + const double leftGain = + FitnessFunction::template Evaluate(leftLabels, leftWeights, + 0, leftLeafSize); + const double rightGain = + FitnessFunction::template Evaluate(rightLabels, rightWeights, + 0, rightLeafSize); + + // Calculate the gain at this split point. + double gain; + if (UseWeights) + gain = totalLeftWeight * leftGain + totalRightWeight * rightGain; + else + gain = double(leftLeafSize) * leftGain + double(rightLeafSize) * rightGain; + + if (gain < bestFoundGain && splitIfBetterGain) + return DBL_MAX; + + splitInfo = randomPivot; + + if (UseWeights) + gain /= totalWeight; + else + gain /= labels.n_elem; + + return gain; +} + template template size_t RandomBinaryNumericSplit::CalculateDirection( diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index bbf6a458c4..11add44067 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -325,6 +325,91 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") REQUIRE(gain == DBL_MAX); } +/** + * Check that the RandomBinaryNumericSplit always splits when splitIfBetterGain + * is false. + */ +TEST_CASE("RandomBinaryNumericSplitAlwaysSplit_", + "[DecisionTreeRegressorTest]") +{ + arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); + arma::rowvec labels("0 0 0 0 0 1 1 1 1 1 1"); + arma::rowvec weights; + weights.ones(labels.n_elem); + + double splitInfo; + RandomBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 2, weights); + const double gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, weights, 1, 1e-7, splitInfo, aux); + const double weightedGain = + RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, + labels, weights, 1, 1e-7, splitInfo, aux); + + // Make sure that split was made. + REQUIRE(gain != DBL_MAX); + REQUIRE(weightedGain != DBL_MAX); +} + +/** + * Check that the RandomBinaryNumericSplit won't split if not enough points are + * given. + */ +TEST_CASE("RandomBinaryNumericSplitMinSamplesTest_", + "[DecisionTreeRegressorTest]") +{ + arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); + arma::rowvec labels("0 0 0 0 0 1 1 1 1 1 1"); + arma::rowvec weights(labels.n_elem); + + double splitInfo; + RandomBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 2, weights); + const double gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, weights, 8, 1e-7, splitInfo, aux); + // This should make no difference because it won't split at all. + const double weightedGain = + RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, + labels, weights, 8, 1e-7, splitInfo, aux); + + // Make sure that no split was made. + REQUIRE(gain == DBL_MAX); + REQUIRE(gain == weightedGain); +} + +/** + * Check that the RandomBinaryNumericSplit doesn't split a dimension that gives + * no gain when splitIfBetterGain is true. + */ +TEST_CASE("RandomBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") +{ + arma::vec values(100); + arma::Row labels(100); + arma::rowvec weights; + for (size_t i = 0; i < 100; i += 2) + { + values[i] = i; + labels[i] = 0.0; + values[i + 1] = i; + labels[i + 1] = 1.0; + } + + double splitInfo; + RandomBinaryNumericSplit::AuxiliarySplitInfo aux; + + // Call the method to do the splitting. + const double bestGain = MSEGain::Evaluate(labels, 2, weights); + const double gain = RandomBinaryNumericSplit::SplitIfBetter( + bestGain, values, labels, weights, 10, 1e-7, splitInfo, aux, true); + + // Make sure there was no split. + REQUIRE(gain == DBL_MAX); +} + /** * A basic construction of the decision tree---ensure that we can create the * tree and that it split at least once. From 44c2b5ca51d7e1f64492f787717a7a9655dab65f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:27:51 +0530 Subject: [PATCH 579/729] Reverted AllCategoricalSplit to use arma::vec for splitInfo --- .../decision_tree/all_categorical_split.hpp | 5 ++-- .../all_categorical_split_impl.hpp | 26 ++++++++++++++++--- .../decision_tree/decision_tree_impl.hpp | 4 +-- src/mlpack/tests/decision_tree_test.cpp | 20 +++++++------- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index 2ac91b099a..ed265bba89 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -54,7 +54,8 @@ class AllCategoricalSplit * @param aux Auxiliary split information, which may be modified on a * successful split. */ - template + template static double SplitIfBetter( const double bestGain, const VecType& data, @@ -64,7 +65,7 @@ class AllCategoricalSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - double& splitInfo, + SplitInfoType& splitInfo, AuxiliarySplitInfo& aux); /** diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 754a092737..0fbeeeec25 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -15,8 +15,28 @@ namespace mlpack { namespace tree { +/** + * Helper function to store split information. This is used for regression. + * payload contains the information to be stored in splitInfo. + */ +static void StoreSplitInfo(double& splitInfo, const double& payload) +{ + splitInfo = payload; +} + +/** + * Helper function to store split information. This is used for classification. + * payload contains the information to be stored in splitInfo. + */ +static void StoreSplitInfo(arma::vec& splitInfo, const double& payload) +{ + splitInfo.set_size(1); + splitInfo[0] = payload; +} + template -template +template double AllCategoricalSplit::SplitIfBetter( const double bestGain, const VecType& data, @@ -26,7 +46,7 @@ double AllCategoricalSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - double& splitInfo, + SplitInfoType& splitInfo, AuxiliarySplitInfo& /* aux */) { // Count the number of elements in each potential child. @@ -100,7 +120,7 @@ double AllCategoricalSplit::SplitIfBetter( if (overallGain > bestGain + minimumGainSplit + epsilon) { // This is better, so store it in splitInfo and return. - splitInfo = numCategories; + StoreSplitInfo(splitInfo, numCategories); return overallGain; } diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index e085fee9a4..3053e74b35 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -636,7 +636,6 @@ double DecisionTree::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( bestGain, values, 4, labels, 3, weights, 4, 1e-7, - classProbabilities[0], aux); + classProbabilities, aux); // Make sure it's not split. REQUIRE(gain == DBL_MAX); + REQUIRE(classProbabilities.n_elem == 0); } /** @@ -555,21 +556,22 @@ TEST_CASE("AllCategoricalSplitNoGainTest", "[DecisionTreeTest]") labels[i + 2] = 2; } - arma::vec classProbabilities(1); + arma::vec classProbabilities; AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( bestGain, values, 10, labels, 3, weights, 10, 1e-7, - classProbabilities[0], aux); + classProbabilities, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, values, 10, - labels, 3, weights, 10, 1e-7, classProbabilities[0], aux); + labels, 3, weights, 10, 1e-7, classProbabilities, aux); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); + REQUIRE(classProbabilities.n_elem == 0); } /** From 8d8687a928bbd481bcd297b1382f49de5bc1cbdc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 15 Jun 2021 18:21:30 +0530 Subject: [PATCH 580/729] Add a mock categorical dataset and test DecisionTreeRegressor on it --- .../tests/decision_tree_regressor_test.cpp | 204 +++++++++--------- src/mlpack/tests/mock_categorical_data.hpp | 60 +++++- src/mlpack/tests/test_function_tools.hpp | 30 +-- 3 files changed, 159 insertions(+), 135 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 11add44067..9b5ef0e234 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "catch.hpp" #include "serialization.hpp" @@ -530,77 +531,69 @@ TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") } } -// /** -// * Test that we can build a decision tree on a simple categorical dataset. -// */ -// TEST_CASE("CategoricalBuildTest", "[DecisionTreeTest]") -// { -// arma::mat d; -// arma::Row l; -// data::DatasetInfo di; -// MockCategoricalData(d, l, di); +/** + * Test that we can build a decision tree on a simple categorical dataset. + */ +TEST_CASE("CategoricalBuildTest_", "[DecisionTreeRegressorTest]") +{ + arma::mat d; + arma::rowvec l; + data::DatasetInfo di; + MockCategoricalData(d, l, di); -// // Split into a training set and a test set. -// arma::mat trainingData = d.cols(0, 1999); -// arma::mat testData = d.cols(2000, 3999); -// arma::Row trainingLabels = l.subvec(0, 1999); -// arma::Row testLabels = l.subvec(2000, 3999); + // Split into a training set and a test set. + arma::mat trainingData = d.cols(0, 1999); + arma::mat testData = d.cols(2000, 3999); + arma::rowvec trainingLabels = l.subvec(0, 1999); + arma::rowvec testLabels = l.subvec(2000, 3999); -// // Build the tree. -// DecisionTree<> tree(trainingData, di, trainingLabels, 5, 10); + // Build the tree. + DecisionTreeRegressor<> tree(trainingData, di, trainingLabels, 10); -// // Now evaluate the accuracy of the tree. -// arma::Row predictions; -// tree.Classify(testData, predictions); + // Now evaluate the quality of predictions. + arma::rowvec predictions; + tree.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); -// size_t correct = 0; -// for (size_t i = 0; i < testData.n_cols; ++i) -// if (testLabels[i] == predictions[i]) -// ++correct; + REQUIRE(predictions.n_elem == testData.n_cols); -// // Make sure we got at least 70% accuracy. -// const double correctPct = double(correct) / double(testData.n_cols); -// REQUIRE(correctPct > 0.70); -// } + // Make sure we get reasonable rmse. + const double rmse = RMSE(predictions, testLabels); + REQUIRE(rmse < 1.0); +} -// /** -// * Test that we can build a decision tree with weights on a simple categorical -// * dataset. -// */ -// TEST_CASE("CategoricalBuildTestWithWeight", "[DecisionTreeTest]") -// { -// arma::mat d; -// arma::Row l; -// data::DatasetInfo di; -// MockCategoricalData(d, l, di); +/** + * Test that we can build a decision tree with weights on a simple categorical + * dataset. + */ +TEST_CASE("CategoricalBuildTestWithWeight_", "[DecisionTreeRegressorTest]") +{ + arma::mat d; + arma::rowvec l; + data::DatasetInfo di; + MockCategoricalData(d, l, di); -// // Split into a training set and a test set. -// arma::mat trainingData = d.cols(0, 1999); -// arma::mat testData = d.cols(2000, 3999); -// arma::Row trainingLabels = l.subvec(0, 1999); -// arma::Row testLabels = l.subvec(2000, 3999); + // Split into a training set and a test set. + arma::mat trainingData = d.cols(0, 1999); + arma::mat testData = d.cols(2000, 3999); + arma::rowvec trainingLabels = l.subvec(0, 1999); + arma::rowvec testLabels = l.subvec(2000, 3999); -// arma::Row weights = arma::ones>( -// trainingLabels.n_elem); + arma::rowvec weights = arma::ones( + trainingLabels.n_elem); -// // Build the tree. -// DecisionTree<> tree(trainingData, di, trainingLabels, 5, weights, 10); + // Build the tree. + DecisionTreeRegressor<> tree(trainingData, di, trainingLabels, weights, 10); -// // Now evaluate the accuracy of the tree. -// arma::Row predictions; -// tree.Classify(testData, predictions); + // Now evaluate the quality of predictions. + arma::rowvec predictions; + tree.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); -// size_t correct = 0; -// for (size_t i = 0; i < testData.n_cols; ++i) -// if (testLabels[i] == predictions[i]) -// ++correct; + REQUIRE(predictions.n_elem == testData.n_cols); -// // Make sure we got at least 70% accuracy. -// const double correctPct = double(correct) / double(testData.n_cols); -// REQUIRE(correctPct > 0.70); -// } + // Make sure we get reasonable rmse. + const double rmse = RMSE(predictions, testLabels); + REQUIRE(rmse < 1.0); +} /** * Test that we can build a decision tree using weighted data (where the @@ -647,62 +640,59 @@ TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") // REQUIRE(rmse < 9.21); // } -// /** -// * Test that we can build a decision tree on a simple categorical dataset using -// * weights, with low-weight noise added. -// */ -// TEST_CASE("CategoricalWeightedBuildTest", "[DecisionTreeTest]") -// { -// arma::mat d; -// arma::Row l; -// data::DatasetInfo di; -// MockCategoricalData(d, l, di); +/** + * Test that we can build a decision tree on a simple categorical dataset using + * weights, with low-weight noise added. + */ +TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") +{ + arma::mat d; + arma::rowvec l; + data::DatasetInfo di; + MockCategoricalData(d, l, di); -// // Split into a training set and a test set. -// arma::mat trainingData = d.cols(0, 1999); -// arma::mat testData = d.cols(2000, 3999); -// arma::Row trainingLabels = l.subvec(0, 1999); -// arma::Row testLabels = l.subvec(2000, 3999); + // Split into a training set and a test set. + arma::mat trainingData = d.cols(0, 1999); + arma::mat testData = d.cols(2000, 3999); + arma::rowvec trainingLabels = l.subvec(0, 1999); + arma::rowvec testLabels = l.subvec(2000, 3999); -// // Now create random points. -// arma::mat randomNoise(4, 2000); -// arma::Row randomLabels(2000); -// for (size_t i = 0; i < 2000; ++i) -// { -// randomNoise(0, i) = math::Random(); -// randomNoise(1, i) = math::Random(); -// randomNoise(2, i) = math::RandInt(4); -// randomNoise(3, i) = math::RandInt(2); -// randomLabels[i] = math::RandInt(5); -// } + // Now create random points. + arma::mat randomNoise(5, 2000); + arma::rowvec randomLabels(2000); + for (size_t i = 0; i < 2000; ++i) + { + randomNoise(0, i) = math::Random(); + randomNoise(1, i) = math::Random(-1, 1); + randomNoise(2, i) = math::Random(); + randomNoise(3, i) = math::RandInt(0, 2); + randomNoise(4, i) = math::RandInt(0, 5); + randomLabels[i] = math::Random(-10, 18); + } -// // Generate weights. -// arma::rowvec weights(4000); -// for (size_t i = 0; i < 2000; ++i) -// weights[i] = math::Random(0.9, 1.0); -// for (size_t i = 2000; i < 4000; ++i) -// weights[i] = math::Random(0.0, 0.001); + // Generate weights. + arma::rowvec weights(4000); + for (size_t i = 0; i < 2000; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = 2000; i < 4000; ++i) + weights[i] = math::Random(0.0, 0.001); -// arma::mat fullData = arma::join_rows(trainingData, randomNoise); -// arma::Row fullLabels = arma::join_rows(trainingLabels, randomLabels); + arma::mat fullData = arma::join_rows(trainingData, randomNoise); + arma::rowvec fullLabels = arma::join_rows(trainingLabels, randomLabels); -// // Build the tree. -// DecisionTree<> tree(fullData, di, fullLabels, 5, weights, 10); + // Build the tree. + DecisionTreeRegressor<> tree(fullData, di, fullLabels, weights, 10); -// // Now evaluate the accuracy of the tree. -// arma::Row predictions; -// tree.Classify(testData, predictions); + // Now evaluate the quality of predictions. + arma::rowvec predictions; + tree.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); -// size_t correct = 0; -// for (size_t i = 0; i < testData.n_cols; ++i) -// if (testLabels[i] == predictions[i]) -// ++correct; + REQUIRE(predictions.n_elem == testData.n_cols); -// // Make sure we got at least 70% accuracy. -// const double correctPct = double(correct) / double(testData.n_cols); -// REQUIRE(correctPct > 0.70); -// } + // Make sure we get reasonable rmse. + const double rmse = RMSE(predictions, testLabels); + REQUIRE(rmse < 1.5); +} // /** // * Test that we can build a decision tree using weighted data (where the diff --git a/src/mlpack/tests/mock_categorical_data.hpp b/src/mlpack/tests/mock_categorical_data.hpp index 8b0f00e143..fab25e9061 100644 --- a/src/mlpack/tests/mock_categorical_data.hpp +++ b/src/mlpack/tests/mock_categorical_data.hpp @@ -15,7 +15,7 @@ #include /** - * Create a mock categorical dataset for testing. + * Create a mock categorical dataset for testing classification. */ inline void MockCategoricalData(arma::mat& d, arma::Row& l, @@ -113,4 +113,62 @@ inline void MockCategoricalData(arma::mat& d, } } +/** + * Create a mock categorical dataset for testing regression. + */ +inline void MockCategoricalData(arma::mat& d, + arma::Row& l, + mlpack::data::DatasetInfo& datasetInfo) +{ + // Dataset of size 4000. + d.set_size(5, 4000); + l.set_size(4000); + + for (size_t i = 0; i < 4000; ++i) + { + // Random numeric features. + d(0, i) = mlpack::math::Random(); + d(1, i) = mlpack::math::Random(-1, 1); + d(2, i) = mlpack::math::Random(); + + // Binary feature. + d(3, i) = mlpack::math::RandInt(0, 2); + // 5-category categorical feature. + d(4, i) = mlpack::math::RandInt(0, 5); + + // Mappings from categorical features to regression value. + std::map f; + f[0] = 5.0; + f[1] = -5.0; + + std::map g; + g[0] = 2.0; + g[1] = 7.0; + g[2] = -3.0; + g[3] = 0.0; + g[4] = 4.0; + + // Random noise in range [-0.5, 0.5). + const double noise = mlpack::math::Random() - 0.5; + + // y = x1 + x2 + 3 * x3 + f(x4) + g(x5) + noise + l[i] = d(0, i) + d(1, i) + 3 * d(2, i) + f[(int) d(3, i)] + + g[(int) d(4, i)] + noise; + } + + // Now create the dataset info. + datasetInfo = mlpack::data::DatasetInfo(5); + datasetInfo.Type(3) = mlpack::data::Datatype::categorical; + datasetInfo.Type(4) = mlpack::data::Datatype::categorical; + // Set mappings. + datasetInfo.MapString("0", 3); + datasetInfo.MapString("1", 3); + + datasetInfo.MapString("0", 4); + datasetInfo.MapString("1", 4); + datasetInfo.MapString("2", 4); + datasetInfo.MapString("3", 4); + datasetInfo.MapString("4", 4); +} + #endif diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index 693c3ec469..990cb07747 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -117,33 +117,9 @@ inline void LoadBostonHousingDataset(arma::mat& trainData, inline double RMSE(const arma::Row& predictions, const arma::Row& trueLabels) { - double rmse = 0.0; - for (size_t i = 0; i < predictions.n_elem; ++i) - { - rmse += std::pow(predictions[i] - trueLabels[i], 2); - } - rmse /= predictions.n_elem; - rmse = sqrt(rmse); - return rmse; -} - -/** - * Calculates the R2 score of the predictions with true labels. - */ -inline double R2Score(const arma::Row& predictions, - const arma::Row& trueLabels) -{ - double mean = arma::mean(trueLabels); - double SStot = 0.0; - double SSres = 0.0; - for (size_t i = 0; i < predictions.n_elem; ++i) - SSres += std::pow(predictions[i] - trueLabels[i], 2); - for (size_t i = 0; i < predictions.n_elem; ++i) - { - SStot += std::pow(trueLabels[i] - mean, 2); - } - - return 1 - SSres / SStot; + double mse = arma::accu(arma::square(predictions - trueLabels)) / + predictions.n_elem; + return sqrt(mse); } #endif From b7d2f22bdc43e7ddbed58e84bc541f84e757b272 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 15 Jun 2021 19:47:49 +0530 Subject: [PATCH 581/729] Add MultiSplit tests that ensure that tree learns obvious patterns in data --- .../tests/decision_tree_regressor_test.cpp | 204 +++++++++--------- 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 9b5ef0e234..efcb733d57 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -26,6 +26,48 @@ using namespace mlpack; using namespace mlpack::tree; using namespace mlpack::distribution; +/** + * Creates dataset with 5 groups with all the points in same group have exactly + * same label. + */ +void CreateMultiSplitData(arma::mat& d, arma::rowvec& l, const size_t count, + arma::rowvec& values) +{ + d = arma::mat(10, count, arma::fill::randu); + l = arma::rowvec(count); + + // Group 1. + for (size_t i = 0; i < count / 5; i++) + { + d(3, i) = i; + l(i) = values[0]; + } + // Group 2. + for (size_t i = count / 5; i < (count / 5) * 2; i++) + { + d(3, i) = i; + l(i) = values[1]; + } + // Group 3. + for (size_t i = (count / 5) * 2; i < (count / 5) * 3; i++) + { + d(3, i) = i; + l(i) = values[2]; + } + // Group 4. + for (size_t i = (count / 5) * 3; i < (count / 5) * 4; i++) + { + d(3, i) = i; + l(i) = values[3]; + } + // Group 5. + for (size_t i = (count / 5) * 4; i < count; i++) + { + d(3, i) = i; + l(i) = values[4]; + } +} + /** * Make sure the MSE gain is zero when the labels are perfect. */ @@ -899,139 +941,103 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") // REQUIRE(mse == Approx(0.0).epsilon(1e-4)); // } -TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]") +/** + * Test that the tree is able to perfectly fit all the obvious splits present + * in the data. + * + * | + * | + * 2 | xxxxxx + * | + * | + * 1 | xxxxxx xxxxxx + * | + * | + * 0 |xxxxxx xxxxxx + * |___________________________________ + */ +TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]") { - arma::mat dataset(10, 500, arma::fill::randu); - arma::Row labels(500); + arma::mat dataset; + arma::rowvec labels; + arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; - for (size_t i = 0; i < 100; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - for (size_t i = 100; i < 200; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 200; i < 300; i++) - { - dataset(3, i) = i; - labels(i) = 2.0; - } - for (size_t i = 300; i < 400; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 400; i < 500; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } + CreateMultiSplitData(dataset, labels, 1000, values); arma::rowvec weights(labels.n_elem); weights.ones(); // Minimum leaf size of 1. - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0); arma::rowvec preds; d.Predict(dataset, preds); - const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; - REQUIRE(mse == Approx(0.0).epsilon(1e-4)); - std::cout << "****************End****************\n"; + for (size_t i = 0; i < labels.n_elem; ++i) + REQUIRE(preds[i] == labels[i]); } -TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]") +/** + * Test that the tree is able to perfectly fit all the obvious splits present + * in the data. Same test as above, but with less data. + */ +TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]") { - arma::mat dataset(10, 250, arma::fill::randu); - arma::Row labels(500); + arma::mat dataset; + arma::rowvec labels; + arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; - for (size_t i = 0; i < 50; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - for (size_t i = 50; i < 100; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 100; i < 150; i++) - { - dataset(3, i) = i; - labels(i) = 2.0; - } - for (size_t i = 150; i < 200; i++) - { - dataset(3, i) = i; - labels(i) = 1.0; - } - for (size_t i = 200; i < 250; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } + CreateMultiSplitData(dataset, labels, 100, values); arma::rowvec weights(labels.n_elem); weights.ones(); // Minimum leaf size of 1. - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0); arma::rowvec preds; d.Predict(dataset, preds); - const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; - REQUIRE(mse == Approx(0.0).epsilon(1e-4)); - std::cout << "****************End****************\n"; + for (size_t i = 0; i < labels.n_elem; ++i) + REQUIRE(preds[i] == labels[i]); } -TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]") +/** + * Test that the tree is able to perfectly fit all the obvious splits present + * in the data. + * + * | + * 20 | xxxxxx + * | + * | + * 15 | xxxxxx + * | + * | + * 10 | xxxxxx + * | + * | + * 5 | xxxxxx + * | + * | + * 0 |xxxxxx + * |________________________________________ + */ +TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") { - arma::mat dataset(10, 500, arma::fill::randu); - arma::Row labels(500); + arma::mat dataset; + arma::Row labels; + arma::rowvec values = {0.0, 5.0, 10.0, 15.0, 20.0}; - for (size_t i = 0; i < 100; i++) - { - dataset(3, i) = i; - labels(i) = 0.0; - } - for (size_t i = 100; i < 200; i++) - { - dataset(3, i) = i; - labels(i) = 5.0; - } - for (size_t i = 200; i < 300; i++) - { - dataset(3, i) = i; - labels(i) = 10.0; - } - for (size_t i = 300; i < 400; i++) - { - dataset(3, i) = i; - labels(i) = 15.0; - } - for (size_t i = 400; i < 500; i++) - { - dataset(3, i) = i; - labels(i) = 20.0; - } + CreateMultiSplitData(dataset, labels, 500, values); arma::rowvec weights(labels.n_elem); weights.ones(); // Minimum leaf size of 1. - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20); + DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0); arma::rowvec preds; d.Predict(dataset, preds); - const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; - REQUIRE(mse == Approx(0.0).epsilon(1e-4)); - std::cout << "****************End****************\n"; + for (size_t i = 0; i < labels.n_elem; ++i) + REQUIRE(preds[i] == labels[i]); } TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") From e0487772eac79380e68103607c6231becd3d37fe Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 15 Jun 2021 21:38:43 +0530 Subject: [PATCH 582/729] Added NumLeaves() to regression tree --- .../decision_tree/decision_tree_regressor.hpp | 9 +- .../decision_tree_regressor_impl.hpp | 86 +++++++++++-------- .../tests/decision_tree_regressor_test.cpp | 6 ++ 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 2e8d117f83..cd1f6bf0d6 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -404,6 +404,9 @@ class DecisionTreeRegressor : //! Get the number of children. size_t NumChildren() const { return children.size(); } + //! Get the number of leaves in the tree. + size_t NumLeaves() const; + //! Get the child of the given index. const DecisionTreeRegressor& Child(const size_t i) const { return *children[i]; } //! Modify the child of the given index (be careful!). @@ -483,8 +486,7 @@ class DecisionTreeRegressor : const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector, - int& numLeaves); + DimensionSelectionType& dimensionSelector); /** * Corresponding to the public Train() method, this method is designed for @@ -512,8 +514,7 @@ class DecisionTreeRegressor : const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector, - int& numLeaves); + DimensionSelectionType& dimensionSelector); }; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 320470df08..fd762a389f 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -65,13 +65,12 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + dimensionSelector); } //! Construct and train without weight on numeric data. @@ -102,12 +101,11 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } //! Construct and train with weights. @@ -144,12 +142,11 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + dimensionSelector); } //! Construct and train on numeric data with weights. @@ -187,11 +184,10 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } //! Take ownership of another tree and train with weights. @@ -269,11 +265,10 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, - minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } //! Copy another tree. @@ -452,12 +447,12 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector, leaves); + dimensionSelector); } //! Train on the given data, assuming all dimensions are numeric. @@ -491,13 +486,12 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + dimensionSelector); } //! Train on the given weighted data. @@ -539,12 +533,11 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + dimensionSelector); } //! Train on the given weighted all numeric data. @@ -585,12 +578,11 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector, leaves); - std::cout << "NumLeaves: " << leaves << std::endl; + dimensionSelector); } //! Train on the given data. @@ -615,8 +607,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, datasetInfo, labels, numClasses, weights, currentCol - currentChildBegin, minimumGainSplit, - maximumDepth - 1, dimensionSelector, numLeaves); + maximumDepth - 1, dimensionSelector); } else { @@ -753,7 +744,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, datasetInfo, labels, numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, - dimensionSelector, numLeaves); + dimensionSelector); bestGain += double(childCounts[i]) / double(count) * (-childGain); } children.push_back(child); @@ -768,9 +759,9 @@ double DecisionTreeRegressor( labels.subvec(begin, begin + count - 1), - UseWeights ? weights.subvec(begin, begin + count - 1) : weights); - numLeaves++; - + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + std::cout << "Number of points in leaf: " << count << + " Prediction: " << splitPointOrPrediction << std::endl; } return -bestGain; @@ -797,8 +788,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, labels, numClasses, weights, currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, - dimensionSelector, numLeaves); + dimensionSelector); } else { @@ -914,7 +904,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, currentCol - currentChildBegin, labels, numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, - dimensionSelector, numLeaves); + dimensionSelector); bestGain += double(childCounts[i]) / double(count) * (-childGain); } children.push_back(child); @@ -931,7 +921,6 @@ double DecisionTreeRegressor class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +size_t DecisionTreeRegressor::NumLeaves() const +{ + if (this->NumChildren() == 0) + return 1; + + size_t numLeaves = 0; + for (size_t i = 0; i < this->NumChildren(); ++i) + numLeaves += children[i]->NumLeaves(); + + return numLeaves; +} } // namespace tree } // namespace mlpack diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index efcb733d57..b2bddbd8a7 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -974,6 +974,8 @@ TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]") for (size_t i = 0; i < labels.n_elem; ++i) REQUIRE(preds[i] == labels[i]); + + REQUIRE(d.NumLeaves() == 5); } /** @@ -998,6 +1000,8 @@ TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]") for (size_t i = 0; i < labels.n_elem; ++i) REQUIRE(preds[i] == labels[i]); + + REQUIRE(d.NumLeaves() == 5); } /** @@ -1038,6 +1042,8 @@ TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") for (size_t i = 0; i < labels.n_elem; ++i) REQUIRE(preds[i] == labels[i]); + + REQUIRE(d.NumLeaves() == 5); } TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") From 26477c778c0d64dcede8c4a85c2e0ac887348366 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 15 Jun 2021 21:43:15 +0530 Subject: [PATCH 583/729] Removed unnecessary test --- .../tests/decision_tree_regressor_test.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index b2bddbd8a7..511c0078fb 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -1045,22 +1045,3 @@ TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") REQUIRE(d.NumLeaves() == 5); } - -TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]") -{ - // drug dosage (in mg). - arma::mat dataset = {{2, 3, 5, 10, 14, 16, 20, 22, 28, 30, 32, 35, 39}}; - // percentage effectiveness. - arma::rowvec labels = {0, 0, 0, 5, 99, 99, 99, 95, 55, 45, 7, 0, 0}; - - arma::rowvec weights(labels.n_elem); - weights.ones(); - std::cout << "****************Start**************\n"; - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 5); - arma::rowvec preds; - d.Predict(dataset, preds); - - const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem; - REQUIRE(mse == Approx(0.0).epsilon(1e-4)); - std::cout << "****************End****************\n"; -} From 4dc37b23a843fde10e5e36b24050dd6781debca1 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 16 Jun 2021 19:12:00 +0530 Subject: [PATCH 584/729] Changed labels to responses throughtout regression tree codebase --- .../best_binary_numeric_split.hpp | 6 +- .../best_binary_numeric_split_impl.hpp | 34 +- .../decision_tree/decision_tree_regressor.hpp | 129 +++---- .../decision_tree_regressor_impl.hpp | 154 ++++---- src/mlpack/methods/decision_tree/mad_gain.hpp | 26 +- src/mlpack/methods/decision_tree/mse_gain.hpp | 30 +- ...csv => boston_housing_price_responses.csv} | 0 .../tests/decision_tree_regressor_test.cpp | 334 +++++++++--------- src/mlpack/tests/test_function_tools.hpp | 18 +- 9 files changed, 372 insertions(+), 359 deletions(-) rename src/mlpack/tests/data/{boston_housing_price_labels.csv => boston_housing_price_responses.csv} (100%) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index d2e052f4dd..f1be1a426a 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -74,8 +74,8 @@ class BestBinaryNumericSplit * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). * @param data The dimension of data points to check for a split in. - * @param labels Labels for each point. - * @param weights Weights associated with labels. + * @param responses Responses for each point. + * @param weights Weights associated with responses. * @param minimumLeafSize Minimum number of points in a leaf node for * splitting. * @param minimumGainSplit Minimum gain split. @@ -87,7 +87,7 @@ class BestBinaryNumericSplit static double SplitIfBetter( const double bestGain, const VecType& data, - const arma::Row& labels, + const arma::rowvec& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index ff84a5496f..9a2f3cc3a8 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -189,7 +189,7 @@ template double BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, - const arma::Row& labels, + const arma::rowvec& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -204,10 +204,10 @@ double BestBinaryNumericSplit::SplitIfBetter( // Next, sort the data. arma::uvec sortedIndices = arma::sort_index(data); - arma::Row sortedLabels(labels.n_elem); + arma::rowvec sortedResponses(responses.n_elem); arma::rowvec sortedWeights; - for (size_t i = 0; i < sortedLabels.n_elem; ++i) - sortedLabels[i] = labels[sortedIndices[i]]; + for (size_t i = 0; i < sortedResponses.n_elem; ++i) + sortedResponses[i] = responses[sortedIndices[i]]; // Sanity check: if the first element is the same as the last, we can't split // in this dimension. @@ -217,9 +217,9 @@ double BestBinaryNumericSplit::SplitIfBetter( // Only initialize if we are using weights. if (UseWeights) { - sortedWeights.set_size(sortedLabels.n_elem); - // The weights must keep the same order as the labels. - for (size_t i = 0; i < sortedLabels.n_elem; ++i) + sortedWeights.set_size(sortedResponses.n_elem); + // The weights must keep the same order as the responses. + for (size_t i = 0; i < sortedResponses.n_elem; ++i) sortedWeights[i] = weights[sortedIndices[i]]; } @@ -260,16 +260,18 @@ double BestBinaryNumericSplit::SplitIfBetter( if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) continue; - /* TODO: The following function calculates the gain for each split each time from scratch - This can be greatly improved using advanced techniques like prefix sum and - prefix sum of squares etc. This will have drastic effects on runtime and is - definitely something we would want in future. + /* TODO: The following function calculates the gain for each split each + time from scratch. This can be greatly improved using advanced + techniques like prefix sum and prefix sum of squares etc. This + will have drastic effects on runtime and is definitely something + we would want in future. */ // Calculate the gain for the left and right child. - const double leftGain = FitnessFunction::template Evaluate(sortedLabels, - sortedWeights, 0, index); - const double rightGain = FitnessFunction::template Evaluate(sortedLabels, - sortedWeights, index, labels.n_elem); + const double leftGain = FitnessFunction::template + Evaluate(sortedResponses, sortedWeights, 0, index); + const double rightGain = FitnessFunction::template + Evaluate(sortedResponses, sortedWeights, index, + responses.n_elem); double gain; if (UseWeights) @@ -280,7 +282,7 @@ double BestBinaryNumericSplit::SplitIfBetter( { // Calculate the gain at this split point. gain = double(index) * leftGain + - double(sortedLabels.n_elem - index) * rightGain; + double(sortedResponses.n_elem - index) * rightGain; } // Corner case: is this the best possible split? diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index cd1f6bf0d6..d9996e727f 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -56,25 +56,25 @@ class DecisionTreeRegressor : DecisionTreeRegressor(); /** - * Construct the decision tree on the given data and labels, where the data - * can be both numeric and categorical. Setting minimumLeafSize and + * Construct the decision tree on the given data and responses, where the + * data can be both numeric and categorical. Setting minimumLeafSize and * minimumGainSplit too small may cause the tree to overfit, but setting them * too large may cause it to underfit. * - * Use std::move if data or labels are no longer needed to avoid copies. + * Use std::move if data or responses are no longer needed to avoid copies. * * @param data Dataset to train on. * @param datasetInfo Type information for each dimension of the dataset. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. */ - template + template DecisionTreeRegressor(MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, @@ -82,23 +82,23 @@ class DecisionTreeRegressor : DimensionSelectionType()); /** - * Construct the decision tree on the given data and labels, assuming that + * Construct the decision tree on the given data and responses, assuming that * the data is all of the numeric type. Setting minimumLeafSize and * minimumGainSplit too small may cause the tree to overfit, but setting them * too large may cause it to underfit. * - * Use std::move if data or labels are no longer needed to avoid copies. + * Use std::move if data or responses are no longer needed to avoid copies. * * @param data Dataset to train on. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. */ - template + template DecisionTreeRegressor(MatType data, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, @@ -106,28 +106,28 @@ class DecisionTreeRegressor : DimensionSelectionType()); /** - * Construct the decision tree on the given data and labels with weights, + * Construct the decision tree on the given data and responses with weights, * where the data can be both numeric and categorical. Setting minimumLeafSize * and minimumGainSplit too small may cause the tree to overfit, but setting * them too large may cause it to underfit. * - * Use std::move if data, labels or weights are no longer needed to avoid + * Use std::move if data, responses or weights are no longer needed to avoid * copies. * * @param data Dataset to train on. * @param datasetInfo Type information for each dimension of the dataset. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param weights The weight list of given label. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. */ - template + template DecisionTreeRegressor( MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, @@ -137,26 +137,26 @@ class DecisionTreeRegressor : typename std::remove_reference::type>::value>* = 0); /** - * Construct the decision tree on the given data and labels with weights, + * Construct the decision tree on the given data and responses with weights, * assuming that the data is all of the numeric type. Setting minimumLeafSize * and minimumGainSplit too small may cause the tree to overfit, but setting * them too large may cause it to underfit. * - * Use std::move if data, labels or weights are no longer needed to avoid + * Use std::move if data, responses or weights are no longer needed to avoid * copies. * * @param data Dataset to train on. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param weights The Weight list of given labels. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. */ - template + template DecisionTreeRegressor( MatType data, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, @@ -167,27 +167,28 @@ class DecisionTreeRegressor : /** * Take ownership of another decision tree and train on the given data and - * labels with weights, where the data can be both numeric and categorical. - * Setting minimumLeafSize and minimumGainSplit too small may cause the - * tree to overfit, but setting them too large may cause it to underfit. + * responses with weights, where the data can be both numeric and + * categorical. Setting minimumLeafSize and minimumGainSplit too small may + * cause the tree to overfit, but setting them too large may cause it to + * underfit. * - * Use std::move if data, labels or weights are no longer needed to avoid + * Use std::move if data, responses or weights are no longer needed to avoid * copies. * * @param other Tree to take ownership of. * @param data Dataset to train on. * @param datasetInfo Type information for each dimension of the dataset. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param weights The weight list of given label. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. */ - template + template DecisionTreeRegressor( const DecisionTreeRegressor& other, MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, @@ -195,27 +196,27 @@ class DecisionTreeRegressor : typename std::remove_reference::type>::value>* = 0); /** - * Take ownership of another decision tree and train on the given data and labels - * with weights, assuming that the data is all of the numeric type. Setting - * minimumLeafSize and minimumGainSplit too small may cause the tree to - * overfit, but setting them too large may cause it to underfit. + * Take ownership of another decision tree and train on the given data and + * responses with weights, assuming that the data is all of the numeric type. + * Setting minimumLeafSize and minimumGainSplit too small may cause the tree + * to overfit, but setting them too large may cause it to underfit. * - * Use std::move if data, labels or weights are no longer needed to avoid + * Use std::move if data, responses or weights are no longer needed to avoid * copies. * @param other Tree to take ownership of. * @param data Dataset to train on. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param weights The Weight list of given labels. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. */ - template + template DecisionTreeRegressor( const DecisionTreeRegressor& other, MatType data, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, @@ -261,26 +262,26 @@ class DecisionTreeRegressor : /** * Train the decision tree on the given data. This will overwrite the - * existing model. The data may have numeric and categorical types, specified + * existing model. The data may have numeric and categorical types, specified * by the datasetInfo parameter. Setting minimumLeafSize and * minimumGainSplit too small may cause the tree to overfit, but setting them * too large may cause it to underfit. * - * Use std::move if data or labels are no longer needed to avoid copies. + * Use std::move if data or responses are no longer needed to avoid copies. * * @param data Dataset to train on. * @param datasetInfo Type information for each dimension. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. * @return The final entropy of decision tree. */ - template + template double Train(MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, @@ -293,19 +294,19 @@ class DecisionTreeRegressor : * minimumGainSplit too small may cause the tree to overfit, but setting them * too large may cause it to underfit. * - * Use std::move if data or labels are no longer needed to avoid copies. + * Use std::move if data or responses are no longer needed to avoid copies. * * @param data Dataset to train on. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @param dimensionSelector Instantiated dimension selection policy. * @return The final entropy of decision tree. */ - template + template double Train(MatType data, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, @@ -319,12 +320,12 @@ class DecisionTreeRegressor : * minimumGainSplit too small may cause the tree to overfit, but setting them * too large may cause it to underfit. * - * Use std::move if data, labels or weights are no longer needed to avoid + * Use std::move if data, responses or weights are no longer needed to avoid * copies. * * @param data Dataset to train on. * @param datasetInfo Type information for each dimension. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param weights Weights of all the labels * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. @@ -332,10 +333,10 @@ class DecisionTreeRegressor : * @param dimensionSelector Instantiated dimension selection policy. * @return The final entropy of decision tree. */ - template + template double Train(MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, @@ -351,11 +352,11 @@ class DecisionTreeRegressor : * minimumLeafSize and minimumGainSplit too small may cause the tree to * overfit, but setting them too large may cause it to underfit. * - * Use std::move if data, labels or weights are no longer needed to avoid + * Use std::move if data, responses or weights are no longer needed to avoid * copies. * * @param data Dataset to train on. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param weights Weights of all the labels * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. @@ -363,9 +364,9 @@ class DecisionTreeRegressor : * @param dimensionSelector Instantiated dimension selection policy. * @return The final entropy of decision tree. */ - template + template double Train(MatType data, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize = 10, const double minimumGainSplit = 1e-7, @@ -386,7 +387,7 @@ class DecisionTreeRegressor : /** * Make prediction for the given points, using the entire tree. The predicted - * labels for each point are stored in the given vector. + * responses for each point are stored in the given vector. * * @param data Set of points to predict. * @param predictions This will be filled with predictions for each point. @@ -436,7 +437,7 @@ class DecisionTreeRegressor : size_t dimensionType; /** * This variable may hold different things. If the node has no children, then - * it is guaranteed to hold the prediction label for that node. If the node + * it is guaranteed to hold the prediction value for that node. If the node * has children, then it may be used arbitrarily by the split type's * CalculateDirection() and SplitIfBetter() function. In this case, it stores * the point at which the split was made. @@ -452,10 +453,10 @@ class DecisionTreeRegressor : CategoricalAuxiliarySplitInfo; /** - * Calculate the prediction label for the leaf nodes. + * Calculate the prediction value for the leaf nodes. */ - template - void CalculatePrediction(const LabelsType& labels, + template + void CalculatePrediction(const ResponsesType& responses, const WeightsType& weights); /** @@ -468,19 +469,19 @@ class DecisionTreeRegressor : * this node. * @param count Number of points in this node. * @param datasetInfo Type information for each dimension. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param numClasses Number of classes in the dataset. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @return The final entropy of decision tree. */ - template + template double Train(MatType& data, const size_t begin, const size_t count, const data::DatasetInfo& datasetInfo, - LabelsType& labels, + ResponsesType& responses, const size_t numClasses, arma::rowvec& weights, const size_t minimumLeafSize, @@ -497,18 +498,18 @@ class DecisionTreeRegressor : * @param begin Index of the starting point in the dataset that belongs to * this node. * @param count Number of points in this node. - * @param labels Labels for each training point. + * @param responses Responses for each training point. * @param numClasses Number of classes in the dataset. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. * @return The final entropy of decision tree. */ - template + template double Train(MatType& data, const size_t begin, const size_t count, - LabelsType& labels, + ResponsesType& responses, const size_t numClasses, arma::rowvec& weights, const size_t minimumLeafSize, diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index fd762a389f..be8a4c137c 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -42,7 +42,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template DecisionTreeRegressor::DecisionTreeRegressor( MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, DimensionSelectionType dimensionSelector) { using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. - Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -79,32 +79,32 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template DecisionTreeRegressor::DecisionTreeRegressor( MatType data, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, DimensionSelectionType dimensionSelector) { using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. - Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, weights, + Train(tmpData, 0, tmpData.n_cols, tmpResponses, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -114,7 +114,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template DecisionTreeRegressor::DecisionTreeRegressor( MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -132,19 +132,19 @@ DecisionTreeRegressor::type>::value>*) { using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; using TrueWeightsType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the weighted Train() method. - Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -155,14 +155,14 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template DecisionTreeRegressor::DecisionTreeRegressor( MatType data, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -174,19 +174,19 @@ DecisionTreeRegressor::type>::value>*) { using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; using TrueWeightsType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the weighted Train() method. - Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, + Train(tmpData, 0, tmpData.n_cols, tmpResponses, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -196,7 +196,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template DecisionTreeRegressor::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; using TrueWeightsType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Pass off work to the weighted Train() method. - Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, 0, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, tmpWeights, minimumLeafSize, minimumGainSplit); } @@ -234,7 +234,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template DecisionTreeRegressor::DecisionTreeRegressor( const DecisionTreeRegressor& other, MatType data, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -255,19 +255,19 @@ DecisionTreeRegressor::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; using TrueWeightsType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the weighted Train() method. - Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, tmpWeights, + Train(tmpData, 0, tmpData.n_cols, tmpResponses, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -421,7 +421,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template double DecisionTreeRegressor::Train( MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, DimensionSelectionType dimensionSelector) { // Sanity check on data. - util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + util::CheckSameSizes(data, responses, "DecisionTreeRegressor::Train()"); using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. - return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, + return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -461,35 +461,35 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template double DecisionTreeRegressor::Train( MatType data, - LabelsType labels, + ResponsesType responses, const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, DimensionSelectionType dimensionSelector) { // Sanity check on data. - util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + util::CheckSameSizes(data, responses, "DecisionTreeRegressor::Train()"); using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the Train() method. arma::rowvec weights; // Fake weights, not used. - return Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, + return Train(tmpData, 0, tmpData.n_cols, responses, 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -500,7 +500,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template double DecisionTreeRegressor::Train( MatType data, const data::DatasetInfo& datasetInfo, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -520,22 +520,22 @@ double DecisionTreeRegressor::type>::value>*) { // Sanity check on data. - util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + util::CheckSameSizes(data, responses, "DecisionTreeRegressor::Train()"); using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; using TrueWeightsType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the Train() method. - return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, + return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -546,14 +546,14 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template double DecisionTreeRegressor::Train( MatType data, - LabelsType labels, + ResponsesType responses, WeightsType weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -565,22 +565,22 @@ double DecisionTreeRegressor::type>::value>*) { // Sanity check on data. - util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + util::CheckSameSizes(data, responses, "DecisionTreeRegressor::Train()"); using TrueMatType = typename std::decay::type; - using TrueLabelsType = typename std::decay::type; + using TrueResponsesType = typename std::decay::type; using TrueWeightsType = typename std::decay::type; // Copy or move data. TrueMatType tmpData(std::move(data)); - TrueLabelsType tmpLabels(std::move(labels)); + TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; // Pass off work to the Train() method. - return Train(tmpData, 0, tmpData.n_cols, tmpLabels, 0, + return Train(tmpData, 0, tmpData.n_cols, tmpResponses, 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -591,7 +591,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template double DecisionTreeRegressor( - labels.subvec(begin, begin + count - 1), + responses.subvec(begin, begin + count - 1), numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = datasetInfo.Dimensionality(); // This means "no split". @@ -635,7 +635,7 @@ double DecisionTreeRegressor(bestGain, data.cols(begin, begin + count - 1).row(i), datasetInfo.NumMappings(i), - labels.subvec(begin, begin + count - 1), + responses.subvec(begin, begin + count - 1), numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, @@ -647,7 +647,7 @@ double DecisionTreeRegressor(bestGain, data.cols(begin, begin + count - 1).row(i), - labels.subvec(begin, begin + count - 1), + responses.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, minimumGainSplit, @@ -722,7 +722,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, datasetInfo, labels, numClasses, + currentCol - currentChildBegin, datasetInfo, responses, numClasses, weights, currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, dimensionSelector); } @@ -742,7 +742,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, datasetInfo, labels, numClasses, + currentCol - currentChildBegin, datasetInfo, responses, numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, dimensionSelector); bestGain += double(childCounts[i]) / double(count) * (-childGain); @@ -758,7 +758,7 @@ double DecisionTreeRegressor( - labels.subvec(begin, begin + count - 1), + responses.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); std::cout << "Number of points in leaf: " << count << " Prediction: " << splitPointOrPrediction << std::endl; @@ -773,7 +773,7 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template double DecisionTreeRegressor( - labels.subvec(begin, begin + count - 1), + responses.subvec(begin, begin + count - 1), numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = data.n_rows; // This means "no split". @@ -817,7 +817,7 @@ double DecisionTreeRegressor::template SplitIfBetter(bestGain, data.cols(begin, begin + count - 1).row(i), - labels.cols(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.cols(begin, begin + count - 1) : weights, @@ -882,7 +882,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, labels, numClasses, weights, + currentCol - currentChildBegin, responses, numClasses, weights, currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, dimensionSelector); } @@ -902,7 +902,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, labels, numClasses, weights, + currentCol - currentChildBegin, responses, numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, dimensionSelector); bestGain += double(childCounts[i]) / double(count) * (-childGain); @@ -917,7 +917,7 @@ double DecisionTreeRegressor( - labels.subvec(begin, begin + count - 1), + responses.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); std::cout << "Number of points in leaf: " << count << " Prediction: " << splitPointOrPrediction << std::endl; @@ -980,25 +980,27 @@ template class CategoricalSplitType, typename DimensionSelectionType, bool NoRecursion> -template +template void DecisionTreeRegressor::CalculatePrediction(const LabelsType& labels, const WeightsType& weights) +>::CalculatePrediction(const ResponsesType& responses, + const WeightsType& weights) { if (UseWeights) { double accWeights, weightedSum; - WeightedSum(labels, weights, 0, labels.n_elem, accWeights, weightedSum); + WeightedSum(responses, weights, 0, responses.n_elem, accWeights, + weightedSum); splitPointOrPrediction = weightedSum / accWeights; } else { double sum; - Sum(labels, 0, labels.n_elem, sum); - splitPointOrPrediction = sum / labels.n_elem; + Sum(responses, 0, responses.n_elem, sum); + splitPointOrPrediction = sum / responses.n_elem; } } diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index d64d566eff..0c84c36684 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -34,16 +34,16 @@ class MADGain * Evaluate the mean absolute deviation gain from begin to end index. Note * that gain can be slightly greater than 0 due to floating-point * representation issues. Thus if you are checking for perfect fit, be sure - * to use 'gain >= 0.0'. Not 'gain == 0.0'. The labels should always be of + * to use 'gain >= 0.0'. Not 'gain == 0.0'. The values should always be of * type arma::Row or arma::rowvec. * - * @param labels Set of labels to evaluate MAD gain on. - * @param weights Weight of labels. + * @param values Set of values to evaluate MAD gain on. + * @param weights Weights associated to each value. * @param begin Start index. * @param end End index. */ template - static double Evaluate(const arma::rowvec& labels, + static double Evaluate(const arma::rowvec& values, const WeightVecType& weights, const size_t begin, const size_t end) @@ -55,7 +55,7 @@ class MADGain double accWeights = 0.0; double weightedMean = 0.0; - WeightedSum(labels, weights, begin, end, accWeights, weightedMean); + WeightedSum(values, weights, begin, end, accWeights, weightedMean); // Catch edge case: if there are no weights, the impurity is zero. if (accWeights == 0.0) @@ -65,18 +65,18 @@ class MADGain for (size_t i = begin; i < end; ++i) { - mad += weights[i] * (std::abs(labels[i] - weightedMean)); + mad += weights[i] * (std::abs(values[i] - weightedMean)); } mad /= accWeights; } else { double mean = 0.0; - Sum(labels, begin, end, mean); + Sum(values, begin, end, mean); mean /= (double) (end - begin); for (size_t i = begin; i < end; ++i) - mad += std::abs(labels[i] - mean); + mad += std::abs(values[i] - mean); mad /= (double) (end - begin); } @@ -87,19 +87,19 @@ class MADGain /** * Evaluate the MAD gain on the complete vector. * - * @param labels Set of labels to evaluate MAD gain on. - * @param weights Weights associated to each label. + * @param values Set of values to evaluate MAD gain on. + * @param weights Weights associated to each value. */ template - static double Evaluate(const arma::rowvec& labels, + static double Evaluate(const arma::rowvec& values, const size_t /* numClasses */, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. - if (labels.n_elem == 0) + if (values.n_elem == 0) return 0.0; - return Evaluate(labels, weights, 0, labels.n_elem); + return Evaluate(values, weights, 0, values.n_elem); } }; diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index e12ae34ae4..b42e694945 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -29,19 +29,19 @@ class MSEGain { public: /** - * Evaluate the mean squared error gain of labls from begin to end index. + * Evaluate the mean squared error gain of values from begin to end index. * Note that gain can be slightly greater than 0 due to floating-point * representation issues. Thus if you are checking for perfect fit, be - * sure to use 'gain >= 0.0' and not 'gain == 0.0'. The labels vector should - * always be of type arma::Row or arma::rowvec. + * sure to use 'gain >= 0.0' and not 'gain == 0.0'. The values vector + * should always be of type arma::Row or arma::rowvec. * - * @param labels Set of labels to evaluate MAD gain on. - * @param weights Weight of labels. + * @param values Set of values to evaluate MAD gain on. + * @param weights Weights associated to each value. * @param begin Start index. * @param end End index. */ template - static double Evaluate(const arma::rowvec& labels, + static double Evaluate(const arma::rowvec& values, const WeightVecType& weights, const size_t begin, const size_t end) @@ -52,7 +52,7 @@ class MSEGain { double accWeights = 0.0; double weightedMean = 0.0; - WeightedSum(labels, weights, begin, end, accWeights, weightedMean); + WeightedSum(values, weights, begin, end, accWeights, weightedMean); // Catch edge case: if there are no weights, the impurity is zero. if (accWeights == 0.0) @@ -61,18 +61,18 @@ class MSEGain weightedMean /= accWeights; for (size_t i = begin; i < end; ++i) - mse += weights[i] * std::pow(labels[i] - weightedMean, 2); + mse += weights[i] * std::pow(values[i] - weightedMean, 2); mse /= accWeights; } else { double mean = 0.0; - Sum(labels, begin, end, mean); + Sum(values, begin, end, mean); mean /= (double) (end - begin); for (size_t i = begin; i < end; ++i) - mse += std::pow(labels[i] - mean, 2); + mse += std::pow(values[i] - mean, 2); mse /= (double) (end - begin); } @@ -83,19 +83,19 @@ class MSEGain /** * Evaluate the MSE gain on the complete vector. * - * @param labels Set of labels to evaluate MAD gain on. - * @param weights Weights associated to each label. + * @param values Set of values to evaluate MSE gain on. + * @param weights Weights associated to each value. */ template - static double Evaluate(const arma::rowvec& labels, + static double Evaluate(const arma::rowvec& values, const size_t /* numClasses */, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. - if (labels.n_elem == 0) + if (values.n_elem == 0) return 0.0; - return Evaluate(labels, weights, 0, labels.n_elem); + return Evaluate(values, weights, 0, values.n_elem); } }; diff --git a/src/mlpack/tests/data/boston_housing_price_labels.csv b/src/mlpack/tests/data/boston_housing_price_responses.csv similarity index 100% rename from src/mlpack/tests/data/boston_housing_price_labels.csv rename to src/mlpack/tests/data/boston_housing_price_responses.csv diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 511c0078fb..38f61ee7ca 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -28,56 +28,56 @@ using namespace mlpack::distribution; /** * Creates dataset with 5 groups with all the points in same group have exactly - * same label. + * same responses. */ -void CreateMultiSplitData(arma::mat& d, arma::rowvec& l, const size_t count, +void CreateMultiSplitData(arma::mat& d, arma::rowvec& r, const size_t count, arma::rowvec& values) { d = arma::mat(10, count, arma::fill::randu); - l = arma::rowvec(count); + r = arma::rowvec(count); // Group 1. for (size_t i = 0; i < count / 5; i++) { d(3, i) = i; - l(i) = values[0]; + r(i) = values[0]; } // Group 2. for (size_t i = count / 5; i < (count / 5) * 2; i++) { d(3, i) = i; - l(i) = values[1]; + r(i) = values[1]; } // Group 3. for (size_t i = (count / 5) * 2; i < (count / 5) * 3; i++) { d(3, i) = i; - l(i) = values[2]; + r(i) = values[2]; } // Group 4. for (size_t i = (count / 5) * 3; i < (count / 5) * 4; i++) { d(3, i) = i; - l(i) = values[3]; + r(i) = values[3]; } // Group 5. for (size_t i = (count / 5) * 4; i < count; i++) { d(3, i) = i; - l(i) = values[4]; + r(i) = values[4]; } } /** - * Make sure the MSE gain is zero when the labels are perfect. + * Make sure the MSE gain is zero when the responses are perfect. */ TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels; - labels.ones(10); + arma::rowvec responses; + responses.ones(10); - REQUIRE(MSEGain::Evaluate(labels, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, 0, weights) == Approx(0.0).margin(1e-5)); } @@ -87,11 +87,11 @@ TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressorTest]") TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); - arma::rowvec labels; - REQUIRE(MSEGain::Evaluate(labels, 0, weights) == + arma::rowvec responses; + REQUIRE(MSEGain::Evaluate(responses, 0, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(labels, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, 0, weights) == Approx(0.0).margin(1e-5)); } @@ -101,48 +101,49 @@ TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressorTest]") */ TEST_CASE("MSEGainHandCalculation", "[DecisionTreeRegressorTest]") { - arma::rowvec labels = {4., 2., 3., 4., 13., 6., 20., 8., 9., 10.}; + arma::rowvec responses = {4., 2., 3., 4., 13., 6., 20., 8., 9., 10.}; arma::rowvec weights = {0.3, 0.3, 0.3, 0.3, 0.3, 0.7, 0.7, 0.7, 0.7, 0.7}; // Hand calculated gain values. const double gain = -27.08999; const double weightedGain = -27.53960; - REQUIRE(MSEGain::Evaluate(labels, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, 0, weights) == Approx(gain).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(labels, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, 0, weights) == Approx(weightedGain).margin(1e-5)); } /** - * Make sure the MAD gain is zero when the labels are perfect. + * Make sure the MAD gain is zero when the responses are perfect. */ TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels; - labels.ones(10); + arma::rowvec responses; + responses.ones(10); - REQUIRE(MADGain::Evaluate(labels, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, 0, weights) == Approx(0.0).margin(1e-5)); } /** - * Make sure that when mean of labels is zero, MAD_gain = mean of + * Make sure that when mean of responses is zero, MAD_gain = mean of * absolute values of the distribution. */ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressorTest") { arma::rowvec weights(10, arma::fill::ones); - arma::rowvec labels = { 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; // Mean = 0. + arma::rowvec responses = { 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; // Mean = 0. // Theoretical gain. double theoreticalGain = 0.0; - for (size_t i = 0; i < labels.n_elem; ++i) - theoreticalGain -= std::abs(labels[i]); - theoreticalGain /= (double) labels.n_elem; + for (size_t i = 0; i < responses.n_elem; ++i) + theoreticalGain -= std::abs(responses[i]); + theoreticalGain /= (double) responses.n_elem; // Calculated gain. - const double calculatedGain = MADGain::Evaluate(labels, 0, weights); + const double calculatedGain = + MADGain::Evaluate(responses, 0, weights); REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); } @@ -153,11 +154,11 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressorTest") TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); - arma::rowvec labels; - REQUIRE(MADGain::Evaluate(labels, 0, weights) == + arma::rowvec responses; + REQUIRE(MADGain::Evaluate(responses, 0, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MADGain::Evaluate(labels, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, 0, weights) == Approx(0.0).margin(1e-5)); } @@ -167,15 +168,15 @@ TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressorTest]") */ TEST_CASE("MADGainHandCalculation", "[DecisionTreeRegressorTest]") { - arma::rowvec labels = {4., 2., 3., 4., 13., 6., 20., 8., 9., 10.}; + arma::rowvec responses = {4., 2., 3., 4., 13., 6., 20., 8., 9., 10.}; arma::rowvec weights = {0.3, 0.3, 0.3, 0.3, 0.3, 0.7, 0.7, 0.7, 0.7, 0.7}; // Hand calculated gain values. const double gain = -4.1; const double weightedGain = -3.8592; - REQUIRE(MADGain::Evaluate(labels, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, 0, weights) == Approx(gain).margin(1e-5)); - REQUIRE(MADGain::Evaluate(labels, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, 0, weights) == Approx(weightedGain).margin(1e-5)); } @@ -186,28 +187,28 @@ TEST_CASE("MADGainHandCalculation", "[DecisionTreeRegressorTest]") TEST_CASE("AllCategoricalSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") { arma::vec predictor(100); - arma::rowvec labels(100); - arma::rowvec weights(labels.n_elem); + arma::rowvec responses(100); + arma::rowvec weights(responses.n_elem); weights.ones(); for (size_t i = 0; i < 100; i+=2) { predictor[i] = 0; - labels[i] = 5.0; + responses[i] = 5.0; predictor[i + 1] = 1; - labels[i + 1] = 100; + responses[i + 1] = 100; } double splitInfo; AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, 0, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictor, 2, labels, 0, weights, 3, 1e-7, splitInfo, aux); + bestGain, predictor, 2, responses, 0, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictor, 2, - labels, 0, weights, 3, 1e-7, splitInfo, aux); + responses, 0, weights, 3, 1e-7, splitInfo, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -225,17 +226,17 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") TEST_CASE("AllCategoricalSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3}; - arma::rowvec labels = {0, 0, 0, 2, 2, 2, 1, 1, 1, 2, 2, 2}; - arma::rowvec weights(labels.n_elem); + arma::rowvec responses = {0, 0, 0, 2, 2, 2, 1, 1, 1, 2, 2, 2}; + arma::rowvec weights(responses.n_elem); weights.ones(); double splitInfo; AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, 0, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 4, labels, 0, weights, 4, 1e-7, splitInfo, aux); + bestGain, predictors, 4, responses, 0, weights, 4, 1e-7, splitInfo, aux); // Make sure it's not split. REQUIRE(gain == DBL_MAX); @@ -247,30 +248,30 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") TEST_CASE("AllCategoricalSplitNoGainTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors(300); - arma::rowvec labels(300); + arma::rowvec responses(300); arma::rowvec weights = arma::ones(300); for (size_t i = 0; i < 300; i += 3) { predictors[i] = int(i / 3) % 10; - labels[i] = -0.5; + responses[i] = -0.5; predictors[i + 1] = int(i / 3) % 10; - labels[i + 1] = 0; + responses[i + 1] = 0; predictors[i + 2] = int(i / 3) % 10; - labels[i + 2] = 0.5; + responses[i + 2] = 0.5; } double splitInfo; AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, 0, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 10, labels, 0, weights, 10, 1e-7, + bestGain, predictors, 10, responses, 0, weights, 10, 1e-7, splitInfo, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictors, - 10, labels, 0, predictors, 10, 1e-7, splitInfo, aux); + 10, responses, 0, predictors, 10, 1e-7, splitInfo, aux); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); @@ -281,23 +282,26 @@ TEST_CASE("AllCategoricalSplitNoGainTest_", "[DecisionTreeRegressorTest]") * Check that the BestBinaryNumericSplit will split on an obviously splittable * dimension. */ -TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") +TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", + "[DecisionTreeRegressorTest]") { - arma::rowvec predictors = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; - arma::rowvec labels = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; - arma::rowvec weights(labels.n_elem); + arma::rowvec predictors = + { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; + arma::rowvec responses = + { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; + arma::rowvec weights(responses.n_elem); weights.ones(); double splitInfo; BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MADGain::Evaluate(labels, 0, weights); + const double bestGain = MADGain::Evaluate(responses, 0, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, labels, weights, 3, 1e-7, splitInfo, aux); + bestGain, predictors, responses, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, - labels, weights, 3, 1e-7, splitInfo, aux); + responses, weights, 3, 1e-7, splitInfo, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -315,23 +319,26 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", "[DecisionTreeRegressorTest] * Check that the BestBinaryNumericSplit won't split if not enough points are * given. */ -TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") +TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", + "[DecisionTreeRegressorTest]") { - arma::rowvec predictors = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; - arma::rowvec labels = { 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; - arma::rowvec weights(labels.n_elem); + arma::rowvec predictors = + { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; + arma::rowvec responses = + { 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; + arma::rowvec weights(responses.n_elem); double splitInfo; BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, 0, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, labels, weights, 8, 1e-7, splitInfo, aux); + bestGain, predictors, responses, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. const double weightedGain = - BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, - labels, weights, 8, 1e-7, splitInfo, aux); + BestBinaryNumericSplit::SplitIfBetter(bestGain, + predictors, responses, weights, 8, 1e-7, splitInfo, aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); @@ -339,30 +346,29 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", "[DecisionTreeRegressorTest]" } /** - * Check that the BestBinaryNumericSplit doesn't split a dimension that gives no - * gain. + * Check that the BestBinaryNumericSplit doesn't split a dimension that gives + * no gain. */ TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") { arma::rowvec predictors(100); - arma::rowvec labels(100); + arma::rowvec responses(100); arma::rowvec weights; for (size_t i = 0; i < 100; i += 2) { predictors[i] = i; - labels[i] = 0.0; + responses[i] = 0.0; predictors[i + 1] = i; - labels[i + 1] = 1.0; + responses[i + 1] = 1.0; } double splitInfo; BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, 0, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, labels, weights, 10, 1e-7, splitInfo, - aux); + bestGain, predictors, responses, weights, 10, 1e-7, splitInfo, aux); // Make sure there was no split. REQUIRE(gain == DBL_MAX); @@ -376,20 +382,20 @@ TEST_CASE("RandomBinaryNumericSplitAlwaysSplit_", "[DecisionTreeRegressorTest]") { arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); - arma::rowvec labels("0 0 0 0 0 1 1 1 1 1 1"); + arma::rowvec responses("0 0 0 0 0 1 1 1 1 1 1"); arma::rowvec weights; - weights.ones(labels.n_elem); + weights.ones(responses.n_elem); double splitInfo; RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 2, weights); + const double bestGain = MSEGain::Evaluate(responses, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, weights, 1, 1e-7, splitInfo, aux); + bestGain, values, responses, weights, 1, 1e-7, splitInfo, aux); const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, weights, 1, 1e-7, splitInfo, aux); + responses, weights, 1, 1e-7, splitInfo, aux); // Make sure that split was made. REQUIRE(gain != DBL_MAX); @@ -404,20 +410,20 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") { arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); - arma::rowvec labels("0 0 0 0 0 1 1 1 1 1 1"); - arma::rowvec weights(labels.n_elem); + arma::rowvec responses("0 0 0 0 0 1 1 1 1 1 1"); + arma::rowvec weights(responses.n_elem); double splitInfo; RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 2, weights); + const double bestGain = MSEGain::Evaluate(responses, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, weights, 8, 1e-7, splitInfo, aux); + bestGain, values, responses, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, weights, 8, 1e-7, splitInfo, aux); + responses, weights, 8, 1e-7, splitInfo, aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); @@ -431,23 +437,23 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest_", TEST_CASE("RandomBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") { arma::vec values(100); - arma::Row labels(100); + arma::rowvec responses(100); arma::rowvec weights; for (size_t i = 0; i < 100; i += 2) { values[i] = i; - labels[i] = 0.0; + responses[i] = 0.0; values[i + 1] = i; - labels[i + 1] = 1.0; + responses[i + 1] = 1.0; } double splitInfo; RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(labels, 2, weights); + const double bestGain = MSEGain::Evaluate(responses, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, weights, 10, 1e-7, splitInfo, aux, true); + bestGain, values, responses, weights, 10, 1e-7, splitInfo, aux, true); // Make sure there was no split. REQUIRE(gain == DBL_MAX); @@ -460,48 +466,48 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") TEST_CASE("BasicConstructionTest_", "[DecisionTreeRegressorTest]") { arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); + arma::rowvec responses(100); for (size_t i = 0; i < 50; ++i) { dataset(3, i) = i; - labels[i] = 0.0; + responses[i] = 0.0; } for (size_t i = 50; i < 100; ++i) { dataset(3, i) = i; - labels[i] = 1.0; + responses[i] = 1.0; } // Use default parameters. - DecisionTreeRegressor<> d(dataset, labels); + DecisionTreeRegressor<> d(dataset, responses); // Now require that we have some children. REQUIRE(d.NumChildren() > 0); } /** - * Construct a tree with weighted labels. + * Construct a tree with weighted responses. */ TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") { arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); + arma::rowvec responses(100); for (size_t i = 0; i < 50; ++i) { dataset(3, i) = i; - labels[i] = 0.0; + responses[i] = 0.0; } for (size_t i = 50; i < 100; ++i) { dataset(3, i) = i; - labels[i] = 1.0; + responses[i] = 1.0; } - arma::rowvec weights(labels.n_elem); + arma::rowvec weights(responses.n_elem); weights.ones(); // Use default parameters. - DecisionTreeRegressor<> wd(dataset, labels, weights); - DecisionTreeRegressor<> d(dataset, labels); + DecisionTreeRegressor<> wd(dataset, responses, weights); + DecisionTreeRegressor<> d(dataset, responses); // Now require that we have some children. REQUIRE(wd.NumChildren() > 0); @@ -515,53 +521,53 @@ TEST_CASE("BasicConstructionTestWithWeight_", "[DecisionTreeRegressorTest]") TEST_CASE("PerfectTrainingSet_", "[DecisionTreeRegressorTest]") { arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); + arma::rowvec responses(100); for (size_t i = 0; i < 50; ++i) { dataset(3, i) = i; - labels[i] = 0.0; + responses[i] = 0.0; } for (size_t i = 50; i < 100; ++i) { dataset(3, i) = i; - labels[i] = 1.0; + responses[i] = 1.0; } - DecisionTreeRegressor<> d(dataset, labels, 1, 0.0); // Minimum leaf size of 1. + // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, responses, 1, 0.0); - // Make sure that we can get perfect accuracy on the training set. + // Make sure that we can get perfect fit on the training set. for (size_t i = 0; i < 100; ++i) { double prediction; prediction = d.Predict(dataset.col(i)); - REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + REQUIRE(prediction == Approx(responses[i]).epsilon(1e-7)); } } /** - * Construct the decision tree with weighted labels + * Construct the decision tree with weighted responses. */ TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") { // Completely random dataset with no structure. arma::mat dataset(10, 100, arma::fill::randu); - arma::Row labels(100); + arma::rowvec responses(100); for (size_t i = 0; i < 50; ++i) { dataset(3, i) = i; - labels[i] = 0.0; + responses[i] = 0.0; } for (size_t i = 50; i < 100; ++i) { dataset(3, i) = i; - labels[i] = 1.0; + responses[i] = 1.0; } - arma::rowvec weights(labels.n_elem); - weights.ones(); + arma::rowvec weights = arma::ones(responses.n_elem); // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, labels, weights, 1, 0.0); + DecisionTreeRegressor<> d(dataset, responses, weights, 1, 0.0); // This part of code is dupliacte with no weighted one. for (size_t i = 0; i < 100; ++i) @@ -569,7 +575,7 @@ TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") size_t prediction; prediction = d.Predict(dataset.col(i)); - REQUIRE(prediction == Approx(labels[i]).epsilon(1e-7)); + REQUIRE(prediction == Approx(responses[i]).epsilon(1e-7)); } } @@ -579,18 +585,18 @@ TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") TEST_CASE("CategoricalBuildTest_", "[DecisionTreeRegressorTest]") { arma::mat d; - arma::rowvec l; + arma::rowvec r; data::DatasetInfo di; - MockCategoricalData(d, l, di); + MockCategoricalData(d, r, di); // Split into a training set and a test set. arma::mat trainingData = d.cols(0, 1999); arma::mat testData = d.cols(2000, 3999); - arma::rowvec trainingLabels = l.subvec(0, 1999); - arma::rowvec testLabels = l.subvec(2000, 3999); + arma::rowvec trainingResponses = r.subvec(0, 1999); + arma::rowvec testResponses = r.subvec(2000, 3999); // Build the tree. - DecisionTreeRegressor<> tree(trainingData, di, trainingLabels, 10); + DecisionTreeRegressor<> tree(trainingData, di, trainingResponses, 10); // Now evaluate the quality of predictions. arma::rowvec predictions; @@ -599,7 +605,7 @@ TEST_CASE("CategoricalBuildTest_", "[DecisionTreeRegressorTest]") REQUIRE(predictions.n_elem == testData.n_cols); // Make sure we get reasonable rmse. - const double rmse = RMSE(predictions, testLabels); + const double rmse = RMSE(predictions, testResponses); REQUIRE(rmse < 1.0); } @@ -610,21 +616,21 @@ TEST_CASE("CategoricalBuildTest_", "[DecisionTreeRegressorTest]") TEST_CASE("CategoricalBuildTestWithWeight_", "[DecisionTreeRegressorTest]") { arma::mat d; - arma::rowvec l; + arma::rowvec r; data::DatasetInfo di; - MockCategoricalData(d, l, di); + MockCategoricalData(d, r, di); // Split into a training set and a test set. arma::mat trainingData = d.cols(0, 1999); arma::mat testData = d.cols(2000, 3999); - arma::rowvec trainingLabels = l.subvec(0, 1999); - arma::rowvec testLabels = l.subvec(2000, 3999); + arma::rowvec trainingResponses = r.subvec(0, 1999); + arma::rowvec testResponses = r.subvec(2000, 3999); - arma::rowvec weights = arma::ones( - trainingLabels.n_elem); + arma::rowvec weights = arma::ones(trainingResponses.n_elem); // Build the tree. - DecisionTreeRegressor<> tree(trainingData, di, trainingLabels, weights, 10); + DecisionTreeRegressor<> tree(trainingData, di, trainingResponses, weights, + 10); // Now evaluate the quality of predictions. arma::rowvec predictions; @@ -633,7 +639,7 @@ TEST_CASE("CategoricalBuildTestWithWeight_", "[DecisionTreeRegressorTest]") REQUIRE(predictions.n_elem == testData.n_cols); // Make sure we get reasonable rmse. - const double rmse = RMSE(predictions, testLabels); + const double rmse = RMSE(predictions, testResponses); REQUIRE(rmse < 1.0); } @@ -689,19 +695,19 @@ TEST_CASE("CategoricalBuildTestWithWeight_", "[DecisionTreeRegressorTest]") TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") { arma::mat d; - arma::rowvec l; + arma::rowvec r; data::DatasetInfo di; - MockCategoricalData(d, l, di); + MockCategoricalData(d, r, di); // Split into a training set and a test set. arma::mat trainingData = d.cols(0, 1999); arma::mat testData = d.cols(2000, 3999); - arma::rowvec trainingLabels = l.subvec(0, 1999); - arma::rowvec testLabels = l.subvec(2000, 3999); + arma::rowvec trainingResponses = r.subvec(0, 1999); + arma::rowvec testResponses = r.subvec(2000, 3999); // Now create random points. arma::mat randomNoise(5, 2000); - arma::rowvec randomLabels(2000); + arma::rowvec randomResponses(2000); for (size_t i = 0; i < 2000; ++i) { randomNoise(0, i) = math::Random(); @@ -709,7 +715,7 @@ TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") randomNoise(2, i) = math::Random(); randomNoise(3, i) = math::RandInt(0, 2); randomNoise(4, i) = math::RandInt(0, 5); - randomLabels[i] = math::Random(-10, 18); + randomResponses[i] = math::Random(-10, 18); } // Generate weights. @@ -720,10 +726,11 @@ TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") weights[i] = math::Random(0.0, 0.001); arma::mat fullData = arma::join_rows(trainingData, randomNoise); - arma::rowvec fullLabels = arma::join_rows(trainingLabels, randomLabels); + arma::rowvec fullResponses = arma::join_rows(trainingResponses, + randomResponses); // Build the tree. - DecisionTreeRegressor<> tree(fullData, di, fullLabels, weights, 10); + DecisionTreeRegressor<> tree(fullData, di, fullResponses, weights, 10); // Now evaluate the quality of predictions. arma::rowvec predictions; @@ -732,7 +739,7 @@ TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") REQUIRE(predictions.n_elem == testData.n_cols); // Make sure we get reasonable rmse. - const double rmse = RMSE(predictions, testLabels); + const double rmse = RMSE(predictions, testResponses); REQUIRE(rmse < 1.5); } @@ -856,29 +863,30 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") // Loading data. data::DatasetInfo info; arma::mat trainData, testData; - arma::Row trainLabels, testLabels; + arma::rowvec trainResponses, testResponses; arma::rowvec weights = arma::ones(355); - LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); + LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, + info); // Build decision tree. - DecisionTreeRegressor d(trainData, info, trainLabels); + DecisionTreeRegressor d(trainData, info, trainResponses); - // Get the predicted test labels. + // Get the predicted test responses. arma::Row predictions; d.Predict(testData, predictions); REQUIRE(predictions.n_elem == testData.n_cols); // Figure out rmse. - double rmse = RMSE(predictions, testLabels); + double rmse = RMSE(predictions, testResponses); // REQUIRE(rmse < 9.21); - // std::cout << predictions << std::endl << testLabels; + // std::cout << predictions << std::endl << testResponses; arma::Row trainPred; d.Predict(trainData, trainPred); // std::cout << trainPred; - std::cout << "Train RMSE: " << RMSE(trainLabels, trainPred) << std::endl; + std::cout << "Train RMSE: " << RMSE(trainResponses, trainPred) << std::endl; } /** @@ -959,21 +967,21 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]") { arma::mat dataset; - arma::rowvec labels; + arma::rowvec responses; arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; - CreateMultiSplitData(dataset, labels, 1000, values); + CreateMultiSplitData(dataset, responses, 1000, values); - arma::rowvec weights(labels.n_elem); + arma::rowvec weights(responses.n_elem); weights.ones(); // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0); + DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); arma::rowvec preds; d.Predict(dataset, preds); - for (size_t i = 0; i < labels.n_elem; ++i) - REQUIRE(preds[i] == labels[i]); + for (size_t i = 0; i < responses.n_elem; ++i) + REQUIRE(preds[i] == responses[i]); REQUIRE(d.NumLeaves() == 5); } @@ -985,21 +993,21 @@ TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]") TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]") { arma::mat dataset; - arma::rowvec labels; + arma::rowvec responses; arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; - CreateMultiSplitData(dataset, labels, 100, values); + CreateMultiSplitData(dataset, responses, 100, values); - arma::rowvec weights(labels.n_elem); + arma::rowvec weights(responses.n_elem); weights.ones(); // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0); + DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); arma::rowvec preds; d.Predict(dataset, preds); - for (size_t i = 0; i < labels.n_elem; ++i) - REQUIRE(preds[i] == labels[i]); + for (size_t i = 0; i < responses.n_elem; ++i) + REQUIRE(preds[i] == responses[i]); REQUIRE(d.NumLeaves() == 5); } @@ -1027,21 +1035,21 @@ TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]") TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") { arma::mat dataset; - arma::Row labels; + arma::Row responses; arma::rowvec values = {0.0, 5.0, 10.0, 15.0, 20.0}; - CreateMultiSplitData(dataset, labels, 500, values); + CreateMultiSplitData(dataset, responses, 500, values); - arma::rowvec weights(labels.n_elem); + arma::rowvec weights(responses.n_elem); weights.ones(); // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0); + DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); arma::rowvec preds; d.Predict(dataset, preds); - for (size_t i = 0; i < labels.n_elem; ++i) - REQUIRE(preds[i] == labels[i]); + for (size_t i = 0; i < responses.n_elem; ++i) + REQUIRE(preds[i] == responses[i]); REQUIRE(d.NumLeaves() == 5); } diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index 990cb07747..0233402506 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -83,20 +83,20 @@ inline void LogisticRegressionTestData(arma::mat& data, inline void LoadBostonHousingDataset(arma::mat& trainData, arma::mat& testData, - arma::Row& trainLabels, - arma::Row& testLabels, + arma::rowvec& trainResponses, + arma::rowvec& testResponses, data::DatasetInfo& info) { arma::mat dataset; - arma::Row labels; + arma::rowvec responses; if (!data::Load("boston_housing_price.csv", dataset, info)) FAIL("Cannot load test dataset boston_housing_price.csv!"); - if (!data::Load("boston_housing_price_labels.csv", labels)) - FAIL("Cannot load test dataset boston_housing_price_labels.csv!"); + if (!data::Load("boston_housing_price_responses.csv", responses)) + FAIL("Cannot load test dataset boston_housing_price_responses.csv!"); - data::Split(dataset, labels, trainData, testData, - trainLabels, testLabels, 0.3); + data::Split(dataset, responses, trainData, testData, + trainResponses, testResponses, 0.3); // info.Type(3) = data::Datatype::categorical; // info.Type(8) = data::Datatype::categorical; @@ -115,9 +115,9 @@ inline void LoadBostonHousingDataset(arma::mat& trainData, } inline double RMSE(const arma::Row& predictions, - const arma::Row& trueLabels) + const arma::Row& trueResponses) { - double mse = arma::accu(arma::square(predictions - trueLabels)) / + double mse = arma::accu(arma::square(predictions - trueResponses)) / predictions.n_elem; return sqrt(mse); } From ac0b08ead8a065082ecd81bf38db0474c1c4b7d7 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 16 Jun 2021 19:20:33 +0530 Subject: [PATCH 585/729] This was missed while changing labels to responses --- .../random_binary_numeric_split.hpp | 7 +++---- .../random_binary_numeric_split_impl.hpp | 20 +++++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 98d1f13787..60f51ce5d1 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -99,9 +99,8 @@ class RandomBinaryNumericSplit * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). * @param data The dimension of data points to check for a split in. - * @param labels Labels for each point. - * @param numClasses Number of classes in the dataset. - * @param weights Weights associated with labels. + * @param responses Responses for each point. + * @param weights Weights associated with responses. * @param minimumLeafSize Minimum number of points in a leaf node for * splitting. * @param minimumGainSplit Minimum gain split. @@ -116,7 +115,7 @@ class RandomBinaryNumericSplit static double SplitIfBetter( const double bestGain, const VecType& data, - const arma::Row& labels, + const arma::rowvec& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 2bd09bc53b..cb33c837ba 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -141,7 +141,7 @@ template double RandomBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, - const arma::Row& labels, + const arma::rowvec& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -203,7 +203,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( } // Splitting data to compute gain. - arma::rowvec leftLabels(leftLeafSize), rightLabels(rightLeafSize); + arma::rowvec leftResponses(leftLeafSize), rightResponses(rightLeafSize); arma::rowvec leftWeights, rightWeights; if (UseWeights) { @@ -222,18 +222,16 @@ double RandomBinaryNumericSplit::SplitIfBetter( rightWeights[r] = weights[i]; } if (data[i] < randomPivot) - leftLabels[l++] = labels[i]; + leftResponses[l++] = responses[i]; else - rightLabels[r++] = labels[i]; + rightResponses[r++] = responses[i]; } // Calculate the gain for the left and right child. - const double leftGain = - FitnessFunction::template Evaluate(leftLabels, leftWeights, - 0, leftLeafSize); - const double rightGain = - FitnessFunction::template Evaluate(rightLabels, rightWeights, - 0, rightLeafSize); + const double leftGain = FitnessFunction::template + Evaluate(leftResponses, leftWeights, 0, leftLeafSize); + const double rightGain = FitnessFunction::template + Evaluate(rightResponses, rightWeights, 0, rightLeafSize); // Calculate the gain at this split point. double gain; @@ -250,7 +248,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( if (UseWeights) gain /= totalWeight; else - gain /= labels.n_elem; + gain /= responses.n_elem; return gain; } From b1f5a836d99a050b8ad444cb069223aabbdd6611 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 16 Jun 2021 19:33:11 +0530 Subject: [PATCH 586/729] Minor style fixes and documentation updates from code review --- .../decision_tree/best_binary_numeric_split.hpp | 4 ++-- .../decision_tree/decision_tree_regressor_impl.hpp | 13 +++++++------ src/mlpack/methods/decision_tree/mad_gain.hpp | 2 +- .../decision_tree/random_binary_numeric_split.hpp | 4 ++-- .../random_binary_numeric_split_impl.hpp | 6 +++--- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index f1be1a426a..6907edb943 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -36,7 +36,7 @@ class BestBinaryNumericSplit * return the value 'bestGain'. If a split is made, then splitInfo and aux * may be modified. * - * It is used only for classification tasks. + * This overload is used only for classification tasks. * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). @@ -69,7 +69,7 @@ class BestBinaryNumericSplit * return the value 'bestGain'. If a split is made, then splitInfo and aux * may be modified. * - * It is used only for regression tasks. + * This overload is used only for regression tasks. * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index be8a4c137c..d74c7e4f7a 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -615,8 +615,10 @@ double DecisionTreeRegressor( responses.subvec(begin, begin + count - 1), numClasses, @@ -798,11 +800,10 @@ double DecisionTreeRegressor( responses.subvec(begin, begin + count - 1), numClasses, diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 0c84c36684..e962ec77a7 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -2,7 +2,7 @@ * @file methods/decision_tree/mad_gain.hpp * @author Rishabh Garg * - * The mean absolute deviation gain class, a fitness funtion for regression + * The mean absolute deviation gain class, a fitness function for regression * based decision trees. * * mlpack is free software; you may redistribute it and/or modify it under the diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp index 60f51ce5d1..9d86c69e12 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split.hpp @@ -37,7 +37,7 @@ class RandomBinaryNumericSplit * return the value 'bestGain'. If a split is made, then splitInfo * and aux may be modified. * - * It is used only for classification tasks. + * This overload is used only for classification tasks. * * @code * @article{10.1007/s10994-006-6226-1, @@ -94,7 +94,7 @@ class RandomBinaryNumericSplit * return the value 'bestGain'. If a split is made, then splitInfo * and aux may be modified. * - * It is used only for regression tasks. + * This overload is used only for regression tasks. * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index cb33c837ba..6a9db54a05 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -207,12 +207,12 @@ double RandomBinaryNumericSplit::SplitIfBetter( arma::rowvec leftWeights, rightWeights; if (UseWeights) { - leftWeights.set_size(leftLeafSize); - rightWeights.set_size(rightLeafSize); + leftWeights.set_size(leftLeafSize); + rightWeights.set_size(rightLeafSize); } size_t l = 0, r = 0; - for(size_t i = 0; i < data.n_elem; ++i) + for (size_t i = 0; i < data.n_elem; ++i) { if (UseWeights) { From 34b5ac7badcb6481b8a0b4f85ece42067fc95ec2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 17 Jun 2021 09:32:40 +0530 Subject: [PATCH 587/729] Use armadillo's functions to evaluate mse and mad gains --- src/mlpack/methods/decision_tree/mad_gain.hpp | 4 +--- src/mlpack/methods/decision_tree/mse_gain.hpp | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index e962ec77a7..10016045a0 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -75,9 +75,7 @@ class MADGain Sum(values, begin, end, mean); mean /= (double) (end - begin); - for (size_t i = begin; i < end; ++i) - mad += std::abs(values[i] - mean); - + mad = arma::accu(arma::abs(values - mean)); mad /= (double) (end - begin); } diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index b42e694945..44dadb574e 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -71,9 +71,7 @@ class MSEGain Sum(values, begin, end, mean); mean /= (double) (end - begin); - for (size_t i = begin; i < end; ++i) - mse += std::pow(values[i] - mean, 2); - + mse = arma::accu(arma::square(values.subvec(begin, end - 1) - mean)); mse /= (double) (end - begin); } From 917885b609adc486d0207d9486310ad16d14454b Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 17 Jun 2021 10:14:40 +0530 Subject: [PATCH 588/729] Fix bug in MAD gain --- src/mlpack/methods/decision_tree/mad_gain.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 10016045a0..aae0439091 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -75,7 +75,7 @@ class MADGain Sum(values, begin, end, mean); mean /= (double) (end - begin); - mad = arma::accu(arma::abs(values - mean)); + mad = arma::accu(arma::abs(values.subvec(begin, end - 1) - mean)); mad /= (double) (end - begin); } From 0717855241c43f2e0a405d2897265061f3e8b463 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 17 Jun 2021 10:58:54 +0530 Subject: [PATCH 589/729] Added tests on LARS dataset and a test where tree is trained on MAD gain --- .../tests/decision_tree_regressor_test.cpp | 151 ++++++++++++------ 1 file changed, 103 insertions(+), 48 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 38f61ee7ca..9d9ac9d2c1 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -797,62 +797,61 @@ TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") // REQUIRE(accuracy > 0.75); // } -// /** -// * Test that we can build a decision tree using information gain on a simple -// * categorical dataset using weights, with low-weight noise added. -// */ -// TEST_CASE("CategoricalInformationGainWeightedBuildTest", "[DecisionTreeTest]") -// { -// arma::mat d; -// arma::Row l; -// data::DatasetInfo di; -// MockCategoricalData(d, l, di); +/** + * Test that we can build a decision tree using MAD gain on a simple + * categorical dataset using weights, with low-weight noise added. + */ +TEST_CASE("CategoricalInformationGainWeightedBuildTest_", "[DecisionTreeTest]") +{ + arma::mat d; + arma::rowvec r; + data::DatasetInfo di; + MockCategoricalData(d, r, di); -// // Split into a training set and a test set. -// arma::mat trainingData = d.cols(0, 1999); -// arma::mat testData = d.cols(2000, 3999); -// arma::Row trainingLabels = l.subvec(0, 1999); -// arma::Row testLabels = l.subvec(2000, 3999); + // Split into a training set and a test set. + arma::mat trainingData = d.cols(0, 1999); + arma::mat testData = d.cols(2000, 3999); + arma::rowvec trainingResponses = r.subvec(0, 1999); + arma::rowvec testResponses = r.subvec(2000, 3999); -// // Now create random points. -// arma::mat randomNoise(4, 2000); -// arma::Row randomLabels(2000); -// for (size_t i = 0; i < 2000; ++i) -// { -// randomNoise(0, i) = math::Random(); -// randomNoise(1, i) = math::Random(); -// randomNoise(2, i) = math::RandInt(4); -// randomNoise(3, i) = math::RandInt(2); -// randomLabels[i] = math::RandInt(5); -// } + // Now create random points. + arma::mat randomNoise(5, 2000); + arma::rowvec randomResponses(2000); + for (size_t i = 0; i < 2000; ++i) + { + randomNoise(0, i) = math::Random(); + randomNoise(1, i) = math::Random(-1, 1); + randomNoise(2, i) = math::Random(); + randomNoise(3, i) = math::RandInt(0, 2); + randomNoise(4, i) = math::RandInt(0, 5); + randomResponses[i] = math::Random(-10, 18); + } -// // Generate weights. -// arma::rowvec weights(4000); -// for (size_t i = 0; i < 2000; ++i) -// weights[i] = math::Random(0.9, 1.0); -// for (size_t i = 2000; i < 4000; ++i) -// weights[i] = math::Random(0.0, 0.001); + // Generate weights. + arma::rowvec weights(4000); + for (size_t i = 0; i < 2000; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = 2000; i < 4000; ++i) + weights[i] = math::Random(0.0, 0.001); -// arma::mat fullData = arma::join_rows(trainingData, randomNoise); -// arma::Row fullLabels = arma::join_rows(trainingLabels, randomLabels); + arma::mat fullData = arma::join_rows(trainingData, randomNoise); + arma::rowvec fullResponses = arma::join_rows(trainingResponses, + randomResponses); -// // Build the tree. -// DecisionTree tree(fullData, di, fullLabels, 5, weights, 10); + // Build the tree. + DecisionTreeRegressor tree(fullData, di, fullResponses, weights, + 10); -// // Now evaluate the accuracy of the tree. -// arma::Row predictions; -// tree.Classify(testData, predictions); + // Now evaluate the quality of predictions. + arma::rowvec predictions; + tree.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); -// size_t correct = 0; -// for (size_t i = 0; i < testData.n_cols; ++i) -// if (testLabels[i] == predictions[i]) -// ++correct; + REQUIRE(predictions.n_elem == testData.n_cols); -// // Make sure we got at least 70% accuracy. -// const double correctPct = double(correct) / double(testData.n_cols); -// REQUIRE(correctPct > 0.70); -// } + // Make sure we get reasonable rmse. + const double rmse = RMSE(predictions, testResponses); + REQUIRE(rmse < 1.0); +} /** * Test that the decision tree generalizes reasonably. @@ -1053,3 +1052,59 @@ TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") REQUIRE(d.NumLeaves() == 5); } + +/** + * Test that the tree builds correctly on unweighted numerical dataset. + */ +TEST_CASE("LARSDatasetTest", "[DecisionTreeRegressorTest]") +{ + arma::mat X; + arma::rowvec Y; + + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); + + arma::mat XTrain, XTest; + arma::rowvec YTrain, YTest; + data::Split(X, Y, XTrain, XTest, YTrain, YTest, 0.3); + + DecisionTreeRegressor<> tree(XTrain, YTrain, 5); + + arma::rowvec predictions; + tree.Predict(XTest, predictions); + + const double rmse = RMSE(predictions, YTest); + + REQUIRE(rmse < 1.0); +} + +/** + * Test that the tree builds correctly on weighted numerical dataset. + */ +TEST_CASE("LARSDatasetWeightedTest", "[DecisionTreeRegressorTest]") +{ + arma::mat X; + arma::rowvec Y; + + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); + + arma::mat XTrain, XTest; + arma::rowvec YTrain, YTest; + data::Split(X, Y, XTrain, XTest, YTrain, YTest, 0.3); + + arma::rowvec weights = arma::ones(XTrain.n_elem); + + DecisionTreeRegressor<> tree(XTrain, YTrain, weights, 5); + + arma::rowvec predictions; + tree.Predict(XTest, predictions); + + const double rmse = RMSE(predictions, YTest); + + REQUIRE(rmse < 1.0); +} From 0ff17398a50e88362a795420d8797b147ead9c1f Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 18 Jun 2021 17:59:18 +0530 Subject: [PATCH 590/729] Making non template functions as inline to avoid duplicate definition error --- src/mlpack/methods/decision_tree/utils.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/decision_tree/utils.hpp b/src/mlpack/methods/decision_tree/utils.hpp index 1928803e88..37c6453c56 100644 --- a/src/mlpack/methods/decision_tree/utils.hpp +++ b/src/mlpack/methods/decision_tree/utils.hpp @@ -15,7 +15,7 @@ /** * Calculates the weighted sum and total weight of labels. */ -void WeightedSum(const arma::rowvec& labels, +inline void WeightedSum(const arma::rowvec& labels, const arma::rowvec& weights, const size_t begin, const size_t end, @@ -88,7 +88,7 @@ void WeightedSum(const arma::rowvec& labels, /** * Sums up the labels vector. */ -void Sum(const arma::rowvec& labels, +inline void Sum(const arma::rowvec& labels, const size_t begin, const size_t end, double& mean) From 17ae3872fddab67c63554c54373022ee3f888a25 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 19 Jun 2021 22:47:23 +0530 Subject: [PATCH 591/729] =?UTF-8?q?Optimised=20MSEGain=20computation=20usi?= =?UTF-8?q?ng=20prefix=20sum=20of=20squares=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../best_binary_numeric_split.hpp | 33 +++ .../best_binary_numeric_split_impl.hpp | 235 +++++++++++++++++- .../decision_tree_regressor_impl.hpp | 9 +- src/mlpack/methods/decision_tree/mse_gain.hpp | 50 ++++ 4 files changed, 313 insertions(+), 14 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 6907edb943..9a888b3341 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -13,6 +13,7 @@ #define MLPACK_METHODS_DECISION_TREE_BEST_BINARY_NUMERIC_SPLIT_HPP #include +#include "mse_gain.hpp" namespace mlpack { namespace tree { @@ -117,6 +118,38 @@ class BestBinaryNumericSplit const AuxiliarySplitInfo& /* aux */); }; +/** +* Check if we can split a node. If we can split a node in a way that +* improves on 'bestGain', then we return the improved gain. Otherwise we +* return the value 'bestGain'. If a split is made, then splitInfo and aux +* may be modified. +* +* This overload is specialized only for MSEGain fitness function. +* +* @param bestGain Best gain seen so far (we'll only split if we find gain +* better than this). +* @param data The dimension of data points to check for a split in. +* @param responses Responses for each point. +* @param weights Weights associated with responses. +* @param minimumLeafSize Minimum number of points in a leaf node for +* splitting. +* @param minimumGainSplit Minimum gain split. +* @param splitInfo Stores split information on a successful split. +* @param aux Auxiliary split information, which may be modified on a +* successful split. +*/ +template<> +template +double BestBinaryNumericSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::rowvec& responses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& /* aux */); + } // namespace tree } // namespace mlpack diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 9a2f3cc3a8..bd94d5f064 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -260,12 +260,6 @@ double BestBinaryNumericSplit::SplitIfBetter( if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) continue; - /* TODO: The following function calculates the gain for each split each - time from scratch. This can be greatly improved using advanced - techniques like prefix sum and prefix sum of squares etc. This - will have drastic effects on runtime and is definitely something - we would want in future. - */ // Calculate the gain for the left and right child. const double leftGain = FitnessFunction::template Evaluate(sortedResponses, sortedWeights, 0, index); @@ -319,6 +313,235 @@ double BestBinaryNumericSplit::SplitIfBetter( return bestFoundGain; } +// Optimized version when fitness function is MSEGain. +template<> +template +double BestBinaryNumericSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const arma::rowvec& responses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& /* aux */) +{ + // First sanity check: if we don't have enough points, we can't split. + if (data.n_elem < (minimumLeafSize * 2)) + return DBL_MAX; + if (bestGain == 0.0) + return DBL_MAX; // It can't be outperformed. + + // Next, sort the data. + arma::uvec sortedIndices = arma::sort_index(data); + arma::rowvec sortedResponses(responses.n_elem); + arma::rowvec sortedWeights; + for (size_t i = 0; i < sortedResponses.n_elem; ++i) + sortedResponses[i] = responses[sortedIndices[i]]; + + // Sanity check: if the first element is the same as the last, we can't split + // in this dimension. + if (data[sortedIndices[0]] == data[sortedIndices[sortedIndices.n_elem - 1]]) + return DBL_MAX; + + // Only initialize if we are using weights. + if (UseWeights) + { + sortedWeights.set_size(sortedResponses.n_elem); + // The weights must keep the same order as the responses. + for (size_t i = 0; i < sortedResponses.n_elem; ++i) + sortedWeights[i] = weights[sortedIndices[i]]; + } + + double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); + bool improved = false; + // Force a minimum leaf size of 1 (empty children don't make sense). + const size_t minimum = std::max(minimumLeafSize, (size_t) 1); + + double totalWeight = 0.0; + double leftChildWeight = 0.0; + double rightChildWeight = 0.0; + double leftWeightedMean = 0.0; + double rightWeightedMean = 0.0; + double totalWeightedSumSquares = 0.0; + arma::rowvec weightedSumSquares; + + double leftMean = 0.0; + double rightMean = 0.0; + size_t leftChildSize = 0; + size_t rightChildSize = 0; + double totalSumSquares = 0.0; + arma::rowvec sumSquares; + + // Precomputing prefix sum of squares and prefix weighted sum of squares. + // This will be used by MSEGain::Evaluate to efficiently compute gain + // values for all possible splits. + if (UseWeights) + { + totalWeight = arma::accu(sortedWeights); + bestFoundGain *= totalWeight; + + weightedSumSquares.set_size(data.n_elem); + // Stores the weighted sum of squares till the previous index. + double prevWeightedSumSquares = 0.0; + + for (size_t i = 0; i < minimum - 1; ++i) + { + const double w = sortedWeights[i]; + const double x = sortedResponses[i]; + + // Calculating initial weighted mean of responses for the left child. + leftChildWeight += w; + leftWeightedMean += w * x; + weightedSumSquares[i] = prevWeightedSumSquares + w * x * x; + prevWeightedSumSquares += w * x * x; + } + if (leftChildWeight > 1e-9) + leftWeightedMean /= leftChildWeight; + + for (size_t i = minimum - 1; i < data.n_elem; ++i) + { + const double w = sortedWeights[i]; + const double x = sortedResponses[i]; + + // Calculating initial weighted mean of responses for the right child. + rightChildWeight += w; + rightWeightedMean += w * x; + weightedSumSquares[i] = prevWeightedSumSquares + w * x * x; + prevWeightedSumSquares += w * x * x; + } + if (rightChildWeight > 1e-9) + rightWeightedMean /= rightChildWeight; + + totalWeightedSumSquares = prevWeightedSumSquares; + } + else + { + bestFoundGain *= data.n_elem; + + sumSquares.set_size(data.n_elem); + // Stores the sum of squares till the previous index. + double prevSumSquares = 0.0; + + for (size_t i = 0; i < minimum - 1; ++i) + { + const double x = sortedResponses[i]; + + // Calculating the initial mean of responses for the left child. + ++leftChildSize; + leftMean += x; + sumSquares[i] = prevSumSquares + x * x; + prevSumSquares += x * x; + } + if (leftChildSize) + leftMean /= (double) leftChildSize; + + for (size_t i = minimum - 1; i < data.n_elem; ++i) + { + const double x = sortedResponses[i]; + + // Calculating the initial mean of responses for the right child. + rightChildSize++; + rightMean += x; + sumSquares[i] = prevSumSquares + x * x; + prevSumSquares += x * x; + } + if (rightChildSize) + rightMean /= (double) rightChildSize; + + totalSumSquares = prevSumSquares; + } + + // Loop through all possible split points, choosing the best one. + for (size_t index = minimum; index < data.n_elem - minimum + 1; ++index) + { + if (UseWeights) + { + // Updating the weighted mean for both childs for each index. + const double w = sortedWeights[index - 1]; + const double x = sortedResponses[index - 1]; + leftWeightedMean = (leftWeightedMean * leftChildWeight + w * x) + / (leftChildWeight + w); + leftChildWeight += w; + + rightWeightedMean = (rightWeightedMean * rightChildWeight - w * x) + / (rightChildWeight - w); + rightChildWeight -= w; + } + else + { + // Updating the mean for both childs for each index. + const double x = sortedResponses[index - 1]; + leftMean = (leftMean * (double) leftChildSize + x) / + (double) (leftChildSize + 1); + ++leftChildSize; + + rightMean = (rightMean * (double) rightChildSize - x) / + (double) (rightChildSize - 1); + --rightChildSize; + } + + // Make sure that the value has changed. + if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) + continue; + + // Calculate the gain for the left and right child. + const double leftGain = UseWeights ? + MSEGain::Evaluate(weightedSumSquares[index - 1], + leftWeightedMean, leftChildWeight) : + MSEGain::Evaluate(sumSquares[index - 1], leftMean, leftChildSize); + const double rightGain = UseWeights ? + MSEGain::Evaluate( + totalWeightedSumSquares - weightedSumSquares[index - 1], + rightWeightedMean, rightChildWeight) : + MSEGain::Evaluate(totalSumSquares - sumSquares[index - 1], + rightMean, rightChildSize); + + double gain; + if (UseWeights) + { + gain = leftChildWeight * leftGain + rightChildWeight * rightGain; + } + else + { + // Calculate the gain at this split point. + gain = double(leftChildSize) * leftGain + + double(rightChildSize) * rightGain; + } + + // Corner case: is this the best possible split? + if (gain >= 0.0) + { + // We can take a shortcut: no split will be better than this, so just + // take this one. The actual split value will be halfway between the + // value at index - 1 and index. + splitInfo = (data[sortedIndices[index - 1]] + + data[sortedIndices[index]]) / 2.0; + + return gain; + } + if (gain > bestFoundGain) + { + // We still have a better split. + bestFoundGain = gain; + splitInfo = (data[sortedIndices[index - 1]] + + data[sortedIndices[index]]) / 2.0; + improved = true; + } + } + // If we didn't improve, return the original gain exactly as we got it + // (without introducing floating point errors). + if (!improved) + return DBL_MAX; + + if (UseWeights) + bestFoundGain /= totalWeight; + else + bestFoundGain /= data.n_elem; + + return bestFoundGain; +} + template template size_t BestBinaryNumericSplit::CalculateDirection( diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index d74c7e4f7a..d10c83e395 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -761,9 +761,7 @@ double DecisionTreeRegressor( responses.subvec(begin, begin + count - 1), - UseWeights ? weights.subvec(begin, begin + count - 1) : weights); - std::cout << "Number of points in leaf: " << count << - " Prediction: " << splitPointOrPrediction << std::endl; + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); } return -bestGain; @@ -829,7 +827,6 @@ double DecisionTreeRegressor( responses.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); - std::cout << "Number of points in leaf: " << count << - " Prediction: " << splitPointOrPrediction << std::endl; } return -bestGain; diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 44dadb574e..9f70fccb21 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -95,6 +95,56 @@ class MSEGain return Evaluate(values, weights, 0, values.n_elem); } + + /** + * Calculates the weighted mean squared error gain given the sum of squares + * and mean. + * + * X = array of values of size n. + * W = array of weights of size n. + * + * @f{eqnarray*}{ + * MSE = \sum\limits_{i=1}^n {W_i * {X_i}^2} - + * {\dfrac{\sum\limits_{j=1}^n W_j * X_j} + * {\sum\limits_{j=1}^n W_i}}^2 + * @f} + * + * @param weightedSumSquares Precomputed weighted sum of square + * (sum(Wi * Xi^2)) of values. + * @param weightedMean Precomputed weighted mean (sum(Wi * Xi) / sum(Wi)) of + * values. + * @param totalChildWeight Total weight of all the samples in that child. + */ + static double Evaluate(const double weightedSumSquares, + const double weightedMean, + const double totalChildWeight) + { + double mse = weightedSumSquares / totalChildWeight - + weightedMean * weightedMean; + return -mse; + } + + /** + * Calculates the mean squared error gain given the sum of squares and mean. + * + * X = array of values of size n. + * + * @f{eqnarray*}{ + * MSE = \sum\limits_{i=1}^n {X_i}^2 - + * {\dfrac{\sum\limits_{j=1}^n X_j}{n}}^2 + * @f} + * + * @param sumSquares Precomputed sum of square (sum(Xi^2)) of values. + * @param mean Precomputed mean (sum(Xi) / n) of values. + * @param childSize The total number of samples in that child. + */ + static double Evaluate(const double sumSquares, + const double mean, + const size_t childSize) + { + double mse = sumSquares / (double) childSize - mean * mean; + return -mse; + } }; } // namespace tree From db1fcdc26b6363cd7608b57b36c387fe1ab86918 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 10 May 2021 14:30:37 +0530 Subject: [PATCH 592/729] Amend RandomBinaryNumericSplit signature to support regression --- src/mlpack/tests/decision_tree_test.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 1412b70495..e5ad32a03b 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -385,7 +385,7 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); arma::rowvec weights(labels.n_elem); - arma::vec classProbabilities; + arma::vec classProbabilities(1); RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. @@ -395,12 +395,11 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") // This should make no difference because it won't split at all. const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 8, 1e-7, classProbabilities, aux); + labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); REQUIRE(gain == weightedGain); - REQUIRE(classProbabilities.n_elem == 0); } /** @@ -420,18 +419,17 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities; + arma::vec classProbabilities(1); RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities[0], aux, true); // Make sure there was no split. REQUIRE(gain == DBL_MAX); - REQUIRE(classProbabilities.n_elem == 0); } /** @@ -451,7 +449,7 @@ TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities, classProbabilities1; + arma::vec classProbabilities(1), classProbabilities1(1); BestBinaryNumericSplit::AuxiliarySplitInfo aux; RandomBinaryNumericSplit::AuxiliarySplitInfo aux1; From 442cb4284dc8454dd3a1193d48013aacf8df6c82 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 21 Jun 2021 21:46:08 +0530 Subject: [PATCH 593/729] Removed headers from csv and fixed loading of boston dataset --- .../tests/data/boston_housing_price.csv | 1 - .../data/boston_housing_price_responses.csv | 1 - src/mlpack/tests/test_function_tools.hpp | 31 ++++++++++--------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/mlpack/tests/data/boston_housing_price.csv b/src/mlpack/tests/data/boston_housing_price.csv index 5c0d211062..50aadfc932 100644 --- a/src/mlpack/tests/data/boston_housing_price.csv +++ b/src/mlpack/tests/data/boston_housing_price.csv @@ -1,4 +1,3 @@ -0,1,2,3,4,5,6,7,8,9,10,11,12 0.00632,18.0,2.31,0,0.538,6.575,65.2,4.09,1,296.0,15.3,396.9,4.98 0.02731,0.0,7.07,0,0.469,6.421,78.9,4.9671,2,242.0,17.8,396.9,9.14 0.02729,0.0,7.07,0,0.469,7.185,61.1,4.9671,2,242.0,17.8,392.83,4.03 diff --git a/src/mlpack/tests/data/boston_housing_price_responses.csv b/src/mlpack/tests/data/boston_housing_price_responses.csv index fd7ad517aa..2a6908a56b 100644 --- a/src/mlpack/tests/data/boston_housing_price_responses.csv +++ b/src/mlpack/tests/data/boston_housing_price_responses.csv @@ -1,4 +1,3 @@ -0 24.0 21.6 34.7 diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index 0233402506..7b9eec84d4 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -97,21 +97,24 @@ inline void LoadBostonHousingDataset(arma::mat& trainData, data::Split(dataset, responses, trainData, testData, trainResponses, testResponses, 0.3); - // info.Type(3) = data::Datatype::categorical; - // info.Type(8) = data::Datatype::categorical; - // info.MapString("0", 3); - // info.MapString("1", 3); - // info.MapString("1", 8); - // info.MapString("2", 8); - // info.MapString("3", 8); - // info.MapString("4", 8); - // info.MapString("5", 8); - // info.MapString("6", 8); - // info.MapString("7", 8); - // info.MapString("8", 8); - // info.MapString("24", 8); - // std::cout << arma::unique(trainData.row(8)); + // Defining categorical deimensions. + info.Type(3) = data::Datatype::categorical; + info.Type(8) = data::Datatype::categorical; + + // Creating mappings for categorical dimensions. + info.MapString("0", 3); + info.MapString("1", 3); + + info.MapString("1", 8); + info.MapString("2", 8); + info.MapString("3", 8); + info.MapString("4", 8); + info.MapString("5", 8); + info.MapString("6", 8); + info.MapString("7", 8); + info.MapString("8", 8); + info.MapString("24", 8); } inline double RMSE(const arma::Row& predictions, From ffb68e0f7ce9c44e49430bc1e530a6da79c453df Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 21 Jun 2021 21:46:26 +0530 Subject: [PATCH 594/729] Debugging code --- .../all_categorical_split_impl.hpp | 10 +++++++ .../decision_tree_regressor_impl.hpp | 3 ++ .../tests/decision_tree_regressor_test.cpp | 30 +++++++------------ 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 0fbeeeec25..4f4e60ac68 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -49,6 +49,7 @@ double AllCategoricalSplit::SplitIfBetter( SplitInfoType& splitInfo, AuxiliarySplitInfo& /* aux */) { + std::cout << "Calling All categorical split " << numCategories << std::endl; // Count the number of elements in each potential child. const double epsilon = 1e-7; // Tolerance for floating-point errors. arma::Col counts(numCategories, arma::fill::zeros); @@ -73,20 +74,29 @@ double AllCategoricalSplit::SplitIfBetter( // If each child will have the minimum number of points in it, we can split. // Otherwise we can't. if (arma::min(counts) < minimumLeafSize) + { + std::cout << counts << std::endl; return DBL_MAX; + } // Calculate the gain of the split. First we have to calculate the labels // that would be assigned to each child. arma::uvec childPositions(numCategories, arma::fill::zeros); std::vector> childLabels(numCategories); std::vector> childWeights(numCategories); + + std::cout << counts << std::endl; + std::cout << "Num categories: " << numCategories << std::endl; for (size_t i = 0; i < numCategories; ++i) { + std::cout << i; // Labels and weights should have same length. childLabels[i].zeros(counts[i]); + if (numCategories == 9) std::cout << "Labels initialized\n"; if (UseWeights) childWeights[i].zeros(counts[i]); } + std::cout << "\n"; // Extract labels for each child. for (size_t i = 0; i < data.n_elem; ++i) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index d10c83e395..8f4ebb830e 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -135,6 +135,7 @@ DecisionTreeRegressor::type; using TrueWeightsType = typename std::decay::type; + std::cout << "Data copying begin\n"; // Copy or move data. TrueMatType tmpData(std::move(data)); TrueResponsesType tmpResponses(std::move(responses)); @@ -142,6 +143,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, @@ -631,6 +633,7 @@ double DecisionTreeRegressor(355); LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, info); + arma::rowvec weights(trainResponses.n_elem, arma::fill::ones); + std::cout << weights.n_elem << " " << trainResponses.n_elem << std::endl; + + std::cout << "NumMappings: " << info.NumMappings(8) << std::endl; + std::cout << info.Type(8) << std::endl; + // Build decision tree. - DecisionTreeRegressor d(trainData, info, trainResponses); + // DecisionTreeRegressor<> d(trainData, info, trainResponses, 1); + std::cout << "***********************************\n"; + DecisionTreeRegressor<> wd(trainData, info, trainResponses, weights); - // Get the predicted test responses. - arma::Row predictions; - d.Predict(testData, predictions); - - REQUIRE(predictions.n_elem == testData.n_cols); - - // Figure out rmse. - double rmse = RMSE(predictions, testResponses); - - // REQUIRE(rmse < 9.21); - // std::cout << predictions << std::endl << testResponses; - arma::Row trainPred; - d.Predict(trainData, trainPred); - // std::cout << trainPred; - - std::cout << "Train RMSE: " << RMSE(trainResponses, trainPred) << std::endl; + std::cout << "training done\n"; } /** From 60c2239210343ecd7f0c7ddb8dc4b370e2bbff43 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 01:09:55 +0530 Subject: [PATCH 595/729] Fixed tests from the crazy merge that unexpectedly happened --- src/mlpack/tests/decision_tree_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index e5ad32a03b..1785e05c41 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -395,7 +395,7 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") // This should make no difference because it won't split at all. const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - labels, 2, weights, 8, 1e-7, classProbabilities[0], aux); + labels, 2, weights, 8, 1e-7, classProbabilities, aux); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); @@ -419,13 +419,13 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities(1); + arma::vec classProbabilities; RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 2, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities[0], + bestGain, values, labels, 2, weights, 10, 1e-7, classProbabilities, aux, true); // Make sure there was no split. @@ -449,7 +449,7 @@ TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]") labels[i + 1] = 1; } - arma::vec classProbabilities(1), classProbabilities1(1); + arma::vec classProbabilities, classProbabilities1; BestBinaryNumericSplit::AuxiliarySplitInfo aux; RandomBinaryNumericSplit::AuxiliarySplitInfo aux1; From 8d1c188883c3561efb37055131e83286873743fc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 01:11:13 +0530 Subject: [PATCH 596/729] Fixed loading the boston housing data (finally) :) --- src/mlpack/tests/test_function_tools.hpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index 7b9eec84d4..0210b7973d 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -90,6 +90,11 @@ inline void LoadBostonHousingDataset(arma::mat& trainData, arma::mat dataset; arma::rowvec responses; + // Defining categorical deimensions. + info.SetDimensionality(13); + info.Type(3) = data::Datatype::categorical; + info.Type(8) = data::Datatype::categorical; + if (!data::Load("boston_housing_price.csv", dataset, info)) FAIL("Cannot load test dataset boston_housing_price.csv!"); if (!data::Load("boston_housing_price_responses.csv", responses)) @@ -97,24 +102,6 @@ inline void LoadBostonHousingDataset(arma::mat& trainData, data::Split(dataset, responses, trainData, testData, trainResponses, testResponses, 0.3); - - // Defining categorical deimensions. - info.Type(3) = data::Datatype::categorical; - info.Type(8) = data::Datatype::categorical; - - // Creating mappings for categorical dimensions. - info.MapString("0", 3); - info.MapString("1", 3); - - info.MapString("1", 8); - info.MapString("2", 8); - info.MapString("3", 8); - info.MapString("4", 8); - info.MapString("5", 8); - info.MapString("6", 8); - info.MapString("7", 8); - info.MapString("8", 8); - info.MapString("24", 8); } inline double RMSE(const arma::Row& predictions, From 9539af8caef3691765b1897ba56896b7406de73b Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 01:14:55 +0530 Subject: [PATCH 597/729] Removed the debugging code and reverted back to the previous version. --- .../all_categorical_split_impl.hpp | 11 +------ .../decision_tree_regressor_impl.hpp | 4 --- .../tests/decision_tree_regressor_test.cpp | 30 ++++++++++++------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 4f4e60ac68..32650df507 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -49,7 +49,6 @@ double AllCategoricalSplit::SplitIfBetter( SplitInfoType& splitInfo, AuxiliarySplitInfo& /* aux */) { - std::cout << "Calling All categorical split " << numCategories << std::endl; // Count the number of elements in each potential child. const double epsilon = 1e-7; // Tolerance for floating-point errors. arma::Col counts(numCategories, arma::fill::zeros); @@ -74,29 +73,21 @@ double AllCategoricalSplit::SplitIfBetter( // If each child will have the minimum number of points in it, we can split. // Otherwise we can't. if (arma::min(counts) < minimumLeafSize) - { - std::cout << counts << std::endl; return DBL_MAX; - } // Calculate the gain of the split. First we have to calculate the labels // that would be assigned to each child. arma::uvec childPositions(numCategories, arma::fill::zeros); std::vector> childLabels(numCategories); std::vector> childWeights(numCategories); - - std::cout << counts << std::endl; - std::cout << "Num categories: " << numCategories << std::endl; + for (size_t i = 0; i < numCategories; ++i) { - std::cout << i; // Labels and weights should have same length. childLabels[i].zeros(counts[i]); - if (numCategories == 9) std::cout << "Labels initialized\n"; if (UseWeights) childWeights[i].zeros(counts[i]); } - std::cout << "\n"; // Extract labels for each child. for (size_t i = 0; i < data.n_elem; ++i) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 8f4ebb830e..599b9a0978 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -135,15 +135,12 @@ DecisionTreeRegressor::type; using TrueWeightsType = typename std::decay::type; - std::cout << "Data copying begin\n"; - // Copy or move data. TrueMatType tmpData(std::move(data)); TrueResponsesType tmpResponses(std::move(responses)); TrueWeightsType tmpWeights(std::move(weights)); // Set the correct dimensionality for the dimension selector. dimensionSelector.Dimensions() = tmpData.n_rows; - std::cout << "Pre training!\n"; // Pass off work to the weighted Train() method. Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, @@ -633,7 +630,6 @@ double DecisionTreeRegressor(355); LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, info); - arma::rowvec weights(trainResponses.n_elem, arma::fill::ones); - std::cout << weights.n_elem << " " << trainResponses.n_elem << std::endl; - - std::cout << "NumMappings: " << info.NumMappings(8) << std::endl; - std::cout << info.Type(8) << std::endl; - // Build decision tree. - // DecisionTreeRegressor<> d(trainData, info, trainResponses, 1); - std::cout << "***********************************\n"; - DecisionTreeRegressor<> wd(trainData, info, trainResponses, weights); + DecisionTreeRegressor d(trainData, info, trainResponses); - std::cout << "training done\n"; + // Get the predicted test responses. + arma::Row predictions; + d.Predict(testData, predictions); + + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out rmse. + double rmse = RMSE(predictions, testResponses); + + // REQUIRE(rmse < 9.21); + // std::cout << predictions << std::endl << testResponses; + arma::Row trainPred; + d.Predict(trainData, trainPred); + // std::cout << trainPred; + + std::cout << "Train RMSE: " << RMSE(trainResponses, trainPred) << std::endl; } /** From 561c14062d3f8a164d8b66f944e0f64143d23ddc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 10:50:05 +0530 Subject: [PATCH 598/729] Removed numClasses from regression tree codebase --- .../decision_tree/all_categorical_split.hpp | 41 +++++- .../all_categorical_split_impl.hpp | 126 ++++++++++++++---- .../best_binary_numeric_split_impl.hpp | 2 + .../decision_tree/decision_tree_regressor.hpp | 4 - .../decision_tree_regressor_impl.hpp | 33 ++--- src/mlpack/methods/decision_tree/mad_gain.hpp | 1 - src/mlpack/methods/decision_tree/mse_gain.hpp | 1 - .../random_binary_numeric_split_impl.hpp | 2 + .../tests/decision_tree_regressor_test.cpp | 50 +++---- src/mlpack/tests/decision_tree_test.cpp | 6 +- 10 files changed, 187 insertions(+), 79 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index ed265bba89..13911887a9 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -40,6 +40,8 @@ class AllCategoricalSplit * aux may be modified. For this particular split type, aux will be empty * and splitInfo will store the number of children of the node. * + * This overload is used only for classification. + * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). * @param data The dimension of data points to check for a split in. @@ -55,7 +57,7 @@ class AllCategoricalSplit * successful split. */ template + typename WeightVecType> static double SplitIfBetter( const double bestGain, const VecType& data, @@ -65,7 +67,42 @@ class AllCategoricalSplit const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - SplitInfoType& splitInfo, + arma::vec& splitInfo, + AuxiliarySplitInfo& aux); + + /** + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then splitInfo and + * aux may be modified. For this particular split type, aux will be empty + * and splitInfo will store the number of children of the node. + * + * This overload is used only for regression. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param numCategories Number of categories in the categorical data. + * @param responses Responses for each point. + * @param weights Weights associated with responses. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param splitInfo Stores split information on a successful split. + * @param minimumGainSplit Minimum gain split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + */ + template + static double SplitIfBetter( + const double bestGain, + const VecType& data, + const size_t numCategories, + const ResponsesType& responses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, AuxiliarySplitInfo& aux); /** diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 32650df507..cda19da51f 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -15,28 +15,10 @@ namespace mlpack { namespace tree { -/** - * Helper function to store split information. This is used for regression. - * payload contains the information to be stored in splitInfo. - */ -static void StoreSplitInfo(double& splitInfo, const double& payload) -{ - splitInfo = payload; -} - -/** - * Helper function to store split information. This is used for classification. - * payload contains the information to be stored in splitInfo. - */ -static void StoreSplitInfo(arma::vec& splitInfo, const double& payload) -{ - splitInfo.set_size(1); - splitInfo[0] = payload; -} - +// Overload used in classification. template template + typename WeightVecType> double AllCategoricalSplit::SplitIfBetter( const double bestGain, const VecType& data, @@ -46,14 +28,14 @@ double AllCategoricalSplit::SplitIfBetter( const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, - SplitInfoType& splitInfo, + arma::vec& splitInfo, AuxiliarySplitInfo& /* aux */) { // Count the number of elements in each potential child. const double epsilon = 1e-7; // Tolerance for floating-point errors. arma::Col counts(numCategories, arma::fill::zeros); - // If we are using weighted training, learn the weights for each child too. + // If we are using weighted training, split the weights for each child too. arma::vec childWeightSums; double sumWeight = 0.0; if (UseWeights) @@ -78,7 +60,7 @@ double AllCategoricalSplit::SplitIfBetter( // Calculate the gain of the split. First we have to calculate the labels // that would be assigned to each child. arma::uvec childPositions(numCategories, arma::fill::zeros); - std::vector> childLabels(numCategories); + std::vector> childLabels(numCategories); std::vector> childWeights(numCategories); for (size_t i = 0; i < numCategories; ++i) @@ -121,7 +103,103 @@ double AllCategoricalSplit::SplitIfBetter( if (overallGain > bestGain + minimumGainSplit + epsilon) { // This is better, so store it in splitInfo and return. - StoreSplitInfo(splitInfo, numCategories); + splitInfo.set_size(1); + splitInfo[0] = numCategories; + return overallGain; + } + + // Otherwise there was no improvement. + return DBL_MAX; +} + +// Overload used in regression. +template +template +double AllCategoricalSplit::SplitIfBetter( + const double bestGain, + const VecType& data, + const size_t numCategories, + const ResponsesType& responses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& /* aux */) +{ + // Count the number of elements in each potential child. + const double epsilon = 1e-7; // Tolerance for floating-point errors. + arma::Col counts(numCategories, arma::fill::zeros); + + // If we are using weighted training, split the weights for each child too. + arma::vec childWeightSums; + double sumWeight = 0.0; + if (UseWeights) + childWeightSums.zeros(numCategories); + + for (size_t i = 0; i < data.n_elem; ++i) + { + counts[(size_t) data[i]]++; + + if (UseWeights) + { + childWeightSums[(size_t) data[i]] += weights[i]; + sumWeight += weights[i]; + } + } + + // If each child will have the minimum number of points in it, we can split. + // Otherwise we can't. + if (arma::min(counts) < minimumLeafSize) + return DBL_MAX; + + // Calculate the gain of the split. First we have to calculate the labels + // that would be assigned to each child. + arma::uvec childPositions(numCategories, arma::fill::zeros); + std::vector childResponses(numCategories); + std::vector childWeights(numCategories); + + for (size_t i = 0; i < numCategories; ++i) + { + // Responses and weights should have same length. + childResponses[i].zeros(counts[i]); + if (UseWeights) + childWeights[i].zeros(counts[i]); + } + + // Extract labels for each child. + for (size_t i = 0; i < data.n_elem; ++i) + { + const size_t category = (size_t) data[i]; + + if (UseWeights) + { + childResponses[category][childPositions[category]] = responses[i]; + childWeights[category][childPositions[category]++] = weights[i]; + } + else + { + childResponses[category][childPositions[category]++] = responses[i]; + } + } + + double overallGain = 0.0; + for (size_t i = 0; i < counts.n_elem; ++i) + { + // Calculate the gain of this child. + const double childPct = UseWeights ? + double(childWeightSums[i]) / sumWeight : + double(counts[i]) / double(data.n_elem); + const double childGain = FitnessFunction::template Evaluate( + childResponses[i], childWeights[i]); + + overallGain += childPct * childGain; + } + + if (overallGain > bestGain + minimumGainSplit + epsilon) + { + // This is better, so store it in splitInfo and return. + splitInfo = numCategories; return overallGain; } diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index bd94d5f064..f16c25521b 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -15,6 +15,7 @@ namespace mlpack { namespace tree { +// Overload used for classification. template template double BestBinaryNumericSplit::SplitIfBetter( @@ -184,6 +185,7 @@ double BestBinaryNumericSplit::SplitIfBetter( return bestFoundGain; } +// Overload used for regression. template template double BestBinaryNumericSplit::SplitIfBetter( diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index d9996e727f..aed4529921 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -470,7 +470,6 @@ class DecisionTreeRegressor : * @param count Number of points in this node. * @param datasetInfo Type information for each dimension. * @param responses Responses for each training point. - * @param numClasses Number of classes in the dataset. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. @@ -482,7 +481,6 @@ class DecisionTreeRegressor : const size_t count, const data::DatasetInfo& datasetInfo, ResponsesType& responses, - const size_t numClasses, arma::rowvec& weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -499,7 +497,6 @@ class DecisionTreeRegressor : * this node. * @param count Number of points in this node. * @param responses Responses for each training point. - * @param numClasses Number of classes in the dataset. * @param minimumLeafSize Minimum number of points in each leaf node. * @param minimumGainSplit Minimum gain for the node to split. * @param maximumDepth Maximum depth for the tree. @@ -510,7 +507,6 @@ class DecisionTreeRegressor : const size_t begin, const size_t count, ResponsesType& responses, - const size_t numClasses, arma::rowvec& weights, const size_t minimumLeafSize, const double minimumGainSplit, diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 599b9a0978..d29bae904b 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -68,7 +68,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -104,7 +104,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpResponses, 0, weights, + Train(tmpData, 0, tmpData.n_cols, tmpResponses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -143,7 +143,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -185,7 +185,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpResponses, 0, tmpWeights, + Train(tmpData, 0, tmpData.n_cols, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -223,7 +223,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, 0, + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit); } @@ -266,7 +266,7 @@ DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpResponses, 0, tmpWeights, + Train(tmpData, 0, tmpData.n_cols, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -450,7 +450,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, - 0, weights, minimumLeafSize, minimumGainSplit, maximumDepth, + weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -488,7 +488,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, responses, 0, + return Train(tmpData, 0, tmpData.n_cols, tmpResponses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -535,7 +535,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, - 0, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -579,7 +579,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpResponses, 0, + return Train(tmpData, 0, tmpData.n_cols, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); } @@ -601,7 +601,6 @@ double DecisionTreeRegressor( responses.subvec(begin, begin + count - 1), - numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = datasetInfo.Dimensionality(); // This means "no split". const size_t end = dimensionSelector.End(); @@ -637,7 +635,6 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, datasetInfo, responses, numClasses, + currentCol - currentChildBegin, datasetInfo, responses, weights, currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, dimensionSelector); } @@ -743,7 +740,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, datasetInfo, responses, numClasses, + currentCol - currentChildBegin, datasetInfo, responses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, dimensionSelector); bestGain += double(childCounts[i]) / double(count) * (-childGain); @@ -782,7 +779,6 @@ double DecisionTreeRegressor( responses.subvec(begin, begin + count - 1), - numClasses, UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = data.n_rows; // This means "no split". @@ -889,7 +884,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, responses, numClasses, weights, + currentCol - currentChildBegin, responses, weights, currentCol - currentChildBegin, minimumGainSplit, maximumDepth - 1, dimensionSelector); } @@ -897,7 +892,7 @@ double DecisionTreeRegressorTrain(data, currentChildBegin, - currentCol - currentChildBegin, responses, numClasses, weights, + currentCol - currentChildBegin, responses, weights, minimumLeafSize, minimumGainSplit, maximumDepth - 1, dimensionSelector); bestGain += double(childCounts[i]) / double(count) * (-childGain); diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index aae0439091..8a2bf968b9 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -90,7 +90,6 @@ class MADGain */ template static double Evaluate(const arma::rowvec& values, - const size_t /* numClasses */, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 9f70fccb21..7d013cd9aa 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -86,7 +86,6 @@ class MSEGain */ template static double Evaluate(const arma::rowvec& values, - const size_t /* numClasses */, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 6a9db54a05..4d459798b1 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -17,6 +17,7 @@ namespace mlpack { namespace tree { +// Overload used for classification. template template double RandomBinaryNumericSplit::SplitIfBetter( @@ -136,6 +137,7 @@ double RandomBinaryNumericSplit::SplitIfBetter( return gain; } +// Overload used for regression. template template double RandomBinaryNumericSplit::SplitIfBetter( diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 9d9ac9d2c1..b2bbc37674 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -77,7 +77,7 @@ TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressorTest]") arma::rowvec responses; responses.ones(10); - REQUIRE(MSEGain::Evaluate(responses, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -88,10 +88,10 @@ TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); arma::rowvec responses; - REQUIRE(MSEGain::Evaluate(responses, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(responses, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -107,9 +107,9 @@ TEST_CASE("MSEGainHandCalculation", "[DecisionTreeRegressorTest]") // Hand calculated gain values. const double gain = -27.08999; const double weightedGain = -27.53960; - REQUIRE(MSEGain::Evaluate(responses, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, weights) == Approx(gain).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(responses, 0, weights) == + REQUIRE(MSEGain::Evaluate(responses, weights) == Approx(weightedGain).margin(1e-5)); } @@ -122,7 +122,7 @@ TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressorTest]") arma::rowvec responses; responses.ones(10); - REQUIRE(MADGain::Evaluate(responses, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -143,7 +143,7 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressorTest") // Calculated gain. const double calculatedGain = - MADGain::Evaluate(responses, 0, weights); + MADGain::Evaluate(responses, weights); REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); } @@ -155,10 +155,10 @@ TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); arma::rowvec responses; - REQUIRE(MADGain::Evaluate(responses, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MADGain::Evaluate(responses, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -174,9 +174,9 @@ TEST_CASE("MADGainHandCalculation", "[DecisionTreeRegressorTest]") // Hand calculated gain values. const double gain = -4.1; const double weightedGain = -3.8592; - REQUIRE(MADGain::Evaluate(responses, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, weights) == Approx(gain).margin(1e-5)); - REQUIRE(MADGain::Evaluate(responses, 0, weights) == + REQUIRE(MADGain::Evaluate(responses, weights) == Approx(weightedGain).margin(1e-5)); } @@ -203,12 +203,12 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictor, 2, responses, 0, weights, 3, 1e-7, splitInfo, aux); + bestGain, predictor, 2, responses, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictor, 2, - responses, 0, weights, 3, 1e-7, splitInfo, aux); + responses, weights, 3, 1e-7, splitInfo, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -234,9 +234,9 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 4, responses, 0, weights, 4, 1e-7, splitInfo, aux); + bestGain, predictors, 4, responses, weights, 4, 1e-7, splitInfo, aux); // Make sure it's not split. REQUIRE(gain == DBL_MAX); @@ -265,13 +265,13 @@ TEST_CASE("AllCategoricalSplitNoGainTest_", "[DecisionTreeRegressorTest]") AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 10, responses, 0, weights, 10, 1e-7, + bestGain, predictors, 10, responses, weights, 10, 1e-7, splitInfo, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictors, - 10, responses, 0, predictors, 10, 1e-7, splitInfo, aux); + 10, responses, weights, 10, 1e-7, splitInfo, aux); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); @@ -296,7 +296,7 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MADGain::Evaluate(responses, 0, weights); + const double bestGain = MADGain::Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( bestGain, predictors, responses, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = @@ -332,7 +332,7 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( bestGain, predictors, responses, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. @@ -366,7 +366,7 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 0, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( bestGain, predictors, responses, weights, 10, 1e-7, splitInfo, aux); @@ -390,7 +390,7 @@ TEST_CASE("RandomBinaryNumericSplitAlwaysSplit_", RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 2, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, responses, weights, 1, 1e-7, splitInfo, aux); const double weightedGain = @@ -417,7 +417,7 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest_", RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 2, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, responses, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. @@ -451,7 +451,7 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, 2, weights); + const double bestGain = MSEGain::Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, responses, weights, 10, 1e-7, splitInfo, aux, true); diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 1785e05c41..28ff10e1b6 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -485,17 +485,17 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest", "[DecisionTreeTest]") arma::rowvec weights(labels.n_elem); weights.ones(); - arma::vec classProbabilities(1); + arma::vec classProbabilities; AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. const double bestGain = GiniGain::Evaluate(labels, 3, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, values, 4, labels, 3, weights, 3, 1e-7, classProbabilities[0], + bestGain, values, 4, labels, 3, weights, 3, 1e-7, classProbabilities, aux); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, values, 4, - labels, 3, weights, 3, 1e-7, classProbabilities[0], aux); + labels, 3, weights, 3, 1e-7, classProbabilities, aux); // Make sure that a split was made. REQUIRE(gain > bestGain); From d0bb74468487456da12c882045bd0f82892c7569 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 12:16:35 +0530 Subject: [PATCH 599/729] Added remaining tests --- .../tests/decision_tree_regressor_test.cpp | 247 ++++++++---------- src/mlpack/tests/test_function_tools.hpp | 7 +- 2 files changed, 114 insertions(+), 140 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index b2bbc37674..7e395a2d67 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -648,45 +648,45 @@ TEST_CASE("CategoricalBuildTestWithWeight_", "[DecisionTreeRegressorTest]") * low-weighted data is random noise), and that the tree still builds correctly * enough to get good results. */ -// TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") -// { -// // Loading data. -// data::DatasetInfo info; -// arma::mat trainData, testData; -// arma::Row trainLabels, testLabels; -// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); +TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::rowvec trainResponses, testResponses; + LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, + info); -// // Add some noise. -// arma::mat noise(trainData.n_rows, 500, arma::fill::randu); -// arma::Row noiseLabels(500); -// for (size_t i = 0; i < noiseLabels.n_elem; ++i) -// noiseLabels[i] = 15 + math::Random(0, 10); // Random label. + // Add some noise. + arma::mat noise(trainData.n_rows, 500, arma::fill::randu); + arma::rowvec noiseResponses(500); + for (size_t i = 0; i < noiseResponses.n_elem; ++i) + noiseResponses[i] = 15 + math::Random(0, 10); // Random response. -// // Concatenate data matrices. -// arma::mat data = arma::join_rows(trainData, noise); -// arma::Row fullLabels = arma::join_rows(trainLabels, noiseLabels); + // Concatenate data matrices. + arma::mat data = arma::join_rows(trainData, noise); + arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); -// // Now set weights. -// arma::rowvec weights(trainData.n_cols + 500); -// for (size_t i = 0; i < trainData.n_cols; ++i) -// weights[i] = math::Random(0.9, 1.0); -// for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) -// weights[i] = math::Random(0.0, 0.01); // Low weights for false points. + // Now set weights. + arma::rowvec weights(trainData.n_cols + 500); + for (size_t i = 0; i < trainData.n_cols; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) + weights[i] = math::Random(0.0, 0.01); // Low weights for false points. -// // Now build the decision tree. I think the syntax is right here. -// DecisionTreeRegressor<> d(data, fullLabels, weights); + // Now build the decision tree. + DecisionTreeRegressor<> d(data, fullResponses, weights, 5); -// // Now we can check that we get good performance on the VC2 test set. -// arma::Row predictions; -// d.Predict(testData, predictions); + // Now we can check that we get good performance on the test set. + arma::rowvec predictions; + d.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); -// // Figure out the accuracy. -// double rmse = RMSE(predictions, testLabels); - -// REQUIRE(rmse < 9.21); -// } + // Figure out the accuracy. + double rmse = RMSE(predictions, testResponses); + REQUIRE(rmse < 5.0); +} /** * Test that we can build a decision tree on a simple categorical dataset using @@ -743,65 +743,56 @@ TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") REQUIRE(rmse < 1.5); } -// /** -// * Test that we can build a decision tree using weighted data (where the -// * low-weighted data is random noise) with information gain, and that the tree -// * still builds correctly enough to get good results. -// */ -// TEST_CASE("WeightedDecisionTreeInformationGainTest_", -// "[DecisionTreeRegressorTest]") -// { -// arma::mat dataset; -// arma::Row labels; -// if (!data::Load("vc2.csv", dataset)) -// FAIL("Cannot load test dataset vc2.csv!"); -// if (!data::Load("vc2_labels.txt", labels)) -// FAIL("Cannot load labels for vc2_labels.txt!"); +/** + * Test that we can build a decision tree using weighted data (where the + * low-weighted data is random noise) with MAD gain, and that the tree + * still builds correctly enough to get good results. + */ +TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::rowvec trainResponses, testResponses; + LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, + info); -// // Add some noise. -// arma::mat noise(dataset.n_rows, 1000, arma::fill::randu); -// arma::Row noiseLabels(1000); -// for (size_t i = 0; i < noiseLabels.n_elem; ++i) -// noiseLabels[i] = math::Random(0, 3); // Random label. + // Add some noise. + arma::mat noise(trainData.n_rows, 500, arma::fill::randu); + arma::rowvec noiseResponses(500); + for (size_t i = 0; i < noiseResponses.n_elem; ++i) + noiseResponses[i] = 15 + math::Random(0, 10); // Random response. -// // Concatenate data matrices. -// arma::mat data = arma::join_rows(dataset, noise); -// arma::Row fullLabels = arma::join_rows(labels, noiseLabels); + // Concatenate data matrices. + arma::mat data = arma::join_rows(trainData, noise); + arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); -// // Now set weights. -// arma::rowvec weights(dataset.n_cols + 1000); -// for (size_t i = 0; i < dataset.n_cols; ++i) -// weights[i] = math::Random(0.9, 1.0); -// for (size_t i = dataset.n_cols; i < dataset.n_cols + 1000; ++i) -// weights[i] = math::Random(0.0, 0.01); // Low weights for false points. + // Now set weights. + arma::rowvec weights(trainData.n_cols + 500); + for (size_t i = 0; i < trainData.n_cols; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) + weights[i] = math::Random(0.0, 0.01); // Low weights for false points. -// // Now build the decision tree. I think the syntax is right here. -// DecisionTreeRegressor d(data, fullLabels, weights); + // Now build the decision tree using MADGain. + DecisionTreeRegressor d(data, fullResponses, weights, 5); -// // Now we can check that we get good performance on the VC2 test set. -// arma::mat testData; -// arma::Row testLabels; -// if (!data::Load("vc2_test.csv", testData)) -// FAIL("Cannot load test dataset vc2_test.csv!"); -// if (!data::Load("vc2_test_labels.txt", testLabels)) -// FAIL("Cannot load labels for vc2_test_labels.txt!"); + // Now we can check that we get good performance on the test set. + arma::rowvec predictions; + d.Predict(testData, predictions); -// arma::Row predictions; -// d.Predict(testData, predictions); + REQUIRE(predictions.n_elem == testData.n_cols); -// REQUIRE(predictions.n_elem == testData.n_cols); - -// // Figure out the accuracy. -// double accuracy = R2Score(predictions, testLabels); - -// REQUIRE(accuracy > 0.75); -// } + // Figure out the accuracy. + double rmse = RMSE(predictions, testResponses); + REQUIRE(rmse < 5.5); +} /** * Test that we can build a decision tree using MAD gain on a simple * categorical dataset using weights, with low-weight noise added. */ -TEST_CASE("CategoricalInformationGainWeightedBuildTest_", "[DecisionTreeTest]") +TEST_CASE("CategoricalMADGainWeightedBuildTest", "[DecisionTreeRegressorTest]") { arma::mat d; arma::rowvec r; @@ -858,95 +849,77 @@ TEST_CASE("CategoricalInformationGainWeightedBuildTest_", "[DecisionTreeTest]") */ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") { - // Loading data. data::DatasetInfo info; arma::mat trainData, testData; arma::rowvec trainResponses, testResponses; - arma::rowvec weights = arma::ones(355); LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, info); + arma::rowvec weights = arma::ones(trainResponses.n_elem); // Build decision tree. - DecisionTreeRegressor d(trainData, info, trainResponses); + DecisionTreeRegressor<> d(trainData, info, trainResponses, 5); + DecisionTreeRegressor<> wd(trainData, info, trainResponses, weights, 5); // Get the predicted test responses. - arma::Row predictions; + arma::rowvec predictions; d.Predict(testData, predictions); REQUIRE(predictions.n_elem == testData.n_cols); // Figure out rmse. double rmse = RMSE(predictions, testResponses); + REQUIRE(rmse < 1.0); - // REQUIRE(rmse < 9.21); - // std::cout << predictions << std::endl << testResponses; - arma::Row trainPred; - d.Predict(trainData, trainPred); - // std::cout << trainPred; + // Reset the predictions. + predictions.zeros(); + wd.Predict(testData, predictions); - std::cout << "Train RMSE: " << RMSE(trainResponses, trainPred) << std::endl; + REQUIRE(predictions.n_elem == testData.n_cols); + + // Figure out rmse. + rmse = RMSE(predictions, testResponses); + REQUIRE(rmse < 4.0); } /** * Test that the decision tree generalizes reasonably when built on float data. */ -// TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") -// { -// // Loading data. -// data::DatasetInfo info; -// arma::mat trainData, testData; -// arma::Row trainLabels, testLabels; -// LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); +TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") +{ + // Loading data. + data::DatasetInfo info; + arma::fmat trainData, testData; + arma::rowvec trainLabels, testLabels; + LoadBostonHousingDataset(trainData, testData, trainLabels, testLabels, info); -// // Initialize an all-ones weight matrix. -// arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); + // Initialize an all-ones weight matrix. + arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); -// // Build decision tree. -// DecisionTreeRegressor<> d(trainData, trainLabels); -// DecisionTreeRegressor<> wd(trainData, trainLabels, weights); + // Build decision tree. + DecisionTreeRegressor<> d(trainData, trainLabels, 5); + DecisionTreeRegressor<> wd(trainData, trainLabels, weights, 5); -// // Get the predicted test labels. -// arma::Row predictions; -// d.Predict(testData, predictions); + // Get the predicted test labels. + arma::rowvec predictions; + d.Predict(testData, predictions); -// REQUIRE(predictions.n_elem == testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); -// // Figure out the rmse. -// double rmse = RMSE(predictions, testLabels); + // Figure out the rmse. + double rmse = RMSE(predictions, testLabels); + REQUIRE(rmse < 1.0); -// REQUIRE(rmse < 9.21); -// std::cout << R2Score(predictions, testLabels) << std::endl; + // Reset the prediction. + predictions.zeros(); + wd.Predict(testData, predictions); -// // Reset the prediction. -// predictions.zeros(); -// wd.Predict(testData, predictions); + REQUIRE(predictions.n_elem == testData.n_cols); -// REQUIRE(predictions.n_elem == testData.n_cols); - -// // Figure out the rmse. -// double wdrmse = RMSE(predictions, testLabels); - -// REQUIRE(wdrmse < 9.21); -// } - -// TEST_CASE("DecisionTreeRegressorEnergyTest", "[DecisionTreeRegressorTest]") -// { -// arma::mat m; -// if (!data::Load("energydata_complete.csv", m)) -// FAIL("Cannot load dataset energydata_complete.csv!"); - -// arma::rowvec r = m.row(0); -// m.shed_row(0); - -// DecisionTreeRegressor<> d(m, r, 1, 0.0, 0); - -// arma::rowvec p; -// d.Predict(m, p); - -// const double mse = arma::accu(arma::square(p - r)) / p.n_elem; -// REQUIRE(mse == Approx(0.0).epsilon(1e-4)); -// } + // Figure out the rmse. + double wdrmse = RMSE(predictions, testLabels); + REQUIRE(wdrmse < 4.0); +} /** * Test that the tree is able to perfectly fit all the obvious splits present diff --git a/src/mlpack/tests/test_function_tools.hpp b/src/mlpack/tests/test_function_tools.hpp index 0210b7973d..ede3a44828 100644 --- a/src/mlpack/tests/test_function_tools.hpp +++ b/src/mlpack/tests/test_function_tools.hpp @@ -81,13 +81,14 @@ inline void LogisticRegressionTestData(arma::mat& data, } } -inline void LoadBostonHousingDataset(arma::mat& trainData, - arma::mat& testData, +template +void LoadBostonHousingDataset(MatType& trainData, + MatType& testData, arma::rowvec& trainResponses, arma::rowvec& testResponses, data::DatasetInfo& info) { - arma::mat dataset; + MatType dataset; arma::rowvec responses; // Defining categorical deimensions. From fccba9fb52fdb9fa84ee554d41583a2da360d146 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 12:47:35 +0530 Subject: [PATCH 600/729] Reogranised tests for readability and updated tolerances for some tests --- .../tests/decision_tree_regressor_test.cpp | 463 +++++++++--------- 1 file changed, 236 insertions(+), 227 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 7e395a2d67..3624216f65 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -579,6 +579,176 @@ TEST_CASE("PerfectTrainingSetWithWeight_", "[DecisionTreeRegressorTest]") } } +/** + * Test that the tree is able to perfectly fit all the obvious splits present + * in the data. + * + * | + * | + * 2 | xxxxxx + * | + * | + * 1 | xxxxxx xxxxxx + * | + * | + * 0 |xxxxxx xxxxxx + * |___________________________________ + */ +TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset; + arma::rowvec responses; + arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; + + CreateMultiSplitData(dataset, responses, 1000, values); + + arma::rowvec weights(responses.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); + arma::rowvec preds; + d.Predict(dataset, preds); + + // Ensure that the predictions are perfect. + for (size_t i = 0; i < responses.n_elem; ++i) + REQUIRE(preds[i] == responses[i]); + + // Ensure that a split is made only when required and no redundant splits are + // made. + REQUIRE(d.NumLeaves() == 5); +} + +/** + * Test that the tree is able to perfectly fit all the obvious splits present + * in the data. Same test as above, but with less data. + */ +TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset; + arma::rowvec responses; + arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; + + CreateMultiSplitData(dataset, responses, 100, values); + + arma::rowvec weights(responses.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); + arma::rowvec preds; + d.Predict(dataset, preds); + + // Ensure that the predictions are perfect. + for (size_t i = 0; i < responses.n_elem; ++i) + REQUIRE(preds[i] == responses[i]); + + // Ensure that a split is made only when required and no redundant splits are + // made. + REQUIRE(d.NumLeaves() == 5); +} + +/** + * Test that the tree is able to perfectly fit all the obvious splits present + * in the data. + * + * | + * 20 | xxxxxx + * | + * | + * 15 | xxxxxx + * | + * | + * 10 | xxxxxx + * | + * | + * 5 | xxxxxx + * | + * | + * 0 |xxxxxx + * |________________________________________ + */ +TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") +{ + arma::mat dataset; + arma::Row responses; + arma::rowvec values = {0.0, 5.0, 10.0, 15.0, 20.0}; + + CreateMultiSplitData(dataset, responses, 500, values); + + arma::rowvec weights(responses.n_elem); + weights.ones(); + + // Minimum leaf size of 1. + DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); + arma::rowvec preds; + d.Predict(dataset, preds); + + // Ensure that the predictions are perfect. + for (size_t i = 0; i < responses.n_elem; ++i) + REQUIRE(preds[i] == responses[i]); + + // Ensure that a split is made only when required and no redundant splits are + // made. + REQUIRE(d.NumLeaves() == 5); +} + +/** + * Test that the tree builds correctly on unweighted numerical dataset. + */ +TEST_CASE("NumericalBuildTest", "[DecisionTreeRegressorTest]") +{ + arma::mat X; + arma::rowvec Y; + + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); + + arma::mat XTrain, XTest; + arma::rowvec YTrain, YTest; + data::Split(X, Y, XTrain, XTest, YTrain, YTest, 0.3); + + DecisionTreeRegressor<> tree(XTrain, YTrain, 5); + + arma::rowvec predictions; + tree.Predict(XTest, predictions); + + // Ensuring a decent performance. + const double rmse = RMSE(predictions, YTest); + REQUIRE(rmse < 1.0); +} + +/** + * Test that the tree builds correctly on weighted numerical dataset. + */ +TEST_CASE("NumericalBuildTestWithWeights", "[DecisionTreeRegressorTest]") +{ + arma::mat X; + arma::rowvec Y; + + if (!data::Load("lars_dependent_x.csv", X)) + FAIL("Cannot load dataset lars_dependent_x.csv"); + if (!data::Load("lars_dependent_y.csv", Y)) + FAIL("Cannot load dataset lars_dependent_y.csv"); + + arma::mat XTrain, XTest; + arma::rowvec YTrain, YTest; + data::Split(X, Y, XTrain, XTest, YTrain, YTest, 0.3); + + arma::rowvec weights = arma::ones(XTrain.n_elem); + + DecisionTreeRegressor<> tree(XTrain, YTrain, weights, 5); + + arma::rowvec predictions; + tree.Predict(XTest, predictions); + + // Ensuring a decent performance. + const double rmse = RMSE(predictions, YTest); + REQUIRE(rmse < 1.0); +} + /** * Test that we can build a decision tree on a simple categorical dataset. */ @@ -643,51 +813,6 @@ TEST_CASE("CategoricalBuildTestWithWeight_", "[DecisionTreeRegressorTest]") REQUIRE(rmse < 1.0); } -/** - * Test that we can build a decision tree using weighted data (where the - * low-weighted data is random noise), and that the tree still builds correctly - * enough to get good results. - */ -TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") -{ - // Loading data. - data::DatasetInfo info; - arma::mat trainData, testData; - arma::rowvec trainResponses, testResponses; - LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, - info); - - // Add some noise. - arma::mat noise(trainData.n_rows, 500, arma::fill::randu); - arma::rowvec noiseResponses(500); - for (size_t i = 0; i < noiseResponses.n_elem; ++i) - noiseResponses[i] = 15 + math::Random(0, 10); // Random response. - - // Concatenate data matrices. - arma::mat data = arma::join_rows(trainData, noise); - arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); - - // Now set weights. - arma::rowvec weights(trainData.n_cols + 500); - for (size_t i = 0; i < trainData.n_cols; ++i) - weights[i] = math::Random(0.9, 1.0); - for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) - weights[i] = math::Random(0.0, 0.01); // Low weights for false points. - - // Now build the decision tree. - DecisionTreeRegressor<> d(data, fullResponses, weights, 5); - - // Now we can check that we get good performance on the test set. - arma::rowvec predictions; - d.Predict(testData, predictions); - - REQUIRE(predictions.n_elem == testData.n_cols); - - // Figure out the accuracy. - double rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 5.0); -} - /** * Test that we can build a decision tree on a simple categorical dataset using * weights, with low-weight noise added. @@ -743,51 +868,6 @@ TEST_CASE("CategoricalWeightedBuildTest_", "[DecisionTreeRegressorTest]") REQUIRE(rmse < 1.5); } -/** - * Test that we can build a decision tree using weighted data (where the - * low-weighted data is random noise) with MAD gain, and that the tree - * still builds correctly enough to get good results. - */ -TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") -{ - // Loading data. - data::DatasetInfo info; - arma::mat trainData, testData; - arma::rowvec trainResponses, testResponses; - LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, - info); - - // Add some noise. - arma::mat noise(trainData.n_rows, 500, arma::fill::randu); - arma::rowvec noiseResponses(500); - for (size_t i = 0; i < noiseResponses.n_elem; ++i) - noiseResponses[i] = 15 + math::Random(0, 10); // Random response. - - // Concatenate data matrices. - arma::mat data = arma::join_rows(trainData, noise); - arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); - - // Now set weights. - arma::rowvec weights(trainData.n_cols + 500); - for (size_t i = 0; i < trainData.n_cols; ++i) - weights[i] = math::Random(0.9, 1.0); - for (size_t i = trainData.n_cols; i < trainData.n_cols + 500; ++i) - weights[i] = math::Random(0.0, 0.01); // Low weights for false points. - - // Now build the decision tree using MADGain. - DecisionTreeRegressor d(data, fullResponses, weights, 5); - - // Now we can check that we get good performance on the test set. - arma::rowvec predictions; - d.Predict(testData, predictions); - - REQUIRE(predictions.n_elem == testData.n_cols); - - // Figure out the accuracy. - double rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 5.5); -} - /** * Test that we can build a decision tree using MAD gain on a simple * categorical dataset using weights, with low-weight noise added. @@ -829,7 +909,7 @@ TEST_CASE("CategoricalMADGainWeightedBuildTest", "[DecisionTreeRegressorTest]") arma::rowvec fullResponses = arma::join_rows(trainingResponses, randomResponses); - // Build the tree. + // Build the tree using MAD gain. DecisionTreeRegressor tree(fullData, di, fullResponses, weights, 10); @@ -879,7 +959,7 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") // Figure out rmse. rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 4.0); + REQUIRE(rmse < 1.0); } /** @@ -918,166 +998,95 @@ TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") // Figure out the rmse. double wdrmse = RMSE(predictions, testLabels); - REQUIRE(wdrmse < 4.0); + REQUIRE(wdrmse < 1.0); } /** - * Test that the tree is able to perfectly fit all the obvious splits present - * in the data. - * - * | - * | - * 2 | xxxxxx - * | - * | - * 1 | xxxxxx xxxxxx - * | - * | - * 0 |xxxxxx xxxxxx - * |___________________________________ + * Test that we can build a decision tree using weighted data (where the + * low-weighted data is random noise), and that the tree still builds correctly + * enough to get good results. */ -TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]") +TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") { - arma::mat dataset; - arma::rowvec responses; - arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::rowvec trainResponses, testResponses; + LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, + info); - CreateMultiSplitData(dataset, responses, 1000, values); + // Add some noise. + arma::mat noise(trainData.n_rows, 200, arma::fill::randu); + arma::rowvec noiseResponses(200); + for (size_t i = 0; i < noiseResponses.n_elem; ++i) + noiseResponses[i] = 15 + math::Random(0, 10); // Random response. - arma::rowvec weights(responses.n_elem); - weights.ones(); + // Concatenate data matrices. + arma::mat data = arma::join_rows(trainData, noise); + arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); - // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); - arma::rowvec preds; - d.Predict(dataset, preds); + // Now set weights. + arma::rowvec weights(trainData.n_cols + 200); + for (size_t i = 0; i < trainData.n_cols; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = trainData.n_cols; i < trainData.n_cols + 200; ++i) + weights[i] = math::Random(0.0, 0.01); // Low weights for false points. - for (size_t i = 0; i < responses.n_elem; ++i) - REQUIRE(preds[i] == responses[i]); - - REQUIRE(d.NumLeaves() == 5); -} - -/** - * Test that the tree is able to perfectly fit all the obvious splits present - * in the data. Same test as above, but with less data. - */ -TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset; - arma::rowvec responses; - arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0}; - - CreateMultiSplitData(dataset, responses, 100, values); - - arma::rowvec weights(responses.n_elem); - weights.ones(); - - // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); - arma::rowvec preds; - d.Predict(dataset, preds); - - for (size_t i = 0; i < responses.n_elem; ++i) - REQUIRE(preds[i] == responses[i]); - - REQUIRE(d.NumLeaves() == 5); -} - -/** - * Test that the tree is able to perfectly fit all the obvious splits present - * in the data. - * - * | - * 20 | xxxxxx - * | - * | - * 15 | xxxxxx - * | - * | - * 10 | xxxxxx - * | - * | - * 5 | xxxxxx - * | - * | - * 0 |xxxxxx - * |________________________________________ - */ -TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]") -{ - arma::mat dataset; - arma::Row responses; - arma::rowvec values = {0.0, 5.0, 10.0, 15.0, 20.0}; - - CreateMultiSplitData(dataset, responses, 500, values); - - arma::rowvec weights(responses.n_elem); - weights.ones(); - - // Minimum leaf size of 1. - DecisionTreeRegressor<> d(dataset, responses, weights, 2, 0.0); - arma::rowvec preds; - d.Predict(dataset, preds); - - for (size_t i = 0; i < responses.n_elem; ++i) - REQUIRE(preds[i] == responses[i]); - - REQUIRE(d.NumLeaves() == 5); -} - -/** - * Test that the tree builds correctly on unweighted numerical dataset. - */ -TEST_CASE("LARSDatasetTest", "[DecisionTreeRegressorTest]") -{ - arma::mat X; - arma::rowvec Y; - - if (!data::Load("lars_dependent_x.csv", X)) - FAIL("Cannot load dataset lars_dependent_x.csv"); - if (!data::Load("lars_dependent_y.csv", Y)) - FAIL("Cannot load dataset lars_dependent_y.csv"); - - arma::mat XTrain, XTest; - arma::rowvec YTrain, YTest; - data::Split(X, Y, XTrain, XTest, YTrain, YTest, 0.3); - - DecisionTreeRegressor<> tree(XTrain, YTrain, 5); + // Now build the decision tree. + DecisionTreeRegressor<> d(data, fullResponses, weights, 5); + // Now we can check that we get good performance on the test set. arma::rowvec predictions; - tree.Predict(XTest, predictions); + d.Predict(testData, predictions); - const double rmse = RMSE(predictions, YTest); + REQUIRE(predictions.n_elem == testData.n_cols); + // Figure out the accuracy. + double rmse = RMSE(predictions, testResponses); REQUIRE(rmse < 1.0); } /** - * Test that the tree builds correctly on weighted numerical dataset. + * Test that we can build a decision tree using weighted data (where the + * low-weighted data is random noise) with MAD gain, and that the tree + * still builds correctly enough to get good results. */ -TEST_CASE("LARSDatasetWeightedTest", "[DecisionTreeRegressorTest]") +TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") { - arma::mat X; - arma::rowvec Y; + // Loading data. + data::DatasetInfo info; + arma::mat trainData, testData; + arma::rowvec trainResponses, testResponses; + LoadBostonHousingDataset(trainData, testData, trainResponses, testResponses, + info); - if (!data::Load("lars_dependent_x.csv", X)) - FAIL("Cannot load dataset lars_dependent_x.csv"); - if (!data::Load("lars_dependent_y.csv", Y)) - FAIL("Cannot load dataset lars_dependent_y.csv"); + // Add some noise. + arma::mat noise(trainData.n_rows, 200, arma::fill::randu); + arma::rowvec noiseResponses(200); + for (size_t i = 0; i < noiseResponses.n_elem; ++i) + noiseResponses[i] = 15 + math::Random(0, 10); // Random response. - arma::mat XTrain, XTest; - arma::rowvec YTrain, YTest; - data::Split(X, Y, XTrain, XTest, YTrain, YTest, 0.3); + // Concatenate data matrices. + arma::mat data = arma::join_rows(trainData, noise); + arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); - arma::rowvec weights = arma::ones(XTrain.n_elem); + // Now set weights. + arma::rowvec weights(trainData.n_cols + 200); + for (size_t i = 0; i < trainData.n_cols; ++i) + weights[i] = math::Random(0.9, 1.0); + for (size_t i = trainData.n_cols; i < trainData.n_cols + 200; ++i) + weights[i] = math::Random(0.0, 0.01); // Low weights for false points. - DecisionTreeRegressor<> tree(XTrain, YTrain, weights, 5); + // Now build the decision tree using MADGain. + DecisionTreeRegressor d(data, fullResponses, weights, 5); + // Now we can check that we get good performance on the test set. arma::rowvec predictions; - tree.Predict(XTest, predictions); + d.Predict(testData, predictions); - const double rmse = RMSE(predictions, YTest); + REQUIRE(predictions.n_elem == testData.n_cols); - REQUIRE(rmse < 1.0); + // Figure out the accuracy. + double rmse = RMSE(predictions, testResponses); + REQUIRE(rmse < 1.5); } From f0f78cc65a454015c27d9bec9b2427f03f69b8d3 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 13:21:03 +0530 Subject: [PATCH 601/729] Increased tolerance in tests having boston housing dataset. --- .../tests/decision_tree_regressor_test.cpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 3624216f65..7e5ff390dd 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -938,8 +938,8 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") arma::rowvec weights = arma::ones(trainResponses.n_elem); // Build decision tree. - DecisionTreeRegressor<> d(trainData, info, trainResponses, 5); - DecisionTreeRegressor<> wd(trainData, info, trainResponses, weights, 5); + DecisionTreeRegressor<> d(trainData, info, trainResponses); + DecisionTreeRegressor<> wd(trainData, info, trainResponses, weights); // Get the predicted test responses. arma::rowvec predictions; @@ -949,7 +949,7 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") // Figure out rmse. double rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 1.0); + REQUIRE(rmse < 6.0); // Reset the predictions. predictions.zeros(); @@ -959,7 +959,7 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]") // Figure out rmse. rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 1.0); + REQUIRE(rmse < 6.0); } /** @@ -977,8 +977,8 @@ TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") arma::rowvec weights(trainLabels.n_cols, arma::fill::ones); // Build decision tree. - DecisionTreeRegressor<> d(trainData, trainLabels, 5); - DecisionTreeRegressor<> wd(trainData, trainLabels, weights, 5); + DecisionTreeRegressor<> d(trainData, trainLabels); + DecisionTreeRegressor<> wd(trainData, trainLabels, weights); // Get the predicted test labels. arma::rowvec predictions; @@ -988,7 +988,7 @@ TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") // Figure out the rmse. double rmse = RMSE(predictions, testLabels); - REQUIRE(rmse < 1.0); + REQUIRE(rmse < 6.0); // Reset the prediction. predictions.zeros(); @@ -998,7 +998,7 @@ TEST_CASE("SimpleGeneralizationFMatTest_", "[DecisionTreeRegressorTest]") // Figure out the rmse. double wdrmse = RMSE(predictions, testLabels); - REQUIRE(wdrmse < 1.0); + REQUIRE(wdrmse < 6.0); } /** @@ -1016,8 +1016,8 @@ TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") info); // Add some noise. - arma::mat noise(trainData.n_rows, 200, arma::fill::randu); - arma::rowvec noiseResponses(200); + arma::mat noise(trainData.n_rows, 100, arma::fill::randu); + arma::rowvec noiseResponses(100); for (size_t i = 0; i < noiseResponses.n_elem; ++i) noiseResponses[i] = 15 + math::Random(0, 10); // Random response. @@ -1026,14 +1026,14 @@ TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); // Now set weights. - arma::rowvec weights(trainData.n_cols + 200); + arma::rowvec weights(trainData.n_cols + 100); for (size_t i = 0; i < trainData.n_cols; ++i) weights[i] = math::Random(0.9, 1.0); - for (size_t i = trainData.n_cols; i < trainData.n_cols + 200; ++i) + for (size_t i = trainData.n_cols; i < trainData.n_cols + 100; ++i) weights[i] = math::Random(0.0, 0.01); // Low weights for false points. // Now build the decision tree. - DecisionTreeRegressor<> d(data, fullResponses, weights, 5); + DecisionTreeRegressor<> d(data, fullResponses, weights); // Now we can check that we get good performance on the test set. arma::rowvec predictions; @@ -1041,9 +1041,9 @@ TEST_CASE("WeightedDecisionTreeTest_", "[DecisionTreeRegressorTest]") REQUIRE(predictions.n_elem == testData.n_cols); - // Figure out the accuracy. + // Figure out the rmse. double rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 1.0); + REQUIRE(rmse < 6.0); } /** @@ -1061,8 +1061,8 @@ TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") info); // Add some noise. - arma::mat noise(trainData.n_rows, 200, arma::fill::randu); - arma::rowvec noiseResponses(200); + arma::mat noise(trainData.n_rows, 100, arma::fill::randu); + arma::rowvec noiseResponses(100); for (size_t i = 0; i < noiseResponses.n_elem; ++i) noiseResponses[i] = 15 + math::Random(0, 10); // Random response. @@ -1071,14 +1071,14 @@ TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") arma::rowvec fullResponses = arma::join_rows(trainResponses, noiseResponses); // Now set weights. - arma::rowvec weights(trainData.n_cols + 200); + arma::rowvec weights(trainData.n_cols + 100); for (size_t i = 0; i < trainData.n_cols; ++i) weights[i] = math::Random(0.9, 1.0); - for (size_t i = trainData.n_cols; i < trainData.n_cols + 200; ++i) + for (size_t i = trainData.n_cols; i < trainData.n_cols + 100; ++i) weights[i] = math::Random(0.0, 0.01); // Low weights for false points. // Now build the decision tree using MADGain. - DecisionTreeRegressor d(data, fullResponses, weights, 5); + DecisionTreeRegressor d(data, fullResponses, weights); // Now we can check that we get good performance on the test set. arma::rowvec predictions; @@ -1086,7 +1086,7 @@ TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") REQUIRE(predictions.n_elem == testData.n_cols); - // Figure out the accuracy. + // Figure out the rmse. double rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 1.5); + REQUIRE(rmse < 6.0); } From 1a171bcfef18ce00cf02f4a0b272f283554dcd46 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 22 Jun 2021 14:53:14 +0530 Subject: [PATCH 602/729] Fix style check warnings --- .../methods/decision_tree/decision_tree_regressor.hpp | 5 ++++- .../methods/decision_tree/decision_tree_regressor_impl.hpp | 6 ++++-- src/mlpack/methods/decision_tree/mad_gain.hpp | 1 - 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index aed4529921..6ad75adc05 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -409,7 +409,10 @@ class DecisionTreeRegressor : size_t NumLeaves() const; //! Get the child of the given index. - const DecisionTreeRegressor& Child(const size_t i) const { return *children[i]; } + const DecisionTreeRegressor& Child(const size_t i) const + { + return *children[i]; + } //! Modify the child of the given index (be careful!). DecisionTreeRegressor& Child(const size_t i) { return *children[i]; } diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index d29bae904b..82432d01e1 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -677,7 +677,8 @@ double DecisionTreeRegressor(values, weights, 0, values.n_elem); } - }; } // namespace tree From 3051459e46092ed67319026593cd5e1ff1098bde Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 28 Jun 2021 16:59:46 +0530 Subject: [PATCH 603/729] Replaced the use of double with templates to enable floats in responses --- .../best_binary_numeric_split.hpp | 10 +- .../best_binary_numeric_split_impl.hpp | 80 ++++++++-------- src/mlpack/methods/decision_tree/mad_gain.hpp | 8 +- src/mlpack/methods/decision_tree/mse_gain.hpp | 8 +- src/mlpack/methods/decision_tree/utils.hpp | 91 ++++++++++--------- 5 files changed, 106 insertions(+), 91 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 9a888b3341..7120fe2055 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -84,11 +84,12 @@ class BestBinaryNumericSplit * @param aux Auxiliary split information, which may be modified on a * successful split. */ - template + template static double SplitIfBetter( const double bestGain, const VecType& data, - const arma::rowvec& responses, + const ResponsesType& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, @@ -139,11 +140,12 @@ class BestBinaryNumericSplit * successful split. */ template<> -template +template double BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, - const arma::rowvec& responses, + const ResponsesType& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index f16c25521b..0ba2429ae1 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -187,17 +187,21 @@ double BestBinaryNumericSplit::SplitIfBetter( // Overload used for regression. template -template +template double BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, - const arma::rowvec& responses, + const ResponsesType& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, AuxiliarySplitInfo& /* aux */) { + typedef typename ResponsesType::elem_type RType; + typedef typename WeightVecType::elem_type WType; + // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) return DBL_MAX; @@ -206,8 +210,8 @@ double BestBinaryNumericSplit::SplitIfBetter( // Next, sort the data. arma::uvec sortedIndices = arma::sort_index(data); - arma::rowvec sortedResponses(responses.n_elem); - arma::rowvec sortedWeights; + arma::Row sortedResponses(responses.n_elem); + arma::Row sortedWeights; for (size_t i = 0; i < sortedResponses.n_elem; ++i) sortedResponses[i] = responses[sortedIndices[i]]; @@ -230,9 +234,9 @@ double BestBinaryNumericSplit::SplitIfBetter( // Force a minimum leaf size of 1 (empty children don't make sense). const size_t minimum = std::max(minimumLeafSize, (size_t) 1); - double totalWeight = 0.0; - double totalLeftWeight = 0.0; - double totalRightWeight = 0.0; + WType totalWeight = 0.0; + WType totalLeftWeight = 0.0; + WType totalRightWeight = 0.0; if (UseWeights) { @@ -317,17 +321,21 @@ double BestBinaryNumericSplit::SplitIfBetter( // Optimized version when fitness function is MSEGain. template<> -template +template double BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, - const arma::rowvec& responses, + const ResponsesType& responses, const WeightVecType& weights, const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, AuxiliarySplitInfo& /* aux */) { + typedef typename ResponsesType::elem_type RType; + typedef typename ResponsesType::elem_type WType; + // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) return DBL_MAX; @@ -336,8 +344,8 @@ double BestBinaryNumericSplit::SplitIfBetter( // Next, sort the data. arma::uvec sortedIndices = arma::sort_index(data); - arma::rowvec sortedResponses(responses.n_elem); - arma::rowvec sortedWeights; + arma::Row sortedResponses(responses.n_elem); + arma::Row sortedWeights; for (size_t i = 0; i < sortedResponses.n_elem; ++i) sortedResponses[i] = responses[sortedIndices[i]]; @@ -360,20 +368,20 @@ double BestBinaryNumericSplit::SplitIfBetter( // Force a minimum leaf size of 1 (empty children don't make sense). const size_t minimum = std::max(minimumLeafSize, (size_t) 1); - double totalWeight = 0.0; - double leftChildWeight = 0.0; - double rightChildWeight = 0.0; - double leftWeightedMean = 0.0; - double rightWeightedMean = 0.0; - double totalWeightedSumSquares = 0.0; - arma::rowvec weightedSumSquares; + WType totalWeight = 0.0; + WType leftChildWeight = 0.0; + WType rightChildWeight = 0.0; + WType leftWeightedMean = 0.0; + WType rightWeightedMean = 0.0; + WType totalWeightedSumSquares = 0.0; + arma::Row weightedSumSquares; - double leftMean = 0.0; - double rightMean = 0.0; + RType leftMean = 0.0; + RType rightMean = 0.0; size_t leftChildSize = 0; size_t rightChildSize = 0; - double totalSumSquares = 0.0; - arma::rowvec sumSquares; + RType totalSumSquares = 0.0; + arma::Row sumSquares; // Precomputing prefix sum of squares and prefix weighted sum of squares. // This will be used by MSEGain::Evaluate to efficiently compute gain @@ -403,8 +411,8 @@ double BestBinaryNumericSplit::SplitIfBetter( for (size_t i = minimum - 1; i < data.n_elem; ++i) { - const double w = sortedWeights[i]; - const double x = sortedResponses[i]; + const WType w = sortedWeights[i]; + const RType x = sortedResponses[i]; // Calculating initial weighted mean of responses for the right child. rightChildWeight += w; @@ -423,11 +431,11 @@ double BestBinaryNumericSplit::SplitIfBetter( sumSquares.set_size(data.n_elem); // Stores the sum of squares till the previous index. - double prevSumSquares = 0.0; + RType prevSumSquares = 0.0; for (size_t i = 0; i < minimum - 1; ++i) { - const double x = sortedResponses[i]; + const RType x = sortedResponses[i]; // Calculating the initial mean of responses for the left child. ++leftChildSize; @@ -436,11 +444,11 @@ double BestBinaryNumericSplit::SplitIfBetter( prevSumSquares += x * x; } if (leftChildSize) - leftMean /= (double) leftChildSize; + leftMean /= (RType) leftChildSize; for (size_t i = minimum - 1; i < data.n_elem; ++i) { - const double x = sortedResponses[i]; + const RType x = sortedResponses[i]; // Calculating the initial mean of responses for the right child. rightChildSize++; @@ -449,7 +457,7 @@ double BestBinaryNumericSplit::SplitIfBetter( prevSumSquares += x * x; } if (rightChildSize) - rightMean /= (double) rightChildSize; + rightMean /= (RType) rightChildSize; totalSumSquares = prevSumSquares; } @@ -460,8 +468,8 @@ double BestBinaryNumericSplit::SplitIfBetter( if (UseWeights) { // Updating the weighted mean for both childs for each index. - const double w = sortedWeights[index - 1]; - const double x = sortedResponses[index - 1]; + const WType w = sortedWeights[index - 1]; + const RType x = sortedResponses[index - 1]; leftWeightedMean = (leftWeightedMean * leftChildWeight + w * x) / (leftChildWeight + w); leftChildWeight += w; @@ -473,13 +481,13 @@ double BestBinaryNumericSplit::SplitIfBetter( else { // Updating the mean for both childs for each index. - const double x = sortedResponses[index - 1]; - leftMean = (leftMean * (double) leftChildSize + x) / - (double) (leftChildSize + 1); + const RType x = sortedResponses[index - 1]; + leftMean = (leftMean * (RType) leftChildSize + x) / + (RType) (leftChildSize + 1); ++leftChildSize; - rightMean = (rightMean * (double) rightChildSize - x) / - (double) (rightChildSize - 1); + rightMean = (rightMean * (RType) rightChildSize - x) / + (RType) (rightChildSize - 1); --rightChildSize; } diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index bdd654c5a5..5e2e519dc4 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -42,8 +42,8 @@ class MADGain * @param begin Start index. * @param end End index. */ - template - static double Evaluate(const arma::rowvec& values, + template + static double Evaluate(const VecType& values, const WeightVecType& weights, const size_t begin, const size_t end) @@ -88,8 +88,8 @@ class MADGain * @param values Set of values to evaluate MAD gain on. * @param weights Weights associated to each value. */ - template - static double Evaluate(const arma::rowvec& values, + template + static double Evaluate(const VecType& values, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 7d013cd9aa..bd9af8b14b 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -40,8 +40,8 @@ class MSEGain * @param begin Start index. * @param end End index. */ - template - static double Evaluate(const arma::rowvec& values, + template + static double Evaluate(const VecType& values, const WeightVecType& weights, const size_t begin, const size_t end) @@ -84,8 +84,8 @@ class MSEGain * @param values Set of values to evaluate MSE gain on. * @param weights Weights associated to each value. */ - template - static double Evaluate(const arma::rowvec& values, + template + static double Evaluate(const VecType& values, const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. diff --git a/src/mlpack/methods/decision_tree/utils.hpp b/src/mlpack/methods/decision_tree/utils.hpp index 37c6453c56..3b646b35fc 100644 --- a/src/mlpack/methods/decision_tree/utils.hpp +++ b/src/mlpack/methods/decision_tree/utils.hpp @@ -15,29 +15,33 @@ /** * Calculates the weighted sum and total weight of labels. */ -inline void WeightedSum(const arma::rowvec& labels, - const arma::rowvec& weights, - const size_t begin, - const size_t end, - double& accWeights, - double& weightedMean) +template +inline void WeightedSum(const VecType& values, + const WeightVecType& weights, + const size_t begin, + const size_t end, + double& accWeights, + double& weightedMean) { - double totalWeights[4] = { 0.0, 0.0, 0.0, 0.0 }; - double weightedSum[4] = { 0.0, 0.0, 0.0, 0.0 }; + typedef typename VecType::elem_type VType; + typedef typename WeightVecType::elem_type WType; + + WType totalWeights[4] = { 0.0, 0.0, 0.0, 0.0 }; + VType weightedSum[4] = { 0.0, 0.0, 0.0, 0.0 }; // SIMD loop: sums four elements simultaneously (if the compiler manages // to vectorize the loop). for (size_t i = begin + 3; i < end; i += 4) { - const double weight1 = weights[i - 3]; - const double weight2 = weights[i - 2]; - const double weight3 = weights[i - 1]; - const double weight4 = weights[i]; + const WType weight1 = weights[i - 3]; + const WType weight2 = weights[i - 2]; + const WType weight3 = weights[i - 1]; + const WType weight4 = weights[i]; - weightedSum[0] += weight1 * labels[i - 3]; - weightedSum[1] += weight2 * labels[i - 2]; - weightedSum[2] += weight3 * labels[i - 1]; - weightedSum[3] += weight4 * labels[i]; + weightedSum[0] += weight1 * values[i - 3]; + weightedSum[1] += weight2 * values[i - 2]; + weightedSum[2] += weight3 * values[i - 1]; + weightedSum[3] += weight4 * values[i]; totalWeights[0] += weight1; totalWeights[1] += weight2; @@ -48,30 +52,30 @@ inline void WeightedSum(const arma::rowvec& labels, // Handle leftovers. if ((end - begin) % 4 == 1) { - const double weight1 = weights[end - 1]; - weightedSum[0] += weight1 * labels[end - 1]; + const WType weight1 = weights[end - 1]; + weightedSum[0] += weight1 * values[end - 1]; totalWeights[0] += weight1; } else if ((end - begin) % 4 == 2) { - const double weight1 = weights[end - 2]; - const double weight2 = weights[end - 1]; + const WType weight1 = weights[end - 2]; + const WType weight2 = weights[end - 1]; - weightedSum[0] += weight1 * labels[end - 2]; - weightedSum[1] += weight2 * labels[end - 1]; + weightedSum[0] += weight1 * values[end - 2]; + weightedSum[1] += weight2 * values[end - 1]; totalWeights[0] += weight1; totalWeights[1] += weight2; } else if ((end - begin) % 4 == 3) { - const double weight1 = weights[end - 3]; - const double weight2 = weights[end - 2]; - const double weight3 = weights[end - 1]; + const WType weight1 = weights[end - 3]; + const WType weight2 = weights[end - 2]; + const WType weight3 = weights[end - 1]; - weightedSum[0] += weight1 * labels[end - 3]; - weightedSum[1] += weight2 * labels[end - 2]; - weightedSum[2] += weight1 * labels[end - 1]; + weightedSum[0] += weight1 * values[end - 3]; + weightedSum[1] += weight2 * values[end - 2]; + weightedSum[2] += weight1 * values[end - 1]; totalWeights[0] += weight1; totalWeights[1] += weight2; @@ -88,38 +92,39 @@ inline void WeightedSum(const arma::rowvec& labels, /** * Sums up the labels vector. */ -inline void Sum(const arma::rowvec& labels, - const size_t begin, - const size_t end, - double& mean) +template +inline void Sum(const VecType& values, + const size_t begin, + const size_t end, + double& mean) { - double total[4] = { 0.0, 0.0, 0.0, 0.0 }; + typename VecType::elem_type total[4] = { 0.0, 0.0, 0.0, 0.0 }; // SIMD loop: add counts for four elements simultaneously (if the compiler // manages to vectorize the loop). for (size_t i = begin + 3; i < end; i += 4) { - total[0] += labels[i - 3]; - total[1] += labels[i - 2]; - total[2] += labels[i - 1]; - total[3] += labels[i]; + total[0] += values[i - 3]; + total[1] += values[i - 2]; + total[2] += values[i - 1]; + total[3] += values[i]; } // Handle leftovers. if ((end - begin) % 4 == 1) { - total[0] += labels[end - 1]; + total[0] += values[end - 1]; } else if ((end - begin) % 4 == 2) { - total[0] += labels[end - 2]; - total[1] += labels[end - 1]; + total[0] += values[end - 2]; + total[1] += values[end - 1]; } else if ((end - begin) % 4 == 3) { - total[0] += labels[end - 3]; - total[1] += labels[end - 2]; - total[2] += labels[end - 1]; + total[0] += values[end - 3]; + total[1] += values[end - 2]; + total[2] += values[end - 1]; } total[0] += total[1] + total[2] + total[3]; From 15c6f86de071a599590b7c210b2d949d3309780b Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 2 Jul 2021 21:06:54 +0530 Subject: [PATCH 604/729] Create interface for MSEGain optimized version --- .../best_binary_numeric_split_impl.hpp | 131 ++---------- src/mlpack/methods/decision_tree/mse_gain.hpp | 197 ++++++++++++++---- 2 files changed, 181 insertions(+), 147 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 0ba2429ae1..65a66c0a70 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -334,7 +334,9 @@ double BestBinaryNumericSplit::SplitIfBetter( AuxiliarySplitInfo& /* aux */) { typedef typename ResponsesType::elem_type RType; - typedef typename ResponsesType::elem_type WType; + typedef typename WeightVecType::elem_type WType; + + MSEGain fitnessFunction; // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) @@ -371,141 +373,48 @@ double BestBinaryNumericSplit::SplitIfBetter( WType totalWeight = 0.0; WType leftChildWeight = 0.0; WType rightChildWeight = 0.0; - WType leftWeightedMean = 0.0; - WType rightWeightedMean = 0.0; - WType totalWeightedSumSquares = 0.0; - arma::Row weightedSumSquares; - RType leftMean = 0.0; - RType rightMean = 0.0; - size_t leftChildSize = 0; - size_t rightChildSize = 0; - RType totalSumSquares = 0.0; - arma::Row sumSquares; - - // Precomputing prefix sum of squares and prefix weighted sum of squares. - // This will be used by MSEGain::Evaluate to efficiently compute gain - // values for all possible splits. if (UseWeights) { totalWeight = arma::accu(sortedWeights); bestFoundGain *= totalWeight; - weightedSumSquares.set_size(data.n_elem); - // Stores the weighted sum of squares till the previous index. - double prevWeightedSumSquares = 0.0; - for (size_t i = 0; i < minimum - 1; ++i) - { - const double w = sortedWeights[i]; - const double x = sortedResponses[i]; - - // Calculating initial weighted mean of responses for the left child. - leftChildWeight += w; - leftWeightedMean += w * x; - weightedSumSquares[i] = prevWeightedSumSquares + w * x * x; - prevWeightedSumSquares += w * x * x; - } - if (leftChildWeight > 1e-9) - leftWeightedMean /= leftChildWeight; + leftChildWeight += sortedWeights[i]; for (size_t i = minimum - 1; i < data.n_elem; ++i) - { - const WType w = sortedWeights[i]; - const RType x = sortedResponses[i]; - - // Calculating initial weighted mean of responses for the right child. - rightChildWeight += w; - rightWeightedMean += w * x; - weightedSumSquares[i] = prevWeightedSumSquares + w * x * x; - prevWeightedSumSquares += w * x * x; - } - if (rightChildWeight > 1e-9) - rightWeightedMean /= rightChildWeight; - - totalWeightedSumSquares = prevWeightedSumSquares; + rightChildWeight += sortedWeights[i]; } else { bestFoundGain *= data.n_elem; - - sumSquares.set_size(data.n_elem); - // Stores the sum of squares till the previous index. - RType prevSumSquares = 0.0; - - for (size_t i = 0; i < minimum - 1; ++i) - { - const RType x = sortedResponses[i]; - - // Calculating the initial mean of responses for the left child. - ++leftChildSize; - leftMean += x; - sumSquares[i] = prevSumSquares + x * x; - prevSumSquares += x * x; - } - if (leftChildSize) - leftMean /= (RType) leftChildSize; - - for (size_t i = minimum - 1; i < data.n_elem; ++i) - { - const RType x = sortedResponses[i]; - - // Calculating the initial mean of responses for the right child. - rightChildSize++; - rightMean += x; - sumSquares[i] = prevSumSquares + x * x; - prevSumSquares += x * x; - } - if (rightChildSize) - rightMean /= (RType) rightChildSize; - - totalSumSquares = prevSumSquares; } + // Precomputing various statistics to efficiently compute gain values for + // all possible splits. + fitnessFunction.CalculateStatistics(sortedResponses, + sortedWeights, minimum); + // Loop through all possible split points, choosing the best one. for (size_t index = minimum; index < data.n_elem - minimum + 1; ++index) { if (UseWeights) { - // Updating the weighted mean for both childs for each index. - const WType w = sortedWeights[index - 1]; - const RType x = sortedResponses[index - 1]; - leftWeightedMean = (leftWeightedMean * leftChildWeight + w * x) - / (leftChildWeight + w); - leftChildWeight += w; - - rightWeightedMean = (rightWeightedMean * rightChildWeight - w * x) - / (rightChildWeight - w); - rightChildWeight -= w; + leftChildWeight += sortedWeights[index - 1]; + rightChildWeight -= sortedWeights[index - 1]; } - else - { - // Updating the mean for both childs for each index. - const RType x = sortedResponses[index - 1]; - leftMean = (leftMean * (RType) leftChildSize + x) / - (RType) (leftChildSize + 1); - ++leftChildSize; - rightMean = (rightMean * (RType) rightChildSize - x) / - (RType) (rightChildSize - 1); - --rightChildSize; - } + // Update statistics for the current index. + fitnessFunction.UpdateStatistics(sortedResponses, + sortedWeights, index - 1); // Make sure that the value has changed. if (data[sortedIndices[index]] == data[sortedIndices[index - 1]]) continue; // Calculate the gain for the left and right child. - const double leftGain = UseWeights ? - MSEGain::Evaluate(weightedSumSquares[index - 1], - leftWeightedMean, leftChildWeight) : - MSEGain::Evaluate(sumSquares[index - 1], leftMean, leftChildSize); - const double rightGain = UseWeights ? - MSEGain::Evaluate( - totalWeightedSumSquares - weightedSumSquares[index - 1], - rightWeightedMean, rightChildWeight) : - MSEGain::Evaluate(totalSumSquares - sumSquares[index - 1], - rightMean, rightChildSize); + const double leftGain = fitnessFunction.Evaluate(index - 1, 0); + const double rightGain = fitnessFunction.Evaluate(index - 1, 1); double gain; if (UseWeights) @@ -515,8 +424,8 @@ double BestBinaryNumericSplit::SplitIfBetter( else { // Calculate the gain at this split point. - gain = double(leftChildSize) * leftGain + - double(rightChildSize) * rightGain; + gain = double(index) * leftGain + + double(sortedResponses.n_elem - index) * rightGain; } // Corner case: is this the best possible split? @@ -530,7 +439,7 @@ double BestBinaryNumericSplit::SplitIfBetter( return gain; } - if (gain > bestFoundGain) + if (gain > bestFoundGain) { // We still have a better split. bestFoundGain = gain; diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index bd9af8b14b..a4cc033aa3 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -96,35 +96,7 @@ class MSEGain } /** - * Calculates the weighted mean squared error gain given the sum of squares - * and mean. - * - * X = array of values of size n. - * W = array of weights of size n. - * - * @f{eqnarray*}{ - * MSE = \sum\limits_{i=1}^n {W_i * {X_i}^2} - - * {\dfrac{\sum\limits_{j=1}^n W_j * X_j} - * {\sum\limits_{j=1}^n W_i}}^2 - * @f} - * - * @param weightedSumSquares Precomputed weighted sum of square - * (sum(Wi * Xi^2)) of values. - * @param weightedMean Precomputed weighted mean (sum(Wi * Xi) / sum(Wi)) of - * values. - * @param totalChildWeight Total weight of all the samples in that child. - */ - static double Evaluate(const double weightedSumSquares, - const double weightedMean, - const double totalChildWeight) - { - double mse = weightedSumSquares / totalChildWeight - - weightedMean * weightedMean; - return -mse; - } - - /** - * Calculates the mean squared error gain given the sum of squares and mean. + * Calculates the mean squared error gain for the given child and index. * * X = array of values of size n. * @@ -133,17 +105,170 @@ class MSEGain * {\dfrac{\sum\limits_{j=1}^n X_j}{n}}^2 * @f} * - * @param sumSquares Precomputed sum of square (sum(Xi^2)) of values. - * @param mean Precomputed mean (sum(Xi) / n) of values. - * @param childSize The total number of samples in that child. + * @param index The current index to calculate gain. + * @param child The child to calculate gain. + * 0 -> Left child, 1 -> Right child */ - static double Evaluate(const double sumSquares, - const double mean, - const size_t childSize) + double Evaluate(const size_t index, const size_t child) { - double mse = sumSquares / (double) childSize - mean * mean; + double mse; + // Left child. + if (child == 0) + mse = sumSquares[index] / leftSize - leftMean * leftMean; + // Right child. + else + mse = (totalSumSquares - sumSquares[index]) / rightSize + - rightMean * rightMean; return -mse; } + + /** + * Caches the prefix sum of squares to efficiently compute gain value for + * each split. It also computes the initial mean for left and right child. + * + * @param responses The set of responses on which statistics are computed. + * @param weights The set of weights associated to each response. + * @param minimum The minimum number of elements in a leaf. + */ + template + void CalculateStatistics(const ResponsesType& responses, + const WeightVecType& weights, + const size_t minimum) + { + typedef typename ResponsesType::elem_type RType; + typedef typename WeightVecType::elem_type WType; + + // Initializing data members to cache statistics. + leftMean = 0.0; + rightMean = 0.0; + leftSize = 0.0; + rightSize = 0.0; + totalSumSquares = 0.0; + sumSquares.set_size(responses.n_elem); + + if (UseWeights) + { + // Stores the weighted sum of squares till the previous index. + double prevWeightedSumSquares = 0.0; + + for (size_t i = 0; i < minimum - 1; ++i) + { + const WType w = weights[i]; + const RType x = responses[i]; + + // Calculating initial weighted mean of responses for the left child. + leftSize += w; + leftMean += w * x; + sumSquares[i] = prevWeightedSumSquares + w * x * x; + prevWeightedSumSquares += w * x * x; + } + if (leftSize > 1e-9) + leftMean /= leftSize; + + for(size_t i = minimum - 1; i < responses.n_elem; ++i) + { + const WType w = weights[i]; + const RType x = responses[i]; + + // Calculating initial weighted mean of responses for the right child. + rightSize += w; + rightMean += w * x; + sumSquares[i] = prevWeightedSumSquares + w * x * x; + prevWeightedSumSquares += w * x * x; + } + if (rightSize > 1e-9) + rightMean /= rightSize; + + totalSumSquares = prevWeightedSumSquares; + } + else + { + // Stores the sum of squares till the previous index. + double prevSumSquares = 0.0; + + for (size_t i = 0; i < minimum - 1; ++i) + { + const RType x = responses[i]; + + // Calculating the initial mean of responses for the left child. + ++leftSize; + leftMean += x; + sumSquares[i] = prevSumSquares + x * x; + prevSumSquares += x * x; + } + if (leftSize > 1e-9) + leftMean /= leftSize; + + for(size_t i = minimum - 1; i < responses.n_elem; ++i) + { + const RType x = responses[i]; + + // Calculating the initial mean of responses for the right child. + ++rightSize; + rightMean += x; + sumSquares[i] = prevSumSquares + x * x; + prevSumSquares += x * x; + } + if (rightSize > 1e-9) + rightMean /= rightSize; + + totalSumSquares = prevSumSquares; + } + } + + /** + * Updates the statistics for the given index. + * + * @param responses The set of responses on which statistics are computed. + * @param weights The set of weights associated to each response. + * @param index The current index. + */ + template + void UpdateStatistics(const ResponsesType& responses, + const WeightVecType& weights, + const size_t index) + { + typedef typename ResponsesType::elem_type RType; + typedef typename WeightVecType::elem_type WType; + + if (UseWeights) + { + const WType w = weights[index]; + const RType x = responses[index]; + leftMean = (leftMean * leftSize + w * x) / (leftSize + w); + leftSize += w; + + rightMean = (rightMean * rightSize - w * x) / (rightSize - w); + rightSize -= w; + } + else + { + const RType x = responses[index]; + leftMean = (leftMean * leftSize + x) / (leftSize + 1); + ++leftSize; + + rightMean = (rightMean * rightSize - x) / (rightSize - 1); + --rightSize; + } + } + + private: + /** + * The following data members cache statistics for weighted data when + * `UseWeights` is true, else it will calculate unweighted statistics. + */ + // Stores the sum of squares / weighted sum of squares. + arma::rowvec sumSquares; + // For unweighted data, stores the number of elements in each child. + // For weighted data, stores the sum of weights of elements in each + // child. + double leftSize; + double rightSize; + // Stores the mean / weighted mean. + double leftMean; + double rightMean; + // Stores the total sum of squares / total weighted sum of squares. + double totalSumSquares; }; } // namespace tree From 7aa4dc403c4a66b772970691d910b6241a7c67f4 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 2 Jul 2021 21:12:06 +0530 Subject: [PATCH 605/729] Update tolerance for failing test --- src/mlpack/tests/decision_tree_regressor_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index 7e5ff390dd..cafde0cc4d 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -1088,5 +1088,5 @@ TEST_CASE("WeightedDecisionTreeMADGainTest", "[DecisionTreeRegressorTest]") // Figure out the rmse. double rmse = RMSE(predictions, testResponses); - REQUIRE(rmse < 6.0); + REQUIRE(rmse < 6.5); } From d25657755b694d6ca2a04c1c85911f64b0ce0a40 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 3 Jul 2021 10:01:49 +0530 Subject: [PATCH 606/729] Removed sumSquared vector to use O(1) space --- src/mlpack/methods/decision_tree/mse_gain.hpp | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index a4cc033aa3..f4973ed48d 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -114,10 +114,10 @@ class MSEGain double mse; // Left child. if (child == 0) - mse = sumSquares[index] / leftSize - leftMean * leftMean; + mse = leftSumSquares / leftSize - leftMean * leftMean; // Right child. else - mse = (totalSumSquares - sumSquares[index]) / rightSize + mse = (totalSumSquares - leftSumSquares) / rightSize - rightMean * rightMean; return -mse; } @@ -143,14 +143,15 @@ class MSEGain rightMean = 0.0; leftSize = 0.0; rightSize = 0.0; + leftSumSquares = 0.0; totalSumSquares = 0.0; - sumSquares.set_size(responses.n_elem); if (UseWeights) { - // Stores the weighted sum of squares till the previous index. - double prevWeightedSumSquares = 0.0; - + // Do I need to document that the % symbol does the elementwise multiplication? + // It might be misleading to general developers who might confuse it with modulo + // operator. + totalSumSquares = arma::accu(weights % arma::square(responses)); for (size_t i = 0; i < minimum - 1; ++i) { const WType w = weights[i]; @@ -159,8 +160,7 @@ class MSEGain // Calculating initial weighted mean of responses for the left child. leftSize += w; leftMean += w * x; - sumSquares[i] = prevWeightedSumSquares + w * x * x; - prevWeightedSumSquares += w * x * x; + leftSumSquares += w * x * x; } if (leftSize > 1e-9) leftMean /= leftSize; @@ -173,19 +173,13 @@ class MSEGain // Calculating initial weighted mean of responses for the right child. rightSize += w; rightMean += w * x; - sumSquares[i] = prevWeightedSumSquares + w * x * x; - prevWeightedSumSquares += w * x * x; } if (rightSize > 1e-9) rightMean /= rightSize; - - totalSumSquares = prevWeightedSumSquares; } else { - // Stores the sum of squares till the previous index. - double prevSumSquares = 0.0; - + totalSumSquares = arma::accu(arma::square(responses)); for (size_t i = 0; i < minimum - 1; ++i) { const RType x = responses[i]; @@ -193,8 +187,7 @@ class MSEGain // Calculating the initial mean of responses for the left child. ++leftSize; leftMean += x; - sumSquares[i] = prevSumSquares + x * x; - prevSumSquares += x * x; + leftSumSquares += x * x; } if (leftSize > 1e-9) leftMean /= leftSize; @@ -206,13 +199,9 @@ class MSEGain // Calculating the initial mean of responses for the right child. ++rightSize; rightMean += x; - sumSquares[i] = prevSumSquares + x * x; - prevSumSquares += x * x; } if (rightSize > 1e-9) rightMean /= rightSize; - - totalSumSquares = prevSumSquares; } } @@ -235,6 +224,11 @@ class MSEGain { const WType w = weights[index]; const RType x = responses[index]; + + // Update weighted sum of squares for left child. + leftSumSquares += w * x * x; + + // Update weighted mean for both childs. leftMean = (leftMean * leftSize + w * x) / (leftSize + w); leftSize += w; @@ -244,6 +238,11 @@ class MSEGain else { const RType x = responses[index]; + + // Update sum of squares for left child. + leftSumSquares += x * x; + + // Update mean for both childs. leftMean = (leftMean * leftSize + x) / (leftSize + 1); ++leftSize; @@ -257,8 +256,8 @@ class MSEGain * The following data members cache statistics for weighted data when * `UseWeights` is true, else it will calculate unweighted statistics. */ - // Stores the sum of squares / weighted sum of squares. - arma::rowvec sumSquares; + // Stores the sum of squares / weighted sum of squares for the left child. + double leftSumSquares; // For unweighted data, stores the number of elements in each child. // For weighted data, stores the sum of weights of elements in each // child. From 16f5fc1a22827d5ce321bae9cc7283738a26e778 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 3 Jul 2021 10:56:03 +0530 Subject: [PATCH 607/729] Return tuple from Evaluate method. --- .../best_binary_numeric_split_impl.hpp | 5 +++-- src/mlpack/methods/decision_tree/mse_gain.hpp | 21 +++++++------------ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 65a66c0a70..2aacd38439 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -413,8 +413,9 @@ double BestBinaryNumericSplit::SplitIfBetter( continue; // Calculate the gain for the left and right child. - const double leftGain = fitnessFunction.Evaluate(index - 1, 0); - const double rightGain = fitnessFunction.Evaluate(index - 1, 1); + auto value = fitnessFunction.Evaluate(); + const double leftGain = std::get<0>(value); + const double rightGain = std::get<1>(value); double gain; if (UseWeights) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index f4973ed48d..4226e9699f 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -96,7 +96,8 @@ class MSEGain } /** - * Calculates the mean squared error gain for the given child and index. + * Calculates the mean squared error gain for the left and right children + * for the current index. * * X = array of values of size n. * @@ -104,22 +105,14 @@ class MSEGain * MSE = \sum\limits_{i=1}^n {X_i}^2 - * {\dfrac{\sum\limits_{j=1}^n X_j}{n}}^2 * @f} - * - * @param index The current index to calculate gain. - * @param child The child to calculate gain. - * 0 -> Left child, 1 -> Right child */ - double Evaluate(const size_t index, const size_t child) + std::tuple Evaluate() { - double mse; - // Left child. - if (child == 0) - mse = leftSumSquares / leftSize - leftMean * leftMean; - // Right child. - else - mse = (totalSumSquares - leftSumSquares) / rightSize + double mseLeft = leftSumSquares / leftSize - leftMean * leftMean; + double mseRight = (totalSumSquares - leftSumSquares) / rightSize - rightMean * rightMean; - return -mse; + + return {-mseLeft, -mseRight}; } /** From 451fa167ea35f70e7b32486bb16e5d3318a533e8 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:08:54 +0530 Subject: [PATCH 608/729] Change names of functions --- .../best_binary_numeric_split_impl.hpp | 16 ++++++++-------- src/mlpack/methods/decision_tree/mse_gain.hpp | 17 +++++++---------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 2aacd38439..8d8031293c 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -390,9 +390,9 @@ double BestBinaryNumericSplit::SplitIfBetter( bestFoundGain *= data.n_elem; } - // Precomputing various statistics to efficiently compute gain values for - // all possible splits. - fitnessFunction.CalculateStatistics(sortedResponses, + // Initialize and precompute various statistics to efficiently compute gain + // values for all possible splits. + fitnessFunction.BinaryScanInitialize(sortedResponses, sortedWeights, minimum); // Loop through all possible split points, choosing the best one. @@ -404,8 +404,8 @@ double BestBinaryNumericSplit::SplitIfBetter( rightChildWeight -= sortedWeights[index - 1]; } - // Update statistics for the current index. - fitnessFunction.UpdateStatistics(sortedResponses, + // Steps through the current index and updates the cached data. + fitnessFunction.BinaryStep(sortedResponses, sortedWeights, index - 1); // Make sure that the value has changed. @@ -413,9 +413,9 @@ double BestBinaryNumericSplit::SplitIfBetter( continue; // Calculate the gain for the left and right child. - auto value = fitnessFunction.Evaluate(); - const double leftGain = std::get<0>(value); - const double rightGain = std::get<1>(value); + auto binaryGains = fitnessFunction.BinaryGains(); + const double leftGain = std::get<0>(binaryGains); + const double rightGain = std::get<1>(binaryGains); double gain; if (UseWeights) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 4226e9699f..2b4e058eb2 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -106,7 +106,7 @@ class MSEGain * {\dfrac{\sum\limits_{j=1}^n X_j}{n}}^2 * @f} */ - std::tuple Evaluate() + std::tuple BinaryGains() { double mseLeft = leftSumSquares / leftSize - leftMean * leftMean; double mseRight = (totalSumSquares - leftSumSquares) / rightSize @@ -124,9 +124,9 @@ class MSEGain * @param minimum The minimum number of elements in a leaf. */ template - void CalculateStatistics(const ResponsesType& responses, - const WeightVecType& weights, - const size_t minimum) + void BinaryScanInitialize(const ResponsesType& responses, + const WeightVecType& weights, + const size_t minimum) { typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; @@ -141,9 +141,6 @@ class MSEGain if (UseWeights) { - // Do I need to document that the % symbol does the elementwise multiplication? - // It might be misleading to general developers who might confuse it with modulo - // operator. totalSumSquares = arma::accu(weights % arma::square(responses)); for (size_t i = 0; i < minimum - 1; ++i) { @@ -206,9 +203,9 @@ class MSEGain * @param index The current index. */ template - void UpdateStatistics(const ResponsesType& responses, - const WeightVecType& weights, - const size_t index) + void BinaryStep(const ResponsesType& responses, + const WeightVecType& weights, + const size_t index) { typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; From 8174764fe1552817d5b696fdf29cf76a858e7162 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:45:04 +0530 Subject: [PATCH 609/729] Finally after so many errors... Add SFINAE to resolve optimized and unoptimized overloads of SplitIfBetter --- .../best_binary_numeric_split.hpp | 82 +++++++++++-------- .../best_binary_numeric_split_impl.hpp | 12 ++- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 7120fe2055..043c66f212 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -15,9 +15,20 @@ #include #include "mse_gain.hpp" +#include + namespace mlpack { namespace tree { +// This gives us a HasBinaryScanInitialize type (where U is a function +// pointer) we can use with SFINAE to catch when a type has a +// BinaryScanInitialize(...) function. +HAS_MEM_FUNC(BinaryScanInitialize, HasBinaryScanInitialize); + +// This gives us a HasBinaryStep type (where U is a function pointer) +// we can use with SFINAE to catch when a type has a BinaryStep(...) function. +HAS_MEM_FUNC(BinaryStep, HasBinaryStep); + /** * The BestBinaryNumericSplit is a splitting function for decision trees that * will exhaustively search a numeric dimension for the best binary split. @@ -96,6 +107,44 @@ class BestBinaryNumericSplit double& splitInfo, AuxiliarySplitInfo& aux); + /** + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then splitInfo and aux + * may be modified. + * + * This overload is specialized only for MSEGain fitness function. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param responses Responses for each point. + * @param weights Weights associated with responses. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param minimumGainSplit Minimum gain split. + * @param splitInfo Stores split information on a successful split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + */ + template + typename std::enable_if< + HasBinaryScanInitialize::value && + HasBinaryStep::value, + double>::type + SplitIfBetter( + const double bestGain, + const VecType& data, + const ResponsesType& responses, + const WeightVecType& weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + double& splitInfo, + AuxiliarySplitInfo& /* aux */); + /** * Returns 2, since the binary split always has two children. */ @@ -119,39 +168,6 @@ class BestBinaryNumericSplit const AuxiliarySplitInfo& /* aux */); }; -/** -* Check if we can split a node. If we can split a node in a way that -* improves on 'bestGain', then we return the improved gain. Otherwise we -* return the value 'bestGain'. If a split is made, then splitInfo and aux -* may be modified. -* -* This overload is specialized only for MSEGain fitness function. -* -* @param bestGain Best gain seen so far (we'll only split if we find gain -* better than this). -* @param data The dimension of data points to check for a split in. -* @param responses Responses for each point. -* @param weights Weights associated with responses. -* @param minimumLeafSize Minimum number of points in a leaf node for -* splitting. -* @param minimumGainSplit Minimum gain split. -* @param splitInfo Stores split information on a successful split. -* @param aux Auxiliary split information, which may be modified on a -* successful split. -*/ -template<> -template -double BestBinaryNumericSplit::SplitIfBetter( - const double bestGain, - const VecType& data, - const ResponsesType& responses, - const WeightVecType& weights, - const size_t minimumLeafSize, - const double minimumGainSplit, - double& splitInfo, - AuxiliarySplitInfo& /* aux */); - } // namespace tree } // namespace mlpack diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 8d8031293c..1913fc0868 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -320,10 +320,16 @@ double BestBinaryNumericSplit::SplitIfBetter( } // Optimized version when fitness function is MSEGain. -template<> +template template -double BestBinaryNumericSplit::SplitIfBetter( +typename std::enable_if< + HasBinaryScanInitialize::value && + HasBinaryStep::value, + double>::type +BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, const ResponsesType& responses, @@ -336,7 +342,7 @@ double BestBinaryNumericSplit::SplitIfBetter( typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; - MSEGain fitnessFunction; + FitnessFunction fitnessFunction; // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) From d204474e8d50aeb820af1ec722726d9f0128a991 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:45:45 +0530 Subject: [PATCH 610/729] Fix style warning --- src/mlpack/methods/decision_tree/mse_gain.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 2b4e058eb2..3752319e4f 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -155,7 +155,7 @@ class MSEGain if (leftSize > 1e-9) leftMean /= leftSize; - for(size_t i = minimum - 1; i < responses.n_elem; ++i) + for (size_t i = minimum - 1; i < responses.n_elem; ++i) { const WType w = weights[i]; const RType x = responses[i]; @@ -182,7 +182,7 @@ class MSEGain if (leftSize > 1e-9) leftMean /= leftSize; - for(size_t i = minimum - 1; i < responses.n_elem; ++i) + for (size_t i = minimum - 1; i < responses.n_elem; ++i) { const RType x = responses[i]; From f9f43d4957aa5050aa4ab0217d57b98aeea5348d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:54:10 +0530 Subject: [PATCH 611/729] Add a log to HISTORY.md --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 1c1c157cf8..08909cde5f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? + * Added Decision Tree Regressor (#2905). It can be used using the class + `mlpack::tree::DecisionTreeRegressor`. It is accessible only though C++. * Added dict-style inspection of mlpack models in python bindings (#2868). * Added Extra Trees Algorithm (#2883). Currently, it can be used using the From af3e985d784d469e6f3eb75d258a9b2107415367 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Jul 2021 07:31:32 +0530 Subject: [PATCH 612/729] Fix style issues from code review --- .../best_binary_numeric_split.hpp | 38 +++++++++---------- .../decision_tree_regressor_impl.hpp | 16 ++++---- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 043c66f212..77dfa29569 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -108,25 +108,25 @@ class BestBinaryNumericSplit AuxiliarySplitInfo& aux); /** - * Check if we can split a node. If we can split a node in a way that - * improves on 'bestGain', then we return the improved gain. Otherwise we - * return the value 'bestGain'. If a split is made, then splitInfo and aux - * may be modified. - * - * This overload is specialized only for MSEGain fitness function. - * - * @param bestGain Best gain seen so far (we'll only split if we find gain - * better than this). - * @param data The dimension of data points to check for a split in. - * @param responses Responses for each point. - * @param weights Weights associated with responses. - * @param minimumLeafSize Minimum number of points in a leaf node for - * splitting. - * @param minimumGainSplit Minimum gain split. - * @param splitInfo Stores split information on a successful split. - * @param aux Auxiliary split information, which may be modified on a - * successful split. - */ + * Check if we can split a node. If we can split a node in a way that + * improves on 'bestGain', then we return the improved gain. Otherwise we + * return the value 'bestGain'. If a split is made, then splitInfo and aux + * may be modified. + * + * This overload is specialized only for MSEGain fitness function. + * + * @param bestGain Best gain seen so far (we'll only split if we find gain + * better than this). + * @param data The dimension of data points to check for a split in. + * @param responses Responses for each point. + * @param weights Weights associated with responses. + * @param minimumLeafSize Minimum number of points in a leaf node for + * splitting. + * @param minimumGainSplit Minimum gain split. + * @param splitInfo Stores split information on a successful split. + * @param aux Auxiliary split information, which may be modified on a + * successful split. + */ template typename std::enable_if< diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 82432d01e1..31a63fedd0 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -191,10 +191,10 @@ DecisionTreeRegressor class NumericSplitType, - template class CategoricalSplitType, - typename DimensionSelectionType, - bool NoRecursion> + template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> template DecisionTreeRegressor class NumericSplitType, - template class CategoricalSplitType, - typename DimensionSelectionType, - bool NoRecursion> + template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> template DecisionTreeRegressor Date: Sat, 10 Jul 2021 07:35:29 +0530 Subject: [PATCH 613/729] Update documentation. --- src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 77dfa29569..657df344d9 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -113,7 +113,8 @@ class BestBinaryNumericSplit * return the value 'bestGain'. If a split is made, then splitInfo and aux * may be modified. * - * This overload is specialized only for MSEGain fitness function. + * This overload is specialized for any fitness function that implements + * BinaryScanInitialize(), BinaryStep() and BinaryGains() functions. * * @param bestGain Best gain seen so far (we'll only split if we find gain * better than this). From de9938ee51fdda645a8c2d0d39422077dc0be5e0 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 12 Jul 2021 19:57:14 +0530 Subject: [PATCH 614/729] Removing unrequired overload of Hessian() --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 50e016524c..a7ffe559a1 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -56,16 +56,6 @@ class SSELoss return - (observed - values); } - /** - * Returns the second order gradient of the loss function with respect to the - * values. This is used only for scalars. - */ - template - T Hessians(const T& /* observed */, const T& /* values */) - { - return (T) 1; - } - /** * Returns the second order gradient of the loss function with respect to the * values. This is used only for vectors. From 25f8f47cb5063120259f390dfb7b4b964eb030dc Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 12 Jul 2021 19:57:32 +0530 Subject: [PATCH 615/729] Add more tests --- src/mlpack/tests/xgboost_test.cpp | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index c34b973399..31f8754569 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -30,3 +30,80 @@ TEST_CASE("SSEInitialPredictionTest", "[XGBTest]") SSELoss Loss; REQUIRE(Loss.InitialPrediction(values) == initPred); } + +/** + * Test that gradients are calculated correctly for SSE Loss. + */ +TEST_CASE("SSEGradientsTest", "[XGBTest]") +{ + arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; + arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; + + // Actual gradients. + arma::vec gradients = {-0.5, -2, 0.5, -0.5, 0, 2, -1, -0.25, 1, 1.5}; + + SSELoss Loss; + // Calculated gradients. + arma::vec calculatedGradients = Loss.Gradients(observed, predicted); + + for (int i = 0; i < 10; i++) + REQUIRE(calculatedGradients[i] == gradients[i]); +} + +/** + * Test that hessians are calculated correctly for SSE Loss. + */ +TEST_CASE("SSEHessiansTest", "[XGBTest]") +{ + arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; + arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; + + // Actual hessians. + arma::vec hessians = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + SSELoss Loss; + // Calculated hessians. + arma::vec calculatedHessians = Loss.Hessians(observed, predicted); + + for (int i = 0; i < 10; i++) + REQUIRE(calculatedHessians[i] == hessians[i]); +} + +/** + * Test that residuals are calculated correctly for SSE Loss. + */ +TEST_CASE("SSEResidualsTest", "[XGBTest]") +{ + arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; + arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; + + // Actual residuals. + arma::vec residuals = {0.5, 2, -0.5, 0.5, 0, -2, 1, 0.25, -1, -1.5}; + + SSELoss Loss; + // Calculated residuals. + arma::vec calculatedResiduals = Loss.Residuals(observed, predicted); + + for (int i = 0; i < 10; i++) + REQUIRE(calculatedResiduals[i] == residuals[i]); +} + +/** + * Test that output value is calculated correctly for SSE Loss. + */ +TEST_CASE("SSEOutputValueTest", "[XGBTest]") +{ + arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; + arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; + + // Actual outut value. + double outputValue = -0.075; + + SSELoss Loss; + // Calculating gradients and hessians for input to OutputValue(). + arma::vec gradients = Loss.Gradients(observed, predicted); + arma::vec hessians = Loss.Hessians(observed, predicted); + + // Lambda = 0; + REQUIRE(Loss.OutputValue(gradients, hessians, 0) == outputValue); +} From c3d65e857123870f74fece6747ec5dfedf2910ea Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Mon, 12 Jul 2021 21:36:17 +0530 Subject: [PATCH 616/729] Simplified methods by removing unnecessary indirections of functions --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index a7ffe559a1..ef86cebf35 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -53,7 +53,7 @@ class SSELoss template T Gradients(const T& observed, const T& values) { - return - (observed - values); + return values - observed; } /** @@ -79,7 +79,7 @@ class SSELoss template VecType Residuals(const VecType& observed, const VecType& f) { - return - Gradients(observed, f); + return observed - f; } /** From 33d83e4db8b53d5407c79d423155b47b3cef7a2c Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Mon, 12 Jul 2021 13:37:08 -0400 Subject: [PATCH 617/729] Fix memory leak. --- src/mlpack/tests/main_tests/linear_svm_test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mlpack/tests/main_tests/linear_svm_test.cpp b/src/mlpack/tests/main_tests/linear_svm_test.cpp index e62680967c..f51c3932fa 100644 --- a/src/mlpack/tests/main_tests/linear_svm_test.cpp +++ b/src/mlpack/tests/main_tests/linear_svm_test.cpp @@ -172,13 +172,15 @@ TEST_CASE_METHOD(LinearSVMTestFixture, "LinearSVMModelReuseTest", RUN_BINDING(); // Get the output model obtained from training. - LinearSVMModel* model = - params.Get("output_model"); + LinearSVMModel* model = params.Get("output_model"); + params.Get("output_model") = NULL; + // Get the output. - const arma::Row& testLabels1 = + arma::Row testLabels1 = std::move(params.Get>("predictions")); // Reset the data passed. + CleanMemory(); ResetSettings(); SetInputParam("input_model", model); From 80f2f51043db850098209bfe270524605b55911e Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Tue, 13 Jul 2021 10:19:54 +0530 Subject: [PATCH 618/729] typo fix in variable Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 17206c595e..b0b339a708 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -41,7 +41,7 @@ BicubicInterpolation( const size_t outRowSize, const size_t outColSize, const size_t depth, - const double aplha): + const double alpha): inRowSize(inRowSize), inColSize(inColSize), outRowSize(outRowSize), From 7634d357402077ca2af614cc6403f0ce2d820a54 Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Tue, 13 Jul 2021 11:54:27 +0530 Subject: [PATCH 619/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 1b3850a6c5..38411a684b 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2182,10 +2182,10 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") size_t depth = 1; double alpha = -0.75; input.zeros(inRowSize * inColSize * depth, 1); - input[0] = 10.0; - input[1] = 20.0; - input[2] = 30.0; - input[3] = 40.0; + + input << 10 << 20 << arma::endr + << 30 << 40 << arma::endr; + BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth, alpha); expectedOutput << 6.6880 << 7.3331 << 9.6973 << 12.7950 << 15.8927 << 18.2569 << 18.9020 << arma::endr From d0ecbf5f85ca75a25b1ea828beab6ec329611bb6 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Jul 2021 07:49:22 +0530 Subject: [PATCH 620/729] Add BinaryGains() to SFINAE check --- .../methods/decision_tree/best_binary_numeric_split.hpp | 8 +++++++- .../decision_tree/best_binary_numeric_split_impl.hpp | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 657df344d9..3f5cd27e65 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -29,6 +29,10 @@ HAS_MEM_FUNC(BinaryScanInitialize, HasBinaryScanInitialize); // we can use with SFINAE to catch when a type has a BinaryStep(...) function. HAS_MEM_FUNC(BinaryStep, HasBinaryStep); +// This gives us a HasBinaryGains type (where U is a function pointer) +// we can use with SFINAE to catch when a type has a BinaryGains(...) function. +HAS_MEM_FUNC(BinaryGains, HasBinaryGains); + /** * The BestBinaryNumericSplit is a splitting function for decision trees that * will exhaustively search a numeric dimension for the best binary split. @@ -134,7 +138,9 @@ class BestBinaryNumericSplit HasBinaryScanInitialize::value && HasBinaryStep::value, + (const ResponsesType&, const WeightVecType&, const size_t)>::value && + HasBinaryGains(FitnessFunction::*)()>::value, double>::type SplitIfBetter( const double bestGain, diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 1913fc0868..3d0ebdc078 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -327,7 +327,9 @@ typename std::enable_if< HasBinaryScanInitialize::value && HasBinaryStep::value, + (const ResponsesType&, const WeightVecType&, const size_t)>::value && + HasBinaryGains(FitnessFunction::*)()>::value, double>::type BestBinaryNumericSplit::SplitIfBetter( const double bestGain, From f6c8e1b3eb79da0b03af8b6afbbdb4afad6710f2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Jul 2021 08:15:59 +0530 Subject: [PATCH 621/729] Add static keyword to function... Doesn't compile yet. --- .../decision_tree/best_binary_numeric_split.hpp | 14 +++++++++++--- .../best_binary_numeric_split_impl.hpp | 12 ++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 3f5cd27e65..6114b7e1b9 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -101,7 +101,15 @@ class BestBinaryNumericSplit */ template - static double SplitIfBetter( + static typename std::enable_if< + !HasBinaryScanInitialize::value && + !HasBinaryStep::value && + !HasBinaryGains(FitnessFunction::*)(void)>::value, + double>::type + SplitIfBetter( const double bestGain, const VecType& data, const ResponsesType& responses, @@ -134,13 +142,13 @@ class BestBinaryNumericSplit */ template - typename std::enable_if< + static typename std::enable_if< HasBinaryScanInitialize::value && HasBinaryStep::value && HasBinaryGains(FitnessFunction::*)()>::value, + std::tuple(FitnessFunction::*)(void)>::value, double>::type SplitIfBetter( const double bestGain, diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 3d0ebdc078..76fb90df95 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -189,7 +189,15 @@ double BestBinaryNumericSplit::SplitIfBetter( template template -double BestBinaryNumericSplit::SplitIfBetter( +typename std::enable_if< + !HasBinaryScanInitialize::value && + !HasBinaryStep::value && + !HasBinaryGains(FitnessFunction::*)(void)>::value, + double>::type +BestBinaryNumericSplit::SplitIfBetter( const double bestGain, const VecType& data, const ResponsesType& responses, @@ -329,7 +337,7 @@ typename std::enable_if< HasBinaryStep::value && HasBinaryGains(FitnessFunction::*)()>::value, + std::tuple(FitnessFunction::*)(void)>::value, double>::type BestBinaryNumericSplit::SplitIfBetter( const double bestGain, From 167667785056fe1d2b6a8d79b8ad6717f6c9a09c Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Jul 2021 08:17:29 +0530 Subject: [PATCH 622/729] Change auto to std::tuple --- .../methods/decision_tree/best_binary_numeric_split_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 76fb90df95..486a1ac370 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -429,7 +429,7 @@ BestBinaryNumericSplit::SplitIfBetter( continue; // Calculate the gain for the left and right child. - auto binaryGains = fitnessFunction.BinaryGains(); + std::tuple binaryGains = fitnessFunction.BinaryGains(); const double leftGain = std::get<0>(binaryGains); const double rightGain = std::get<1>(binaryGains); From edb9879f2a185eff4f8b4d1ba3945b746137a5cf Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sat, 10 Jul 2021 08:22:03 +0530 Subject: [PATCH 623/729] Update HISTORY.md Co-authored-by: Ryan Curtin --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 08909cde5f..80d463881a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ ###### ????-??-?? * Added Decision Tree Regressor (#2905). It can be used using the class `mlpack::tree::DecisionTreeRegressor`. It is accessible only though C++. + * Added dict-style inspection of mlpack models in python bindings (#2868). * Added Extra Trees Algorithm (#2883). Currently, it can be used using the From 64c84846f052a3fe1779c1a630ad8cca93fafeee Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Sun, 11 Jul 2021 10:49:49 +0530 Subject: [PATCH 624/729] Removing template function checks is failing too --- .../methods/decision_tree/best_binary_numeric_split.hpp | 8 -------- .../decision_tree/best_binary_numeric_split_impl.hpp | 9 +-------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 6114b7e1b9..18919900a3 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -102,10 +102,6 @@ class BestBinaryNumericSplit template static typename std::enable_if< - !HasBinaryScanInitialize::value && - !HasBinaryStep::value && !HasBinaryGains(FitnessFunction::*)(void)>::value, double>::type @@ -143,10 +139,6 @@ class BestBinaryNumericSplit template static typename std::enable_if< - HasBinaryScanInitialize::value && - HasBinaryStep::value && HasBinaryGains(FitnessFunction::*)(void)>::value, double>::type diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 486a1ac370..9b77cbb29f 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -190,10 +190,6 @@ template template typename std::enable_if< - !HasBinaryScanInitialize::value && - !HasBinaryStep::value && !HasBinaryGains(FitnessFunction::*)(void)>::value, double>::type @@ -332,10 +328,6 @@ template template typename std::enable_if< - HasBinaryScanInitialize::value && - HasBinaryStep::value && HasBinaryGains(FitnessFunction::*)(void)>::value, double>::type @@ -349,6 +341,7 @@ BestBinaryNumericSplit::SplitIfBetter( double& splitInfo, AuxiliarySplitInfo& /* aux */) { + std::cout << "Optimized\n"; typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; From 0f4bd653cfe096f2617481f20c71d717087591ac Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 13 Jul 2021 08:05:34 +0530 Subject: [PATCH 625/729] Fix the SFINAE bug with @rcurtin's patch --- .../best_binary_numeric_split.hpp | 30 +++++++++++-------- .../best_binary_numeric_split_impl.hpp | 10 +++---- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index 18919900a3..a39ac91d8f 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -20,19 +20,25 @@ namespace mlpack { namespace tree { -// This gives us a HasBinaryScanInitialize type (where U is a function -// pointer) we can use with SFINAE to catch when a type has a -// BinaryScanInitialize(...) function. -HAS_MEM_FUNC(BinaryScanInitialize, HasBinaryScanInitialize); - -// This gives us a HasBinaryStep type (where U is a function pointer) -// we can use with SFINAE to catch when a type has a BinaryStep(...) function. -HAS_MEM_FUNC(BinaryStep, HasBinaryStep); - // This gives us a HasBinaryGains type (where U is a function pointer) // we can use with SFINAE to catch when a type has a BinaryGains(...) function. HAS_MEM_FUNC(BinaryGains, HasBinaryGains); +// This struct will have `value` set to `true` if a BinaryGains() function of +// the right signature is detected. We only check for BinaryGains(), and not +// BinaryScanInitialize() or BinaryStep(), because those two are template +// members functions and would make this check far more difficult. +// +// The unused UseWeights template parameter is necessary to ensure that the +// compiler thinks the result `value` depends on a parameter specific to the +// SplitIfBetter() function in BestBinaryNumericSplit(). +template +struct HasOptimizedBinarySplitForms +{ + const static bool value = HasBinaryGains(T::*)()>::value; +}; + /** * The BestBinaryNumericSplit is a splitting function for decision trees that * will exhaustively search a numeric dimension for the best binary split. @@ -102,8 +108,7 @@ class BestBinaryNumericSplit template static typename std::enable_if< - !HasBinaryGains(FitnessFunction::*)(void)>::value, + !HasOptimizedBinarySplitForms::value, double>::type SplitIfBetter( const double bestGain, @@ -139,8 +144,7 @@ class BestBinaryNumericSplit template static typename std::enable_if< - HasBinaryGains(FitnessFunction::*)(void)>::value, + HasOptimizedBinarySplitForms::value, double>::type SplitIfBetter( const double bestGain, diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 9b77cbb29f..6a69194153 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -190,8 +190,7 @@ template template typename std::enable_if< - !HasBinaryGains(FitnessFunction::*)(void)>::value, + !HasOptimizedBinarySplitForms::value, double>::type BestBinaryNumericSplit::SplitIfBetter( const double bestGain, @@ -328,8 +327,7 @@ template template typename std::enable_if< - HasBinaryGains(FitnessFunction::*)(void)>::value, + HasOptimizedBinarySplitForms::value, double>::type BestBinaryNumericSplit::SplitIfBetter( const double bestGain, @@ -401,7 +399,7 @@ BestBinaryNumericSplit::SplitIfBetter( // Initialize and precompute various statistics to efficiently compute gain // values for all possible splits. - fitnessFunction.BinaryScanInitialize(sortedResponses, + fitnessFunction.template BinaryScanInitialize(sortedResponses, sortedWeights, minimum); // Loop through all possible split points, choosing the best one. @@ -414,7 +412,7 @@ BestBinaryNumericSplit::SplitIfBetter( } // Steps through the current index and updates the cached data. - fitnessFunction.BinaryStep(sortedResponses, + fitnessFunction.template BinaryStep(sortedResponses, sortedWeights, index - 1); // Make sure that the value has changed. From ff5892cc7ec66b349be7de5b9ccc78179fe7dd10 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 13 Jul 2021 08:06:37 +0530 Subject: [PATCH 626/729] Update comment --- .../methods/decision_tree/best_binary_numeric_split_impl.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 6a69194153..68d02ecb17 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -322,7 +322,8 @@ BestBinaryNumericSplit::SplitIfBetter( return bestFoundGain; } -// Optimized version when fitness function is MSEGain. +// Optimized version for any fitness function that implements +// BinaryScanInitialize(), BinaryStep() and BinaryGains() functions. template template From 18e609efc0a945a23ff64a2e5edbe1b7bf190743 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 13 Jul 2021 08:07:13 +0530 Subject: [PATCH 627/729] Removed debugging print statement --- .../methods/decision_tree/best_binary_numeric_split_impl.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 68d02ecb17..0f20f97145 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -340,7 +340,6 @@ BestBinaryNumericSplit::SplitIfBetter( double& splitInfo, AuxiliarySplitInfo& /* aux */) { - std::cout << "Optimized\n"; typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; From 9a7290a47d0cf1829e583df831a9c22f751fd9e1 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 13 Jul 2021 13:50:08 +0530 Subject: [PATCH 628/729] Attempt to fix tuple error --- src/mlpack/methods/decision_tree/mse_gain.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 3752319e4f..2516351d80 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -112,7 +112,7 @@ class MSEGain double mseRight = (totalSumSquares - leftSumSquares) / rightSize - rightMean * rightMean; - return {-mseLeft, -mseRight}; + return std::make_tuple(-mseLeft, -mseRight); } /** From 0858305c77b7fda169e3c51d8c518afdd3672aec Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Tue, 13 Jul 2021 14:23:22 +0530 Subject: [PATCH 629/729] Made FitnessFunction::Evaluate a non-static member function. --- .../all_categorical_split_impl.hpp | 4 +- .../best_binary_numeric_split_impl.hpp | 6 +- .../decision_tree_regressor_impl.hpp | 8 ++- src/mlpack/methods/decision_tree/mad_gain.hpp | 12 ++-- src/mlpack/methods/decision_tree/mse_gain.hpp | 12 ++-- .../random_binary_numeric_split_impl.hpp | 6 +- .../tests/decision_tree_regressor_test.cpp | 61 ++++++++++++------- 7 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index cda19da51f..1256436f79 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -127,6 +127,8 @@ double AllCategoricalSplit::SplitIfBetter( double& splitInfo, AuxiliarySplitInfo& /* aux */) { + FitnessFunction fitnessFunction; + // Count the number of elements in each potential child. const double epsilon = 1e-7; // Tolerance for floating-point errors. arma::Col counts(numCategories, arma::fill::zeros); @@ -190,7 +192,7 @@ double AllCategoricalSplit::SplitIfBetter( const double childPct = UseWeights ? double(childWeightSums[i]) / sumWeight : double(counts[i]) / double(data.n_elem); - const double childGain = FitnessFunction::template Evaluate( + const double childGain = fitnessFunction.template Evaluate( childResponses[i], childWeights[i]); overallGain += childPct * childGain; diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 0f20f97145..7ece8f3f9a 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -205,6 +205,8 @@ BestBinaryNumericSplit::SplitIfBetter( typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; + FitnessFunction fitnessFunction; + // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) return DBL_MAX; @@ -270,9 +272,9 @@ BestBinaryNumericSplit::SplitIfBetter( continue; // Calculate the gain for the left and right child. - const double leftGain = FitnessFunction::template + const double leftGain = fitnessFunction.template Evaluate(sortedResponses, sortedWeights, 0, index); - const double rightGain = FitnessFunction::template + const double rightGain = fitnessFunction.template Evaluate(sortedResponses, sortedWeights, index, responses.n_elem); diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 31a63fedd0..5e0b7339ca 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -607,6 +607,8 @@ double DecisionTreeRegressor( + double bestGain = fitnessFunction.template Evaluate( responses.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = datasetInfo.Dimensionality(); // This means "no split". @@ -786,6 +788,8 @@ double DecisionTreeRegressor( + double bestGain = fitnessFunction.template Evaluate( responses.subvec(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = data.n_rows; // This means "no split". diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 5e2e519dc4..56c5087306 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -43,10 +43,10 @@ class MADGain * @param end End index. */ template - static double Evaluate(const VecType& values, - const WeightVecType& weights, - const size_t begin, - const size_t end) + double Evaluate(const VecType& values, + const WeightVecType& weights, + const size_t begin, + const size_t end) { double mad = 0.0; @@ -89,8 +89,8 @@ class MADGain * @param weights Weights associated to each value. */ template - static double Evaluate(const VecType& values, - const WeightVecType& weights) + double Evaluate(const VecType& values, + const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. if (values.n_elem == 0) diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index 2516351d80..e4e9c0ff3b 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -41,10 +41,10 @@ class MSEGain * @param end End index. */ template - static double Evaluate(const VecType& values, - const WeightVecType& weights, - const size_t begin, - const size_t end) + double Evaluate(const VecType& values, + const WeightVecType& weights, + const size_t begin, + const size_t end) { double mse = 0.0; @@ -85,8 +85,8 @@ class MSEGain * @param weights Weights associated to each value. */ template - static double Evaluate(const VecType& values, - const WeightVecType& weights) + double Evaluate(const VecType& values, + const WeightVecType& weights) { // Corner case: if there are no elements, the impurity is zero. if (values.n_elem == 0) diff --git a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp index 4d459798b1..a9f03396dc 100644 --- a/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/random_binary_numeric_split_impl.hpp @@ -151,6 +151,8 @@ double RandomBinaryNumericSplit::SplitIfBetter( AuxiliarySplitInfo& /* aux */, const bool splitIfBetterGain) { + FitnessFunction fitnessFunction; + double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); // Forcing a minimum leaf size of 1 (empty children don't make sense). const size_t minimum = std::max(minimumLeafSize, (size_t) 1); @@ -230,9 +232,9 @@ double RandomBinaryNumericSplit::SplitIfBetter( } // Calculate the gain for the left and right child. - const double leftGain = FitnessFunction::template + const double leftGain = fitnessFunction.template Evaluate(leftResponses, leftWeights, 0, leftLeafSize); - const double rightGain = FitnessFunction::template + const double rightGain = fitnessFunction.template Evaluate(rightResponses, rightWeights, 0, rightLeafSize); // Calculate the gain at this split point. diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index cafde0cc4d..c7909aaeab 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -77,7 +77,8 @@ TEST_CASE("MSEGainPerfectTest", "[DecisionTreeRegressorTest]") arma::rowvec responses; responses.ones(10); - REQUIRE(MSEGain::Evaluate(responses, weights) == + MSEGain Gain; + REQUIRE(Gain.Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -88,10 +89,12 @@ TEST_CASE("MSEGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); arma::rowvec responses; - REQUIRE(MSEGain::Evaluate(responses, weights) == + + MSEGain Gain; + REQUIRE(Gain.Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(responses, weights) == + REQUIRE(Gain.Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -107,9 +110,11 @@ TEST_CASE("MSEGainHandCalculation", "[DecisionTreeRegressorTest]") // Hand calculated gain values. const double gain = -27.08999; const double weightedGain = -27.53960; - REQUIRE(MSEGain::Evaluate(responses, weights) == + + MSEGain Gain; + REQUIRE(Gain.Evaluate(responses, weights) == Approx(gain).margin(1e-5)); - REQUIRE(MSEGain::Evaluate(responses, weights) == + REQUIRE(Gain.Evaluate(responses, weights) == Approx(weightedGain).margin(1e-5)); } @@ -122,7 +127,8 @@ TEST_CASE("MADGainPerfectTest", "[DecisionTreeRegressorTest]") arma::rowvec responses; responses.ones(10); - REQUIRE(MADGain::Evaluate(responses, weights) == + MADGain Gain; + REQUIRE(Gain.Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -142,8 +148,8 @@ TEST_CASE("MADGainNormalTest", "[DecisionTreeRegressorTest") theoreticalGain /= (double) responses.n_elem; // Calculated gain. - const double calculatedGain = - MADGain::Evaluate(responses, weights); + MADGain Gain; + const double calculatedGain = Gain.Evaluate(responses, weights); REQUIRE(calculatedGain == Approx(theoreticalGain).margin(1e-5)); } @@ -155,10 +161,12 @@ TEST_CASE("MADGainEmptyTest", "[DecisionTreeRegressorTest]") { arma::rowvec weights = arma::ones(10); arma::rowvec responses; - REQUIRE(MADGain::Evaluate(responses, weights) == + + MADGain Gain; + REQUIRE(Gain.Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); - REQUIRE(MADGain::Evaluate(responses, weights) == + REQUIRE(Gain.Evaluate(responses, weights) == Approx(0.0).margin(1e-5)); } @@ -174,9 +182,11 @@ TEST_CASE("MADGainHandCalculation", "[DecisionTreeRegressorTest]") // Hand calculated gain values. const double gain = -4.1; const double weightedGain = -3.8592; - REQUIRE(MADGain::Evaluate(responses, weights) == + + MADGain Gain; + REQUIRE(Gain.Evaluate(responses, weights) == Approx(gain).margin(1e-5)); - REQUIRE(MADGain::Evaluate(responses, weights) == + REQUIRE(Gain.Evaluate(responses, weights) == Approx(weightedGain).margin(1e-5)); } @@ -203,7 +213,8 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( bestGain, predictor, 2, responses, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = @@ -234,7 +245,8 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( bestGain, predictors, 4, responses, weights, 4, 1e-7, splitInfo, aux); @@ -265,7 +277,8 @@ TEST_CASE("AllCategoricalSplitNoGainTest_", "[DecisionTreeRegressorTest]") AllCategoricalSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( bestGain, predictors, 10, responses, weights, 10, 1e-7, splitInfo, aux); @@ -296,7 +309,8 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MADGain::Evaluate(responses, weights); + MADGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( bestGain, predictors, responses, weights, 3, 1e-7, splitInfo, aux); const double weightedGain = @@ -332,7 +346,8 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( bestGain, predictors, responses, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. @@ -366,7 +381,8 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") BestBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( bestGain, predictors, responses, weights, 10, 1e-7, splitInfo, aux); @@ -390,7 +406,8 @@ TEST_CASE("RandomBinaryNumericSplitAlwaysSplit_", RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, responses, weights, 1, 1e-7, splitInfo, aux); const double weightedGain = @@ -417,7 +434,8 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest_", RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, responses, weights, 8, 1e-7, splitInfo, aux); // This should make no difference because it won't split at all. @@ -451,7 +469,8 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") RandomBinaryNumericSplit::AuxiliarySplitInfo aux; // Call the method to do the splitting. - const double bestGain = MSEGain::Evaluate(responses, weights); + MSEGain Gain; + const double bestGain = Gain.Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( bestGain, values, responses, weights, 10, 1e-7, splitInfo, aux, true); From 94fdb609f0ded649de64c6096e916cdd9279e383 Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Tue, 13 Jul 2021 14:57:49 +0530 Subject: [PATCH 630/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 38411a684b..f24e678c00 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2195,7 +2195,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") << 31.0980 << 31.7431 << 34.1073 << 37.2050 << 40.3027 << 42.6669 << 43.3120 << arma::endr; expectedOutput.reshape(35, 1); layer.Forward(input, output); - CheckMatrices(output, expectedOutput, 1e-4); + CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); } /** From f63a13f643278efbc6e67953761fbefa5c1577a0 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 13 Jul 2021 14:18:40 -0400 Subject: [PATCH 631/729] Adapt go bindings to use Params and Timers objects. --- CMake/go/AppendModel.cmake | 18 +- CMake/go/ConfigureGoHCPP.cmake | 20 +- src/mlpack/bindings/go/generate_go.cpp.in | 10 +- src/mlpack/bindings/go/go_method.cpp.in | 10 +- src/mlpack/bindings/go/go_method.h.in | 2 +- src/mlpack/bindings/go/go_option.hpp | 62 +++---- src/mlpack/bindings/go/mlpack/arma_util.go | 151 ++++++++------- .../bindings/go/mlpack/capi/arma_util.cpp | 172 ++++++++++++------ .../bindings/go/mlpack/capi/arma_util.h | 87 +++++---- .../bindings/go/mlpack/capi/io_util.cpp | 168 +++++++++++------ src/mlpack/bindings/go/mlpack/capi/io_util.h | 75 +++++--- .../bindings/go/mlpack/capi/io_util.hpp | 21 +-- src/mlpack/bindings/go/mlpack/io_util.go | 122 ++++++++----- .../bindings/go/print_doc_functions.hpp | 19 +- .../bindings/go/print_doc_functions_impl.hpp | 101 ++++++---- src/mlpack/bindings/go/print_go.cpp | 69 ++++--- src/mlpack/bindings/go/print_go.hpp | 9 +- .../bindings/go/print_input_processing.hpp | 55 +++--- .../bindings/go/print_output_processing.hpp | 18 +- .../go/tests/test_go_binding_main.cpp | 94 +++++----- .../markdown/generate_markdown.binding.cpp.in | 1 - src/mlpack/bindings/markdown/print_docs.cpp | 9 +- src/mlpack/bindings/python/py_option.hpp | 9 +- src/mlpack/core/util/mlpack_main.hpp | 21 +-- src/mlpack/methods/hmm/hmm_generate_main.cpp | 2 +- src/mlpack/methods/hmm/hmm_loglik_main.cpp | 2 +- .../methods/linear_svm/linear_svm_main.cpp | 2 +- src/mlpack/methods/nca/nca_main.cpp | 2 +- .../preprocess/image_converter_main.cpp | 2 +- src/mlpack/methods/radical/radical_main.cpp | 2 +- 30 files changed, 770 insertions(+), 565 deletions(-) diff --git a/CMake/go/AppendModel.cmake b/CMake/go/AppendModel.cmake index ec85510239..bb531adf6f 100644 --- a/CMake/go/AppendModel.cmake +++ b/CMake/go/AppendModel.cmake @@ -64,18 +64,20 @@ function(append_model SERIALIZATION_FILE PROGRAM_MAIN_FILE) " mem unsafe.Pointer \n" "}\n\n" "func (m *${GOMODEL_SAFE_TYPE}) alloc" - "${MODEL_SAFE_TYPE}(identifier string) {\n" - " m.mem = C.mlpackGet${MODEL_SAFE_TYPE}Ptr(C.CString(identifier))\n" + "${MODEL_SAFE_TYPE}(params *params, identifier string) {\n" + " m.mem = C.mlpackGet${MODEL_SAFE_TYPE}Ptr(params.mem,\n" + " C.CString(identifier))\n" " runtime.KeepAlive(m)\n" "}\n\n" "func (m *${GOMODEL_SAFE_TYPE}) get" - "${MODEL_SAFE_TYPE}(identifier string) {\n" - " m.alloc${MODEL_SAFE_TYPE}(identifier)\n" + "${MODEL_SAFE_TYPE}(params *params, identifier string) {\n" + " m.alloc${MODEL_SAFE_TYPE}(params, identifier)\n" "}\n\n" - "func set${MODEL_SAFE_TYPE}(identifier string, ptr *" - "${GOMODEL_SAFE_TYPE}) {\n" - " C.mlpackSet${MODEL_SAFE_TYPE}" - "Ptr(C.CString(identifier), (unsafe.Pointer)(ptr.mem))\n" + "func set${MODEL_SAFE_TYPE}(params* params,\n" + " identifier string,\n" + " ptr *${GOMODEL_SAFE_TYPE}) {\n" + " C.mlpackSet${MODEL_SAFE_TYPE}Ptr(params.mem,\n" + " C.CString(identifier), ptr.mem)\n" "}\n\n") endif() endforeach () diff --git a/CMake/go/ConfigureGoHCPP.cmake b/CMake/go/ConfigureGoHCPP.cmake index a4cb3c4b14..0b035937b2 100644 --- a/CMake/go/ConfigureGoHCPP.cmake +++ b/CMake/go/ConfigureGoHCPP.cmake @@ -24,10 +24,13 @@ if (${NUM_MODEL_TYPES} GREATER 0) # Generate the definition. set(MODEL_PTR_DEFNS "${MODEL_PTR_DEFNS} // Set the pointer to a ${MODEL_TYPE} parameter. -extern void mlpackSet${MODEL_SAFE_TYPE}Ptr(const char* identifier, void* value); +extern void mlpackSet${MODEL_SAFE_TYPE}Ptr(void* params, + const char* identifier, + void* value); // Get the pointer to a ${MODEL_TYPE} parameter. -extern void* mlpackGet${MODEL_SAFE_TYPE}Ptr(const char* identifier); +extern void* mlpackGet${MODEL_SAFE_TYPE}Ptr(void* params, + const char* identifier); " ) @@ -35,17 +38,22 @@ extern void* mlpackGet${MODEL_SAFE_TYPE}Ptr(const char* identifier); set(MODEL_PTR_IMPLS "${MODEL_PTR_IMPLS} // Set the pointer to a ${MODEL_TYPE} parameter. extern \"C\" void mlpackSet${MODEL_SAFE_TYPE}Ptr( + void* params, const char* identifier, void* value) { - mlpack::util::SetParamPtr<${MODEL_TYPE}>(identifier, - static_cast<${MODEL_TYPE}*>(value)); + util::Params& p = *((util::Params*) params); + mlpack::util::SetParamPtr<${MODEL_TYPE}>(p, identifier, + static_cast<${MODEL_TYPE}*>(value)); } // Get the pointer to a ${MODEL_TYPE} parameter. -extern \"C\" void *mlpackGet${MODEL_SAFE_TYPE}Ptr(const char* identifier) +extern \"C\" void *mlpackGet${MODEL_SAFE_TYPE}Ptr( + void* params, + const char* identifier) { - ${MODEL_TYPE} *modelptr = IO::GetParam<${MODEL_TYPE}*>(identifier); + util::Params& p = *((util::Params*) params); + ${MODEL_TYPE} *modelptr = p.Get<${MODEL_TYPE}*>(identifier); return modelptr; } ") diff --git a/src/mlpack/bindings/go/generate_go.cpp.in b/src/mlpack/bindings/go/generate_go.cpp.in index 0e75e9c4cd..fd4b7ae36f 100644 --- a/src/mlpack/bindings/go/generate_go.cpp.in +++ b/src/mlpack/bindings/go/generate_go.cpp.in @@ -28,11 +28,12 @@ #include #include -#include // This will include the ParamData options that are a part of the program. #include <${PROGRAM_MAIN_FILE}> +#include + using namespace mlpack; using namespace mlpack::bindings; using namespace mlpack::bindings::go; @@ -41,9 +42,8 @@ using namespace mlpack::util; int main(int /* argc */, char** /* argv */) { - // All the parameters are registered, but stored, so restore them. - // programName is defined in mlpack_main.hpp. - IO::RestoreSettings(programName); + // All the parameters are registered. + util::Params p = IO::Parameters(STRINGIFY(BINDING_NAME)); - PrintGo(IO::GetSingleton().doc, "${PROGRAM_NAME}"); + PrintGo(p, p.Doc(), "${PROGRAM_NAME}", STRINGIFY(BINDING_NAME)); } diff --git a/src/mlpack/bindings/go/go_method.cpp.in b/src/mlpack/bindings/go/go_method.cpp.in index 93127ba92a..5108b48d92 100644 --- a/src/mlpack/bindings/go/go_method.cpp.in +++ b/src/mlpack/bindings/go/go_method.cpp.in @@ -8,14 +8,12 @@ #include <${PROGRAM_MAIN_FILE}> #include -static void ${GOPROGRAM_NAME}MlpackMain() +extern "C" void mlpack${GOPROGRAM_NAME}(void* params, void* timers) { - mlpackMain(); -} + util::Params& p = *((util::Params*) params); + util::Timers& t = *((util::Timers*) timers); -extern "C" void mlpack${GOPROGRAM_NAME}() -{ - ${GOPROGRAM_NAME}MlpackMain(); + BINDING_FUNCTION(p, t); } // Any implementations of methods for dealing with model pointers will be put diff --git a/src/mlpack/bindings/go/go_method.h.in b/src/mlpack/bindings/go/go_method.h.in index da269eff93..f152451c3b 100644 --- a/src/mlpack/bindings/go/go_method.h.in +++ b/src/mlpack/bindings/go/go_method.h.in @@ -15,7 +15,7 @@ extern "C" { #endif -extern void mlpack${GOPROGRAM_NAME}(); +extern void mlpack${GOPROGRAM_NAME}(void* params, void* timers); // Any definitions of methods for dealing with model pointers will be put below // this comment, if needed. diff --git a/src/mlpack/bindings/go/go_option.hpp b/src/mlpack/bindings/go/go_option.hpp index a6607fe47f..f566ccea6d 100644 --- a/src/mlpack/bindings/go/go_option.hpp +++ b/src/mlpack/bindings/go/go_option.hpp @@ -29,9 +29,6 @@ namespace mlpack { namespace bindings { namespace go { -// Defined in mlpack_main.hpp. -extern std::string programName; - /** * The Go option class. */ @@ -65,7 +62,7 @@ class GoOption const bool required = false, const bool input = true, const bool noTranspose = false, - const std::string& /*testName*/ = "") + const std::string& bindingName = "") { // Create the ParamData object to give to IO. util::ParamData data; @@ -83,41 +80,36 @@ class GoOption data.value = boost::any(defaultValue); - // Restore the parameters for this program. - if (identifier != "verbose" /*&& identifier != "copy_all_inputs"*/) - IO::RestoreSettings(programName, false); - // Set the function pointers that we'll need. All of these function // pointers will be used by both the program that generates the .cpp, // the .h, and the .go binding files. - IO::GetSingleton().functionMap[data.tname]["GetParam"] = &GetParam; - IO::GetSingleton().functionMap[data.tname]["GetPrintableParam"] = - &GetPrintableParam; + IO::AddFunction(data.tname, "GetParam", &GetParam); + IO::AddFunction(data.tname, "GetPrintableParam", &GetPrintableParam); + IO::AddFunction(data.tname, "DefaultParam", &DefaultParam); + IO::AddFunction(data.tname, "PrintDefnInput", &PrintDefnInput); + IO::AddFunction(data.tname, "PrintDefnOutput", &PrintDefnOutput); + IO::AddFunction(data.tname, "PrintDoc", &PrintDoc); + IO::AddFunction(data.tname, "PrintOutputProcessing", + &PrintOutputProcessing); + IO::AddFunction(data.tname, "PrintMethodConfig", &PrintMethodConfig); + IO::AddFunction(data.tname, "PrintMethodInit", &PrintMethodInit); + IO::AddFunction(data.tname, "PrintInputProcessing", + &PrintInputProcessing); + IO::AddFunction(data.tname, "GetType", &GetType); - IO::GetSingleton().functionMap[data.tname]["DefaultParam"] = - &DefaultParam; - IO::GetSingleton().functionMap[data.tname]["PrintDefnInput"] = - &PrintDefnInput; - IO::GetSingleton().functionMap[data.tname]["PrintDefnOutput"] = - &PrintDefnOutput; - IO::GetSingleton().functionMap[data.tname]["PrintDoc"] = &PrintDoc; - IO::GetSingleton().functionMap[data.tname]["PrintOutputProcessing"] = - &PrintOutputProcessing; - IO::GetSingleton().functionMap[data.tname]["PrintMethodConfig"] = - &PrintMethodConfig; - IO::GetSingleton().functionMap[data.tname]["PrintMethodInit"] = - &PrintMethodInit; - IO::GetSingleton().functionMap[data.tname]["PrintInputProcessing"] = - &PrintInputProcessing; - IO::GetSingleton().functionMap[data.tname]["GetType"] = &GetType; - - // Add the ParamData object, then store. This is necessary because we may - // import more than one .so that uses IO, so we have to keep the options - // separate. programName is a global variable from mlpack_main.hpp. - IO::Add(std::move(data)); - if (identifier != "verbose" /*&& identifier != "copy_all_inputs"*/) - IO::StoreSettings(programName); - IO::ClearSettings(); + // Add the ParamData object to the IO class for the correct binding name. + if (identifier != "verbose") + { + IO::AddParameter(bindingName, std::move(data)); + } + else + { + // This is a total hack! + // TODO: remove this when the macro solution in mlpack_main.hpp is fixed. + util::Params p = IO::Parameters(""); + if (p.Parameters().count("verbose") == 0) + IO::AddParameter("", std::move(data)); + } } }; diff --git a/src/mlpack/bindings/go/mlpack/arma_util.go b/src/mlpack/bindings/go/mlpack/arma_util.go index 84dacfd042..6657f1ce15 100644 --- a/src/mlpack/bindings/go/mlpack/arma_util.go +++ b/src/mlpack/bindings/go/mlpack/arma_util.go @@ -18,7 +18,6 @@ import ( ) type mlpackArma struct { - mem unsafe.Pointer } @@ -26,7 +25,7 @@ type mlpackArma struct { // (Categoricals) indicating which dimensions are categorical (represented by // `true`) and which are numeric (represented by `false`). The number of // elements in the boolean array should be the same as the dimensionality of -// the data matrix. It is expected that each row of the matrix corresponds to a +// the data matrix. It is expected that each row of the matrix corresponds to a // single data point when calling mlpack bindings. type matrixWithInfo struct { Categoricals []bool @@ -43,55 +42,56 @@ func DataAndInfo() *matrixWithInfo { // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrMat(identifier string) { - m.mem = C.mlpackArmaPtrMat(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrMat(p *params, identifier string) { + m.mem = C.mlpackArmaPtrMat(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrUmat(identifier string) { - m.mem = C.mlpackArmaPtrUmat(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrUmat(p *params, identifier string) { + m.mem = C.mlpackArmaPtrUmat(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrRow(identifier string) { - m.mem = C.mlpackArmaPtrRow(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrRow(p *params, identifier string) { + m.mem = C.mlpackArmaPtrRow(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrUrow(identifier string) { - m.mem = C.mlpackArmaPtrUrow(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrUrow(p *params, identifier string) { + m.mem = C.mlpackArmaPtrUrow(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrCol(identifier string) { - m.mem = C.mlpackArmaPtrCol(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrCol(p *params, identifier string) { + m.mem = C.mlpackArmaPtrCol(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrUcol(identifier string) { - m.mem = C.mlpackArmaPtrUcol(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrUcol(p *params, identifier string) { + m.mem = C.mlpackArmaPtrUcol(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Allocates a C memory Pointer via cgo and registers the finalizer // in order to free the C memory once the input has been registered in Go. -func (m *mlpackArma) allocArmaPtrMatWithInfo(identifier string) { - m.mem = C.mlpackArmaPtrMatWithInfoPtr(C.CString(identifier)) +func (m *mlpackArma) allocArmaPtrMatWithInfo(p *params, + identifier string) { + m.mem = C.mlpackArmaPtrMatWithInfoPtr(p.mem, C.CString(identifier)) runtime.KeepAlive(m) } // Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func gonumToArmaMat(identifier string, m *mat.Dense) { +func gonumToArmaMat(p *params, identifier string, m *mat.Dense) { // Get the number of elements in the Armadillo column. r, c := m.Dims() blas64General := m.RawMatrix() @@ -99,11 +99,12 @@ func gonumToArmaMat(identifier string, m *mat.Dense) { // Pass pointer of the underlying matrix to mlpack. ptr := unsafe.Pointer(&data[0]) - C.mlpackToArmaMat(C.CString(identifier), (*C.double)(ptr), C.size_t(c), C.size_t(r)) + C.mlpackToArmaMat(p.mem, C.CString(identifier), (*C.double)(ptr), + C.size_t(c), C.size_t(r)) } // Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func gonumToArmaUmat(identifier string, m *mat.Dense) { +func gonumToArmaUmat(p *params, identifier string, m *mat.Dense) { // Get the number of elements in the Armadillo column. r, c := m.Dims() blas64General := m.RawMatrix() @@ -111,11 +112,12 @@ func gonumToArmaUmat(identifier string, m *mat.Dense) { // Pass pointer of the underlying matrix to mlpack. ptr := unsafe.Pointer(&data[0]) - C.mlpackToArmaUmat(C.CString(identifier), (*C.double)(ptr), C.size_t(c), C.size_t(r)) + C.mlpackToArmaUmat(p.mem, C.CString(identifier), (*C.double)(ptr), + C.size_t(c), C.size_t(r)) } // Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func gonumToArmaRow(identifier string, m *mat.Dense) { +func gonumToArmaRow(p *params, identifier string, m *mat.Dense) { // Get the number of elements in the Armadillo column. e, err := m.Dims() if (err != 1 && e != 1){ @@ -133,11 +135,12 @@ func gonumToArmaRow(identifier string, m *mat.Dense) { // Pass pointer of the underlying matrix to mlpack. ptr := unsafe.Pointer(&data[0]) - C.mlpackToArmaRow(C.CString(identifier), (*C.double)(ptr), C.size_t(e)) + C.mlpackToArmaRow(p.mem, C.CString(identifier), (*C.double)(ptr), + C.size_t(e)) } // Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func gonumToArmaUrow(identifier string, m *mat.Dense) { +func gonumToArmaUrow(p *params, identifier string, m *mat.Dense) { // Get the number of elements in the Armadillo column. e, err := m.Dims() if (err != 1 && e != 1){ @@ -155,11 +158,12 @@ func gonumToArmaUrow(identifier string, m *mat.Dense) { // Pass pointer of the underlying matrix to mlpack. ptr := unsafe.Pointer(&data[0]) - C.mlpackToArmaUrow(C.CString(identifier), (*C.double)(ptr), C.size_t(e)) + C.mlpackToArmaUrow(p.mem, C.CString(identifier), (*C.double)(ptr), + C.size_t(e)) } // Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func gonumToArmaCol(identifier string, m *mat.Dense) { +func gonumToArmaCol(p *params, identifier string, m *mat.Dense) { // Get the number of elements in the Armadillo column. err, e := m.Dims() if (err != 1 && e != 1){ @@ -177,11 +181,12 @@ func gonumToArmaCol(identifier string, m *mat.Dense) { // Pass pointer of the underlying matrix to mlpack. ptr := unsafe.Pointer(&data[0]) - C.mlpackToArmaCol(C.CString(identifier), (*C.double)(ptr), C.size_t(e)) + C.mlpackToArmaCol(p.mem, C.CString(identifier), (*C.double)(ptr), + C.size_t(e)) } // Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func gonumToArmaUcol(identifier string, m *mat.Dense) { +func gonumToArmaUcol(p *params, identifier string, m *mat.Dense) { // Get the number of elements in the Armadillo column. err, e := m.Dims() if (err != 1 && e != 1){ @@ -199,12 +204,15 @@ func gonumToArmaUcol(identifier string, m *mat.Dense) { // Pass pointer of the underlying matrix to mlpack. ptr := unsafe.Pointer(&data[0]) - C.mlpackToArmaUcol(C.CString(identifier), (*C.double)(ptr), C.size_t(e)) + C.mlpackToArmaUcol(p.mem, C.CString(identifier), (*C.double)(ptr), + C.size_t(e)) } // GonumToArmaMatWithInfo passes a gonum matrix with info to C by // using it's gonums underlying blas64. -func gonumToArmaMatWithInfo(identifier string, m *matrixWithInfo) { +func gonumToArmaMatWithInfo(p *params, + identifier string, + m *matrixWithInfo) { // Get the number of elements in the Armadillo column. r, c := m.Data.Dims() blas64General := m.Data.RawMatrix() @@ -213,20 +221,21 @@ func gonumToArmaMatWithInfo(identifier string, m *matrixWithInfo) { // Pass pointer of the underlying matrix to mlpack. boolptr := unsafe.Pointer(&boolarray[0]) matptr := unsafe.Pointer(&dataAndInfo[0]) - C.mlpackToArmaMatWithInfo(C.CString(identifier), (*C.bool)(boolptr), - (*C.double)(matptr), C.size_t(c), C.size_t(r)) + C.mlpackToArmaMatWithInfo(p.mem, C.CString(identifier), + (*C.bool)(boolptr), (*C.double)(matptr), C.size_t(c), C.size_t(r)) } // ArmaToGonum returns a gonum matrix based on the memory pointer // of an armadillo matrix. -func (m *mlpackArma) armaToGonumMat(identifier string) *mat.Dense { +func (m *mlpackArma) armaToGonumMat(p *params, + identifier string) *mat.Dense { // Get the number of elements in the Armadillo row. - c := int(C.mlpackNumRowMat(C.CString(identifier))) - r := int(C.mlpackNumColMat(C.CString(identifier))) - e := int(C.mlpackNumElemMat(C.CString(identifier))) + c := int(C.mlpackNumRowMat(p.mem, C.CString(identifier))) + r := int(C.mlpackNumColMat(p.mem, C.CString(identifier))) + e := int(C.mlpackNumElemMat(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrMat(identifier) + m.allocArmaPtrMat(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -244,14 +253,15 @@ func (m *mlpackArma) armaToGonumMat(identifier string) *mat.Dense { // ArmaToGonum returns a gonum matrix based on the memory pointer // of an armadillo matrix. -func (m *mlpackArma) armaToGonumArray(identifier string) (int, int, []float64){ +func (m *mlpackArma) armaToGonumArray(p *params, + identifier string) (int, int, []float64) { // Get the number of elements in the Armadillo row. - c := int(C.mlpackNumRowMat(C.CString(identifier))) - r := int(C.mlpackNumColMat(C.CString(identifier))) - e := int(C.mlpackNumElemMat(C.CString(identifier))) + c := int(C.mlpackNumRowMat(p.mem, C.CString(identifier))) + r := int(C.mlpackNumColMat(p.mem, C.CString(identifier))) + e := int(C.mlpackNumElemMat(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrMat(identifier) + m.allocArmaPtrMat(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -262,14 +272,15 @@ func (m *mlpackArma) armaToGonumArray(identifier string) (int, int, []float64){ // ArmaToGonum returns a gonum matrix based on the memory pointer // of an armadillo matrix. -func (m *mlpackArma) armaToGonumUmat(identifier string) *mat.Dense { +func (m *mlpackArma) armaToGonumUmat(p *params, + identifier string) *mat.Dense { // Get the number of elements in the Armadillo row. - c := int(C.mlpackNumRowUmat(C.CString(identifier))) - r := int(C.mlpackNumColUmat(C.CString(identifier))) - e := int(C.mlpackNumElemUmat(C.CString(identifier))) + c := int(C.mlpackNumRowUmat(p.mem, C.CString(identifier))) + r := int(C.mlpackNumColUmat(p.mem, C.CString(identifier))) + e := int(C.mlpackNumElemUmat(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrUmat(identifier) + m.allocArmaPtrUmat(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -287,12 +298,13 @@ func (m *mlpackArma) armaToGonumUmat(identifier string) *mat.Dense { // ArmaRowToGonum returns a gonum vector based on the memory pointer // of the underlying armadillo object. -func (m *mlpackArma) armaToGonumRow(identifier string) *mat.Dense{ +func (m *mlpackArma) armaToGonumRow(p *params, + identifier string) *mat.Dense { // Get the number of elements in the Armadillo row. - e := int(C.mlpackNumElemRow(C.CString(identifier))) + e := int(C.mlpackNumElemRow(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrRow(identifier) + m.allocArmaPtrRow(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -310,12 +322,13 @@ func (m *mlpackArma) armaToGonumRow(identifier string) *mat.Dense{ // ArmaRowToGonum returns a gonum vector based on the memory pointer // of the underlying armadillo object. -func (m *mlpackArma) armaToGonumUrow(identifier string) *mat.Dense { +func (m *mlpackArma) armaToGonumUrow(p *params, + identifier string) *mat.Dense { // Get the number of elements in the Armadillo row. - e := int(C.mlpackNumElemUrow(C.CString(identifier))) + e := int(C.mlpackNumElemUrow(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrUrow(identifier) + m.allocArmaPtrUrow(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -330,13 +343,15 @@ func (m *mlpackArma) armaToGonumUrow(identifier string) *mat.Dense { return mat.NewDense(1, 1, nil) } -// Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func (m *mlpackArma) armaToGonumCol(identifier string) *mat.Dense { +// Passes a Gonum matrix to C by using the underlying data from the Gonum +// matrix. +func (m *mlpackArma) armaToGonumCol(p *params, + identifier string) *mat.Dense { // Get the number of elements in the Armadillo column. - e := int(C.mlpackNumElemCol(C.CString(identifier))) + e := int(C.mlpackNumElemCol(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrCol(identifier) + m.allocArmaPtrCol(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -352,13 +367,15 @@ func (m *mlpackArma) armaToGonumCol(identifier string) *mat.Dense { return mat.NewDense(1, 1, nil) } -// Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func (m *mlpackArma) armaToGonumUcol(identifier string) *mat.Dense { +// Passes a Gonum matrix to C by using the underlying data from the Gonum +// matrix. +func (m *mlpackArma) armaToGonumUcol(p *params, + identifier string) *mat.Dense { // Get the number of elements in the Armadillo column. - e := int(C.mlpackNumElemUcol(C.CString(identifier))) + e := int(C.mlpackNumElemUcol(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrUcol(identifier) + m.allocArmaPtrUcol(p, identifier) // Convert pointer to slice of data, to then pass it to a gonum matrix. array := (*[1<<30 - 1]float64)(m.mem) @@ -374,15 +391,17 @@ func (m *mlpackArma) armaToGonumUcol(identifier string) *mat.Dense { return mat.NewDense(1, 1, nil) } -// Passes a Gonum matrix to C by using the underlying data from the Gonum matrix. -func (m *mlpackArma) armaToGonumMatWithInfo(identifier string) *mat.Dense { +// Passes a Gonum matrix to C by using the underlying data from the Gonum +// matrix. +func (m *mlpackArma) armaToGonumMatWithInfo(p *params, + identifier string) *mat.Dense { // Get number of rows, columns, and elements of the Armadillo matrix. - c := int(C.mlpackArmaMatWithInfoRows(C.CString(identifier))) - r := int(C.mlpackArmaMatWithInfoCols(C.CString(identifier))) - e := int(C.mlpackArmaMatWithInfoElements(C.CString(identifier))) + c := int(C.mlpackArmaMatWithInfoRows(p.mem, C.CString(identifier))) + r := int(C.mlpackArmaMatWithInfoCols(p.mem, C.CString(identifier))) + e := int(C.mlpackArmaMatWithInfoElements(p.mem, C.CString(identifier))) // Allocate Go memory pointer to the armadillo matrix. - m.allocArmaPtrMatWithInfo(identifier) + m.allocArmaPtrMatWithInfo(p, identifier) matarray := (*[1<<30 - 1]float64)(m.mem) if matarray != nil { diff --git a/src/mlpack/bindings/go/mlpack/capi/arma_util.cpp b/src/mlpack/bindings/go/mlpack/capi/arma_util.cpp index cac87f39b3..e205deab4f 100644 --- a/src/mlpack/bindings/go/mlpack/capi/arma_util.cpp +++ b/src/mlpack/bindings/go/mlpack/capi/arma_util.cpp @@ -24,88 +24,119 @@ extern "C" { /** * Pass Gonum Dense pointer and wrap an Armadillo mat around it. */ -void mlpackToArmaMat(const char* identifier, double* mat, - const size_t row, const size_t col) +void mlpackToArmaMat(void* params, + const char* identifier, + double* mat, + const size_t row, + const size_t col) { + util::Params& p = *((util::Params*) params); + // Advanced constructor. arma::mat m(mat, row, col, false, true); // Set input parameter with corresponding matrix in IO. - SetParam(identifier, m); + SetParam(p, identifier, m); } /** * Pass Gonum Dense pointer and wrap an Armadillo mat around it. */ -void mlpackToArmaUmat(const char* identifier, double* mat, - const size_t row, const size_t col) +void mlpackToArmaUmat(void* params, + const char* identifier, + double* mat, + const size_t row, + const size_t col) { + util::Params& p = *((util::Params*) params); + // Advanced constructor. arma::mat m(mat, row, col, false, true); arma::Mat matr = arma::conv_to>::from(m); // Set input parameter with corresponding matrix in IO. - SetParam(identifier, matr); + SetParam(p, identifier, matr); } /** * Pass Gonum VecDense pointer and wrap an Armadillo rowvec around it. */ -void mlpackToArmaRow(const char* identifier, double* rowvec, const size_t elem) +void mlpackToArmaRow(void* params, + const char* identifier, + double* rowvec, + const size_t elem) { + util::Params& p = *((util::Params*) params); + // Advanced constructor. arma::rowvec m(rowvec, elem, false, true); // Set input parameter with corresponding row in IO. - SetParam(identifier, m); + SetParam(p, identifier, m); } /** * Pass Gonum VecDense pointer and wrap an Armadillo rowvec around it. */ -void mlpackToArmaUrow(const char* identifier, double* rowvec, const size_t elem) +void mlpackToArmaUrow(void* params, + const char* identifier, + double* rowvec, + const size_t elem) { + util::Params& p = *((util::Params*) params); + // Advanced constructor. arma::rowvec m(rowvec, elem, false, true); arma::Row matr = arma::conv_to>::from(m); // Set input parameter with corresponding row in IO. - SetParam(identifier, matr); + SetParam(p, identifier, matr); } /** * Pass Gonum VecDense pointer and wrap an Armadillo colvec around it. */ -void mlpackToArmaCol(const char* identifier, double* colvec, const size_t elem) +void mlpackToArmaCol(void* params, + const char* identifier, + double* colvec, + const size_t elem) { + util::Params& p = *((util::Params*) params); + // Advanced constructor. arma::colvec m(colvec, elem, false, true); // Set input parameter with corresponding column in IO. - SetParam(identifier, m); + SetParam(p, identifier, m); } /** * Pass Gonum VecDense pointer and wrap an Armadillo colvec around it. */ -void mlpackToArmaUcol(const char* identifier, double* colvec, const size_t elem) +void mlpackToArmaUcol(void* params, + const char* identifier, + double* colvec, + const size_t elem) { + util::Params& p = *((util::Params*) params); + // Advanced constructor. arma::colvec m(colvec, elem, false, true); arma::Col matr = arma::conv_to>::from(m); // Set input parameter with corresponding column in IO. - SetParam(identifier, matr); + SetParam(p, identifier, matr); } /** * Return the memory pointer of an Armadillo mat object. */ -void* mlpackArmaPtrMat(const char* identifier) +void* mlpackArmaPtrMat(void* params, const char* identifier) { - arma::mat& output = IO::GetParam(identifier); + util::Params& p = *((util::Params*) params); + arma::mat& output = p.Get(identifier); if (output.is_empty()) { return NULL; @@ -117,9 +148,10 @@ void* mlpackArmaPtrMat(const char* identifier) /** * Return the memory pointer of an Armadillo umat object. */ -void* mlpackArmaPtrUmat(const char* identifier) +void* mlpackArmaPtrUmat(void* params, const char* identifier) { - arma::Mat& m = IO::GetParam>(identifier); + util::Params& p = *((util::Params*) params); + arma::Mat& m = p.Get>(identifier); arma::mat output = arma::conv_to::from(m); if (output.is_empty()) @@ -133,9 +165,10 @@ void* mlpackArmaPtrUmat(const char* identifier) /** * Return the memory pointer of an Armadillo row object. */ -void* mlpackArmaPtrRow(const char* identifier) +void* mlpackArmaPtrRow(void* params, const char* identifier) { - arma::Row& output = IO::GetParam>(identifier); + util::Params& p = *((util::Params*) params); + arma::Row& output = p.Get>(identifier); if (output.is_empty()) { return NULL; @@ -147,9 +180,10 @@ void* mlpackArmaPtrRow(const char* identifier) /** * Return the memory pointer of an Armadillo urow object. */ -void* mlpackArmaPtrUrow(const char* identifier) +void* mlpackArmaPtrUrow(void* params, const char* identifier) { - arma::Row& m = IO::GetParam>(identifier); + util::Params& p = *((util::Params*) params); + arma::Row& m = p.Get>(identifier); arma::Row output = arma::conv_to>::from(m); if (output.is_empty()) @@ -163,9 +197,10 @@ void* mlpackArmaPtrUrow(const char* identifier) /** * Return the memory pointer of an Armadillo col object. */ -void* mlpackArmaPtrCol(const char* identifier) +void* mlpackArmaPtrCol(void* params, const char* identifier) { - arma::Col& output = IO::GetParam>(identifier); + util::Params& p = *((util::Params*) params); + arma::Col& output = p.Get>(identifier); if (output.is_empty()) { return NULL; @@ -177,9 +212,10 @@ void* mlpackArmaPtrCol(const char* identifier) /** * Return the memory pointer of an Armadillo ucol object. */ -void* mlpackArmaPtrUcol(const char* identifier) +void* mlpackArmaPtrUcol(void* params, const char* identifier) { - arma::Col& m = IO::GetParam>(identifier); + util::Params& p = *((util::Params*) params); + arma::Col& m = p.Get>(identifier); arma::Col output = arma::conv_to>::from(m); if (output.is_empty()) @@ -193,92 +229,104 @@ void* mlpackArmaPtrUcol(const char* identifier) /** * Return the number of rows in a Armadillo mat. */ -int mlpackNumRowMat(const char* identifier) +int mlpackNumRowMat(void* params, const char* identifier) { - return IO::GetParam(identifier).n_rows; + util::Params& p = *((util::Params*) params); + return p.Get(identifier).n_rows; } /** * Return the number of columns in an Armadillo mat. */ -int mlpackNumColMat(const char* identifier) +int mlpackNumColMat(void* params, const char* identifier) { - return IO::GetParam(identifier).n_cols; + util::Params& p = *((util::Params*) params); + return p.Get(identifier).n_cols; } /** * Return the number of elements in an Armadillo mat. */ -int mlpackNumElemMat(const char* identifier) +int mlpackNumElemMat(void* params, const char* identifier) { - return IO::GetParam(identifier).n_elem; + util::Params& p = *((util::Params*) params); + return p.Get(identifier).n_elem; } /** * Return the number of rows in an Armadillo umat. */ -int mlpackNumRowUmat(const char* identifier) +int mlpackNumRowUmat(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_rows; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_rows; } /** * Return the number of columns in an Armadillo umat. */ -int mlpackNumColUmat(const char* identifier) +int mlpackNumColUmat(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_cols; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_cols; } /** * Return the number of elements in an Armadillo umat. */ -int mlpackNumElemUmat(const char* identifier) +int mlpackNumElemUmat(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_elem; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_elem; } /** * Return the number of elements in an Armadillo row. */ -int mlpackNumElemRow(const char* identifier) +int mlpackNumElemRow(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_elem; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_elem; } /** * Return the number of elements in an Armadillo urow. */ -int mlpackNumElemUrow(const char* identifier) +int mlpackNumElemUrow(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_elem; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_elem; } /** * Return the number of elements in an Armadillo col. */ -int mlpackNumElemCol(const char* identifier) +int mlpackNumElemCol(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_elem; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_elem; } /** * Return the number of elements in an Armadillo ucol. */ -int mlpackNumElemUcol(const char* identifier) +int mlpackNumElemUcol(void* params, const char* identifier) { - return IO::GetParam>(identifier).n_elem; + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).n_elem; } /** * Call IO::SetParam>(). */ -void mlpackToArmaMatWithInfo(const char* identifier, +void mlpackToArmaMatWithInfo(void* params, + const char* identifier, const bool* dimensions, double* memptr, const size_t rows, const size_t cols) { + util::Params& p = *((util::Params*) params); data::DatasetInfo d(rows); for (size_t i = 0; i < d.Dimensionality(); ++i) { @@ -287,48 +335,52 @@ void mlpackToArmaMatWithInfo(const char* identifier, } arma::mat m(memptr, rows, cols, false, true); - std::get<0>(IO::GetParam>( - identifier)) = std::move(d); - std::get<1>(IO::GetParam>( - identifier)) = std::move(m); - IO::SetPassed(identifier); + std::get<0>(p.Get>( identifier)) = + std::move(d); + std::get<1>(p.Get>( identifier)) = + std::move(m); + p.SetPassed(identifier); } /** * Get the number of elements in a matrix with DatasetInfo parameter. */ -int mlpackArmaMatWithInfoElements(const char* identifier) +int mlpackArmaMatWithInfoElements(void* params, const char* identifier) { + util::Params& p = *((util::Params*) params); typedef std::tuple TupleType; - return std::get<1>(IO::GetParam(identifier)).n_elem; + return std::get<1>(p.Get(identifier)).n_elem; } /** * Get the number of rows in a matrix with DatasetInfo parameter. */ -int mlpackArmaMatWithInfoRows(const char* identifier) +int mlpackArmaMatWithInfoRows(void* params, const char* identifier) { + util::Params& p = *((util::Params*) params); typedef std::tuple TupleType; - return std::get<1>(IO::GetParam(identifier)).n_rows; + return std::get<1>(p.Get(identifier)).n_rows; } /** * Get the number of columns in a matrix with DatasetInfo parameter. */ -int mlpackArmaMatWithInfoCols(const char* identifier) +int mlpackArmaMatWithInfoCols(void* params, const char* identifier) { + util::Params& p = *((util::Params*) params); typedef std::tuple TupleType; - return std::get<1>(IO::GetParam(identifier)).n_cols; + return std::get<1>(p.Get(identifier)).n_cols; } /** * Get a pointer to the memory of the matrix. The calling function is expected * to own the memory. */ -void* mlpackArmaPtrMatWithInfoPtr(const char* identifier) +void* mlpackArmaPtrMatWithInfoPtr(void* params, const char* identifier) { + util::Params& p = *((util::Params*) params); typedef std::tuple TupleType; - arma::mat& m = std::get<1>(IO::GetParam(identifier)); + arma::mat& m = std::get<1>(p.Get(identifier)); if (m.is_empty()) { return NULL; diff --git a/src/mlpack/bindings/go/mlpack/capi/arma_util.h b/src/mlpack/bindings/go/mlpack/capi/arma_util.h index be1505cc79..8d3da53e2a 100644 --- a/src/mlpack/bindings/go/mlpack/capi/arma_util.h +++ b/src/mlpack/bindings/go/mlpack/capi/arma_util.h @@ -22,133 +22,140 @@ extern "C" { #endif /** - * Pass Gonum Dense poconst size_t er and wrap an Armadillo mat around it. + * Pass Gonum Dense pointer and wrap an Armadillo mat around it. */ -void mlpackToArmaMat(const char* identifier, +void mlpackToArmaMat(void* params, + const char* identifier, double* mat, const size_t row, const size_t col); /** - * Pass Gonum Dense poconst size_t er and wrap an Armadillo mat around it. + * Pass Gonum Dense pointer and wrap an Armadillo mat around it. */ -void mlpackToArmaUmat(const char* identifier, +void mlpackToArmaUmat(void* params, + const char* identifier, double* mat, const size_t row, const size_t col); /** - * Pass Gonum VecDense poconst size_t er and wrap an Armadillo rowvec around it. + * Pass Gonum VecDense pointer and wrap an Armadillo rowvec around it. */ -void mlpackToArmaRow(const char* identifier, +void mlpackToArmaRow(void* params, + const char* identifier, double* rowvec, const size_t elem); /** - * Pass Gonum VecDense poconst size_t er and wrap an Armadillo rowvec around it. + * Pass Gonum VecDense pointer and wrap an Armadillo rowvec around it. */ -void mlpackToArmaUrow(const char* identifier, +void mlpackToArmaUrow(void* params, + const char* identifier, double* rowvec, const size_t elem); /** - * Pass Gonum VecDense poconst size_t er and wrap an Armadillo colvec around it. + * Pass Gonum VecDense pointer and wrap an Armadillo colvec around it. */ -void mlpackToArmaCol(const char* identifier, +void mlpackToArmaCol(void* params, + const char* identifier, double* colvec, const size_t elem); /** - * Pass Gonum VecDense poconst size_t er and wrap an Armadillo colvec around it. + * Pass Gonum VecDense pointer and wrap an Armadillo colvec around it. */ -void mlpackToArmaUcol(const char* identifier, +void mlpackToArmaUcol(void* params, + const char* identifier, double* colvec, const size_t elem); /** - * Return the memory poconst size_t er of an Armadillo mat object. + * Return the memory pointer of an Armadillo mat object. */ -void* mlpackArmaPtrMat(const char* identifier); +void* mlpackArmaPtrMat(void* params, const char* identifier); /** - * Return the memory poconst size_t er of an Armadillo umat object. + * Return the memory pointer of an Armadillo umat object. */ -void* mlpackArmaPtrUmat(const char* identifier); +void* mlpackArmaPtrUmat(void* params, const char* identifier); /** - * Return the memory poconst size_t er of an Armadillo row object. + * Return the memory pointer of an Armadillo row object. */ -void* mlpackArmaPtrRow(const char* identifier); +void* mlpackArmaPtrRow(void* params, const char* identifier); /** - * Return the memory poconst size_t er of an Armadillo urow object. + * Return the memory pointer of an Armadillo urow object. */ -void* mlpackArmaPtrUrow(const char* identifier); +void* mlpackArmaPtrUrow(void* params, const char* identifier); /** - * Return the memory poconst size_t er of an Armadillo col object. + * Return the memory pointer of an Armadillo col object. */ -void* mlpackArmaPtrCol(const char* identifier); +void* mlpackArmaPtrCol(void* params, const char* identifier); /** - * Return the memory poconst size_t er of an Armadillo ucol object. + * Return the memory pointer of an Armadillo ucol object. */ -void* mlpackArmaPtrUcol(const char* identifier); +void* mlpackArmaPtrUcol(void* params, const char* identifier); /** * Return the number of rows in a Armadillo mat. */ -int mlpackNumRowMat(const char* identifier); +int mlpackNumRowMat(void* params, const char* identifier); /** * Return the number of columns in an Armadillo mat. */ -int mlpackNumColMat(const char* identifier); +int mlpackNumColMat(void* params, const char* identifier); /** * Return the number of elements in an Armadillo mat. */ -int mlpackNumElemMat(const char* identifier); +int mlpackNumElemMat(void* params, const char* identifier); /** * Return the number of rows in an Armadillo umat. */ -int mlpackNumRowUmat(const char* identifier); +int mlpackNumRowUmat(void* params, const char* identifier); /** * Return the number of columns in an Armadillo umat. */ -int mlpackNumColUmat(const char* identifier); +int mlpackNumColUmat(void* params, const char* identifier); /** * Return the number of elements in an Armadillo umat. */ -int mlpackNumElemUmat(const char* identifier); +int mlpackNumElemUmat(void* params, const char* identifier); /** * Return the number of elements in an Armadillo row. */ -int mlpackNumElemRow(const char* identifier); +int mlpackNumElemRow(void* params, const char* identifier); /** * Return the number of elements in an Armadillo urow. */ -int mlpackNumElemUrow(const char* identifier); +int mlpackNumElemUrow(void* params, const char* identifier); /** * Return the number of elements in an Armadillo col. */ -int mlpackNumElemCol(const char* identifier); +int mlpackNumElemCol(void* params, const char* identifier); /** * Return the number of elements in an Armadillo ucol. */ -int mlpackNumElemUcol(const char* identifier); +int mlpackNumElemUcol(void* params, const char* identifier); /** * Call IO::SetParam>(). */ -void mlpackToArmaMatWithInfo(const char* identifier, +void mlpackToArmaMatWithInfo(void* params, + const char* identifier, const bool* dimensions, double* memptr, const size_t rows, @@ -157,23 +164,23 @@ void mlpackToArmaMatWithInfo(const char* identifier, /** * Get the number of elements in a matrix with DatasetInfo parameter. */ -int mlpackArmaMatWithInfoElements(const char* identifier); +int mlpackArmaMatWithInfoElements(void* params, const char* identifier); /** * Get the number of rows in a matrix with DatasetInfo parameter. */ -int mlpackArmaMatWithInfoRows(const char* identifier); +int mlpackArmaMatWithInfoRows(void* params, const char* identifier); /** * Get the number of columns in a matrix with DatasetInfo parameter. */ -int mlpackArmaMatWithInfoCols(const char* identifier); +int mlpackArmaMatWithInfoCols(void* params, const char* identifier); /** - * Get a poconst size_t er to the memory of the matrix. The calling function is expected + * Get a pointer to the memory of the matrix. The calling function is expected * to own the memory. */ -void* mlpackArmaPtrMatWithInfoPtr(const char* identifier); +void* mlpackArmaPtrMatWithInfoPtr(void* params, const char* identifier); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/src/mlpack/bindings/go/mlpack/capi/io_util.cpp b/src/mlpack/bindings/go/mlpack/capi/io_util.cpp index 4f81188aad..d677af785f 100644 --- a/src/mlpack/bindings/go/mlpack/capi/io_util.cpp +++ b/src/mlpack/bindings/go/mlpack/capi/io_util.cpp @@ -18,144 +18,202 @@ namespace mlpack { extern "C" { +/** + * Get a new Params object for the given binding name. + */ +void* mlpackGetParams(const char* bindingName) +{ + util::Params* p = new util::Params(IO::Parameters(bindingName)); + std::cout << "created params p " << p << "\n"; + return (void*) p; +} + +/** + * Get a new Timers object. + */ +void* mlpackGetTimers() +{ + util::Timers* t = new util::Timers(); + return (void*) t; +} + +/** + * Delete the given Params object. + */ +void mlpackCleanParams(void* params) +{ + util::Params* p = (util::Params*) params; + delete p; +} + +/** + * Delete the given Timers object. + */ +void mlpackCleanTimers(void* timers) +{ + util::Timers* t = (util::Timers*) timers; + delete t; +} + /** * Set the double parameter to the given value. */ -void mlpackSetParamDouble(const char* identifier, double value) +void mlpackSetParamDouble(void* params, const char* identifier, double value) { - util::SetParam(identifier, value); + util::Params& p = *((util::Params*) params); + util::SetParam(p, identifier, value); } /** * Set the int parameter to the given value. */ -void mlpackSetParamInt(const char* identifier, int value) +void mlpackSetParamInt(void* params, const char* identifier, int value) { - util::SetParam(identifier, value); + util::Params& p = *((util::Params*) params); + util::SetParam(p, identifier, value); } /** * Set the float parameter to the given value. */ -void mlpackSetParamFloat(const char* identifier, float value) +void mlpackSetParamFloat(void* params, const char* identifier, float value) { - util::SetParam(identifier, value); + util::Params& p = *((util::Params*) params); + util::SetParam(p, identifier, value); } /** * Set the bool parameter to the given value. */ -void mlpackSetParamBool(const char* identifier, bool value) +void mlpackSetParamBool(void* params, const char* identifier, bool value) { - util::SetParam(identifier, value); + util::Params& p = *((util::Params*) params); + util::SetParam(p, identifier, value); } /** * Set the string parameter to the given value. */ -void mlpackSetParamString(const char* identifier, const char* value) +void mlpackSetParamString(void* params, + const char* identifier, + const char* value) { - IO::GetParam(identifier) = value; + util::Params& p = *((util::Params*) params); + p.Get(identifier) = value; } /** * Set the int vector parameter to the given value. */ -void mlpackSetParamVectorInt(const char* identifier, +void mlpackSetParamVectorInt(void* params, + const char* identifier, const long long* ints, const size_t length) { + util::Params& p = *((util::Params*) params); + // Create a std::vector object; unfortunately this requires copying the // vector elements. std::vector vec(length); for (size_t i = 0; i < length; ++i) vec[i] = ints[i]; - IO::GetParam>(identifier) = std::move(vec); - IO::SetPassed(identifier); + p.Get>(identifier) = std::move(vec); + p.SetPassed(identifier); } /** * Call IO::SetParam>() to set the length. */ -void mlpackSetParamVectorStrLen(const char* identifier, +void mlpackSetParamVectorStrLen(void* params, + const char* identifier, const size_t length) { - IO::GetParam>(identifier).clear(); - IO::GetParam>(identifier).resize(length); - IO::SetPassed(identifier); + util::Params& p = *((util::Params*) params); + p.Get>(identifier).clear(); + p.Get>(identifier).resize(length); + p.SetPassed(identifier); } /** * Set the string vector parameter to the given value. */ -void mlpackSetParamVectorStr(const char* identifier, +void mlpackSetParamVectorStr(void* params, + const char* identifier, const char* str, const size_t element) { - IO::GetParam>(identifier)[element] = - std::string(str); + util::Params& p = *((util::Params*) params); + p.Get>(identifier)[element] = std::string(str); } /** * Set the parameter to the given value, given that the type is a pointer. */ -void mlpackSetParamPtr(const char* identifier, +void mlpackSetParamPtr(void* params, + const char* identifier, const double* ptr) { - util::SetParamPtr(identifier, ptr); + util::Params& p = *((util::Params*) params); + util::SetParamPtr(p, identifier, ptr); } /** * Check if IO has a specified parameter. */ -bool mlpackHasParam(const char* identifier) +bool mlpackHasParam(void* params, const char* identifier) { - return IO::HasParam(identifier); + util::Params& p = *((util::Params*) params); + return p.Has(identifier); } /** * Get the string parameter associated with specified identifier. */ -const char* mlpackGetParamString(const char* identifier) +const char* mlpackGetParamString(void* params, const char* identifier) { - return IO::GetParam(identifier).c_str(); + util::Params& p = *((util::Params*) params); + return p.Get(identifier).c_str(); } /** * Get the double parameter associated with specified identifier. */ -double mlpackGetParamDouble(const char* identifier) +double mlpackGetParamDouble(void* params, const char* identifier) { - return IO::GetParam(identifier); + util::Params& p = *((util::Params*) params); + return p.Get(identifier); } /** * Get the int parameter associated with specified identifier. */ -int mlpackGetParamInt(const char* identifier) +int mlpackGetParamInt(void* params, const char* identifier) { - return IO::GetParam(identifier); + util::Params& p = *((util::Params*) params); + return p.Get(identifier); } /** * Get the bool parameter associated with specified identifier. */ -bool mlpackGetParamBool(const char* identifier) +bool mlpackGetParamBool(void* params, const char* identifier) { - return IO::GetParam(identifier); + util::Params& p = *((util::Params*) params); + return p.Get(identifier); } /** * Get the vector parameter associated with specified identifier. */ -void* mlpackGetVecIntPtr(const char* identifier) +void* mlpackGetVecIntPtr(void* params, const char* identifier) { - const size_t size = mlpackVecIntSize(identifier); + const size_t size = mlpackVecIntSize(params, identifier); long long* ints = new long long[size]; + util::Params& p = *((util::Params*) params); for (size_t i = 0; i < size; i++) - ints[i] = IO::GetParam>(identifier)[i]; + ints[i] = p.Get>(identifier)[i]; return ints; } @@ -163,33 +221,39 @@ void* mlpackGetVecIntPtr(const char* identifier) /** * Get the vector parameter associated with specified identifier. */ -const char* mlpackGetVecStringPtr(const char* identifier, const size_t i) +const char* mlpackGetVecStringPtr(void* params, + const char* identifier, + const size_t i) { - return IO::GetParam>(identifier)[i].c_str(); + util::Params& p = *((util::Params*) params); + return p.Get>(identifier)[i].c_str(); } /** * Get the vector parameter's size. */ -int mlpackVecIntSize(const char* identifier) +int mlpackVecIntSize(void* params, const char* identifier) { - return IO::GetParam>(identifier).size(); + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).size(); } /** * Get the vector parameter's size. */ -int mlpackVecStringSize(const char* identifier) +int mlpackVecStringSize(void* params, const char* identifier) { - return IO::GetParam>(identifier).size(); + util::Params& p = *((util::Params*) params); + return p.Get>(identifier).size(); } /** * Set parameter as passed. */ -void mlpackSetPassed(const char* name) +void mlpackSetPassed(void* params, const char* name) { - IO::SetPassed(name); + util::Params& p = *((util::Params*) params); + p.SetPassed(name); } /** @@ -197,7 +261,7 @@ void mlpackSetPassed(const char* name) */ void mlpackResetTimers() { - IO::GetSingleton().timer.Reset(); +// IO::GetSingleton().timer.Reset(); } /** @@ -232,22 +296,6 @@ void mlpackDisableVerbose() Log::Info.ignoreInput = true; } -/** - * Clear settings. - */ -void mlpackClearSettings() -{ - IO::ClearSettings(); -} - -/** - * Restore Settings. - */ -void mlpackRestoreSettings(const char* name) -{ - IO::RestoreSettings(name); -} - } // extern C } // namespace mlpack diff --git a/src/mlpack/bindings/go/mlpack/capi/io_util.h b/src/mlpack/bindings/go/mlpack/capi/io_util.h index 900f09568b..d278161ab9 100644 --- a/src/mlpack/bindings/go/mlpack/capi/io_util.h +++ b/src/mlpack/bindings/go/mlpack/capi/io_util.h @@ -21,105 +21,132 @@ extern "C" { #endif +/** + * Get a new Params object for the given binding name. + */ +void* mlpackGetParams(const char* bindingName); + +/** + * Get a new Timers object. + */ +void* mlpackGetTimers(); + +/** + * Delete the given Params object. + */ +void mlpackCleanParams(void* params); + +/** + * Delete the given Timers object. + */ +void mlpackCleanTimers(void* timers); + /** * Set the double parameter to the given value. */ -void mlpackSetParamDouble(const char* identifier, double value); +void mlpackSetParamDouble(void* params, const char* identifier, double value); /** * Set the int parameter to the given value. */ -void mlpackSetParamInt(const char* identifier, int value); +void mlpackSetParamInt(void* params, const char* identifier, int value); /** * Set the float parameter to the given value. */ -void mlpackSetParamFloat(const char* identifier, float value); +void mlpackSetParamFloat(void* params, const char* identifier, float value); /** * Set the bool parameter to the given value. */ -void mlpackSetParamBool(const char* identifier, bool value); +void mlpackSetParamBool(void* params, const char* identifier, bool value); /** * Set the string parameter to the given value. */ -void mlpackSetParamString(const char* identifier, const char* value); +void mlpackSetParamString(void* params, + const char* identifier, + const char* value); /** * Set the parameter to the given value, given that the type is a pointer. */ -void mlpackSetParamPtr(const char* identifier, const double* ptr); +void mlpackSetParamPtr(void* params, const char* identifier, const double* ptr); /** * Set the int vector parameter to the given value. */ -void mlpackSetParamVectorInt(const char* identifier, +void mlpackSetParamVectorInt(void* params, + const char* identifier, const long long* ints, const size_t length); /** * Set the string vector parameter to the given value. */ -void mlpackSetParamVectorStr(const char* identifier, +void mlpackSetParamVectorStr(void* params, + const char* identifier, const char* str, const size_t element); /** * Call IO::SetParam>() to set the length. */ -void mlpackSetParamVectorStrLen(const char* identifier, +void mlpackSetParamVectorStrLen(void* params, + const char* identifier, const size_t length); /** * Check if IO has a specified parameter. */ -bool mlpackHasParam(const char* identifier); +bool mlpackHasParam(void* params, const char* identifier); /** * Get the string parameter associated with specified identifier. */ -const char* mlpackGetParamString(const char* identifier); +const char* mlpackGetParamString(void* params, const char* identifier); /** * Get the double parameter associated with specified identifier. */ -double mlpackGetParamDouble(const char* identifier); +double mlpackGetParamDouble(void* params, const char* identifier); /** * Get the int parameter associated with specified identifier. */ -int mlpackGetParamInt(const char* identifier); +int mlpackGetParamInt(void* params, const char* identifier); /** * Get the bool parameter associated with specified identifier. */ -bool mlpackGetParamBool(const char* identifier); +bool mlpackGetParamBool(void* params, const char* identifier); /** * Get the vector parameter associated with specified identifier. */ -void* mlpackGetVecIntPtr(const char* identifier); +void* mlpackGetVecIntPtr(void* params, const char* identifier); /** * Get the vector parameter associated with specified identifier. */ -const char* mlpackGetVecStringPtr(const char* identifier, const size_t i); +const char* mlpackGetVecStringPtr(void* params, + const char* identifier, + const size_t i); /** * Get the vector parameter's size. */ -int mlpackVecIntSize(const char* identifier); +int mlpackVecIntSize(void* params, const char* identifier); /** * Get the vector parameter's size. */ -int mlpackVecStringSize(const char* identifier); +int mlpackVecStringSize(void* params, const char* identifier); /** * Set parameter as passed. */ -void mlpackSetPassed(const char* name); +void mlpackSetPassed(void* params, const char* name); /** * Reset the status of all timers. @@ -146,16 +173,6 @@ void mlpackEnableVerbose(); */ void mlpackDisableVerbose(); -/** - * Clear settings. - */ -void mlpackClearSettings(); - -/** - * Restore Settings. - */ -void mlpackRestoreSettings(const char* name); - #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/src/mlpack/bindings/go/mlpack/capi/io_util.hpp b/src/mlpack/bindings/go/mlpack/capi/io_util.hpp index 76b1c0afad..f6bad6d4b2 100644 --- a/src/mlpack/bindings/go/mlpack/capi/io_util.hpp +++ b/src/mlpack/bindings/go/mlpack/capi/io_util.hpp @@ -26,9 +26,11 @@ namespace util { * @param value Value to set parameter to. */ template -inline void SetParam(const std::string& identifier, T& value) +inline void SetParam(util::Params& p, + const std::string& identifier, + T& value) { - IO::GetParam(identifier) = std::move(value); + p.Get(identifier) = std::move(value); } /** @@ -38,10 +40,11 @@ inline void SetParam(const std::string& identifier, T& value) * @param value Value to set parameter to. */ template -inline void SetParamPtr(const std::string& identifier, +inline void SetParamPtr(util::Params& p, + const std::string& identifier, T* value) { - IO::GetParam(identifier) = value; + p.Get(identifier) = value; } /** @@ -49,9 +52,9 @@ inline void SetParamPtr(const std::string& identifier, * of support for template pointer types. */ template -T* GetParamPtr(const std::string& paramName) +T* GetParamPtr(util::Params& p, const std::string& paramName) { - return IO::GetParam(paramName); + return p.Get(paramName); } /** @@ -78,13 +81,9 @@ inline void DisableBacktrace() Log::Fatal.backtrace = false; } -/** - * Reset the status of all timers. - */ inline void ResetTimers() { - // Just get a new object---removes all old timers. - IO::GetSingleton().timer.Reset(); + Timer::ResetAll(); } /** diff --git a/src/mlpack/bindings/go/mlpack/io_util.go b/src/mlpack/bindings/go/mlpack/io_util.go index 4c63e54964..96cffcb136 100644 --- a/src/mlpack/bindings/go/mlpack/io_util.go +++ b/src/mlpack/bindings/go/mlpack/io_util.go @@ -12,36 +12,67 @@ import ( "unsafe" ) -func hasParam(identifier string) bool { - return bool((C.mlpackHasParam(C.CString(identifier)))) +type params struct { + mem unsafe.Pointer } -func setPassed(identifier string) { - C.mlpackSetPassed(C.CString(identifier)) +type timers struct { + mem unsafe.Pointer } -func setParamDouble(identifier string, value float64) { - C.mlpackSetParamDouble(C.CString(identifier), C.double(value)) +func getParams(binding string) *params { + ptr := C.mlpackGetParams(C.CString(binding)) + p := ¶ms { mem: ptr } + runtime.KeepAlive(p) + return p } -func setParamInt(identifier string, value int) { - C.mlpackSetParamInt(C.CString(identifier), C.int(value)) -} -func setParamFloat(identifier string, value float64) { - C.mlpackSetParamFloat(C.CString(identifier), C.float(value)) +func getTimers() *timers { + ptr := C.mlpackGetTimers() + t := &timers { mem: ptr } + runtime.KeepAlive(t) + return t } -func setParamBool(identifier string, value bool) { - C.mlpackSetParamBool(C.CString(identifier), C.bool(value)) +func cleanParams(p *params) { + C.mlpackCleanParams(p.mem) } -func setParamString(identifier string, value string) { - C.mlpackSetParamString(C.CString(identifier), C.CString(value)) +func cleanTimers(t *timers) { + C.mlpackCleanTimers(t.mem) } -func setParamPtr(identifier string, ptr unsafe.Pointer) { - C.mlpackSetParamPtr(C.CString(identifier), (*C.double)(ptr)) +func hasParam(p *params, identifier string) bool { + return bool((C.mlpackHasParam(p.mem, C.CString(identifier)))) } + +func setPassed(p *params, identifier string) { + C.mlpackSetPassed(p.mem, C.CString(identifier)) +} + +func setParamDouble(p *params, identifier string, value float64) { + C.mlpackSetParamDouble(p.mem, C.CString(identifier), C.double(value)) +} + +func setParamInt(p *params, identifier string, value int) { + C.mlpackSetParamInt(p.mem, C.CString(identifier), C.int(value)) +} +func setParamFloat(p *params, identifier string, value float64) { + C.mlpackSetParamFloat(p.mem, C.CString(identifier), C.float(value)) +} + +func setParamBool(p *params, identifier string, value bool) { + C.mlpackSetParamBool(p.mem, C.CString(identifier), C.bool(value)) +} + +func setParamString(p *params, identifier string, value string) { + C.mlpackSetParamString(p.mem, C.CString(identifier), C.CString(value)) +} + +func setParamPtr(p *params, identifier string, ptr unsafe.Pointer) { + C.mlpackSetParamPtr(p.mem, C.CString(identifier), (*C.double)(ptr)) +} + func resetTimers() { C.mlpackResetTimers() } @@ -62,31 +93,23 @@ func enableVerbose() { C.mlpackEnableVerbose() } -func restoreSettings(method string) { - C.mlpackRestoreSettings(C.CString(method)) -} - -func clearSettings() { - C.mlpackClearSettings() -} - -func getParamString(identifier string) string { - val := C.GoString(C.mlpackGetParamString(C.CString(identifier))) +func getParamString(p *params, identifier string) string { + val := C.GoString(C.mlpackGetParamString(p.mem, C.CString(identifier))) return val } -func getParamBool(identifier string) bool { - val := bool(C.mlpackGetParamBool(C.CString(identifier))) +func getParamBool(p *params, identifier string) bool { + val := bool(C.mlpackGetParamBool(p.mem, C.CString(identifier))) return val } -func getParamInt(identifier string) int { - val := int(C.mlpackGetParamInt(C.CString(identifier))) +func getParamInt(p *params, identifier string) int { + val := int(C.mlpackGetParamInt(p.mem, C.CString(identifier))) return val } -func getParamDouble(identifier string) float64 { - val := float64(C.mlpackGetParamDouble(C.CString(identifier))) +func getParamDouble(p *params, identifier string) float64 { + val := float64(C.mlpackGetParamDouble(p.mem, C.CString(identifier))) return val } @@ -94,12 +117,12 @@ type mlpackVectorType struct { mem unsafe.Pointer } -func (v *mlpackVectorType) allocVecIntPtr(identifier string) { - v.mem = C.mlpackGetVecIntPtr(C.CString(identifier)) +func (v *mlpackVectorType) allocVecIntPtr(p *params, identifier string) { + v.mem = C.mlpackGetVecIntPtr(p.mem, C.CString(identifier)) runtime.KeepAlive(v) } -func setParamVecInt(identifier string, vecInt []int) { +func setParamVecInt(p *params, identifier string, vecInt []int) { vecInt64 := make([]int64, len(vecInt)) // Here we are promisely passing int64 to C++. for i := 0; i < len(vecInt); i++ { @@ -108,23 +131,24 @@ func setParamVecInt(identifier string, vecInt []int) { ptr := unsafe.Pointer(&vecInt64[0]) // As we are not guaranteed that int is always equivalent of int64_t or // int32_t in Go. Hence we are passing `long long` to C++. - C.mlpackSetParamVectorInt(C.CString(identifier), (*C.longlong)(ptr), - C.size_t(len(vecInt))) + C.mlpackSetParamVectorInt(p.mem, C.CString(identifier), + (*C.longlong)(ptr), C.size_t(len(vecInt))) } -func setParamVecString(identifier string, vecString []string) { - C.mlpackSetParamVectorStrLen(C.CString(identifier), C.size_t(len(vecString))) +func setParamVecString(p *params, identifier string, vecString []string) { + C.mlpackSetParamVectorStrLen(p.mem, C.CString(identifier), + C.size_t(len(vecString))) for i := 0; i < len(vecString); i++ { - C.mlpackSetParamVectorStr(C.CString(identifier), (C.CString)(vecString[i]), - C.size_t(i)) + C.mlpackSetParamVectorStr(p.mem, C.CString(identifier), + (C.CString)(vecString[i]), C.size_t(i)) } } -func getParamVecInt(identifier string) []int { - e := int(C.mlpackVecIntSize(C.CString(identifier))) +func getParamVecInt(p *params, identifier string) []int { + e := int(C.mlpackVecIntSize(p.mem, C.CString(identifier))) var v mlpackVectorType - v.allocVecIntPtr(identifier) + v.allocVecIntPtr(p, identifier) data := (*[1<<30 - 1]int)(v.mem) output := data[:e] @@ -134,13 +158,13 @@ func getParamVecInt(identifier string) []int { return []int{} } -func getParamVecString(identifier string) []string { - e := int(C.mlpackVecStringSize(C.CString(identifier))) +func getParamVecString(p *params, identifier string) []string { + e := int(C.mlpackVecStringSize(p.mem, C.CString(identifier))) data := make([]string, e) for i := 0; i < e; i++ { - data[i] = C.GoString(C.mlpackGetVecStringPtr(C.CString(identifier), - C.size_t(i))) + data[i] = C.GoString(C.mlpackGetVecStringPtr(p.mem, + C.CString(identifier), C.size_t(i))) } return data } diff --git a/src/mlpack/bindings/go/print_doc_functions.hpp b/src/mlpack/bindings/go/print_doc_functions.hpp index cac5a31a75..9b44d74249 100644 --- a/src/mlpack/bindings/go/print_doc_functions.hpp +++ b/src/mlpack/bindings/go/print_doc_functions.hpp @@ -53,10 +53,12 @@ inline std::string PrintValue(const bool& value, bool quotes); /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName); +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName); // Base case: no modification needed. inline void GetOptions( + util::Params& /* params */, std::vector>& /* results */); /** @@ -66,23 +68,25 @@ inline void GetOptions( */ template void GetOptions( + util::Params& params, std::vector>& results, const std::string& paramName, const T& value, Args... args); // Recursion base case. -inline std::string PrintOptionalInputs(/* option */); +inline std::string PrintOptionalInputs(util::Params& /* params */); // Recursion base case. -inline std::string PrintInputOptions(/* option */); +inline std::string PrintInputOptions(util::Params& /* params */); /** * Print an input option. This will throw an exception if the parameter does * not exist in IO. */ template -std::string PrintOptionalInputs(const std::string& paramName, +std::string PrintOptionalInputs(util::Params& params, + const std::string& paramName, const T& value, Args... args); @@ -91,15 +95,16 @@ std::string PrintOptionalInputs(const std::string& paramName, * not exist in IO. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args); // Recursion base case. -inline std::string PrintOutputOptions(); +inline std::string PrintOutputOptions(util::Params& /* params */); template -std::string PrintOutputOptions(Args... args); +std::string PrintOutputOptions(util::Params& params, Args... args); /** * Given a name of a binding and a variable number of arguments (and their diff --git a/src/mlpack/bindings/go/print_doc_functions_impl.hpp b/src/mlpack/bindings/go/print_doc_functions_impl.hpp index 3675bdf4e3..97fed30472 100644 --- a/src/mlpack/bindings/go/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/go/print_doc_functions_impl.hpp @@ -116,37 +116,48 @@ inline std::string PrintValue(const bool& value, bool quotes) /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName) +inline std::string PrintDefault(util::Params& params, + const std::string& paramName) { - if (IO::Parameters().count(paramName) == 0) + if (params.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; std::string defaultValue; - IO::GetSingleton().functionMap[d.tname]["DefaultParam"](d, NULL, - (void*) &defaultValue); + params.functionMap[d.tname]["DefaultParam"](d, NULL, (void*) &defaultValue); return defaultValue; } +/** + * Given a parameter name, print its corresponding default value. + */ +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName) +{ + util::Params params = IO::Parameters(bindingName); + return PrintDefault(params, paramName); +} + // Recursion base case. -std::string PrintOptionalInputs() { return ""; } +std::string PrintOptionalInputs(util::Params& /* params */) { return ""; } /** * Print an input option. This will throw an exception if the parameter does * not exist in IO. */ template -std::string PrintOptionalInputs(const std::string& paramName, +std::string PrintOptionalInputs(util::Params& params, + const std::string& paramName, const T& value, Args... args) { // See if this is part of the program. std::string result = ""; - if (IO::Parameters().count(paramName) > 0) + if (params.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; if (d.input && !d.required) { std::string goParamName = util::CamelCase(paramName, false); @@ -156,7 +167,7 @@ std::string PrintOptionalInputs(const std::string& paramName, oss << "param." << goParamName << " = "; // Special handling is needed for model types. - if (PrintDefault(paramName) == "nil") + if (PrintDefault(params, paramName) == "nil") { oss << "&"; std::string goStrippedType, strippedType, printedType, defaultsType; @@ -181,7 +192,7 @@ std::string PrintOptionalInputs(const std::string& paramName, } // Continue recursion. - std::string rest = PrintOptionalInputs(args...); + std::string rest = PrintOptionalInputs(params, args...); if (rest != "" && result != "") result += rest; else if (result == "") @@ -191,30 +202,31 @@ std::string PrintOptionalInputs(const std::string& paramName, } // Recursion base case. -std::string PrintInputOptions() { return ""; } +std::string PrintInputOptions(util::Params& /* params */) { return ""; } /** * Print an input option. This will throw an exception if the parameter does * not exist in IO. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(util::Params& params, + const std::string& paramName, const T& value, Args... args) { // See if this is part of the program. std::string result = ""; - if (IO::Parameters().count(paramName) > 0) + if (params.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = params.Parameters()[paramName]; if (d.input && d.required) { // Print the input option. std::ostringstream oss; // Special handling is needed for model types. - if (PrintDefault(paramName) == "nil") + if (PrintDefault(params, paramName) == "nil") { oss << "&"; std::string goStrippedType, strippedType, printedType, defaultsType; @@ -238,7 +250,7 @@ std::string PrintInputOptions(const std::string& paramName, } // Continue recursion. - std::string rest = PrintInputOptions(args...); + std::string rest = PrintInputOptions(params, args...); if (rest != "" && result != "") result += ", " + rest; else if (result == "") @@ -249,6 +261,7 @@ std::string PrintInputOptions(const std::string& paramName, // Base case: no modification needed. void GetOptions( + util::Params& /* params */, std::vector>& /* results */) { // Nothing to do. @@ -261,18 +274,19 @@ void GetOptions( */ template void GetOptions( + util::Params& params, std::vector>& results, const std::string& paramName, const T& value, Args... args) { // Determine whether or not the value is required. - if (IO::Parameters().count(paramName) > 0) + if (params.Parameters().count(paramName) > 0) { std::ostringstream oss; oss << value; results.push_back(std::make_tuple(paramName, oss.str())); - GetOptions(results, args...); + GetOptions(params, results, args...); } else { @@ -284,14 +298,14 @@ void GetOptions( } // Recursion base case. -inline std::string PrintOutputOptions() { return ""; } +inline std::string PrintOutputOptions(util::Params& /* params */) { return ""; } template -std::string PrintOutputOptions(Args... args) +std::string PrintOutputOptions(util::Params& params, Args... args) { // Get the list of output options for the binding. std::vector outputOptions; - std::map& parameters = IO::Parameters(); + std::map& parameters = params.Parameters(); for (auto it = parameters.begin(); it != parameters.end(); ++it) { util::ParamData& d = it->second; @@ -301,7 +315,7 @@ std::string PrintOutputOptions(Args... args) // Now get the full list of output options that we have. std::vector> passedOptions; - GetOptions(passedOptions, args...); + GetOptions(params, passedOptions, args...); // Next, iterate over all the options. std::ostringstream oss; @@ -373,19 +387,21 @@ std::string ProgramCall(const std::string& programName, Args... args) result = oss.str(); oss.str(""); // Reset it. + util::Params params = IO::Parameters(programName); + // Now process each optional parameters. - oss << PrintOptionalInputs(args...) << "\n"; + oss << PrintOptionalInputs(params, args...) << "\n"; result = result + oss.str(); oss.str(""); // Reset it. // Now process each output parameters. std::ostringstream ossOutputs; - ossOutputs << PrintOutputOptions(args...); + ossOutputs << PrintOutputOptions(params, args...); ossOutputs << " := mlpack." << goProgramName << "("; // Now process each required input parameter. - oss << PrintInputOptions(args...); + oss << PrintInputOptions(params, args...); std::string input = oss.str(); if (input != "") ossOutputs << input << ", "; @@ -425,7 +441,9 @@ inline std::string ProgramCall(const std::string& programName) std::ostringstream ossInital; // Determine if we have any output options. - std::map& parameters = IO::Parameters(); + util::Params params = IO::Parameters(programName); + std::map& parameters = params.Parameters(); + ossInital << "// Initialize optional parameters for " << goProgramName << "()." << "\n"; oss << util::HyphenateString(ossInital.str(), 4); @@ -444,8 +462,8 @@ inline std::string ProgramCall(const std::string& programName) // Print the input option. ossInputs << "param." << util::CamelCase(it->second.name, false) << " = "; std::string value; - IO::GetSingleton().functionMap[it->second.tname]["DefaultParam"]( - it->second, NULL, (void*) &value); + params.functionMap[it->second.tname]["DefaultParam"](it->second, NULL, + (void*) &value); ossInputs << value; ossInputs << "\n"; oss << util::HyphenateString(ossInputs.str(), 4); @@ -522,25 +540,32 @@ inline std::string ParamString(const std::string& paramName) * documentation when referencing that argument. */ template -inline std::string ParamString(const std::string& paramName, const T& value) +inline std::string ParamString(const std::string& bindingName, + const std::string& paramName, + const T& value) { - util::ParamData& d = IO::Parameters()[paramName]; + util::Params params = IO::Parameters(bindingName); + util::ParamData& d = params.Parameters()[paramName]; std::ostringstream oss; oss << paramName << "=" << PrintValue(value, d.tname == TYPENAME(std::string)); return oss.str(); } -inline bool IgnoreCheck(const std::string& paramName) +inline bool IgnoreCheck(const std::string& bindingName, + const std::string& paramName) { - return !IO::Parameters()[paramName].input; + util::Params params = IO::Parameters(bindingName); + return !params.Parameters()[paramName].input; } -inline bool IgnoreCheck(const std::vector& constraints) +inline bool IgnoreCheck(const std::string& bindingName, + const std::vector& constraints) { + util::Params params = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i]].input) + if (!params.Parameters()[constraints[i]].input) return true; } @@ -548,16 +573,18 @@ inline bool IgnoreCheck(const std::vector& constraints) } inline bool IgnoreCheck( + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName) { + util::Params params = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i].first].input) + if (!params.Parameters()[constraints[i].first].input) return true; } - return !IO::Parameters()[paramName].input; + return !params.Parameters()[paramName].input; } } // namespace go diff --git a/src/mlpack/bindings/go/print_go.cpp b/src/mlpack/bindings/go/print_go.cpp index 1774e202b7..d44756478d 100644 --- a/src/mlpack/bindings/go/print_go.cpp +++ b/src/mlpack/bindings/go/print_go.cpp @@ -10,9 +10,14 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ +#ifndef BINDING_TYPE +#define BINDING_TYPE BINDING_TYPE_GO +#endif + #include "print_go.hpp" #include #include +#include #include #include @@ -27,16 +32,17 @@ namespace go { * Given a list of parameter definition and program documentation, print a * generated .go file to stdout. * + * @param params Instantiated Params struct with program options. * @param doc Documentation for the program. * @param functionName Name of the function (i.e. "pca"). + * @param bindingName Name of the binding (as registered with IO). */ -void PrintGo(const util::BindingDetails& doc, - const std::string& functionName) +void PrintGo(util::Params& params, + const util::BindingDetails& doc, + const std::string& functionName, + const std::string& bindingName) { - // Restore parameters. - IO::RestoreSettings(doc.programName); - - std::map& parameters = IO::Parameters(); + std::map& parameters = params.Parameters(); typedef std::map::iterator ParamIter; // Split into input and output parameters. Take two passes on the input @@ -100,8 +106,7 @@ void PrintGo(const util::BindingDetails& doc, { util::ParamData& d = parameters.at(inputOptions[i]); size_t indent = 4; - IO::GetSingleton().functionMap[d.tname]["PrintMethodConfig"](d, - (void*) &indent, NULL); + params.functionMap[d.tname]["PrintMethodConfig"](d, (void*) &indent, NULL); } cout << "}" << endl; cout << endl; @@ -115,8 +120,7 @@ void PrintGo(const util::BindingDetails& doc, { util::ParamData& d = parameters.at(inputOptions[i]); size_t indent = 4; - IO::GetSingleton().functionMap[d.tname]["PrintMethodInit"](d, - (void*) &indent, NULL); + params.functionMap[d.tname]["PrintMethodInit"](d, (void*) &indent, NULL); } cout << " " << "}" << endl; cout << "}" << endl; @@ -144,14 +148,12 @@ void PrintGo(const util::BindingDetails& doc, if (!d.required) { bool isLower = false; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, (void*) &indent, - &isLower); + params.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, &isLower); } else { bool isLower = true; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, (void*) &indent, - &isLower); + params.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, &isLower); } cout << endl; } @@ -165,8 +167,7 @@ void PrintGo(const util::BindingDetails& doc, cout << " "; size_t indent = 4; bool isLower = true; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, (void*) &indent, - &isLower); + params.functionMap[d.tname]["PrintDoc"](d, (void*) &indent, &isLower); cout << endl; } cout << endl; @@ -185,7 +186,7 @@ void PrintGo(const util::BindingDetails& doc, if (i != 0) cout << ", "; - IO::GetSingleton().functionMap[d.tname]["PrintDefnInput"](d, NULL, NULL); + params.functionMap[d.tname]["PrintDefnInput"](d, NULL, NULL); counter++; } } @@ -209,7 +210,7 @@ void PrintGo(const util::BindingDetails& doc, cout << ", "; std::tuple t = std::make_tuple(2, false); - IO::GetSingleton().functionMap[d.tname]["PrintDefnOutput"](d, + params.functionMap[d.tname]["PrintDefnOutput"](d, (void*) &t, NULL); } @@ -217,14 +218,11 @@ void PrintGo(const util::BindingDetails& doc, cout << ") {" << endl; // Reset any timers and disable backtraces. - cout << " " << "resetTimers()" << endl; - cout << " " << "enableTimers()" << endl; - cout << " " << "disableBacktrace()" << endl; - cout << " " << "disableVerbose()" << endl; - - // Restore the parameters. - cout << " " << "restoreSettings(\"" << doc.programName << "\")" << endl; + cout << " params := getParams(\"" << bindingName << "\")" << endl; + cout << " timers := getTimers()" << endl; cout << endl; + cout << " disableBacktrace()" << endl; + cout << " disableVerbose()" << endl; // Do any input processing. for (size_t i = 0; i < inputOptions.size(); ++i) @@ -232,8 +230,8 @@ void PrintGo(const util::BindingDetails& doc, util::ParamData& d = parameters.at(inputOptions[i]); size_t indent = 2; - IO::GetSingleton().functionMap[d.tname]["PrintInputProcessing"](d, - (void*) &indent, NULL); + params.functionMap[d.tname]["PrintInputProcessing"](d, (void*) &indent, + NULL); } // Set all output options as passed. @@ -241,13 +239,14 @@ void PrintGo(const util::BindingDetails& doc, for (size_t i = 0; i < outputOptions.size(); ++i) { util::ParamData& d = parameters.at(outputOptions[i]); - cout << " " << "setPassed(\"" << d.name << "\")" << endl; + cout << " " << "setPassed(params, \"" << d.name << "\")" << endl; } cout << endl; // Call the method. cout << " " << "// Call the mlpack program." << endl; - cout << " " << "C.mlpack" << goFunctionName << "()" << endl; + cout << " " << "C.mlpack" << goFunctionName << "(params.mem, timers.mem)" + << endl; cout << endl; // Do any output processing and return. @@ -257,15 +256,13 @@ void PrintGo(const util::BindingDetails& doc, { util::ParamData& d = parameters.at(outputOptions[i]); - IO::GetSingleton().functionMap[d.tname]["PrintOutputProcessing"](d, - NULL, NULL); + params.functionMap[d.tname]["PrintOutputProcessing"](d, NULL, NULL); } - // Clear the parameters. - cout << endl; - cout << " " << "// Clear settings." << endl; - cout << " " << "clearSettings()" << endl; - cout << endl; + // Clean up memory. + cout << " // Clean memory." << endl; + cout << " cleanParams(params)" << endl; + cout << " cleanTimers(timers)" << endl; // Return output parameters. cout << " " << "// Return output(s)." << endl; diff --git a/src/mlpack/bindings/go/print_go.hpp b/src/mlpack/bindings/go/print_go.hpp index d2ce7161de..de5945b4f8 100644 --- a/src/mlpack/bindings/go/print_go.hpp +++ b/src/mlpack/bindings/go/print_go.hpp @@ -22,11 +22,16 @@ namespace go { /** * Given a list of parameter definition and program documentation, print a * generated .go file to stdout. + * + * @param params Instantiated Params struct with program options. * @param doc Documentation for the program. * @param functionName Name of the function (i.e. "pca"). + * @param bindingName Name of the binding as registered with IO. */ -void PrintGo(const util::BindingDetails& doc, - const std::string& functionName); +void PrintGo(util::Params& params, + const util::BindingDetails& doc, + const std::string& functionName, + const std::string& bindingName); } // namespace go diff --git a/src/mlpack/bindings/go/print_input_processing.hpp b/src/mlpack/bindings/go/print_input_processing.hpp index 99b0f9a9ed..9674677004 100644 --- a/src/mlpack/bindings/go/print_input_processing.hpp +++ b/src/mlpack/bindings/go/print_input_processing.hpp @@ -54,8 +54,8 @@ void PrintInputProcessing( * * // Detect if the parameter was passed; set if so. * if param.Name != nil { - * setParam("paramName", param.Name) - * setPassed("paramName") + * setParam(params, "paramName", param.Name) + * setPassed(params, "paramName") * } */ std::cout << prefix << "// Detect if the parameter was passed; set if so." @@ -95,11 +95,12 @@ void PrintInputProcessing( // Print function call to set the given parameter into the io. std::cout << " {" << std::endl; - std::cout << prefix << prefix << "setParam" << GetType(d) << "(\"" - << d.name << "\", param." << goParamName << ")" << std::endl; + std::cout << prefix << prefix << "setParam" << GetType(d) << "(params, " + << "\"" << d.name << "\", param." << goParamName << ")" + << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << prefix << "setPassed(\"" + std::cout << prefix << prefix << "setPassed(params, \"" << d.name << "\")" << std::endl; // If this parameter is "verbose", then enable verbose output. @@ -112,12 +113,13 @@ void PrintInputProcessing( { goParamName = util::CamelCase(goParamName, true); // Print function call to set the given parameter into the io. - std::cout << prefix << "setParam" << GetType(d) << "(\"" + std::cout << prefix << "setParam" << GetType(d) << "(params, \"" << d.name << "\", " << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << "setPassed(\"" << d.name << "\")" << std::endl; + std::cout << prefix << "setPassed(params, \"" << d.name << "\")" + << std::endl; } std::cout << std::endl; // Extra line is to clear up the code a bit. } @@ -147,8 +149,8 @@ void PrintInputProcessing( * * // Detect if the parameter was passed; set if so. * if param.Name != nil { - * gonumToArma("paramName", param.Name) - * setPassed("paramName") + * gonumToArma(params, "paramName", param.Name) + * setPassed(params, "paramName") * } */ std::cout << prefix << "// Detect if the parameter was passed; set if so." @@ -160,11 +162,11 @@ void PrintInputProcessing( // Print function call to set the given parameter into the io. std::cout << prefix << prefix << "gonumToArma" << GetType(d) - << "(\"" << d.name << "\", param." << goParamName + << "(params, \"" << d.name << "\", param." << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << prefix << "setPassed(\"" << d.name << "\")" + std::cout << prefix << prefix << "setPassed(params, \"" << d.name << "\")" << std::endl; std::cout << prefix << "}" << std::endl; // Closing brace. } @@ -173,11 +175,12 @@ void PrintInputProcessing( goParamName = util::CamelCase(goParamName, true); // Print function call to set the given parameter into the io. std::cout << prefix << "gonumToArma" << GetType(d) - << "(\"" << d.name << "\", " << goParamName + << "(params, \"" << d.name << "\", " << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << "setPassed(\"" << d.name << "\")" << std::endl; + std::cout << prefix << "setPassed(params, \"" << d.name << "\")" + << std::endl; } std::cout << std::endl; // Extra line is to clear up the code a bit. } @@ -208,8 +211,8 @@ void PrintInputProcessing( * * // Detect if the parameter was passed; set if so. * if param.Name != nil { - * gonumToArmaMatWithInfo("paramName", param.Name) - * setPassed("paramName") + * gonumToArmaMatWithInfo(params, "paramName", param.Name) + * setPassed(params, "paramName") * } */ std::cout << prefix << "// Detect if the parameter was passed; set if so." @@ -221,11 +224,11 @@ void PrintInputProcessing( // Print function call to set the given parameter into the io. std::cout << prefix << prefix << "gonumToArmaMatWithInfo" - << "(\"" << d.name << "\", param." << goParamName + << "(params, \"" << d.name << "\", param." << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << prefix << "setPassed(\"" << d.name << "\")" + std::cout << prefix << prefix << "setPassed(params, \"" << d.name << "\")" << std::endl; std::cout << prefix << "}" << std::endl; // Closing brace. } @@ -234,11 +237,12 @@ void PrintInputProcessing( goParamName = util::CamelCase(goParamName, true); // Print function call to set the given parameter into the io. std::cout << prefix << "gonumToArmaMatWithInfo" - << "(\"" << d.name << "\", " << goParamName + << "(params, \"" << d.name << "\", " << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << "setPassed(\"" << d.name << "\")" << std::endl; + std::cout << prefix << "setPassed(params, \"" << d.name << "\")" + << std::endl; } std::cout << std::endl; // Extra line is to clear up the code a bit. } @@ -273,8 +277,8 @@ void PrintInputProcessing( * * // Detect if the parameter was passed; set if so. * if param.Name != nil { - * set("paramName", param.Name) - * setPassed("paramName") + * set(params, "paramName", param.Name) + * setPassed(params, "paramName") * } */ std::cout << prefix << "// Detect if the parameter was passed; set if so." @@ -284,11 +288,11 @@ void PrintInputProcessing( std::cout << prefix << "if param." << goParamName << " != nil {" << std::endl; // Print function call to set the given parameter into the io. - std::cout << prefix << prefix << "set" << strippedType << "(\"" + std::cout << prefix << prefix << "set" << strippedType << "(params, \"" << d.name << "\", param." << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << prefix << "setPassed(\"" << d.name << "\")" + std::cout << prefix << prefix << "setPassed(params, \"" << d.name << "\")" << std::endl; std::cout << prefix << "}" << std::endl; // Closing brace. } @@ -296,11 +300,12 @@ void PrintInputProcessing( { goParamName = util::CamelCase(goParamName, true); // Print function call to set the given parameter into the io. - std::cout << prefix << "set" << strippedType << "(\"" << d.name + std::cout << prefix << "set" << strippedType << "(params, \"" << d.name << "\", " << goParamName << ")" << std::endl; // Print function call to set the given parameter as passed. - std::cout << prefix << "setPassed(\"" << d.name << "\")" << std::endl; + std::cout << prefix << "setPassed(params, \"" << d.name << "\")" + << std::endl; } std::cout << std::endl; // Extra line is to clear up the code a bit. } diff --git a/src/mlpack/bindings/go/print_output_processing.hpp b/src/mlpack/bindings/go/print_output_processing.hpp index 5a5c77fa74..e5684fe569 100644 --- a/src/mlpack/bindings/go/print_output_processing.hpp +++ b/src/mlpack/bindings/go/print_output_processing.hpp @@ -39,14 +39,14 @@ void PrintOutputProcessing( /** * This gives us code like: * - * \ := GetParam\("paramName") + * \ := GetParam\(params, "paramName") * */ std::string name = d.name; name = util::CamelCase(name, true); std::cout << prefix << name << " := getParam" << GetType(d) - << "(\"" << d.name << "\")" << std::endl; + << "(params, \"" << d.name << "\")" << std::endl; } /** @@ -66,7 +66,8 @@ void PrintOutputProcessing( * This gives us code like: * * var \Ptr mlpackArma - * \ := \_ptr.ArmaToGonum_\("paramName") + * \ := \_ptr.ArmaToGonum_\(params, + * "paramName") * */ std::string name = d.name; @@ -74,7 +75,7 @@ void PrintOutputProcessing( std::cout << prefix << "var " << name << "Ptr mlpackArma" << std::endl; std::cout << prefix << name << " := " << name << "Ptr.armaToGonum" << GetType(d) - << "(\"" << d.name << "\")" << std::endl; + << "(params, \"" << d.name << "\")" << std::endl; } /** * Print output processing for a matrix with info type. @@ -92,14 +93,15 @@ void PrintOutputProcessing( * This gives us code like: * * var \_ptr mlpackArma - * \ := \Ptr.ArmaToGonumWithInfo\("paramName") + * \ := \Ptr.ArmaToGonumWithInfo\(params, + * "paramName") * */ std::string name = d.name; name = util::CamelCase(name, true); std::cout << prefix << "var " << name << "Ptr mlpackArma" << std::endl; std::cout << prefix << name << " := " << name << "Ptr.armaToGonumWith" - << "Info(\"" << d.name << "\")" << std::endl; + << "Info(params, \"" << d.name << "\")" << std::endl; } /** @@ -122,14 +124,14 @@ void PrintOutputProcessing( * This gives us code like: * * var modelOut \ - * modelOut.get\("paramName") + * modelOut.get\(params, "paramName") * */ std::string name = d.name; name = util::CamelCase(name, true); std::cout << prefix << "var " << name << " " << goStrippedType << std::endl; std::cout << prefix << name << ".get" << strippedType - << "(\"" << d.name << "\")" << std::endl; + << "(params, \"" << d.name << "\")" << std::endl; } /** diff --git a/src/mlpack/bindings/go/tests/test_go_binding_main.cpp b/src/mlpack/bindings/go/tests/test_go_binding_main.cpp index 3aeb255906..d608ccafc2 100644 --- a/src/mlpack/bindings/go/tests/test_go_binding_main.cpp +++ b/src/mlpack/bindings/go/tests/test_go_binding_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME test_go_binding + #include #include @@ -19,7 +25,7 @@ using namespace mlpack; using namespace mlpack::kernel; // Program Name. -BINDING_NAME("Golang binding test"); +BINDING_USER_NAME("Golang binding test"); // Short description. BINDING_SHORT_DESC( @@ -65,110 +71,110 @@ PARAM_MODEL_OUT(GaussianKernel, "model_out", "Output model, with twice the " "bandwidth.", ""); PARAM_DOUBLE_OUT("model_bw_out", "The bandwidth of the model."); -static void mlpackMain() +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */) { - const string s = IO::GetParam("string_in"); - const int i = IO::GetParam("int_in"); - const double d = IO::GetParam("double_in"); + const string s = params.Get("string_in"); + const int i = params.Get("int_in"); + const double d = params.Get("double_in"); - IO::GetParam("string_out") = "wrong"; - IO::GetParam("int_out") = 11; - IO::GetParam("double_out") = 3.0; + params.Get("string_out") = "wrong"; + params.Get("int_out") = 11; + params.Get("double_out") = 3.0; // Check that everything is right on the input, and then set output // accordingly. - if (!IO::HasParam("flag2") && IO::HasParam("flag1")) + if (!params.Has("flag2") && params.Has("flag1")) { if (s == "hello") - IO::GetParam("string_out") = "hello2"; + params.Get("string_out") = "hello2"; if (i == 12) - IO::GetParam("int_out") = 13; + params.Get("int_out") = 13; if (d == 4.0) - IO::GetParam("double_out") = 5.0; + params.Get("double_out") = 5.0; } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("matrix_in")) + if (params.Has("matrix_in")) { - arma::mat out = move(IO::GetParam("matrix_in")); + arma::mat out = move(params.Get("matrix_in")); out.shed_row(4); out.row(2) *= 2.0; - IO::GetParam("matrix_out") = move(out); + params.Get("matrix_out") = move(out); } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("umatrix_in")) + if (params.Has("umatrix_in")) { arma::Mat out = - move(IO::GetParam>("umatrix_in")); + move(params.Get>("umatrix_in")); out.shed_row(4); out.row(2) *= 2; - IO::GetParam>("umatrix_out") = move(out); + params.Get>("umatrix_out") = move(out); } // An input column or row should have all elements multiplied by two. - if (IO::HasParam("col_in")) + if (params.Has("col_in")) { - arma::vec out = move(IO::GetParam("col_in")); + arma::vec out = move(params.Get("col_in")); out *= 2.0; - IO::GetParam("col_out") = move(out); + params.Get("col_out") = move(out); } - if (IO::HasParam("ucol_in")) + if (params.Has("ucol_in")) { arma::Col out = - move(IO::GetParam>("ucol_in")); + move(params.Get>("ucol_in")); out *= 2; - IO::GetParam>("ucol_out") = move(out); + params.Get>("ucol_out") = move(out); } - if (IO::HasParam("row_in")) + if (params.Has("row_in")) { - arma::rowvec out = move(IO::GetParam("row_in")); + arma::rowvec out = move(params.Get("row_in")); out *= 2.0; - IO::GetParam("row_out") = move(out); + params.Get("row_out") = move(out); } - if (IO::HasParam("urow_in")) + if (params.Has("urow_in")) { arma::Row out = - move(IO::GetParam>("urow_in")); + move(params.Get>("urow_in")); out *= 2; - IO::GetParam>("urow_out") = move(out); + params.Get>("urow_out") = move(out); } // Vector arguments should have the last element removed. - if (IO::HasParam("vector_in")) + if (params.Has("vector_in")) { - vector out = move(IO::GetParam>("vector_in")); + vector out = move(params.Get>("vector_in")); out.pop_back(); - IO::GetParam>("vector_out") = move(out); + params.Get>("vector_out") = move(out); } - if (IO::HasParam("str_vector_in")) + if (params.Has("str_vector_in")) { - vector out = move(IO::GetParam>("str_vector_in")); + vector out = move(params.Get>("str_vector_in")); out.pop_back(); - IO::GetParam>("str_vector_out") = move(out); + params.Get>("str_vector_out") = move(out); } // All numeric elements should be multiplied by 3. - if (IO::HasParam("matrix_and_info_in")) + if (params.Has("matrix_and_info_in")) { typedef tuple TupleType; - TupleType tuple = move(IO::GetParam("matrix_and_info_in")); + TupleType tuple = move(params.Get("matrix_and_info_in")); const data::DatasetInfo& di = std::get<0>(tuple); arma::mat& m = std::get<1>(tuple); @@ -179,19 +185,19 @@ static void mlpackMain() m.row(i) *= 2.0; } - IO::GetParam("matrix_and_info_out") = move(m); + params.Get("matrix_and_info_out") = move(m); } // If we got a request to build a model, then build it. - if (IO::HasParam("build_model")) + if (params.Has("build_model")) { - IO::GetParam("model_out") = new GaussianKernel(10.0); + params.Get("model_out") = new GaussianKernel(10.0); } // If we got an input model, double the bandwidth and output that. - if (IO::HasParam("model_in")) + if (params.Has("model_in")) { - IO::GetParam("model_bw_out") = - IO::GetParam("model_in")->Bandwidth() * 2.0; + params.Get("model_bw_out") = + params.Get("model_in")->Bandwidth() * 2.0; } } diff --git a/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in b/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in index a6286faeab..203f7fefd7 100644 --- a/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in +++ b/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in @@ -20,7 +20,6 @@ #include "print_docs.hpp" #include "get_binding_name.hpp" -static const std::string testName = "${BINDING}"; #include <${PROGRAM_MAIN_FILE}> using namespace std; diff --git a/src/mlpack/bindings/markdown/print_docs.cpp b/src/mlpack/bindings/markdown/print_docs.cpp index e103437f80..56a4575c7a 100644 --- a/src/mlpack/bindings/markdown/print_docs.cpp +++ b/src/mlpack/bindings/markdown/print_docs.cpp @@ -57,9 +57,8 @@ void PrintHeaders(const std::string& bindingName, void PrintDocs(const std::string& bindingName, const vector& languages) { - BindingDetails& doc = BindingInfo::GetBindingDetails(bindingName); - - IO::RestoreSettings(bindingName); + Params params = IO::Parameters(bindingName); + const BindingDetails& doc = params.Doc(); // First, for this section, print each of the names. for (size_t i = 0; i < languages.size(); ++i) @@ -122,7 +121,7 @@ void PrintDocs(const std::string& bindingName, << endl; cout << "|------------|------------|-------------------|---------------|" << endl; - map& parameters = IO::Parameters(); + map& parameters = params.Parameters(); for (map::iterator it = parameters.begin(); it != parameters.end(); ++it) { @@ -288,6 +287,4 @@ void PrintDocs(const std::string& bindingName, cout << "" << endl; cout << endl; } - - IO::ClearSettings(); } diff --git a/src/mlpack/bindings/python/py_option.hpp b/src/mlpack/bindings/python/py_option.hpp index 645279173b..8c6fca7590 100644 --- a/src/mlpack/bindings/python/py_option.hpp +++ b/src/mlpack/bindings/python/py_option.hpp @@ -77,12 +77,13 @@ class PyOption IO::AddFunction(data.tname, "PrintClassDefn", &PrintClassDefn); IO::AddFunction(data.tname, "PrintDefn", &PrintDefn); IO::AddFunction(data.tname, "PrintDoc", &PrintDoc); - IO::AddFunction(data.tname, "PrintOutputProcessing", &PrintOutputProcessing); - IO::AddFunction(data.tname, "PrintInputProcessing", &PrintInputProcessing); + IO::AddFunction(data.tname, "PrintOutputProcessing", + &PrintOutputProcessing); + IO::AddFunction(data.tname, "PrintInputProcessing", + &PrintInputProcessing); IO::AddFunction(data.tname, "ImportDecl", &ImportDecl); - // Add the ParamData object to the IO class - // for the correct binding name. + // Add the ParamData object to the IO class for the correct binding name. IO::AddParameter(bindingName, std::move(data)); } }; diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index 09ed876aef..bd690e1560 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -309,7 +309,8 @@ PARAM_FLAG("verbose", "Display informational messages and the full list of " #define PRINT_DATASET mlpack::bindings::go::PrintDataset #define PRINT_MODEL mlpack::bindings::go::PrintModel #define PRINT_CALL mlpack::bindings::go::ProgramCall -#define BINDING_IGNORE_CHECK mlpack::bindings::go::IgnoreCheck +#define BINDING_IGNORE_CHECK(x) mlpack::bindings::go::IgnoreCheck( \ + STRINGIFY(BINDING_NAME), x) namespace mlpack { namespace util { @@ -320,21 +321,15 @@ using Option = mlpack::bindings::go::GoOption; } } -static const std::string testName = ""; #include -#undef BINDING_USER_NAME -#define BINDING_USER_NAME(NAME) static \ - mlpack::util::ProgramName \ - io_programname_dummy_object = mlpack::util::ProgramName(NAME); \ - namespace mlpack { \ - namespace bindings { \ - namespace go { \ - std::string programName = NAME; \ - } \ - } \ - } +// In Go, we want to call the binding function mlpack_() instead +// of just (), so we change the definition of BINDING_FUNCTION(). +#undef BINDING_FUNCTION +#define BINDING_FUNCTION(...) JOIN(mlpack_, BINDING_NAME)(__VA_ARGS__) +// TODO: can't use PARAM_FLAG here---need to actually specify it as part of the +// "" binding PARAM_FLAG("verbose", "Display informational messages and the full list of " "parameters and timers at the end of execution.", "v"); diff --git a/src/mlpack/methods/hmm/hmm_generate_main.cpp b/src/mlpack/methods/hmm/hmm_generate_main.cpp index 257bd46bad..8381d5901b 100644 --- a/src/mlpack/methods/hmm/hmm_generate_main.cpp +++ b/src/mlpack/methods/hmm/hmm_generate_main.cpp @@ -125,7 +125,7 @@ struct Generate } }; -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { RequireAtLeastOnePassed(params, { "output", "state" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/hmm/hmm_loglik_main.cpp b/src/mlpack/methods/hmm/hmm_loglik_main.cpp index c671fe5b05..b78fb09b1b 100644 --- a/src/mlpack/methods/hmm/hmm_loglik_main.cpp +++ b/src/mlpack/methods/hmm/hmm_loglik_main.cpp @@ -105,7 +105,7 @@ struct Loglik } }; -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { // Load model, and calculate the log-likelihood of the sequence. params.Get("input_model")->PerformAction( diff --git a/src/mlpack/methods/linear_svm/linear_svm_main.cpp b/src/mlpack/methods/linear_svm/linear_svm_main.cpp index c34deb0acf..26ba1ab565 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_main.cpp +++ b/src/mlpack/methods/linear_svm/linear_svm_main.cpp @@ -175,7 +175,7 @@ PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " "matrix is where the class probabilities for the test set will be saved.", "p"); -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/nca/nca_main.cpp b/src/mlpack/methods/nca/nca_main.cpp index c5dceaa007..7502aa4d57 100644 --- a/src/mlpack/methods/nca/nca_main.cpp +++ b/src/mlpack/methods/nca/nca_main.cpp @@ -149,7 +149,7 @@ using namespace mlpack::metric; using namespace mlpack::util; using namespace std; -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { if (params.Get("seed") != 0) math::RandomSeed((size_t) params.Get("seed")); diff --git a/src/mlpack/methods/preprocess/image_converter_main.cpp b/src/mlpack/methods/preprocess/image_converter_main.cpp index 75d7537696..9e7e0281dd 100644 --- a/src/mlpack/methods/preprocess/image_converter_main.cpp +++ b/src/mlpack/methods/preprocess/image_converter_main.cpp @@ -86,7 +86,7 @@ PARAM_INT_IN("height", "Height of the images.", "H", 0); PARAM_FLAG("save", "Save a dataset as images.", "s"); PARAM_MATRIX_IN("dataset", "Input matrix to save as images.", "I"); -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { // Parse command line options. const vector fileNames = params.Get >("input"); diff --git a/src/mlpack/methods/radical/radical_main.cpp b/src/mlpack/methods/radical/radical_main.cpp index 6f52dac94c..c910037ebf 100644 --- a/src/mlpack/methods/radical/radical_main.cpp +++ b/src/mlpack/methods/radical/radical_main.cpp @@ -87,7 +87,7 @@ using namespace mlpack::util; using namespace std; using namespace arma; -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { // Set random seed. if (params.Get("seed") != 0) From c47b5fed397217d73c17aa8c46f6715ac0f091f0 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 13 Jul 2021 15:10:49 -0400 Subject: [PATCH 632/729] Use BINDING_FUNCTION() not BINDING_NAME(). --- src/mlpack/bindings/python/tests/test_python_binding_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp index 19b5f5aa4b..b9439e9d7f 100644 --- a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp +++ b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp @@ -79,7 +79,7 @@ PARAM_MODEL_OUT(GaussianKernel, "model_out", "Output model, with twice the " "bandwidth.", ""); PARAM_DOUBLE_OUT("model_bw_out", "The bandwidth of the model."); -static void BINDING_NAME(util::Params& params, util::Timers& timer) +void BINDING_FUNCTION(util::Params& params, util::Timers& timer) { const string s = params.Get("string_in"); const int i = params.Get("int_in"); From b5db87de130460aa2c1b81f81175f2667f2855d5 Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Wed, 14 Jul 2021 00:51:43 +0530 Subject: [PATCH 633/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index f24e678c00..edaa3c8b11 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2185,7 +2185,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") input << 10 << 20 << arma::endr << 30 << 40 << arma::endr; - + input.reshape(4, 1); BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth, alpha); expectedOutput << 6.6880 << 7.3331 << 9.6973 << 12.7950 << 15.8927 << 18.2569 << 18.9020 << arma::endr From 4d8c1ff83781802085e41d06fb2e4569d55e603c Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Wed, 14 Jul 2021 02:54:13 +0530 Subject: [PATCH 634/729] Better approach for forward pass by computing weight matrix --- .../methods/ann/layer/bicubic_interpolation_impl.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index b0b339a708..31c1f78937 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -126,13 +126,13 @@ void BicubicInterpolation::Forward( double fr = rOrigin - 0.5; fr = fr - std::floor(fr); - arma::mat weightR = arma::mat(1, 4); - arma::mat weightC = arma::mat(4, 1); + arma::mat weightR = arma::mat(4, 1); + arma::mat weightC = arma::mat(1, 4); GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - arma::mat val = weightR * kernal * weightC; - outputAsCube(i, j, k) = val(0); + arma::mat weightMatrix = weightR * weightC; + outputAsCube(i, j, k) = arma::accu(weightMatrix % kernal); } } } From 78845cadf5fa0161d929b62a33661eb72cbadb04 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 14 Jul 2021 18:47:46 +0530 Subject: [PATCH 635/729] Add FitnessFunction as parameter to private Train functions --- .../methods/decision_tree/decision_tree_regressor.hpp | 6 ++++-- .../decision_tree/decision_tree_regressor_impl.hpp | 10 ++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 6ad75adc05..0bb619ea1c 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -488,7 +488,8 @@ class DecisionTreeRegressor : const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector); + DimensionSelectionType& dimensionSelector, + FitnessFunction fitnessFunction = FitnessFunction()); /** * Corresponding to the public Train() method, this method is designed for @@ -514,7 +515,8 @@ class DecisionTreeRegressor : const size_t minimumLeafSize, const double minimumGainSplit, const size_t maximumDepth, - DimensionSelectionType& dimensionSelector); + DimensionSelectionType& dimensionSelector, + FitnessFunction fitnessFunction = FitnessFunction()); }; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 5e0b7339ca..278789c316 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -605,10 +605,9 @@ double DecisionTreeRegressor Date: Wed, 14 Jul 2021 19:00:07 +0530 Subject: [PATCH 636/729] Add FitnessFunction as parameter to SplitIfBetter --- .../decision_tree/all_categorical_split.hpp | 3 +- .../all_categorical_split_impl.hpp | 5 ++- .../best_binary_numeric_split.hpp | 6 ++-- .../best_binary_numeric_split_impl.hpp | 10 +++--- .../decision_tree_regressor_impl.hpp | 9 +++-- .../random_binary_numeric_split.hpp | 1 + .../random_binary_numeric_split_impl.hpp | 3 +- .../tests/decision_tree_regressor_test.cpp | 34 +++++++++++-------- 8 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/mlpack/methods/decision_tree/all_categorical_split.hpp b/src/mlpack/methods/decision_tree/all_categorical_split.hpp index 13911887a9..b604729a00 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split.hpp @@ -103,7 +103,8 @@ class AllCategoricalSplit const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, - AuxiliarySplitInfo& aux); + AuxiliarySplitInfo& aux, + FitnessFunction fitnessFunction); /** * Return the number of children in the split. diff --git a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp index 1256436f79..25ca80a858 100644 --- a/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/all_categorical_split_impl.hpp @@ -125,10 +125,9 @@ double AllCategoricalSplit::SplitIfBetter( const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, - AuxiliarySplitInfo& /* aux */) + AuxiliarySplitInfo& /* aux */, + FitnessFunction fitnessFunction) { - FitnessFunction fitnessFunction; - // Count the number of elements in each potential child. const double epsilon = 1e-7; // Tolerance for floating-point errors. arma::Col counts(numCategories, arma::fill::zeros); diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp index a39ac91d8f..4b51055705 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split.hpp @@ -118,7 +118,8 @@ class BestBinaryNumericSplit const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, - AuxiliarySplitInfo& aux); + AuxiliarySplitInfo& aux, + FitnessFunction fitnessFunction); /** * Check if we can split a node. If we can split a node in a way that @@ -154,7 +155,8 @@ class BestBinaryNumericSplit const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, - AuxiliarySplitInfo& /* aux */); + AuxiliarySplitInfo& /* aux */, + FitnessFunction fitnessFunction); /** * Returns 2, since the binary split always has two children. diff --git a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp index 7ece8f3f9a..de06768c65 100644 --- a/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp +++ b/src/mlpack/methods/decision_tree/best_binary_numeric_split_impl.hpp @@ -200,13 +200,12 @@ BestBinaryNumericSplit::SplitIfBetter( const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, - AuxiliarySplitInfo& /* aux */) + AuxiliarySplitInfo& /* aux */, + FitnessFunction fitnessFunction) { typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; - FitnessFunction fitnessFunction; - // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) return DBL_MAX; @@ -340,13 +339,12 @@ BestBinaryNumericSplit::SplitIfBetter( const size_t minimumLeafSize, const double minimumGainSplit, double& splitInfo, - AuxiliarySplitInfo& /* aux */) + AuxiliarySplitInfo& /* aux */, + FitnessFunction fitnessFunction) { typedef typename ResponsesType::elem_type RType; typedef typename WeightVecType::elem_type WType; - FitnessFunction fitnessFunction; - // First sanity check: if we don't have enough points, we can't split. if (data.n_elem < (minimumLeafSize * 2)) return DBL_MAX; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 278789c316..b10f089c7c 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -640,7 +640,8 @@ double DecisionTreeRegressor::SplitIfBetter( const double minimumGainSplit, double& splitInfo, AuxiliarySplitInfo& /* aux */, + FitnessFunction fitnessFunction, const bool splitIfBetterGain) { - FitnessFunction fitnessFunction; - double bestFoundGain = std::min(bestGain + minimumGainSplit, 0.0); // Forcing a minimum leaf size of 1 (empty children don't make sense). const size_t minimum = std::max(minimumLeafSize, (size_t) 1); diff --git a/src/mlpack/tests/decision_tree_regressor_test.cpp b/src/mlpack/tests/decision_tree_regressor_test.cpp index c7909aaeab..da158bc462 100644 --- a/src/mlpack/tests/decision_tree_regressor_test.cpp +++ b/src/mlpack/tests/decision_tree_regressor_test.cpp @@ -216,10 +216,11 @@ TEST_CASE("AllCategoricalSplitSimpleSplitTest_", "[DecisionTreeRegressorTest]") MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictor, 2, responses, weights, 3, 1e-7, splitInfo, aux); + bestGain, predictor, 2, responses, weights, 3, 1e-7, splitInfo, aux, + Gain); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictor, 2, - responses, weights, 3, 1e-7, splitInfo, aux); + responses, weights, 3, 1e-7, splitInfo, aux, Gain); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -248,7 +249,8 @@ TEST_CASE("AllCategoricalSplitMinSamplesTest_", "[DecisionTreeRegressorTest]") MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( - bestGain, predictors, 4, responses, weights, 4, 1e-7, splitInfo, aux); + bestGain, predictors, 4, responses, weights, 4, 1e-7, splitInfo, aux, + Gain); // Make sure it's not split. REQUIRE(gain == DBL_MAX); @@ -281,10 +283,10 @@ TEST_CASE("AllCategoricalSplitNoGainTest_", "[DecisionTreeRegressorTest]") const double bestGain = Gain.Evaluate(responses, weights); const double gain = AllCategoricalSplit::SplitIfBetter( bestGain, predictors, 10, responses, weights, 10, 1e-7, - splitInfo, aux); + splitInfo, aux, Gain); const double weightedGain = AllCategoricalSplit::SplitIfBetter(bestGain, predictors, - 10, responses, weights, 10, 1e-7, splitInfo, aux); + 10, responses, weights, 10, 1e-7, splitInfo, aux, Gain); // Make sure that there was no split. REQUIRE(gain == DBL_MAX); @@ -312,10 +314,10 @@ TEST_CASE("BestBinaryNumericSplitSimpleSplitTest_", MADGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, responses, weights, 3, 1e-7, splitInfo, aux); + bestGain, predictors, responses, weights, 3, 1e-7, splitInfo, aux, Gain); const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, predictors, - responses, weights, 3, 1e-7, splitInfo, aux); + responses, weights, 3, 1e-7, splitInfo, aux, Gain); // Make sure that a split was made. REQUIRE(gain > bestGain); @@ -349,11 +351,11 @@ TEST_CASE("BestBinaryNumericSplitMinSamplesTest_", MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, responses, weights, 8, 1e-7, splitInfo, aux); + bestGain, predictors, responses, weights, 8, 1e-7, splitInfo, aux, Gain); // This should make no difference because it won't split at all. const double weightedGain = BestBinaryNumericSplit::SplitIfBetter(bestGain, - predictors, responses, weights, 8, 1e-7, splitInfo, aux); + predictors, responses, weights, 8, 1e-7, splitInfo, aux, Gain); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); @@ -384,7 +386,8 @@ TEST_CASE("BestBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = BestBinaryNumericSplit::SplitIfBetter( - bestGain, predictors, responses, weights, 10, 1e-7, splitInfo, aux); + bestGain, predictors, responses, weights, 10, 1e-7, splitInfo, aux, + Gain); // Make sure there was no split. REQUIRE(gain == DBL_MAX); @@ -409,10 +412,10 @@ TEST_CASE("RandomBinaryNumericSplitAlwaysSplit_", MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, responses, weights, 1, 1e-7, splitInfo, aux); + bestGain, values, responses, weights, 1, 1e-7, splitInfo, aux, Gain); const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - responses, weights, 1, 1e-7, splitInfo, aux); + responses, weights, 1, 1e-7, splitInfo, aux, Gain); // Make sure that split was made. REQUIRE(gain != DBL_MAX); @@ -437,11 +440,11 @@ TEST_CASE("RandomBinaryNumericSplitMinSamplesTest_", MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, responses, weights, 8, 1e-7, splitInfo, aux); + bestGain, values, responses, weights, 8, 1e-7, splitInfo, aux, Gain); // This should make no difference because it won't split at all. const double weightedGain = RandomBinaryNumericSplit::SplitIfBetter(bestGain, values, - responses, weights, 8, 1e-7, splitInfo, aux); + responses, weights, 8, 1e-7, splitInfo, aux, Gain); // Make sure that no split was made. REQUIRE(gain == DBL_MAX); @@ -472,7 +475,8 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest_", "[DecisionTreeRegressorTest]") MSEGain Gain; const double bestGain = Gain.Evaluate(responses, weights); const double gain = RandomBinaryNumericSplit::SplitIfBetter( - bestGain, values, responses, weights, 10, 1e-7, splitInfo, aux, true); + bestGain, values, responses, weights, 10, 1e-7, splitInfo, aux, Gain, + true); // Make sure there was no split. REQUIRE(gain == DBL_MAX); From 52f4886efc9c883937fb03eb6ce2c2e24672dae9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 14 Jul 2021 19:12:04 +0530 Subject: [PATCH 637/729] Add FitnessFunction as parameter to public Train functions --- .../decision_tree/decision_tree_regressor.hpp | 8 ++++++-- .../decision_tree_regressor_impl.hpp | 16 ++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 0bb619ea1c..f244fbf9f8 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -286,7 +286,8 @@ class DecisionTreeRegressor : const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = - DimensionSelectionType()); + DimensionSelectionType(), + FitnessFunction fitnessFunction = FitnessFunction()); /** * Train the decision tree on the given data, assuming that all dimensions are @@ -311,7 +312,8 @@ class DecisionTreeRegressor : const double minimumGainSplit = 1e-7, const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = - DimensionSelectionType()); + DimensionSelectionType(), + FitnessFunction fitnessFunction = FitnessFunction()); /** * Train the decision tree on the given weighted data. This will overwrite @@ -343,6 +345,7 @@ class DecisionTreeRegressor : const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = DimensionSelectionType(), + FitnessFunction fitnessFunction = FitnessFunction(), const std::enable_if_t::type>::value>* = 0); @@ -373,6 +376,7 @@ class DecisionTreeRegressor : const size_t maximumDepth = 0, DimensionSelectionType dimensionSelector = DimensionSelectionType(), + FitnessFunction fitnessFunction = FitnessFunction(), const std::enable_if_t::type>::value>* = 0); diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index b10f089c7c..e798f1c107 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -432,7 +432,8 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, fitnessFunction); } //! Train on the given data, assuming all dimensions are numeric. @@ -471,7 +472,8 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpResponses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, fitnessFunction); } //! Train on the given weighted data. @@ -513,6 +515,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, datasetInfo, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, fitnessFunction); } //! Train on the given weighted all numeric data. @@ -558,6 +561,7 @@ double DecisionTreeRegressor(tmpData, 0, tmpData.n_cols, tmpResponses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, - dimensionSelector); + dimensionSelector, fitnessFunction); } //! Train on the given data. From e1bc920028929a730b05fa3f827c0ed478a2cde9 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 14 Jul 2021 09:59:09 -0400 Subject: [PATCH 638/729] Adapt test Julia binding. --- .../julia/tests/test_julia_binding_main.cpp | 100 ++++++++++-------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp b/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp index 28885ca13b..85e728f26c 100644 --- a/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp +++ b/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME test_julia_binding + #include #include @@ -19,7 +25,7 @@ using namespace mlpack; using namespace mlpack::kernel; // Program Name. -BINDING_NAME("Julia binding test"); +BINDING_USER_NAME("Julia binding test"); // Short description. BINDING_SHORT_DESC( @@ -67,110 +73,110 @@ PARAM_MODEL_OUT(GaussianKernel, "model_out", "Output model, with twice the " "bandwidth.", ""); PARAM_DOUBLE_OUT("model_bw_out", "The bandwidth of the model."); -static void mlpackMain() +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { - const string s = IO::GetParam("string_in"); - const int i = IO::GetParam("int_in"); - const double d = IO::GetParam("double_in"); + const string s = params.Get("string_in"); + const int i = params.Get("int_in"); + const double d = params.Get("double_in"); - IO::GetParam("string_out") = "wrong"; - IO::GetParam("int_out") = 11; - IO::GetParam("double_out") = 3.0; + params.Get("string_out") = "wrong"; + params.Get("int_out") = 11; + params.Get("double_out") = 3.0; // Check that everything is right on the input, and then set output // accordingly. - if (!IO::HasParam("flag2") && IO::HasParam("flag1")) + if (!params.Has("flag2") && params.Has("flag1")) { if (s == "hello") - IO::GetParam("string_out") = "hello2"; + params.Get("string_out") = "hello2"; if (i == 12) - IO::GetParam("int_out") = 13; + params.Get("int_out") = 13; if (d == 4.0) - IO::GetParam("double_out") = 5.0; + params.Get("double_out") = 5.0; } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("matrix_in")) + if (params.Has("matrix_in")) { - arma::mat out = move(IO::GetParam("matrix_in")); + arma::mat out = move(params.Get("matrix_in")); out.shed_row(4); out.row(2) *= 2.0; - IO::GetParam("matrix_out") = move(out); + params.Get("matrix_out") = move(out); } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("umatrix_in")) + if (params.Has("umatrix_in")) { arma::Mat out = - move(IO::GetParam>("umatrix_in")); + move(params.Get>("umatrix_in")); out.shed_row(4); out.row(2) *= 2; - IO::GetParam>("umatrix_out") = move(out); + params.Get>("umatrix_out") = move(out); } // An input column or row should have all elements multiplied by two. - if (IO::HasParam("col_in")) + if (params.Has("col_in")) { - arma::vec out = move(IO::GetParam("col_in")); + arma::vec out = move(params.Get("col_in")); out *= 2.0; - IO::GetParam("col_out") = move(out); + params.Get("col_out") = move(out); } - if (IO::HasParam("ucol_in")) + if (params.Has("ucol_in")) { arma::Col out = - move(IO::GetParam>("ucol_in")); + move(params.Get>("ucol_in")); out *= 2; - IO::GetParam>("ucol_out") = move(out); + params.Get>("ucol_out") = move(out); } - if (IO::HasParam("row_in")) + if (params.Has("row_in")) { - arma::rowvec out = move(IO::GetParam("row_in")); + arma::rowvec out = move(params.Get("row_in")); out *= 2.0; - IO::GetParam("row_out") = move(out); + params.Get("row_out") = move(out); } - if (IO::HasParam("urow_in")) + if (params.Has("urow_in")) { arma::Row out = - move(IO::GetParam>("urow_in")); + move(params.Get>("urow_in")); out *= 2; - IO::GetParam>("urow_out") = move(out); + params.Get>("urow_out") = move(out); } // Vector arguments should have the last element removed. - if (IO::HasParam("vector_in")) + if (params.Has("vector_in")) { - vector out = move(IO::GetParam>("vector_in")); + vector out = move(params.Get>("vector_in")); out.pop_back(); - IO::GetParam>("vector_out") = move(out); + params.Get>("vector_out") = move(out); } - if (IO::HasParam("str_vector_in")) + if (params.Has("str_vector_in")) { - vector out = move(IO::GetParam>("str_vector_in")); + vector out = move(params.Get>("str_vector_in")); out.pop_back(); - IO::GetParam>("str_vector_out") = move(out); + params.Get>("str_vector_out") = move(out); } // All numeric elements should be multiplied by 3. - if (IO::HasParam("matrix_and_info_in")) + if (params.Has("matrix_and_info_in")) { typedef tuple TupleType; - TupleType tuple = move(IO::GetParam("matrix_and_info_in")); + TupleType tuple = move(params.Get("matrix_and_info_in")); const data::DatasetInfo& di = std::get<0>(tuple); arma::mat& m = std::get<1>(tuple); @@ -181,26 +187,26 @@ static void mlpackMain() m.row(i) *= 2.0; } - IO::GetParam("matrix_and_info_out") = move(m); + params.Get("matrix_and_info_out") = move(m); } // If we got a request to build a model, then build it. - if (IO::HasParam("build_model")) + if (params.Has("build_model")) { - IO::GetParam("model_out") = new GaussianKernel(10.0); + params.Get("model_out") = new GaussianKernel(10.0); } // If we got an input model, double the bandwidth and output that. - if (IO::HasParam("model_in")) + if (params.Has("model_in")) { - IO::GetParam("model_bw_out") = - IO::GetParam("model_in")->Bandwidth() * 2.0; + params.Get("model_bw_out") = + params.Get("model_in")->Bandwidth() * 2.0; } // If requested, duplicate the input model as the output model. - if (IO::HasParam("duplicate_model")) + if (params.Has("duplicate_model")) { - IO::GetParam("model_out") = - IO::GetParam("model_in"); + params.Get("model_out") = + params.Get("model_in"); } } From f43a51b58d0af2c596c3e1e12f74f6b0237f72e1 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Wed, 14 Jul 2021 20:06:22 +0530 Subject: [PATCH 639/729] DecisionTreeRegressor::CalculatePrediction() => FitnessFunction::OutputLeafValue() --- .../decision_tree/decision_tree_regressor.hpp | 7 --- .../decision_tree_regressor_impl.hpp | 47 ++++--------------- src/mlpack/methods/decision_tree/mad_gain.hpp | 22 +++++++++ src/mlpack/methods/decision_tree/mse_gain.hpp | 22 +++++++++ 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index f244fbf9f8..6dfd53ecf4 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -459,13 +459,6 @@ class DecisionTreeRegressor : typedef typename CategoricalSplit::AuxiliarySplitInfo CategoricalAuxiliarySplitInfo; - /** - * Calculate the prediction value for the leaf nodes. - */ - template - void CalculatePrediction(const ResponsesType& responses, - const WeightsType& weights); - /** * Corresponding to the public Train() method, this method is designed for * avoiding unnecessary copies during training. This function is called to diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index e798f1c107..ba87d0a74d 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -762,10 +762,11 @@ double DecisionTreeRegressor( - responses.subvec(begin, begin + count - 1), - UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + // Calculate prediction value because we are a leaf. + splitPointOrPrediction = + fitnessFunction.template OutputLeafValue( + responses.subvec(begin, begin + count - 1), + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); } return -bestGain; @@ -916,10 +917,11 @@ double DecisionTreeRegressor( - responses.subvec(begin, begin + count - 1), - UseWeights ? weights.subvec(begin, begin + count - 1) : weights); + // Calculate prediction value because we are a leaf. + splitPointOrPrediction = + fitnessFunction.template OutputLeafValue( + responses.subvec(begin, begin + count - 1), + UseWeights ? weights.subvec(begin, begin + count - 1) : weights); } return -bestGain; @@ -974,35 +976,6 @@ void DecisionTreeRegressor class NumericSplitType, - template class CategoricalSplitType, - typename DimensionSelectionType, - bool NoRecursion> -template -void DecisionTreeRegressor::CalculatePrediction(const ResponsesType& responses, - const WeightsType& weights) -{ - if (UseWeights) - { - double accWeights, weightedSum; - WeightedSum(responses, weights, 0, responses.n_elem, accWeights, - weightedSum); - splitPointOrPrediction = weightedSum / accWeights; - } - else - { - double sum; - Sum(responses, 0, responses.n_elem, sum); - splitPointOrPrediction = sum / responses.n_elem; - } -} - template class NumericSplitType, template class CategoricalSplitType, diff --git a/src/mlpack/methods/decision_tree/mad_gain.hpp b/src/mlpack/methods/decision_tree/mad_gain.hpp index 56c5087306..d73ecba4cc 100644 --- a/src/mlpack/methods/decision_tree/mad_gain.hpp +++ b/src/mlpack/methods/decision_tree/mad_gain.hpp @@ -98,6 +98,28 @@ class MADGain return Evaluate(values, weights, 0, values.n_elem); } + + /** + * Calculates the output value for each leaf node for prediction. + */ + template + double OutputLeafValue(const ResponsesType& responses, + const WeightsType& weights) + { + if (UseWeights) + { + double accWeights, weightedSum; + WeightedSum(responses, weights, 0, responses.n_elem, accWeights, + weightedSum); + return weightedSum / accWeights; + } + else + { + double sum; + Sum(responses, 0, responses.n_elem, sum); + return sum / responses.n_elem; + } + } }; } // namespace tree diff --git a/src/mlpack/methods/decision_tree/mse_gain.hpp b/src/mlpack/methods/decision_tree/mse_gain.hpp index e4e9c0ff3b..af1368881b 100644 --- a/src/mlpack/methods/decision_tree/mse_gain.hpp +++ b/src/mlpack/methods/decision_tree/mse_gain.hpp @@ -95,6 +95,28 @@ class MSEGain return Evaluate(values, weights, 0, values.n_elem); } + /** + * Calculates the output value for each leaf node for prediction. + */ + template + double OutputLeafValue(const ResponsesType& responses, + const WeightsType& weights) + { + if (UseWeights) + { + double accWeights, weightedSum; + WeightedSum(responses, weights, 0, responses.n_elem, accWeights, + weightedSum); + return weightedSum / accWeights; + } + else + { + double sum; + Sum(responses, 0, responses.n_elem, sum); + return sum / responses.n_elem; + } + } + /** * Calculates the mean squared error gain for the left and right children * for the current index. From 07bb8511466893c68f10341ab900936ea9dcd689 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 15 Jul 2021 00:35:29 +0530 Subject: [PATCH 640/729] Fixed back prop --- .../methods/ann/layer/bicubic_interpolation_impl.hpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 31c1f78937..04e58d7dfa 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -188,12 +188,12 @@ void BicubicInterpolation::Backward( double fr = rOrigin - 0.5; fr = fr - std::floor(fr); - arma::mat weightR = arma::mat(1, 4); - arma::mat weightC = arma::mat(4, 1); + arma::mat weightR = arma::mat(4, 1); + arma::mat weightC = arma::mat(1, 4); GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - temp(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)) += (weightR * gradientAsCube(i, j, k) * weightC); + temp(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)) += weightR * weightC * gradientAsCube(i, j, k); } } // Adding the contribution of the corner points to the output matrix. @@ -205,10 +205,6 @@ void BicubicInterpolation::Backward( temp.col(2) += temp.col(1); temp.col(inColSize + 1) += temp.col(inColSize + 2); temp.col(inColSize + 1) += temp.col(inColSize + 3); - temp(2, 2) += arma::accu(temp(arma::span(0, 1), arma::span(0, 1))); - temp(inRowSize + 1, inColSize + 1) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(inColSize + 2, inColSize + 3))); - temp(inRowSize + 1, 2) += arma::accu(temp(arma::span(inRowSize + 2, inRowSize + 3), arma::span(0, 1))); - temp(2, inColSize + 1) += arma::accu(temp(arma::span(0, 1), arma::span(inColSize + 2, inColSize + 3))); outputAsCube.slice(k) += temp(arma::span(2, inRowSize + 1), arma::span(2, inColSize + 1)); } From 1343297649792f29f76f0463c5f457c7dd7227df Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 15 Jul 2021 00:39:40 +0530 Subject: [PATCH 641/729] Added back prop test_case --- src/mlpack/tests/ann_layer_test.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index edaa3c8b11..ec492f4532 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2180,7 +2180,6 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") size_t outRowSize = 5; size_t outColSize = 7; size_t depth = 1; - double alpha = -0.75; input.zeros(inRowSize * inColSize * depth, 1); input << 10 << 20 << arma::endr @@ -2196,6 +2195,15 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") expectedOutput.reshape(35, 1); layer.Forward(input, output); CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); + + expectedOutput.clear(); + expectedOutput << 103.7905 << 180.5134 << arma::endr + << 256.9865 << 333.7095 << arma::endr; + expectedOutput.reshape(4, 1); + + layer.Backward(output, output, unzoomedOutput); + CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(output.n_rows), 1e-4); + } /** From c29517a97390a62ad96a70edbeb83f354aa58207 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 15 Jul 2021 01:12:30 +0530 Subject: [PATCH 642/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index ec492f4532..39de48b974 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2185,7 +2185,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") input << 10 << 20 << arma::endr << 30 << 40 << arma::endr; input.reshape(4, 1); - BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth, alpha); + BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth); expectedOutput << 6.6880 << 7.3331 << 9.6973 << 12.7950 << 15.8927 << 18.2569 << 18.9020 << arma::endr << 10.5330 << 11.1781 << 13.5423 << 16.6400 << 19.7377 << 22.1019 << 22.7470 << arma::endr From c7fd4882666717b09e116e80eb566797995bc3a8 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 15 Jul 2021 02:15:38 +0530 Subject: [PATCH 643/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 39de48b974..c90d7b722b 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2202,7 +2202,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") expectedOutput.reshape(4, 1); layer.Backward(output, output, unzoomedOutput); - CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(output.n_rows), 1e-4); + CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-4); } From 16d63517a2525eeb845e22dee9a2b19ecd438c09 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 14 Jul 2021 19:52:17 -0400 Subject: [PATCH 644/729] Adapt R bindings for threadsafe IO. --- CMake/R/ConfigureRCPP.cmake | 12 +- src/mlpack/bindings/R/R_option.hpp | 47 ++- src/mlpack/bindings/R/generate_R.cpp.in | 7 +- src/mlpack/bindings/R/mlpack/R/matrix_utils.R | 6 +- src/mlpack/bindings/R/mlpack/src/r_util.cpp | 278 +++++++++++------- src/mlpack/bindings/R/print_R.cpp | 54 ++-- src/mlpack/bindings/R/print_R.hpp | 8 +- src/mlpack/bindings/R/print_doc_functions.hpp | 14 +- .../bindings/R/print_doc_functions_impl.hpp | 69 +++-- .../bindings/R/print_input_processing.hpp | 40 +-- .../bindings/R/print_output_processing.hpp | 18 +- .../bindings/R/print_serialize_util.hpp | 6 +- src/mlpack/bindings/R/r_method.cpp.in | 7 +- .../bindings/R/tests/test_r_binding_main.cpp | 94 +++--- src/mlpack/core/util/mlpack_main.hpp | 7 +- 15 files changed, 372 insertions(+), 295 deletions(-) diff --git a/CMake/R/ConfigureRCPP.cmake b/CMake/R/ConfigureRCPP.cmake index e728c73d34..c85e14f3a1 100644 --- a/CMake/R/ConfigureRCPP.cmake +++ b/CMake/R/ConfigureRCPP.cmake @@ -35,17 +35,19 @@ if (NOT (MODEL_FILE_TYPE MATCHES "\"${MODEL_SAFE_TYPES}\"")) set(MODEL_PTR_IMPLS "${MODEL_PTR_IMPLS} // Get the pointer to a ${MODEL_TYPE} parameter. // [[Rcpp::export]] -SEXP IO_GetParam${MODEL_SAFE_TYPE}Ptr(const std::string& paramName) +SEXP GetParam${MODEL_SAFE_TYPE}Ptr(SEXP params, const std::string& paramName) { - return std::move((${MODEL_PTR_TYPEDEF}) IO::GetParam<${MODEL_TYPE}*>(paramName)); + util::Params& p = *Rcpp::as>(params); + return std::move((${MODEL_PTR_TYPEDEF}) p.Get<${MODEL_TYPE}*>(paramName)); } // Set the pointer to a ${MODEL_TYPE} parameter. // [[Rcpp::export]] -void IO_SetParam${MODEL_SAFE_TYPE}Ptr(const std::string& paramName, SEXP ptr) +void SetParam${MODEL_SAFE_TYPE}Ptr(SEXP params, const std::string& paramName, SEXP ptr) { - IO::GetParam<${MODEL_TYPE}*>(paramName) = Rcpp::as<${MODEL_PTR_TYPEDEF}>(ptr); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get<${MODEL_TYPE}*>(paramName) = Rcpp::as<${MODEL_PTR_TYPEDEF}>(ptr); + p.SetPassed(paramName); } // Serialize a ${MODEL_TYPE} pointer. diff --git a/src/mlpack/bindings/R/R_option.hpp b/src/mlpack/bindings/R/R_option.hpp index 77f74c091f..598beb321b 100644 --- a/src/mlpack/bindings/R/R_option.hpp +++ b/src/mlpack/bindings/R/R_option.hpp @@ -47,7 +47,7 @@ class ROption * @param input Whether or not the option is an input option. * @param noTranspose If the parameter is a matrix and this is true, then the * matrix will not be transposed on loading. - * @param * (testName) Is not used and added for compatibility reasons. + * @param bindingName Name of the binding that this parameter is for. */ ROption(const T defaultValue, const std::string& identifier, @@ -57,7 +57,7 @@ class ROption const bool required = false, const bool input = true, const bool noTranspose = false, - const std::string& /* testName */ = "") + const std::string& bindingName = "") { // Create the ParamData object to give to IO. util::ParamData data; @@ -75,36 +75,35 @@ class ROption // Every parameter we'll get from R will have the correct type. data.value = boost::any(defaultValue); - // Restore the parameters for this program. - if (identifier != "verbose") - IO::RestoreSettings(IO::ProgramName(), false); - // Set the function pointers that we'll need. All of these function // pointers will be used by both the program that generates the R, and // also the binding itself. (The binding itself will only use GetParam, // GetPrintableParam, and GetRawParam.) - IO::GetSingleton().functionMap[data.tname]["GetParam"] = &GetParam; - IO::GetSingleton().functionMap[data.tname]["GetPrintableParam"] = - &GetPrintableParam; + IO::AddFunction(data.tname, "GetParam", &GetParam); + IO::AddFunction(data.tname, "GetPrintableParam", &GetPrintableParam); // These are used by the R generator. - IO::GetSingleton().functionMap[data.tname]["PrintDoc"] = &PrintDoc; - IO::GetSingleton().functionMap[data.tname]["PrintInputParam"] = - &PrintInputParam; - IO::GetSingleton().functionMap[data.tname]["PrintOutputProcessing"] = - &PrintOutputProcessing; - IO::GetSingleton().functionMap[data.tname]["PrintInputProcessing"] = - &PrintInputProcessing; - IO::GetSingleton().functionMap[data.tname]["PrintSerializeUtil"] = - &PrintSerializeUtil; + IO::AddFunction(data.tname, "PrintDoc", &PrintDoc); + IO::AddFunction(data.tname, "PrintInputParam", &PrintInputParam); + IO::AddFunction(data.tname, "PrintOutputProcessing", + &PrintOutputProcessing); + IO::AddFunction(data.tname, "PrintInputProcessing", + &PrintInputProcessing); + IO::AddFunction(data.tname, "PrintSerializeUtil", &PrintSerializeUtil); - // Add the ParamData object, then store. This is necessary because we may - // import more than one .so or .o that uses IO, so we have to keep the - // options separate. programName is a global variable from mlpack_main.hpp. - IO::Add(std::move(data)); + // Add the ParamData object. if (identifier != "verbose") - IO::StoreSettings(IO::ProgramName()); - IO::ClearSettings(); + { + IO::AddParameter(bindingName, std::move(data)); + } + else + { + // This is a total hack! + // TODO: remove this when the macro solution in mlpack_main.hpp is fixed. + util::Params p = IO::Parameters(""); + if (p.Parameters().count("verbose") == 0) + IO::AddParameter("", std::move(data)); + } } }; diff --git a/src/mlpack/bindings/R/generate_R.cpp.in b/src/mlpack/bindings/R/generate_R.cpp.in index 632fe554bb..93c5db6b96 100644 --- a/src/mlpack/bindings/R/generate_R.cpp.in +++ b/src/mlpack/bindings/R/generate_R.cpp.in @@ -31,9 +31,8 @@ using namespace mlpack::util; int main(int /* argc */, char** /* argv */) { - // All the parameters are registered, but stored, so restore them. - // programName is defined in mlpack_main.hpp. - IO::RestoreSettings(IO::ProgramName()); + // All the parameters are registered; get a copy of them. + util::Params params = IO::Parameters(STRINGIFY(BINDING_NAME)); - PrintR(IO::GetSingleton().doc, "${NAME}"); + PrintR(params, "${NAME}", STRINGIFY(BINDING_NAME)); } diff --git a/src/mlpack/bindings/R/mlpack/R/matrix_utils.R b/src/mlpack/bindings/R/mlpack/R/matrix_utils.R index b6ae94b132..c2b6def269 100644 --- a/src/mlpack/bindings/R/mlpack/R/matrix_utils.R +++ b/src/mlpack/bindings/R/mlpack/R/matrix_utils.R @@ -38,13 +38,13 @@ mark_categorical_variable = function(x) { # Given some matrix-like x (which should be either a matrix or # data.frame), convert it into a matrix. to_matrix_with_info <- function(x) { - + # Handle transformation transformed_x <- to_matrix(x) # Figure out categoricals info <- mark_categorical_variable(x) - - # Return needed data. + + # Return needed data. return(list("info" = info, "data" = transformed_x)) } diff --git a/src/mlpack/bindings/R/mlpack/src/r_util.cpp b/src/mlpack/bindings/R/mlpack/src/r_util.cpp index 0da7e78bd1..a42eee50a3 100644 --- a/src/mlpack/bindings/R/mlpack/src/r_util.cpp +++ b/src/mlpack/bindings/R/mlpack/src/r_util.cpp @@ -30,271 +30,321 @@ bool inline inplace_transpose(arma::Mat& X) } } -// Call IO::RestoreSettings() for a given program name. +// Create a new util::Params object. // [[Rcpp::export]] -void IO_RestoreSettings(const std::string& programName) +SEXP CreateParams(const std::string& bindingName) { - IO::RestoreSettings(programName); + util::Params* p = new util::Params(IO::Parameters(bindingName)); + std::cout << "create params " << p << "\n"; + return std::move(Rcpp::XPtr(p)); } -// Call IO::SetParam(). +// Create a new util::Timers object. // [[Rcpp::export]] -void IO_SetParamInt(const std::string& paramName, int paramValue) +SEXP CreateTimers() { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Timers* t = new util::Timers(); + std::cout << "create timers " << t << "\n"; + return std::move(Rcpp::XPtr(t)); } -// Call IO::SetParam(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamDouble(const std::string& paramName, double paramValue) +void SetParamInt(SEXP params, const std::string& paramName, int paramValue) { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = paramValue; + p.SetPassed(paramName); } -// Call IO::SetParam(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamString(const std::string& paramName, std::string& paramValue) +void SetParamDouble(SEXP params, + const std::string& paramName, + double paramValue) { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = paramValue; + p.SetPassed(paramName); } -// Call IO::SetParam(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamBool(const std::string& paramName, bool paramValue) +void SetParamString(SEXP params, + const std::string& paramName, + std::string& paramValue) { - IO::GetParam(paramName) = paramValue; - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = paramValue; + p.SetPassed(paramName); } -// Call IO::SetParam>(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamVecString(const std::string& paramName, +void SetParamBool(SEXP params, const std::string& paramName, bool paramValue) +{ + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = paramValue; + p.SetPassed(paramName); +} + +// Call params.Get>() to set the value of a parameter. +// [[Rcpp::export]] +void SetParamVecString(SEXP params, + const std::string& paramName, const std::vector& str) { - IO::GetParam>(paramName) = std::move(str); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get>(paramName) = std::move(str); + p.SetPassed(paramName); } -// Call IO::SetParam>(). +// Call params.Get>() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamVecInt(const std::string& paramName, +void SetParamVecInt(SEXP params, + const std::string& paramName, const std::vector& ints) { - IO::GetParam>(paramName) = std::move(ints); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get>(paramName) = std::move(ints); + p.SetPassed(paramName); } -// Call IO::SetParam(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamMat(const std::string& paramName, +void SetParamMat(SEXP params, + const std::string& paramName, const arma::mat& paramValue) { - IO::GetParam(paramName) = paramValue.t(); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = paramValue.t(); + p.SetPassed(paramName); } -// Call IO::SetParam>(). +// Call params.Get>() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamUMat(const std::string& paramName, +void SetParamUMat(SEXP params, + const std::string& paramName, const arma::Mat& paramValue) { - IO::GetParam>(paramName) = paramValue.t(); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get>(paramName) = paramValue.t(); + p.SetPassed(paramName); } -// Call IO::SetParam(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamRow(const std::string& paramName, +void SetParamRow(SEXP params, + const std::string& paramName, const arma::rowvec& paramValue) { - IO::GetParam(paramName) = std::move(paramValue); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = std::move(paramValue); + p.SetPassed(paramName); } -// Call IO::SetParam>(). +// Call params.Get>() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamURow(const std::string& paramName, +void SetParamURow(SEXP params, + const std::string& paramName, const arma::Row& paramValue) { - IO::GetParam>(paramName) = paramValue - 1; - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get>(paramName) = paramValue - 1; + p.SetPassed(paramName); } -// Call IO::SetParam(). +// Call params.Get() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamCol(const std::string& paramName, +void SetParamCol(SEXP params, + const std::string& paramName, const arma::vec& paramValue) { - IO::GetParam(paramName) = std::move(paramValue); - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get(paramName) = std::move(paramValue); + p.SetPassed(paramName); } -// Call IO::SetParam>(). +// Call params.Get>() to set the value of a parameter. // [[Rcpp::export]] -void IO_SetParamUCol(const std::string& paramName, +void SetParamUCol(SEXP params, + const std::string& paramName, const arma::Col& paramValue) { - IO::GetParam>(paramName) = paramValue - 1; - IO::SetPassed(paramName); + util::Params& p = *Rcpp::as>(params); + p.Get>(paramName) = paramValue - 1; + p.SetPassed(paramName); } -// Call IO::SetParam>(). +// Call params.Get>() to set the value +// of a parameter. // [[Rcpp::export]] -void IO_SetParamMatWithInfo(const std::string& paramName, +void SetParamMatWithInfo(SEXP params, + const std::string& paramName, const LogicalVector& dimensions, const arma::mat& paramValue) { + util::Params& p = *Rcpp::as>(params); data::DatasetInfo d(paramValue.n_cols); for (size_t i = 0; i < d.Dimensionality(); ++i) { d.Type(i) = (dimensions[i]) ? data::Datatype::categorical : data::Datatype::numeric; } - std::get<0>(IO::GetParam>( + std::get<0>(p.Get>( paramName)) = std::move(d); - std::get<1>(IO::GetParam>( + std::get<1>(p.Get>( paramName)) = paramValue.t(); - IO::SetPassed(paramName); + p.SetPassed(paramName); } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -int IO_GetParamInt(const std::string& paramName) +int GetParamInt(SEXP params, const std::string& paramName) { - return IO::GetParam(paramName); + util::Params& p = *Rcpp::as>(params); + return p.Get(paramName); } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -double IO_GetParamDouble(const std::string& paramName) +double GetParamDouble(SEXP params, const std::string& paramName) { - return IO::GetParam(paramName); + util::Params& p = *Rcpp::as>(params); + return p.Get(paramName); } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -std::string& IO_GetParamString(const std::string& paramName) +std::string& GetParamString(SEXP params, const std::string& paramName) { - return IO::GetParam(paramName); + util::Params& p = *Rcpp::as>(params); + return p.Get(paramName); } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -bool IO_GetParamBool(const std::string& paramName) +bool GetParamBool(SEXP params, const std::string& paramName) { - return IO::GetParam(paramName); + util::Params& p = *Rcpp::as>(params); + return p.Get(paramName); } -// Call IO::GetParam>(). +// Call p.Get>(). // [[Rcpp::export]] -const std::vector& IO_GetParamVecString(const - std::string& paramName) +const std::vector& GetParamVecString( + SEXP params, + const std::string& paramName) { - return std::move(IO::GetParam>(paramName)); + util::Params& p = *Rcpp::as>(params); + return std::move(p.Get>(paramName)); } -// Call IO::GetParam>(). +// Call p.Get>(). // [[Rcpp::export]] -const std::vector& IO_GetParamVecInt(const std::string& paramName) +const std::vector& GetParamVecInt(SEXP params, + const std::string& paramName) { - return std::move(IO::GetParam>(paramName)); + util::Params& p = *Rcpp::as>(params); + return std::move(p.Get>(paramName)); } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -const arma::mat& IO_GetParamMat(const std::string& paramName) +const arma::mat& GetParamMat(SEXP params, const std::string& paramName) { - inplace_transpose(IO::GetParam(paramName)); - return std::move(IO::GetParam(paramName)); + util::Params& p = *Rcpp::as>(params); + inplace_transpose(p.Get(paramName)); + return std::move(p.Get(paramName)); } -// Call IO::GetParam>(). +// Call p.Get>(). // [[Rcpp::export]] -const arma::Mat& IO_GetParamUMat(const std::string& paramName) +const arma::Mat& GetParamUMat(SEXP params, + const std::string& paramName) { - inplace_transpose(IO::GetParam>(paramName)); - return std::move(IO::GetParam>(paramName)); + util::Params& p = *Rcpp::as>(params); + inplace_transpose(p.Get>(paramName)); + return std::move(p.Get>(paramName)); } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -const arma::vec IO_GetParamRow(const std::string& paramName) +const arma::vec GetParamRow(SEXP params, const std::string& paramName) { - return IO::GetParam(paramName).t(); + util::Params& p = *Rcpp::as>(params); + return p.Get(paramName).t(); } -// Call IO::GetParam>(). +// Call p.Get>(). // [[Rcpp::export]] -const arma::Col IO_GetParamURow(const std::string& paramName) +const arma::Col GetParamURow(SEXP params, + const std::string& paramName) { - return IO::GetParam>(paramName).t() + 1; + util::Params& p = *Rcpp::as>(params); + return p.Get>(paramName).t() + 1; } -// Call IO::GetParam(). +// Call p.Get(). // [[Rcpp::export]] -const arma::rowvec IO_GetParamCol(const std::string& paramName) +const arma::rowvec GetParamCol(SEXP params, const std::string& paramName) { - return IO::GetParam(paramName).t(); + util::Params& p = *Rcpp::as>(params); + return p.Get(paramName).t(); } -// Call IO::GetParam>(). +// Call p.Get>(). // [[Rcpp::export]] -const arma::Row IO_GetParamUCol(const std::string& paramName) +const arma::Row GetParamUCol(SEXP params, + const std::string& paramName) { - return IO::GetParam>(paramName).t() + 1; + util::Params& p = *Rcpp::as>(params); + return p.Get>(paramName).t() + 1; } -// Call IO::GetParam>(). +// Call p.Get>(). // [[Rcpp::export]] -List IO_GetParamMatWithInfo(const std::string& paramName) +List IO_GetParamMatWithInfo(SEXP params, const std::string& paramName) { + util::Params& p = *Rcpp::as>(params); const data::DatasetInfo& d = std::get<0>( - IO::GetParam>(paramName)); + p.Get>(paramName)); const arma::mat& m = std::get<1>( - IO::GetParam>(paramName)).t(); + p.Get>(paramName)).t(); LogicalVector dims(d.Dimensionality()); for (size_t i = 0; i < d.Dimensionality(); ++i) dims[i] = (d.Type(i) == data::Datatype::numeric) ? false : true; - return List::create (Rcpp::Named("Info") = std::move(dims), - Rcpp::Named("Data") = std::move(m)); + return List::create(Rcpp::Named("Info") = std::move(dims), + Rcpp::Named("Data") = std::move(m)); } // Enable verbose output. // [[Rcpp::export]] -void IO_EnableVerbose() +void EnableVerbose() { Log::Info.ignoreInput = false; } // Disable verbose output. // [[Rcpp::export]] -void IO_DisableVerbose() +void DisableVerbose() { Log::Info.ignoreInput = true; } // Reset the state of all timers. // [[Rcpp::export]] -void IO_ResetTimers() +void ResetTimers() { - IO::GetSingleton().timer.Reset(); + Timer::ResetAll(); } // Set an argument as passed to the IO object. // [[Rcpp::export]] -void IO_SetPassed(const std::string& paramName) +void SetPassed(SEXP params, const std::string& paramName) { - IO::SetPassed(paramName); -} - -// Clear settings. -// [[Rcpp::export]] -void IO_ClearSettings() -{ - IO::ClearSettings(); + util::Params& p = *Rcpp::as>(params); + p.SetPassed(paramName); } diff --git a/src/mlpack/bindings/R/print_R.cpp b/src/mlpack/bindings/R/print_R.cpp index 5b089cbd28..8f6e3ed8ab 100644 --- a/src/mlpack/bindings/R/print_R.cpp +++ b/src/mlpack/bindings/R/print_R.cpp @@ -21,20 +21,20 @@ namespace mlpack { namespace bindings { namespace r { - /** * Print the code for a .R binding for an mlpack program to stdout. * - * @param doc Documentation for the binding. + * @param params Instantiated Params object for this binding. * @param functionName Name of the function (i.e. "pca"). + * @param bindingName Name of the binding (as specified by BINDING_NAME). */ -void PrintR(const util::BindingDetails& doc, - const string& functionName) +void PrintR(util::Params& params, + const string& functionName, + const string& bindingName) { - // Restore parameters. - IO::RestoreSettings(doc.programName); + const util::BindingDetails& doc = params.Doc(); - map& parameters = IO::Parameters(); + map& parameters = params.Parameters(); typedef map::iterator ParamIter; // First, let's get a list of input and output options. We'll take two passes @@ -68,7 +68,7 @@ void PrintR(const util::BindingDetails& doc, // Print the documentation. // Print programName as @title. cout << "#' @title "; - cout << util::HyphenateString(doc.programName, "#' ") << endl; + cout << util::HyphenateString(doc.name, "#' ") << endl; cout << "#'" << endl; // Next print the short description as @description. @@ -85,7 +85,7 @@ void PrintR(const util::BindingDetails& doc, util::ParamData& d = parameters.at(opt); bool out = false; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &out); + params.functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &out); cout << endl; } @@ -101,7 +101,7 @@ void PrintR(const util::BindingDetails& doc, util::ParamData& d = parameters.at(opt); bool out = true; - IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &out); + params.functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &out); cout << endl; } @@ -162,36 +162,35 @@ void PrintR(const util::BindingDetails& doc, if (i != 0) cout << "," << endl << std::string(indent, ' '); - IO::GetSingleton().functionMap[d.tname]["PrintInputParam"](d, NULL, NULL); + params.functionMap[d.tname]["PrintInputParam"](d, NULL, NULL); } // Print closing brace for function definition. cout << ") {" << endl; - // Restore IO settings. - cout << " # Restore IO settings." << endl; - cout << " IO_RestoreSettings(\"" << IO::ProgramName() - << "\")" << endl; + // Create timers and parameters objects. + cout << " # Create parameters and timers objects." << endl; + cout << " p <- CreateParams(\"" << bindingName << "\")" << endl; + cout << " t <- CreateTimers()" << endl; cout << endl; - // Handle each input argument's processing before calling mlpackMain(). - cout << " # Process each input argument before calling mlpackMain()." + // Handle each input argument's processing before calling the binding. + cout << " # Process each input argument before calling the binding." << endl; for (const string& opt : inputOptions) { if (opt != "verbose") { util::ParamData& d = parameters.at(opt); - IO::GetSingleton().functionMap[d.tname]["PrintInputProcessing"](d, - NULL, NULL); + params.functionMap[d.tname]["PrintInputProcessing"](d, NULL, NULL); } } // Special handling for verbose output. cout << " if (verbose) {" << endl; - cout << " IO_EnableVerbose()" << endl; + cout << " EnableVerbose()" << endl; cout << " } else {" << endl; - cout << " IO_DisableVerbose()" << endl; + cout << " DisableVerbose()" << endl; cout << " }" << endl; cout << endl; @@ -200,13 +199,13 @@ void PrintR(const util::BindingDetails& doc, for (const string& opt : outputOptions) { util::ParamData& d = parameters.at(opt); - cout << " IO_SetPassed(\"" << d.name << "\")" << endl; + cout << " SetPassed(p, \"" << d.name << "\")" << endl; } cout << endl; // Call the program. cout << " # Call the program." << endl; - cout << " " << functionName << "_mlpackMain()" << endl << endl; + cout << " " << functionName << "_call(p, t)" << endl << endl; // Add ModelType as attr to the model pointer. cout << " # Add ModelType as attribute to the model pointer, if needed." @@ -214,8 +213,7 @@ void PrintR(const util::BindingDetails& doc, for (size_t i = 0; i < outputOptions.size(); ++i) { util::ParamData& d = parameters.at(outputOptions[i]); - IO::GetSingleton().functionMap[d.tname]["PrintSerializeUtil"](d, - NULL, NULL); + params.functionMap[d.tname]["PrintSerializeUtil"](d, NULL, NULL); } cout << endl; @@ -228,17 +226,13 @@ void PrintR(const util::BindingDetails& doc, if (i == 0) cout << indentStr; util::ParamData& d = parameters.at(outputOptions[i]); - IO::GetSingleton().functionMap[d.tname]["PrintOutputProcessing"](d, - NULL, NULL); + params.functionMap[d.tname]["PrintOutputProcessing"](d, NULL, NULL); // Print newlines if we are returning multiple output options. if (i + 1 < outputOptions.size()) cout << "," << endl << indentStr; } cout << endl << " )" << endl << endl; - // Clear the parameters. - cout << " # Clear the parameters." << endl; - cout << " IO_ClearSettings()" << endl; cout << endl; cout << " return(out)" << endl << "}" << endl; } diff --git a/src/mlpack/bindings/R/print_R.hpp b/src/mlpack/bindings/R/print_R.hpp index 76689420cd..a36ab7421d 100644 --- a/src/mlpack/bindings/R/print_R.hpp +++ b/src/mlpack/bindings/R/print_R.hpp @@ -21,11 +21,13 @@ namespace r { /** * Print the code for a .R binding for an mlpack program to stdout. * - * @param doc Documentation for the binding. + * @param params Instantiated Params object for this binding. * @param functionName Name of the function (i.e. "pca"). + * @param bindingName Name of the binding (as specified by BINDING_NAME). */ -void PrintR(const util::BindingDetails& doc, - const std::string& functionName); +void PrintR(util::Params& params, + const std::string& functionName, + const std::string& bindingName); } // namespace r } // namespace bindings diff --git a/src/mlpack/bindings/R/print_doc_functions.hpp b/src/mlpack/bindings/R/print_doc_functions.hpp index 27fafff169..bc67700136 100644 --- a/src/mlpack/bindings/R/print_doc_functions.hpp +++ b/src/mlpack/bindings/R/print_doc_functions.hpp @@ -54,29 +54,33 @@ inline std::string PrintValue(const bool& value, bool quotes); /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName); +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName); /** * Recursion base case. */ -inline std::string PrintInputOptions(); +inline std::string PrintInputOptions(util::Params& /* p */); /** * Print an input option. This will throw an exception if the parameter does * not exist in IO. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(util::Params& p, + const std::string& paramName, const T& value, Args... args); /** * Recursion base case. */ -inline std::string PrintOutputOptions(const bool /* markdown */); +inline std::string PrintOutputOptions(util::Params& /* p */, + const bool /* markdown */); template -std::string PrintOutputOptions(const bool markdown, +std::string PrintOutputOptions(util::Params& p, + const bool markdown, const std::string& paramName, const T& value, Args... args); diff --git a/src/mlpack/bindings/R/print_doc_functions_impl.hpp b/src/mlpack/bindings/R/print_doc_functions_impl.hpp index fab8904eec..0ddfb20d65 100644 --- a/src/mlpack/bindings/R/print_doc_functions_impl.hpp +++ b/src/mlpack/bindings/R/print_doc_functions_impl.hpp @@ -93,16 +93,17 @@ inline std::string PrintValue(const std::vector& value, bool quotes) /** * Given a parameter name, print its corresponding default value. */ -inline std::string PrintDefault(const std::string& paramName) +inline std::string PrintDefault(const std::string& bindingName, + const std::string& paramName) { - if (IO::Parameters().count(paramName) == 0) + util::Params p = IO::Parameters(bindingName); + if (p.Parameters().count(paramName) == 0) throw std::invalid_argument("unknown parameter " + paramName + "!"); - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; std::string defaultValue; - IO::GetSingleton().functionMap[d.tname]["DefaultParam"](d, NULL, - (void*) &defaultValue); + p.functionMap[d.tname]["DefaultParam"](d, NULL, (void*) &defaultValue); return defaultValue; } @@ -126,22 +127,23 @@ inline std::string PrintValue(const bool& value, bool quotes) /** * Recursion base case. */ -std::string PrintInputOptions() { return ""; } +std::string PrintInputOptions(util::Params& /* p */) { return ""; } /** * Print an input option. This will throw an exception if the parameter does * not exist in IO. */ template -std::string PrintInputOptions(const std::string& paramName, +std::string PrintInputOptions(util::Params& p, + const std::string& paramName, const T& value, Args... args) { // See if this is part of the program. std::string result = ""; - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; if (d.input) { // Print the input option. @@ -160,7 +162,7 @@ std::string PrintInputOptions(const std::string& paramName, } // Continue recursion. - std::string rest = PrintInputOptions(args...); + std::string rest = PrintInputOptions(p, args...); if (rest != "" && result != "") result += ", " + rest; else if (result == "") @@ -172,10 +174,15 @@ std::string PrintInputOptions(const std::string& paramName, /** * Recursion base case. */ -inline std::string PrintOutputOptions(const bool /* markdown */) { return ""; } +inline std::string PrintOutputOptions(util::Params& /* p */, + const bool /* markdown */) +{ + return ""; +} template -std::string PrintOutputOptions(const bool markdown, +std::string PrintOutputOptions(util::Params& p, + const bool markdown, const std::string& paramName, const T& value, Args... args) @@ -183,9 +190,9 @@ std::string PrintOutputOptions(const bool markdown, // See if this is part of the program. std::string result = ""; std::string command_prefix = "R> "; - if (IO::Parameters().count(paramName) > 0) + if (p.Parameters().count(paramName) > 0) { - util::ParamData& d = IO::Parameters()[paramName]; + util::ParamData& d = p.Parameters()[paramName]; if (!d.input) { // Print a new line for the output option. @@ -205,7 +212,7 @@ std::string PrintOutputOptions(const bool markdown, } // Continue recursion. - std::string rest = PrintOutputOptions(markdown, args...); + std::string rest = PrintOutputOptions(p, markdown, args...); if (rest != "" && result != "") result += "\n"; result += rest; @@ -223,26 +230,27 @@ std::string ProgramCall(const bool markdown, const std::string& programName, Args... args) { + util::Params p = IO::Parameters(programName); std::ostringstream oss; if (markdown) oss << "R> "; // Find out if we have any output options first. std::ostringstream ossOutput; - ossOutput << PrintOutputOptions(markdown, args...); + ossOutput << PrintOutputOptions(p, markdown, args...); if (ossOutput.str() != "") oss << "output <- "; oss << programName << "("; // Now process each input option. - oss << PrintInputOptions(args...); + oss << PrintInputOptions(p, args...); oss << ")"; std::string call = oss.str(); oss.str(""); // Reset it. // Now process each output option. - oss << PrintOutputOptions(markdown, args...); + oss << PrintOutputOptions(p, markdown, args...); if (markdown) { if (oss.str() == "") @@ -269,7 +277,8 @@ inline std::string ProgramCall(const std::string& programName) oss << command_prefix; // Determine if we have any output options. - std::map& parameters = IO::Parameters(); + util::Params p = IO::Parameters(programName); + std::map& parameters = p.Parameters(); bool hasOutput = false; for (auto it = parameters.begin(); it != parameters.end(); ++it) { @@ -301,8 +310,8 @@ inline std::string ProgramCall(const std::string& programName) oss << it->second.name << "="; std::string value; - IO::GetSingleton().functionMap[it->second.tname]["DefaultParam"]( - it->second, NULL, (void*) &value); + p.functionMap[it->second.tname]["DefaultParam"]( it->second, NULL, + (void*) &value); oss << value; } oss << ")"; @@ -373,16 +382,20 @@ inline std::string ParamString(const std::string& paramName, const T& value) return oss.str(); } -inline bool IgnoreCheck(const std::string& paramName) +inline bool IgnoreCheck(const std::string& bindingName, + const std::string& paramName) { - return !IO::Parameters()[paramName].input; + util::Params p = IO::Parameters(bindingName); + return !p.Parameters()[paramName].input; } -inline bool IgnoreCheck(const std::vector& constraints) +inline bool IgnoreCheck(const std::string& bindingName, + const std::vector& constraints) { + util::Params p = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i]].input) + if (!p.Parameters()[constraints[i]].input) return true; } @@ -390,16 +403,18 @@ inline bool IgnoreCheck(const std::vector& constraints) } inline bool IgnoreCheck( + const std::string& bindingName, const std::vector>& constraints, const std::string& paramName) { + util::Params p = IO::Parameters(bindingName); for (size_t i = 0; i < constraints.size(); ++i) { - if (!IO::Parameters()[constraints[i].first].input) + if (!p.Parameters()[constraints[i].first].input) return true; } - return !IO::Parameters()[paramName].input; + return !p.Parameters()[paramName].input; } } // namespace r diff --git a/src/mlpack/bindings/R/print_input_processing.hpp b/src/mlpack/bindings/R/print_input_processing.hpp index 4565a6d503..7c992b5e80 100644 --- a/src/mlpack/bindings/R/print_input_processing.hpp +++ b/src/mlpack/bindings/R/print_input_processing.hpp @@ -37,7 +37,7 @@ void PrintInputProcessing( * This gives us code like: * * if (!identical(, NA)) { - * IO_SetParam("", ) + * SetParam(p, "", ) * } */ MLPACK_COUT_STREAM << " if (!identical(" << d.name; @@ -49,7 +49,7 @@ void PrintInputProcessing( { MLPACK_COUT_STREAM << ", NA)) {" << std::endl; } - MLPACK_COUT_STREAM << " IO_SetParam" << GetType(d) << "(\"" + MLPACK_COUT_STREAM << " SetParam" << GetType(d) << "(p, \"" << d.name << "\", " << d.name << ")" << std::endl; MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace. } @@ -58,9 +58,9 @@ void PrintInputProcessing( /** * This gives us code like: * - * IO_SetParam("", ) + * SetParam(p, "", ) */ - MLPACK_COUT_STREAM << " IO_SetParam" << GetType(d) << "(\"" + MLPACK_COUT_STREAM << " SetParam" << GetType(d) << "(p, \"" << d.name << "\", " << d.name << ")" << std::endl; } MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit. @@ -80,12 +80,12 @@ void PrintInputProcessing( * This gives us code like: * * if (!identical(, NA)) { - * IO_SetParam("", to_matrix()) + * SetParam(p, "", to_matrix()) * } */ MLPACK_COUT_STREAM << " if (!identical(" << d.name << ", NA)) {" << std::endl; - MLPACK_COUT_STREAM << " IO_SetParam" << GetType(d) << "(\"" + MLPACK_COUT_STREAM << " SetParam" << GetType(d) << "(p, \"" << d.name << "\", to_matrix(" << d.name << "))" << std::endl; MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace. } @@ -94,9 +94,9 @@ void PrintInputProcessing( /** * This gives us code like: * - * IO_SetParam("", to_matrix()) + * SetParam(p, "", to_matrix()) */ - MLPACK_COUT_STREAM << " IO_SetParam" << GetType(d) << "(\"" + MLPACK_COUT_STREAM << " SetParam" << GetType(d) << "(p, \"" << d.name << "\", to_matrix(" << d.name << "))" << std::endl; } MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit. @@ -118,15 +118,15 @@ void PrintInputProcessing( * * if (!identical(, NA)) { * = to_matrix_with_info() - * IO_SetParam("", $info, - * $data) + * SetParam(p, "", $info, + * $data) * } */ MLPACK_COUT_STREAM << " if (!identical(" << d.name << ", NA)) {" << std::endl; MLPACK_COUT_STREAM << " " << d.name << " <- to_matrix_with_info(" << d.name << ")" << std::endl; - MLPACK_COUT_STREAM << " IO_SetParam" << GetType(d) << "(\"" + MLPACK_COUT_STREAM << " SetParam" << GetType(d) << "(p, \"" << d.name << "\", " << d.name << "$info, " << d.name << "$data)" << std::endl; MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace. @@ -137,12 +137,12 @@ void PrintInputProcessing( * This gives us code like: * * = to_matrix_with_info() - * IO_SetParam("", $info, - * $data) + * SetParam(p, "", $info, + * $data) */ MLPACK_COUT_STREAM << " " << d.name << " <- to_matrix_with_info(" << d.name << ")" << std::endl; - MLPACK_COUT_STREAM << " IO_SetParam" << GetType(d) << "(\"" + MLPACK_COUT_STREAM << " SetParam" << GetType(d) << "(p, \"" << d.name << "\", " << d.name << "$info, " << d.name << "$data)" << std::endl; } @@ -164,13 +164,13 @@ void PrintInputProcessing( * This gives us code like: * * if (!identical(, NA)) { - * IO_SetParamPtr("", ) + * SetParamPtr(p, "", ) * } */ MLPACK_COUT_STREAM << " if (!identical(" << d.name << ", NA)) {" << std::endl; - MLPACK_COUT_STREAM << " IO_SetParam" << util::StripType(d.cppType) - << "Ptr(\"" << d.name << "\", " << d.name << ")" << std::endl; + MLPACK_COUT_STREAM << " SetParam" << util::StripType(d.cppType) + << "Ptr(p, \"" << d.name << "\", " << d.name << ")" << std::endl; MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace. } else @@ -178,10 +178,10 @@ void PrintInputProcessing( /** * This gives us code like: * - * IO_SetParamPtr("", ) + * SetParamPtr(p, "", ) */ - MLPACK_COUT_STREAM << " IO_SetParam" << util::StripType(d.cppType) - << "Ptr(\"" << d.name << "\", " << d.name << ")" << std::endl; + MLPACK_COUT_STREAM << " SetParam" << util::StripType(d.cppType) + << "Ptr(p, \"" << d.name << "\", " << d.name << ")" << std::endl; } MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit. } diff --git a/src/mlpack/bindings/R/print_output_processing.hpp b/src/mlpack/bindings/R/print_output_processing.hpp index 3345f6e437..3a470856d4 100644 --- a/src/mlpack/bindings/R/print_output_processing.hpp +++ b/src/mlpack/bindings/R/print_output_processing.hpp @@ -34,12 +34,12 @@ void PrintOutputProcessing( /** * This gives us code like: * - * "" = IO_GetParam("param_name") + * "" = GetParam(p, "param_name") * */ - MLPACK_COUT_STREAM << " \"" << d.name << "\" = IO_GetParam" << GetType(d) - << "(\"" << d.name << "\")"; + MLPACK_COUT_STREAM << " \"" << d.name << "\" = GetParam" << GetType(d) + << "(p, \"" << d.name << "\")"; } /** @@ -55,12 +55,12 @@ void PrintOutputProcessing( /** * This gives us code like: * - * "" = IO_GetParam("param_name") + * "" = GetParam(p, "param_name") * */ - MLPACK_COUT_STREAM << " \"" << d.name << "\" = IO_GetParam" << GetType(d) - << "(\"" << d.name << "\")"; + MLPACK_COUT_STREAM << " \"" << d.name << "\" = GetParam" << GetType(d) + << "(p, \"" << d.name << "\")"; } /** @@ -75,12 +75,12 @@ void PrintOutputProcessing( /** * This gives us code like: * - * "" = IO_GetParam("param_name") + * "" = GetParam(p, "param_name") * */ - MLPACK_COUT_STREAM << " \"" << d.name << "\" = IO_GetParam" << GetType(d) - << "(\"" << d.name << "\")"; + MLPACK_COUT_STREAM << " \"" << d.name << "\" = GetParam" << GetType(d) + << "(p, \"" << d.name << "\")"; } /** diff --git a/src/mlpack/bindings/R/print_serialize_util.hpp b/src/mlpack/bindings/R/print_serialize_util.hpp index a899f2b8ed..da0fa372de 100644 --- a/src/mlpack/bindings/R/print_serialize_util.hpp +++ b/src/mlpack/bindings/R/print_serialize_util.hpp @@ -54,12 +54,12 @@ void PrintSerializeUtil( /** * This gives us code like: * - * <- IO_GetParamPtr("") + * <- GetParamPtr(p, "") * attr(, "type") <- "" * */ - MLPACK_COUT_STREAM << " " << d.name << " <- IO_GetParam" - << util::StripType(d.cppType) << "Ptr(\"" << d.name << "\")"; + MLPACK_COUT_STREAM << " " << d.name << " <- GetParam" + << util::StripType(d.cppType) << "Ptr(p, \"" << d.name << "\")"; MLPACK_COUT_STREAM << std::endl; MLPACK_COUT_STREAM << " attr(" << d.name << ", \"type\") <- \"" << util::StripType(d.cppType) << "\""; diff --git a/src/mlpack/bindings/R/r_method.cpp.in b/src/mlpack/bindings/R/r_method.cpp.in index b9612bce06..68e1928da9 100644 --- a/src/mlpack/bindings/R/r_method.cpp.in +++ b/src/mlpack/bindings/R/r_method.cpp.in @@ -12,9 +12,12 @@ #define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL) // [[Rcpp::export]] -void ${PROGRAM_NAME}_mlpackMain() +void ${PROGRAM_NAME}_call(SEXP params, SEXP timers) { - mlpackMain(); + util::Params& p = *Rcpp::as>(params); + util::Timers& t = *Rcpp::as>(timers); + + BINDING_FUNCTION(p, t); } // Any implementations of methods for dealing with model pointers will be put diff --git a/src/mlpack/bindings/R/tests/test_r_binding_main.cpp b/src/mlpack/bindings/R/tests/test_r_binding_main.cpp index 8bd78992b6..7e90328e95 100644 --- a/src/mlpack/bindings/R/tests/test_r_binding_main.cpp +++ b/src/mlpack/bindings/R/tests/test_r_binding_main.cpp @@ -11,6 +11,12 @@ */ #include #include + +#ifdef BINDING_NAME + #undef BINDING_NAME +#endif +#define BINDING_NAME test_R_binding + #include #include @@ -19,7 +25,7 @@ using namespace mlpack; using namespace mlpack::kernel; // Program Name. -BINDING_NAME("R binding test"); +BINDING_USER_NAME("R binding test"); // Short description. BINDING_SHORT_DESC( @@ -65,110 +71,110 @@ PARAM_MODEL_OUT(GaussianKernel, "model_out", "Output model, with twice the " "bandwidth.", ""); PARAM_DOUBLE_OUT("model_bw_out", "The bandwidth of the model."); -static void mlpackMain() +void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { - const string s = IO::GetParam("string_in"); - const int i = IO::GetParam("int_in"); - const double d = IO::GetParam("double_in"); + const string s = params.Get("string_in"); + const int i = params.Get("int_in"); + const double d = params.Get("double_in"); - IO::GetParam("string_out") = "wrong"; - IO::GetParam("int_out") = 11; - IO::GetParam("double_out") = 3.0; + params.Get("string_out") = "wrong"; + params.Get("int_out") = 11; + params.Get("double_out") = 3.0; // Check that everything is right on the input, and then set output // accordingly. - if (!IO::HasParam("flag2") && IO::HasParam("flag1")) + if (!params.Has("flag2") && params.Has("flag1")) { if (s == "hello") - IO::GetParam("string_out") = "hello2"; + params.Get("string_out") = "hello2"; if (i == 12) - IO::GetParam("int_out") = 13; + params.Get("int_out") = 13; if (d == 4.0) - IO::GetParam("double_out") = 5.0; + params.Get("double_out") = 5.0; } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("matrix_in")) + if (params.Has("matrix_in")) { - arma::mat out = move(IO::GetParam("matrix_in")); + arma::mat out = move(params.Get("matrix_in")); out.shed_row(4); out.row(2) *= 2.0; - IO::GetParam("matrix_out") = move(out); + params.Get("matrix_out") = move(out); } // Input matrices should be at least 5 rows; the 5th row will be dropped and // the 3rd row will be multiplied by two. - if (IO::HasParam("umatrix_in")) + if (params.Has("umatrix_in")) { arma::Mat out = - move(IO::GetParam>("umatrix_in")); + move(params.Get>("umatrix_in")); out.shed_row(4); out.row(2) *= 2; - IO::GetParam>("umatrix_out") = move(out); + params.Get>("umatrix_out") = move(out); } // An input column or row should have all elements multiplied by two. - if (IO::HasParam("col_in")) + if (params.Has("col_in")) { - arma::vec out = move(IO::GetParam("col_in")); + arma::vec out = move(params.Get("col_in")); out *= 2.0; - IO::GetParam("col_out") = move(out); + params.Get("col_out") = move(out); } - if (IO::HasParam("ucol_in")) + if (params.Has("ucol_in")) { arma::Col out = - move(IO::GetParam>("ucol_in")); + move(params.Get>("ucol_in")); out += 1; - IO::GetParam>("ucol_out") = move(out); + params.Get>("ucol_out") = move(out); } - if (IO::HasParam("row_in")) + if (params.Has("row_in")) { - arma::rowvec out = move(IO::GetParam("row_in")); + arma::rowvec out = move(params.Get("row_in")); out *= 2.0; - IO::GetParam("row_out") = move(out); + params.Get("row_out") = move(out); } - if (IO::HasParam("urow_in")) + if (params.Has("urow_in")) { arma::Row out = - move(IO::GetParam>("urow_in")); + move(params.Get>("urow_in")); out += 1; - IO::GetParam>("urow_out") = move(out); + params.Get>("urow_out") = move(out); } // Vector arguments should have the last element removed. - if (IO::HasParam("vector_in")) + if (params.Has("vector_in")) { - vector out = move(IO::GetParam>("vector_in")); + vector out = move(params.Get>("vector_in")); out.pop_back(); - IO::GetParam>("vector_out") = move(out); + params.Get>("vector_out") = move(out); } - if (IO::HasParam("str_vector_in")) + if (params.Has("str_vector_in")) { - vector out = move(IO::GetParam>("str_vector_in")); + vector out = move(params.Get>("str_vector_in")); out.pop_back(); - IO::GetParam>("str_vector_out") = move(out); + params.Get>("str_vector_out") = move(out); } // All numeric elements should be multiplied by 3. - if (IO::HasParam("matrix_and_info_in")) + if (params.Has("matrix_and_info_in")) { typedef tuple TupleType; - TupleType tuple = move(IO::GetParam("matrix_and_info_in")); + TupleType tuple = move(params.Get("matrix_and_info_in")); const data::DatasetInfo& di = std::get<0>(tuple); arma::mat& m = std::get<1>(tuple); @@ -179,19 +185,19 @@ static void mlpackMain() m.row(i) *= 2.0; } - IO::GetParam("matrix_and_info_out") = move(m); + params.Get("matrix_and_info_out") = move(m); } // If we got a request to build a model, then build it. - if (IO::HasParam("build_model")) + if (params.Has("build_model")) { - IO::GetParam("model_out") = new GaussianKernel(10.0); + params.Get("model_out") = new GaussianKernel(10.0); } // If we got an input model, double the bandwidth and output that. - if (IO::HasParam("model_in")) + if (params.Has("model_in")) { - IO::GetParam("model_bw_out") = - IO::GetParam("model_in")->Bandwidth() * 2.0; + params.Get("model_bw_out") = + params.Get("model_in")->Bandwidth() * 2.0; } } diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index bd690e1560..48a8f178b8 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -348,7 +348,8 @@ PARAM_FLAG("verbose", "Display informational messages and the full list of " #define PRINT_DATASET mlpack::bindings::r::PrintDataset #define PRINT_MODEL mlpack::bindings::r::PrintModel #define PRINT_CALL(...) mlpack::bindings::r::ProgramCall(false, __VA_ARGS__) -#define BINDING_IGNORE_CHECK mlpack::bindings::r::IgnoreCheck +#define BINDING_IGNORE_CHECK(...) mlpack::bindings::r::IgnoreCheck( \ + STRINGIFY(BINDING_NAME), __VA_ARGS__) namespace mlpack { namespace util { @@ -359,12 +360,14 @@ using Option = mlpack::bindings::r::ROption; } } -static const std::string testName = ""; #include PARAM_FLAG("verbose", "Display informational messages and the full list of " "parameters and timers at the end of execution.", "v"); +#undef BINDING_FUNCTION +#define BINDING_FUNCTION(...) JOIN(mlpack_, BINDING_NAME)(__VA_ARGS__) + // Nothing else needs to be defined---the binding will use mlpackMain() as-is. #elif BINDING_TYPE == BINDING_TYPE_MARKDOWN From 154768851a848d5ceb6927d96c7f37346ddaaa69 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:19:53 +0530 Subject: [PATCH 645/729] Update src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp Co-authored-by: Ryan Curtin --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index ef86cebf35..a5ede0ab93 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -90,7 +90,7 @@ class SSELoss OutputValue(const VecType& gradients, const VecType& hessians, const double lambda) { - return - arma::accu(gradients) / (arma::accu(hessians) + lambda); + return -arma::accu(gradients) / (arma::accu(hessians) + lambda); } /** From a1edb432b894526dac4530af45bdfb74a9f3fe45 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 06:57:21 +0530 Subject: [PATCH 646/729] Removed unnecessary SFINAE check --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index a5ede0ab93..7c6df621f4 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -58,10 +58,9 @@ class SSELoss /** * Returns the second order gradient of the loss function with respect to the - * values. This is used only for vectors. + * values. */ - template> + template VecType Hessians(const VecType& /* observed */, const VecType& values) { VecType h(values.n_elem, arma::fill::ones); From 6a187c41cd63b21dd952ff6cadc8080e7e445dcb Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 06:59:50 +0530 Subject: [PATCH 647/729] Add sanity check for empty vector --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 7c6df621f4..1ff28b75d2 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -35,6 +35,10 @@ class SSELoss template typename VecType::elem_type InitialPrediction(const VecType& values) { + // Sanity check for empty vector. + if (values.n_elem == 0) + return 0; + return arma::accu(values) / (typename VecType::elem_type) values.n_elem; } From a3769b67999b9016f60f6c4e3fcb987aae66a160 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:17:20 +0530 Subject: [PATCH 648/729] Add L1 and L2 parameter to SSELoss --- .../methods/xgboost/loss_functions/sse_loss.hpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 1ff28b75d2..b5f8765b8c 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -29,6 +29,12 @@ namespace ensemble { class SSELoss { public: + SSELoss(const double alpha, const double lambda): + alpha(alpha), lambda(lambda) + { + // Nothing to do. + } + /** * Returns the initial predition for gradient boosting. */ @@ -90,8 +96,7 @@ class SSELoss */ template typename VecType::elem_type - OutputValue(const VecType& gradients, const VecType& hessians, - const double lambda) + OutputValue(const VecType& gradients, const VecType& hessians) { return -arma::accu(gradients) / (arma::accu(hessians) + lambda); } @@ -101,7 +106,7 @@ class SSELoss */ template double SimilarityScore(const VecType& observed, const VecType& residuals, - const size_t begin, const size_t end, const double lambda) + const size_t begin, const size_t end) { VecType gradients = Gradients(observed.subvec(begin, end), residuals.subvec(begin, end)); @@ -111,6 +116,11 @@ class SSELoss return std::pow(arma::accu(gradients), 2) / (arma::accu(hessians) + lambda); } + private: + //! The L2 regularization parameter. + const double lambda; + //! The L1 regularization parameter. + const double alpha; }; } // namespace ensemble From 537e3ca44791c17cab30cfda6f1ee6ba6db9d34a Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:27:32 +0530 Subject: [PATCH 649/729] Add default ctor and fix one test --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 3 +++ src/mlpack/tests/xgboost_test.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index b5f8765b8c..62f27a66da 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -29,6 +29,9 @@ namespace ensemble { class SSELoss { public: + // Default constructor---No regularization. + SSELoss(): alpha(0), lambda(0) { /* Nothing to do. */} + SSELoss(const double alpha, const double lambda): alpha(alpha), lambda(lambda) { diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index 31f8754569..fa7ab0fff0 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -105,5 +105,5 @@ TEST_CASE("SSEOutputValueTest", "[XGBTest]") arma::vec hessians = Loss.Hessians(observed, predicted); // Lambda = 0; - REQUIRE(Loss.OutputValue(gradients, hessians, 0) == outputValue); + REQUIRE(Loss.OutputValue(gradients, hessians) == outputValue); } From 83cca54140750bcaef0274f0994f466c8fd5f3b8 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:47:14 +0530 Subject: [PATCH 650/729] Add L1 regularization --- .../xgboost/loss_functions/sse_loss.hpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 62f27a66da..fc4b9f3558 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -101,7 +101,7 @@ class SSELoss typename VecType::elem_type OutputValue(const VecType& gradients, const VecType& hessians) { - return -arma::accu(gradients) / (arma::accu(hessians) + lambda); + return -ApplyL1(arma::accu(gradients)) / (arma::accu(hessians) + lambda); } /** @@ -116,7 +116,7 @@ class SSELoss VecType hessians = Hessians(observed.subvec(begin, end), residuals.subvec(begin, end)); - return std::pow(arma::accu(gradients), 2) / + return std::pow(ApplyL1(arma::accu(gradients)), 2) / (arma::accu(hessians) + lambda); } private: @@ -124,6 +124,21 @@ class SSELoss const double lambda; //! The L1 regularization parameter. const double alpha; + + //! Applies the L1 regularization. + double ApplyL1(const double sumGradients) + { + if (sumGradients > alpha) + { + return sumGradients - alpha; + } + else if (sumGradients < - alpha) + { + return sumGradients + alpha; + } + + return 0; + } }; } // namespace ensemble From fade7e7c19d9175fbe4f25956ae7ce85d31eaf79 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 15 Jul 2021 10:25:38 +0530 Subject: [PATCH 651/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index c90d7b722b..f5f1154d35 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2197,8 +2197,8 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); expectedOutput.clear(); - expectedOutput << 103.7905 << 180.5134 << arma::endr - << 256.9865 << 333.7095 << arma::endr; + expectedOutput << 103.79045868 << 180.51335144 << arma::endr + << 256.98651123 << 333.70950317 << arma::endr; expectedOutput.reshape(4, 1); layer.Backward(output, output, unzoomedOutput); From ddad3f94d8b32c9880e35e3999a71e1dbd562f2b Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Thu, 15 Jul 2021 11:37:42 +0530 Subject: [PATCH 652/729] Update bicubic_interpolation_impl.hpp --- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 04e58d7dfa..6ba6443cd5 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -193,7 +193,7 @@ void BicubicInterpolation::Backward( GetKernalWeight(fr, weightR); GetKernalWeight(fc, weightC); - temp(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)) += weightR * weightC * gradientAsCube(i, j, k); + temp(arma::span(rEnd - 3, rEnd), arma::span(cEnd - 3, cEnd)) += gradientAsCube(i, j, k) * weightR * weightC; } } // Adding the contribution of the corner points to the output matrix. From 52caa2315c4af0ef02548dfacd73dd5a61dbc2d9 Mon Sep 17 00:00:00 2001 From: Abhinav-Aidash <85210822+Abhinav-Aidash@users.noreply.github.com> Date: Thu, 15 Jul 2021 19:32:37 +0530 Subject: [PATCH 653/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index f5f1154d35..4635f52912 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2194,6 +2194,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") << 31.0980 << 31.7431 << 34.1073 << 37.2050 << 40.3027 << 42.6669 << 43.3120 << arma::endr; expectedOutput.reshape(35, 1); layer.Forward(input, output); + output.raw_print(std::cout, "output:"); CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); expectedOutput.clear(); @@ -2202,7 +2203,8 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") expectedOutput.reshape(4, 1); layer.Backward(output, output, unzoomedOutput); - CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-4); + unzoomedOutput.raw_print(std::cout, "unzoomedOutput:"); + CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-2); } From a5fffe3c0bd629e95dd211678e28a6bbb9439ddd Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 22:07:00 +0530 Subject: [PATCH 654/729] OutputValue => OutputLeafValue --- .../methods/xgboost/loss_functions/sse_loss.hpp | 2 +- src/mlpack/tests/xgboost_test.cpp | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index fc4b9f3558..8b447371b3 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -99,7 +99,7 @@ class SSELoss */ template typename VecType::elem_type - OutputValue(const VecType& gradients, const VecType& hessians) + OutputLeafValue(const VecType& gradients, const VecType& hessians) { return -ApplyL1(arma::accu(gradients)) / (arma::accu(hessians) + lambda); } diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index fa7ab0fff0..6a147950fc 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -89,21 +89,20 @@ TEST_CASE("SSEResidualsTest", "[XGBTest]") } /** - * Test that output value is calculated correctly for SSE Loss. + * Test that output leaf value is calculated correctly for SSE Loss. */ -TEST_CASE("SSEOutputValueTest", "[XGBTest]") +TEST_CASE("SSELeafValueTest", "[XGBTest]") { arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; - // Actual outut value. - double outputValue = -0.075; + // Actual output leaf value. + double leafValue = -0.075; SSELoss Loss; - // Calculating gradients and hessians for input to OutputValue(). + // Calculating gradients and hessians for input to OutputLeafValue(). arma::vec gradients = Loss.Gradients(observed, predicted); arma::vec hessians = Loss.Hessians(observed, predicted); - // Lambda = 0; - REQUIRE(Loss.OutputValue(gradients, hessians) == outputValue); + REQUIRE(Loss.OutputLeafValue(gradients, hessians) == leafValue); } From 708eb5cfadf14e06bf7b1d2c3c168121b81225a7 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Thu, 15 Jul 2021 23:55:18 +0530 Subject: [PATCH 655/729] Change responses.subvec() to responses.cols(). --- .../decision_tree/decision_tree_regressor_impl.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index ba87d0a74d..029a5ff57c 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -623,7 +623,7 @@ double DecisionTreeRegressor( - responses.subvec(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = datasetInfo.Dimensionality(); // This means "no split". const size_t end = dimensionSelector.End(); @@ -639,7 +639,7 @@ double DecisionTreeRegressor(bestGain, data.cols(begin, begin + count - 1).row(i), datasetInfo.NumMappings(i), - responses.subvec(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, minimumGainSplit, @@ -651,7 +651,7 @@ double DecisionTreeRegressor(bestGain, data.cols(begin, begin + count - 1).row(i), - responses.subvec(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights, minimumLeafSize, minimumGainSplit, @@ -765,7 +765,7 @@ double DecisionTreeRegressor( - responses.subvec(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); } @@ -808,7 +808,7 @@ double DecisionTreeRegressor( - responses.subvec(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); size_t bestDim = data.n_rows; // This means "no split". @@ -920,7 +920,7 @@ double DecisionTreeRegressor( - responses.subvec(begin, begin + count - 1), + responses.cols(begin, begin + count - 1), UseWeights ? weights.subvec(begin, begin + count - 1) : weights); } From 8b34433e050fd6d70aa4f572566130fcb364e9a2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 16 Jul 2021 00:20:01 +0530 Subject: [PATCH 656/729] Add evaluate method to calculate gain before split --- .../xgboost/loss_functions/sse_loss.hpp | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 8b447371b3..eff0693951 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -97,9 +97,7 @@ class SSELoss /** * Returns the output value for the leaf in the tree. */ - template - typename VecType::elem_type - OutputLeafValue(const VecType& gradients, const VecType& hessians) + double OutputLeafValue() { return -ApplyL1(arma::accu(gradients)) / (arma::accu(hessians) + lambda); } @@ -119,11 +117,36 @@ class SSELoss return std::pow(ApplyL1(arma::accu(gradients)), 2) / (arma::accu(hessians) + lambda); } + + /** + * Calculates the gain of the node before splitting. It also initializes the + * gradients and hessians used later for finding split. + * UseWeights and weights are ignored here. These are just to make the API + * consistent. + * + * @param input This is a 2D matrix. The first row stores the true observed + * values and the second row stores the prediction at the current step + * of boosting. + */ + template + double Evaluate(const MatType& input, const WeightVecType& /* weights */) + { + // Calculate gradients and hessians. + gradients = input.row(1) - input.row(0); + hessians = arma::vec(input.n_cols, arma::fill::ones); + + return std::pow(ApplyL1(arma::accu(gradients)), 2) / + (arma::accu(hessians) + lambda); + } private: //! The L2 regularization parameter. const double lambda; //! The L1 regularization parameter. const double alpha; + //! First order gradients. + arma::vec gradients; + //! Second order gradients (hessians). + arma::vec hessians; //! Applies the L1 regularization. double ApplyL1(const double sumGradients) From d8de86b095d6af96e506ae3ee52dc1cd01430e63 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 16 Jul 2021 00:33:53 +0530 Subject: [PATCH 657/729] Remove unrequired functions --- .../xgboost/loss_functions/sse_loss.hpp | 56 +-------------- src/mlpack/tests/xgboost_test.cpp | 68 ++----------------- 2 files changed, 8 insertions(+), 116 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index eff0693951..4eba295a37 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -51,49 +51,6 @@ class SSELoss return arma::accu(values) / (typename VecType::elem_type) values.n_elem; } - /** - * Returns the first order gradient of the loss function with respect to the - * values. - * - * This is primarily used in calculating the residuals and split gain for the - * gradient boosted trees. - * - * @tparam T The type of input data. This can be both a vector or a scalar. - * @param observed The true observed values. - * @param values The values with respect to which the gradient will be - * calculated. - */ - template - T Gradients(const T& observed, const T& values) - { - return values - observed; - } - - /** - * Returns the second order gradient of the loss function with respect to the - * values. - */ - template - VecType Hessians(const VecType& /* observed */, const VecType& values) - { - VecType h(values.n_elem, arma::fill::ones); - return h; - } - - /** - * Returns the pseudo residuals of the predictions. - * This is equal to the negative gradient of the loss function with respect - * to the predicted values f. - * - * @param observed The true observed values. - * @param f The prediction at the current step of boosting. - */ - template - VecType Residuals(const VecType& observed, const VecType& f) - { - return observed - f; - } - /** * Returns the output value for the leaf in the tree. */ @@ -105,17 +62,10 @@ class SSELoss /** * Calculates the similarity score for evaluating the splits. */ - template - double SimilarityScore(const VecType& observed, const VecType& residuals, - const size_t begin, const size_t end) + double SimilarityScore(const size_t begin, const size_t end) { - VecType gradients = Gradients(observed.subvec(begin, end), - residuals.subvec(begin, end)); - VecType hessians = Hessians(observed.subvec(begin, end), - residuals.subvec(begin, end)); - - return std::pow(ApplyL1(arma::accu(gradients)), 2) / - (arma::accu(hessians) + lambda); + return std::pow(ApplyL1(arma::accu(gradients.subvec(begin, end))), 2) / + (arma::accu(hessians.subvec(begin, end)) + lambda); } /** diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index 6a147950fc..ed9b900b91 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -31,78 +31,20 @@ TEST_CASE("SSEInitialPredictionTest", "[XGBTest]") REQUIRE(Loss.InitialPrediction(values) == initPred); } -/** - * Test that gradients are calculated correctly for SSE Loss. - */ -TEST_CASE("SSEGradientsTest", "[XGBTest]") -{ - arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; - arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; - - // Actual gradients. - arma::vec gradients = {-0.5, -2, 0.5, -0.5, 0, 2, -1, -0.25, 1, 1.5}; - - SSELoss Loss; - // Calculated gradients. - arma::vec calculatedGradients = Loss.Gradients(observed, predicted); - - for (int i = 0; i < 10; i++) - REQUIRE(calculatedGradients[i] == gradients[i]); -} - -/** - * Test that hessians are calculated correctly for SSE Loss. - */ -TEST_CASE("SSEHessiansTest", "[XGBTest]") -{ - arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; - arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; - - // Actual hessians. - arma::vec hessians = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - - SSELoss Loss; - // Calculated hessians. - arma::vec calculatedHessians = Loss.Hessians(observed, predicted); - - for (int i = 0; i < 10; i++) - REQUIRE(calculatedHessians[i] == hessians[i]); -} - -/** - * Test that residuals are calculated correctly for SSE Loss. - */ -TEST_CASE("SSEResidualsTest", "[XGBTest]") -{ - arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; - arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; - - // Actual residuals. - arma::vec residuals = {0.5, 2, -0.5, 0.5, 0, -2, 1, 0.25, -1, -1.5}; - - SSELoss Loss; - // Calculated residuals. - arma::vec calculatedResiduals = Loss.Residuals(observed, predicted); - - for (int i = 0; i < 10; i++) - REQUIRE(calculatedResiduals[i] == residuals[i]); -} - /** * Test that output leaf value is calculated correctly for SSE Loss. */ TEST_CASE("SSELeafValueTest", "[XGBTest]") { - arma::vec observed = {1, 3, 2, 2, 5, 6, 9, 11, 8, 8}; - arma::vec predicted = {0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5}; + arma::mat input = { { 1, 3, 2, 2, 5, 6, 9, 11, 8, 8 }, + { 0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5 } }; + arma::vec weights; // dummy weights not used. // Actual output leaf value. double leafValue = -0.075; SSELoss Loss; - // Calculating gradients and hessians for input to OutputLeafValue(). - arma::vec gradients = Loss.Gradients(observed, predicted); - arma::vec hessians = Loss.Hessians(observed, predicted); + double gain = Loss.Evaluate(input, weights); - REQUIRE(Loss.OutputLeafValue(gradients, hessians) == leafValue); + REQUIRE(Loss.OutputLeafValue() == leafValue); } From fb8699af16a9375eea769b2521d05cf2e54491d3 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 16 Jul 2021 00:36:11 +0530 Subject: [PATCH 658/729] Add method to calculate gain for split --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index 4eba295a37..d2f0aa9785 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -60,9 +60,12 @@ class SSELoss } /** - * Calculates the similarity score for evaluating the splits. + * Calculates the gain from begin to end. + * + * @param begin The begin index to calculate gain. + * @param end The end index to calculate gain. */ - double SimilarityScore(const size_t begin, const size_t end) + double Evaluate(const size_t begin, const size_t end) { return std::pow(ApplyL1(arma::accu(gradients.subvec(begin, end))), 2) / (arma::accu(hessians.subvec(begin, end)) + lambda); From 1a7c16feb6e5bc3e5eba8249b1294a0fa161d921 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 16 Jul 2021 00:40:00 +0530 Subject: [PATCH 659/729] Updates signature of OutputLeafValue to make API consistent --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 4 +++- src/mlpack/tests/xgboost_test.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index d2f0aa9785..d777ade217 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -54,7 +54,9 @@ class SSELoss /** * Returns the output value for the leaf in the tree. */ - double OutputLeafValue() + template + double OutputLeafValue(const MatType& input, + const WeightVecType& /* weights */) { return -ApplyL1(arma::accu(gradients)) / (arma::accu(hessians) + lambda); } diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index ed9b900b91..f3904857ca 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -46,5 +46,5 @@ TEST_CASE("SSELeafValueTest", "[XGBTest]") SSELoss Loss; double gain = Loss.Evaluate(input, weights); - REQUIRE(Loss.OutputLeafValue() == leafValue); + REQUIRE(Loss.OutputLeafValue(input, weights) == leafValue); } From 905faca153474f54576005cac6589660ae22905b Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 15 Jul 2021 16:28:11 -0400 Subject: [PATCH 660/729] Hopefully some Julia fixes. --- src/mlpack/bindings/julia/julia_option.hpp | 14 +++++-- .../julia/print_input_processing_impl.hpp | 12 +++--- src/mlpack/bindings/julia/print_jl.cpp | 2 +- .../bindings/julia/print_param_defn.hpp | 39 +++++++++++-------- src/mlpack/core/util/mlpack_main.hpp | 15 +------ 5 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/mlpack/bindings/julia/julia_option.hpp b/src/mlpack/bindings/julia/julia_option.hpp index 54656c887b..ed2c45a7f5 100644 --- a/src/mlpack/bindings/julia/julia_option.hpp +++ b/src/mlpack/bindings/julia/julia_option.hpp @@ -87,10 +87,16 @@ class JuliaOption // This is needed for the Markdown binding output. IO::AddFunction(data.tname, "DefaultParam", &DefaultParam); - // Add the ParamData object, then store. This is necessary because we may - // import more than one .so that uses IO, so we have to keep the options - // separate. - IO::AddParameter(bindingName, std::move(data)); + // Add the ParamData object. + // TODO: fix this hack! + if (identifier != "verbose") + { + IO::AddParameter(bindingName, std::move(data)); + } + else + { + IO::AddParameter("", std::move(data)); + } } }; diff --git a/src/mlpack/bindings/julia/print_input_processing_impl.hpp b/src/mlpack/bindings/julia/print_input_processing_impl.hpp index 25c429353c..3c3d3319dc 100644 --- a/src/mlpack/bindings/julia/print_input_processing_impl.hpp +++ b/src/mlpack/bindings/julia/print_input_processing_impl.hpp @@ -35,7 +35,7 @@ void PrintInputProcessing( // "type" is a reserved keyword or function. const std::string juliaName = (d.name == "type") ? "type_" : d.name; - // Here we can just call IOSetParam() directly; we don't need a separate + // Here we can just call SetParam() directly; we don't need a separate // overload. if (d.required) { @@ -102,7 +102,7 @@ void PrintInputProcessing( extra = ", points_are_rows"; } - // Now print the IOSetParam call. + // Now print the SetParam call. std::cout << indent << "SetParam" << uChar << matTypeModifier << "(p, \"" << d.name << "\", " << juliaName << extra << ")" << std::endl; @@ -131,7 +131,7 @@ void PrintInputProcessing( // // if !ismissing() // push!(model_ptrs, convert(, ).ptr) - // IOSetParam("", convert(, )) + // SetParam("", convert(, )) // end // If the argument is not required, then we have to encase the code in an if. @@ -147,7 +147,7 @@ void PrintInputProcessing( std::cout << indent << "push!(modelPtrs, convert(" << GetJuliaType::type>(d) << ", " << juliaName << ").ptr)" << std::endl; - std::cout << indent << functionName << "_internal.IOSetParam" << type + std::cout << indent << functionName << "_internal.SetParam" << type << "(\"" << d.name << "\", convert(" << GetJuliaType::type>(d) << ", " << juliaName << "))" << std::endl; @@ -172,13 +172,13 @@ void PrintInputProcessing( // "type" is a reserved keyword or function. const std::string juliaName = (d.name == "type") ? "type_" : d.name; - // Here we can just call IOSetParam() directly; we don't need a separate + // Here we can just call SetParam() directly; we don't need a separate // overload. But we do have to pass in points_are_rows. if (d.required) { // This gives us code like the following: // - // IOSetParam(p, "", convert(, )) + // SetParam(p, "", convert(, )) std::cout << " SetParam(p, \"" << d.name << "\", convert(" << GetJuliaType(d) << ", " << juliaName << "), points_are_rows)" << std::endl; diff --git a/src/mlpack/bindings/julia/print_jl.cpp b/src/mlpack/bindings/julia/print_jl.cpp index 6fefcbe53e..7adaa5b981 100644 --- a/src/mlpack/bindings/julia/print_jl.cpp +++ b/src/mlpack/bindings/julia/print_jl.cpp @@ -253,7 +253,7 @@ void PrintJL(const string& bindingName, cout << endl; // Get an empty Params and Timers object. - cout << " p = IOGetParameters(\"" << bindingName << "\")" << endl; + cout << " p = GetParameters(\"" << bindingName << "\")" << endl; cout << " t = Timers()" << endl; cout << endl; diff --git a/src/mlpack/bindings/julia/print_param_defn.hpp b/src/mlpack/bindings/julia/print_param_defn.hpp index 6e5d152770..af5145b2f6 100644 --- a/src/mlpack/bindings/julia/print_param_defn.hpp +++ b/src/mlpack/bindings/julia/print_param_defn.hpp @@ -58,15 +58,19 @@ void PrintParamDefn( // // import ... // - // function IOGetParam(paramName::String, modelPtrs::Set{Ptr{Nothing}}) - // ptr = ccall((:IO_GetParamPtr, Library), - // Ptr{Nothing}, (Cstring,), paramName) + // function GetParam(params::Ptr{Nothing}, + // paramName::String, + // modelPtrs::Set{Ptr{Nothing}}) + // ptr = ccall((:GetParamPtr, Library), + // Ptr{Nothing}, (Ptr{Nothing}, Cstring,), params, paramName) // return (ptr; finalize=!(ptr in modelPtrs)) // end // - // function IOSetParam(paramName::String, model::) - // ccall((:IO_SetParamPtr, Library), Nothing, - // (Cstring, Ptr{Nothing}), paramName, model.ptr) + // function SetParam(params::Ptr{Nothing}, + // paramName::String, + // model::) + // ccall((:SetParamPtr, Library), Nothing, + // (Ptr{Nothing}, Cstring, Ptr{Nothing}), params, paramName, model.ptr) // end // // function Delete(ptr::Ptr{Nothing}) @@ -97,14 +101,15 @@ void PrintParamDefn( std::cout << "import ..." << type << std::endl; std::cout << std::endl; - // Now, IOGetParam(). + // Now, GetParam(). std::cout << "# Get the value of a model pointer parameter of type " << type << "." << std::endl; - std::cout << "function IOGetParam" << type << "(paramName::String, " - << "modelPtrs::Set{Ptr{Nothing}})::" << type << std::endl; - std::cout << " ptr = ccall((:IO_GetParam" << type - << "Ptr, " << programName << "Library), Ptr{Nothing}, (Cstring,), " - << "paramName)" << std::endl; + std::cout << "function GetParam" << type << "(params::Ptr{Nothing}, " + << "paramName::String, modelPtrs::Set{Ptr{Nothing}})::" << type + << std::endl; + std::cout << " ptr = ccall((:GetParam" << type + << "Ptr, " << programName << "Library), Ptr{Nothing}, (Ptr{Nothing}, " + << "Cstring,), params, paramName)" << std::endl; std::cout << " return " << type << "(ptr; finalize=!(ptr in modelPtrs))" << std::endl; std::cout << "end" << std::endl; @@ -113,11 +118,11 @@ void PrintParamDefn( // Next, IOSetParam(). std::cout << "# Set the value of a model pointer parameter of type " << type << "." << std::endl; - std::cout << "function IOSetParam" << type << "(paramName::String, " - << "model::" << type << ")" << std::endl; - std::cout << " ccall((:IO_SetParam" << type << "Ptr, " - << programName << "Library), Nothing, (Cstring, " - << "Ptr{Nothing}), paramName, model.ptr)" << std::endl; + std::cout << "function SetParam" << type << "(params::Ptr{Nothing}, " + << "paramName::String, model::" << type << ")" << std::endl; + std::cout << " ccall((:SetParam" << type << "Ptr, " + << programName << "Library), Nothing, (Ptr{Nothing}, Cstring, " + << "Ptr{Nothing}), params, paramName, model.ptr)" << std::endl; std::cout << "end" << std::endl; std::cout << std::endl; diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp index 48a8f178b8..e9342940f8 100644 --- a/src/mlpack/core/util/mlpack_main.hpp +++ b/src/mlpack/core/util/mlpack_main.hpp @@ -277,23 +277,10 @@ using Option = mlpack::bindings::julia::JuliaOption; #include -#ifdef BINDING_NAME - #define OLD_BINDING_NAME BINDING_NAME -#undef BINDING_NAME -#endif -#define BINDING_NAME - +// TODO: fix so that this is a part of the "" binding name PARAM_FLAG("verbose", "Display informational messages and the full list of " "parameters and timers at the end of execution.", "v"); -#ifdef OLD_BINDING_NAME - #undef BINDING_NAME - #define BINDING_NAME OLD_BINDING_NAME - #undef OLD_BINDING_NAME -#else - #undef BINDING_NAME -#endif - // Nothing else needs to be defined---the binding will use mlpackMain() as-is. #elif(BINDING_TYPE == BINDING_TYPE_GO) // This is a Go binding. From 76d685cd2e19705d4b44d8a455fdfdddf9799ef2 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 16 Jul 2021 09:17:57 +0530 Subject: [PATCH 661/729] Fix static analysis error --- src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp | 2 +- src/mlpack/tests/xgboost_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp index d777ade217..d4ffe22c3c 100644 --- a/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp +++ b/src/mlpack/methods/xgboost/loss_functions/sse_loss.hpp @@ -55,7 +55,7 @@ class SSELoss * Returns the output value for the leaf in the tree. */ template - double OutputLeafValue(const MatType& input, + double OutputLeafValue(const MatType& /* input */, const WeightVecType& /* weights */) { return -ApplyL1(arma::accu(gradients)) / (arma::accu(hessians) + lambda); diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index f3904857ca..40c3fdfe11 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -44,7 +44,7 @@ TEST_CASE("SSELeafValueTest", "[XGBTest]") double leafValue = -0.075; SSELoss Loss; - double gain = Loss.Evaluate(input, weights); + double = Loss.Evaluate(input, weights); REQUIRE(Loss.OutputLeafValue(input, weights) == leafValue); } From 5d68b3481baace687859fe8a7e4025e5eaa5f812 Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 16 Jul 2021 09:24:54 +0530 Subject: [PATCH 662/729] Add test for gain computation --- src/mlpack/tests/xgboost_test.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/xgboost_test.cpp b/src/mlpack/tests/xgboost_test.cpp index 40c3fdfe11..7145e34f7e 100644 --- a/src/mlpack/tests/xgboost_test.cpp +++ b/src/mlpack/tests/xgboost_test.cpp @@ -44,7 +44,23 @@ TEST_CASE("SSELeafValueTest", "[XGBTest]") double leafValue = -0.075; SSELoss Loss; - double = Loss.Evaluate(input, weights); + (void) Loss.Evaluate(input, weights); REQUIRE(Loss.OutputLeafValue(input, weights) == leafValue); } + +/** + * Test that the gain is computed correctly for SSE Loss. + */ +TEST_CASE("SSEGainTest", "[XGBTest]") +{ + arma::mat input = { { 1, 3, 2, 2, 5, 6, 9, 11, 8, 8 }, + { 0.5, 1, 2.5, 1.5, 5, 8, 8, 10.75, 9, 9.5 } }; + arma::vec weights; // dummy weights not used. + + // Actual gain value. + double gain = 0.05625; + + SSELoss Loss; + REQUIRE(Loss.Evaluate(input, weights) == gain); +} From 029b9052b147aead541bdd469504722b6d232827 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Fri, 16 Jul 2021 10:53:55 +0530 Subject: [PATCH 663/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 4635f52912..4c18f8e747 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2187,24 +2187,24 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") input.reshape(4, 1); BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth); - expectedOutput << 6.6880 << 7.3331 << 9.6973 << 12.7950 << 15.8927 << 18.2569 << 18.9020 << arma::endr - << 10.5330 << 11.1781 << 13.5423 << 16.6400 << 19.7377 << 22.1019 << 22.7470 << arma::endr - << 18.8930 << 19.5381 << 21.9023 << 25.0000 << 28.0977 << 30.4619 << 31.1070 << arma::endr - << 27.2530 << 27.8981 << 30.2623 << 33.3600 << 36.4577 << 38.8219 << 39.4670 << arma::endr - << 31.0980 << 31.7431 << 34.1073 << 37.2050 << 40.3027 << 42.6669 << 43.3120 << arma::endr; + expectedOutput << 6.6880435944 << 7.3330874443 << 9.6973438263 << 12.7950067520 << 15.8926725388 << 18.2569236755 << 18.9019603729 << arma::endr + << 10.5330419540 << 11.1780862808 << 13.5423421860 << 16.6400032043 << 19.7376689911 << 22.1019191742 << 22.7469558716 << arma::endr + << 18.8930358887 << 19.5380821228 << 21.9023399353 << 25.0000000000 << 28.0976638794 << 30.4619140625 << 31.1069507599 << arma::endr + << 27.2530345917 << 27.8980865479 << 30.2623443604 << 33.3600006104 << 36.4576644897 << 38.8219146729 << 39.4669494629 << arma::endr + << 31.0980434418 << 31.7430934906 << 34.1073532104 << 37.2050094604 << 40.3026695251 << 42.6669273376 << 43.3119621277 << arma::endr; expectedOutput.reshape(35, 1); layer.Forward(input, output); - output.raw_print(std::cout, "output:"); + CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); expectedOutput.clear(); - expectedOutput << 103.79045868 << 180.51335144 << arma::endr - << 256.98651123 << 333.70950317 << arma::endr; + expectedOutput << 103.7904586792 << 180.5133514404 << arma::endr + << 256.9865112305 << 333.7095031738 << arma::endr; expectedOutput.reshape(4, 1); layer.Backward(output, output, unzoomedOutput); - unzoomedOutput.raw_print(std::cout, "unzoomedOutput:"); - CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-2); + + CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-4); } From caa405333d93b0bf39f977f3be514ae0ffc89d6a Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sat, 17 Jul 2021 00:07:28 +0530 Subject: [PATCH 664/729] Added nearest interpolation upsampling --- src/mlpack/methods/ann/layer/CMakeLists.txt | 2 + src/mlpack/methods/ann/layer/layer.hpp | 1 + src/mlpack/methods/ann/layer/layer_types.hpp | 2 + .../ann/layer/nearest_interpolation.hpp | 153 +++++++++++++++++ .../ann/layer/nearest_interpolation_impl.hpp | 162 ++++++++++++++++++ src/mlpack/tests/ann_layer_test.cpp | 52 ++++++ 6 files changed, 372 insertions(+) create mode 100644 src/mlpack/methods/ann/layer/nearest_interpolation.hpp create mode 100644 src/mlpack/methods/ann/layer/nearest_interpolation_impl.hpp diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index e5d21d215a..f9f4498f2f 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -85,6 +85,8 @@ set(SOURCES multiply_constant_impl.hpp multiply_merge.hpp multiply_merge_impl.hpp + nearest_interpolation.hpp + nearest_interpolation_impl.hpp noisylinear.hpp noisylinear_impl.hpp parametric_relu.hpp diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index abc246f7f4..ef82085d76 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -56,6 +56,7 @@ #include "multihead_attention.hpp" #include "multiply_constant.hpp" #include "multiply_merge.hpp" +#include "nearest_interpolation.hpp" #include "noisylinear.hpp" #include "padding.hpp" #include "parametric_relu.hpp" diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index 4a5a202e67..8ebbbabdc2 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -246,6 +247,7 @@ using MoreTypes = boost::variant< BaseLayer*, PositionalEncoding*, ISRLU* + NearestInterpolation* >; template diff --git a/src/mlpack/methods/ann/layer/nearest_interpolation.hpp b/src/mlpack/methods/ann/layer/nearest_interpolation.hpp new file mode 100644 index 0000000000..c2d6a407cc --- /dev/null +++ b/src/mlpack/methods/ann/layer/nearest_interpolation.hpp @@ -0,0 +1,153 @@ +/** + * @file methods/ann/layer/nearest_interpolation.hpp + * @author Abhinav Anand + * + * 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_NEAREST_INTERPOLATION_HPP +#define MLPACK_METHODS_ANN_LAYER_NEAREST_INTERPOLATION_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Definition and Implementation of the Nearest Interpoltion Layer. + * + * Nearest Interpoltion is an mathematical technique, primarily used for + * scaling purposes. The input should be a 2D matrix and it can have + * a number of channels/units. + * + * @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 NearestInterpolation +{ + public: + //! Create the NearestInterpolation object. + NearestInterpolation(); + + /** + * The constructor for the NearestInterpolation. + * + * @param inRowSize Number of input rows. + * @param inColSize Number of input columns. + * @param outRowSize Number of output rows. + * @param outColSize Number of output columns. + * @param depth Number of input slices. + */ + NearestInterpolation(const size_t inRowSize, + const size_t inColSize, + const size_t outRowSize, + const size_t outColSize, + const size_t depth); + + /** + * Forward pass through the layer. The layer interpolates + * the matrix using the given Nearest Interpolation method. + * + * @param input The input matrix. + * @param output The resulting interpolated output matrix. + */ + template + void Forward(const arma::Mat& input, arma::Mat& 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. Since the layer does not have any learn-able parameters, + * we just have to down-sample the gradient to make its size compatible with + * the input size. + * + * @param * (input) The input matrix. + * @param gradient The computed backward gradient. + * @param output The resulting down-sampled output. + */ + template + void Backward(const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output); + + //! Get the output parameter. + OutputDataType const& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const& Delta() const { return delta; } + //! Modify the delta. + OutputDataType& Delta() { return delta; } + + //! Get the row size of the input. + size_t const& InRowSize() const { return inRowSize; } + //! Modify the row size of the input. + size_t& InRowSize() { return inRowSize; } + + //! Get the column size of the input. + size_t const& InColSize() const { return inColSize; } + //! Modify the column size of the input. + size_t& InColSize() { return inColSize; } + + //! Get the row size of the output. + size_t const& OutRowSize() const { return outRowSize; } + //! Modify the row size of the output. + size_t& OutRowSize() { return outRowSize; } + + //! Get the column size of the output. + size_t const& OutColSize() const { return outColSize; } + //! Modify the column size of the output. + size_t& OutColSize() { return outColSize; } + + //! Get the depth of the input. + size_t const& InDepth() const { return depth; } + //! Modify the depth of the input. + size_t& InDepth() { return depth; } + + //! Get the shape of the input. + size_t InputShape() const + { + return inRowSize; + } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& ar, const uint32_t /* version */); + + private: + //! Locally stored row size of the input. + size_t inRowSize; + //! Locally stored column size of the input. + size_t inColSize; + //! Locally stored row size of the output. + size_t outRowSize; + //! Locally stored column size of the input. + size_t outColSize; + //! Locally stored depth of the input. + size_t depth; + //! Locally stored number of input points. + size_t batchSize; + //! Locally-stored delta object. + OutputDataType delta; + //! Locally-stored output parameter object. + OutputDataType outputParameter; +}; // class NearestInterpolation + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "nearest_interpolation_impl.hpp" + +#endif \ No newline at end of file diff --git a/src/mlpack/methods/ann/layer/nearest_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/nearest_interpolation_impl.hpp new file mode 100644 index 0000000000..6838c47847 --- /dev/null +++ b/src/mlpack/methods/ann/layer/nearest_interpolation_impl.hpp @@ -0,0 +1,162 @@ +/** + * @file methods/ann/layer/nearest_interpolation_impl.hpp + * @author Abhinav Anand + * + * Implementation of the NearestInterpolation layer. + * + * 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_NEAREST_INTERPOLATION_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_NEAREST_INTERPOLATION_IMPL_HPP + +// In case it hasn't yet been included. +#include "nearest_interpolation.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + + +template +NearestInterpolation:: + NearestInterpolation(): + inRowSize(0), + inColSize(0), + outRowSize(0), + outColSize(0), + depth(0), + batchSize(0) + { + // Nothing to do here. + } + +template +NearestInterpolation:: + NearestInterpolation( + const size_t inRowSize, + const size_t inColSize, + const size_t outRowSize, + const size_t outColSize, + const size_t depth): + inRowSize(inRowSize), + inColSize(inColSize), + outRowSize(outRowSize), + outColSize(outColSize), + depth(depth), + batchSize(0) + { + // Nothing to do here. + } + +template +template +void NearestInterpolation::Forward( + const arma::Mat& input, arma::Mat& output) + { + batchSize = input.n_cols; + if (output.is_empty()) + output.set_size(outRowSize * outColSize * depth, batchSize); + else + { + assert(output.n_rows == outRowSize * outColSize * depth); + assert(output.n_cols == batchSize); + } + + assert(inRowSize >= 2); + assert(inColSize >= 2); + + arma::cube inputAsCube(const_cast&>(input).memptr(), + inRowSize, inColSize, depth * batchSize, false, false); + arma::cube outputAsCube(output.memptr(), outRowSize, outColSize, + depth * batchSize, false, true); + + double scaleRow = (double) inRowSize / (double) outRowSize; + double scaleCol = (double) inColSize / (double) outColSize; + + for (size_t i = 0; i < outRowSize; ++i) + { + const size_t rOrigin = std::floor(i * scaleRow); + + for (size_t j = 0; j < outColSize; ++j) + { + const size_t cOrigin = std::floor(j * scaleCol); + + for (size_t k = 0; k < depth * batchSize; ++k) + { + outputAsCube(i, j, k) = inputAsCube.slice(k)( + rOrigin, cOrigin); + } + } + } + } + +template +template +void NearestInterpolation::Backward( + const arma::Mat& /*input*/, + const arma::Mat& gradient, + arma::Mat& output) + { + if (output.is_empty()) + { + output.set_size(inRowSize * inColSize * depth, batchSize); + } + else + { + assert(output.n_rows == inRowSize * inColSize * depth); + assert(output.n_cols == batchSize); + } + + assert(outRowSize >= 2); + assert(outColSize >= 2); + + arma::cube outputAsCube(output.memptr(), inRowSize, inColSize, + depth * batchSize, false, true); + arma::cube gradientAsCube(((arma::Mat&) gradient).memptr(), outRowSize, + outColSize, depth * batchSize, false, false); + + double scaleRow = (double)(inRowSize) / outRowSize; + double scaleCol = (double)(inColSize) / outColSize; + + if (gradient.n_elem == output.n_elem) + { + outputAsCube = gradientAsCube; + } + else + { + for (size_t i = 0; i < outRowSize; ++i) + { + const size_t rOrigin = std::floor(i * scaleRow); + + for (size_t j = 0; j < outColSize; ++j) + { + const size_t cOrigin = std::floor(j* scaleCol); + + for (size_t k = 0; k < depth * batchSize; ++k) + { + outputAsCube(rOrigin, cOrigin, k) += + gradientAsCube(i, j, k); + } + } + } + } + } + +template +template +void NearestInterpolation::serialize( + Archive& ar, const uint32_t /* version */) + { + ar(CEREAL_NVP(inRowSize)); + ar(CEREAL_NVP(inColSize)); + ar(CEREAL_NVP(outRowSize)); + ar(CEREAL_NVP(outColSize)); + ar(CEREAL_NVP(depth)); + } + +} // namespace ann +} // namespace mlpack + +#endif \ No newline at end of file diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index cbc01b35a8..8104f1d36a 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2102,6 +2102,58 @@ TEST_CASE("GradientSoftmaxTest", "[ANNLayerTest]") REQUIRE(CheckGradient(function) <= 1e-4); } +/* + * Simple test for the NearestInterpolation layer + */ +TEST_CASE("SimpleNearestInterpolationLayerTest", "[ANNLayerTest]") +{ + // Tested output against torch.nn.Upsample(mode="nearest") + arma::mat input, output, unzoomedOutput, expectedOutput; + size_t inRowSize = 2; + size_t inColSize = 2; + size_t outRowSize = 5; + size_t outColSize = 7; + size_t depth = 1; + input.zeros(inRowSize * inColSize * depth, 1); + input[0] = 1.0; + input[1] = 3.0; + input[2] = 2.0; + input[3] = 4.0; + NearestInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, + depth); + expectedOutput << 1.0000 << 1.0000 << 1.0000 << 1.0000 << 2.0000 << 2.0000 << 2.0000 << arma::endr + << 1.0000 << 1.0000 << 1.0000 << 1.0000 << 2.0000 << 2.0000 << 2.0000 << arma::endr + << 1.0000 << 1.0000 << 1.0000 << 1.0000 << 2.0000 << 2.0000 << 2.0000 << arma::endr + << 3.0000 << 3.0000 << 3.0000 << 3.0000 << 4.0000 << 4.0000 << 4.0000 << arma::endr + << 3.0000 << 3.0000 << 3.0000 << 3.0000 << 4.0000 << 4.0000 << 4.0000 << arma::endr; + expectedOutput.reshape(35, 1); + layer.Forward(input, output); + CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); + + expectedOutput.clear(); + expectedOutput << 12.0000 << 18.0000 << arma::endr + << 24.0000 << 24.0000 << arma::endr; + expectedOutput.reshape(4, 1); + layer.Backward(output, output, unzoomedOutput); + CheckMatrices(unzoomedOutput - expectedOutput, + arma::zeros(input.n_rows), 1e-4); + + arma::mat input1, output1, unzoomedOutput1, expectedOutput1; + inRowSize = 2; + inColSize = 3; + outRowSize = 17; + outColSize = 23; + input1 << 1 << 2 << 3 << arma::endr + << 4 << 5 << 6 << arma::endr; + input1.reshape(6, 1); + NearestInterpolation<> layer1(inRowSize, inColSize, outRowSize, outColSize, + depth); + layer1.Forward(input1, output1); + layer1.Backward(output1, output1, unzoomedOutput1); + REQUIRE(arma::accu(output1) - 1317.00 == Approx(0.0).margin(1e-05)); + REQUIRE(arma::accu(unzoomedOutput1) - 1317.00 == Approx(0.0).margin(1e-05)); +} + /* * Simple test for the BilinearInterpolation layer */ From 0a4377af6c52cdc4f64886708722760b05b9f3ef Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sat, 17 Jul 2021 00:14:58 +0530 Subject: [PATCH 665/729] Update src/mlpack/tests/ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 8104f1d36a..2998bff314 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2121,12 +2121,14 @@ TEST_CASE("SimpleNearestInterpolationLayerTest", "[ANNLayerTest]") input[3] = 4.0; NearestInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth); + expectedOutput << 1.0000 << 1.0000 << 1.0000 << 1.0000 << 2.0000 << 2.0000 << 2.0000 << arma::endr << 1.0000 << 1.0000 << 1.0000 << 1.0000 << 2.0000 << 2.0000 << 2.0000 << arma::endr << 1.0000 << 1.0000 << 1.0000 << 1.0000 << 2.0000 << 2.0000 << 2.0000 << arma::endr << 3.0000 << 3.0000 << 3.0000 << 3.0000 << 4.0000 << 4.0000 << 4.0000 << arma::endr << 3.0000 << 3.0000 << 3.0000 << 3.0000 << 4.0000 << 4.0000 << 4.0000 << arma::endr; expectedOutput.reshape(35, 1); + layer.Forward(input, output); CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); From 4bdace1303a7b286a8a97fcdef8c707db0bee175 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sat, 17 Jul 2021 00:29:04 +0530 Subject: [PATCH 666/729] Fixed test case --- src/mlpack/tests/ann_layer_test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 4c18f8e747..b1bf9c3555 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2187,24 +2187,24 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") input.reshape(4, 1); BicubicInterpolation<> layer(inRowSize, inColSize, outRowSize, outColSize, depth); - expectedOutput << 6.6880435944 << 7.3330874443 << 9.6973438263 << 12.7950067520 << 15.8926725388 << 18.2569236755 << 18.9019603729 << arma::endr - << 10.5330419540 << 11.1780862808 << 13.5423421860 << 16.6400032043 << 19.7376689911 << 22.1019191742 << 22.7469558716 << arma::endr - << 18.8930358887 << 19.5380821228 << 21.9023399353 << 25.0000000000 << 28.0976638794 << 30.4619140625 << 31.1069507599 << arma::endr - << 27.2530345917 << 27.8980865479 << 30.2623443604 << 33.3600006104 << 36.4576644897 << 38.8219146729 << 39.4669494629 << arma::endr - << 31.0980434418 << 31.7430934906 << 34.1073532104 << 37.2050094604 << 40.3026695251 << 42.6669273376 << 43.3119621277 << arma::endr; + expectedOutput << 6.68803935860 << 7.33308309038 << 9.69733236152 << 12.79500000000 << 15.89266763848 << 18.25691690962 << 18.90196064140 << arma::endr + << 10.53303935860 << 11.17808309038 << 13.54233236152 << 16.64000000000 << 19.73766763848 << 22.10191690962 << 22.74696064140 << arma::endr + << 18.89303935860 << 19.53808309038 << 21.90233236152 << 25.00000000000 << 28.09766763848 << 30.46191690962 << 31.10696064140 << arma::endr + << 27.25303935860 << 27.89808309038 << 30.26233236152 << 33.36000000000 << 36.45766763848 << 38.82191690962 << 39.46696064140 << arma::endr + << 31.09803935860 << 31.74308309038 << 34.10733236152 << 37.20500000000 << 40.30266763848 << 42.66691690962 << 43.31196064140 << arma::endr; expectedOutput.reshape(35, 1); layer.Forward(input, output); - CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-4); + CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-6); expectedOutput.clear(); - expectedOutput << 103.7904586792 << 180.5133514404 << arma::endr - << 256.9865112305 << 333.7095031738 << arma::endr; + expectedOutput << 103.79040654914 << 180.51345595086 << arma::endr + << 256.98654404914 << 333.70959345086 << arma::endr; expectedOutput.reshape(4, 1); layer.Backward(output, output, unzoomedOutput); - CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-4); + CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-6); } From df2fc410ce4e635b9c23b2b1133e02761719a167 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sat, 17 Jul 2021 01:00:26 +0530 Subject: [PATCH 667/729] Update layer_types.hpp --- src/mlpack/methods/ann/layer/layer_types.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index 8ebbbabdc2..794edf079d 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -246,7 +246,7 @@ using MoreTypes = boost::variant< RBF*, BaseLayer*, PositionalEncoding*, - ISRLU* + ISRLU*, NearestInterpolation* >; From a392a5bbe614fc9d88c49cc4bd060172c60093b7 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Sat, 17 Jul 2021 01:40:32 +0530 Subject: [PATCH 668/729] Update ann_layer_test.cpp --- src/mlpack/tests/ann_layer_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index b1bf9c3555..5d4077cf73 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -2195,7 +2195,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") expectedOutput.reshape(35, 1); layer.Forward(input, output); - CheckMatrices(output - expectedOutput, arma::zeros(output.n_rows), 1e-6); + CheckMatrices(output, expectedOutput, 1e-6); expectedOutput.clear(); expectedOutput << 103.79040654914 << 180.51345595086 << arma::endr @@ -2204,7 +2204,7 @@ TEST_CASE("SimpleBicubicInterpolationLayerTest", "[ANNLayerTest]") layer.Backward(output, output, unzoomedOutput); - CheckMatrices(unzoomedOutput - expectedOutput, arma::zeros(input.n_rows), 1e-6); + CheckMatrices(unzoomedOutput, expectedOutput, 1e-6); } From daa842131ff90a09b250e2f46d0c82547fa055b4 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Sat, 17 Jul 2021 02:54:22 +0530 Subject: [PATCH 669/729] removed storeing temp matrix --- src/mlpack/methods/ann/layer/bicubic_interpolation.hpp | 5 ----- src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp index 21b4402e02..d35b15e458 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation.hpp @@ -83,9 +83,6 @@ class BicubicInterpolation const arma::Mat& gradient, arma::Mat& output); - //! Get the size of the weights. - size_t WeightSize() const { return (inRowSize + 5) * (inColSize + 4); } - template void GetKernalWeight(eT delta, arma::mat& coeffs); @@ -171,8 +168,6 @@ class BicubicInterpolation //! Locally-stored weights parameter. OutputDataType weights; - // Locally-stored temp for padded output matrix. - arma::Mat temp; }; // class BicubicInterpolation } // namespace ann diff --git a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp index 6ba6443cd5..7eacae2f8e 100644 --- a/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp +++ b/src/mlpack/methods/ann/layer/bicubic_interpolation_impl.hpp @@ -50,8 +50,7 @@ BicubicInterpolation( alpha(alpha), batchSize(0) { - weights.set_size(WeightSize(), 1); - temp = arma::mat(weights.memptr(), inRowSize + 4, inColSize + 4, false, false); + } template @@ -170,6 +169,7 @@ void BicubicInterpolation::Backward( } else { + arma::mat temp = arma::mat(inRowSize + 4, inColSize + 4); for (size_t k = 0; k < depth * batchSize; ++k) { temp.zeros(); From 1e16d1194cc7d5c50afc22bab4778f8bd713506e Mon Sep 17 00:00:00 2001 From: Yashwants19 Date: Sat, 17 Jul 2021 10:00:38 +0000 Subject: [PATCH 670/729] Upgrade CLI11 to 2.0.0 --- .../bindings/cli/third_party/CLI/CLI11.hpp | 2034 +++++++++++------ 1 file changed, 1357 insertions(+), 677 deletions(-) diff --git a/src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp b/src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp index 68244d3864..ce1d06e3f2 100644 --- a/src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp +++ b/src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp @@ -1,20 +1,16 @@ -#pragma once - -// CLI11: Version 1.9.1 +// CLI11: Version 2.0.0 // Originally designed by Henry Schreiner // https://github.com/CLIUtils/CLI11 // // This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts -// from: v1.9.1 +// from: v2.0.0 (added include gaurd) // -// From LICENSE: -// -// CLI11 1.8 Copyright (c) 2017-2019 University of Cincinnati, developed by Henry +// CLI11 2.0.0 Copyright (c) 2017-2020 University of Cincinnati, developed by Henry // Schreiner under NSF AWARD 1414736. All rights reserved. -// +// // Redistribution and use in source and binary forms of CLI11, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, @@ -23,7 +19,7 @@ // 3. Neither the name of the copyright holder nor the names of its contributors // may be used to endorse or promote products derived from this software without // specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -35,48 +31,42 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#pragma once // Standard combined includes: - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -// Verbatim copy from Version.hpp: - - -#define CLI11_VERSION_MAJOR 1 -#define CLI11_VERSION_MINOR 9 -#define CLI11_VERSION_PATCH 1 -#define CLI11_VERSION "1.9.1" +#define CLI11_VERSION_MAJOR 2 +#define CLI11_VERSION_MINOR 0 +#define CLI11_VERSION_PATCH 0 +#define CLI11_VERSION "2.0.0" -// Verbatim copy from Macros.hpp: - - -// The following version macro is very similar to the one in PyBind11 +// The following version macro is very similar to the one in pybind11 #if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER) #if __cplusplus >= 201402L #define CLI11_CPP14 @@ -112,9 +102,6 @@ -// Verbatim copy from Validators.hpp: - - // C standard library // Only needed for existence checking #if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM @@ -149,18 +136,9 @@ -// From Version.hpp: - - - -// From Macros.hpp: - - - -// From StringTools.hpp: - namespace CLI { + /// Include the items in this namespace to get free conversion of enums to/from streams. /// (This is available inside CLI as well, so CLI11 will use this without a using statement). namespace enums { @@ -220,10 +198,14 @@ std::string join(const T &v, Callable func, std::string delim = ",") { std::ostringstream s; auto beg = std::begin(v); auto end = std::end(v); - if(beg != end) - s << func(*beg++); + auto loc = s.tellp(); while(beg != end) { - s << delim << func(*beg++); + auto nloc = s.tellp(); + if(nloc > loc) { + s << delim; + loc = nloc; + } + s << func(*beg++); } return s.str(); } @@ -299,7 +281,7 @@ inline std::string trim_copy(const std::string &str, const std::string &filter) return trim(s, filter); } /// Print a two part "help" string -inline std::ostream &format_help(std::ostream &out, std::string name, std::string description, std::size_t wid) { +inline std::ostream &format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) { name = " " + name; out << std::setw(static_cast(wid)) << std::left << name; if(!description.empty()) { @@ -316,6 +298,24 @@ inline std::ostream &format_help(std::ostream &out, std::string name, std::strin return out; } +/// Print subcommand aliases +inline std::ostream &format_aliases(std::ostream &out, const std::vector &aliases, std::size_t wid) { + if(!aliases.empty()) { + out << std::setw(static_cast(wid)) << " aliases: "; + bool front = true; + for(const auto &alias : aliases) { + if(!front) { + out << ", "; + } else { + front = false; + } + out << alias; + } + out << "\n"; + } + return out; +} + /// Verify the first character of an option template bool valid_first_char(T c) { return std::isalnum(c, std::locale()) || c == '_' || c == '?' || c == '@'; @@ -334,6 +334,12 @@ inline bool valid_name_string(const std::string &str) { return true; } +/// check if a string is a container segment separator (empty or "%%") +inline bool is_separator(const std::string &str) { + static const std::string sep("%%"); + return (str.empty() || str == sep); +} + /// Verify that str consists of letters only inline bool isalpha(const std::string &str) { return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); }); @@ -448,7 +454,12 @@ inline std::vector split_up(std::string str, char delimiter = '\0') } if(end != std::string::npos) { output.push_back(str.substr(1, end - 1)); - str = str.substr(end + 1); + if(end + 2 < str.size()) { + str = str.substr(end + 2); + } else { + str.clear(); + } + } else { output.push_back(str.substr(1)); str = ""; @@ -520,11 +531,8 @@ inline std::string &add_quotes_if_needed(std::string &str) { } // namespace detail -} // namespace CLI -// From Error.hpp: -namespace CLI { // Use one of these on all error classes. // These are temporary and are undef'd at the end of this file. @@ -666,19 +674,26 @@ class Success : public ParseError { }; /// -h or --help on command line -class CallForHelp : public ParseError { - CLI11_ERROR_DEF(ParseError, CallForHelp) +class CallForHelp : public Success { + CLI11_ERROR_DEF(Success, CallForHelp) CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} }; /// Usually something like --help-all on command line -class CallForAllHelp : public ParseError { - CLI11_ERROR_DEF(ParseError, CallForAllHelp) +class CallForAllHelp : public Success { + CLI11_ERROR_DEF(Success, CallForAllHelp) CallForAllHelp() : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} }; -/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code. +/// -v or --version on command line +class CallForVersion : public Success { + CLI11_ERROR_DEF(Success, CallForVersion) + CallForVersion() + : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Does not output a diagnostic in CLI11_PARSE, but allows main() to return with a specific error code. class RuntimeError : public ParseError { CLI11_ERROR_DEF(ParseError, RuntimeError) explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} @@ -846,11 +861,8 @@ class OptionNotFound : public Error { /// @} -} // namespace CLI -// From TypeTools.hpp: -namespace CLI { // Type tools @@ -880,15 +892,6 @@ template using void_t = typename make_void::type; /// A copy of std::conditional_t from C++14 - same reasoning as enable_if_t, it does not hurt to redefine template using conditional_t = typename std::conditional::type; -/// Check to see if something is a vector (fail check by default) -template struct is_vector : std::false_type {}; - -/// Check to see if something is a vector (true if actually a vector) -template struct is_vector> : std::true_type {}; - -/// Check to see if something is a vector (true if actually a const vector) -template struct is_vector> : std::true_type {}; - /// Check to see if something is bool (fail check by default) template struct is_bool : std::false_type {}; @@ -1030,6 +1033,17 @@ template class is_istreamable { static constexpr bool value = decltype(test(0))::value; }; +/// Check for complex +template class is_complex { + template + static auto test(int) -> decltype(std::declval().real(), std::declval().imag(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + /// Templated operation to get a value from a stream template ::value, detail::enabler> = detail::dummy> bool from_stream(const std::string &istring, T &obj) { @@ -1044,12 +1058,49 @@ bool from_stream(const std::string & /*istring*/, T & /*obj*/) { return false; } +// check to see if an object is a mutable container (fail by default) +template struct is_mutable_container : std::false_type {}; + +/// type trait to test if a type is a mutable container meaning it has a value_type, it has an iterator, a clear, and +/// end methods and an insert function. And for our purposes we exclude std::string and types that can be constructed +/// from a std::string +template +struct is_mutable_container< + T, + conditional_t().end()), + decltype(std::declval().clear()), + decltype(std::declval().insert(std::declval().end())>(), + std::declval()))>, + void>> + : public conditional_t::value, std::false_type, std::true_type> {}; + +// check to see if an object is a mutable container (fail by default) +template struct is_readable_container : std::false_type {}; + +/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, a clear, and an end +/// methods and an insert function. And for our purposes we exclude std::string and types that can be constructed from +/// a std::string +template +struct is_readable_container< + T, + conditional_t().end()), decltype(std::declval().begin())>, void>> + : public std::true_type {}; + +// check to see if an object is a wrapper (fail by default) +template struct is_wrapper : std::false_type {}; + +// check if an object is a wrapper (it has a value_type defined) +template +struct is_wrapper, void>> : public std::true_type {}; + // Check for tuple like types, as in classes with a tuple_size type trait template class is_tuple_like { template // static auto test(int) // -> decltype(std::conditional<(std::tuple_size::value > 0), std::true_type, std::false_type>::type()); - static auto test(int) -> decltype(std::tuple_size::value, std::true_type{}); + static auto test(int) -> decltype(std::tuple_size::type>::value, std::true_type{}); template static auto test(...) -> std::false_type; public: @@ -1084,20 +1135,19 @@ std::string to_string(T &&value) { /// If conversion is not supported, return an empty string (streaming is not supported for that type) template ::value && !is_ostreamable::value && - !is_vector::type>::type>::value, + !is_readable_container::type>::value, detail::enabler> = detail::dummy> std::string to_string(T &&) { return std::string{}; } -/// convert a vector to a string +/// convert a readable container to a string template ::value && !is_ostreamable::value && - is_vector::type>::type>::value, + is_readable_container::value, detail::enabler> = detail::dummy> std::string to_string(T &&variable) { std::vector defaults; - defaults.reserve(variable.size()); auto cval = variable.begin(); auto end = variable.end(); while(cval != end) { @@ -1141,25 +1191,142 @@ auto value_string(const T &value) -> decltype(to_string(value)) { return to_string(value); } -/// This will only trigger for actual void type -template struct type_count { static const int value{0}; }; +/// template to get the underlying value type if it exists or use a default +template struct wrapped_type { using type = def; }; -/// Set of overloads to get the type size of an object -template struct type_count::value>::type> { - static constexpr int value{std::tuple_size::value}; +/// Type size for regular object types that do not look like a tuple +template struct wrapped_type::value>::type> { + using type = typename T::value_type; }; + +/// This will only trigger for actual void type +template struct type_count_base { static const int value{0}; }; + /// Type size for regular object types that do not look like a tuple template -struct type_count< - T, - typename std::enable_if::value && !is_tuple_like::value && !std::is_void::value>::type> { +struct type_count_base::value && !is_mutable_container::value && + !std::is_void::value>::type> { static constexpr int value{1}; }; -/// Type size of types that look like a vector -template struct type_count::value>::type> { - static constexpr int value{is_vector::value ? expected_max_vector_size - : type_count::value}; +/// the base tuple size +template +struct type_count_base::value && !is_mutable_container::value>::type> { + static constexpr int value{std::tuple_size::value}; +}; + +/// Type count base for containers is the type_count_base of the individual element +template struct type_count_base::value>::type> { + static constexpr int value{type_count_base::value}; +}; + +/// Set of overloads to get the type size of an object + +/// forward declare the subtype_count structure +template struct subtype_count; + +/// forward declare the subtype_count_min structure +template struct subtype_count_min; + +/// This will only trigger for actual void type +template struct type_count { static const int value{0}; }; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count::value && !is_tuple_like::value && !is_complex::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; + +/// Type size for complex since it sometimes looks like a wrapper +template struct type_count::value>::type> { + static constexpr int value{2}; +}; + +/// Type size of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) +template struct type_count::value>::type> { + static constexpr int value{subtype_count::value}; +}; + +/// Type size of types that are wrappers,except containers complex and tuples(which can also be wrappers sometimes) +template +struct type_count::value && !is_complex::value && !is_tuple_like::value && + !is_mutable_container::value>::type> { + static constexpr int value{type_count::value}; +}; + +/// 0 if the index > tuple size +template +constexpr typename std::enable_if::value, int>::type tuple_type_size() { + return 0; +} + +/// Recursively generate the tuple type name +template + constexpr typename std::enable_if < I::value, int>::type tuple_type_size() { + return subtype_count::type>::value + tuple_type_size(); +} + +/// Get the type size of the sum of type sizes for all the individual tuple types +template struct type_count::value>::type> { + static constexpr int value{tuple_type_size()}; +}; + +/// definition of subtype count +template struct subtype_count { + static constexpr int value{is_mutable_container::value ? expected_max_vector_size : type_count::value}; +}; + +/// This will only trigger for actual void type +template struct type_count_min { static const int value{0}; }; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count_min< + T, + typename std::enable_if::value && !is_tuple_like::value && !is_wrapper::value && + !is_complex::value && !std::is_void::value>::type> { + static constexpr int value{type_count::value}; +}; + +/// Type size for complex since it sometimes looks like a wrapper +template struct type_count_min::value>::type> { + static constexpr int value{1}; +}; + +/// Type size min of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) +template +struct type_count_min< + T, + typename std::enable_if::value && !is_complex::value && !is_tuple_like::value>::type> { + static constexpr int value{subtype_count_min::value}; +}; + +/// 0 if the index > tuple size +template +constexpr typename std::enable_if::value, int>::type tuple_type_size_min() { + return 0; +} + +/// Recursively generate the tuple type name +template + constexpr typename std::enable_if < I::value, int>::type tuple_type_size_min() { + return subtype_count_min::type>::value + tuple_type_size_min(); +} + +/// Get the type size of the sum of type sizes for all the individual tuple types +template struct type_count_min::value>::type> { + static constexpr int value{tuple_type_size_min()}; +}; + +/// definition of subtype count +template struct subtype_count_min { + static constexpr int value{is_mutable_container::value + ? ((type_count::value < expected_max_vector_size) ? type_count::value : 0) + : type_count_min::value}; }; /// This will only trigger for actual void type @@ -1167,16 +1334,25 @@ template struct expected_count { static con /// For most types the number of expected items is 1 template -struct expected_count::value && !std::is_void::value>::type> { +struct expected_count::value && !is_wrapper::value && + !std::is_void::value>::type> { static constexpr int value{1}; }; /// number of expected items in a vector -template struct expected_count::value>::type> { +template struct expected_count::value>::type> { static constexpr int value{expected_max_vector_size}; }; +/// number of expected items in a vector +template +struct expected_count::value && is_wrapper::value>::type> { + static constexpr int value{expected_count::value}; +}; + // Enumeration of the different supported categorizations of objects enum class object_category : int { + char_value = 1, integral_value = 2, unsigned_integral = 4, enumeration = 6, @@ -1185,36 +1361,48 @@ enum class object_category : int { number_constructible = 12, double_constructible = 14, integer_constructible = 16, - vector_value = 30, - tuple_value = 35, - // string assignable or greater used in a condition so anything string like must come last - string_assignable = 50, - string_constructible = 60, - other = 200, + // string like types + string_assignable = 23, + string_constructible = 24, + other = 45, + // special wrapper or container types + wrapper_value = 50, + complex_number = 60, + tuple_value = 70, + container_value = 80, }; +/// Set of overloads to classify an object according to type + /// some type that is not otherwise recognized template struct classify_object { static constexpr object_category value{object_category::other}; }; -/// Set of overloads to classify an object according to type +/// Signed integers template -struct classify_object::value && std::is_signed::value && - !is_bool::value && !std::is_enum::value>::type> { +struct classify_object< + T, + typename std::enable_if::value && !std::is_same::value && std::is_signed::value && + !is_bool::value && !std::is_enum::value>::type> { static constexpr object_category value{object_category::integral_value}; }; /// Unsigned integers template -struct classify_object< - T, - typename std::enable_if::value && std::is_unsigned::value && !is_bool::value>::type> { +struct classify_object::value && std::is_unsigned::value && + !std::is_same::value && !is_bool::value>::type> { static constexpr object_category value{object_category::unsigned_integral}; }; +/// single character values +template +struct classify_object::value && !std::is_enum::value>::type> { + static constexpr object_category value{object_category::char_value}; +}; + /// Boolean values template struct classify_object::value>::type> { static constexpr object_category value{object_category::boolean_value}; @@ -1227,10 +1415,9 @@ template struct classify_object -struct classify_object< - T, - typename std::enable_if::value && !std::is_integral::value && - std::is_assignable::value && !is_vector::value>::type> { +struct classify_object::value && !std::is_integral::value && + std::is_assignable::value>::type> { static constexpr object_category value{object_category::string_assignable}; }; @@ -1239,8 +1426,8 @@ template struct classify_object< T, typename std::enable_if::value && !std::is_integral::value && - !std::is_assignable::value && - std::is_constructible::value && !is_vector::value>::type> { + !std::is_assignable::value && (type_count::value == 1) && + std::is_constructible::value>::type> { static constexpr object_category value{object_category::string_constructible}; }; @@ -1249,23 +1436,35 @@ template struct classify_object struct classify_object::value>::type> { + static constexpr object_category value{object_category::complex_number}; +}; + /// Handy helper to contain a bunch of checks that rule out many common types (integers, string like, floating point, /// vectors, and enumerations template struct uncommon_type { using type = typename std::conditional::value && !std::is_integral::value && !std::is_assignable::value && - !std::is_constructible::value && !is_vector::value && - !std::is_enum::value, + !std::is_constructible::value && !is_complex::value && + !is_mutable_container::value && !std::is_enum::value, std::true_type, std::false_type>::type; static constexpr bool value = type::value; }; +/// wrapper type +template +struct classify_object::value && is_wrapper::value && + !is_tuple_like::value && uncommon_type::value)>::type> { + static constexpr object_category value{object_category::wrapper_value}; +}; + /// Assignable from double or int template struct classify_object::value && type_count::value == 1 && - is_direct_constructible::value && + !is_wrapper::value && is_direct_constructible::value && is_direct_constructible::value>::type> { static constexpr object_category value{object_category::number_constructible}; }; @@ -1274,7 +1473,7 @@ struct classify_object struct classify_object::value && type_count::value == 1 && - !is_direct_constructible::value && + !is_wrapper::value && !is_direct_constructible::value && is_direct_constructible::value>::type> { static constexpr object_category value{object_category::integer_constructible}; }; @@ -1283,24 +1482,30 @@ struct classify_object struct classify_object::value && type_count::value == 1 && - is_direct_constructible::value && + !is_wrapper::value && is_direct_constructible::value && !is_direct_constructible::value>::type> { static constexpr object_category value{object_category::double_constructible}; }; /// Tuple type template -struct classify_object::value >= 2 && !is_vector::value) || - (is_tuple_like::value && uncommon_type::value && - !is_direct_constructible::value && - !is_direct_constructible::value)>::type> { +struct classify_object< + T, + typename std::enable_if::value && + ((type_count::value >= 2 && !is_wrapper::value) || + (uncommon_type::value && !is_direct_constructible::value && + !is_direct_constructible::value))>::type> { static constexpr object_category value{object_category::tuple_value}; + // the condition on this class requires it be like a tuple, but on some compilers (like Xcode) tuples can be + // constructed from just the first element so tuples of can be constructed from a string, which + // could lead to issues so there are two variants of the condition, the first isolates things with a type size >=2 + // mainly to get tuples on Xcode with the exception of wrappers, the second is the main one and just separating out + // those cases that are caught by other object classifications }; -/// Vector type -template struct classify_object::value>::type> { - static constexpr object_category value{object_category::vector_value}; +/// container type +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::container_value}; }; // Type name print @@ -1309,6 +1514,12 @@ template struct classify_object::value == object_category::char_value, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "CHAR"; +} + template ::value == object_category::integral_value || classify_object::value == object_category::integer_constructible, @@ -1346,31 +1557,53 @@ constexpr const char *type_name() { return "BOOLEAN"; } +/// Print name for enumeration types +template ::value == object_category::complex_number, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "COMPLEX"; +} + /// Print for all other types template ::value >= object_category::string_assignable, detail::enabler> = detail::dummy> + enable_if_t::value >= object_category::string_assignable && + classify_object::value <= object_category::other, + detail::enabler> = detail::dummy> constexpr const char *type_name() { return "TEXT"; } +/// typename for tuple value +template ::value == object_category::tuple_value && type_count_base::value >= 2, + detail::enabler> = detail::dummy> +std::string type_name(); // forward declaration + +/// Generate type name for a wrapper or container value +template ::value == object_category::container_value || + classify_object::value == object_category::wrapper_value, + detail::enabler> = detail::dummy> +std::string type_name(); // forward declaration /// Print name for single element tuple types template ::value == object_category::tuple_value && type_count::value == 1, + enable_if_t::value == object_category::tuple_value && type_count_base::value == 1, detail::enabler> = detail::dummy> inline std::string type_name() { - return type_name::type>(); + return type_name::type>::type>(); } /// Empty string if the index > tuple size template -inline typename std::enable_if::value, std::string>::type tuple_name() { +inline typename std::enable_if::value, std::string>::type tuple_name() { return std::string{}; } /// Recursively generate the tuple type name template - inline typename std::enable_if < I::value, std::string>::type tuple_name() { - std::string str = std::string(type_name::type>()) + ',' + tuple_name(); +inline typename std::enable_if<(I < type_count_base::value), std::string>::type tuple_name() { + std::string str = std::string(type_name::type>::type>()) + + ',' + tuple_name(); if(str.back() == ',') str.pop_back(); return str; @@ -1378,23 +1611,49 @@ template /// Print type name for tuples with 2 or more elements template ::value == object_category::tuple_value && type_count::value >= 2, - detail::enabler> = detail::dummy> -std::string type_name() { + enable_if_t::value == object_category::tuple_value && type_count_base::value >= 2, + detail::enabler>> +inline std::string type_name() { auto tname = std::string(1, '[') + tuple_name(); tname.push_back(']'); return tname; } -/// This one should not be used normally, since vector types print the internal type +/// get the type name for a type that has a value_type member template ::value == object_category::vector_value, detail::enabler> = detail::dummy> + enable_if_t::value == object_category::container_value || + classify_object::value == object_category::wrapper_value, + detail::enabler>> inline std::string type_name() { return type_name(); } // Lexical cast +/// Convert to an unsigned integral +template ::value, detail::enabler> = detail::dummy> +bool integral_conversion(const std::string &input, T &output) noexcept { + if(input.empty()) { + return false; + } + char *val = nullptr; + std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); + output = static_cast(output_ll); + return val == (input.c_str() + input.size()) && static_cast(output) == output_ll; +} + +/// Convert to a signed integral +template ::value, detail::enabler> = detail::dummy> +bool integral_conversion(const std::string &input, T &output) noexcept { + if(input.empty()) { + return false; + } + char *val = nullptr; + std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); + output = static_cast(output_ll); + return val == (input.c_str() + input.size()) && static_cast(output) == output_ll; +} + /// Convert a flag into an integer value typically binary flags inline std::int64_t to_flag_value(std::string val) { static const std::string trueString("true"); @@ -1438,39 +1697,24 @@ inline std::int64_t to_flag_value(std::string val) { return ret; } -/// Signed integers +/// Integer conversion template ::value == object_category::integral_value, detail::enabler> = detail::dummy> + enable_if_t::value == object_category::integral_value || + classify_object::value == object_category::unsigned_integral, + detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { - try { - std::size_t n = 0; - std::int64_t output_ll = std::stoll(input, &n, 0); - output = static_cast(output_ll); - return n == input.size() && static_cast(output) == output_ll; - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { - return false; - } + return integral_conversion(input, output); } -/// Unsigned integers +/// char values template ::value == object_category::unsigned_integral, detail::enabler> = detail::dummy> + enable_if_t::value == object_category::char_value, detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { - if(!input.empty() && input.front() == '-') - return false; // std::stoull happily converts negative values to junk without any errors. - - try { - std::size_t n = 0; - std::uint64_t output_ll = std::stoull(input, &n, 0); - output = static_cast(output_ll); - return n == input.size() && static_cast(output) == output_ll; - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { - return false; + if(input.size() == 1) { + output = static_cast(input[0]); + return true; } + return integral_conversion(input, output); } /// Boolean values @@ -1495,15 +1739,45 @@ bool lexical_cast(const std::string &input, T &output) { template ::value == object_category::floating_point, detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { - try { - std::size_t n = 0; - output = static_cast(std::stold(input, &n)); - return n == input.size(); - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { + if(input.empty()) { return false; } + char *val = nullptr; + auto output_ld = std::strtold(input.c_str(), &val); + output = static_cast(output_ld); + return val == (input.c_str() + input.size()); +} + +/// complex +template ::value == object_category::complex_number, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + using XC = typename wrapped_type::type; + XC x{0.0}, y{0.0}; + auto str1 = input; + bool worked = false; + auto nloc = str1.find_last_of("+-"); + if(nloc != std::string::npos && nloc > 0) { + worked = detail::lexical_cast(str1.substr(0, nloc), x); + str1 = str1.substr(nloc); + if(str1.back() == 'i' || str1.back() == 'j') + str1.pop_back(); + worked = worked && detail::lexical_cast(str1, y); + } else { + if(str1.back() == 'i' || str1.back() == 'j') { + str1.pop_back(); + worked = detail::lexical_cast(str1, y); + x = XC{0}; + } else { + worked = detail::lexical_cast(str1, x); + y = XC{0}; + } + } + if(worked) { + output = T{x, y}; + return worked; + } + return from_stream(input, output); } /// String and similar direct assignment @@ -1528,21 +1802,47 @@ template ::value == object_category::enumeration, detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { typename std::underlying_type::type val; - bool retval = detail::lexical_cast(input, val); - if(!retval) { + if(!integral_conversion(input, val)) { return false; } output = static_cast(val); return true; } +/// wrapper types +template ::value == object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename T::value_type val; + if(lexical_cast(input, val)) { + output = val; + return true; + } + return from_stream(input, output); +} + +template ::value == object_category::wrapper_value && + !std::is_assignable::value && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename T::value_type val; + if(lexical_cast(input, val)) { + output = T{val}; + return true; + } + return from_stream(input, output); +} + /// Assignable from double or int template < typename T, enable_if_t::value == object_category::number_constructible, detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { int val; - if(lexical_cast(input, val)) { + if(integral_conversion(input, val)) { output = T(val); return true; } else { @@ -1561,7 +1861,7 @@ template < enable_if_t::value == object_category::integer_constructible, detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { int val; - if(lexical_cast(input, val)) { + if(integral_conversion(input, val)) { output = T(val); return true; } @@ -1581,8 +1881,36 @@ bool lexical_cast(const std::string &input, T &output) { return from_stream(input, output); } +/// Non-string convertible from an int +template ::value == object_category::other && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val; + if(integral_conversion(input, val)) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4800) +#endif + // with Atomic this could produce a warning due to the conversion but if atomic gets here it is an old style + // so will most likely still work + output = val; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + return true; + } + // LCOV_EXCL_START + // This version of cast is only used for odd cases in an older compilers the fail over + // from_stream is tested elsewhere an not relevant for coverage here + return from_stream(input, output); + // LCOV_EXCL_STOP +} + /// Non-string parsable by a stream -template ::value == object_category::other, detail::enabler> = detail::dummy> +template ::value == object_category::other && !std::is_assignable::value, + detail::enabler> = detail::dummy> bool lexical_cast(const std::string &input, T &output) { static_assert(is_istreamable::value, "option object type must have a lexical cast overload or streaming input operator(>>) defined, if it " @@ -1591,38 +1919,77 @@ bool lexical_cast(const std::string &input, T &output) { } /// Assign a value through lexical cast operations -template < - typename T, - typename XC, - enable_if_t::value && (classify_object::value == object_category::string_assignable || - classify_object::value == object_category::string_constructible), - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, T &output) { +/// Strings can be empty so we need to do a little different +template ::value && + (classify_object::value == object_category::string_assignable || + classify_object::value == object_category::string_constructible), + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { return lexical_cast(input, output); } /// Assign a value through lexical cast operations -template ::value && classify_object::value != object_category::string_assignable && - classify_object::value != object_category::string_constructible, +template ::value && std::is_assignable::value && + classify_object::value != object_category::string_assignable && + classify_object::value != object_category::string_constructible, detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, T &output) { +bool lexical_assign(const std::string &input, AssignTo &output) { if(input.empty()) { - output = T{}; + output = AssignTo{}; + return true; + } + + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations +template ::value && !std::is_assignable::value && + classify_object::value == object_category::wrapper_value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + typename AssignTo::value_type emptyVal{}; + output = emptyVal; return true; } return lexical_cast(input, output); } +/// Assign a value through lexical cast operations for int compatible values +/// mainly for atomic operations on some compilers +template ::value && !std::is_assignable::value && + classify_object::value != object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + output = 0; + return true; + } + int val; + if(lexical_cast(input, val)) { + output = val; + return true; + } + return false; +} + /// Assign a value converted from a string in lexical cast to the output value directly -template < - typename T, - typename XC, - enable_if_t::value && std::is_assignable::value, detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, T &output) { - XC val{}; - bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; +template ::value && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + ConvertTo val{}; + bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; if(parse_result) { output = val; } @@ -1630,84 +1997,242 @@ bool lexical_assign(const std::string &input, T &output) { } /// Assign a value from a lexical cast through constructing a value and move assigning it -template ::value && !std::is_assignable::value && - std::is_move_assignable::value, - detail::enabler> = detail::dummy> -bool lexical_assign(const std::string &input, T &output) { - XC val{}; - bool parse_result = input.empty() ? true : lexical_cast(input, val); +template < + typename AssignTo, + typename ConvertTo, + enable_if_t::value && !std::is_assignable::value && + std::is_move_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + ConvertTo val{}; + bool parse_result = input.empty() ? true : lexical_cast(input, val); if(parse_result) { - output = T(val); // use () form of constructor to allow some implicit conversions + output = AssignTo(val); // use () form of constructor to allow some implicit conversions } return parse_result; } -/// Lexical conversion if there is only one element -template < - typename T, - typename XC, - enable_if_t::value && !is_tuple_like::value && !is_vector::value && !is_vector::value, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { - return lexical_assign(strings[0], output); + +/// primary lexical conversion operation, 1 string to 1 type of some kind +template ::value <= object_category::other && + classify_object::value <= object_category::wrapper_value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + return lexical_assign(strings[0], output); } -/// Lexical conversion if there is only one element but the conversion type is for two call a two element constructor -template ::value == 1 && type_count::value == 2, detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { - typename std::tuple_element<0, XC>::type v1; - typename std::tuple_element<1, XC>::type v2; +/// Lexical conversion if there is only one element but the conversion type is for two, then call a two element +/// constructor +template ::value <= 2) && expected_count::value == 1 && + is_tuple_like::value && type_count_base::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + // the remove const is to handle pair types coming from a container + typename std::remove_const::type>::type v1; + typename std::tuple_element<1, ConvertTo>::type v2; bool retval = lexical_assign(strings[0], v1); if(strings.size() > 1) { retval = retval && lexical_assign(strings[1], v2); } if(retval) { - output = T{v1, v2}; + output = AssignTo{v1, v2}; } return retval; } -/// Lexical conversion of a vector types -template ::value == expected_max_vector_size && - expected_count::value == expected_max_vector_size && type_count::value == 1, +/// Lexical conversion of a container types of single elements +template ::value && is_mutable_container::value && + type_count::value == 1, detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + output.erase(output.begin(), output.end()); + for(const auto &elem : strings) { + typename AssignTo::value_type out; + bool retval = lexical_assign(elem, out); + if(!retval) { + return false; + } + output.insert(output.end(), std::move(out)); + } + return (!output.empty()); +} + +/// Lexical conversion for complex types +template ::value, detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + + if(strings.size() >= 2 && !strings[1].empty()) { + using XC2 = typename wrapped_type::type; + XC2 x{0.0}, y{0.0}; + auto str1 = strings[1]; + if(str1.back() == 'i' || str1.back() == 'j') { + str1.pop_back(); + } + auto worked = detail::lexical_cast(strings[0], x) && detail::lexical_cast(str1, y); + if(worked) { + output = ConvertTo{x, y}; + } + return worked; + } else { + return lexical_assign(strings[0], output); + } +} + +/// Conversion to a vector type using a particular single type as the conversion type +template ::value && (expected_count::value == 1) && + (type_count::value == 1), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + bool retval = true; output.clear(); output.reserve(strings.size()); for(const auto &elem : strings) { output.emplace_back(); - bool retval = lexical_assign(elem, output.back()); - if(!retval) { - return false; - } + retval = retval && lexical_assign(elem, output.back()); } - return (!output.empty()); + return (!output.empty()) && retval; } -/// Lexical conversion of a vector types with type size of two -template ::value == expected_max_vector_size && - expected_count::value == expected_max_vector_size && type_count::value == 2, - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { - output.clear(); - for(std::size_t ii = 0; ii < strings.size(); ii += 2) { +// forward declaration - typename std::tuple_element<0, typename XC::value_type>::type v1; - typename std::tuple_element<1, typename XC::value_type>::type v2; - bool retval = lexical_assign(strings[ii], v1); - if(strings.size() > ii + 1) { - retval = retval && lexical_assign(strings[ii + 1], v2); +/// Lexical conversion of a container types with conversion type of two elements +template ::value && is_mutable_container::value && + type_count_base::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(std::vector strings, AssignTo &output); + +/// Lexical conversion of a vector types with type_size >2 forward declaration +template ::value && is_mutable_container::value && + type_count_base::value != 2 && + ((type_count::value > 2) || + (type_count::value > type_count_base::value)), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output); + +/// Conversion for tuples +template ::value && is_tuple_like::value && + (type_count_base::value != type_count::value || + type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output); // forward declaration + +/// Conversion for operations where the assigned type is some class but the conversion is a mutable container or large +/// tuple +template ::value && !is_mutable_container::value && + classify_object::value != object_category::wrapper_value && + (is_mutable_container::value || type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + + if(strings.size() > 1 || (!strings.empty() && !(strings.front().empty()))) { + ConvertTo val; + auto retval = lexical_conversion(strings, val); + output = AssignTo{val}; + return retval; + } + output = AssignTo{}; + return true; +} + +/// function template for converting tuples if the static Index is greater than the tuple size +template +inline typename std::enable_if<(I >= type_count_base::value), bool>::type +tuple_conversion(const std::vector &, AssignTo &) { + return true; +} + +/// Conversion of a tuple element where the type size ==1 and not a mutable container +template +inline typename std::enable_if::value && type_count::value == 1, bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + auto retval = lexical_assign(strings[0], output); + strings.erase(strings.begin()); + return retval; +} + +/// Conversion of a tuple element where the type size !=1 but the size is fixed and not a mutable container +template +inline typename std::enable_if::value && (type_count::value > 1) && + type_count::value == type_count_min::value, + bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + auto retval = lexical_conversion(strings, output); + strings.erase(strings.begin(), strings.begin() + type_count::value); + return retval; +} + +/// Conversion of a tuple element where the type is a mutable container or a type with different min and max type sizes +template +inline typename std::enable_if::value || + type_count::value != type_count_min::value, + bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + + std::size_t index{subtype_count_min::value}; + const std::size_t mx_count{subtype_count::value}; + const std::size_t mx{(std::max)(mx_count, strings.size())}; + + while(index < mx) { + if(is_separator(strings[index])) { + break; + } + ++index; + } + bool retval = lexical_conversion( + std::vector(strings.begin(), strings.begin() + static_cast(index)), output); + strings.erase(strings.begin(), strings.begin() + static_cast(index) + 1); + return retval; +} + +/// Tuple conversion operation +template +inline typename std::enable_if<(I < type_count_base::value), bool>::type +tuple_conversion(std::vector strings, AssignTo &output) { + bool retval = true; + using ConvertToElement = typename std:: + conditional::value, typename std::tuple_element::type, ConvertTo>::type; + if(!strings.empty()) { + retval = retval && tuple_type_conversion::type, ConvertToElement>( + strings, std::get(output)); + } + retval = retval && tuple_conversion(std::move(strings), output); + return retval; +} + +/// Lexical conversion of a container types with tuple elements of size 2 +template ::value && is_mutable_container::value && + type_count_base::value == 2, + detail::enabler>> +bool lexical_conversion(std::vector strings, AssignTo &output) { + output.clear(); + while(!strings.empty()) { + + typename std::remove_const::type>::type v1; + typename std::tuple_element<1, typename ConvertTo::value_type>::type v2; + bool retval = tuple_type_conversion(strings, v1); + if(!strings.empty()) { + retval = retval && tuple_type_conversion(strings, v2); } if(retval) { - output.emplace_back(v1, v2); + output.insert(output.end(), typename AssignTo::value_type{v1, v2}); } else { return false; } @@ -1715,110 +2240,103 @@ bool lexical_conversion(const std::vector &strings, T &output) { return (!output.empty()); } -/// Conversion to a vector type using a particular single type as the conversion type -template ::value == expected_max_vector_size) && (expected_count::value == 1) && - (type_count::value == 1), - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { - bool retval = true; - output.clear(); - output.reserve(strings.size()); - for(const auto &elem : strings) { - - output.emplace_back(); - retval = retval && lexical_assign(elem, output.back()); - } - return (!output.empty()) && retval; -} -// This one is last since it can call other lexical_conversion functions -/// Lexical conversion if there is only one element but the conversion type is a vector -template ::value && !is_vector::value && is_vector::value, detail::enabler> = - detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { - - if(strings.size() > 1 || (!strings.empty() && !(strings.front().empty()))) { - XC val; - auto retval = lexical_conversion(strings, val); - output = T{val}; - return retval; - } - output = T{}; - return true; -} - -/// function template for converting tuples if the static Index is greater than the tuple size -template -inline typename std::enable_if= type_count::value, bool>::type tuple_conversion(const std::vector &, - T &) { - return true; -} -/// Tuple conversion operation -template - inline typename std::enable_if < - I::value, bool>::type tuple_conversion(const std::vector &strings, T &output) { - bool retval = true; - if(strings.size() > I) { - retval = retval && lexical_assign::type, - typename std::conditional::value, - typename std::tuple_element::type, - XC>::type>(strings[I], std::get(output)); - } - retval = retval && tuple_conversion(strings, output); - return retval; -} - -/// Conversion for tuples -template ::value, detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { +/// lexical conversion of tuples with type count>2 or tuples of types of some element with a type size>=2 +template ::value && is_tuple_like::value && + (type_count_base::value != type_count::value || + type_count::value > 2), + detail::enabler>> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { static_assert( - !is_tuple_like::value || type_count::value == type_count::value, + !is_tuple_like::value || type_count_base::value == type_count_base::value, "if the conversion type is defined as a tuple it must be the same size as the type you are converting to"); - return tuple_conversion(strings, output); + return tuple_conversion(strings, output); } -/// Lexical conversion of a vector types with type_size >2 -template ::value == expected_max_vector_size && - expected_count::value == expected_max_vector_size && (type_count::value > 2), - detail::enabler> = detail::dummy> -bool lexical_conversion(const std::vector &strings, T &output) { +/// Lexical conversion of a vector types for everything but tuples of two elements and types of size 1 +template ::value && is_mutable_container::value && + type_count_base::value != 2 && + ((type_count::value > 2) || + (type_count::value > type_count_base::value)), + detail::enabler>> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { bool retval = true; output.clear(); std::vector temp; - std::size_t ii = 0; - std::size_t icount = 0; - std::size_t xcm = type_count::value; - while(ii < strings.size()) { + std::size_t ii{0}; + std::size_t icount{0}; + std::size_t xcm{type_count::value}; + auto ii_max = strings.size(); + while(ii < ii_max) { temp.push_back(strings[ii]); ++ii; ++icount; - if(icount == xcm || temp.back().empty()) { - if(static_cast(xcm) == expected_max_vector_size) { + if(icount == xcm || is_separator(temp.back()) || ii == ii_max) { + if(static_cast(xcm) > type_count_min::value && is_separator(temp.back())) { temp.pop_back(); } - output.emplace_back(); - retval = retval && lexical_conversion(temp, output.back()); + typename AssignTo::value_type temp_out; + retval = retval && + lexical_conversion(temp, temp_out); temp.clear(); if(!retval) { return false; } + output.insert(output.end(), std::move(temp_out)); icount = 0; } } return retval; } + +/// conversion for wrapper types +template ::value == object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + if(strings.empty() || strings.front().empty()) { + output = ConvertTo{}; + return true; + } + typename ConvertTo::value_type val; + if(lexical_conversion(strings, val)) { + output = ConvertTo{val}; + return true; + } + return false; +} + +/// conversion for wrapper types +template ::value == object_category::wrapper_value && + !std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + using ConvertType = typename ConvertTo::value_type; + if(strings.empty() || strings.front().empty()) { + output = ConvertType{}; + return true; + } + ConvertType val; + if(lexical_conversion(strings, val)) { + output = val; + return true; + } + return false; +} + /// Sum a vector of flag representations /// The flag vector produces a series of strings in a vector, simple true is represented by a "1", simple false is /// by /// "-1" an if numbers are passed by some fashion they are captured as well so the function just checks for the most /// common true and false strings then uses stoll to convert the rest for summing -template ::value && std::is_unsigned::value, detail::enabler> = detail::dummy> +template ::value, detail::enabler> = detail::dummy> void sum_flag_vector(const std::vector &flags, T &output) { std::int64_t count{0}; for(auto &flag : flags) { @@ -1832,8 +2350,7 @@ void sum_flag_vector(const std::vector &flags, T &output) { /// by /// "-1" an if numbers are passed by some fashion they are captured as well so the function just checks for the most /// common true and false strings then uses stoll to convert the rest for summing -template ::value && std::is_signed::value, detail::enabler> = detail::dummy> +template ::value, detail::enabler> = detail::dummy> void sum_flag_vector(const std::vector &flags, T &output) { std::int64_t count{0}; for(auto &flag : flags) { @@ -1842,12 +2359,37 @@ void sum_flag_vector(const std::vector &flags, T &output) { output = static_cast(count); } +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4800) +#endif +// with Atomic this could produce a warning due to the conversion but if atomic gets here it is an old style so will +// most likely still work + +/// Sum a vector of flag representations +/// The flag vector produces a series of strings in a vector, simple true is represented by a "1", simple false is +/// by +/// "-1" an if numbers are passed by some fashion they are captured as well so the function just checks for the most +/// common true and false strings then uses stoll to convert the rest for summing +template ::value && !std::is_unsigned::value, detail::enabler> = detail::dummy> +void sum_flag_vector(const std::vector &flags, T &output) { + std::int64_t count{0}; + for(auto &flag : flags) { + count += detail::to_flag_value(flag); + } + std::string out = detail::to_string(count); + lexical_cast(out, output); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } // namespace detail -} // namespace CLI -// From Split.hpp: -namespace CLI { + namespace detail { // Returns false if not a short option. Otherwise, sets opt name and rest and returns true @@ -1968,11 +2510,8 @@ get_names(const std::vector &input) { } } // namespace detail -} // namespace CLI -// From ConfigFwd.hpp: -namespace CLI { class App; @@ -2028,19 +2567,23 @@ class Config { virtual ~Config() = default; }; -/// This converter works with INI/TOML files; to write proper TOML files use ConfigTOML +/// This converter works with INI/TOML files; to write INI files use ConfigINI class ConfigBase : public Config { protected: /// the character used for comments - char commentChar = ';'; + char commentChar = '#'; /// the character used to start an array '\0' is a default to not use - char arrayStart = '\0'; + char arrayStart = '['; /// the character used to end an array '\0' is a default to not use - char arrayEnd = '\0'; + char arrayEnd = ']'; /// the character used to separate elements in an array - char arraySeparator = ' '; + char arraySeparator = ','; /// the character used separate the name from the value char valueDelimiter = '='; + /// the character to use around strings + char stringQuote = '"'; + /// the character to use around single characters + char characterQuote = '\''; public: std::string @@ -2068,28 +2611,31 @@ class ConfigBase : public Config { valueDelimiter = vSep; return this; } + /// Specify the quote characters used around strings and characters + ConfigBase *quoteCharacter(char qString, char qChar) { + stringQuote = qString; + characterQuote = qChar; + return this; + } }; -/// the default Config is the INI file format -using ConfigINI = ConfigBase; +/// the default Config is the TOML file format +using ConfigTOML = ConfigBase; -/// ConfigTOML generates a TOML compliant output -class ConfigTOML : public ConfigINI { +/// ConfigINI generates a "standard" INI compliant output +class ConfigINI : public ConfigTOML { public: - ConfigTOML() { - commentChar = '#'; - arrayStart = '['; - arrayEnd = ']'; - arraySeparator = ','; + ConfigINI() { + commentChar = ';'; + arrayStart = '\0'; + arrayEnd = '\0'; + arraySeparator = ' '; valueDelimiter = '='; } }; -} // namespace CLI -// From Validators.hpp: -namespace CLI { class Option; @@ -2451,53 +2997,6 @@ class IPV4Validator : public Validator { } }; -/// Validate the argument is a number and greater than 0 -class PositiveNumber : public Validator { - public: - PositiveNumber() : Validator("POSITIVE") { - func_ = [](std::string &number_str) { - double number; - if(!detail::lexical_cast(number_str, number)) { - return std::string("Failed parsing number: (") + number_str + ')'; - } - if(number <= 0) { - return std::string("Number less or equal to 0: (") + number_str + ')'; - } - return std::string(); - }; - } -}; -/// Validate the argument is a number and greater than or equal to 0 -class NonNegativeNumber : public Validator { - public: - NonNegativeNumber() : Validator("NONNEGATIVE") { - func_ = [](std::string &number_str) { - double number; - if(!detail::lexical_cast(number_str, number)) { - return std::string("Failed parsing number: (") + number_str + ')'; - } - if(number < 0) { - return std::string("Number less than 0: (") + number_str + ')'; - } - return std::string(); - }; - } -}; - -/// Validate the argument is a number -class Number : public Validator { - public: - Number() : Validator("NUMBER") { - func_ = [](std::string &number_str) { - double number; - if(!detail::lexical_cast(number_str, number)) { - return std::string("Failed parsing as a number (") + number_str + ')'; - } - return std::string(); - }; - } -}; - } // namespace detail // Static is not needed here, because global const implies static. @@ -2517,14 +3016,23 @@ const detail::NonexistentPathValidator NonexistentPath; /// Check for an IP4 address const detail::IPV4Validator ValidIPV4; -/// Check for a positive number -const detail::PositiveNumber PositiveNumber; - -/// Check for a non-negative number -const detail::NonNegativeNumber NonNegativeNumber; +/// Validate the input as a particular type +template class TypeValidator : public Validator { + public: + explicit TypeValidator(const std::string &validator_name) : Validator(validator_name) { + func_ = [](std::string &input_string) { + auto val = DesiredType(); + if(!detail::lexical_cast(input_string, val)) { + return std::string("Failed parsing ") + input_string + " as a " + detail::type_name(); + } + return std::string(); + }; + } + TypeValidator() : TypeValidator(detail::type_name()) {} +}; /// Check for a number -const detail::Number Number; +const TypeValidator Number("NUMBER"); /// Produce a range (factory). Min and max are inclusive. class Range : public Validator { @@ -2533,10 +3041,13 @@ class Range : public Validator { /// /// Note that the constructor is templated, but the struct is not, so C++17 is not /// needed to provide nice syntax for Range(a,b). - template Range(T min, T max) { - std::stringstream out; - out << detail::type_name() << " in [" << min << " - " << max << "]"; - description(out.str()); + template + Range(T min, T max, const std::string &validator_name = std::string{}) : Validator(validator_name) { + if(validator_name.empty()) { + std::stringstream out; + out << detail::type_name() << " in [" << min << " - " << max << "]"; + description(out.str()); + } func_ = [min, max](std::string &input) { T val; @@ -2550,9 +3061,17 @@ class Range : public Validator { } /// Range of one value is 0 to value - template explicit Range(T max) : Range(static_cast(0), max) {} + template + explicit Range(T max, const std::string &validator_name = std::string{}) + : Range(static_cast(0), max, validator_name) {} }; +/// Check for a non negative number +const Range NonNegativeNumber(std::numeric_limits::max(), "NONNEGATIVE"); + +/// Check for a positive valued number (val>0.0), min() her is the smallest positive number +const Range PositiveNumber(std::numeric_limits::min(), std::numeric_limits::max(), "POSITIVE"); + /// Produce a bounded range (factory). Min and max are inclusive. class Bound : public Validator { public: @@ -2778,9 +3297,7 @@ class IsMember : public Validator { } // If you reach this point, the result was not found - std::string out(" not in "); - out += detail::generate_set(detail::smart_deref(set)); - return out; + return input + " not in " + detail::generate_set(detail::smart_deref(set)); }; } @@ -3000,14 +3517,11 @@ class AsNumberWithUnit : public Validator { if(opts & CASE_INSENSITIVE) { unit = detail::to_lower(unit); } - - bool converted = detail::lexical_cast(input, num); - if(!converted) { - throw ValidationError(std::string("Value ") + input + " could not be converted to " + - detail::type_name()); - } - if(unit.empty()) { + if(!detail::lexical_cast(input, num)) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } // No need to modify input if no unit passed return {}; } @@ -3021,12 +3535,22 @@ class AsNumberWithUnit : public Validator { detail::generate_map(mapping, true)); } - // perform safe multiplication - bool ok = detail::checked_multiply(num, it->second); - if(!ok) { - throw ValidationError(detail::to_string(num) + " multiplied by " + unit + - " factor would cause number overflow. Use smaller value."); + if(!input.empty()) { + bool converted = detail::lexical_cast(input, num); + if(!converted) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } + // perform safe multiplication + bool ok = detail::checked_multiply(num, it->second); + if(!ok) { + throw ValidationError(detail::to_string(num) + " multiplied by " + unit + + " factor would cause number overflow. Use smaller value."); + } + } else { + num = static_cast(it->second); } + input = detail::to_string(num); return {}; @@ -3151,12 +3675,36 @@ inline std::pair split_program_name(std::string comman if(esp == std::string::npos) { // if we have reached the end and haven't found a valid file just assume the first argument is the // program name - esp = commandline.find_first_of(' ', 1); + if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') { + bool embeddedQuote = false; + auto keyChar = commandline[0]; + auto end = commandline.find_first_of(keyChar, 1); + while((end != std::string::npos) && (commandline[end - 1] == '\\')) { // deal with escaped quotes + end = commandline.find_first_of(keyChar, end + 1); + embeddedQuote = true; + } + if(end != std::string::npos) { + vals.first = commandline.substr(1, end - 1); + esp = end + 1; + if(embeddedQuote) { + vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar)); + embeddedQuote = false; + } + } else { + esp = commandline.find_first_of(' ', 1); + } + } else { + esp = commandline.find_first_of(' ', 1); + } + break; } } - vals.first = commandline.substr(0, esp); - rtrim(vals.first); + if(vals.first.empty()) { + vals.first = commandline.substr(0, esp); + rtrim(vals.first); + } + // strip the program name vals.second = (esp != std::string::npos) ? commandline.substr(esp + 1) : std::string{}; ltrim(vals.second); @@ -3166,11 +3714,8 @@ inline std::pair split_program_name(std::string comman } // namespace detail /// @} -} // namespace CLI -// From FormatterFwd.hpp: -namespace CLI { class Option; class App; @@ -3334,11 +3879,8 @@ class Formatter : public FormatterBase { ///@} }; -} // namespace CLI -// From Option.hpp: -namespace CLI { using results_t = std::vector; /// callback function definition @@ -3581,6 +4123,9 @@ class Option : public OptionBase