26 #define GRT_DLL_EXPORTS
34 numInputDimensions = 0;
35 numPrincipalComponents = 0;
38 classType =
"PrincipalComponentAnalysis";
39 errorLog.setProceedingText(
"[ERROR PrincipalComponentAnalysis]");
40 warningLog.setProceedingText(
"[WARNING PrincipalComponentAnalysis]");
49 this->maxVariance = maxVariance;
50 this->normData = normData;
51 return computeFeatureVector_(data,MAX_VARIANCE);
56 if( numPrincipalComponents > data.
getNumCols() ){
57 errorLog <<
"computeFeatureVector(const MatrixFloat &data,UINT numPrincipalComponents,bool normData) - The number of principal components (";
58 errorLog << numPrincipalComponents <<
") is greater than the number of columns in your data (" << data.
getNumCols() <<
")" << std::endl;
61 this->numPrincipalComponents = numPrincipalComponents;
62 this->normData = normData;
63 return computeFeatureVector_(data,MAX_NUM_PCS);
66 bool PrincipalComponentAnalysis::computeFeatureVector_(
const MatrixFloat &data,
const UINT analysisMode){
71 this->numInputDimensions = N;
81 for(UINT i=0; i<M; i++)
82 for(UINT j=0; j<N; j++)
83 msData[i][j] = (data[i][j]-mean[j]) / stdDev[j];
87 for(UINT i=0; i<M; i++)
88 for(UINT j=0; j<N; j++)
89 msData[i][j] = data[i][j] - mean[j];
98 if( !eig.decompose( cov ) ){
101 componentWeights.clear();
102 sortedEigenvalues.clear();
103 eigenvectors.
clear();
104 errorLog <<
"computeFeatureVector(const MatrixFloat &data,UINT analysisMode) - Failed to decompose input matrix!" << std::endl;
113 for(UINT i=0; i<eigenvalues.size(); i++){
114 if( eigenvalues[i] < 0 )
120 UINT componentIndex = 0;
121 sortedEigenvalues.clear();
122 componentWeights.
resize(N,0);
127 for(UINT i=0; i<eigenvalues.size(); i++){
128 if( eigenvalues[i] > maxValue ){
129 maxValue = eigenvalues[i];
133 if( maxValue == 0 || componentIndex >= eigenvalues.size() ){
136 sortedEigenvalues.push_back(
IndexedDouble(index,maxValue) );
137 componentWeights[ componentIndex++ ] = eigenvalues[ index ];
138 sum += eigenvalues[ index ];
139 eigenvalues[ index ] = 0;
142 Float cumulativeVariance = 0;
143 switch( analysisMode ){
146 numPrincipalComponents = 0;
147 for(UINT k=0; k<N; k++){
148 componentWeights[k] /= sum;
149 cumulativeVariance += componentWeights[k];
150 if( cumulativeVariance >= maxVariance && numPrincipalComponents==0 ){
151 numPrincipalComponents = k+1;
158 for(UINT k=0; k<N; k++){
159 componentWeights[k] /= sum;
160 if( k < numPrincipalComponents ){
161 maxVariance += componentWeights[k];
166 errorLog <<
"computeFeatureVector(const MatrixFloat &data,UINT analysisMode) - Unknown analysis mode!" << std::endl;
182 warningLog <<
"project(const MatrixFloat &data,MatrixFloat &prjData) - The PrincipalComponentAnalysis module has not been trained!" << std::endl;
186 if( data.
getNumCols() != numInputDimensions ){
187 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;
197 for(UINT j=0; j<numInputDimensions; j++)
198 msData[i][j] = (msData[i][j]-mean[j])/stdDev[j];
202 for(UINT j=0; j<numInputDimensions; j++)
203 msData[i][j] -= mean[j];
207 for(UINT row=0; row<msData.
getNumRows(); row++){
208 for(UINT i=0; i<numPrincipalComponents; i++){
211 prjData[row][i] += msData[row][j] * eigenvectors[j][sortedEigenvalues[i].index];
220 const unsigned int N = (
unsigned int)data.size();
223 warningLog <<
"project(const VectorFloat &data,VectorFloat &prjData) - The PrincipalComponentAnalysis module has not been trained!" << std::endl;
227 if( N != numInputDimensions ){
228 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;
236 for(UINT j=0; j<numInputDimensions; j++)
237 msData[j] = (msData[j]-mean[j])/stdDev[j];
240 for(UINT j=0; j<numInputDimensions; j++)
241 msData[j] -= mean[j];
245 prjData.
resize( numPrincipalComponents );
246 for(UINT i=0; i<numPrincipalComponents; i++){
248 for(UINT j=0; j<N; j++)
249 prjData[i] += msData[j] * eigenvectors[j][sortedEigenvalues[i].index];
258 file <<
"GRT_PCA_MODEL_FILE_V1.0\n";
262 file <<
"NumPrincipalComponents: " << numPrincipalComponents << std::endl;
263 file <<
"NormData: " << normData << std::endl;
264 file <<
"MaxVariance: " << maxVariance << std::endl;
268 for(
unsigned int i=0; i<numInputDimensions; i++){
269 file << mean[i] <<
" ";
274 for(
unsigned int i=0; i<numInputDimensions; i++){
275 file << stdDev[i] <<
" ";
279 file <<
"ComponentWeights: ";
280 for(
unsigned int i=0; i<numInputDimensions; i++){
281 file << componentWeights[i] <<
" ";
285 file <<
"Eigenvalues: ";
286 for(
unsigned int i=0; i<numInputDimensions; i++){
287 file << eigenvalues[i] <<
" ";
291 file <<
"SortedEigenvalues: ";
292 for(
unsigned int i=0; i<numInputDimensions; i++){
293 file << sortedEigenvalues[i].index <<
" ";
294 file << sortedEigenvalues[i].value <<
" ";
298 file <<
"Eigenvectors: ";
300 for(
unsigned int i=0; i<eigenvectors.
getNumRows(); i++){
301 for(
unsigned int j=0; j<eigenvectors.
getNumCols(); j++){
302 file << eigenvectors[i][j];
303 if( j+1 < eigenvectors.getNumCols() ) file <<
" ";
304 else file << std::endl;
319 if( word !=
"GRT_PCA_MODEL_FILE_V1.0" ){
327 if( word !=
"NumPrincipalComponents:" ){
330 file >> numPrincipalComponents;
334 if( word !=
"NormData:" ){
341 if( word !=
"MaxVariance:" ){
349 if( word !=
"Mean:" ){
353 mean.
resize( numInputDimensions );
355 for(
unsigned int i=0; i<numInputDimensions; i++){
361 if( word !=
"StdDev:" ){
365 stdDev.
resize( numInputDimensions );
367 for(
unsigned int i=0; i<numInputDimensions; i++){
373 if( word !=
"ComponentWeights:" ){
377 componentWeights.
resize( numInputDimensions );
379 for(
unsigned int i=0; i<numInputDimensions; i++){
380 file >> componentWeights[i];
385 if( word !=
"Eigenvalues:" ){
389 eigenvalues.
resize( numInputDimensions );
391 for(
unsigned int i=0; i<numInputDimensions; i++){
392 file >> eigenvalues[i];
397 if( word !=
"SortedEigenvalues:" ){
401 sortedEigenvalues.
resize( numInputDimensions );
403 for(
unsigned int i=0; i<numInputDimensions; i++){
404 file >> sortedEigenvalues[i].index;
405 file >> sortedEigenvalues[i].value;
410 if( word !=
"Eigenvectors:" ){
418 eigenvectors.
resize( numRows, numCols );
420 for(
unsigned int i=0; i<eigenvectors.
getNumRows(); i++){
421 for(
unsigned int j=0; j<eigenvectors.
getNumCols(); j++){
422 file >> eigenvectors[i][j];
433 std::cout << title << std::endl;
436 std::cout <<
"Not Trained!\n";
439 std::cout <<
"NumInputDimensions: " << numInputDimensions <<
" NumPrincipalComponents: " << numPrincipalComponents << std::endl;
440 std::cout <<
"ComponentWeights: ";
441 for(UINT k=0; k<componentWeights.size(); k++){
442 std::cout <<
"\t" << componentWeights[k];
444 std::cout << std::endl;
445 std::cout <<
"SortedEigenValues: ";
446 for(UINT k=0; k<sortedEigenvalues.size(); k++){
447 std::cout <<
"\t" << sortedEigenvalues[k].value;
449 std::cout << std::endl;
450 eigenvectors.
print(
"Eigenvectors:");
461 if( (UINT)mean.size() != eigenvectors.
getNumCols() ){
466 numInputDimensions = eigenvectors.
getNumCols();
467 numPrincipalComponents = eigenvectors.
getNumRows();
470 componentWeights.clear();
472 sortedEigenvalues.clear();
473 this->eigenvectors = eigenvectors;
476 for(UINT i=0; i<numPrincipalComponents; i++){
bool saveBaseSettingsToFile(std::fstream &file) const
virtual ~PrincipalComponentAnalysis()
virtual bool resize(const unsigned int size)
PrincipalComponentAnalysis()
virtual bool save(std::fstream &file) const
virtual bool load(std::fstream &file)
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