Categorical support preprocess_one_hot_encoding (#3487)

This commit is contained in:
Ryan Curtin
2023-06-09 02:51:54 +02:00
committed by GitHub
parent ce9e1d77c9
commit 97fa8af3dd
6 changed files with 412 additions and 58 deletions
+6 -1
View File
@@ -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).
@@ -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, <const "
<< "string> '" << d.name << "', dereference(" << d.name << "_mat), "
<< "<const cbool*> PyArray_DATA(" << d.name << "_dims))" << std::endl;
<< "string> '" << d.name << "', dereference(" << name << "_mat), "
<< "<const cbool*> PyArray_DATA(" << name << "_dims))" << std::endl;
std::cout << prefix << " p.SetPassed(<const string> '" << 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, <const "
<< "string> '" << d.name << "', dereference(" << d.name << "_mat), "
<< "<const cbool*> PyArray_DATA(" << d.name << "_dims))" << std::endl;
<< "string> '" << d.name << "', dereference(" << name << "_mat), "
<< "<const cbool*> PyArray_DATA(" << name << "_dims))" << std::endl;
std::cout << prefix << "p.SetPassed(<const string> '" << d.name << "')"
<< std::endl;
std::cout << prefix << "del " << name << "_mat" << std::endl;
+38 -8
View File
@@ -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<arma::mat>(ID)
* will be saved to whatever it was set to by params.Get<arma::mat>(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<arma::mat>(ID) during the program. From the command-line, the
* params.Get<arma::mat>(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<size_t>). When the
* program terminates, the matrix will be saved to whatever it was set to by
* IO::GetParam<arma::Mat<size_t>>(ID) during the program. From the
* params.Get<arma::Mat<size_t>>(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<std::tuple<DatasetInfo, arma::mat>>("matrix").get<0>());
* params.Get<std::tuple<DatasetInfo, arma::mat>>("matrix").get<0>());
* arma::mat m = std::move(
* IO::GetParam<std::tuple<DatasetInfo, arma::mat>>("matrix").get<1>());
* params.Get<std::tuple<DatasetInfo, arma::mat>>("matrix").get<1>());
* @endcode
*
* @param ID Name of the parameter.
@@ -763,6 +763,38 @@
"std::tuple<mlpack::data::DatasetInfo, arma::mat>", 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<std::tuple<DatasetInfo, arma::mat>>("matrix").get<0>());
* arma::mat m = std::move(
* params.Get<std::tuple<DatasetInfo, arma::mat>>("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<mlpack::data::DatasetInfo, arma::mat>
#define PARAM_MATRIX_AND_INFO_IN_REQ(ID, DESC, ALIAS) \
PARAM(TUPLE_TYPE, ID, DESC, ALIAS, \
"std::tuple<mlpack::data::DatasetInfo, arma::mat>", 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.
@@ -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<arma::mat>("input");
vector<int>& indices = params.Get<vector<int> >("dimensions");
vector<size_t> copyIndices(indices.size());
RequireParamValue<std::vector<int>>(params, "dimensions",
[data](std::vector<int> 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<data::DatasetInfo, arma::mat>& t =
params.Get<std::tuple<data::DatasetInfo, arma::mat>>("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<int>& indices = params.Get<vector<int>>("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<std::vector<int>>(params, "dimensions",
[data](std::vector<int> 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<size_t> 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<size_t>)(copyIndices), output);
if (params.Has("output"))
params.Get<arma::mat>("output") = std::move(output);
}
else if (params.Has("output"))
{
params.Get<arma::mat>("output") = data; // Copy input to output.
}
arma::mat output;
data::OneHotEncoding(data, (arma::Col<size_t>)(copyIndices), output);
if (params.Has("output"))
params.Get<arma::mat>("output") = std::move(output);
}
@@ -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<vector<int>>("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<vector<int>>("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<vector<int>>("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<vector<int>>("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<vector<int>>("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<vector<int>>("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<double>("0", 2);
(void) info.MapString<double>("1", 2);
(void) info.MapString<double>("2", 2);
REQUIRE(info.NumMappings(2) == 3);
SetInputParam("input", std::make_tuple(info, dataset));
RUN_BINDING();
arma::mat output = params.Get<arma::mat>("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<arma::mat>("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<double>("0", 0);
(void) info.MapString<double>("1", 0);
(void) info.MapString<double>("2", 0);
(void) info.MapString<double>("3", 0);
info.Type(2) = data::Datatype::categorical;
(void) info.MapString<double>("0", 2);
(void) info.MapString<double>("1", 2);
(void) info.MapString<double>("2", 2);
info.Type(3) = data::Datatype::categorical;
(void) info.MapString<double>("0", 3);
(void) info.MapString<double>("1", 3);
SetInputParam("input", std::make_tuple(info, dataset));
RUN_BINDING();
arma::mat output = params.Get<arma::mat>("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<double>("0", 0);
(void) info.MapString<double>("1", 0);
(void) info.MapString<double>("2", 0);
(void) info.MapString<double>("3", 0);
info.Type(2) = data::Datatype::categorical;
(void) info.MapString<double>("0", 2);
(void) info.MapString<double>("1", 2);
(void) info.MapString<double>("2", 2);
info.Type(3) = data::Datatype::categorical;
(void) info.MapString<double>("0", 3);
(void) info.MapString<double>("1", 3);
SetInputParam("input", std::make_tuple(info, dataset));
SetInputParam<vector<int>>("dimensions", {0, 2});
RUN_BINDING();
arma::mat output = params.Get<arma::mat>("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);
}
@@ -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;