[mlpack-svn] r13108 - mlpack/trunk/src/mlpack/methods/sparse_coding
fastlab-svn at coffeetalk-1.cc.gatech.edu
fastlab-svn at coffeetalk-1.cc.gatech.edu
Tue Jun 26 15:10:41 EDT 2012
Author: rcurtin
Date: 2012-06-26 15:10:40 -0400 (Tue, 26 Jun 2012)
New Revision: 13108
Modified:
mlpack/trunk/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
Log:
Stop using activeAtoms because it isn't necessary (minor speed boost). Clean up
code just a little more.
Modified: mlpack/trunk/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp
===================================================================
--- mlpack/trunk/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp 2012-06-25 22:22:37 UTC (rev 13107)
+++ mlpack/trunk/src/mlpack/methods/sparse_coding/sparse_coding_impl.hpp 2012-06-26 19:10:40 UTC (rev 13108)
@@ -146,12 +146,10 @@
{
if (accu(codes.row(j) != 0) == 0)
inactiveAtoms.push_back(j);
- else
- activeAtoms.push_back(j);
}
- const size_t nActiveAtoms = activeAtoms.size();
const size_t nInactiveAtoms = inactiveAtoms.size();
+ const size_t nActiveAtoms = atoms - nInactiveAtoms;
// Efficient construction of Z restricted to active atoms.
arma::mat matActiveZ;
@@ -166,10 +164,6 @@
RemoveRows(codes, inactiveAtomsVec, matActiveZ);
}
- arma::uvec atomReverseLookup(atoms);
- for (size_t i = 0; i < nActiveAtoms; ++i)
- atomReverseLookup(activeAtoms[i]) = i;
-
if (nInactiveAtoms > 0)
{
Log::Warn << "There are " << nInactiveAtoms
@@ -178,7 +172,6 @@
Log::Debug << "Solving Dual via Newton's Method.\n";
- arma::mat dictionaryEstimate;
// Solve using Newton's method in the dual - note that the final dot
// multiplication with inv(A) seems to be unavoidable. Although more
// expensive, the code written this way (we use solve()) should be more
@@ -201,6 +194,7 @@
arma::mat codesXT = matActiveZ * trans(data);
arma::mat codesZT = matActiveZ * trans(matActiveZ);
+ double improvement;
for (size_t t = 1; !converged; ++t)
{
arma::mat A = codesZT + diagmat(dualVars);
@@ -213,7 +207,6 @@
arma::mat hessian = -(-2 * (matAInvZXT * trans(matAInvZXT)) % inv(A));
arma::vec searchDirection = -solve(hessian, gradient);
- //vec searchDirection = -gradient;
// Armijo line search.
const double c = 1e-4;
@@ -221,20 +214,6 @@
const double rho = 0.9;
double sufficientDecrease = c * dot(gradient, searchDirection);
- /*
- {
- double sumDualVars = sum(dualVars);
- double fOld = -(-trace(trans(codesXT) * matAInvZXT) - sumDualVars);
- Log::Debug << "fOld = " << fOld << "." << std::endl;
- double fNew =
- -(-trace(trans(codesXT) * solve(codesZT +
- diagmat(dualVars + alpha * searchDirection), codesXT))
- - (sumDualVars + alpha * sum(searchDirection)) );
- Log::Debug << "fNew = " << fNew << "." << std::endl;
- }
- */
-
- double improvement;
while (true)
{
// Calculate objective.
@@ -254,8 +233,7 @@
alpha *= rho;
}
- // End of Armijo line search code.
-
+ // Take step and print useful information.
dualVars += searchDirection;
double normGradient = norm(gradient, 2);
Log::Debug << "Newton Method iteration " << t << ":" << std::endl;
@@ -269,31 +247,37 @@
if (inactiveAtoms.empty())
{
- dictionaryEstimate = trans(solve(codesZT + diagmat(dualVars), codesXT));
+ // Directly update dictionary.
+ dictionary = trans(solve(codesZT + diagmat(dualVars), codesXT));
}
else
{
- arma::mat dictionaryActiveEstimate = trans(solve(codesZT +
+ arma::mat activeDictionary = trans(solve(codesZT +
diagmat(dualVars), codesXT));
- dictionaryEstimate = arma::zeros(data.n_rows, atoms);
- for (size_t i = 0; i < nActiveAtoms; ++i)
- dictionaryEstimate.col(activeAtoms[i]) = dictionaryActiveEstimate.col(i);
-
- for (size_t i = 0; i < nInactiveAtoms; ++i)
+ // Update all atoms.
+ size_t currentInactiveIndex = 0;
+ for (size_t i = 0; i < atoms; ++i)
{
- // Make a new random atom estimate.
- dictionaryEstimate.col(inactiveAtoms[i]) =
- (data.col(math::RandInt(data.n_cols)) +
- data.col(math::RandInt(data.n_cols)) +
- data.col(math::RandInt(data.n_cols)));
+ if (inactiveAtoms[currentInactiveIndex] == i)
+ {
+ // This atom is inactive. Reinitialize it randomly.
+ dictionary.col(i) = (data.col(math::RandInt(data.n_cols)) +
+ data.col(math::RandInt(data.n_cols)) +
+ data.col(math::RandInt(data.n_cols)));
- dictionaryEstimate.col(inactiveAtoms[i]) /=
- norm(dictionaryEstimate.col(inactiveAtoms[i]), 2);
+ dictionary.col(i) /= norm(dictionary.col(i), 2);
+
+ // Increment inactive index counter.
+ ++currentInactiveIndex;
+ }
+ else
+ {
+ // Update estimate.
+ dictionary.col(i) = activeDictionary.col(i - currentInactiveIndex);
+ }
}
}
-
- dictionary = dictionaryEstimate;
}
// Project each atom of the dictionary back into the unit ball (if necessary).
More information about the mlpack-svn
mailing list