* Modified AMF module so that now it uses tolerance checking rather

than minResidue checking
* Added SVD batch learning
This commit is contained in:
sumedhghaisas
2014-06-09 23:37:53 +00:00
parent 457c523e1c
commit 52e55828db
3 changed files with 137 additions and 16 deletions
+12 -7
View File
@@ -1,9 +1,13 @@
/**
* @file nmf_als.hpp
* @author Sumedh Ghaisas
*/
#ifndef __MLPACK_METHODS_LMF_LMF_HPP
#define __MLPACK_METHODS_LMF_LMF_HPP
#include <mlpack/core.hpp>
#include "update_rules/nmf_mult_dist.hpp"
#include "init_rules/random_init.hpp"
#include <amf/update_rules/nmf_mult_dist.hpp>
#include <amf/init_rules/random_init.hpp>
namespace mlpack {
namespace amf {
@@ -63,7 +67,7 @@ class AMF
* the W and H vector has states that it needs to store
*/
AMF(const size_t maxIterations = 10000,
const double minResidue = 1e-10,
const double tolerance = 1e-5,
const InitializationRule initializeRule = InitializationRule(),
const UpdateRule update = UpdateRule());
@@ -76,7 +80,7 @@ class AMF
* @param r Rank r of the factorization.
*/
template<typename MatType>
void Apply(const MatType& V,
double Apply(const MatType& V,
const size_t r,
arma::mat& W,
arma::mat& H) const;
@@ -85,7 +89,7 @@ class AMF
//! The maximum number of iterations allowed before giving up.
size_t maxIterations;
//! The minimum residue, below which iteration is considered converged.
double minResidue;
double tolerance;
//! Instantiated initialization Rule.
InitializationRule initializeRule;
//! Instantiated update rule.
@@ -97,9 +101,9 @@ class AMF
//! Modify the maximum number of iterations.
size_t& MaxIterations() { return maxIterations; }
//! Access the minimum residue before termination.
double MinResidue() const { return minResidue; }
double Tolerance() const { return tolerance; }
//! Modify the minimum residue before termination.
double& MinResidue() { return minResidue; }
double& Tolerance() { return tolerance; }
//! Access the initialization rule.
const InitializationRule& InitializeRule() const { return initializeRule; }
//! Modify the initialization rule.
@@ -118,3 +122,4 @@ class AMF
#include "amf_impl.hpp"
#endif
+22 -9
View File
@@ -1,3 +1,7 @@
/**
* @file nmf_als.hpp
* @author Sumedh Ghaisas
*/
namespace mlpack {
namespace amf {
@@ -8,19 +12,19 @@ template<typename InitializationRule,
typename UpdateRule>
AMF<InitializationRule, UpdateRule>::AMF(
const size_t maxIterations,
const double minResidue,
const double tolerance,
const InitializationRule initializeRule,
const UpdateRule update) :
maxIterations(maxIterations),
minResidue(minResidue),
tolerance(tolerance),
initializeRule(initializeRule),
update(update)
{
if (minResidue < 0.0)
if (tolerance < 0.0 || tolerance > 1)
{
Log::Warn << "AMF::AMF(): minResidue must be a positive value ("
<< minResidue << " given). Setting to the default value of 1e-10.\n";
this->minResidue = 1e-10;
Log::Warn << "AMF::AMF(): tolerance must be a positive value in the range (0-1) but value "
<< tolerance << " is given. Setting to the default value of 1e-5.\n";
this->tolerance = 1e-5;
}
}
@@ -35,7 +39,7 @@ AMF<InitializationRule, UpdateRule>::AMF(
template<typename InitializationRule,
typename UpdateRule>
template<typename MatType>
void AMF<InitializationRule, UpdateRule>::Apply(
double AMF<InitializationRule, UpdateRule>::Apply(
const MatType& V,
const size_t r,
arma::mat& W,
@@ -51,12 +55,15 @@ void AMF<InitializationRule, UpdateRule>::Apply(
size_t iteration = 1;
const size_t nm = n * m;
double residue = minResidue;
double residue = DBL_MIN;
double oldResidue = DBL_MAX;
double normOld = 0;
double norm = 0;
arma::mat WH;
while (residue >= minResidue && iteration != maxIterations)
std::cout << tolerance << std::endl;
while (((oldResidue - residue) / oldResidue >= tolerance || iteration < 4) && iteration != maxIterations)
{
// Update step.
// Update the value of W and H based on the Update Rules provided
@@ -69,6 +76,7 @@ void AMF<InitializationRule, UpdateRule>::Apply(
if (iteration != 0)
{
oldResidue = residue;
residue = fabs(normOld - norm);
residue /= normOld;
}
@@ -76,11 +84,16 @@ void AMF<InitializationRule, UpdateRule>::Apply(
normOld = norm;
iteration++;
std::cout << residue << std::endl;
}
Log::Info << "AMF converged to residue of " << sqrt(residue) << " in "
<< iteration << " iterations." << std::endl;
return residue;
}
}; // namespace nmf
}; // namespace mlpack
@@ -0,0 +1,103 @@
#ifndef __MLPACK_METHODS_AMF_UPDATE_RULES_SVD_BATCHLEARNING_HPP
#define __MLPACK_METHODS_AMF_UPDATE_RULES_SVD_BATCHLEARNING_HPP
#include <mlpack/core.hpp>
namespace mlpack
{
namespace amf
{
class SVDBatchLearning
{
public:
SVDBatchLearning(double u = 0.000001,
double kw = 0,
double kh = 0,
double min = -DBL_MIN,
double max = DBL_MAX)
: u(u), kw(kw), kh(kh), min(min), max(max) {}
/**
* The update rule for the basis matrix W.
* The function takes in all the matrices and only changes the
* value of the W matrix.
*
* @param V Input matrix to be factorized.
* @param W Basis matrix to be updated.
* @param H Encoding matrix.
*/
template<typename MatType>
inline void WUpdate(const MatType& V,
arma::mat& W,
const arma::mat& H) const
{
size_t n = V.n_rows;
size_t m = V.n_cols;
size_t r = W.n_cols;
arma::mat deltaW(n, r);
deltaW.zeros();
for(size_t i = 0; i < n; i++)
{
for(size_t j = 0; j < m; j++)
if(V(i,j) != 0) deltaW.row(i) += (V(i,j) - Predict(W.row(i), H.col(j))) * arma::trans(H.col(j));
deltaW.row(i) -= kw * W.row(i);
}
W += u * deltaW;
}
/**
* The update rule for the encoding matrix H.
* The function takes in all the matrices and only changes the
* value of the H matrix.
*
* @param V Input matrix to be factorized.
* @param W Basis matrix.
* @param H Encoding matrix to be updated.
*/
template<typename MatType>
inline void HUpdate(const MatType& V,
const arma::mat& W,
arma::mat& H) const
{
size_t n = V.n_rows;
size_t m = V.n_cols;
size_t r = W.n_cols;
arma::mat deltaH(r, m);
deltaH.zeros();
for(size_t j = 0; j < m; j++)
{
for(size_t i = 0; i < n; i++)
if(V(i,j) != 0) deltaH.col(j) += (V(i,j) - Predict(W.row(i), H.col(j))) * arma::trans(W.row(i));
deltaH.col(j) -= kh * H.col(j);
}
H += u*deltaH;
}
private:
double Predict(const arma::mat& wi, const arma::mat& hj) const
{
arma::mat temp = (wi * hj);
double out = temp(0,0);
return out;
}
double u;
double kw;
double kh;
double min;
double max;
};
} // namespace amf
} // namespace mlpack
#endif