[mlpack-svn] r10814 - mlpack/trunk/src/mlpack/methods/radical
fastlab-svn at coffeetalk-1.cc.gatech.edu
fastlab-svn at coffeetalk-1.cc.gatech.edu
Wed Dec 14 18:12:08 EST 2011
Author: rcurtin
Date: 2011-12-14 18:12:08 -0500 (Wed, 14 Dec 2011)
New Revision: 10814
Modified:
mlpack/trunk/src/mlpack/methods/radical/radical.cpp
mlpack/trunk/src/mlpack/methods/radical/radical.hpp
mlpack/trunk/src/mlpack/methods/radical/radical_main.cpp
Log:
Change formatting of RADICAL code and redo the documentation a little bit to
make it more consistent with other programs.
Modified: mlpack/trunk/src/mlpack/methods/radical/radical.cpp
===================================================================
--- mlpack/trunk/src/mlpack/methods/radical/radical.cpp 2011-12-14 22:59:30 UTC (rev 10813)
+++ mlpack/trunk/src/mlpack/methods/radical/radical.cpp 2011-12-14 23:12:08 UTC (rev 10814)
@@ -14,8 +14,8 @@
namespace radical {
-Radical::Radical(double noiseStdDev, size_t nReplicates, size_t nAngles,
- size_t nSweeps) :
+Radical::Radical(double noiseStdDev, size_t nReplicates, size_t nAngles,
+ size_t nSweeps) :
noiseStdDev(noiseStdDev),
nReplicates(nReplicates),
nAngles(nAngles),
@@ -26,7 +26,7 @@
}
Radical::Radical(double noiseStdDev, size_t nReplicates, size_t nAngles, size_t nSweeps,
- size_t m) :
+ size_t m) :
noiseStdDev(noiseStdDev),
nReplicates(nReplicates),
nAngles(nAngles),
@@ -35,8 +35,8 @@
{
// nothing to do here
}
-
+
void Radical::CopyAndPerturb(mat& matXNew, const mat& matX) {
matXNew = repmat(matX, nReplicates, 1) + noiseStdDev * randn(nReplicates * matX.n_rows, matX.n_cols);
}
@@ -44,7 +44,7 @@
double Radical::Vasicek(vec& z) {
z = sort(z);
-
+
// Apparently slower
/*
vec logs = log(z.subvec(m, nPoints - 1) - z.subvec(0, nPoints - 1 - m));
@@ -66,13 +66,13 @@
mat matXMod;
CopyAndPerturb(matXMod, matX);
-
+
mat matJacobi(2,2);
mat candidateY;
vec thetas = linspace<vec>(0, nAngles - 1, nAngles) / ((double) nAngles) * math::pi() / 2;
vec values(nAngles);
-
+
for(size_t i = 0; i < nAngles; i++) {
double cosTheta = cos(thetas(i));
double sinTheta = sin(thetas(i));
@@ -80,14 +80,14 @@
matJacobi(1,0) = -sinTheta;
matJacobi(0,1) = sinTheta;
matJacobi(1,1) = cosTheta;
-
+
candidateY = matXMod * matJacobi;
vec candidateY1 = candidateY.unsafe_col(0);
vec candidateY2 = candidateY.unsafe_col(1);
-
+
values(i) = Vasicek(candidateY1) + Vasicek(candidateY2);
}
-
+
u32 indOpt;
values.min(indOpt); // we ignore the return value; we don't care about it
return thetas(indOpt);
@@ -95,36 +95,36 @@
void Radical::DoRadical(const mat& matXT, mat& matY, mat& matW) {
-
- // matX is nPoints by nDims (although less intuitive than columns being
+
+ // matX is nPoints by nDims (although less intuitive than columns being
// points, and although this is the transpose of the ICA literature, this
- // choice is for computational efficiency when repeatedly generating
+ // choice is for computational efficiency when repeatedly generating
// two-dimensional coordinate projections for Radical2D
mat matX = trans(matXT);
-
-
- // if m was not specified, initialize m as recommended in
+
+
+ // if m was not specified, initialize m as recommended in
// (Learned-Miller and Fisher, 2003)
if(m < 1) {
m = floor(sqrt(matX.n_rows));
}
-
+
const size_t nDims = matX.n_cols;
const size_t nPoints = matX.n_rows;
-
+
mat matXWhitened;
mat matWhitening;
WhitenFeatureMajorMatrix(matX, matY, matWhitening);
// matY is now the whitened form of matX
-
+
// in the RADICAL code, they do not copy and perturb initially, although the
// paper does. we follow the code as it should match their reported results
// and likely does a better job bouncing out of local optima
//GeneratePerturbedX(X, X);
-
+
// initialize the unmixing matrix to the whitening matrix
matW = matWhitening;
-
+
mat matYSubspace(nPoints, 2);
mat matEye = eye(nDims, nDims);
@@ -132,24 +132,24 @@
for(size_t sweepNum = 0; sweepNum < nSweeps; sweepNum++) {
for(size_t i = 0; i < nDims - 1; i++) {
for(size_t j = i + 1; j < nDims; j++) {
- matYSubspace.col(0) = matY.col(i);
- matYSubspace.col(1) = matY.col(j);
- double thetaOpt = DoRadical2D(matYSubspace);
- mat matJ = matEye;
- double cosThetaOpt = cos(thetaOpt);
- double sinThetaOpt = sin(thetaOpt);
- matJ(i,i) = cosThetaOpt;
- matJ(j,i) = -sinThetaOpt;
- matJ(i,j) = sinThetaOpt;
- matJ(j,j) = cosThetaOpt;
- matW = matW * matJ;
- matY = matX * matW; // to avoid any issues of mismatch between matW
- // and matY, do not use matY = matY * matJ,
- // even though it may be much more efficient
+ matYSubspace.col(0) = matY.col(i);
+ matYSubspace.col(1) = matY.col(j);
+ double thetaOpt = DoRadical2D(matYSubspace);
+ mat matJ = matEye;
+ double cosThetaOpt = cos(thetaOpt);
+ double sinThetaOpt = sin(thetaOpt);
+ matJ(i,i) = cosThetaOpt;
+ matJ(j,i) = -sinThetaOpt;
+ matJ(i,j) = sinThetaOpt;
+ matJ(j,j) = cosThetaOpt;
+ matW = matW * matJ;
+ matY = matX * matW; // to avoid any issues of mismatch between matW
+ // and matY, do not use matY = matY * matJ,
+ // even though it may be much more efficient
}
}
}
-
+
// the final transposes provide W and Y in the typical form from the ICA literature
//matW = trans(matWhitening * matW);
//matY = trans(matY);
@@ -159,8 +159,8 @@
void WhitenFeatureMajorMatrix(const mat& matX,
- mat& matXWhitened,
- mat& matWhitening) {
+ mat& matXWhitened,
+ mat& matWhitening) {
mat matU, matV;
vec s;
svd(matU, s, matV, cov(matX));
Modified: mlpack/trunk/src/mlpack/methods/radical/radical.hpp
===================================================================
--- mlpack/trunk/src/mlpack/methods/radical/radical.hpp 2011-12-14 22:59:30 UTC (rev 10813)
+++ mlpack/trunk/src/mlpack/methods/radical/radical.hpp 2011-12-14 23:12:08 UTC (rev 10814)
@@ -3,7 +3,7 @@
* @author Nishant Mehta
*
* Declaration of Radical class (RADICAL is Robust, Accurate, Direct ICA aLgorithm)
- * Note: upper case variables correspond to matrices. do not convert them to
+ * Note: upper case variables correspond to matrices. do not convert them to
* camelCase because that would make them appear to be vectors (which is bad!)
*/
@@ -36,15 +36,13 @@
* }
*/
class Radical {
-
-public:
-
+ public:
/**
- * Set the parameters to RADICAL
+ * Set the parameters to RADICAL.
*
* @param noiseStdDev Standard deviation of the Gaussian noise added to the
* replicates of the data points during Radical2D
- * @param nReplicates Number of Gaussian-perturbed replicates to use
+ * @param nReplicates Number of Gaussian-perturbed replicates to use
* (per point) in Radical2D
* @param nAngles Number of angles to consider in brute-force search during
* Radical2D
@@ -52,14 +50,14 @@
* Each sweep calls Radical2D once for each pair of dimensions
*/
Radical(double noiseStdDev, size_t nReplicates, size_t nAngles,
- size_t nSweeps);
+ size_t nSweeps);
/**
- * Set the parameters to RADICAL
+ * Set the parameters to RADICAL.
*
* @param noiseStdDev Standard deviation of the Gaussian noise added to the
* replicates of the data points during Radical2D
- * @param nReplicates Number of Gaussian-perturbed replicates to use
+ * @param nReplicates Number of Gaussian-perturbed replicates to use
* (per point) in Radical2D
* @param nAngles Number of angles to consider in brute-force search during
* Radical2D
@@ -68,73 +66,70 @@
* @param m The variable m from Vasicek's m-spacing estimator of entropy
*/
Radical(double noiseStdDev, size_t nReplicates, size_t nAngles,
- size_t nSweeps, size_t m);
-
+ size_t nSweeps, size_t m);
/**
+ * Run RADICAL.
+ *
+ * @param matX Input data into the algorithm - a matrix where each column is
+ * a point and each row is a dimension
+ * @param matY Estimated independent components - a matrix where each column
+ * is a point and each row is an estimated independent component
+ * @param matW Estimated unmixing matrix, where matY = matW * matX
+ */
+ void DoRadical(const arma::mat& matX, arma::mat& matY, arma::mat& matW);
+
+ /**
* Vasicek's m-spacing estimator of entropy, with overlap modification from
* (Learned-Miller and Fisher, 2003)
- *
+ *
* @param x Empirical sample (one-dimensional) over which to estimate entropy
*
*/
double Vasicek(arma::vec& x);
-
- /** Make nReplicates copies of each data point and perturb data with Gaussian
- * noise with standard deviation noiseStdDev
+
+ /**
+ * Make nReplicates copies of each data point and perturb data with Gaussian
+ * noise with standard deviation noiseStdDev.
*/
void CopyAndPerturb(arma::mat& matXNew, const arma::mat& matX);
-
- /** Two-dimensional version of RADICAL */
+
+ //! Two-dimensional version of RADICAL.
double DoRadical2D(const arma::mat& matX);
-
- /** Run RADICAL
- *
- * @param matX Input data into the algorithm - a matrix where each column is
- * a point and each row is a dimension
- * @param matY Estimated independent components - a matrix where each column
- * is a point and each row is an estimated independent component
- * @param matW Estimated unmixing matrix, where matY = matW * matX
- */
- void DoRadical(const arma::mat& matX, arma::mat& matY, arma::mat& matW);
-
-
-private:
+ private:
/**
* standard deviation of the Gaussian noise added to the replicates of
* the data points during Radical2D
*/
double noiseStdDev;
-
+
/**
* Number of Gaussian-perturbed replicates to use (per point) in Radical2D
*/
size_t nReplicates;
-
+
/**
* Number of angles to consider in brute-force search during Radical2D
*/
size_t nAngles;
-
+
/**
* Number of sweeps
* - Each sweep calls Radical2D once for each pair of dimensions
*/
size_t nSweeps;
-
+
/**
* m to use for Vasicek's m-spacing estimator of entropy
*/
size_t m;
-
+
};
-
-
void WhitenFeatureMajorMatrix(const arma::mat& matX,
- arma::mat& matXWhitened,
- arma::mat& matWhitening);
+ arma::mat& matXWhitened,
+ arma::mat& matWhitening);
}; // namespace radical
}; // namespace mlpack
Modified: mlpack/trunk/src/mlpack/methods/radical/radical_main.cpp
===================================================================
--- mlpack/trunk/src/mlpack/methods/radical/radical_main.cpp 2011-12-14 22:59:30 UTC (rev 10813)
+++ mlpack/trunk/src/mlpack/methods/radical/radical_main.cpp 2011-12-14 23:12:08 UTC (rev 10814)
@@ -2,81 +2,92 @@
* @file radical_main.cpp
* @author Nishant Mehta
*
- * Executable for RADICAL
+ * Executable for RADICAL.
*/
#include <mlpack/core.hpp>
#include <armadillo>
#include "radical.hpp"
-using namespace std;
-using namespace arma;
+PROGRAM_INFO("RADICAL", "An implementation of RADICAL, a method for independent"
+ "component analysis (ICA). Assuming that we have an input matrix X, the"
+ "goal is to find a square unmixing matrix W such that Y = W * X and the "
+ "dimensions of Y are independent components.\n"
+ "\n"
+ "For more details, see the following paper:\n"
+ "\n"
+ "@article{\n"
+ " title = {ICA Using Spacings Estimates of Entropy},\n"
+ " author = {Learned-Miller, E.G. and Fisher III, J.W.},\n"
+ " journal = {Journal of Machine Learning Research},\n"
+ " volume = {4},\n"
+ " pages = {1271--1295},\n"
+ " year = {2003}\n"
+ "}");
-PROGRAM_INFO("RADICAL", "An implementation of RADICAL, a method for independent "
- "component analysis (ICA)");
+PARAM_STRING_REQ("input_file", "Input dataset filename for ICA.", "");
-PARAM_STRING_REQ("X", "Input dataset filename for ICA", "");
-PARAM_STRING_REQ("Y", "Independent components filename", "");
-PARAM_STRING_REQ("W", "Unmixing matrix filename", "");
+PARAM_STRING("output_ic", "File to save independent components to.", "o",
+ "output_ic.csv");
+PARAM_STRING("output_unmixing", "File to save unmixing matrix to.", "u",
+ "output_unmixing.csv");
PARAM_DOUBLE("noise_std_dev", "Standard deviation of Gaussian noise", "",
- 0.175);
-PARAM_INT("n_replicates", "Number of Gaussian-perturbed replicates to use "
- "(per point) in Radical2D", "",
- 30);
-PARAM_INT("n_angles", "Number of angles to consider in brute-force search "
- "during Radical2D", "",
- 150);
-PARAM_INT("n_sweeps", "Number of sweeps (each sweep calls Radical2D once for "
- "each pair of dimensions", "",
- 0);
+ 0.175);
+PARAM_INT("replicates", "Number of Gaussian-perturbed replicates to use "
+ "(per point) in Radical2D.", "", 30);
+PARAM_INT("angles", "Number of angles to consider in brute-force search "
+ "during Radical2D.", "", 150);
+PARAM_INT("sweeps", "Number of sweeps (each sweep calls Radical2D once for "
+ "each pair of dimensions", "", 0);
+using namespace mlpack;
+using namespace mlpack::radical;
+using namespace std;
+using namespace arma;
int main(int argc, char* argv[]) {
+ // Handle parameters.
+ CLI::ParseCommandLine(argc, argv);
- // Handle parameters
- CLI::ParseCommandLine(argc, argv);
-
- // load the data
- const std::string matXFilename = CLI::GetParam<std::string>("X");
+ // Load the data.
+ const string matXFilename = CLI::GetParam<string>("input_file");
mat matX;
data::Load(matXFilename, matX);
-
-
- // load parameters
+
+ // Load parameters.
double noiseStdDev = CLI::GetParam<double>("noise_std_dev");
- u32 nReplicates = CLI::GetParam<int>("n_replicates");
- u32 nAngles = CLI::GetParam<int>("n_angles");
- u32 nSweeps = CLI::GetParam<int>("n_sweeps");
- if(nSweeps == 0) {
+ size_t nReplicates = CLI::GetParam<int>("replicates");
+ size_t nAngles = CLI::GetParam<int>("angles");
+ size_t nSweeps = CLI::GetParam<int>("sweeps");
+
+ if(nSweeps == 0)
+ {
nSweeps = matX.n_rows - 1;
}
-
- // run RADICAL
- mlpack::radical::Radical rad(noiseStdDev, nReplicates, nAngles, nSweeps);
+
+ // Run RADICAL.
+ Radical rad(noiseStdDev, nReplicates, nAngles, nSweeps);
mat matY;
mat matW;
rad.DoRadical(matX, matY, matW);
-
+
// save results
- const std::string matYFilename = CLI::GetParam<std::string>("Y");
+ const string matYFilename = CLI::GetParam<string>("output_ic");
data::Save(matYFilename, matY);
-
- const std::string matWFilename = CLI::GetParam<std::string>("W");
+
+ const string matWFilename = CLI::GetParam<string>("output_unmixing");
data::Save(matWFilename, matW);
-
-
+
/*
- // compute and print objective
+ // compute and print objective
mat matYT = trans(matY);
double valEst = 0;
- for(u32 i = 0; i < matYT.n_cols; i++) {
+ for(size_t i = 0; i < matYT.n_cols; i++)
+ {
vec Yi = vec(matYT.col(i));
valEst += rad.Vasicek(Yi);
}
- printf("objective(estimate) = %f\n", valEst);
+ Log::Info << "Objective (estimate): " << valEst << "." << endl;
*/
-
-
-
}
More information about the mlpack-svn
mailing list