From 8e2c8f34fab7339d67e043b489741f05cf929a11 Mon Sep 17 00:00:00 2001 From: Ansh Date: Fri, 27 Oct 2023 23:12:17 +0530 Subject: [PATCH 01/28] feat: add accuracy measure for mlpack_logistic_regression --- .../logistic_regression_main.cpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index d2a842fa6d..10cfb676c6 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -23,7 +23,7 @@ using namespace mlpack; using namespace mlpack::util; // Program Name. -BINDING_USER_NAME("L2-regularized Logistic Regression and Prediction"); +BINDING_USER_NAME("L2-regularized Logistic Regression and Prediction"); // Short description. BINDING_SHORT_DESC( @@ -101,7 +101,7 @@ BINDING_EXAMPLE( PRINT_MODEL("lr_model") + "', the following command may be used:" "\n\n" + PRINT_CALL("logistic_regression", "training", "data", "labels", "labels", - "lambda", 0.1, "output_model", "lr_model") + + "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", true) + "\n\n" "Then, to use that model to predict classes for the dataset '" + PRINT_DATASET("test") + "', storing the output predictions in '" + @@ -153,6 +153,9 @@ PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " 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); +PARAM_FLAG("print_training_accuracy", "If set, then the accuracy of the model " + "on the training set will be predicted (verbose must also be specified).", + "a"); void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { @@ -182,6 +185,10 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) ReportIgnoredParam(params, {{ "test", false }}, "predictions"); ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{ "training", false }}, "print_training_accuracy"); + + RequireAtLeastOnePassed(params, { "test", "output_model", "print_training_accuracy" }, false, "the trained logistic regression model will not be used or saved"); + // Max Iterations needs to be positive. RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, true, "max_iterations must be positive or zero"); @@ -327,6 +334,22 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) } } + // Did we want training accuracy? + if (params.Has("print_training_accuracy")) + { + timers.Start("lr_prediction"); + arma::Row predictions; + model->Classify(regressors, predictions); + + const size_t correct = arma::accu(predictions == responses); + + Log::Info << correct << " of " << responses.n_elem << " correct on training" + << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." + << endl; + timers.Stop("lr_prediction"); + } + } + if (params.Has("test")) { const arma::mat& testSet = params.Get("test"); From a52bbcd32a72a4e602c993dc8333f5ce6a619e7e Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Fri, 27 Oct 2023 23:39:49 +0530 Subject: [PATCH 02/28] fix extra space --- .../methods/logistic_regression/logistic_regression_main.cpp | 2 +- src/mlpack/methods/random_forest/random_forest_main.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 10cfb676c6..a6b0c213ef 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -23,7 +23,7 @@ using namespace mlpack; using namespace mlpack::util; // Program Name. -BINDING_USER_NAME("L2-regularized Logistic Regression and Prediction"); +BINDING_USER_NAME("L2-regularized Logistic Regression and Prediction"); // Short description. BINDING_SHORT_DESC( diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index 41c43b42cf..aeb13c16ed 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -24,14 +24,14 @@ using namespace std; // Program Name. BINDING_USER_NAME("Random forests"); -// Short description. +// Short description BINDING_SHORT_DESC( "An implementation of the standard random forest algorithm by Leo Breiman " "for classification. Given labeled data, a random forest can be trained " "and saved for future use; or, a pre-trained random forest can be used for " "classification."); -// Long description. +// Long description BINDING_LONG_DESC( "This program is an implementation of the standard random forest " "classification algorithm by Leo Breiman. A random forest can be " From c18671547b13a55ff09d62a1d575871715bb59fc Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Fri, 27 Oct 2023 23:57:08 +0530 Subject: [PATCH 03/28] update history.md --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index f6d6316f2c..6fdb99068d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,8 @@ * Use HTTPS for all auto-downloaded dependencies (#3550). + * Feat: Add "print_training_accuracy" in logistic_regression_main.md ([#3552](https://github.com/mlpack/mlpack/issues/3552)) + ### mlpack 4.2.1 ###### 2023-09-05 * Reinforcement Learning: Gaussian noise (#3515). From 6b09706f84ffb541bb7febbb9bb17096d7350dfc Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Sun, 29 Oct 2023 07:28:33 +0530 Subject: [PATCH 04/28] predicted -> printed Co-authored-by: Ryan Curtin --- .../methods/logistic_regression/logistic_regression_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index a6b0c213ef..fd7e63fff5 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -154,7 +154,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); PARAM_FLAG("print_training_accuracy", "If set, then the accuracy of the model " - "on the training set will be predicted (verbose must also be specified).", + "on the training set will be printed (verbose must also be specified).", "a"); void BINDING_FUNCTION(util::Params& params, util::Timers& timers) From a44f04b53f45539e982755bca29565dc4c70ea35 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Sun, 29 Oct 2023 07:34:04 +0530 Subject: [PATCH 05/28] Update history.md Co-authored-by: Ryan Curtin --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 6fdb99068d..b70ed97af6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,7 +6,7 @@ * Use HTTPS for all auto-downloaded dependencies (#3550). - * Feat: Add "print_training_accuracy" in logistic_regression_main.md ([#3552](https://github.com/mlpack/mlpack/issues/3552)) + * Add `print_training_accuracy` option to LogisticRegression bindings (#3552). ### mlpack 4.2.1 ###### 2023-09-05 From 3ba2cbd7a51fcf986913f6235dd8669cc37c5dd9 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Sun, 29 Oct 2023 07:28:33 +0530 Subject: [PATCH 06/28] predicted -> printed Co-authored-by: Ryan Curtin --- .../methods/logistic_regression/logistic_regression_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index a6b0c213ef..fd7e63fff5 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -154,7 +154,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); PARAM_FLAG("print_training_accuracy", "If set, then the accuracy of the model " - "on the training set will be predicted (verbose must also be specified).", + "on the training set will be printed (verbose must also be specified).", "a"); void BINDING_FUNCTION(util::Params& params, util::Timers& timers) From d4bd0cdd05e8422f508237a72763f6cec88df5d1 Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Sun, 29 Oct 2023 07:46:31 +0530 Subject: [PATCH 07/28] fix unintended changes in random_forest_main.cpp --- .../logistic_regression_main.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index fd7e63fff5..71e3c16373 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -335,20 +335,20 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) } // Did we want training accuracy? - if (params.Has("print_training_accuracy")) - { - timers.Start("lr_prediction"); - arma::Row predictions; - model->Classify(regressors, predictions); + if (params.Has("print_training_accuracy")) + { + timers.Start("lr_prediction"); + arma::Row predictions; + model->Classify(regressors, predictions); - const size_t correct = arma::accu(predictions == responses); + const size_t correct = arma::accu(predictions == responses); - Log::Info << correct << " of " << responses.n_elem << " correct on training" - << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." - << endl; - timers.Stop("lr_prediction"); - } + Log::Info << correct << " of " << responses.n_elem << " correct on training" + << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." + << endl; + timers.Stop("lr_prediction"); } + if (params.Has("test")) { From be3e4698d3c581942b8f52f6e850ea4e075b6ddb Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Sun, 29 Oct 2023 07:47:17 +0530 Subject: [PATCH 08/28] fix extra indentation and remove extra brace --- src/mlpack/methods/random_forest/random_forest_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index aeb13c16ed..41c43b42cf 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -24,14 +24,14 @@ using namespace std; // Program Name. BINDING_USER_NAME("Random forests"); -// Short description +// Short description. BINDING_SHORT_DESC( "An implementation of the standard random forest algorithm by Leo Breiman " "for classification. Given labeled data, a random forest can be trained " "and saved for future use; or, a pre-trained random forest can be used for " "classification."); -// Long description +// Long description. BINDING_LONG_DESC( "This program is an implementation of the standard random forest " "classification algorithm by Leo Breiman. A random forest can be " From 1d62977053ff30a00db7daaf910653ac23d9933a Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Wed, 1 Nov 2023 22:26:08 +0530 Subject: [PATCH 09/28] fix line length Co-authored-by: Ryan Curtin --- .../methods/logistic_regression/logistic_regression_main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 71e3c16373..5a81407f1f 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -187,7 +187,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) ReportIgnoredParam(params, {{ "training", false }}, "print_training_accuracy"); - RequireAtLeastOnePassed(params, { "test", "output_model", "print_training_accuracy" }, false, "the trained logistic regression model will not be used or saved"); + RequireAtLeastOnePassed(params, + { "test", "output_model", "print_training_accuracy" }, false, + "the trained logistic regression model will not be used or saved"); // Max Iterations needs to be positive. RequireParamValue(params, "max_iterations", [](int x) { return x >= 0; }, From d639be1799773f8cd54aa464c1b26edbf90246f4 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Wed, 1 Nov 2023 22:26:23 +0530 Subject: [PATCH 10/28] Update src/mlpack/methods/logistic_regression/logistic_regression_main.cpp Co-authored-by: Ryan Curtin --- .../methods/logistic_regression/logistic_regression_main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 5a81407f1f..f2d9f04ddb 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -101,7 +101,8 @@ BINDING_EXAMPLE( PRINT_MODEL("lr_model") + "', the following command may be used:" "\n\n" + PRINT_CALL("logistic_regression", "training", "data", "labels", "labels", - "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", true) + + "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", + true) + "\n\n" "Then, to use that model to predict classes for the dataset '" + PRINT_DATASET("test") + "', storing the output predictions in '" + From c8ac8e42495f05560f9524215a915a397b5d8f30 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Wed, 1 Nov 2023 22:26:47 +0530 Subject: [PATCH 11/28] Update src/mlpack/methods/logistic_regression/logistic_regression_main.cpp Co-authored-by: Ryan Curtin --- .../methods/logistic_regression/logistic_regression_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index f2d9f04ddb..abc84b8c56 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -352,7 +352,6 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) timers.Stop("lr_prediction"); } - if (params.Has("test")) { const arma::mat& testSet = params.Get("test"); From bb779111a69642aa8cc460ab371b901bbb40718a Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Thu, 2 Nov 2023 02:24:28 +0530 Subject: [PATCH 12/28] add test for print_training_accuracy --- .../main_tests/logistic_regression_test.cpp | 155 ++++++++++-------- 1 file changed, 88 insertions(+), 67 deletions(-) diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index fee66b221e..b090fcff26 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -1,14 +1,14 @@ /** - * @file logistic_regression_test.cpp - * @author B Kartheek Reddy - * - * 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. - */ + * @file logistic_regression_test.cpp + * @author B Kartheek Reddy + * + * 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. + */ #define BINDING_TYPE BINDING_TYPE_TEST #include @@ -25,7 +25,7 @@ using namespace mlpack; BINDING_TEST_FIXTURE(LogisticRegressionTestFixture); /** - * Ensuring that absence of training data is checked. + * Ensuring that absence of training data is checked. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LogisticRegressionLRNoTrainingData", @@ -33,7 +33,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, { arma::Row trainY; // 10 responses. - trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; + trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; SetInputParam("labels", std::move(trainY)); @@ -72,7 +72,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", arma::mat trainX = arma::randu(D, N); arma::Row trainY; // 10 responses. - trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; + trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; arma::mat testX = arma::randu(D, M); SetInputParam("training", std::move(trainX)); @@ -83,7 +83,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", RUN_BINDING(); // Get the output predictions of the test data. - const arma::Row& testY = + const arma::Row &testY = params.Get>("predictions"); // Output predictions size must match the test data set size. @@ -92,7 +92,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", } /** - * Ensuring that the response size is checked. + * Ensuring that the response size is checked. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LogisticRegressionLRWrongResponseSizeTest", @@ -105,7 +105,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // Response vector with wrong size. // 8 responses - incorrect size. - trainY = { 0, 0, 1, 0, 1, 1, 1, 0 }; + trainY = {0, 0, 1, 0, 1, 1, 1, 0}; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -151,7 +151,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, RUN_BINDING(); // get the output - const arma::Row& testY2 = + const arma::Row &testY2 = params.Get>("predictions"); // Both solutions should be equal. @@ -174,7 +174,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // 10 responses. - trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; + trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; arma::mat testX = arma::randu(D, M); @@ -186,8 +186,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, RUN_BINDING(); // Get the output model obtained from training. - LogisticRegression<>* model = - params.Get*>("output_model"); + LogisticRegression<> *model = + params.Get *>("output_model"); // Get the output. const arma::Row testY1 = std::move(params.Get>("predictions")); @@ -202,7 +202,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, RUN_BINDING(); // Get the output. - const arma::Row& testY2 = + const arma::Row &testY2 = params.Get>("predictions"); // Both solutions must be equal. @@ -210,7 +210,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, } /** - * Checking for dimensionality of the test data set. + * Checking for dimensionality of the test data set. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData", "[LogisticRegressionMainTest][BindingTests]") @@ -222,10 +222,10 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData", arma::Row trainY; // 10 responses. - trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; + trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; // Test data with wrong dimensionality. - arma::mat testX = arma::randu(D-1, N); + arma::mat testX = arma::randu(D - 1, N); SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -248,7 +248,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", arma::mat trainX = arma::randu(D, N); arma::Row trainY; // 10 responses - trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; + trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -257,8 +257,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", RUN_BINDING(); // Get the output model obtained from training. - LogisticRegression<>* model = - params.Get*>("output_model"); + LogisticRegression<> *model = + params.Get *>("output_model"); // Reset the data passed. ResetSettings(); @@ -273,7 +273,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", } /** - * Ensuring that training responses contain only two classes (0 or 1). + * Ensuring that training responses contain only two classes (0 or 1). **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRTrainWithMoreThanTwoClasses", @@ -286,7 +286,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // 8 responses containing more than two classes. - trainY = { 0, 1, 0, 1, 2, 1, 3, 1 }; + trainY = {0, 1, 0, 1, 2, 1, 3, 1}; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -297,10 +297,10 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, } /** - * Ensuring that max iteration for optimizers is non negative. + * Ensuring that max iteration for optimizers is non negative. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, - "LRNonNegativeMaxIterationTest", + "LRNonNegativeMaxIterationTest", "[LogisticRegressionMainTest][BindingTests]") { constexpr int N = 10; @@ -310,7 +310,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // 10 responses. - trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; + trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -321,8 +321,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, } /** - * Ensuring that step size for optimizer is non negative. - **/ + * Ensuring that step size for optimizer is non negative. + **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", "[LogisticRegressionMainTest][BindingTests]") { @@ -333,7 +333,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", arma::Row trainY; // 10 responses. - trainY = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; + trainY = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -345,7 +345,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", } /** - * Ensuring that tolerance is non negative. + * Ensuring that tolerance is non negative. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", "[LogisticRegressionMainTest][BindingTests]") @@ -357,7 +357,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", arma::Row trainY; // 10 responses. - trainY = { 1, 1, 0, 1, 0, 0, 0, 1, 0, 1 }; + trainY = {1, 1, 0, 1, 0, 0, 0, 1, 0, 1}; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -368,7 +368,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", } /** - * Ensuring changing Maximum number of iterations changes the output model. + * Ensuring changing Maximum number of iterations changes the output model. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -380,7 +380,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", arma::Row trainY; // 10 responses. - trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; + trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -391,8 +391,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(params.Get*>("output_model") - ->Parameters()); + std::move(params.Get *>("output_model") + ->Parameters()); // Reset the settings. CleanMemory(); @@ -406,13 +406,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec& parameters2 = - params.Get*>("output_model")->Parameters(); + const arma::rowvec ¶meters2 = + params.Get *>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal // which ensures Max Iteration changes the output model. // arma::all function checks that each element of the vector is equal to zero. - if (arma::all((parameters1-parameters2) == 0)) + if (arma::all((parameters1 - parameters2) == 0)) { FAIL("parameters1 and parameters2 are equal. \ Parameter(Max Iteration) has no effect on the output"); @@ -420,7 +420,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", } /** - * Ensuring that lambda has some effects on the output. + * Ensuring that lambda has some effects on the output. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -432,7 +432,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", arma::Row trainY; // 10 responses. - trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; + trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -443,8 +443,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(params.Get*>("output_model") - ->Parameters()); + std::move(params.Get *>("output_model") + ->Parameters()); // Reset the settings. CleanMemory(); @@ -458,13 +458,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec& parameters2 = - params.Get*>("output_model")->Parameters(); + const arma::rowvec ¶meters2 = + params.Get *>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal // which ensures lambda changes the output model. // arma::all function checks that each element of the vector is equal to zero. - if (arma::all((parameters1-parameters2) == 0)) + if (arma::all((parameters1 - parameters2) == 0)) { FAIL("parameters1 and parameters2 are equal. \ Parameter(lambda) has no effect on the output"); @@ -472,7 +472,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", } /** - * Ensuring that Step size has some effects on the output. + * Ensuring that Step size has some effects on the output. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -484,7 +484,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", arma::Row trainY; // 10 responses. - trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; + trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -496,8 +496,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(params.Get*>("output_model") - ->Parameters()); + std::move(params.Get *>("output_model") + ->Parameters()); // Reset the settings. CleanMemory(); @@ -512,13 +512,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec& parameters2 = - params.Get*>("output_model")->Parameters(); + const arma::rowvec ¶meters2 = + params.Get *>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal // which ensures Step Size changes the output model. // arma::all function checks that each element of the vector is equal to zero. - 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"); @@ -526,7 +526,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", } /** - * Ensuring that lbfgs optimizer converges to a different result than sgd. + * Ensuring that lbfgs optimizer converges to a different result than sgd. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -538,7 +538,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", arma::Row trainY; // 10 responses. - trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; + trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -550,7 +550,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = std::move( - params.Get*>("output_model")->Parameters()); + params.Get *>("output_model")->Parameters()); // Reset the settings. CleanMemory(); @@ -565,8 +565,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec& parameters2 = - params.Get*>("output_model")->Parameters(); + const arma::rowvec ¶meters2 = + params.Get *>("output_model")->Parameters(); // Check that the parameters (parameters1 and parameters2) are not equal which // ensures that different optimizer converge to different results. @@ -579,7 +579,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", } /** - * Ensuring decision_boundary parameter does something. + * Ensuring decision_boundary parameter does something. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", "[LogisticRegressionMainTest][BindingTests]") @@ -592,7 +592,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", arma::Row trainY; // 10 responses. - trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; + trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; arma::mat testX = arma::randu(D, M); @@ -621,9 +621,30 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", RUN_BINDING(); // Get the output after second training. - const arma::Row& output2 = + const arma::Row &output2 = params.Get>("predictions"); // Check that the output changed when the decision boundary moved. REQUIRE(arma::accu(output1 != output2) > 0); -} + + /** + * Check that running the binding with print_training_accuracy set to true + * does not crash. + */ + TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPrintTrainingAccuracyTest", + "[LogisticRegressionMainTest][BindingTests]") + { + constexpr int N = 100; + constexpr int D = 5; + + arma::mat trainX = arma::randu(D, N); + arma::Row trainY(N, arma::fill::randu); + + SetInputParam("training", trainX); + SetInputParam("labels", trainY); + SetInputParam("print_training_accuracy", true); + + // Run the binding with print_training_accuracy set to true. + REQUIRE_NOTHROW(RUN_BINDING()); + } +} \ No newline at end of file From 486d7831796e513b987897cbcba2cc65ea4c49e1 Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Thu, 2 Nov 2023 02:30:12 +0530 Subject: [PATCH 13/28] Revert "add test for print_training_accuracy" This reverts commit bb779111a69642aa8cc460ab371b901bbb40718a. --- .../main_tests/logistic_regression_test.cpp | 155 ++++++++---------- 1 file changed, 67 insertions(+), 88 deletions(-) diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index b090fcff26..fee66b221e 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -1,14 +1,14 @@ /** - * @file logistic_regression_test.cpp - * @author B Kartheek Reddy - * - * 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. - */ + * @file logistic_regression_test.cpp + * @author B Kartheek Reddy + * + * 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. + */ #define BINDING_TYPE BINDING_TYPE_TEST #include @@ -25,7 +25,7 @@ using namespace mlpack; BINDING_TEST_FIXTURE(LogisticRegressionTestFixture); /** - * Ensuring that absence of training data is checked. + * Ensuring that absence of training data is checked. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LogisticRegressionLRNoTrainingData", @@ -33,7 +33,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, { arma::Row trainY; // 10 responses. - trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; + trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; SetInputParam("labels", std::move(trainY)); @@ -72,7 +72,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", arma::mat trainX = arma::randu(D, N); arma::Row trainY; // 10 responses. - trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; + trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; arma::mat testX = arma::randu(D, M); SetInputParam("training", std::move(trainX)); @@ -83,7 +83,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", RUN_BINDING(); // Get the output predictions of the test data. - const arma::Row &testY = + const arma::Row& testY = params.Get>("predictions"); // Output predictions size must match the test data set size. @@ -92,7 +92,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPridictionSizeCheck", } /** - * Ensuring that the response size is checked. + * Ensuring that the response size is checked. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LogisticRegressionLRWrongResponseSizeTest", @@ -105,7 +105,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // Response vector with wrong size. // 8 responses - incorrect size. - trainY = {0, 0, 1, 0, 1, 1, 1, 0}; + trainY = { 0, 0, 1, 0, 1, 1, 1, 0 }; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -151,7 +151,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, RUN_BINDING(); // get the output - const arma::Row &testY2 = + const arma::Row& testY2 = params.Get>("predictions"); // Both solutions should be equal. @@ -174,7 +174,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // 10 responses. - trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; + trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; arma::mat testX = arma::randu(D, M); @@ -186,8 +186,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, RUN_BINDING(); // Get the output model obtained from training. - LogisticRegression<> *model = - params.Get *>("output_model"); + LogisticRegression<>* model = + params.Get*>("output_model"); // Get the output. const arma::Row testY1 = std::move(params.Get>("predictions")); @@ -202,7 +202,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, RUN_BINDING(); // Get the output. - const arma::Row &testY2 = + const arma::Row& testY2 = params.Get>("predictions"); // Both solutions must be equal. @@ -210,7 +210,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, } /** - * Checking for dimensionality of the test data set. + * Checking for dimensionality of the test data set. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData", "[LogisticRegressionMainTest][BindingTests]") @@ -222,10 +222,10 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData", arma::Row trainY; // 10 responses. - trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; + trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; // Test data with wrong dimensionality. - arma::mat testX = arma::randu(D - 1, N); + arma::mat testX = arma::randu(D-1, N); SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -248,7 +248,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", arma::mat trainX = arma::randu(D, N); arma::Row trainY; // 10 responses - trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; + trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -257,8 +257,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", RUN_BINDING(); // Get the output model obtained from training. - LogisticRegression<> *model = - params.Get *>("output_model"); + LogisticRegression<>* model = + params.Get*>("output_model"); // Reset the data passed. ResetSettings(); @@ -273,7 +273,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRWrongDimOfTestData2", } /** - * Ensuring that training responses contain only two classes (0 or 1). + * Ensuring that training responses contain only two classes (0 or 1). **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRTrainWithMoreThanTwoClasses", @@ -286,7 +286,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // 8 responses containing more than two classes. - trainY = {0, 1, 0, 1, 2, 1, 3, 1}; + trainY = { 0, 1, 0, 1, 2, 1, 3, 1 }; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -297,10 +297,10 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, } /** - * Ensuring that max iteration for optimizers is non negative. + * Ensuring that max iteration for optimizers is non negative. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, - "LRNonNegativeMaxIterationTest", + "LRNonNegativeMaxIterationTest", "[LogisticRegressionMainTest][BindingTests]") { constexpr int N = 10; @@ -310,7 +310,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, arma::Row trainY; // 10 responses. - trainY = {0, 1, 0, 1, 1, 1, 0, 1, 0, 0}; + trainY = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 0 }; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -321,8 +321,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, } /** - * Ensuring that step size for optimizer is non negative. - **/ + * Ensuring that step size for optimizer is non negative. + **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", "[LogisticRegressionMainTest][BindingTests]") { @@ -333,7 +333,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", arma::Row trainY; // 10 responses. - trainY = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; + trainY = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -345,7 +345,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeStepSizeTest", } /** - * Ensuring that tolerance is non negative. + * Ensuring that tolerance is non negative. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", "[LogisticRegressionMainTest][BindingTests]") @@ -357,7 +357,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", arma::Row trainY; // 10 responses. - trainY = {1, 1, 0, 1, 0, 0, 0, 1, 0, 1}; + trainY = { 1, 1, 0, 1, 0, 0, 0, 1, 0, 1 }; SetInputParam("training", std::move(trainX)); SetInputParam("labels", std::move(trainY)); @@ -368,7 +368,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRNonNegativeToleranceTest", } /** - * Ensuring changing Maximum number of iterations changes the output model. + * Ensuring changing Maximum number of iterations changes the output model. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -380,7 +380,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", arma::Row trainY; // 10 responses. - trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -391,8 +391,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(params.Get *>("output_model") - ->Parameters()); + std::move(params.Get*>("output_model") + ->Parameters()); // Reset the settings. CleanMemory(); @@ -406,13 +406,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - params.Get *>("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. // 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(Max Iteration) has no effect on the output"); @@ -420,7 +420,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRMaxIterationsChangeTest", } /** - * Ensuring that lambda has some effects on the output. + * Ensuring that lambda has some effects on the output. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -432,7 +432,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", arma::Row trainY; // 10 responses. - trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -443,8 +443,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(params.Get *>("output_model") - ->Parameters()); + std::move(params.Get*>("output_model") + ->Parameters()); // Reset the settings. CleanMemory(); @@ -458,13 +458,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - params.Get *>("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. // 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(lambda) has no effect on the output"); @@ -472,7 +472,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRLambdaChangeTest", } /** - * Ensuring that Step size has some effects on the output. + * Ensuring that Step size has some effects on the output. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -484,7 +484,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", arma::Row trainY; // 10 responses. - trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -496,8 +496,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = - std::move(params.Get *>("output_model") - ->Parameters()); + std::move(params.Get*>("output_model") + ->Parameters()); // Reset the settings. CleanMemory(); @@ -512,13 +512,13 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - params.Get *>("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. // 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"); @@ -526,7 +526,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRStepSizeChangeTest", } /** - * Ensuring that lbfgs optimizer converges to a different result than sgd. + * Ensuring that lbfgs optimizer converges to a different result than sgd. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", "[LogisticRegressionMainTest][BindingTests]") @@ -538,7 +538,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", arma::Row trainY; // 10 responses. - trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; SetInputParam("training", trainX); SetInputParam("labels", trainY); @@ -550,7 +550,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", // Get the parameters of the output model obtained after first training. const arma::rowvec parameters1 = std::move( - params.Get *>("output_model")->Parameters()); + params.Get*>("output_model")->Parameters()); // Reset the settings. CleanMemory(); @@ -565,8 +565,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", RUN_BINDING(); // Get the parameters of the output model obtained after second training. - const arma::rowvec ¶meters2 = - params.Get *>("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. @@ -579,7 +579,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LROptimizerChangeTest", } /** - * Ensuring decision_boundary parameter does something. + * Ensuring decision_boundary parameter does something. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", "[LogisticRegressionMainTest][BindingTests]") @@ -592,7 +592,7 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", arma::Row trainY; // 10 responses. - trainY = {1, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + trainY = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 }; arma::mat testX = arma::randu(D, M); @@ -621,30 +621,9 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", RUN_BINDING(); // Get the output after second training. - const arma::Row &output2 = + const arma::Row& output2 = params.Get>("predictions"); // Check that the output changed when the decision boundary moved. REQUIRE(arma::accu(output1 != output2) > 0); - - /** - * Check that running the binding with print_training_accuracy set to true - * does not crash. - */ - TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPrintTrainingAccuracyTest", - "[LogisticRegressionMainTest][BindingTests]") - { - constexpr int N = 100; - constexpr int D = 5; - - arma::mat trainX = arma::randu(D, N); - arma::Row trainY(N, arma::fill::randu); - - SetInputParam("training", trainX); - SetInputParam("labels", trainY); - SetInputParam("print_training_accuracy", true); - - // Run the binding with print_training_accuracy set to true. - REQUIRE_NOTHROW(RUN_BINDING()); - } -} \ No newline at end of file +} From 94b0c5df68c1568d7ff7ed05a79162bcc38cc781 Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Thu, 2 Nov 2023 02:31:50 +0530 Subject: [PATCH 14/28] add test for print_training_accuracy --- .../main_tests/logistic_regression_test.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index fee66b221e..11fbc4459e 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -626,4 +626,25 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", // Check that the output changed when the decision boundary moved. REQUIRE(arma::accu(output1 != output2) > 0); + + /** + * Check that running the binding with print_training_accuracy set to true + * does not crash. + */ + TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPrintTrainingAccuracyTest", + "[LogisticRegressionMainTest][BindingTests]") + { + constexpr int N = 100; + constexpr int D = 5; + + arma::mat trainX = arma::randu(D, N); + arma::Row trainY(N, arma::fill::randu); + + SetInputParam("training", trainX); + SetInputParam("labels", trainY); + SetInputParam("print_training_accuracy", true); + + // Run the binding with print_training_accuracy set to true. + REQUIRE_NOTHROW(RUN_BINDING()); + } } From 9f0bc8e0c57c9537f824713fed9b24a671db4188 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Tue, 14 Nov 2023 13:50:24 +0530 Subject: [PATCH 15/28] Make the test better Co-authored-by: Ryan Curtin --- src/mlpack/tests/main_tests/logistic_regression_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index 11fbc4459e..12493cd291 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -638,7 +638,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", constexpr int D = 5; arma::mat trainX = arma::randu(D, N); - arma::Row trainY(N, arma::fill::randu); + arma::Row trainY = arma::randi>(N, + arma::distr_param(0, 1)); SetInputParam("training", trainX); SetInputParam("labels", trainY); From 2136e71844c80829fb60b12ddaaee20501640c75 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:40:34 +0530 Subject: [PATCH 16/28] Fix test --- .../main_tests/logistic_regression_test.cpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index 12493cd291..d0f27851ea 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -626,26 +626,26 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", // Check that the output changed when the decision boundary moved. REQUIRE(arma::accu(output1 != output2) > 0); - - /** - * Check that running the binding with print_training_accuracy set to true - * does not crash. - */ - TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPrintTrainingAccuracyTest", - "[LogisticRegressionMainTest][BindingTests]") - { - constexpr int N = 100; - constexpr int D = 5; - - arma::mat trainX = arma::randu(D, N); - arma::Row trainY = arma::randi>(N, - arma::distr_param(0, 1)); - - SetInputParam("training", trainX); - SetInputParam("labels", trainY); - SetInputParam("print_training_accuracy", true); - - // Run the binding with print_training_accuracy set to true. - REQUIRE_NOTHROW(RUN_BINDING()); - } +} + +/** + * Check that running the binding with print_training_accuracy set to true + * does not crash. + **/ +TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPrintTrainingAccuracyTest", + "[LogisticRegressionMainTest][BindingTests]") +{ + constexpr int N = 100; + constexpr int D = 5; + + arma::mat trainX = arma::randu(D, N); + arma::Row trainY = arma::randi>(N, + arma::distr_param(0, 1)); + + SetInputParam("training", trainX); + SetInputParam("labels", trainY); + SetInputParam("print_training_accuracy", true); + + // Run the binding with print_training_accuracy set to true. + REQUIRE_NOTHROW(RUN_BINDING()); } From 4124230c3f090c585586ac787def42f146b857c6 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Sat, 25 Nov 2023 03:03:03 +0530 Subject: [PATCH 17/28] update spacing Co-authored-by: Ryan Curtin --- src/mlpack/tests/main_tests/logistic_regression_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/tests/main_tests/logistic_regression_test.cpp b/src/mlpack/tests/main_tests/logistic_regression_test.cpp index d0f27851ea..d832ca56ad 100644 --- a/src/mlpack/tests/main_tests/logistic_regression_test.cpp +++ b/src/mlpack/tests/main_tests/logistic_regression_test.cpp @@ -629,8 +629,8 @@ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRDecisionBoundaryTest", } /** - * Check that running the binding with print_training_accuracy set to true - * does not crash. + * Check that running the binding with print_training_accuracy set to true + * does not crash. **/ TEST_CASE_METHOD(LogisticRegressionTestFixture, "LRPrintTrainingAccuracyTest", "[LogisticRegressionMainTest][BindingTests]") From 7292509d7fd5867fa18faac098f7162ed5cb2097 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Sat, 25 Nov 2023 03:26:36 +0530 Subject: [PATCH 18/28] add suggestions --- .../methods/logistic_regression/logistic_regression_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index abc84b8c56..25cb7bca9c 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -338,7 +338,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) } // Did we want training accuracy? - if (params.Has("print_training_accuracy")) + if (params.Has("training") && params.Has("print_training_accuracy")) { timers.Start("lr_prediction"); arma::Row predictions; From cd71fbbadb0e1f3ddd11921a5d6e8b90724231dd Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Tue, 28 Nov 2023 10:34:45 +0530 Subject: [PATCH 19/28] fixed --- .../logistic_regression_main.cpp | 250 ++++++++++-------- 1 file changed, 140 insertions(+), 110 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 25cb7bca9c..5b984afce6 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -43,195 +43,225 @@ BINDING_LONG_DESC( "\n\n" "This program allows loading a logistic regression model (via the " + PRINT_PARAM_STRING("input_model") + " parameter) " - "or training a logistic regression model given training data (specified " - "with the " + PRINT_PARAM_STRING("training") + " parameter), or both " - "those things at once. In addition, this program allows classification on " - "a test dataset (specified with the " + PRINT_PARAM_STRING("test") + " " - "parameter) and the classification results may be saved with the " + + "or training a logistic regression model given training data (specified " + "with the " + + PRINT_PARAM_STRING("training") + " parameter), or both " + "those things at once. In addition, this program allows classification on " + "a test dataset (specified with the " + + PRINT_PARAM_STRING("test") + " " + "parameter) and the classification results may be saved with the " + PRINT_PARAM_STRING("predictions") + " output parameter." - " The trained logistic regression model may be saved using the " + + " The trained logistic regression model may be saved using the " + PRINT_PARAM_STRING("output_model") + " output parameter." - "\n\n" - "The training data, if specified, may have class labels as its last " - "dimension. Alternately, the " + PRINT_PARAM_STRING("labels") + " " - "parameter may be used to specify a separate matrix of labels." - "\n\n" - "When a model is being trained, there are many options. L2 regularization " - "(to prevent overfitting) can be specified with the " + + "\n\n" + "The training data, if specified, may have class labels as its last " + "dimension. Alternately, the " + + PRINT_PARAM_STRING("labels") + " " + "parameter may be used to specify a separate matrix of labels." + "\n\n" + "When a model is being trained, there are many options. L2 regularization " + "(to prevent overfitting) can be specified with the " + PRINT_PARAM_STRING("lambda") + " option, and the " - "optimizer used to train the model can be specified with the " + + "optimizer used to train the model can be specified with the " + PRINT_PARAM_STRING("optimizer") + " parameter. Available options are " - "'sgd' (stochastic gradient descent) and 'lbfgs' (the L-BFGS optimizer). " - "There are also various parameters for the optimizer; the " + + "'sgd' (stochastic gradient descent) and 'lbfgs' (the L-BFGS optimizer). " + "There are also various parameters for the optimizer; the " + PRINT_PARAM_STRING("max_iterations") + " parameter specifies the maximum " - "number of allowed iterations, and the " + + "number of allowed iterations, and the " + PRINT_PARAM_STRING("tolerance") + " parameter specifies the tolerance for " - "convergence. For the SGD optimizer, the " + + "convergence. For the SGD optimizer, the " + PRINT_PARAM_STRING("step_size") + " parameter controls the step size taken " - "at each iteration by the optimizer. The batch size for SGD is controlled " - "with the " + PRINT_PARAM_STRING("batch_size") + " parameter. If the " - "objective function for your data is oscillating between Inf and 0, the " - "step size is probably too large. There are more parameters for the " - "optimizers, but the C++ interface must be used to access these." - "\n\n" - "For SGD, an iteration refers to a single point. So to take a single pass " - "over the dataset with SGD, " + PRINT_PARAM_STRING("max_iterations") + + "at each iteration by the optimizer. The batch size for SGD is controlled " + "with the " + + PRINT_PARAM_STRING("batch_size") + " parameter. If the " + "objective function for your data is oscillating between Inf and 0, the " + "step size is probably too large. There are more parameters for the " + "optimizers, but the C++ interface must be used to access these." + "\n\n" + "For SGD, an iteration refers to a single point. So to take a single pass " + "over the dataset with SGD, " + + PRINT_PARAM_STRING("max_iterations") + " should be set to the number of points in the dataset." "\n\n" "Optionally, the model can be used to predict the responses for another " - "matrix of data points, if " + PRINT_PARAM_STRING("test") + " is " - "specified. The " + PRINT_PARAM_STRING("test") + " parameter can be " - "specified without the " + PRINT_PARAM_STRING("training") + " parameter, " - "so long as an existing logistic regression model is given with the " + + "matrix of data points, if " + + PRINT_PARAM_STRING("test") + " is " + "specified. The " + + PRINT_PARAM_STRING("test") + " parameter can be " + "specified without the " + + PRINT_PARAM_STRING("training") + " parameter, " + "so long as an existing logistic regression model is given with the " + PRINT_PARAM_STRING("input_model") + " parameter. The output predictions " - "from the logistic regression model may be saved with the " + + "from the logistic regression model may be saved with the " + PRINT_PARAM_STRING("predictions") + " parameter." + "\n\n" "This implementation of logistic regression does not support the general " "multi-class case but instead only the two-class case. Any labels must be " - "either " + STRINGIFY(BINDING_MIN_LABEL) + " or " + + "either " + + STRINGIFY(BINDING_MIN_LABEL) + " or " + std::to_string(BINDING_MIN_LABEL + 1) + ". For more classes, see the " - "softmax regression implementation."); + "softmax regression implementation."); // Example. BINDING_EXAMPLE( "As an example, to train a logistic regression model on the data '" + PRINT_DATASET("data") + "' with labels '" + PRINT_DATASET("labels") + "' " - "with L2 regularization of 0.1, saving the model to '" + + "with L2 regularization of 0.1, saving the model to '" + PRINT_MODEL("lr_model") + "', the following command may be used:" - "\n\n" + + "\n\n" + PRINT_CALL("logistic_regression", "training", "data", "labels", "labels", - "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", - true) + + "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", + true) + "\n\n" "Then, to use that model to predict classes for the dataset '" + PRINT_DATASET("test") + "', storing the output predictions in '" + PRINT_DATASET("predictions") + "', the following command may be used: " - "\n\n" + + "\n\n" + PRINT_CALL("logistic_regression", "input_model", "lr_model", "test", "test", - "predictions", "predictions")); + "predictions", "predictions")); // See also... BINDING_SEE_ALSO("@softmax_regression", "#softmax_regression"); BINDING_SEE_ALSO("@random_forest", "#random_forest"); BINDING_SEE_ALSO("Logistic regression on Wikipedia", - "https://en.wikipedia.org/wiki/Logistic_regression"); + "https://en.wikipedia.org/wiki/Logistic_regression"); BINDING_SEE_ALSO(":LogisticRegression C++ class documentation", - "@src/mlpack/methods/logistic_regression/logistic_regression.hpp"); + "@src/mlpack/methods/logistic_regression/logistic_regression.hpp"); // Training parameters. PARAM_MATRIX_IN("training", "A matrix containing the training set (the matrix " - "of predictors, X).", "t"); + "of predictors, X).", + "t"); PARAM_UROW_IN("labels", "A matrix containing labels (0 or 1) for the points " - "in the training set (y).", "l"); + "in the training set (y).", + "l"); // Optimizer parameters. PARAM_DOUBLE_IN("lambda", "L2-regularization parameter for training.", "L", - 0.0); + 0.0); PARAM_STRING_IN("optimizer", "Optimizer to use for training ('lbfgs' or " - "'sgd').", "O", "lbfgs"); + "'sgd').", + "O", "lbfgs"); PARAM_DOUBLE_IN("tolerance", "Convergence tolerance for optimizer.", "e", - 1e-10); + 1e-10); PARAM_INT_IN("max_iterations", "Maximum iterations for optimizer (0 indicates " - "no limit).", "n", 10000); + "no limit).", + "n", 10000); PARAM_DOUBLE_IN("step_size", "Step size for SGD optimizer.", - "s", 0.01); + "s", 0.01); PARAM_INT_IN("batch_size", "Batch size for SGD.", "b", 64); // Model loading/saving. PARAM_MODEL_IN(LogisticRegression<>, "input_model", "Existing model " - "(parameters).", "m"); + "(parameters).", + "m"); PARAM_MODEL_OUT(LogisticRegression<>, "output_model", "Output for trained " - "logistic regression model.", "M"); + "logistic regression model.", + "M"); // Testing. PARAM_MATRIX_IN("test", "Matrix containing test dataset.", "T"); PARAM_UROW_OUT("predictions", "If test data is specified, this matrix is where " - "the predictions for the test set will be saved.", "P"); + "the predictions for the test set will be saved.", + "P"); PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " - "matrix is where the class probabilities for the test set will be saved.", - "p"); + "matrix is where the class probabilities for the test set will be saved.", + "p"); 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); + "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); PARAM_FLAG("print_training_accuracy", "If set, then the accuracy of the model " - "on the training set will be printed (verbose must also be specified).", - "a"); + "on the training set will be printed (verbose must also be specified).", + "a"); -void BINDING_FUNCTION(util::Params& params, util::Timers& timers) +void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) { // Collect command-line options. 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 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(params, { "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 (params.Has("training")) { - RequireAtLeastOnePassed(params, { "output_model" }, false, "trained model " - "will not be saved"); + RequireAtLeastOnePassed(params, {"output_model"}, false, "trained model " + "will not be saved"); } - RequireAtLeastOnePassed(params, { "output_model", "predictions", - "probabilities"}, false, "no output will be saved"); + RequireAtLeastOnePassed(params, {"output_model", "predictions", "probabilities"}, false, "no output will be saved"); - ReportIgnoredParam(params, {{ "test", false }}, "predictions"); - ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{"test", false}}, "predictions"); + ReportIgnoredParam(params, {{"test", false}}, "probabilities"); + + ReportIgnoredParam(params, {{"training", false}}, "print_training_accuracy"); - ReportIgnoredParam(params, {{ "training", false }}, "print_training_accuracy"); - RequireAtLeastOnePassed(params, - { "test", "output_model", "print_training_accuracy" }, false, - "the trained logistic regression model will not be used or saved"); + {"test", "output_model", "print_training_accuracy"}, false, + "the trained logistic regression model will not be used or saved"); // Max Iterations needs to be positive. - RequireParamValue(params, "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(params, "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(params, "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(params, "optimizer", { "lbfgs", "sgd" }, - true, "unknown optimizer"); + RequireParamInSet(params, "optimizer", {"lbfgs", "sgd"}, + true, "unknown optimizer"); // Lambda must be positive. - RequireParamValue(params, "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(params, "decision_boundary", - [](double x) { return x >= 0.0 && x <= 1.0; }, true, + 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(params, "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 (params.Has("step_size")) { Log::Warn << PRINT_PARAM_STRING("step_size") << " ignored because " - << "optimizer type is not 'sgd'." << std::endl; + << "optimizer type is not 'sgd'." << std::endl; } if (params.Has("batch_size")) { Log::Warn << PRINT_PARAM_STRING("batch_size") << " ignored because " - << "optimizer type is not 'sgd'." << std::endl; + << "optimizer type is not 'sgd'." << std::endl; } } @@ -246,9 +276,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) regressors = std::move(params.Get("training")); // Load the model, if necessary. - LogisticRegression<>* model; + LogisticRegression<> *model; if (params.Has("input_model")) - model = params.Get*>("input_model"); + model = params.Get *>("input_model"); else { model = new LogisticRegression<>(0, 0); @@ -271,7 +301,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) delete model; Log::Fatal << "The labels must have the same number of points as the " - << "training dataset." << endl; + << "training dataset." << endl; } } else if (params.Has("training")) @@ -284,7 +314,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) delete model; Log::Fatal << "Can't get responses from training data since it has less " - << "than 2 rows." << endl; + << "than 2 rows." << endl; } // The initial predictors for y, Nx1. @@ -301,7 +331,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) delete model; Log::Fatal << "The labels must be either 0 or 1, not " << max(responses) - << "!" << endl; + << "!" << endl; } // Now, do the training. @@ -309,6 +339,21 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { model->Lambda() = lambda; + // Did we want training accuracy? + if (params.Has("print_training_accuracy")) + { + timers.Start("lr_prediction"); + arma::Row predictions; + model->Classify(regressors, predictions); + + const size_t correct = arma::accu(predictions == responses); + + Log::Info << correct << " of " << responses.n_elem << " correct on training" + << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." + << endl; + timers.Stop("lr_prediction"); + } + if (optimizerType == "sgd") { ens::SGD<> sgdOpt; @@ -337,24 +382,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) } } - // Did we want training accuracy? - if (params.Has("training") && params.Has("print_training_accuracy")) - { - timers.Start("lr_prediction"); - arma::Row predictions; - model->Classify(regressors, predictions); - - const size_t correct = arma::accu(predictions == responses); - - Log::Info << correct << " of " << responses.n_elem << " correct on training" - << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." - << endl; - timers.Stop("lr_prediction"); - } - if (params.Has("test")) { - const arma::mat& testSet = params.Get("test"); + const arma::mat &testSet = params.Get("test"); // Checking the dimensionality of the test data. if (testSet.n_rows != model->Parameters().n_cols - 1) @@ -365,8 +395,8 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) delete model; Log::Fatal << "Test data dimensionality (" << testSet.n_rows << ") must " - << "be the same as the dimensionality of the training data (" - << trainingDimensionality << ")!" << endl; + << "be the same as the dimensionality of the training data (" + << trainingDimensionality << ")!" << endl; } // We must perform predictions on the test set. Training (and the @@ -374,7 +404,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) if (params.Has("predictions")) { Log::Info << "Predicting classes of points in '" - << params.GetPrintable("test") << "'." << endl; + << params.GetPrintable("test") << "'." << endl; model->Classify(testSet, predictions, decisionBoundary); if (params.Has("predictions")) @@ -384,7 +414,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) if (params.Has("probabilities")) { Log::Info << "Calculating class probabilities of points in '" - << params.GetPrintable("test") << "'." << endl; + << params.GetPrintable("test") << "'." << endl; arma::mat probabilities; model->Classify(testSet, probabilities); @@ -393,5 +423,5 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) } } - params.Get*>("output_model") = model; + params.Get *>("output_model") = model; } From a602816ce75ad7370897cd39437dae04bec2d865 Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Wed, 29 Nov 2023 02:23:26 +0530 Subject: [PATCH 20/28] Revert "fixed" This reverts commit cd71fbbadb0e1f3ddd11921a5d6e8b90724231dd. --- .../logistic_regression_main.cpp | 250 ++++++++---------- 1 file changed, 110 insertions(+), 140 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 5b984afce6..25cb7bca9c 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -43,225 +43,195 @@ BINDING_LONG_DESC( "\n\n" "This program allows loading a logistic regression model (via the " + PRINT_PARAM_STRING("input_model") + " parameter) " - "or training a logistic regression model given training data (specified " - "with the " + - PRINT_PARAM_STRING("training") + " parameter), or both " - "those things at once. In addition, this program allows classification on " - "a test dataset (specified with the " + - PRINT_PARAM_STRING("test") + " " - "parameter) and the classification results may be saved with the " + + "or training a logistic regression model given training data (specified " + "with the " + PRINT_PARAM_STRING("training") + " parameter), or both " + "those things at once. In addition, this program allows classification on " + "a test dataset (specified with the " + PRINT_PARAM_STRING("test") + " " + "parameter) and the classification results may be saved with the " + PRINT_PARAM_STRING("predictions") + " output parameter." - " The trained logistic regression model may be saved using the " + + " The trained logistic regression model may be saved using the " + PRINT_PARAM_STRING("output_model") + " output parameter." - "\n\n" - "The training data, if specified, may have class labels as its last " - "dimension. Alternately, the " + - PRINT_PARAM_STRING("labels") + " " - "parameter may be used to specify a separate matrix of labels." - "\n\n" - "When a model is being trained, there are many options. L2 regularization " - "(to prevent overfitting) can be specified with the " + + "\n\n" + "The training data, if specified, may have class labels as its last " + "dimension. Alternately, the " + PRINT_PARAM_STRING("labels") + " " + "parameter may be used to specify a separate matrix of labels." + "\n\n" + "When a model is being trained, there are many options. L2 regularization " + "(to prevent overfitting) can be specified with the " + PRINT_PARAM_STRING("lambda") + " option, and the " - "optimizer used to train the model can be specified with the " + + "optimizer used to train the model can be specified with the " + PRINT_PARAM_STRING("optimizer") + " parameter. Available options are " - "'sgd' (stochastic gradient descent) and 'lbfgs' (the L-BFGS optimizer). " - "There are also various parameters for the optimizer; the " + + "'sgd' (stochastic gradient descent) and 'lbfgs' (the L-BFGS optimizer). " + "There are also various parameters for the optimizer; the " + PRINT_PARAM_STRING("max_iterations") + " parameter specifies the maximum " - "number of allowed iterations, and the " + + "number of allowed iterations, and the " + PRINT_PARAM_STRING("tolerance") + " parameter specifies the tolerance for " - "convergence. For the SGD optimizer, the " + + "convergence. For the SGD optimizer, the " + PRINT_PARAM_STRING("step_size") + " parameter controls the step size taken " - "at each iteration by the optimizer. The batch size for SGD is controlled " - "with the " + - PRINT_PARAM_STRING("batch_size") + " parameter. If the " - "objective function for your data is oscillating between Inf and 0, the " - "step size is probably too large. There are more parameters for the " - "optimizers, but the C++ interface must be used to access these." - "\n\n" - "For SGD, an iteration refers to a single point. So to take a single pass " - "over the dataset with SGD, " + - PRINT_PARAM_STRING("max_iterations") + + "at each iteration by the optimizer. The batch size for SGD is controlled " + "with the " + PRINT_PARAM_STRING("batch_size") + " parameter. If the " + "objective function for your data is oscillating between Inf and 0, the " + "step size is probably too large. There are more parameters for the " + "optimizers, but the C++ interface must be used to access these." + "\n\n" + "For SGD, an iteration refers to a single point. So to take a single pass " + "over the dataset with SGD, " + PRINT_PARAM_STRING("max_iterations") + " should be set to the number of points in the dataset." "\n\n" "Optionally, the model can be used to predict the responses for another " - "matrix of data points, if " + - PRINT_PARAM_STRING("test") + " is " - "specified. The " + - PRINT_PARAM_STRING("test") + " parameter can be " - "specified without the " + - PRINT_PARAM_STRING("training") + " parameter, " - "so long as an existing logistic regression model is given with the " + + "matrix of data points, if " + PRINT_PARAM_STRING("test") + " is " + "specified. The " + PRINT_PARAM_STRING("test") + " parameter can be " + "specified without the " + PRINT_PARAM_STRING("training") + " parameter, " + "so long as an existing logistic regression model is given with the " + PRINT_PARAM_STRING("input_model") + " parameter. The output predictions " - "from the logistic regression model may be saved with the " + + "from the logistic regression model may be saved with the " + PRINT_PARAM_STRING("predictions") + " parameter." + "\n\n" "This implementation of logistic regression does not support the general " "multi-class case but instead only the two-class case. Any labels must be " - "either " + - STRINGIFY(BINDING_MIN_LABEL) + " or " + + "either " + STRINGIFY(BINDING_MIN_LABEL) + " or " + std::to_string(BINDING_MIN_LABEL + 1) + ". For more classes, see the " - "softmax regression implementation."); + "softmax regression implementation."); // Example. BINDING_EXAMPLE( "As an example, to train a logistic regression model on the data '" + PRINT_DATASET("data") + "' with labels '" + PRINT_DATASET("labels") + "' " - "with L2 regularization of 0.1, saving the model to '" + + "with L2 regularization of 0.1, saving the model to '" + PRINT_MODEL("lr_model") + "', the following command may be used:" - "\n\n" + + "\n\n" + PRINT_CALL("logistic_regression", "training", "data", "labels", "labels", - "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", - true) + + "lambda", 0.1, "output_model", "lr_model", "print_training_accuracy", + true) + "\n\n" "Then, to use that model to predict classes for the dataset '" + PRINT_DATASET("test") + "', storing the output predictions in '" + PRINT_DATASET("predictions") + "', the following command may be used: " - "\n\n" + + "\n\n" + PRINT_CALL("logistic_regression", "input_model", "lr_model", "test", "test", - "predictions", "predictions")); + "predictions", "predictions")); // See also... BINDING_SEE_ALSO("@softmax_regression", "#softmax_regression"); BINDING_SEE_ALSO("@random_forest", "#random_forest"); BINDING_SEE_ALSO("Logistic regression on Wikipedia", - "https://en.wikipedia.org/wiki/Logistic_regression"); + "https://en.wikipedia.org/wiki/Logistic_regression"); BINDING_SEE_ALSO(":LogisticRegression C++ class documentation", - "@src/mlpack/methods/logistic_regression/logistic_regression.hpp"); + "@src/mlpack/methods/logistic_regression/logistic_regression.hpp"); // Training parameters. PARAM_MATRIX_IN("training", "A matrix containing the training set (the matrix " - "of predictors, X).", - "t"); + "of predictors, X).", "t"); PARAM_UROW_IN("labels", "A matrix containing labels (0 or 1) for the points " - "in the training set (y).", - "l"); + "in the training set (y).", "l"); // Optimizer parameters. PARAM_DOUBLE_IN("lambda", "L2-regularization parameter for training.", "L", - 0.0); + 0.0); PARAM_STRING_IN("optimizer", "Optimizer to use for training ('lbfgs' or " - "'sgd').", - "O", "lbfgs"); + "'sgd').", "O", "lbfgs"); PARAM_DOUBLE_IN("tolerance", "Convergence tolerance for optimizer.", "e", - 1e-10); + 1e-10); PARAM_INT_IN("max_iterations", "Maximum iterations for optimizer (0 indicates " - "no limit).", - "n", 10000); + "no limit).", "n", 10000); PARAM_DOUBLE_IN("step_size", "Step size for SGD optimizer.", - "s", 0.01); + "s", 0.01); PARAM_INT_IN("batch_size", "Batch size for SGD.", "b", 64); // Model loading/saving. PARAM_MODEL_IN(LogisticRegression<>, "input_model", "Existing model " - "(parameters).", - "m"); + "(parameters).", "m"); PARAM_MODEL_OUT(LogisticRegression<>, "output_model", "Output for trained " - "logistic regression model.", - "M"); + "logistic regression model.", "M"); // Testing. PARAM_MATRIX_IN("test", "Matrix containing test dataset.", "T"); PARAM_UROW_OUT("predictions", "If test data is specified, this matrix is where " - "the predictions for the test set will be saved.", - "P"); + "the predictions for the test set will be saved.", "P"); PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " - "matrix is where the class probabilities for the test set will be saved.", - "p"); + "matrix is where the class probabilities for the test set will be saved.", + "p"); 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); + "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); PARAM_FLAG("print_training_accuracy", "If set, then the accuracy of the model " - "on the training set will be printed (verbose must also be specified).", - "a"); + "on the training set will be printed (verbose must also be specified).", + "a"); -void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) +void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Collect command-line options. 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 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(params, {"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 (params.Has("training")) { - RequireAtLeastOnePassed(params, {"output_model"}, false, "trained model " - "will not be saved"); + RequireAtLeastOnePassed(params, { "output_model" }, false, "trained model " + "will not be saved"); } - RequireAtLeastOnePassed(params, {"output_model", "predictions", "probabilities"}, false, "no output will be saved"); + RequireAtLeastOnePassed(params, { "output_model", "predictions", + "probabilities"}, false, "no output will be saved"); - ReportIgnoredParam(params, {{"test", false}}, "predictions"); - ReportIgnoredParam(params, {{"test", false}}, "probabilities"); - - ReportIgnoredParam(params, {{"training", false}}, "print_training_accuracy"); + ReportIgnoredParam(params, {{ "test", false }}, "predictions"); + ReportIgnoredParam(params, {{ "test", false }}, "probabilities"); + ReportIgnoredParam(params, {{ "training", false }}, "print_training_accuracy"); + RequireAtLeastOnePassed(params, - {"test", "output_model", "print_training_accuracy"}, false, - "the trained logistic regression model will not be used or saved"); + { "test", "output_model", "print_training_accuracy" }, false, + "the trained logistic regression model will not be used or saved"); // Max Iterations needs to be positive. - RequireParamValue( - params, "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( - params, "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( - params, "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(params, "optimizer", {"lbfgs", "sgd"}, - true, "unknown optimizer"); + RequireParamInSet(params, "optimizer", { "lbfgs", "sgd" }, + true, "unknown optimizer"); // Lambda must be positive. - RequireParamValue( - params, "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( - params, "decision_boundary", - [](double x) - { return x >= 0.0 && x <= 1.0; }, - true, + 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( - params, "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 (params.Has("step_size")) { Log::Warn << PRINT_PARAM_STRING("step_size") << " ignored because " - << "optimizer type is not 'sgd'." << std::endl; + << "optimizer type is not 'sgd'." << std::endl; } if (params.Has("batch_size")) { Log::Warn << PRINT_PARAM_STRING("batch_size") << " ignored because " - << "optimizer type is not 'sgd'." << std::endl; + << "optimizer type is not 'sgd'." << std::endl; } } @@ -276,9 +246,9 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) regressors = std::move(params.Get("training")); // Load the model, if necessary. - LogisticRegression<> *model; + LogisticRegression<>* model; if (params.Has("input_model")) - model = params.Get *>("input_model"); + model = params.Get*>("input_model"); else { model = new LogisticRegression<>(0, 0); @@ -301,7 +271,7 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) delete model; Log::Fatal << "The labels must have the same number of points as the " - << "training dataset." << endl; + << "training dataset." << endl; } } else if (params.Has("training")) @@ -314,7 +284,7 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) delete model; Log::Fatal << "Can't get responses from training data since it has less " - << "than 2 rows." << endl; + << "than 2 rows." << endl; } // The initial predictors for y, Nx1. @@ -331,7 +301,7 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) delete model; Log::Fatal << "The labels must be either 0 or 1, not " << max(responses) - << "!" << endl; + << "!" << endl; } // Now, do the training. @@ -339,21 +309,6 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) { model->Lambda() = lambda; - // Did we want training accuracy? - if (params.Has("print_training_accuracy")) - { - timers.Start("lr_prediction"); - arma::Row predictions; - model->Classify(regressors, predictions); - - const size_t correct = arma::accu(predictions == responses); - - Log::Info << correct << " of " << responses.n_elem << " correct on training" - << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." - << endl; - timers.Stop("lr_prediction"); - } - if (optimizerType == "sgd") { ens::SGD<> sgdOpt; @@ -382,9 +337,24 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) } } + // Did we want training accuracy? + if (params.Has("training") && params.Has("print_training_accuracy")) + { + timers.Start("lr_prediction"); + arma::Row predictions; + model->Classify(regressors, predictions); + + const size_t correct = arma::accu(predictions == responses); + + Log::Info << correct << " of " << responses.n_elem << " correct on training" + << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." + << endl; + timers.Stop("lr_prediction"); + } + if (params.Has("test")) { - const arma::mat &testSet = params.Get("test"); + const arma::mat& testSet = params.Get("test"); // Checking the dimensionality of the test data. if (testSet.n_rows != model->Parameters().n_cols - 1) @@ -395,8 +365,8 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) delete model; Log::Fatal << "Test data dimensionality (" << testSet.n_rows << ") must " - << "be the same as the dimensionality of the training data (" - << trainingDimensionality << ")!" << endl; + << "be the same as the dimensionality of the training data (" + << trainingDimensionality << ")!" << endl; } // We must perform predictions on the test set. Training (and the @@ -404,7 +374,7 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) if (params.Has("predictions")) { Log::Info << "Predicting classes of points in '" - << params.GetPrintable("test") << "'." << endl; + << params.GetPrintable("test") << "'." << endl; model->Classify(testSet, predictions, decisionBoundary); if (params.Has("predictions")) @@ -414,7 +384,7 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) if (params.Has("probabilities")) { Log::Info << "Calculating class probabilities of points in '" - << params.GetPrintable("test") << "'." << endl; + << params.GetPrintable("test") << "'." << endl; arma::mat probabilities; model->Classify(testSet, probabilities); @@ -423,5 +393,5 @@ void BINDING_FUNCTION(util::Params ¶ms, util::Timers &timers) } } - params.Get *>("output_model") = model; + params.Get*>("output_model") = model; } From 48456f2ca34caf5b34cb3dd67002ff3c30b15307 Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Wed, 29 Nov 2023 02:26:37 +0530 Subject: [PATCH 21/28] fix test --- .../logistic_regression_main.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 25cb7bca9c..7c9fe6282f 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -309,6 +309,21 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { model->Lambda() = lambda; + // Did we want training accuracy? + if (params.Has("print_training_accuracy")) + { + timers.Start("lr_prediction"); + arma::Row predictions; + model->Classify(regressors, predictions); + + const size_t correct = arma::accu(predictions == responses); + + Log::Info << correct << " of " << responses.n_elem << " correct on training" + << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." + << endl; + timers.Stop("lr_prediction"); + } + if (optimizerType == "sgd") { ens::SGD<> sgdOpt; @@ -336,21 +351,6 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) timers.Stop("logistic_regression_optimization"); } } - - // Did we want training accuracy? - if (params.Has("training") && params.Has("print_training_accuracy")) - { - timers.Start("lr_prediction"); - arma::Row predictions; - model->Classify(regressors, predictions); - - const size_t correct = arma::accu(predictions == responses); - - Log::Info << correct << " of " << responses.n_elem << " correct on training" - << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." - << endl; - timers.Stop("lr_prediction"); - } if (params.Has("test")) { From c1d18268634ab89605b1d632199d2bb1b3662240 Mon Sep 17 00:00:00 2001 From: Ansh Babbar Date: Wed, 29 Nov 2023 09:52:19 +0530 Subject: [PATCH 22/28] fix test --- .../logistic_regression_main.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp index 7c9fe6282f..8566980e80 100644 --- a/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp +++ b/src/mlpack/methods/logistic_regression/logistic_regression_main.cpp @@ -309,21 +309,6 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { model->Lambda() = lambda; - // Did we want training accuracy? - if (params.Has("print_training_accuracy")) - { - timers.Start("lr_prediction"); - arma::Row predictions; - model->Classify(regressors, predictions); - - const size_t correct = arma::accu(predictions == responses); - - Log::Info << correct << " of " << responses.n_elem << " correct on training" - << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." - << endl; - timers.Stop("lr_prediction"); - } - if (optimizerType == "sgd") { ens::SGD<> sgdOpt; @@ -350,6 +335,21 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) model->Train(regressors, responses, lbfgsOpt); timers.Stop("logistic_regression_optimization"); } + + // Did we want training accuracy? + if (params.Has("print_training_accuracy")) + { + timers.Start("lr_prediction"); + arma::Row predictions; + model->Classify(regressors, predictions); + + const size_t correct = arma::accu(predictions == responses); + + Log::Info << correct << " of " << responses.n_elem << " correct on training" + << " set (" << (double(correct) / double(responses.n_elem) * 100) << ")." + << endl; + timers.Stop("lr_prediction"); + } } if (params.Has("test")) From afd6d88d2d9c18e15cb05312a3787b0bf29d8612 Mon Sep 17 00:00:00 2001 From: Ansh Babbar <31804810+rabbabansh@users.noreply.github.com> Date: Fri, 1 Dec 2023 04:53:35 +0530 Subject: [PATCH 23/28] Update HISTORY.md At the time of the beginning of this issue, this was a part of the previous release but it didn't get merged in time to be a part of that release ahah. Fixed it! --- HISTORY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index bf61ad4ff7..c157144999 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? + * Add `print_training_accuracy` option to LogisticRegression bindings (#3552). + * Fix `preprocess_split()` call in documentation for `LinearRegression` and `AdaBoost` Python classes (#3563). @@ -11,8 +13,6 @@ * Use HTTPS for all auto-downloaded dependencies (#3550). - * Add `print_training_accuracy` option to LogisticRegression bindings (#3552). - * More robust detection of C++17 mode in the MSVC "compiler" (#3555, #3557). * Fix setting number of classes correctly in `SoftmaxRegression::Train()` From b70e42cd389dda052ebd72badb6703a9f7cef35b Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 3 Dec 2023 15:42:27 +0100 Subject: [PATCH 24/28] Change the template type from arma::mat to MatType in NS Signed-off-by: Omar Shrit --- .../neighbor_search/neighbor_search.hpp | 10 ++++----- .../neighbor_search/neighbor_search_impl.hpp | 22 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/neighbor_search.hpp b/src/mlpack/methods/neighbor_search/neighbor_search.hpp index 2e2b9934d8..ad0f1c6d0f 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search.hpp @@ -223,7 +223,7 @@ class NeighborSearch void Search(const MatType& querySet, const size_t k, arma::Mat& neighbors, - arma::mat& distances); + MatType& distances); /** * Given a pre-built query tree, search for the nearest neighbors of each @@ -248,7 +248,7 @@ class NeighborSearch void Search(Tree& queryTree, const size_t k, arma::Mat& neighbors, - arma::mat& distances, + MatType& distances, bool sameSet = false); /** @@ -267,7 +267,7 @@ class NeighborSearch */ void Search(const size_t k, arma::Mat& neighbors, - arma::mat& distances); + MatType& distances); /** * Calculate the average relative error (effective error) between the @@ -284,8 +284,8 @@ class NeighborSearch * query point. * @return Average relative error. */ - static double EffectiveError(arma::mat& foundDistances, - arma::mat& realDistances); + static double EffectiveError(MatType& foundDistances, + MatType& realDistances); /** * Calculate the recall (% of neighbors found) given the list of found diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp index 13e42232f2..850bfd23dd 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp @@ -104,7 +104,7 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearchMode mode, // Build the tree on the empty dataset, if necessary. if (mode != NAIVE_MODE) { - referenceTree = BuildTree(std::move(arma::mat()), + referenceTree = BuildTree(std::move(MatType()), oldFromNewReferences); referenceSet = &referenceTree->Dataset(); } @@ -255,7 +255,7 @@ NeighborSearch(std::move(arma::mat()), + other.referenceTree = BuildTree(std::move(MatType()), other.oldFromNewReferences); other.referenceSet = &other.referenceTree->Dataset(); other.searchMode = DUAL_TREE_MODE, @@ -365,7 +365,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( const MatType& querySet, const size_t k, arma::Mat& neighbors, - arma::mat& distances) + MatType& distances) { if (k > referenceSet->n_cols) { @@ -386,14 +386,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( // To avoid an extra copy, we will store the neighbors and distances in a // separate matrix. arma::Mat* neighborPtr = &neighbors; - arma::mat* distancePtr = &distances; + MatType* distancePtr = &distances; // Mapping is only necessary if the tree rearranges points. if (TreeTraits::RearrangesDataset) { if (searchMode == DUAL_TREE_MODE) { - distancePtr = new arma::mat; // Query indices need to be mapped. + distancePtr = new MatType; // Query indices need to be mapped. neighborPtr = new arma::Mat; } else if (!oldFromNewReferences.empty()) @@ -570,7 +570,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( Tree& queryTree, const size_t k, arma::Mat& neighbors, - arma::mat& distances, + MatType& distances, bool sameSet) { if (k > referenceSet->n_cols) @@ -648,7 +648,7 @@ void NeighborSearch::Search( const size_t k, arma::Mat& neighbors, - arma::mat& distances) + MatType& distances) { if (k > referenceSet->n_cols) { @@ -670,12 +670,12 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( scores = 0; arma::Mat* neighborPtr = &neighbors; - arma::mat* distancePtr = &distances; + MatType* distancePtr = &distances; if (!oldFromNewReferences.empty() && TreeTraits::RearrangesDataset) { // We will always need to rearrange in this case. - distancePtr = new arma::mat; + distancePtr = new MatType; neighborPtr = new arma::Mat; } @@ -825,8 +825,8 @@ template class SingleTreeTraversalType> double NeighborSearch::EffectiveError( - arma::mat& foundDistances, - arma::mat& realDistances) + MatType& foundDistances, + MatType& realDistances) { if (foundDistances.n_rows != realDistances.n_rows || foundDistances.n_cols != realDistances.n_cols) From a3dcfc70ab353ae2fc5d6b83554e44da9fcca31a Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Sun, 3 Dec 2023 21:10:16 +0100 Subject: [PATCH 25/28] Let us hope that this will pass for sparse matrices Signed-off-by: Omar Shrit --- .../methods/neighbor_search/neighbor_search.hpp | 12 +++++++----- .../neighbor_search/neighbor_search_impl.hpp | 16 ++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/neighbor_search.hpp b/src/mlpack/methods/neighbor_search/neighbor_search.hpp index ad0f1c6d0f..558a4a300f 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search.hpp @@ -82,6 +82,8 @@ class NeighborSearch public: //! Convenience typedef. typedef TreeType, MatType> Tree; + //! The type of element held in MatType. + typedef typename MatType::elem_type ElemType; /** * Initialize the NeighborSearch object, passing a reference dataset (this is @@ -223,7 +225,7 @@ class NeighborSearch void Search(const MatType& querySet, const size_t k, arma::Mat& neighbors, - MatType& distances); + arma::Mat& distances); /** * Given a pre-built query tree, search for the nearest neighbors of each @@ -248,7 +250,7 @@ class NeighborSearch void Search(Tree& queryTree, const size_t k, arma::Mat& neighbors, - MatType& distances, + arma::Mat& distances, bool sameSet = false); /** @@ -267,7 +269,7 @@ class NeighborSearch */ void Search(const size_t k, arma::Mat& neighbors, - MatType& distances); + arma::Mat& distances); /** * Calculate the average relative error (effective error) between the @@ -284,8 +286,8 @@ class NeighborSearch * query point. * @return Average relative error. */ - static double EffectiveError(MatType& foundDistances, - MatType& realDistances); + static double EffectiveError(arma::Mat& foundDistances, + arma::Mat& realDistances); /** * Calculate the recall (% of neighbors found) given the list of found diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp index 850bfd23dd..c528d23f04 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp @@ -365,7 +365,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( const MatType& querySet, const size_t k, arma::Mat& neighbors, - MatType& distances) + arma::Mat& distances) { if (k > referenceSet->n_cols) { @@ -386,14 +386,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( // To avoid an extra copy, we will store the neighbors and distances in a // separate matrix. arma::Mat* neighborPtr = &neighbors; - MatType* distancePtr = &distances; + arma::Mat* distancePtr = &distances; // Mapping is only necessary if the tree rearranges points. if (TreeTraits::RearrangesDataset) { if (searchMode == DUAL_TREE_MODE) { - distancePtr = new MatType; // Query indices need to be mapped. + distancePtr = new arma::Mat; // Query indices need to be mapped. neighborPtr = new arma::Mat; } else if (!oldFromNewReferences.empty()) @@ -570,7 +570,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( Tree& queryTree, const size_t k, arma::Mat& neighbors, - MatType& distances, + arma::Mat& distances, bool sameSet) { if (k > referenceSet->n_cols) @@ -648,7 +648,7 @@ void NeighborSearch::Search( const size_t k, arma::Mat& neighbors, - MatType& distances) + arma::Mat& distances) { if (k > referenceSet->n_cols) { @@ -670,7 +670,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( scores = 0; arma::Mat* neighborPtr = &neighbors; - MatType* distancePtr = &distances; + arma::Mat* distancePtr = &distances; if (!oldFromNewReferences.empty() && TreeTraits::RearrangesDataset) { @@ -825,8 +825,8 @@ template class SingleTreeTraversalType> double NeighborSearch::EffectiveError( - MatType& foundDistances, - MatType& realDistances) + arma::Mat& foundDistances, + arma::Mat& realDistances) { if (foundDistances.n_rows != realDistances.n_rows || foundDistances.n_cols != realDistances.n_cols) From 2f3fde220b208e7f78ebc08f8d5d862891154cce Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 7 Dec 2023 19:57:19 +0100 Subject: [PATCH 26/28] Add a float tests, fix the distances in the rules search Signed-off-by: Omar Shrit --- .../neighbor_search/neighbor_search_rules.hpp | 5 ++- .../neighbor_search_rules_impl.hpp | 2 +- src/mlpack/tests/knn_test.cpp | 38 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp index 9b7ce53661..02577a4049 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp @@ -34,6 +34,9 @@ template class NeighborSearchRules { public: + //! The type of element held in MatType. + typedef typename TreeType::Mat::elem_type ElemType; + /** * Construct the NeighborSearchRules object. This is usually done from within * the NeighborSearch class at search time. @@ -60,7 +63,7 @@ class NeighborSearchRules * @param distances Matrix storing distances of neighbors for each query * point. */ - void GetResults(arma::Mat& neighbors, arma::mat& distances); + void GetResults(arma::Mat& neighbors, arma::Mat& distances); /** * Get the distance from the query point to the reference point. 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 0c1f50d58e..f754427dc2 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp @@ -61,7 +61,7 @@ NeighborSearchRules::NeighborSearchRules( template void NeighborSearchRules::GetResults( arma::Mat& neighbors, - arma::mat& distances) + arma::Mat& distances) { neighbors.set_size(k, querySet.n_cols); distances.set_size(k, querySet.n_cols); diff --git a/src/mlpack/tests/knn_test.cpp b/src/mlpack/tests/knn_test.cpp index dd302a85df..797c717e0f 100644 --- a/src/mlpack/tests/knn_test.cpp +++ b/src/mlpack/tests/knn_test.cpp @@ -746,6 +746,44 @@ TEST_CASE("KNNSingleTreeVsNaive", "[KNNTest]") } } +/** + * Test the single-tree nearest-neighbors method with the naive method. + * + * The main difference with the above test is that this one loads the reference + * dataset as a float32, and the distances as a float32 as well. + * + * Errors are produced if the results are not identical. + */ +TEST_CASE("KNNSingleTreeVsNaiveF32", "[KNNTest]") +{ + arma::fmat dataset; + + // 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!"); + + NeighborSearch + knn(dataset, SINGLE_TREE_MODE); + + // Set up computation for naive mode. + NeighborSearch + naive(dataset, NAIVE_MODE); + + arma::Mat neighborsTree; + arma::fmat distancesTree; + knn.Search(15, neighborsTree, distancesTree); + + arma::Mat neighborsNaive; + arma::fmat distancesNaive; + naive.Search(15, neighborsNaive, distancesNaive); + + for (size_t i = 0; i < neighborsTree.n_elem; ++i) + { + REQUIRE(neighborsTree[i] ==neighborsNaive[i]); + REQUIRE(distancesTree[i] == Approx(distancesNaive[i]).epsilon(1e-7)); + } +} /** * Test the cover tree single-tree nearest-neighbors method against the naive * method. This uses only a random reference dataset. From 63e512ef2e3e61f686a67b325e3d3dde62969cf0 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 11 Dec 2023 22:36:26 +0100 Subject: [PATCH 27/28] Fix the declarations for the knn float Signed-off-by: Omar Shrit --- src/mlpack/tests/knn_test.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/mlpack/tests/knn_test.cpp b/src/mlpack/tests/knn_test.cpp index 797c717e0f..3f77aba9ca 100644 --- a/src/mlpack/tests/knn_test.cpp +++ b/src/mlpack/tests/knn_test.cpp @@ -16,6 +16,18 @@ using namespace mlpack; +/** + * A couple of handful declarations for float32 testing. + * These will be removed when we refactor the Bounds to accept MatType. + * For now, we will keep the following declarations. + */ +template +using FloatHRectBound = HRectBound; + +template +using FloatKDTree = BinarySpaceTree; + /** * Test that Unmap() works in the dual-tree case (see unmap.hpp). */ @@ -763,12 +775,16 @@ TEST_CASE("KNNSingleTreeVsNaiveF32", "[KNNTest]") if (!data::Load("test_data_3_1000.csv", dataset)) FAIL("Cannot load test dataset test_data_3_1000.csv!"); - NeighborSearch - knn(dataset, SINGLE_TREE_MODE); + NeighborSearch knn(dataset, SINGLE_TREE_MODE); // Set up computation for naive mode. - NeighborSearch - naive(dataset, NAIVE_MODE); + NeighborSearch naive(dataset, NAIVE_MODE); arma::Mat neighborsTree; arma::fmat distancesTree; From 884657910760421d574f692c7aa41417643153ac Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 11 Dec 2023 23:24:29 +0100 Subject: [PATCH 28/28] Fix arma::vec to arma::Col Signed-off-by: Omar Shrit --- src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp | 2 +- .../core/tree/binary_space_tree/binary_space_tree_impl.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp b/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp index a042ba849d..8289e0179f 100644 --- a/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp +++ b/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp @@ -504,7 +504,7 @@ class BinarySpaceTree size_t& Count() { return count; } //! Store the center of the bounding region in the given vector. - void Center(arma::vec& center) const { bound.Center(center); } + void Center(arma::Col& center) const { bound.Center(center); } private: /** diff --git a/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp b/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp index 0a1e1d31db..da5bd3d3ba 100644 --- a/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp +++ b/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp @@ -909,7 +909,7 @@ void BinarySpaceTree:: splitter, maxLeafSize); // Calculate parent distances for those two nodes. - arma::vec center, leftCenter, rightCenter; + arma::Col center, leftCenter, rightCenter; Center(center); left->Center(leftCenter); right->Center(rightCenter); @@ -977,7 +977,7 @@ SplitNode(std::vector& oldFromNew, oldFromNew, splitter, maxLeafSize); // Calculate parent distances for those two nodes. - arma::vec center, leftCenter, rightCenter; + arma::Col center, leftCenter, rightCenter; Center(center); left->Center(leftCenter); right->Center(rightCenter);