Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No between #2

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 6 additions & 37 deletions openbr/plugins/eigen3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,18 +346,7 @@ class LDATransform : public Transform
// creates "Label"
TemplateList trainingSet = TemplateList::relabel(_trainingSet, inputVariable, isBinary);
int instances = trainingSet.size();

// Perform PCA dimensionality reduction
PCATransform pca;
pca.keep = pcaKeep;
pca.whiten = pcaWhiten;
pca.train(trainingSet);
mean = pca.mean;

TemplateList ldaTrainingSet;
static_cast<Transform*>(&pca)->project(trainingSet, ldaTrainingSet);

int dimsIn = ldaTrainingSet.first().m().rows * ldaTrainingSet.first().m().cols;
int dimsIn = trainingSet.first().m().rows * trainingSet.first().m().cols;

// OpenBR ensures that class values range from 0 to numClasses-1.
// Label exists because we created it earlier with relabel
Expand All @@ -368,7 +357,7 @@ class LDATransform : public Transform
// Map Eigen into OpenCV
Eigen::MatrixXd data = Eigen::MatrixXd(dimsIn, instances);
for (int i=0; i<instances; i++)
data.col(i) = Eigen::Map<const Eigen::MatrixXf>(ldaTrainingSet[i].m().ptr<float>(), dimsIn, 1).cast<double>();
data.col(i) = Eigen::Map<const Eigen::MatrixXf>(trainingSet[i].m().ptr<float>(), dimsIn, 1).cast<double>();

// Removing class means
Eigen::MatrixXd classMeans = Eigen::MatrixXd::Zero(dimsIn, numClasses);
Expand All @@ -385,8 +374,9 @@ class LDATransform : public Transform
// the mean of each class is removed (lowering degree of freedom
// one per class), the total rank of the covariance/scatter
// matrix that will be computed in PCA is bound by instances - numClasses.
space1.keep = std::min(dimsIn, instances-numClasses);
space1.keep = pcaKeep;
space1.trainCore(data);
mean = space1.mean;

// Divide each eigenvector by sqrt of eigenvalue.
// This has the effect of whitening the within-class scatter.
Expand Down Expand Up @@ -454,30 +444,9 @@ class LDATransform : public Transform
for (int i=0; i<space1.keep; i++) space1.eVecs.col(i) /= pow((double)space1.eVals(i),0.15);
}

// Now we project the mean class vectors into this second
// subspace that minimizes the within-class scatter energy.
// Inside this subspace we learn a subspace projection that
// maximizes the between-class scatter energy.
Eigen::MatrixXd mean2 = Eigen::MatrixXd::Zero(dimsIn, 1);

// Remove means
for (int i=0; i<dimsIn; i++) mean2(i) = classMeans.row(i).sum() / numClasses;
for (int i=0; i<numClasses; i++) classMeans.col(i) -= mean2;

// Project into second subspace
Eigen::MatrixXd data2 = space1.eVecs.transpose().cast<double>() * classMeans;

// The rank of the between-class scatter matrix is bound by numClasses - 1
// because each class is a vector used to compute the covariance,
// but one degree of freedom is lost removing the global mean.
int dim2 = std::min((int)space1.keep, numClasses-1);
PCATransform space2;
space2.keep = dim2;
space2.trainCore(data2);

// Compute final projection matrix
projection = ((space2.eVecs.transpose() * space1.eVecs.transpose()) * pca.eVecs.transpose()).transpose();
dimsOut = dim2;
projection = space1.eVecs;
dimsOut = projection.cols();

stdDev = 1; // default initialize
if (isBinary) {
Expand Down