33 numInputDimensions = 0;
34 numPrincipalComponents = 0;
37 classType =
"PrincipalComponentAnalysis";
38 errorLog.setProceedingText(
"[ERROR PrincipalComponentAnalysis]");
39 warningLog.setProceedingText(
"[WARNING PrincipalComponentAnalysis]");
48 this->maxVariance = maxVariance;
49 this->normData = normData;
50 return computeFeatureVector_(data,MAX_VARIANCE);
55 if( numPrincipalComponents > data.
getNumCols() ){
56 errorLog <<
"computeFeatureVector(const MatrixDouble &data,UINT numPrincipalComponents,bool normData) - The number of principal components (";
57 errorLog << numPrincipalComponents <<
") is greater than the number of columns in your data (" << data.
getNumCols() <<
")" << endl;
60 this->numPrincipalComponents = numPrincipalComponents;
61 this->normData = normData;
62 return computeFeatureVector_(data,MAX_NUM_PCS);
65 bool PrincipalComponentAnalysis::computeFeatureVector_(
const MatrixDouble &data,
const UINT analysisMode){
70 this->numInputDimensions = N;
80 for(UINT i=0; i<M; i++)
81 for(UINT j=0; j<N; j++)
82 msData[i][j] = (data[i][j]-mean[j]) / stdDev[j];
86 for(UINT i=0; i<M; i++)
87 for(UINT j=0; j<N; j++)
88 msData[i][j] = data[i][j] - mean[j];
95 EigenvalueDecomposition eig;
97 if( !eig.decompose( cov ) ){
100 componentWeights.clear();
101 sortedEigenvalues.clear();
102 eigenvectors.
clear();
103 errorLog <<
"computeFeatureVector(const MatrixDouble &data,UINT analysisMode) - Failed to decompose input matrix!" << endl;
108 eigenvectors = eig.getEigenvectors();
109 eigenvalues = eig.getRealEigenvalues();
112 for(UINT i=0; i<eigenvalues.size(); i++){
113 if( eigenvalues[i] < 0 )
119 UINT componentIndex = 0;
120 sortedEigenvalues.clear();
121 componentWeights.resize(N,0);
126 for(UINT i=0; i<eigenvalues.size(); i++){
127 if( eigenvalues[i] > maxValue ){
128 maxValue = eigenvalues[i];
132 if( maxValue == 0 || componentIndex >= eigenvalues.size() ){
135 sortedEigenvalues.push_back( IndexedDouble(index,maxValue) );
136 componentWeights[ componentIndex++ ] = eigenvalues[ index ];
137 sum += eigenvalues[ index ];
138 eigenvalues[ index ] = 0;
141 double cumulativeVariance = 0;
142 switch( analysisMode ){
145 numPrincipalComponents = 0;
146 for(UINT k=0; k<N; k++){
147 componentWeights[k] /= sum;
148 cumulativeVariance += componentWeights[k];
149 if( cumulativeVariance >= maxVariance && numPrincipalComponents==0 ){
150 numPrincipalComponents = k+1;
157 for(UINT k=0; k<N; k++){
158 componentWeights[k] /= sum;
159 if( k < numPrincipalComponents ){
160 maxVariance += componentWeights[k];
165 errorLog <<
"computeFeatureVector(const MatrixDouble &data,UINT analysisMode) - Unknown analysis mode!" << endl;
170 eigenvalues = eig.getRealEigenvalues();
181 warningLog <<
"project(const MatrixDouble &data,MatrixDouble &prjData) - The PrincipalComponentAnalysis module has not been trained!" << endl;
184 if( data.
getNumCols() != numInputDimensions ){
185 warningLog <<
"project(const MatrixDouble &data,MatrixDouble &prjData) - The number of columns in the input vector (" << data.
getNumCols() <<
") does not match the number of input dimensions (" << numInputDimensions <<
")!" << endl;
195 for(UINT j=0; j<numInputDimensions; j++)
196 msData[i][j] = (msData[i][j]-mean[j])/stdDev[j];
200 for(UINT j=0; j<numInputDimensions; j++)
201 msData[i][j] -= mean[j];
205 for(UINT row=0; row<msData.
getNumRows(); row++){
206 for(UINT i=0; i<numPrincipalComponents; i++){
209 prjData[row][i] += msData[row][j] * eigenvectors[j][sortedEigenvalues[i].index];
218 const unsigned int N = (
unsigned int)data.size();
221 warningLog <<
"project(const VectorDouble &data,VectorDouble &prjData) - The PrincipalComponentAnalysis module has not been trained!" << endl;
224 if( N != numInputDimensions ){
225 warningLog <<
"project(const VectorDouble &data,VectorDouble &prjData) - The size of the input vector (" << N <<
") does not match the number of input dimensions (" << numInputDimensions <<
")!" << endl;
229 VectorDouble msData = data;
233 for(UINT j=0; j<numInputDimensions; j++)
234 msData[j] = (msData[j]-mean[j])/stdDev[j];
237 for(UINT j=0; j<numInputDimensions; j++)
238 msData[j] -= mean[j];
242 prjData.resize( numPrincipalComponents );
243 for(UINT i=0; i<numPrincipalComponents; i++){
245 for(UINT j=0; j<N; j++)
246 prjData[i] += msData[j] * eigenvectors[j][sortedEigenvalues[i].index];
255 cout << title << endl;
258 cout <<
"Not Trained!\n";
261 cout <<
"NumInputDimensions: " << numInputDimensions <<
" NumPrincipalComponents: " << numPrincipalComponents << endl;
262 cout <<
"ComponentWeights: ";
263 for(UINT k=0; k<componentWeights.size(); k++){
264 cout <<
"\t" << componentWeights[k];
267 cout <<
"SortedEigenValues: ";
268 for(UINT k=0; k<sortedEigenvalues.size(); k++){
269 cout <<
"\t" << sortedEigenvalues[k].value;
272 eigenvectors.
print(
"Eigenvectors:");
unsigned int getNumCols() const
VectorDouble getStdDev() const
virtual bool print(string title="") const
MatrixDouble getEigenVectors() const
bool computeFeatureVector(const MatrixDouble &data, double maxVariance=0.95, bool normData=false)
MatrixDouble getCovarianceMatrix() const
virtual ~PrincipalComponentAnalysis()
unsigned int getNumRows() const
This class runs the Principal Component Analysis (PCA) algorithm, a dimensionality reduction algorith...
VectorDouble getMean() const
bool project(const MatrixDouble &data, MatrixDouble &prjData)
virtual bool resize(const unsigned int r, const unsigned int c)
PrincipalComponentAnalysis()
bool print(const string title="") const