[mlpack-git] master: Remove data and codes members from SparseCoding. (61f9a47)

gitdub at big.cc.gt.atl.ga.us gitdub at big.cc.gt.atl.ga.us
Mon Dec 7 09:47:47 EST 2015


Repository : https://github.com/mlpack/mlpack

On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/1efafa13b304c7821d858754b0d2dab9a05795a7...c2d22d60c3355e82b45e6596d721c3905351989c

>---------------------------------------------------------------

commit 61f9a475a9e3bb09399696c7dcec90967ddbb2ea
Author: Ryan Curtin <ryan at ratml.org>
Date:   Sun Dec 6 20:33:33 2015 +0000

    Remove data and codes members from SparseCoding.
    
    These are only necessary during training time, so, we should not hold on to
    them.


>---------------------------------------------------------------

61f9a475a9e3bb09399696c7dcec90967ddbb2ea
 src/mlpack/methods/sparse_coding/sparse_coding.hpp | 27 ++++-----------
 .../methods/sparse_coding/sparse_coding_impl.hpp   | 40 ++++++++++++----------
 src/mlpack/tests/sparse_coding_test.cpp            | 23 +++++++------
 3 files changed, 41 insertions(+), 49 deletions(-)

diff --git a/src/mlpack/methods/sparse_coding/sparse_coding.hpp b/src/mlpack/methods/sparse_coding/sparse_coding.hpp
index b1d33b5..f764f5d 100644
--- a/src/mlpack/methods/sparse_coding/sparse_coding.hpp
+++ b/src/mlpack/methods/sparse_coding/sparse_coding.hpp
@@ -166,7 +166,7 @@ class SparseCoding
   /**
    * Sparse code each point via LARS.
    */
-  void OptimizeCode();
+  void OptimizeCode(const arma::mat& data, arma::mat& codes);
 
   /**
    * Learn dictionary via Newton method based on Lagrange dual.
@@ -175,12 +175,14 @@ class SparseCoding
    *    the coding matrix Z that are non-zero (the adjacency matrix for the
    *    bipartite graph of points and atoms).
    * @param newtonTolerance Tolerance of the Newton's method optimizer.
-   * @param maxIterations Maximum number of iterations to run the Newton's method.
-   *     If 0, the method will run until convergence (or forever).
+   * @param maxIterations Maximum number of iterations to run the Newton's
+   *     method. If 0, the method will run until convergence (or forever).
    * @return the norm of the gradient of the Lagrange dual with respect to
    *    the dual variables
    */
