Commit 1c6bfa82 authored by Andreas Schwarzkopf's avatar Andreas Schwarzkopf

[STYLE #42] Principal Component Analysis cleanup

 * Sebastian Eichelbaum told that it is better to use "const Type&" instead of
 * "const Type*" or "Type*". So I adapted PCA inut data field to the reference instead
 * of pointer input.
parent 973d6739
......@@ -32,30 +32,29 @@ WCovarianceSolver::WCovarianceSolver()
WCovarianceSolver::~WCovarianceSolver()
{
}
void WCovarianceSolver::analyzeData( const vector<WPosition>* dataSet )
void WCovarianceSolver::analyzeData( const vector<WPosition>& dataSet )
{
m_dataSet = dataSet;
calculateMean();
calculateCovariance();
calculateMean( dataSet );
calculateCovariance( dataSet );
}
WPosition WCovarianceSolver::getMean()
{
return m_mean;
}
void WCovarianceSolver::calculateMean()
void WCovarianceSolver::calculateMean( const vector<WPosition>& dataSet )
{
if( m_dataSet->size() == 0 )
if( dataSet.size() == 0 )
return;
size_t dimensions = (*m_dataSet)[0].size();
size_t dimensions = dataSet[0].size();
for( size_t dimension = 0; dimension < dimensions; dimension++ )
m_mean[dimension] = 0.0;
for( size_t index = 0; index < m_dataSet->size(); index++ )
for( size_t dimension = 0; dimension < (*m_dataSet)[index].size(); dimension++ )
m_mean[dimension] += (*m_dataSet)[index][dimension];
for( size_t index = 0; index < dataSet.size(); index++ )
for( size_t dimension = 0; dimension < dataSet[index].size(); dimension++ )
m_mean[dimension] += dataSet[index][dimension];
for( size_t dimension = 0; dimension < dimensions; dimension++ )
m_mean[dimension] /= static_cast<double>( m_dataSet->size() );
m_mean[dimension] /= static_cast<double>( dataSet.size() );
}
void WCovarianceSolver::calculateCovariance()
void WCovarianceSolver::calculateCovariance( const vector<WPosition>& dataSet )
{
size_t width = m_mean.size();
MatrixXd newCovariance( width, width );
......@@ -63,22 +62,21 @@ void WCovarianceSolver::calculateCovariance()
for( size_t row = 0; row < width; row++ )
for( size_t col = 0; col < width; col++ )
m_covariance( row, col ) = 0.0;
for( size_t index = 0; index < m_dataSet->size(); index++ )
addPointToCovariance( index );
for( size_t index = 0; index < dataSet.size(); index++ )
addPointToCovariance( dataSet[index] );
for( size_t row = 0; row < width; row++ )
for( size_t col = 0; col < width; col++ )
m_covariance( row, col ) /= static_cast<double>( m_dataSet->size() ) - 1.0;
m_covariance( row, col ) /= static_cast<double>( dataSet.size() ) - 1.0;
}
void WCovarianceSolver::addPointToCovariance( size_t pointIndex )
void WCovarianceSolver::addPointToCovariance( const WPosition& point )
{
size_t width = m_mean.size();
WPosition position = (*m_dataSet)[pointIndex];
for( size_t row = 0; row < width; row++ )
{
double rowValue = position[row] - m_mean[row];
double rowValue = point[row] - m_mean[row];
for( size_t col = 0; col < width; col++ )
{
double colValue = position[col] - m_mean[col];
double colValue = point[col] - m_mean[col];
m_covariance( row, col ) += rowValue * colValue;
}
}
......
......@@ -51,7 +51,7 @@ public:
* Analyzes the dimension covariances of a point data set.
* \param dataSet The point data to be analyzed.
*/
void analyzeData( const vector<WPosition>* dataSet );
void analyzeData( const vector<WPosition>& dataSet );
/**
* Returns the mean coordinate of the input point data set.
* \return The mean of the point data set.
......@@ -66,22 +66,21 @@ public:
private:
/**
* Calculates the mean of the input point data coordinates.
* \param dataSet Input point data that is used for the mean coordinate calculation.
*/
void calculateMean();
void calculateMean( const vector<WPosition>& dataSet );
/**
* Calculates the covariance of the input point data.
* \param dataSet Input point data that is used for the covariance matrix
* calculation.
*/
void calculateCovariance();
void calculateCovariance( const vector<WPosition>& dataSet );
/**
* Adds a point to the covariance solver.
* \param pointIndex Index of a point in the data set to add to the calculation.
* Adds a point to the covariance matrix.
* \param point Point in the data set to be added to the covariance matrix..
*/
void addPointToCovariance( size_t pointIndex );
void addPointToCovariance( const WPosition& point );
/**
* Input point data set to be analyzed.
*/
const vector<WPosition>* m_dataSet;
/**
* The mean of all input points.
*/
......
......@@ -34,11 +34,13 @@ WPrincipalComponentAnalysis::~WPrincipalComponentAnalysis()
{
}
void WPrincipalComponentAnalysis::analyzeData( const vector<WPosition>* inputData )
void WPrincipalComponentAnalysis::analyzeData( const vector<WPosition>& inputData )
{
m_isValidPCA = true;
m_inputData = inputData;
m_covarianceSolver.analyzeData( m_inputData );
m_inputPointCount = inputData.size();
if( m_inputPointCount > 0 )
m_dimensions = inputData.at( 0 ).size();
m_covarianceSolver.analyzeData( inputData );
EigenSolver<MatrixXd> es( m_covarianceSolver.getCovariance() );
m_eigenSolver = es;
extractEigenData();
......@@ -47,8 +49,8 @@ void WPrincipalComponentAnalysis::analyzeData( const vector<WPosition>* inputDat
void WPrincipalComponentAnalysis::extractEigenData()
{
int count = m_eigenSolver.eigenvalues().size();
m_directions.reserve( count );
m_directions.resize( count );
m_eigenVectors.reserve( count );
m_eigenVectors.resize( count );
m_eigenValues.reserve( count );
m_eigenValues.resize( count );
for( int index = 0; index < count; index++ )
......@@ -66,16 +68,15 @@ void WPrincipalComponentAnalysis::extractEigenData()
complex<double> value = vector[dimension];
newPosition[dimension] = value.real();
}
m_directions[index] = newPosition;
m_eigenVectors[index] = newPosition;
}
sortByVarianceDescending();
}
void WPrincipalComponentAnalysis::sortByVarianceDescending()
{
if( m_inputData->size() == 0 ) return;
size_t dimensions = (*m_inputData)[0].size();
for( size_t d1 = 0; d1 < dimensions - 1; d1++ )
for( size_t d2 = d1 + 1; d2 < dimensions; d2++ )
if( m_inputPointCount == 0 ) return;
for( size_t d1 = 0; d1 < m_dimensions - 1; d1++ )
for( size_t d2 = d1 + 1; d2 < m_dimensions; d2++ )
if( m_eigenValues[d1] < m_eigenValues[d2] )
swapEigenVectors( d1, d2 );
}
......@@ -83,9 +84,9 @@ void WPrincipalComponentAnalysis::swapEigenVectors( size_t eigenVectorIndex1, si
{
for( size_t dimension = 0; dimension < m_eigenValues.size(); dimension++ )
{
double prevValue = m_directions[eigenVectorIndex1][dimension];
m_directions[eigenVectorIndex1][dimension] = m_directions[eigenVectorIndex2][dimension];
m_directions[eigenVectorIndex2][dimension] = prevValue;
double prevValue = m_eigenVectors[eigenVectorIndex1][dimension];
m_eigenVectors[eigenVectorIndex1][dimension] = m_eigenVectors[eigenVectorIndex2][dimension];
m_eigenVectors[eigenVectorIndex2][dimension] = prevValue;
}
double prevValue = m_eigenValues[eigenVectorIndex1];
m_eigenValues[eigenVectorIndex1] = m_eigenValues[eigenVectorIndex2];
......@@ -95,9 +96,9 @@ WPosition WPrincipalComponentAnalysis::getMean()
{
return m_covarianceSolver.getMean();
}
vector<WVector3d> WPrincipalComponentAnalysis::getDirections()
vector<WVector3d> WPrincipalComponentAnalysis::getEigenVectors()
{
return m_directions;
return m_eigenVectors;
}
vector<double> WPrincipalComponentAnalysis::getEigenValues()
{
......
......@@ -66,7 +66,7 @@ public:
* Analyzes a point data set using the Principal Component Analysis algorithm.
* \param inputData Point data to be analyzed.
*/
void analyzeData( const vector<WPosition>* inputData );
void analyzeData( const vector<WPosition>& inputData );
/**
* Returns the mean coordinate of all input points.
* \return The mean coordinate of all input points.
......@@ -78,7 +78,7 @@ public:
* getVariance().
* \return Point distribution directions.
*/
vector<WVector3d> getDirections();
vector<WVector3d> getEigenVectors();
/**
* Returns Eigen Values (equals how much the directions of getDirections() are
* distributed). Its index corresponds to the indices of that method. The strengths
......@@ -104,9 +104,14 @@ private:
void swapEigenVectors( size_t eigenVectorIndex1, size_t eigenVectorIndex2 );
/**
* Point data to be analyzed.
* Point count of the input data.
*/
const vector<WPosition>* m_inputData;
size_t m_inputPointCount;
/**
* Dimension count used in the input data.
*/
size_t m_dimensions;
/**
* Instance to analyze the covariances of the point data between each dimension pair.
*/
......@@ -114,7 +119,7 @@ private:
/**
* Main point distribution directions. After process they're sorted by their strength descending.
*/
vector<WVector3d> m_directions;
vector<WVector3d> m_eigenVectors;
/**
* Lambda values for A*x-Lambda*x=0.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment