diff --git a/HISTORY.md b/HISTORY.md index e3ba45d0a7..a85d71443a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -44,6 +44,11 @@ * Fix divide-by-zero edge case for LARS (#3701). + * Templatize `SparseCoding` and `LocalCoordinateCoding` to allow different + matrix types (#3709, #3711). + + * Fix handling of unused atoms in `LocalCoordinateCoding` (#3711). + * Move minimum required C++ version from C++14 to C++17 (#3704). ### mlpack 4.3.0 diff --git a/doc/index.md b/doc/index.md index ad139d423b..d733726ec9 100644 --- a/doc/index.md +++ b/doc/index.md @@ -120,6 +120,8 @@ Prepare data for machine learning algorithms. Transform data from one space to another. + * [`LocalCoordinateCoding`](user/methods/local_coordinate_coding.md): local + coordinate coding with dictionary learning * [`NMF`](user/methods/nmf.md): non-negative matrix factorization * [`PCA`](user/methods/pca.md): principal components analysis * [`SparseCoding`](user/methods/sparse_coding.md): sparse coding with diff --git a/doc/sidebar.html b/doc/sidebar.html index 1f5d15fe67..3f4aaeabd8 100644 --- a/doc/sidebar.html +++ b/doc/sidebar.html @@ -179,6 +179,11 @@ when the sidebar is built for each page. " >> "$output_file.side.tmp"; + echo "" >> "$sb_output_file.side.tmp"; fi # Create the new details block. - echo "
  • " >> "$output_file.side.tmp"; - echo "" >> "$output_file.side.tmp"; - echo "$anchor_title" >> "$output_file.side.tmp"; - echo "" >> "$output_file.side.tmp"; - echo "" >> "$output_file.side.tmp"; - echo "
  • " >> "$sb_output_file.side.tmp"; fi - rm -f "$output_file.side.list.tmp"; + rm -f "$sb_output_file.side.list.tmp"; else # On other pages, the page title is encoded as an h1. - page_title=`grep '

    \(.*\)<\/h1>/\1/'`; - grep '

    \(.*\)<\/h2>/
  • \2<\/a><\/li>/' > "$output_file.side.tmp"; + grep '

    \(.*\)<\/h2>/
  • \2<\/a><\/li>/' \ + > "$sb_output_file.side.tmp"; fi - lines=`cat "$output_file.side.tmp" | wc -l`; + lines=`cat "$sb_output_file.side.tmp" | wc -l`; - echo "" >> "$sb_output_file"; + echo "" >> "$sb_output_file"; - rm -f "$output_file.side.tmp"; + rm -f "$sb_output_file.side.tmp"; } rm -rf "$output_dir"; diff --git a/src/mlpack/methods/local_coordinate_coding/lcc.hpp b/src/mlpack/methods/local_coordinate_coding/lcc.hpp index 4ff9904595..11b96d53b3 100644 --- a/src/mlpack/methods/local_coordinate_coding/lcc.hpp +++ b/src/mlpack/methods/local_coordinate_coding/lcc.hpp @@ -75,9 +75,13 @@ namespace mlpack { * } * @endcode */ +template class LocalCoordinateCoding { public: + typedef typename GetColType::type ColType; + typedef typename GetRowType::type RowType; + /** * Set the parameters to LocalCoordinateCoding, and train the dictionary. * This constructor will also initialize the dictionary using the given @@ -85,7 +89,7 @@ class LocalCoordinateCoding * * If you want to initialize the dictionary to a custom matrix, consider * either writing your own DictionaryInitializer class (with void - * Initialize(const arma::mat& data, arma::mat& dictionary) function), or call + * Initialize(const MatType& data, MatType& dictionary) function), or call * the constructor that does not take a data matrix, then call Dictionary() to * set the dictionary matrix to a matrix of your choosing, and then call * Train() with NothingInitializer (i.e. Train(data)). @@ -99,7 +103,7 @@ class LocalCoordinateCoding * @param initializer Intializer to use. */ template - LocalCoordinateCoding(const arma::mat& data, + LocalCoordinateCoding(const MatType& data, const size_t atoms, const double lambda, const size_t maxIterations = 0, @@ -132,7 +136,7 @@ class LocalCoordinateCoding * @return The final objective value. */ template - double Train(const arma::mat& data, + double Train(const MatType& data, const DictionaryInitializer& initializer = DictionaryInitializer()); @@ -142,7 +146,7 @@ class LocalCoordinateCoding * @param data Matrix containing points to encode. * @param codes Output matrix to store codes in. */ - void Encode(const arma::mat& data, arma::mat& codes); + void Encode(const MatType& data, MatType& codes); /** * Learn dictionary by solving linear system. @@ -153,10 +157,19 @@ class LocalCoordinateCoding * the coding matrix Z that are non-zero (the adjacency matrix for the * bipartite graph of points and atoms) */ - void OptimizeDictionary(const arma::mat& data, - const arma::mat& codes, + void OptimizeDictionary(const MatType& data, + const MatType& codes, const arma::uvec& adjacencies); + /** + * Compute objective function given the list of adjacencies. + * + * @param data Matrix containing points to encode. + * @param codes Output matrix to store codes in. + */ + double Objective(const MatType& data, + const MatType& codes) const; + /** * Compute objective function given the list of adjacencies. * @@ -166,8 +179,8 @@ class LocalCoordinateCoding * the coding matrix Z that are non-zero (the adjacency matrix for the * bipartite graph of points and atoms) */ - double Objective(const arma::mat& data, - const arma::mat& codes, + double Objective(const MatType& data, + const MatType& codes, const arma::uvec& adjacencies) const; //! Get the number of atoms. @@ -176,9 +189,9 @@ class LocalCoordinateCoding size_t& Atoms() { return atoms; } //! Accessor for dictionary. - const arma::mat& Dictionary() const { return dictionary; } + const MatType& Dictionary() const { return dictionary; } //! Mutator for dictionary. - arma::mat& Dictionary() { return dictionary; } + MatType& Dictionary() { return dictionary; } //! Get the L1 regularization parameter. double Lambda() const { return lambda; } @@ -204,7 +217,7 @@ class LocalCoordinateCoding size_t atoms; //! Dictionary (columns are atoms). - arma::mat dictionary; + MatType dictionary; //! l1 regularization term. double lambda; @@ -217,6 +230,9 @@ class LocalCoordinateCoding } // namespace mlpack +CEREAL_TEMPLATE_CLASS_VERSION((typename MatType), + (mlpack::LocalCoordinateCoding), (1)); + // Include implementation. #include "lcc_impl.hpp" diff --git a/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp b/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp index bbaf7817ba..2894d015f6 100644 --- a/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp +++ b/src/mlpack/methods/local_coordinate_coding/lcc_impl.hpp @@ -17,9 +17,10 @@ namespace mlpack { +template template -LocalCoordinateCoding::LocalCoordinateCoding( - const arma::mat& data, +LocalCoordinateCoding::LocalCoordinateCoding( + const MatType& data, const size_t atoms, const double lambda, const size_t maxIterations, @@ -34,7 +35,8 @@ LocalCoordinateCoding::LocalCoordinateCoding( Train(data, initializer); } -inline LocalCoordinateCoding::LocalCoordinateCoding( +template +inline LocalCoordinateCoding::LocalCoordinateCoding( const size_t atoms, const double lambda, const size_t maxIterations, @@ -47,9 +49,10 @@ inline LocalCoordinateCoding::LocalCoordinateCoding( // Nothing to do. } +template template -double LocalCoordinateCoding::Train( - const arma::mat& data, +double LocalCoordinateCoding::Train( + const MatType& data, const DictionaryInitializer& initializer) { // Initialize the dictionary. @@ -61,7 +64,7 @@ double LocalCoordinateCoding::Train( // loop. Log::Info << "Initial Coding Step." << std::endl; - arma::mat codes; + MatType codes; Encode(data, codes); arma::uvec adjacencies = find(codes); @@ -115,15 +118,16 @@ double LocalCoordinateCoding::Train( return lastObjVal; } -inline void LocalCoordinateCoding::Encode(const arma::mat& data, - arma::mat& codes) +template +inline void LocalCoordinateCoding::Encode(const MatType& data, + MatType& codes) { - arma::mat invSqDists = 1.0 / (repmat(trans(sum(square(dictionary))), 1, + MatType invSqDists = 1.0 / (repmat(trans(sum(square(dictionary))), 1, data.n_cols) + repmat(sum(square(data)), atoms, 1) - 2 * trans(dictionary) * data); - arma::mat dictGram = trans(dictionary) * dictionary; - arma::mat dictGramTD(dictGram.n_rows, dictGram.n_cols); + MatType dictGram = trans(dictionary) * dictionary; + MatType dictGramTD(dictGram.n_rows, dictGram.n_cols); codes.set_size(atoms, data.n_cols); for (size_t i = 0; i < data.n_cols; ++i) @@ -134,29 +138,31 @@ inline void LocalCoordinateCoding::Encode(const arma::mat& data, Log::Debug << "Optimization at point " << i << "." << std::endl; } - arma::vec invW = invSqDists.unsafe_col(i); - arma::mat dictPrime = dictionary * diagmat(invW); + ColType invW = invSqDists.unsafe_col(i); + MatType dictPrime = dictionary * diagmat(invW); - arma::mat dictGramTD = diagmat(invW) * dictGram * diagmat(invW); + MatType dictGramTD = diagmat(invW) * dictGram * diagmat(invW); bool useCholesky = false; // Normalization and fitting and intercept are disabled. - LARS<> lars(useCholesky, 0.5 * lambda, 0, 1e-16 /* default tolerance */, - false, false); + const double tol = std::is_same::value ? + 1e-8 : 1e-16; + LARS lars(useCholesky, 0.5 * lambda, 0, tol, false, false); // Run LARS for this point, by making an alias of the point and passing // that. - arma::vec beta = codes.unsafe_col(i); - arma::rowvec responses = data.unsafe_col(i).t(); + ColType beta = codes.unsafe_col(i); + RowType responses = data.unsafe_col(i).t(); lars.Train(dictPrime, responses, false, useCholesky, dictGramTD); beta = lars.Beta(); beta %= invW; // Remember, beta is an alias of codes.col(i). } } -inline void LocalCoordinateCoding::OptimizeDictionary( - const arma::mat& data, - const arma::mat& codes, +template +inline void LocalCoordinateCoding::OptimizeDictionary( + const MatType& data, + const MatType& codes, const arma::uvec& adjacencies) { // Count number of atomic neighbors for each point x^i. @@ -184,7 +190,8 @@ inline void LocalCoordinateCoding::OptimizeDictionary( // Build dataPrime := [X x^1 ... x^1 ... x^n ... x^n] // where each x^i is repeated for the number of neighbors x^i has. - arma::mat dataPrime = zeros(data.n_rows, data.n_cols + adjacencies.n_elem); + MatType dataPrime = zeros(data.n_rows, + data.n_cols + adjacencies.n_elem); dataPrime(arma::span::all, arma::span(0, data.n_cols - 1)) = data; @@ -209,9 +216,9 @@ inline void LocalCoordinateCoding::OptimizeDictionary( const size_t nInactiveAtoms = atoms - nActiveAtoms; // Efficient construction of codes restricted to active atoms. - arma::mat codesPrime = zeros(nActiveAtoms, data.n_cols + + MatType codesPrime = zeros(nActiveAtoms, data.n_cols + adjacencies.n_elem); - arma::vec wSquared = ones(data.n_cols + adjacencies.n_elem, 1); + ColType wSquared = ones(data.n_cols + adjacencies.n_elem, 1); if (nInactiveAtoms > 0) { @@ -219,13 +226,13 @@ inline void LocalCoordinateCoding::OptimizeDictionary( << " inactive atoms. They will be re-initialized randomly.\n"; // Create matrix holding only active codes. - arma::mat activeCodes = codes.rows(arma::uvec(activeAtoms)); + MatType activeCodes = codes.rows(arma::uvec(activeAtoms)); // Create reverse atom lookup for active atoms. arma::uvec atomReverseLookup(atoms); for (size_t i = 0; i < activeAtoms.size(); ++i) { - atomReverseLookup[i] = activeAtoms[i]; + atomReverseLookup[activeAtoms[i]] = i; } codesPrime(arma::span::all, arma::span(0, data.n_cols - 1)) = activeCodes; @@ -259,15 +266,18 @@ inline void LocalCoordinateCoding::OptimizeDictionary( } } - wSquared.subvec(data.n_cols, wSquared.n_elem - 1) = lambda * - abs(wSquared.subvec(data.n_cols, wSquared.n_elem - 1)); + if (adjacencies.n_elem > 0) + { + wSquared.subvec(data.n_cols, wSquared.n_elem - 1) = lambda * + abs(wSquared.subvec(data.n_cols, wSquared.n_elem - 1)); + } // Solve system. if (nInactiveAtoms == 0) { // No inactive atoms. We can solve directly. - arma::mat A = codesPrime * diagmat(wSquared) * trans(codesPrime); - arma::mat B = codesPrime * diagmat(wSquared) * trans(dataPrime); + MatType A = codesPrime * diagmat(wSquared) * trans(codesPrime); + MatType B = codesPrime * diagmat(wSquared) * trans(dataPrime); dictionary = trans(solve(A, B)); /* @@ -279,7 +289,7 @@ inline void LocalCoordinateCoding::OptimizeDictionary( { // Inactive atoms must be reinitialized randomly, so we cannot solve // directly for the entire dictionary estimate. - arma::mat dictionaryActive = + MatType dictionaryActive = trans(solve(codesPrime * diagmat(wSquared) * trans(codesPrime), codesPrime * diagmat(wSquared) * trans(dataPrime))); @@ -310,9 +320,19 @@ inline void LocalCoordinateCoding::OptimizeDictionary( } } -inline double LocalCoordinateCoding::Objective( - const arma::mat& data, - const arma::mat& codes, +template +inline double LocalCoordinateCoding::Objective( + const MatType& data, + const MatType& codes) const +{ + // Compute adjacencies and pass off to other overload. + return Objective(data, codes, find(codes)); +} + +template +inline double LocalCoordinateCoding::Objective( + const MatType& data, + const MatType& codes, const arma::uvec& adjacencies) const { double weightedL1NormZ = 0; @@ -331,11 +351,26 @@ inline double LocalCoordinateCoding::Objective( return std::pow(froNormResidual, 2.0) + lambda * weightedL1NormZ; } +template template -void LocalCoordinateCoding::serialize(Archive& ar, - const uint32_t /* version */) +void LocalCoordinateCoding::serialize(Archive& ar, + const uint32_t version) { ar(CEREAL_NVP(atoms)); + + if (cereal::is_loading() && version == 0) + { + // Older versions of LocalCoordinateCoding always stored dictionary as an + // arma::mat. + arma::mat dictionaryTmp; + ar(cereal::make_nvp("dictionary", dictionaryTmp)); + dictionary = ConvTo::From(dictionaryTmp); + } + else + { + ar(CEREAL_NVP(dictionary)); + } + ar(CEREAL_NVP(dictionary)); ar(CEREAL_NVP(lambda)); ar(CEREAL_NVP(maxIterations)); diff --git a/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp b/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp index 7a028867cf..50418d9d1f 100644 --- a/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp +++ b/src/mlpack/methods/local_coordinate_coding/local_coordinate_coding_main.cpp @@ -90,8 +90,7 @@ BINDING_SEE_ALSO("Nonlinear learning using local coordinate coding (pdf)", "https://papers.nips.cc/paper/3875-nonlinear-learning-using-local-" "coordinate-coding.pdf"); BINDING_SEE_ALSO("LocalCoordinateCoding C++ class documentation", - "@src/mlpack/methods/local_coordinate_coding/local_coordinate_coding." - "hpp"); + "@doc/user/methods/local_coordinate_coding.md"); // Training parameters. PARAM_MATRIX_IN("training", "Matrix of training data (X).", "t"); @@ -106,9 +105,9 @@ PARAM_FLAG("normalize", "If set, the input data matrix will be normalized " PARAM_DOUBLE_IN("tolerance", "Tolerance for objective function.", "o", 0.01); // Load/save a model. -PARAM_MODEL_IN(LocalCoordinateCoding, "input_model", "Input LCC model.", "m"); -PARAM_MODEL_OUT(LocalCoordinateCoding, "output_model", "Output for trained LCC " - "model.", "M"); +PARAM_MODEL_IN(LocalCoordinateCoding<>, "input_model", "Input LCC model.", "m"); +PARAM_MODEL_OUT(LocalCoordinateCoding<>, "output_model", + "Output for trained LCC model.", "M"); // Test on another dataset. PARAM_MATRIX_IN("test", "Test points to encode.", "T"); @@ -143,9 +142,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) ReportIgnoredParam(params, {{ "training", false }}, "tolerance"); // Do we have an existing model? - LocalCoordinateCoding* lcc = NULL; + LocalCoordinateCoding<>* lcc = NULL; if (params.Has("input_model")) - lcc = params.Get("input_model"); + lcc = params.Get*>("input_model"); if (params.Has("training")) { @@ -171,7 +170,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) [](double x) { return x > 0; }, 1, "Tolerance should be a positive real number"); - lcc = new LocalCoordinateCoding(0, 0.0); + lcc = new LocalCoordinateCoding<>(0, 0.0); lcc->Lambda() = params.Get("lambda"); lcc->Atoms() = (size_t) params.Get("atoms"); @@ -257,5 +256,5 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) // Save the dictionary and the model. params.Get("dictionary") = lcc->Dictionary(); - params.Get("output_model") = lcc; + params.Get*>("output_model") = lcc; } diff --git a/src/mlpack/methods/sparse_coding/sparse_coding.hpp b/src/mlpack/methods/sparse_coding/sparse_coding.hpp index 7beb09e258..ba22c17798 100644 --- a/src/mlpack/methods/sparse_coding/sparse_coding.hpp +++ b/src/mlpack/methods/sparse_coding/sparse_coding.hpp @@ -108,7 +108,7 @@ namespace mlpack { * the Encode() function. * * @tparam DictionaryInitializationPolicy The class to use to initialize the - * dictionary; must have 'void Initialize(const arma::mat& data, arma::mat& + * dictionary; must have 'void Initialize(const MatType& data, MatType& * dictionary)' function. */ template @@ -127,7 +127,7 @@ class SparseCoding * * If you want to initialize the dictionary to a custom matrix, consider * either writing your own DictionaryInitializer class (with void - * Initialize(const arma::mat& data, arma::mat& dictionary) function), or call + * Initialize(const MatType& data, MatType& dictionary) function), or call * the constructor that does not take a data matrix, then call Dictionary() to * set the dictionary matrix to a matrix of your choosing, and then call * Train() with NothingInitializer (i.e. Train(data)). diff --git a/src/mlpack/tests/ann/convolutional_network_test.cpp b/src/mlpack/tests/ann/convolutional_network_test.cpp index 313cee7c17..209ac5b131 100644 --- a/src/mlpack/tests/ann/convolutional_network_test.cpp +++ b/src/mlpack/tests/ann/convolutional_network_test.cpp @@ -71,7 +71,7 @@ void CheckMoveFunction(ModelType* network1, TEST_CASE("PaddingTest", "[ConvolutionalNetworktest]") { arma::mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + X.load("mnist_first250_training_4s_and_9s.csv"); // Create the network. FFN model; @@ -148,7 +148,7 @@ TEST_CASE("MaxPoolingTest", "[ConvolutionalNetworkTest]") TEST_CASE("VanillaNetworkTest", "[ConvolutionalNetworkTest]") { arma::mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + X.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. arma::uword nPoints = X.n_cols; @@ -264,7 +264,7 @@ TEST_CASE("VanillaNetworkBatchSizeTest", "[ConvolutionalNetworkTest]") model.InputDimensions() = std::vector({ 28, 28 }); arma::mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + X.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. arma::uword nPoints = X.n_cols; @@ -347,7 +347,7 @@ TEST_CASE("VanillaNetworkBatchSizeTest", "[ConvolutionalNetworkTest]") TEST_CASE("CheckCopyVanillaNetworkTest", "[ConvolutionalNetworkTest]") { arma::mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + X.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. arma::uword nPoints = X.n_cols; diff --git a/src/mlpack/tests/ann/feedforward_network_test.cpp b/src/mlpack/tests/ann/feedforward_network_test.cpp index 13007e71db..4f349b2bfa 100644 --- a/src/mlpack/tests/ann/feedforward_network_test.cpp +++ b/src/mlpack/tests/ann/feedforward_network_test.cpp @@ -400,7 +400,7 @@ TEST_CASE("FFVanillaNetworkTest", "[FeedForwardNetworkTest]") TestNetwork<>(model, trainData, trainLabels, testData, testLabels, 10, 0.1); arma::mat dataset; - dataset.load("mnist_first250_training_4s_and_9s.arm"); + dataset.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. for (size_t i = 0; i < dataset.n_cols; ++i) @@ -421,7 +421,7 @@ TEST_CASE("FFVanillaNetworkTest", "[FeedForwardNetworkTest]") TEST_CASE("ForwardBackwardTest", "[FeedForwardNetworkTest]") { arma::mat dataset; - dataset.load("mnist_first250_training_4s_and_9s.arm"); + dataset.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. for (size_t i = 0; i < dataset.n_cols; ++i) @@ -548,7 +548,7 @@ TEST_CASE("DropoutNetworkTest", "[FeedForwardNetworkTest]") // network must be significant better than 92%. TestNetwork<>(model, trainData, trainLabels, testData, testLabels, 10, 0.1); arma::mat dataset; - dataset.load("mnist_first250_training_4s_and_9s.arm"); + dataset.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. for (size_t i = 0; i < dataset.n_cols; ++i) @@ -627,7 +627,7 @@ TEST_CASE("DropConnectNetworkTest", "[FeedForwardNetworkTest]") TestNetwork(model, trainData, trainLabels, testData, testLabels, 10, 0.1); arma::mat dataset; - dataset.load("mnist_first250_training_4s_and_9s.arm"); + dataset.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. for (size_t i = 0; i < dataset.n_cols; ++i) @@ -952,7 +952,7 @@ TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]") TestNetwork<>(model, trainData, trainLabels1, testData, testLabels, 10, 0.1); arma::mat dataset; - dataset.load("mnist_first250_training_4s_and_9s.arm"); + dataset.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. for (size_t i = 0; i < dataset.n_cols; ++i) diff --git a/src/mlpack/tests/ann/not_adapted/dcgan_test.cpp b/src/mlpack/tests/ann/not_adapted/dcgan_test.cpp index a38ebbecb3..4ed46ec2d9 100644 --- a/src/mlpack/tests/ann/not_adapted/dcgan_test.cpp +++ b/src/mlpack/tests/ann/not_adapted/dcgan_test.cpp @@ -53,7 +53,7 @@ TEST_CASE("DCGANMNISTTest", "[DCGANNetworkTest]") << " shuffle = " << shuffle << std::endl; arma::mat trainData; - trainData.load("mnist_first250_training_4s_and_9s.arm"); + trainData.load("mnist_first250_training_4s_and_9s.csv"); Log::Info << arma::size(trainData) << std::endl; trainData = trainData.cols(0, datasetMaxCols - 1); @@ -212,7 +212,7 @@ TEST_CASE("DCGANMNISTTest", "[DCGANNetworkTest]") << " shuffle = " << shuffle << std::endl; arma::mat trainData; - trainData.load("mnist_first250_training_4s_and_9s.arm"); + trainData.load("mnist_first250_training_4s_and_9s.csv"); Log::Info << arma::size(trainData) << std::endl; // trainData = trainData.cols(0, datasetMaxCols - 1); diff --git a/src/mlpack/tests/ann/not_adapted/feedforward_network_test.cpp b/src/mlpack/tests/ann/not_adapted/feedforward_network_test.cpp index 014f9b4579..f8ea2f199b 100644 --- a/src/mlpack/tests/ann/not_adapted/feedforward_network_test.cpp +++ b/src/mlpack/tests/ann/not_adapted/feedforward_network_test.cpp @@ -134,7 +134,7 @@ TEST_CASE("CheckCopyMovingReparametrizationNetworkTest", TEST_CASE("HighwayNetworkTest", "[FeedForwardNetworkTest]") { arma::mat dataset; - dataset.load("mnist_first250_training_4s_and_9s.arm"); + dataset.load("mnist_first250_training_4s_and_9s.csv"); // Normalize each point since these are images. for (size_t i = 0; i < dataset.n_cols; ++i) diff --git a/src/mlpack/tests/ann/not_adapted/gan_test.cpp b/src/mlpack/tests/ann/not_adapted/gan_test.cpp index 194ac4759a..6ba7447d23 100644 --- a/src/mlpack/tests/ann/not_adapted/gan_test.cpp +++ b/src/mlpack/tests/ann/not_adapted/gan_test.cpp @@ -156,7 +156,7 @@ TEST_CASE("GANMNISTTest", "[GANNetworkTest]") << " shuffle = " << shuffle << std::endl; arma::mat trainData; - trainData.load("mnist_first250_training_4s_and_9s.arm"); + trainData.load("mnist_first250_training_4s_and_9s.csv"); Log::Info << arma::size(trainData) << std::endl; trainData = trainData.cols(0, datasetMaxCols - 1); diff --git a/src/mlpack/tests/ann/not_adapted/wgan_test.cpp b/src/mlpack/tests/ann/not_adapted/wgan_test.cpp index 9772181216..8aacc73ac3 100644 --- a/src/mlpack/tests/ann/not_adapted/wgan_test.cpp +++ b/src/mlpack/tests/ann/not_adapted/wgan_test.cpp @@ -60,7 +60,7 @@ TEST_CASE("WGANMNISTTest", "[WGANNetworkTest]") << " shuffle = " << shuffle << std::endl; arma::mat trainData; - trainData.load("mnist_first250_training_4s_and_9s.arm"); + trainData.load("mnist_first250_training_4s_and_9s.csv"); Log::Info << arma::size(trainData) << std::endl; trainData = trainData.cols(0, datasetMaxCols - 1); @@ -222,7 +222,7 @@ TEST_CASE("WGANGPMNISTTest", "[WGANNetworkTest]") << " shuffle = " << shuffle << std::endl; arma::mat trainData; - trainData.load("mnist_first250_training_4s_and_9s.arm"); + trainData.load("mnist_first250_training_4s_and_9s.csv"); Log::Info << arma::size(trainData) << std::endl; trainData = trainData.cols(0, datasetMaxCols - 1); diff --git a/src/mlpack/tests/data/mnist_first250_training_4s_and_9s.tar.bz2 b/src/mlpack/tests/data/mnist_first250_training_4s_and_9s.tar.bz2 index 63a9e279a6..4eb4d3ff1f 100644 Binary files a/src/mlpack/tests/data/mnist_first250_training_4s_and_9s.tar.bz2 and b/src/mlpack/tests/data/mnist_first250_training_4s_and_9s.tar.bz2 differ diff --git a/src/mlpack/tests/local_coordinate_coding_test.cpp b/src/mlpack/tests/local_coordinate_coding_test.cpp index 89e960f65f..6809a11bf8 100644 --- a/src/mlpack/tests/local_coordinate_coding_test.cpp +++ b/src/mlpack/tests/local_coordinate_coding_test.cpp @@ -18,7 +18,10 @@ using namespace arma; using namespace mlpack; -void VerifyCorrectness(const vec& beta, const vec& errCorr, double lambda) +template +void VerifyCorrectness(const MatType& beta, + const VecType& errCorr, + const double lambda) { const double tol = 0.1; size_t nDims = beta.n_elem; @@ -43,15 +46,18 @@ void VerifyCorrectness(const vec& beta, const vec& errCorr, double lambda) } } - -TEST_CASE("LocalCoordinateCodingTestCodingStep", - "[LocalCoordinateCodingTest]") +TEMPLATE_TEST_CASE("LocalCoordinateCodingTestCodingStep", + "[LocalCoordinateCodingTest]", arma::mat, arma::fmat) { + typedef TestType MatType; + typedef arma::Col VecType; + double lambda1 = 0.1; uword nAtoms = 10; - mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + mat inX; // The .arm file is saved as an arma::mat. + inX.load("mnist_first250_training_4s_and_9s.csv"); + MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols; // normalize each point since these are images @@ -60,37 +66,40 @@ TEST_CASE("LocalCoordinateCodingTestCodingStep", X.col(i) /= norm(X.col(i), 2); } - mat Z; - LocalCoordinateCoding lcc(X, nAtoms, lambda1, 10); + MatType Z; + LocalCoordinateCoding lcc(X, nAtoms, lambda1, 10); lcc.Encode(X, Z); - mat D = lcc.Dictionary(); + MatType D = lcc.Dictionary(); for (uword i = 0; i < nPoints; ++i) { - vec sqDists = vec(nAtoms); + VecType sqDists(nAtoms); for (uword j = 0; j < nAtoms; ++j) { sqDists[j] = arma::norm(D.col(j) - X.col(i)); } - mat Dprime = D * diagmat(1.0 / sqDists); - mat zPrime = Z.unsafe_col(i) % sqDists; + MatType Dprime = D * diagmat(1.0 / sqDists); + MatType zPrime = Z.unsafe_col(i) % sqDists; - vec errCorr = trans(Dprime) * (Dprime * zPrime - X.unsafe_col(i)); + VecType errCorr = trans(Dprime) * (Dprime * zPrime - X.unsafe_col(i)); VerifyCorrectness(zPrime, errCorr, 0.5 * lambda1); } } -TEST_CASE("LocalCoordinateCodingTestDictionaryStep", - "[LocalCoordinateCodingTest]") +TEMPLATE_TEST_CASE("LocalCoordinateCodingTestDictionaryStep", + "[LocalCoordinateCodingTest]", arma::mat, arma::fmat) { + typedef TestType MatType; + const double tol = 0.1; double lambda = 0.1; uword nAtoms = 10; - mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + mat inX; // File is saved as an arma::mat. + inX.load("mnist_first250_training_4s_and_9s.csv"); + MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols; // normalize each point since these are images @@ -99,15 +108,15 @@ TEST_CASE("LocalCoordinateCodingTestDictionaryStep", X.col(i) /= norm(X.col(i), 2); } - mat Z; - LocalCoordinateCoding lcc(X, nAtoms, lambda, 10); + MatType Z; + LocalCoordinateCoding lcc(X, nAtoms, lambda, 10); lcc.Encode(X, Z); uvec adjacencies = find(Z); lcc.OptimizeDictionary(X, Z, adjacencies); - mat D = lcc.Dictionary(); + MatType D = lcc.Dictionary(); - mat grad = zeros(D.n_rows, D.n_cols); + MatType grad = zeros(D.n_rows, D.n_cols); for (uword i = 0; i < nPoints; ++i) { grad += (D - repmat(X.unsafe_col(i), 1, nAtoms)) * @@ -118,26 +127,30 @@ TEST_CASE("LocalCoordinateCodingTestDictionaryStep", REQUIRE(norm(grad, "fro") == Approx(0.0).margin(tol)); } -TEST_CASE("LocalCoordinateCodingSerializationTest", - "[LocalCoordinateCodingTest]") +TEMPLATE_TEST_CASE("LocalCoordinateCodingSerializationTest", + "[LocalCoordinateCodingTest]", arma::mat, arma::fmat) { - mat X = randu(100, 100); + typedef TestType MatType; + + MatType X = randu(100, 100); size_t nAtoms = 10; - LocalCoordinateCoding lcc(nAtoms, 0.05, 2 /* don't care about quality */); + LocalCoordinateCoding lcc(nAtoms, 0.05, + 2 /* don't care about quality */); lcc.Train(X); - mat Y = randu(100, 200); - mat codes; + MatType Y = randu(100, 200); + MatType codes; lcc.Encode(Y, codes); - LocalCoordinateCoding lccXml(50, 0.1), lccJson(12, 0.0), lccBinary(0, 0.0); + LocalCoordinateCoding lccXml(50, 0.1), lccJson(12, 0.0), + lccBinary(0, 0.0); SerializeObjectAll(lcc, lccXml, lccJson, lccBinary); CheckMatrices(lcc.Dictionary(), lccXml.Dictionary(), lccJson.Dictionary(), lccBinary.Dictionary()); - mat xmlCodes, jsonCodes, binaryCodes; + MatType xmlCodes, jsonCodes, binaryCodes; lccXml.Encode(Y, xmlCodes); lccJson.Encode(Y, jsonCodes); lccBinary.Encode(Y, binaryCodes); @@ -167,14 +180,17 @@ TEST_CASE("LocalCoordinateCodingSerializationTest", * Test that LocalCoordinateCoding::Train() returns finite final objective * value. */ -TEST_CASE("LocalCoordinateCodingTrainReturnObjective", - "[LocalCoordinateCodingTest]") +TEMPLATE_TEST_CASE("LocalCoordinateCodingTrainReturnObjective", + "[LocalCoordinateCodingTest]", arma::mat, arma::fmat) { + typedef TestType MatType; + double lambda1 = 0.1; uword nAtoms = 10; - mat X; - X.load("mnist_first250_training_4s_and_9s.arm"); + mat inX; // File is saved as arma::mat. + inX.load("mnist_first250_training_4s_and_9s.csv"); + MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols; // Normalize each point since these are images. @@ -183,7 +199,7 @@ TEST_CASE("LocalCoordinateCodingTrainReturnObjective", X.col(i) /= norm(X.col(i), 2); } - LocalCoordinateCoding lcc(nAtoms, lambda1, 10); + LocalCoordinateCoding lcc(nAtoms, lambda1, 10); double objVal = lcc.Train(X); REQUIRE(std::isfinite(objVal) == true); diff --git a/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp b/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp index 74c271282d..b8cfbc02f0 100644 --- a/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp +++ b/src/mlpack/tests/main_tests/local_coordinate_coding_test.cpp @@ -32,7 +32,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCDimensionsTest", "[LCCMainTest][BindingTests]") { arma::mat x; - x.load("mnist_first250_training_4s_and_9s.arm"); + x.load("mnist_first250_training_4s_and_9s.csv"); int rows = x.n_rows, cols = x.n_cols; arma::mat t = x; int atoms = 10; @@ -58,7 +58,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCOutputModelTest", "[LCCMainTest][BindingTests]") { arma::mat x; - x.load("mnist_first250_training_4s_and_9s.arm"); + x.load("mnist_first250_training_4s_and_9s.csv"); arma::mat t = x; SetInputParam("training", std::move(x)); @@ -71,8 +71,8 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCOutputModelTest", // Get the encoded output and dictionary after training. arma::mat initCodes = std::move(params.Get("codes")); arma::mat initDict = std::move(params.Get("dictionary")); - LocalCoordinateCoding* outputModel = - std::move(params.Get("output_model")); + LocalCoordinateCoding<>* outputModel = + std::move(params.Get*>("output_model")); ResetSettings(); @@ -129,7 +129,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainAndTestDataDimTest", "[LCCMainTest][BindingTests]") { arma::mat x; - x.load("mnist_first250_training_4s_and_9s.arm"); + x.load("mnist_first250_training_4s_and_9s.csv"); arma::mat t = x; t.shed_rows(1, 2); @@ -150,7 +150,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainAndInputModelTest", "[LCCMainTest][BindingTests]") { arma::mat x; - x.load("mnist_first250_training_4s_and_9s.arm"); + x.load("mnist_first250_training_4s_and_9s.csv"); SetInputParam("training", x); SetInputParam("atoms", (int) 10); @@ -158,8 +158,8 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainAndInputModelTest", RUN_BINDING(); - LocalCoordinateCoding* outputModel = - std::move(params.Get("output_model")); + LocalCoordinateCoding<>* outputModel = + std::move(params.Get*>("output_model")); // No need to input training data again. SetInputParam("input_model", std::move(outputModel)); @@ -175,7 +175,7 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainedModelDimTest", "[LCCMainTest][BindingTests]") { arma::mat x; - x.load("mnist_first250_training_4s_and_9s.arm"); + x.load("mnist_first250_training_4s_and_9s.csv"); arma:: mat t = x; t.shed_rows(1, 2); @@ -185,8 +185,8 @@ TEST_CASE_METHOD(LCCTestFixture, "LCCTrainedModelDimTest", RUN_BINDING(); - LocalCoordinateCoding* outputModel = - std::move(params.Get("output_model")); + LocalCoordinateCoding<>* outputModel = + std::move(params.Get*>("output_model")); SetInputParam("input_model", std::move(outputModel)); SetInputParam("test", std::move(t)); diff --git a/src/mlpack/tests/sparse_coding_test.cpp b/src/mlpack/tests/sparse_coding_test.cpp index 582ddad38e..fa22dbc9cc 100644 --- a/src/mlpack/tests/sparse_coding_test.cpp +++ b/src/mlpack/tests/sparse_coding_test.cpp @@ -57,7 +57,7 @@ TEMPLATE_TEST_CASE("SparseCodingTestCodingStepLasso", "[SparseCodingTest]", uword nAtoms = 25; arma::mat inX; // The .arm file contains an arma::mat. - inX.load("mnist_first250_training_4s_and_9s.arm"); + inX.load("mnist_first250_training_4s_and_9s.csv"); MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols; @@ -92,7 +92,7 @@ TEMPLATE_TEST_CASE("SparseCodingTestCodingStepElasticNet", "[SparseCodingTest]", uword nAtoms = 25; arma::mat inX; // The .arm file contains an arma::mat. - inX.load("mnist_first250_training_4s_and_9s.arm"); + inX.load("mnist_first250_training_4s_and_9s.csv"); MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols; @@ -129,7 +129,7 @@ TEMPLATE_TEST_CASE("SparseCodingTestDictionaryStep", "[SparseCodingTest]", uword nAtoms = 25; arma::mat inX; // The .arm file contains an arma::mat. - inX.load("mnist_first250_training_4s_and_9s.arm"); + inX.load("mnist_first250_training_4s_and_9s.csv"); MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols; @@ -222,7 +222,7 @@ TEMPLATE_TEST_CASE("SparseCodingTrainReturnObjective", "[SparseCodingTest]", uword nAtoms = 25; arma::mat inX; // The .arm file contains an arma::mat. - inX.load("mnist_first250_training_4s_and_9s.arm"); + inX.load("mnist_first250_training_4s_and_9s.csv"); MatType X = arma::conv_to::from(inX); uword nPoints = X.n_cols;