-  double OptimizeDictionary(const arma::uvec& adjacencies,
+  double OptimizeDictionary(const arma::mat& data,
+                            const arma::mat& codes,
+                            const arma::uvec& adjacencies,
                             const double newtonTolerance = 1e-6,
                             const size_t maxIterations = 50);
 
@@ -192,21 +194,13 @@ class SparseCoding
   /**
    * Compute the objective function.
    */
-  double Objective() const;
-
-  //! Access the data.
-  const arma::mat& Data() const { return data; }
+  double Objective(const arma::mat& data, const arma::mat& codes) const;
 
   //! Access the dictionary.
   const arma::mat& Dictionary() const { return dictionary; }
   //! Modify the dictionary.
   arma::mat& Dictionary() { return dictionary; }
 
-  //! Access the sparse codes.
-  const arma::mat& Codes() const { return codes; }
-  //! Modify the sparse codes.
-  arma::mat& Codes() { return codes; }
-
   // Returns a string representation of this object.
   std::string ToString() const;
 
@@ -214,18 +208,11 @@ class SparseCoding
   //! Number of atoms.
   size_t atoms;
 
-  //! Data matrix (columns are points).
-  const arma::mat& data;
-
   //! Dictionary (columns are atoms).
   arma::mat dictionary;
 
-  //! Sparse codes (columns are points).
-  arma::mat codes;
-
   //! l1 regularization term.
   double lambda1;
-
   //! l2 regularization term.
   double lambda2;
 
diff --git a/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp b/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
index 0da7e4e..264deb9 100644
--- a/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
+++ b/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
@@ -24,17 +24,12 @@ SparseCoding<DictionaryInitializer>::SparseCoding(
     const double objTolerance,
     const double newtonTolerance) :
     atoms(atoms),
-    data(data),
-    codes(atoms, data.n_cols),
     lambda1(lambda1),
     lambda2(lambda2),
     maxIterations(maxIterations),
     objTolerance(objTolerance),
     newtonTolerance(newtonTolerance)
 {
-  // Initialize the dictionary.
-  DictionaryInitializer::Initialize(data, atoms, dictionary);
-
   Train(data);
 }
 
@@ -47,16 +42,13 @@ SparseCoding<DictionaryInitializer>::SparseCoding(
     const double objTolerance,
     const double newtonTolerance) :
     atoms(atoms),
-    data(data),
-    codes(atoms, data.n_cols),
     lambda1(lambda1),
     lambda2(lambda2),
     maxIterations(maxIterations),
     objTolerance(objTolerance),
     newtonTolerance(newtonTolerance)
 {
-  // Initialize the dictionary.
-  DictionaryInitializer::Initialize(data, atoms, dictionary);
+  // Nothing to do.
 }
 
 template<typename DictionaryInitializer>
@@ -65,18 +57,23 @@ void SparseCoding<DictionaryInitializer>::Train(const arma::mat& data)
   // Now, train.
   Timer::Start("sparse_coding");
 
+  // Initialize the dictionary.
+  DictionaryInitializer::Initialize(data, atoms, dictionary);
+
   double lastObjVal = DBL_MAX;
 
   // Take the initial coding step, which has to happen before entering the main
   // optimization loop.
   Log::Info << "Initial coding step." << std::endl;
 
-  OptimizeCode();
+  arma::mat codes(atoms, data.n_cols);
+  OptimizeCode(data, codes);
   arma::uvec adjacencies = find(codes);
 
   Log::Info << "  Sparsity level: " << 100.0 * ((double) (adjacencies.n_elem))
       / ((double) (atoms * data.n_cols)) << "%." << std::endl;
-  Log::Info << "  Objective value: " << Objective() << "." << std::endl;
+  Log::Info << "  Objective value: " << Objective(data, codes) << "."
+      << std::endl;
 
   for (size_t t = 1; t != maxIterations; ++t)
   {
@@ -89,12 +86,13 @@ void SparseCoding<DictionaryInitializer>::Train(const arma::mat& data)
 
     // First step: optimize the dictionary.
     Log::Info << "Performing dictionary step... " << std::endl;
-    OptimizeDictionary(adjacencies, newtonTolerance);
-    Log::Info << "  Objective value: " << Objective() << "." << std::endl;
+    OptimizeDictionary(data, codes, adjacencies, newtonTolerance);
+    Log::Info << "  Objective value: " << Objective(data, codes) << "."
+        << std::endl;
 
     // Second step: perform the coding.
     Log::Info << "Performing coding step..." << std::endl;
-    OptimizeCode();
+    OptimizeCode(data, codes);
     // Get the indices of all the nonzero elements in the codes.
     adjacencies = find(codes);
     Log::Info << "  Sparsity level: " << 100.0 * ((double) (adjacencies.n_elem))
@@ -102,7 +100,7 @@ void SparseCoding<DictionaryInitializer>::Train(const arma::mat& data)
 
     // Find the new objective value and improvement so we can check for
     // convergence.
-    double curObjVal = Objective();
+    double curObjVal = Objective(data, codes);
     double improvement = lastObjVal - curObjVal;
     Log::Info << "  Objective value: " << curObjVal << " (improvement "
         << std::scientific << improvement << ")." << std::endl;
@@ -121,12 +119,14 @@ void SparseCoding<DictionaryInitializer>::Train(const arma::mat& data)
 }
 
 template<typename DictionaryInitializer>
-void SparseCoding<DictionaryInitializer>::OptimizeCode()
+void SparseCoding<DictionaryInitializer>::OptimizeCode(const arma::mat& data,
+                                                       arma::mat& codes)
 {
   // When using the Cholesky version of LARS, this is correct even if
   // lambda2 > 0.
   arma::mat matGram = trans(dictionary) * dictionary;
 
+  codes.set_size(atoms, data.n_cols);
   for (size_t i = 0; i < data.n_cols; ++i)
   {
     // Report progress.
@@ -147,6 +147,8 @@ void SparseCoding<DictionaryInitializer>::OptimizeCode()
 // Dictionary step for optimization.
 template<typename DictionaryInitializer>
 double SparseCoding<DictionaryInitializer>::OptimizeDictionary(
+    const arma::mat& data,
+    const arma::mat& codes,
     const arma::uvec& adjacencies,
     const double newtonTolerance,
     const size_t maxIterations)
@@ -346,7 +348,9 @@ void SparseCoding<DictionaryInitializer>::ProjectDictionary()
 
 // Compute the objective function.
 template<typename DictionaryInitializer>
-double SparseCoding<DictionaryInitializer>::Objective() const
+double SparseCoding<DictionaryInitializer>::Objective(
+    const arma::mat& data,
+    const arma::mat& codes) const
 {
   double l11NormZ = arma::sum(arma::sum(arma::abs(codes)));
   double froNormResidual = arma::norm(data - (dictionary * codes), "fro");
@@ -368,8 +372,6 @@ std::string SparseCoding<DictionaryInitializer>::ToString() const
 {
   std::ostringstream convert;
   convert << "Sparse Coding  [" << this << "]" << std::endl;
-  convert << "  Data: " << data.n_rows << "x" ;
-  convert <<  data.n_cols << std::endl;
   convert << "  Atoms: " << atoms << std::endl;
   convert << "  Lambda 1: " << lambda1 << std::endl;
   convert << "  Lambda 2: " << lambda2 << std::endl;
diff --git a/src/mlpack/tests/sparse_coding_test.cpp b/src/mlpack/tests/sparse_coding_test.cpp
index 0bd179f..ed4d24e 100644
--- a/src/mlpack/tests/sparse_coding_test.cpp
+++ b/src/mlpack/tests/sparse_coding_test.cpp
@@ -58,11 +58,12 @@ BOOST_AUTO_TEST_CASE(SparseCodingTestCodingStepLasso)
     X.col(i) /= norm(X.col(i), 2);
   }
 
-  SparseCoding<> sc(X, nAtoms, lambda1);
-  sc.OptimizeCode();
+  SparseCoding<> sc(nAtoms, lambda1);
+  mat Z;
+  DataDependentRandomInitializer::Initialize(X, 25, sc.Dictionary());
+  sc.OptimizeCode(X, Z);
 
   mat D = sc.Dictionary();
-  mat Z = sc.Codes();
 
   for (uword i = 0; i < nPoints; ++i)
   {
@@ -85,11 +86,12 @@ BOOST_AUTO_TEST_CASE(SparseCodingTestCodingStepElasticNet)
   for (uword i = 0; i < nPoints; ++i)
     X.col(i) /= norm(X.col(i), 2);
 
-  SparseCoding<> sc(X, nAtoms, lambda1, lambda2);
-  sc.OptimizeCode();
+  SparseCoding<> sc(nAtoms, lambda1, lambda2);
+  mat Z;
+  DataDependentRandomInitializer::Initialize(X, 25, sc.Dictionary());
+  sc.OptimizeCode(X, Z);
 
   mat D = sc.Dictionary();
-  mat Z = sc.Codes();
 
   for(uword i = 0; i < nPoints; ++i)
   {
@@ -116,14 +118,15 @@ BOOST_AUTO_TEST_CASE(SparseCodingTestDictionaryStep)
   for (uword i = 0; i < nPoints; ++i)
     X.col(i) /= norm(X.col(i), 2);
 
-  SparseCoding<> sc(X, nAtoms, lambda1);
-  sc.OptimizeCode();
+  SparseCoding<> sc(nAtoms, lambda1);
+  mat Z;
+  DataDependentRandomInitializer::Initialize(X, 25, sc.Dictionary());
+  sc.OptimizeCode(X, Z);
 
   mat D = sc.Dictionary();
-  mat Z = sc.Codes();
 
   uvec adjacencies = find(Z);
-  double normGradient = sc.OptimizeDictionary(adjacencies, 1e-15);
+  double normGradient = sc.OptimizeDictionary(X, Z, adjacencies, 1e-15);
 
   BOOST_REQUIRE_SMALL(normGradient, tol);
 }



More information about the mlpack-git mailing list