[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