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 MatrixFloat &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() <<
")" << std::endl;
60 this->numPrincipalComponents = numPrincipalComponents;
61 this->normData = normData;
62 return computeFeatureVector_(data,MAX_NUM_PCS);
65 bool PrincipalComponentAnalysis::computeFeatureVector_(
const MatrixFloat &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];
97 if( !eig.decompose( cov ) ){
100 componentWeights.clear();
101 sortedEigenvalues.clear();
102 eigenvectors.
clear();
103 errorLog <<
"computeFeatureVector(const MatrixFloat &data,UINT analysisMode) - Failed to decompose input matrix!" << std::endl;
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 Float 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 MatrixFloat &data,UINT analysisMode) - Unknown analysis mode!" << std::endl;
181 warningLog <<
"project(const MatrixFloat &data,MatrixFloat &prjData) - The PrincipalComponentAnalysis module has not been trained!" << std::endl;
185 if( data.
getNumCols() != numInputDimensions ){
186 warningLog <<
"project(const MatrixFloat &data,MatrixFloat &prjData) - The number of columns in the input vector (" << data.
getNumCols() <<
") does not match the number of input dimensions (" << numInputDimensions <<
")!" << std::endl;
196 for(UINT j=0; j<numInputDimensions; j++)
197 msData[i][j] = (msData[i][j]-mean[j])/stdDev[j];
201 for(UINT j=0; j<numInputDimensions; j++)
202 msData[i][j] -= mean[j];
206 for(UINT row=0; row<msData.
getNumRows(); row++){
207 for(UINT i=0; i<numPrincipalComponents; i++){
210 prjData[row][i] += msData[row][j] * eigenvectors[j][sortedEigenvalues[i].index];
219 const unsigned int N = (
unsigned int)data.size();
222 warningLog <<
"project(const VectorFloat &data,VectorFloat &prjData) - The PrincipalComponentAnalysis module has not been trained!" << std::endl;
226 if( N != numInputDimensions ){
227 warningLog <<
"project(const VectorFloat &data,VectorFloat &prjData) - The size of the input vector (" << N <<
") does not match the number of input dimensions (" << numInputDimensions <<
")!" << std::endl;
235 for(UINT j=0; j<numInputDimensions; j++)
236 msData[j] = (msData[j]-mean[j])/stdDev[j];
239 for(UINT j=0; j<numInputDimensions; j++)
240 msData[j] -= mean[j];
244 prjData.
resize( numPrincipalComponents );
245 for(UINT i=0; i<numPrincipalComponents; i++){
247 for(UINT j=0; j<N; j++)
248 prjData[i] += msData[j] * eigenvectors[j][sortedEigenvalues[i].index];
257 file <<
"GRT_PCA_MODEL_FILE_V1.0\n";
261 file <<
"NumPrincipalComponents: " << numPrincipalComponents << std::endl;
262 file <<
"NormData: " << normData << std::endl;
263 file <<
"MaxVariance: " << maxVariance << std::endl;
267 for(
unsigned int i=0; i<numInputDimensions; i++){
268 file << mean[i] <<
" ";
273 for(
unsigned int i=0; i<numInputDimensions; i++){
274 file << stdDev[i] <<
" ";
278 file <<
"ComponentWeights: ";
279 for(
unsigned int i=0; i<numInputDimensions; i++){
280 file << componentWeights[i] <<
" ";
284 file <<
"Eigenvalues: ";
285 for(
unsigned int i=0; i<numInputDimensions; i++){
286 file << eigenvalues[i] <<
" ";
290 file <<
"SortedEigenvalues: ";
291 for(
unsigned int i=0; i<numInputDimensions; i++){
292 file << sortedEigenvalues[i].index <<
" ";
293 file << sortedEigenvalues[i].value <<
" ";
297 file <<
"Eigenvectors: ";
299 for(
unsigned int i=0; i<eigenvectors.
getNumRows(); i++){
300 for(
unsigned int j=0; j<eigenvectors.
getNumCols(); j++){
301 file << eigenvectors[i][j];
302 if( j+1 < eigenvectors.getNumCols() ) file <<
" ";
303 else file << std::endl;
318 if( word !=
"GRT_PCA_MODEL_FILE_V1.0" ){
326 if( word !=
"NumPrincipalComponents:" ){
329 file >> numPrincipalComponents;
333 if( word !=
"NormData:" ){
340 if( word !=
"MaxVariance:" ){
348 if( word !=
"Mean:" ){
352 mean.
resize( numInputDimensions );
354 for(
unsigned int i=0; i<numInputDimensions; i++){
360 if( word !=
"StdDev:" ){
364 stdDev.
resize( numInputDimensions );
366 for(
unsigned int i=0; i<numInputDimensions; i++){
372 if( word !=
"ComponentWeights:" ){
376 componentWeights.
resize( numInputDimensions );
378 for(
unsigned int i=0; i<numInputDimensions; i++){
379 file >> componentWeights[i];
384 if( word !=
"Eigenvalues:" ){
388 eigenvalues.
resize( numInputDimensions );
390 for(
unsigned int i=0; i<numInputDimensions; i++){
391 file >> eigenvalues[i];
396 if( word !=
"SortedEigenvalues:" ){
400 sortedEigenvalues.
resize( numInputDimensions );
402 for(
unsigned int i=0; i<numInputDimensions; i++){
403 file >> sortedEigenvalues[i].index;
404 file >> sortedEigenvalues[i].value;
409 if( word !=
"Eigenvectors:" ){
417 eigenvectors.
resize( numRows, numCols );
419 for(
unsigned int i=0; i<eigenvectors.
getNumRows(); i++){
420 for(
unsigned int j=0; j<eigenvectors.
getNumCols(); j++){
421 file >> eigenvectors[i][j];
432 std::cout << title << std::endl;
435 std::cout <<
"Not Trained!\n";
438 std::cout <<
"NumInputDimensions: " << numInputDimensions <<
" NumPrincipalComponents: " << numPrincipalComponents << std::endl;
439 std::cout <<
"ComponentWeights: ";
440 for(UINT k=0; k<componentWeights.size(); k++){
441 std::cout <<
"\t" << componentWeights[k];
443 std::cout << std::endl;
444 std::cout <<
"SortedEigenValues: ";
445 for(UINT k=0; k<sortedEigenvalues.size(); k++){
446 std::cout <<
"\t" << sortedEigenvalues[k].value;
448 std::cout << std::endl;
449 eigenvectors.
print(
"Eigenvectors:");
460 if( (UINT)mean.size() != eigenvectors.
getNumCols() ){
465 numInputDimensions = eigenvectors.
getNumCols();
466 numPrincipalComponents = eigenvectors.
getNumRows();
469 componentWeights.clear();
471 sortedEigenvalues.clear();
472 this->eigenvectors = eigenvectors;
475 for(UINT i=0; i<numPrincipalComponents; i++){
bool saveBaseSettingsToFile(std::fstream &file) const
virtual ~PrincipalComponentAnalysis()
virtual bool loadModelFromFile(std::fstream &file)
virtual bool resize(const unsigned int size)
PrincipalComponentAnalysis()
virtual bool saveModelToFile(std::fstream &file) const
MatrixFloat getEigenvectors()
bool print(const std::string title="") const
virtual bool print() const
VectorFloat getMean() const
MatrixFloat getCovarianceMatrix() const
unsigned int getNumRows() const
unsigned int getNumCols() const
bool loadBaseSettingsFromFile(std::fstream &file)
MatrixFloat getEigenVectors() const
This class runs the Principal Component Analysis (PCA) algorithm, a dimensionality reduction algorith...
VectorFloat getRealEigenvalues()
bool project(const MatrixFloat &data, MatrixFloat &prjData)
virtual bool resize(const unsigned int r, const unsigned int c)
bool computeFeatureVector(const MatrixFloat &data, Float maxVariance=0.95, bool normData=false)
VectorFloat getStdDev() const