diff --git a/HISTORY.md b/HISTORY.md index 52c2388d62..7cd82d907b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,7 +4,12 @@ * Fix bug in LogSoftMax derivative (#3469). - * Add `serialize` method to `GaussianInitialization`, `KathirvalavakumarSubavathiInitialization`, `KathirvalavakumarSubavathiInitialization`, `NguyenWidrowInitialization`, and `OrthogonalInitialization` (#3483). + * Add `serialize` method to `GaussianInitialization`, + `KathirvalavakumarSubavathiInitialization`, + `KathirvalavakumarSubavathiInitialization`, `NguyenWidrowInitialization`, + and `OrthogonalInitialization` (#3483). + + * Allow categorical features to `preprocess_one_hot_encode` (#3487). * Install mlpack and cereal headers as part of R package (#3488). diff --git a/src/mlpack/bindings/python/print_input_processing.hpp b/src/mlpack/bindings/python/print_input_processing.hpp index 2cdd01fc4b..99e0d54a72 100644 --- a/src/mlpack/bindings/python/print_input_processing.hpp +++ b/src/mlpack/bindings/python/print_input_processing.hpp @@ -488,9 +488,9 @@ void PrintInputProcessing( { std::cout << prefix << "cdef extern from \"numpy/arrayobject.h\":" << std::endl; std::cout << prefix << " void* PyArray_DATA(np.ndarray arr)" << std::endl; - std::cout << prefix << "if " << d.name << " is not None:" << std::endl; - std::cout << prefix << " " << d.name << "_tuple = to_matrix_with_info(" - << d.name << ", dtype=np.double, copy=p.Has('copy_all_inputs'))" + std::cout << prefix << "if " << name << " is not None:" << std::endl; + std::cout << prefix << " " << name << "_tuple = to_matrix_with_info(" + << name << ", dtype=np.double, copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << " if len(" << name << "_tuple[0].shape" << ") < 2:" << std::endl; @@ -501,8 +501,8 @@ void PrintInputProcessing( std::cout << prefix << " " << name << "_dims = " << name << "_tuple[2]" << std::endl; std::cout << prefix << " SetParamWithInfo[arma.Mat[double]](p, '" << d.name << "', dereference(" << d.name << "_mat), " - << " PyArray_DATA(" << d.name << "_dims))" << std::endl; + << "string> '" << d.name << "', dereference(" << name << "_mat), " + << " PyArray_DATA(" << name << "_dims))" << std::endl; std::cout << prefix << " p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << " del " << name << "_mat" << std::endl; @@ -511,7 +511,7 @@ void PrintInputProcessing( { std::cout << prefix << "cdef extern from \"numpy/arrayobject.h\":" << std::endl; std::cout << prefix << " void* PyArray_DATA(np.ndarray arr)" << std::endl; - std::cout << prefix << d.name << "_tuple = to_matrix_with_info(" << d.name + std::cout << prefix << name << "_tuple = to_matrix_with_info(" << name << ", dtype=np.double, copy=p.Has('copy_all_inputs'))" << std::endl; std::cout << prefix << "if len(" << name << "_tuple[0].shape" @@ -523,8 +523,8 @@ void PrintInputProcessing( std::cout << prefix << name << "_dims = " << name << "_tuple[2]" << std::endl; std::cout << prefix << "SetParamWithInfo[arma.Mat[double]](p, '" << d.name << "', dereference(" << d.name << "_mat), " - << " PyArray_DATA(" << d.name << "_dims))" << std::endl; + << "string> '" << d.name << "', dereference(" << name << "_mat), " + << " PyArray_DATA(" << name << "_dims))" << std::endl; std::cout << prefix << "p.SetPassed( '" << d.name << "')" << std::endl; std::cout << prefix << "del " << name << "_mat" << std::endl; diff --git a/src/mlpack/core/util/param.hpp b/src/mlpack/core/util/param.hpp index 213982e1ab..838b2063af 100644 --- a/src/mlpack/core/util/param.hpp +++ b/src/mlpack/core/util/param.hpp @@ -330,7 +330,7 @@ /** * Define a matrix output parameter. When the program terminates, the matrix - * will be saved to whatever it was set to by IO::GetParam(ID) + * will be saved to whatever it was set to by params.Get(ID) * during the program. From the command-line, the user may specify the file in * which to save the output matrix using a string option that is the name of the * matrix parameter with "_file" appended. So, for instance, if the name of the @@ -400,7 +400,7 @@ * Define a transposed matrix output parameter. This is useful when data is * stored in a row-major form instead of the usual column-major form. When the * program terminates, the matrix will be saved to whatever it was set to by - * IO::GetParam(ID) during the program. From the command-line, the + * params.Get(ID) during the program. From the command-line, the * user may specify the file in which to save the output matrix using a string * option that is the name of the matrix parameter with "_file" appended. So, * for instance, if the name of the output matrix parameter was "mat", the user @@ -467,7 +467,7 @@ /** * Define an unsigned matrix output parameter (arma::Mat). When the * program terminates, the matrix will be saved to whatever it was set to by - * IO::GetParam>(ID) during the program. From the + * params.Get>(ID) during the program. From the * command-line, the user may specify the file in which to save the output * matrix using a string option that is the name of the matrix parameter with * "_file" appended. So, for instance, if the name of the output matrix @@ -746,9 +746,9 @@ * * @code * DatasetInfo d = std::move( - * IO::GetParam>("matrix").get<0>()); + * params.Get>("matrix").get<0>()); * arma::mat m = std::move( - * IO::GetParam>("matrix").get<1>()); + * params.Get>("matrix").get<1>()); * @endcode * * @param ID Name of the parameter. @@ -763,6 +763,38 @@ "std::tuple", false, true, true, \ TUPLE_TYPE()) +/** + * Define a required input DatasetInfo/matrix parameter. From the command line, + * the user can specify the file that holds the matrix, using the name of the + * matrix parameter with "_file" appended (and the same alias). So for + * instance, if the name of the matrix parameter was "matrix", the user could + * specify that the "matrix" matrix was held in file.csv by giving the parameter + * + * @code + * --matrix_file file.csv + * @endcode + * + * Then the DatasetInfo and matrix type could be accessed with + * + * @code + * DatasetInfo d = std::move( + * params.Get>("matrix").get<0>()); + * arma::mat m = std::move( + * params.Get>("matrix").get<1>()); + * @endcode + * + * @param ID Name of the parameter. + * @param DESC Quick description of the parameter (1-2 sentences). Don't use + * printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others + * here---it will cause problems. + * @param ALIAS One-character string representing the alias of the parameter. + */ +#define TUPLE_TYPE std::tuple +#define PARAM_MATRIX_AND_INFO_IN_REQ(ID, DESC, ALIAS) \ + PARAM(TUPLE_TYPE, ID, DESC, ALIAS, \ + "std::tuple", true, true, true, \ + TUPLE_TYPE()) + /** * Define an input model. From the command line, the user can specify the file * that holds the model, using the name of the model parameter with "_file" @@ -836,9 +868,7 @@ * --model_file model.bin * @endcode * - * The model will be saved at the termination of the program. If you use a - * parameter of this type, you must call IO::Destroy() at the end of your - * program. + * The model will be saved at the termination of the program. * * @param TYPE Type of the model to be saved. * @param ID Name of the parameter. diff --git a/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp b/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp index 3b7f1b3e1c..49952872b7 100644 --- a/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_one_hot_encoding_main.cpp @@ -28,6 +28,11 @@ BINDING_LONG_DESC( "encoding of the respective features at those indices. Indices represent " "the IDs of the dimensions to be one-hot encoded." "\n\n" + "If no dimensions are specified with " + PRINT_PARAM_STRING("dimensions") + + ", then all categorical-type dimensions will be one-hot encoded. " + "Otherwise, only the dimensions given in " + + PRINT_PARAM_STRING("dimensions") + " will be one-hot encoded." + "\n\n" "The output matrix with encoded features may be saved with the " + PRINT_PARAM_STRING("output") + " parameters."); @@ -48,12 +53,13 @@ BINDING_SEE_ALSO("One-hot encoding on Wikipedia", "https://en.m.wikipedia.org/wiki/One-hot"); // Define parameters for data. -PARAM_MATRIX_IN_REQ("input", "Matrix containing data.", "i"); +PARAM_MATRIX_AND_INFO_IN_REQ("input", "Matrix containing data.", "i"); PARAM_MATRIX_OUT("output", "Matrix to save one-hot encoded features " "data to.", "o"); -PARAM_VECTOR_IN_REQ(int, "dimensions", "Index of dimensions that" - "need to be one-hot encoded.", "d"); +PARAM_VECTOR_IN(int, "dimensions", "Index of dimensions that need to be one-hot" + " encoded (if unspecified, all categorical dimensions are one-hot " + "encoded).", "d"); using namespace mlpack; using namespace mlpack::util; @@ -63,29 +69,65 @@ using namespace std; void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { // Load the data. - const arma::mat& data = params.Get("input"); - vector& indices = params.Get >("dimensions"); - vector copyIndices(indices.size()); - RequireParamValue>(params, "dimensions", - [data](std::vector x) - { - for (int dim : x) - { - if (dim < 0 || (size_t)dim > data.n_rows) - { - return false; - } - } - return true; - }, true, "dimensions must be greater than 0 and less than the number of " - "dimensions"); + const std::tuple& t = + params.Get>("input"); - for (size_t i = 0; i < indices.size(); ++i) + const data::DatasetInfo& info = std::get<0>(t); + const arma::mat& data = std::get<1>(t); + + vector& indices = params.Get>("dimensions"); + if (!params.Has("dimensions")) { - copyIndices[i] = (size_t)indices[i]; + // If the user did not specify any dimensions to convert, we pick all the + // categorical dimensions by default. + for (size_t d = 0; d < info.Dimensionality(); ++d) + if (info.Type(d) == data::Datatype::categorical) + indices.push_back(d); + + // Print which dimensions we selected to one-hot encode. + if (indices.size() > 0) + { + Log::Info << "One-hot encoding categorical dimensions: ["; + for (size_t i = 0; i < indices.size() - 1; ++i) + Log::Info << indices[i] << ", "; + Log::Info << indices[indices.size() - 1] << "]." << std::endl; + } + } + else + { + // If the user did specify dimensions, let's make sure they are reasonable. + RequireParamValue>(params, "dimensions", + [data](std::vector x) + { + for (int dim : x) + { + if (dim < 0 || (size_t) dim > data.n_rows) + { + return false; + } + } + return true; + }, true, "dimensions must be greater than 0 and less than the number of" + " dimensions"); + } + + // Note that it's possible that zero dimensions are selected for one-hot + // encoding. + if (indices.size() > 0) + { + vector copyIndices(indices.size()); + for (size_t i = 0; i < indices.size(); ++i) + { + copyIndices[i] = (size_t)indices[i]; + } + + arma::mat output; + data::OneHotEncoding(data, (arma::Col)(copyIndices), output); + if (params.Has("output")) + params.Get("output") = std::move(output); + } + else if (params.Has("output")) + { + params.Get("output") = data; // Copy input to output. } - arma::mat output; - data::OneHotEncoding(data, (arma::Col)(copyIndices), output); - if (params.Has("output")) - params.Get("output") = std::move(output); } diff --git a/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp b/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp index 1306da14a2..523025c772 100644 --- a/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp +++ b/src/mlpack/tests/main_tests/preprocess_one_hot_encode_test.cpp @@ -47,7 +47,8 @@ TEST_CASE_METHOD( "0 1 0 0 0 0 1 0;" "1 1 -1 -1 -1 -1 1 1;"; - SetInputParam("input", dataset); + data::DatasetInfo di(dataset.n_rows); + SetInputParam("input", std::make_tuple(di, dataset)); SetInputParam>("dimensions", {1, 3}); RUN_BINDING(); @@ -66,7 +67,8 @@ TEST_CASE_METHOD( { arma::mat dataset; - SetInputParam("input", dataset); + data::DatasetInfo di(dataset.n_rows); + SetInputParam("input", std::make_tuple(di, dataset)); SetInputParam>("dimensions", {1, 3}); // This will throw an error since dimensions are bigger than the matrix. REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); @@ -86,7 +88,8 @@ TEST_CASE_METHOD( "-1 1 -1 -1 -1 -1 1 -1;" "1 1 -1 -1 -1 -1 1 1;"; - SetInputParam("input", dataset); + data::DatasetInfo di(dataset.n_rows); + SetInputParam("input", std::make_tuple(di, dataset)); SetInputParam>("dimensions", {}); RUN_BINDING(); @@ -110,7 +113,8 @@ TEST_CASE_METHOD( "-1 1 -1 -1 -1 -1 1 -1;" "1 1 -1 -1 -1 -1 1 1;"; - SetInputParam("input", dataset); + data::DatasetInfo di(dataset.n_rows); + SetInputParam("input", std::make_tuple(di, dataset)); SetInputParam>("dimensions", {10000}); // Error since dimensions are bigger than matrix. REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); @@ -130,7 +134,8 @@ TEST_CASE_METHOD( "-1 1 -1 -1 -1 -1 1 -1;" "1 1 -1 -1 -1 -1 1 1;"; - SetInputParam("input", dataset); + data::DatasetInfo di(dataset.n_rows); + SetInputParam("input", std::make_tuple(di, dataset)); SetInputParam>("dimensions", {-10000}); REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error); } @@ -143,8 +148,9 @@ TEST_CASE_METHOD( "[PreprocessOneHotEncodingMainTest][BindingTests]") { arma::mat dataset; + data::DatasetInfo di(dataset.n_rows); - SetInputParam("input", dataset); + SetInputParam("input", std::make_tuple(di, dataset)); SetInputParam>("dimensions", {}); RUN_BINDING(); @@ -153,3 +159,274 @@ TEST_CASE_METHOD( REQUIRE(dataset.n_rows == output.n_rows); CheckMatrices(output, dataset); } + +/** + * Test for a dataset with categorical features, where we one-hot encode all + * categorical features. + */ +TEST_CASE_METHOD( + PreprocessOneHotEncodingTestFixture, "CategoricalMatrixTest", + "[PreprocessOneHotEncodingMainTest][BindingTests]") +{ + arma::mat dataset(4, 5); + dataset.randu(); + + // Dimension 2 will be categorical. + dataset(2, 0) = 0; + dataset(2, 1) = 1; + dataset(2, 2) = 1; + dataset(2, 3) = 2; + dataset(2, 4) = 0; + + data::DatasetInfo info(4); + info.Type(2) = data::Datatype::categorical; + (void) info.MapString("0", 2); + (void) info.MapString("1", 2); + (void) info.MapString("2", 2); + REQUIRE(info.NumMappings(2) == 3); + + SetInputParam("input", std::make_tuple(info, dataset)); + RUN_BINDING(); + + arma::mat output = params.Get("output"); + REQUIRE(dataset.n_cols == output.n_cols); + REQUIRE(dataset.n_rows + 2 == output.n_rows); + + // Make sure one-hot encoding was correct. + REQUIRE(output(2, 0) == 1); + REQUIRE(output(2, 1) == 0); + REQUIRE(output(2, 2) == 0); + REQUIRE(output(2, 3) == 0); + REQUIRE(output(2, 4) == 1); + REQUIRE(output(3, 0) == 0); + REQUIRE(output(3, 1) == 1); + REQUIRE(output(3, 2) == 1); + REQUIRE(output(3, 3) == 0); + REQUIRE(output(3, 4) == 0); + REQUIRE(output(4, 0) == 0); + REQUIRE(output(4, 1) == 0); + REQUIRE(output(4, 2) == 0); + REQUIRE(output(4, 3) == 1); + REQUIRE(output(4, 4) == 0); +} + +/** + * Test for a dataset with no categorical features, where we don't specify the + * dimensions to convert. This should convert nothing. + */ +TEST_CASE_METHOD( + PreprocessOneHotEncodingTestFixture, "NoCategoricalMatrixTest", + "[PreprocessOneHotEncodingMainTest][BindingTests]") +{ + arma::mat dataset(4, 5); + dataset.randu(); + data::DatasetInfo info(4); // all numeric dimensions + + SetInputParam("input", std::make_tuple(info, dataset)); + RUN_BINDING(); + + arma::mat output = params.Get("output"); + REQUIRE(dataset.n_cols == output.n_cols); + REQUIRE(dataset.n_rows == output.n_rows); + CheckMatrices(output, dataset); +} + +/** + * Test for a dataset with multiple categorical features. + */ +TEST_CASE_METHOD( + PreprocessOneHotEncodingTestFixture, "MultipleFeatureCategoricalMatrixTest", + "[PreprocessOneHotEncodingMainTest][BindingTests]") +{ + arma::mat dataset(4, 5); + dataset.randu(); + + // Dimensions 0, 2, and 3 will be categorical. + dataset(0, 0) = 0; + dataset(0, 1) = 1; + dataset(0, 2) = 2; + dataset(0, 3) = 3; + dataset(0, 4) = 3; + dataset(2, 0) = 0; + dataset(2, 1) = 1; + dataset(2, 2) = 1; + dataset(2, 3) = 2; + dataset(2, 4) = 0; + dataset(3, 0) = 0; + dataset(3, 1) = 0; + dataset(3, 2) = 1; + dataset(3, 3) = 1; + dataset(3, 4) = 1; + + data::DatasetInfo info(4); + info.Type(0) = data::Datatype::categorical; + (void) info.MapString("0", 0); + (void) info.MapString("1", 0); + (void) info.MapString("2", 0); + (void) info.MapString("3", 0); + + info.Type(2) = data::Datatype::categorical; + (void) info.MapString("0", 2); + (void) info.MapString("1", 2); + (void) info.MapString("2", 2); + + info.Type(3) = data::Datatype::categorical; + (void) info.MapString("0", 3); + (void) info.MapString("1", 3); + + SetInputParam("input", std::make_tuple(info, dataset)); + RUN_BINDING(); + + arma::mat output = params.Get("output"); + REQUIRE(dataset.n_cols == output.n_cols); + REQUIRE(dataset.n_rows + 3 + 2 + 1 == output.n_rows); + + // Make sure one-hot encoding was correct. + REQUIRE(output(0, 0) == 1); + REQUIRE(output(0, 1) == 0); + REQUIRE(output(0, 2) == 0); + REQUIRE(output(0, 3) == 0); + REQUIRE(output(0, 4) == 0); + REQUIRE(output(1, 0) == 0); + REQUIRE(output(1, 1) == 1); + REQUIRE(output(1, 2) == 0); + REQUIRE(output(1, 3) == 0); + REQUIRE(output(1, 4) == 0); + REQUIRE(output(2, 0) == 0); + REQUIRE(output(2, 1) == 0); + REQUIRE(output(2, 2) == 1); + REQUIRE(output(2, 3) == 0); + REQUIRE(output(2, 4) == 0); + REQUIRE(output(3, 0) == 0); + REQUIRE(output(3, 1) == 0); + REQUIRE(output(3, 2) == 0); + REQUIRE(output(3, 3) == 1); + REQUIRE(output(3, 4) == 1); + + REQUIRE(output(5, 0) == 1); + REQUIRE(output(5, 1) == 0); + REQUIRE(output(5, 2) == 0); + REQUIRE(output(5, 3) == 0); + REQUIRE(output(5, 4) == 1); + REQUIRE(output(6, 0) == 0); + REQUIRE(output(6, 1) == 1); + REQUIRE(output(6, 2) == 1); + REQUIRE(output(6, 3) == 0); + REQUIRE(output(6, 4) == 0); + REQUIRE(output(7, 0) == 0); + REQUIRE(output(7, 1) == 0); + REQUIRE(output(7, 2) == 0); + REQUIRE(output(7, 3) == 1); + REQUIRE(output(7, 4) == 0); + + REQUIRE(output(8, 0) == 1); + REQUIRE(output(8, 1) == 1); + REQUIRE(output(8, 2) == 0); + REQUIRE(output(8, 3) == 0); + REQUIRE(output(8, 4) == 0); + REQUIRE(output(9, 0) == 0); + REQUIRE(output(9, 1) == 0); + REQUIRE(output(9, 2) == 1); + REQUIRE(output(9, 3) == 1); + REQUIRE(output(9, 4) == 1); +} + +/** + * Test for a dataset with multiple categorical features, where we are not + * converting them all. + */ +TEST_CASE_METHOD( + PreprocessOneHotEncodingTestFixture, + "MultipleNotAllFeatureCategoricalMatrixTest", + "[PreprocessOneHotEncodingMainTest][BindingTests]") +{ + arma::mat dataset(4, 5); + dataset.randu(); + + // Dimensions 0, 2, and 3 will be categorical, but we will only convert + // dimensions 0 and 2. + dataset(0, 0) = 0; + dataset(0, 1) = 1; + dataset(0, 2) = 2; + dataset(0, 3) = 3; + dataset(0, 4) = 3; + dataset(2, 0) = 0; + dataset(2, 1) = 1; + dataset(2, 2) = 1; + dataset(2, 3) = 2; + dataset(2, 4) = 0; + dataset(3, 0) = 0; + dataset(3, 1) = 0; + dataset(3, 2) = 1; + dataset(3, 3) = 1; + dataset(3, 4) = 1; + + data::DatasetInfo info(4); + info.Type(0) = data::Datatype::categorical; + (void) info.MapString("0", 0); + (void) info.MapString("1", 0); + (void) info.MapString("2", 0); + (void) info.MapString("3", 0); + + info.Type(2) = data::Datatype::categorical; + (void) info.MapString("0", 2); + (void) info.MapString("1", 2); + (void) info.MapString("2", 2); + + info.Type(3) = data::Datatype::categorical; + (void) info.MapString("0", 3); + (void) info.MapString("1", 3); + + SetInputParam("input", std::make_tuple(info, dataset)); + SetInputParam>("dimensions", {0, 2}); + RUN_BINDING(); + + arma::mat output = params.Get("output"); + REQUIRE(dataset.n_cols == output.n_cols); + REQUIRE(dataset.n_rows + 3 + 2 == output.n_rows); + + // Make sure one-hot encoding was correct. + REQUIRE(output(0, 0) == 1); + REQUIRE(output(0, 1) == 0); + REQUIRE(output(0, 2) == 0); + REQUIRE(output(0, 3) == 0); + REQUIRE(output(0, 4) == 0); + REQUIRE(output(1, 0) == 0); + REQUIRE(output(1, 1) == 1); + REQUIRE(output(1, 2) == 0); + REQUIRE(output(1, 3) == 0); + REQUIRE(output(1, 4) == 0); + REQUIRE(output(2, 0) == 0); + REQUIRE(output(2, 1) == 0); + REQUIRE(output(2, 2) == 1); + REQUIRE(output(2, 3) == 0); + REQUIRE(output(2, 4) == 0); + REQUIRE(output(3, 0) == 0); + REQUIRE(output(3, 1) == 0); + REQUIRE(output(3, 2) == 0); + REQUIRE(output(3, 3) == 1); + REQUIRE(output(3, 4) == 1); + + REQUIRE(output(5, 0) == 1); + REQUIRE(output(5, 1) == 0); + REQUIRE(output(5, 2) == 0); + REQUIRE(output(5, 3) == 0); + REQUIRE(output(5, 4) == 1); + REQUIRE(output(6, 0) == 0); + REQUIRE(output(6, 1) == 1); + REQUIRE(output(6, 2) == 1); + REQUIRE(output(6, 3) == 0); + REQUIRE(output(6, 4) == 0); + REQUIRE(output(7, 0) == 0); + REQUIRE(output(7, 1) == 0); + REQUIRE(output(7, 2) == 0); + REQUIRE(output(7, 3) == 1); + REQUIRE(output(7, 4) == 0); + + // Make sure we did not one-hot encode the last dimension. + REQUIRE(output(8, 0) == 0); + REQUIRE(output(8, 1) == 0); + REQUIRE(output(8, 2) == 1); + REQUIRE(output(8, 3) == 1); + REQUIRE(output(8, 4) == 1); +} diff --git a/src/mlpack/tests/main_tests/softmax_regression_test.cpp b/src/mlpack/tests/main_tests/softmax_regression_test.cpp index e27f7bf175..d330ccc722 100644 --- a/src/mlpack/tests/main_tests/softmax_regression_test.cpp +++ b/src/mlpack/tests/main_tests/softmax_regression_test.cpp @@ -31,7 +31,7 @@ BINDING_TEST_FIXTURE(SoftmaxRegressionTestFixture); TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionOutputDimensionTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -76,7 +76,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionLabelsLessDimensionTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -94,7 +94,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionModelReuseTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -157,7 +157,7 @@ TEST_CASE_METHOD( */ TEST_CASE_METHOD( SoftmaxRegressionTestFixture, - "SoftmaxRegressionMaxItrTest", "[SoftmaxRegressionMainTest][BindingsTests]") + "SoftmaxRegressionMaxItrTest", "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -184,7 +184,7 @@ TEST_CASE_METHOD( */ TEST_CASE_METHOD( SoftmaxRegressionTestFixture, - "SoftmaxRegressionLambdaTest", "[SoftmaxRegressionMainTest][BindingsTests]") + "SoftmaxRegressionLambdaTest", "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -212,7 +212,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionNumClassesTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -240,7 +240,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionTrainingVerTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) @@ -274,7 +274,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionDiffLambdaTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { // Train SR for lambda 0.1. arma::mat inputData; @@ -340,7 +340,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionDiffMaxItrTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { // Train SR for lambda 0.1. arma::mat inputData; @@ -406,7 +406,7 @@ TEST_CASE_METHOD( TEST_CASE_METHOD( SoftmaxRegressionTestFixture, "SoftmaxRegressionDiffInterceptTest", - "[SoftmaxRegressionMainTest][BindingsTests]") + "[SoftmaxRegressionMainTest][BindingTests]") { // Train SR with intercept. arma::mat inputData;