GestureRecognitionToolkit  Version: 0.1.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
GestureRecognitionPipeline.cpp
1 /*
2 GRT MIT License
3 Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6 and associated documentation files (the "Software"), to deal in the Software without restriction,
7 including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in all copies or substantial
12 portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 */
20 
22 
23 GRT_BEGIN_NAMESPACE
24 
26 {
27  init();
28 
29  debugLog.setProceedingText("[DEBUG GRP]");
30  errorLog.setProceedingText("[ERROR GRP]");
31  warningLog.setProceedingText("[WARNING GRP]");
32  testingLog.setProceedingText("[TEST GRP]");
33 }
34 
36 
37  init();
38 
39  debugLog.setProceedingText("[DEBUG GRP]");
40  errorLog.setProceedingText("[ERROR GRP]");
41  warningLog.setProceedingText("[WARNING GRP]");
42  testingLog.setProceedingText("[TEST GRP]");
43 
44  //Invoke the equals operator to copy the rhs data to this instance
45  *this = rhs;
46 }
47 
48 
50 
51  if( this != &rhs ){
52  this->clear();
53 
54  //Copy the pipeline variables
55  this->initialized = rhs.initialized;
56  this->trained = rhs.trained;
57  this->info = rhs.info;
58  this->inputVectorDimensions = rhs.inputVectorDimensions;
59  this->outputVectorDimensions = rhs.outputVectorDimensions;
60  this->predictedClassLabel = rhs.predictedClassLabel;
61  this->predictedClusterLabel = rhs.predictedClusterLabel;
62  this->pipelineMode = rhs.pipelineMode;
63  this->predictionModuleIndex = rhs.predictionModuleIndex;
64  this->numTrainingSamples = rhs.numTrainingSamples;
65  this->numTestSamples = rhs.numTestSamples;
66  this->testAccuracy = rhs.testAccuracy;
67  this->testRMSError = rhs.testRMSError;
68  this->testSquaredError = rhs.testSquaredError;
69  this->testTime = rhs.testTime;
70  this->trainingTime = rhs.trainingTime;
71  this->testFMeasure = rhs.testFMeasure;
72  this->testPrecision = rhs.testPrecision;
73  this->testRecall = rhs.testRecall;
74  this->regressionData = rhs.regressionData;
75  this->testRejectionPrecision = rhs.testRejectionPrecision;
76  this->testRejectionRecall = rhs.testRejectionRecall;
77  this->testConfusionMatrix = rhs.testConfusionMatrix;
78  this->crossValidationResults = rhs.crossValidationResults;
79  this->testResults = rhs.testResults;
80 
81  //Copy the GRT Base variables
82  this->debugLog = rhs.debugLog;
83  this->errorLog = rhs.errorLog;
84  this->trainingLog = rhs.trainingLog;
85  this->testingLog = rhs.testingLog;
86  this->warningLog = rhs.warningLog;
87 
88  for(unsigned int i=0; i<rhs.preProcessingModules.size(); i++){
89  this->addPreProcessingModule( *(rhs.preProcessingModules[i]) );
90  }
91 
92  for(unsigned int i=0; i<rhs.featureExtractionModules.size(); i++){
93  this->addFeatureExtractionModule( *(rhs.featureExtractionModules[i]) );
94  }
95 
97  setClassifier( *rhs.classifier );
98  }
99 
100  if( rhs.getIsPipelineInRegressionMode() ){
101  setRegressifier( *rhs.regressifier );
102  }
103 
104  if( rhs.getIsClustererSet() ){
105  setClusterer( *rhs.clusterer );
106  }
107 
108  for(unsigned int i=0; i<rhs.postProcessingModules.size(); i++){
109  this->addPostProcessingModule( *(rhs.postProcessingModules[i]) );
110  }
111 
112  for(unsigned int k=0; k<NUM_CONTEXT_LEVELS; k++){
113  for(unsigned int i=0; i<rhs.contextModules[k].size(); i++){
114  this->addContextModule( *(rhs.contextModules[k][i]), k );
115  }
116  }
117 
118  //Adding the modules will automatically set trained to false, so make sure we get the correct state
119  this->trained = rhs.trained;
120  }
121 
122  return *this;
123 }
124 
126  this->addPreProcessingModule( module );
127  return *this;
128 }
129 
131  this->addFeatureExtractionModule( module );
132  return *this;
133 }
134 
136  this->setClassifier( module );
137  return *this;
138 }
139 
141  this->setRegressifier( module );
142  return *this;
143 }
144 
146  this->setClusterer( module );
147  return *this;
148 }
149 
151  this->addPostProcessingModule( module );
152  return *this;
153 }
154 
156 {
157  //Clean up the memory
158  clear();
159 }
160 
162 
163  trained = false;
164  trainingTime = 0;
166 
167  if( !getIsClassifierSet() ){
168  errorLog << "train(ClassificationData trainingData) - Failed To Train Classifier, the classifier has not been set!" << std::endl;
169  return false;
170  }
171 
172  if( trainingData.getNumSamples() == 0 ){
173  errorLog << "train(ClassificationData trainingData) - Failed To Train Classifier, there is no training data!" << std::endl;
174  return false;
175  }
176 
177  //Reset all the modules
178  reset();
179 
180  //Set the input Vector dimension size
181  inputVectorDimensions = trainingData.getNumDimensions();
182 
183  //Pass the training data through any pre-processing or feature extraction units
184  UINT numDimensions = trainingData.getNumDimensions();
185 
186  //If there are any preprocessing or feature extraction modules, then get the size of the last module
189  numDimensions = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
190  }else{
191  numDimensions = preProcessingModules[ preProcessingModules.size()-1 ]->getNumOutputDimensions();
192  }
193  }
194 
195  //Start the training timer
196  Timer timer;
197  timer.start();
198 
199  ClassificationData processedTrainingData( numDimensions );
200  processedTrainingData.reserve( trainingData.getNumSamples() );
201  UINT classLabel = 0;
202  VectorFloat trainingSample;
203  for(UINT i=0; i<trainingData.getNumSamples(); i++){
204  bool okToAddProcessedData = true;
205  classLabel = trainingData[i].getClassLabel();
206  trainingSample = trainingData[i].getSample();
207 
208  //Perform any preprocessing
209  if( getIsPreProcessingSet() ){
210  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
211  if( !preProcessingModules[moduleIndex]->process( trainingSample ) ){
212  errorLog << "train(ClassificationData trainingData) - Failed to PreProcess Training Data. PreProcessingModuleIndex: ";
213  errorLog << moduleIndex;
214  errorLog << std::endl;
215  return false;
216  }
217  trainingSample = preProcessingModules[moduleIndex]->getProcessedData();
218  }
219  }
220 
221  //Compute any features
223  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
224  if( !featureExtractionModules[moduleIndex]->computeFeatures( trainingSample ) ){
225  errorLog << "train(ClassificationData trainingData) - Failed to Compute Features from Training Data. FeatureExtractionModuleIndex ";
226  errorLog << moduleIndex;
227  errorLog << std::endl;
228  return false;
229  }
230  if( featureExtractionModules[moduleIndex]->getFeatureDataReady() ){
231  trainingSample = featureExtractionModules[moduleIndex]->getFeatureVector();
232  }else{
233  okToAddProcessedData = false;
234  break;
235  }
236  }
237  }
238 
239  if( okToAddProcessedData ){
240  //Add the training sample to the processed training data
241  processedTrainingData.addSample(classLabel, trainingSample);
242  }
243 
244  }
245 
246  if( processedTrainingData.getNumSamples() != trainingData.getNumSamples() ){
247  warningLog << "train(ClassificationData trainingData) - Lost " << trainingData.getNumSamples()-processedTrainingData.getNumSamples() << " of " << trainingData.getNumSamples() << " training samples due to the processing stage!" << std::endl;
248  }
249 
250  //Store the number of training samples
251  numTrainingSamples = processedTrainingData.getNumSamples();
252 
253  //Train the classifier
254  trained = classifier->train_( processedTrainingData );
255  if( !trained ){
256  errorLog << "train(ClassificationData trainingData) - Failed To Train Classifier: " << classifier->getLastErrorMessage() << std::endl;
257  return false;
258  }
259 
260  //Store the training time
261  trainingTime = timer.getMilliSeconds();
262 
263  return true;
264 }
265 
266 bool GestureRecognitionPipeline::train(const ClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling){
267 
268  trained = false;
269  trainingTime = 0;
271 
272  if( !getIsClassifierSet() ){
273  errorLog << "train(const ClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed To Train Classifier, the classifier has not been set!" << std::endl;
274  return false;
275  }
276 
277  if( trainingData.getNumSamples() == 0 ){
278  errorLog << "train(const ClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed To Train Classifier, there is no training data!" << std::endl;
279  return false;
280  }
281 
282  //Reset all the modules
283  reset();
284 
285  //Start the training timer
286  Timer timer;
287  timer.start();
288 
289  //Get a copy of the data so we can spilt it
290  ClassificationData data = trainingData;
291 
292  //Spilt the data into K folds
293  bool spiltResult = data.spiltDataIntoKFolds(kFoldValue, useStratifiedSampling);
294 
295  if( !spiltResult ){
296  return false;
297  }
298 
299  //Run the k-fold training and testing
300  Float crossValidationAccuracy = 0;
301  ClassificationData foldTrainingData;
302  ClassificationData foldTestData;
303  Vector< TestResult > cvResults(kFoldValue);
304 
305  for(UINT k=0; k<kFoldValue; k++){
307  foldTrainingData = data.getTrainingFoldData(k);
308 
309  if( !train( foldTrainingData ) ){
310  return false;
311  }
312 
313  //Test the classification system
314  foldTestData = data.getTestFoldData(k);
315 
316  if( !test( foldTestData ) ){
317  return false;
318  }
319 
320  crossValidationAccuracy += getTestAccuracy();
321  cvResults[k] = getTestResults();
322  }
323 
324  //Flag that the model has been trained
325  trained = true;
326 
327  //Set the accuracy of the classification system averaged over the kfolds
328  testAccuracy = crossValidationAccuracy / Float(kFoldValue);
329  crossValidationResults = cvResults;
330 
331  //Store the training time
332  trainingTime = timer.getMilliSeconds();
333 
334  return true;
335 }
336 
338 
339  trained = false;
340  trainingTime = 0;
342 
343  if( !getIsClassifierSet() ){
344  errorLog << "train(const TimeSeriesClassificationData &trainingData) - Failed To Train Classifier, the classifier has not been set!" << std::endl;
345  return false;
346  }
347 
348  if( trainingData.getNumSamples() == 0 ){
349  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To Train Classifier, there is no training data!" << std::endl;
350  return false;
351  }
352 
353  //Reset all the modules
354  reset();
355 
356  //Start the training timer
357  Timer timer;
358  timer.start();
359 
360  //Set the input Vector dimension size of the pipeline
361  inputVectorDimensions = trainingData.getNumDimensions();
362 
363  TimeSeriesClassificationData processedTrainingData( trainingData.getNumDimensions() );
364  TimeSeriesClassificationData timeseriesClassificationData;
365  ClassificationData classificationData;
366 
367  bool allowNullGestureClass = true;
368  processedTrainingData.setAllowNullGestureClass( allowNullGestureClass );
369  timeseriesClassificationData.setAllowNullGestureClass( allowNullGestureClass );
370  classificationData.setAllowNullGestureClass( allowNullGestureClass );
371 
372  //Setup the data structure, if the classifier works with timeseries data then we use TimeSeriesClassificationData
373  //otherwise we format the data as ClassificationData
374  if( classifier->getTimeseriesCompatible() ){
375  UINT trainingDataInputDimensionSize = trainingData.getNumDimensions();
376  if( getIsPreProcessingSet() ){
377  trainingDataInputDimensionSize = preProcessingModules[ preProcessingModules.size()-1 ]->getNumOutputDimensions();
378  }
380  trainingDataInputDimensionSize = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
381  }
382  timeseriesClassificationData.setNumDimensions( trainingDataInputDimensionSize );
383  }else{
384  UINT trainingDataInputDimensionSize = trainingData.getNumDimensions();
385  if( getIsPreProcessingSet() ){
386  trainingDataInputDimensionSize = preProcessingModules[ preProcessingModules.size()-1 ]->getNumOutputDimensions();
387  }
389  trainingDataInputDimensionSize = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
390  }
391  classificationData.setNumDimensions( trainingDataInputDimensionSize );
392  }
393 
394  //Pass the timeseries data through any pre-processing modules and add it to the processedTrainingData structure
395  for(UINT i=0; i<trainingData.getNumSamples(); i++){
396  UINT classLabel = trainingData[i].getClassLabel();
397  MatrixFloat trainingSample = trainingData[i].getData();
398 
399  if( getIsPreProcessingSet() ){
400 
401  //Try to process the matrix data row-by-row
402  bool resetPreprocessingModule = true;
403  for(UINT r=0; r<trainingSample.getNumRows(); r++){
404  VectorFloat sample = trainingSample.getRow( r );
405 
406  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
407 
408  if( resetPreprocessingModule ){
409  preProcessingModules[moduleIndex]->reset();
410  }
411 
412  //Validate the input and output dimensions match!
413  if( preProcessingModules[moduleIndex]->getNumInputDimensions() != preProcessingModules[moduleIndex]->getNumOutputDimensions() ){
414  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To PreProcess Training Data. The number of inputDimensions (";
415  errorLog << preProcessingModules[moduleIndex]->getNumInputDimensions();
416  errorLog << ") in PreProcessingModule ";
417  errorLog << moduleIndex;
418  errorLog << " do not match the number of outputDimensions (";
419  errorLog << preProcessingModules[moduleIndex]->getNumOutputDimensions();
420  errorLog << std::endl;
421  return false;
422  }
423 
424  if( !preProcessingModules[moduleIndex]->process( sample ) ){
425  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To PreProcess Training Data. PreProcessingModuleIndex: ";
426  errorLog << moduleIndex;
427  errorLog << std::endl;
428  return false;
429  }
430  sample = preProcessingModules[moduleIndex]->getProcessedData();
431  }
432 
433  //The preprocessing modules should only be reset when r==0
434  resetPreprocessingModule = false;
435 
436  //Overwrite the original training sample with the preProcessed sample
437  for(UINT c=0; c<sample.size(); c++){
438  trainingSample[r][c] = sample[c];
439  }
440  }
441 
442  }
443 
444  //Add the training sample to the processed training data
445  processedTrainingData.addSample(classLabel,trainingSample);
446  }
447 
448  //Loop over the processed training data, perfrom any feature extraction if needed
449  //Add the data to either the timeseries or classification data structures
450  for(UINT i=0; i<processedTrainingData.getNumSamples(); i++){
451  UINT classLabel = processedTrainingData[i].getClassLabel();
452  MatrixFloat trainingSample = processedTrainingData[i].getData();
453  bool featureDataReady = false;
454  bool resetFeatureExtractionModules = true;
455 
456  VectorFloat inputVector;
457  MatrixFloat featureData;
458  //Try to process the matrix data row-by-row
459  for(UINT r=0; r<trainingSample.getNumRows(); r++){
460  inputVector = trainingSample.getRow( r );
461  featureDataReady = true;
462 
463  //Pass the processed training data through the feature extraction
465 
466  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
467 
468  if( resetFeatureExtractionModules ){
469  featureExtractionModules[moduleIndex]->reset();
470  }
471 
472  if( !featureExtractionModules[moduleIndex]->computeFeatures( inputVector ) ){
473  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To Compute Features For Training Data. FeatureExtractionModuleIndex: ";
474  errorLog << moduleIndex;
475  errorLog << std::endl;
476  return false;
477  }
478 
479  //Overwrite the input Vector with the features so this can either be input to the next feature module
480  //or converted to the LabelledClassificationData format
481  inputVector = featureExtractionModules[moduleIndex]->getFeatureVector();
482  featureDataReady = featureExtractionModules[moduleIndex]->getFeatureDataReady();
483  }
484 
485  //The feature extraction modules should only be reset on r == 0
486  resetFeatureExtractionModules = false;
487 
488  if( featureDataReady ){
489 
490  if( classifier->getTimeseriesCompatible() ){
491  if( !featureData.push_back( inputVector ) ){
492  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To add feature Vector to feature data matrix! FeatureExtractionModuleIndex: " << std::endl;
493  return false;
494  }
495  }else classificationData.addSample(classLabel, inputVector);
496  }
497 
498  }else{
499  if( classifier->getTimeseriesCompatible() ){
500  if( !featureData.push_back( inputVector ) ){
501  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To add feature Vector to feature data matrix! FeatureExtractionModuleIndex: " << std::endl;
502  return false;
503  }
504  }
505  else classificationData.addSample(classLabel, inputVector);
506  }
507  }
508 
509  if( classifier->getTimeseriesCompatible() ) timeseriesClassificationData.addSample(classLabel, featureData);
510 
511  }
512 
513  //Train the classification system
514  if( classifier->getTimeseriesCompatible() ){
515  numTrainingSamples = timeseriesClassificationData.getNumSamples();
516  trained = classifier->train( timeseriesClassificationData );
517  }else{
518  numTrainingSamples = classificationData.getNumSamples();
519  trained = classifier->train( classificationData );
520  }
521 
522  if( !trained ){
523  errorLog << "train(TimeSeriesClassificationData trainingData) - Failed To Train Classifier" << classifier->getLastErrorMessage() << std::endl;
524  return false;
525  }
526 
527  //Store the training time
528  trainingTime = timer.getMilliSeconds();
529 
530  return true;
531 }
532 
533 bool GestureRecognitionPipeline::train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling){
534 
535  trained = false;
536  trainingTime = 0;
538 
539  if( !getIsClassifierSet() ){
540  errorLog << "train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed To Train Classifier, the classifier has not been set!" << std::endl;
541  return false;
542  }
543 
544  if( trainingData.getNumSamples() == 0 ){
545  errorLog << "train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed To Train Classifier, there is no training data!" << std::endl;
546  return false;
547  }
548 
549  //Reset all the modules
550  reset();
551 
552  //Start the training timer
553  Timer timer;
554  timer.start();
555 
556  //Get a copy of the data so we can split it
557  TimeSeriesClassificationData data = trainingData;
558 
559  //Spilt the data into K folds
560  if( !data.spiltDataIntoKFolds(kFoldValue, useStratifiedSampling) ){
561  errorLog << "train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed To Spilt Dataset into KFolds!" << std::endl;
562  return false;
563  }
564 
565  //Run the k-fold training and testing
566  Float crossValidationAccuracy = 0;
567  TimeSeriesClassificationData foldTrainingData;
568  TimeSeriesClassificationData foldTestData;
569 
570  for(UINT k=0; k<kFoldValue; k++){
572  foldTrainingData = data.getTrainingFoldData(k);
573 
574  if( !train( foldTrainingData ) ){
575  errorLog << "train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed to train pipeline for fold " << k << "." << std::endl;
576  return false;
577  }
578 
579  //Test the classification system
580  foldTestData = data.getTestFoldData(k);
581 
582  if( !test( foldTestData ) ){
583  errorLog << "train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling) - Failed to test pipeline for fold " << k << "." << std::endl;
584  return false;
585  }
586 
587  crossValidationAccuracy += getTestAccuracy();
588  }
589 
590  //Flag that the model has been trained
591  trained = true;
592 
593  //Set the accuracy of the classification system averaged over the kfolds
594  testAccuracy = crossValidationAccuracy / Float(kFoldValue);
595 
596  //Store the training time
597  trainingTime = timer.getMilliSeconds();
598 
599  return true;
600 }
601 
603 
604  trained = false;
605  trainingTime = 0;
607 
608  if( !getIsClassifierSet() ){
609  errorLog << "train(ClassificationDataStream trainingData) - Failed To train Classifier, the classifier has not been set!" << std::endl;
610  return false;
611  }
612 
613  if( trainingData.getNumSamples() == 0 ){
614  errorLog << "train(ClassificationDataStream trainingData) - Failed To train Classifier, there is no training data!" << std::endl;
615  return false;
616  }
617 
618  //Reset all the modules
619  reset();
620 
621  //Set the input Vector dimension size
622  inputVectorDimensions = trainingData.getNumDimensions();
623 
624  //Pass the training data through any pre-processing or feature extraction units
625  UINT numDimensions = inputVectorDimensions;
626 
627  //If there are any preprocessing or feature extraction modules, then get the size of the last module
630  numDimensions = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
631  }else{
632  numDimensions = preProcessingModules[ preProcessingModules.size()-1 ]->getNumOutputDimensions();
633  }
634  }
635 
636  //Start the training timer
637  Timer timer;
638  timer.start();
639 
640  ClassificationData processedTrainingData( numDimensions );
641  processedTrainingData.reserve( trainingData.getNumSamples() );
642  UINT classLabel = 0;
643  VectorFloat trainingSample;
644  for(UINT i=0; i<trainingData.getNumSamples(); i++){
645  bool okToAddProcessedData = true;
646  classLabel = trainingData[i].getClassLabel();
647  trainingSample = trainingData[i].getSample();
648 
649  //Perform any preprocessing
650  if( getIsPreProcessingSet() ){
651  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
652  if( !preProcessingModules[moduleIndex]->process( trainingSample ) ){
653  errorLog << "train(ClassificationDataStream trainingData) - Failed to PreProcess training Data. PreProcessingModuleIndex: ";
654  errorLog << moduleIndex;
655  errorLog << std::endl;
656  return false;
657  }
658  trainingSample = preProcessingModules[moduleIndex]->getProcessedData();
659  }
660  }
661 
662  //Compute any features
664  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
665  if( !featureExtractionModules[moduleIndex]->computeFeatures( trainingSample ) ){
666  errorLog << "train(ClassificationDataStream trainingData) - Failed to Compute Features from training Data. FeatureExtractionModuleIndex ";
667  errorLog << moduleIndex;
668  errorLog << std::endl;
669  return false;
670  }
671  if( featureExtractionModules[moduleIndex]->getFeatureDataReady() ){
672  trainingSample = featureExtractionModules[moduleIndex]->getFeatureVector();
673  }else{
674  okToAddProcessedData = false;
675  break;
676  }
677  }
678  }
679 
680  if( okToAddProcessedData ){
681  //Add the training sample to the processed training data
682  processedTrainingData.addSample(classLabel, trainingSample);
683  }
684 
685  }
686 
687  if( processedTrainingData.getNumSamples() != trainingData.getNumSamples() ){
688  warningLog << "train(ClassificationDataStream trainingData) - Lost " << trainingData.getNumSamples()-processedTrainingData.getNumSamples() << " of " << trainingData.getNumSamples() << " training samples due to the processing stage!" << std::endl;
689  }
690 
691  //Store the number of training samples
692  numTrainingSamples = processedTrainingData.getNumSamples();
693 
694  //Train the classifier
695  trained = classifier->train_( processedTrainingData );
696  if( !trained ){
697  errorLog << "train(ClassificationDataStream trainingData) - Failed To Train Classifier: " << classifier->getLastErrorMessage() << std::endl;
698  return false;
699  }
700 
701  //Store the training time
702  trainingTime = timer.getMilliSeconds();
703 
704  return true;
705 }
706 
708 
709  trained = false;
710  trainingTime = 0;
712 
713  //Reset all the modules
714  reset();
715 
716  //Start the training timer
717  Timer timer;
718  timer.start();
719 
720  //Set the input Vector dimension size
721  inputVectorDimensions = trainingData.getNumInputDimensions();
722 
723  //Pass the training data through any pre-processing or feature extraction units
724  RegressionData processedTrainingData;
725 
726  //Set the dimensionality of the data
727  UINT numInputs = 0;
728  UINT numTargets = trainingData.getNumTargetDimensions();
730  numInputs = trainingData.getNumInputDimensions();
731  }else{
732 
734  numInputs = preProcessingModules[ preProcessingModules.size()-1 ]->getNumOutputDimensions();
735  }
736 
738  numInputs = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
739  }
740 
742  numInputs = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
743  }
744  }
745 
746  processedTrainingData.setInputAndTargetDimensions(numInputs, numTargets);
747 
748  for(UINT i=0; i<trainingData.getNumSamples(); i++){
749  VectorFloat inputVector = trainingData[i].getInputVector();
750  VectorFloat targetVector = trainingData[i].getTargetVector();
751 
752  if( getIsPreProcessingSet() ){
753  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
754  if( !preProcessingModules[ moduleIndex ]->process( inputVector ) ){
755  errorLog << "train(const RegressionData &trainingData) - Failed To Compute Features For Training Data. PreProcessingModuleIndex: " << moduleIndex << std::endl;
756  return false;
757  }
758 
759  inputVector = preProcessingModules[ moduleIndex ]->getProcessedData();
760  }
761  }
762 
764  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
765  if( !featureExtractionModules[ moduleIndex ]->computeFeatures( inputVector ) ){
766  errorLog << "train(const RegressionData &trainingData) - Failed To Compute Features For Training Data. FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
767  return false;
768  }
769 
770  inputVector = featureExtractionModules[ moduleIndex ]->getFeatureVector();
771  }
772  }
773 
774  //Add the training sample to the processed training data
775  if( !processedTrainingData.addSample(inputVector,targetVector) ){
776  errorLog << "train(const RegressionData &trainingData) - Failed to add processed training sample to training data" << std::endl;
777  return false;
778  }
779  }
780 
781  //Store the number of training samples
782  numTrainingSamples = processedTrainingData.getNumSamples();
783 
784  //Train the classification system
785  if( getIsRegressifierSet() ){
786  trained = regressifier->train( processedTrainingData );
787  if( !trained ){
788  errorLog << "train(const RegressionData &trainingData) - Failed To Train Regressifier: " << regressifier->getLastErrorMessage() << std::endl;
789  return false;
790  }
791  }else{
792  errorLog << "train(const RegressionData &trainingData) - Classifier is not set" << std::endl;
793  return false;
794  }
795 
796  //Store the training time
797  trainingTime = timer.getMilliSeconds();
798 
799  return true;
800 }
801 
802 bool GestureRecognitionPipeline::train(const RegressionData &trainingData,const UINT kFoldValue){
803 
804  trained = false;
805  trainingTime = 0;
807 
808  if( !getIsRegressifierSet() ){
809  errorLog << "train(const RegressionData &trainingData,const UINT kFoldValue) - Failed To Train Regressifier, the regressifier has not been set!" << std::endl;
810  return false;
811  }
812 
813  if( trainingData.getNumSamples() == 0 ){
814  errorLog << "train(const RegressionData &trainingData,const UINT kFoldValue) - Failed To Train Regressifier, there is no training data!" << std::endl;
815  return false;
816  }
817 
818  //Reset all the modules
819  reset();
820 
821  //Start the training timer
822  Timer timer;
823  timer.start();
824 
825  //Get a copy of the training data so we can split it
826  RegressionData data = trainingData;
827 
828  //Spilt the data into K folds
829  bool spiltResult = data.spiltDataIntoKFolds(kFoldValue);
830 
831  if( !spiltResult ){
832  return false;
833  }
834 
835  //Run the k-fold training and testing
836  Float crossValidationAccuracy = 0;
837  RegressionData foldTrainingData;
838  RegressionData foldTestData;
839  for(UINT k=0; k<kFoldValue; k++){
841  foldTrainingData = data.getTrainingFoldData(k);
842 
843  if( !train( foldTrainingData ) ){
844  return false;
845  }
846 
847  //Test the classification system
848  foldTestData = data.getTestFoldData(k);
849 
850  if( !test( foldTestData ) ){
851  return false;
852  }
853 
854  crossValidationAccuracy += getTestRMSError();
855 
856  }
857 
858  //Flag that the model has been trained
859  trained = true;
860 
861  testAccuracy = crossValidationAccuracy / Float(kFoldValue);
862 
863  //Store the training time
864  trainingTime = timer.getMilliSeconds();
865 
866  return true;
867 }
868 
870 
871  trained = false;
872  trainingTime = 0;
874 
875  if( !getIsClustererSet() ){
876  errorLog << "train(const UnlabelledData &trainingData) - Failed To Train Clusterer, the clusterer has not been set!" << std::endl;
877  return false;
878  }
879 
880  if( trainingData.getNumSamples() == 0 ){
881  errorLog << "train(const UnlabelledData &trainingData) - Failed To Train Clusterer, there is no training data!" << std::endl;
882  return false;
883  }
884 
885  //Reset all the modules
886  reset();
887 
888  //Set the input Vector dimension size
889  inputVectorDimensions = trainingData.getNumDimensions();
890 
891  //Pass the training data through any pre-processing or feature extraction units
892  UINT numDimensions = trainingData.getNumDimensions();
893 
894  //If there are any preprocessing or feature extraction modules, then get the size of the last module
897  numDimensions = featureExtractionModules[ featureExtractionModules.size()-1 ]->getNumOutputDimensions();
898  }else{
899  numDimensions = preProcessingModules[ preProcessingModules.size()-1 ]->getNumOutputDimensions();
900  }
901  }
902 
903  //Start the training timer
904  Timer timer;
905  timer.start();
906 
907  UnlabelledData processedTrainingData( numDimensions );
908 
909  for(UINT i=0; i<trainingData.getNumSamples(); i++){
910  bool okToAddProcessedData = true;
911  VectorFloat trainingSample = trainingData[i];
912 
913  //Perform any preprocessing
914  if( getIsPreProcessingSet() ){
915  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
916  if( !preProcessingModules[moduleIndex]->process( trainingSample ) ){
917  errorLog << "train(const UnlabelledData &trainingData) - Failed to PreProcess Training Data. PreProcessingModuleIndex: ";
918  errorLog << moduleIndex;
919  errorLog << std::endl;
920  return false;
921  }
922  trainingSample = preProcessingModules[moduleIndex]->getProcessedData();
923  }
924  }
925 
926  //Compute any features
928  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
929  if( !featureExtractionModules[moduleIndex]->computeFeatures( trainingSample ) ){
930  errorLog << "train(const UnlabelledData &trainingData) - Failed to Compute Features from Training Data. FeatureExtractionModuleIndex ";
931  errorLog << moduleIndex;
932  errorLog << std::endl;
933  return false;
934  }
935  if( featureExtractionModules[moduleIndex]->getFeatureDataReady() ){
936  trainingSample = featureExtractionModules[moduleIndex]->getFeatureVector();
937  }else{
938  okToAddProcessedData = false;
939  break;
940  }
941  }
942  }
943 
944  if( okToAddProcessedData ){
945  //Add the training sample to the processed training data
946  processedTrainingData.addSample(trainingSample);
947  }
948 
949  }
950 
951  if( processedTrainingData.getNumSamples() != trainingData.getNumSamples() ){
952 
953  warningLog << "train(const ClassificationData &trainingData) - Lost " << trainingData.getNumSamples()-processedTrainingData.getNumSamples() << " of " << trainingData.getNumSamples() << " training samples due to the processing stage!" << std::endl;
954  }
955 
956  //Store the number of training samples
957  numTrainingSamples = processedTrainingData.getNumSamples();
958 
959  //Train the cluster model
960  trained = clusterer->train_( processedTrainingData );
961  if( !trained ){
962  errorLog << "train(const UnlabelledData &trainingData) - Failed To Train Clusterer: " << clusterer->getLastErrorMessage() << std::endl;
963  return false;
964  }
965 
966  //Store the training time
967  trainingTime = timer.getMilliSeconds();
968 
969  return true;
970 }
971 
973 
974  //Clear any previous test results
976 
977  //Make sure the classification model has been trained
978  if( !trained ){
979  errorLog << "test(const ClassificationData &testData) - Classifier is not trained" << std::endl;
980  return false;
981  }
982 
983  //Make sure the dimensionality of the test data matches the input Vector's dimensions
984  if( testData.getNumDimensions() != inputVectorDimensions ){
985  errorLog << "test(const ClassificationData &testData) - The dimensionality of the test data (" + Util::toString(testData.getNumDimensions()) + ") does not match that of the input Vector dimensions of the pipeline (" << inputVectorDimensions << ")" << std::endl;
986  return false;
987  }
988 
989  if( !getIsClassifierSet() ){
990  errorLog << "test(const ClassificationData &testData) - The classifier has not been set" << std::endl;
991  return false;
992  }
993 
994  //Reset all the modules
995  reset();
996 
997  //Validate that the class labels in the test data match the class labels in the model
998  bool classLabelValidationPassed = true;
999  for(UINT i=0; i<testData.getNumClasses(); i++){
1000  bool labelFound = false;
1001  for(UINT k=0; k<classifier->getNumClasses(); k++){
1002  if( testData.getClassTracker()[i].classLabel == classifier->getClassLabels()[k] ){
1003  labelFound = true;
1004  break;
1005  }
1006  }
1007 
1008  if( !labelFound ){
1009  classLabelValidationPassed = false;
1010  errorLog << "test(const ClassificationData &testData) - The test dataset contains a class label (" << testData.getClassTracker()[i].classLabel << ") that is not in the model!" << std::endl;
1011  }
1012  }
1013 
1014  if( !classLabelValidationPassed ){
1015  errorLog << "test(const ClassificationData &testData) - Model Class Labels: ";
1016  for(UINT k=0; k<classifier->getNumClasses(); k++){
1017  errorLog << classifier->getClassLabels()[k] << "\t";
1018  }
1019  errorLog << std::endl;
1020  return false;
1021  }
1022 
1023  Float rejectionPrecisionCounter = 0;
1024  Float rejectionRecallCounter = 0;
1025  unsigned int confusionMatrixSize = classifier->getNullRejectionEnabled() ? classifier->getNumClasses()+1 : classifier->getNumClasses();
1026  VectorFloat precisionCounter(classifier->getNumClasses(), 0);
1027  VectorFloat recallCounter(classifier->getNumClasses(), 0);
1028  VectorFloat confusionMatrixCounter(confusionMatrixSize,0);
1029 
1030  //Resize the test matrix
1031  testConfusionMatrix.resize(confusionMatrixSize, confusionMatrixSize);
1032  testConfusionMatrix.setAllValues(0);
1033 
1034  //Resize the precision and recall Vectors
1035  testPrecision.clear();
1036  testRecall.clear();
1037  testFMeasure.clear();
1038  testPrecision.resize(getNumClassesInModel(), 0);
1039  testRecall.resize(getNumClassesInModel(), 0);
1040  testFMeasure.resize(getNumClassesInModel(), 0);
1041  testResults.resize(testData.getNumSamples());
1042  numTestSamples = testData.getNumSamples();
1043 
1044  //Start the test timer
1045  Timer timer;
1046  timer.start();
1047 
1048  //Run the test
1049  for(UINT i=0; i<numTestSamples; i++){
1050  UINT classLabel = testData[i].getClassLabel();
1051  VectorFloat testSample = testData[i].getSample();
1052 
1053  //Pass the test sample through the pipeline
1054  if( !predict( testSample ) ){
1055  errorLog << "test(const ClassificationData &testData) - Prediction failed for test sample at index: " << i << std::endl;
1056  return false;
1057  }
1058 
1059  //Update the test metrics
1060  UINT predictedClassLabel = getPredictedClassLabel();
1061 
1062  if( !updateTestMetrics(classLabel,predictedClassLabel,precisionCounter,recallCounter,rejectionPrecisionCounter,rejectionRecallCounter, confusionMatrixCounter) ){
1063  errorLog << "test(const ClassificationData &testData) - Failed to update test metrics at test sample index: " << i << std::endl;
1064  return false;
1065  }
1066  //cout << "i: " << i << " class label: " << classLabel << " predictedClassLabel: " << predictedClassLabel << std::endl;
1067 
1068  //Keep track of the classification results encase the user needs them later
1069  testResults[i].setClassificationResult(i, classLabel, predictedClassLabel, getUnProcessedPredictedClassLabel(),getClassLikelihoods(), getClassDistances());
1070 
1071  //Update any observers
1072  classifier->notifyTestResultsObservers( testResults[i] );
1073  }
1074 
1075  if( !computeTestMetrics(precisionCounter,recallCounter,rejectionPrecisionCounter,rejectionRecallCounter, confusionMatrixCounter, numTestSamples) ){
1076  errorLog <<"test(const ClassificationData &testData) - Failed to compute test metrics!" << std::endl;
1077  return false;
1078  }
1079 
1080  testTime = timer.getMilliSeconds();
1081 
1082  return true;
1083 }
1084 
1086 
1087  //Clear any previous test results
1088  clearTestResults();
1089 
1090  //Make sure the classification model has been trained
1091  if( !trained ){
1092  errorLog << "test(const TimeSeriesClassificationData &testData) - The classifier has not been trained" << std::endl;
1093  return false;
1094  }
1095 
1096  //Make sure the dimensionality of the test data matches the input Vector's dimensions
1097  if( testData.getNumDimensions() != inputVectorDimensions ){
1098  errorLog << "test(const TimeSeriesClassificationData &testData) - The dimensionality of the test data (" << testData.getNumDimensions() << ") does not match that of the input Vector dimensions of the pipeline (" << inputVectorDimensions << ")" << std::endl;
1099  return false;
1100  }
1101 
1102  if( !getIsClassifierSet() ){
1103  errorLog << "test(const TimeSeriesClassificationData &testData) - The classifier has not been set" << std::endl;
1104  return false;
1105  }
1106 
1107  //Reset all the modules
1108  reset();
1109 
1110  Float rejectionPrecisionCounter = 0;
1111  Float rejectionRecallCounter = 0;
1112  const UINT K = classifier->getNumClasses();
1113  UINT confusionMatrixSize = classifier->getNullRejectionEnabled() ? K+1 : K;
1114  VectorFloat precisionCounter(K, 0);
1115  VectorFloat recallCounter(K, 0);
1116  VectorFloat confusionMatrixCounter(confusionMatrixSize,0);
1117 
1118  //Resize the test matrix
1119  testConfusionMatrix.resize(confusionMatrixSize,confusionMatrixSize);
1120  testConfusionMatrix.setAllValues(0);
1121 
1122  //Resize the precision and recall Vectors
1123  testPrecision.resize(K, 0);
1124  testRecall.resize(K, 0);
1125  testFMeasure.resize(K, 0);
1126  numTestSamples = testData.getNumSamples();
1127 
1128  //Start the test timer
1129  Timer timer;
1130  timer.start();
1131 
1132  //Run the test
1133  const UINT M = testData.getNumSamples();
1134  for(UINT i=0; i<M; i++){
1135  UINT classLabel = testData[i].getClassLabel();
1136  MatrixFloat timeseries = testData[i].getData();
1137 
1138  //Pass the test timeseries through the pipeline
1139  if( !predict( timeseries ) ){
1140  errorLog << "test(const TimeSeriesClassificationData &testData) - Failed to run prediction for test sample index: " << i << std::endl;
1141  return false;
1142  }
1143 
1144  //Update the test metrics
1145  UINT predictedClassLabel = getPredictedClassLabel();
1146 
1147  if( !updateTestMetrics(classLabel,predictedClassLabel,precisionCounter,recallCounter,rejectionPrecisionCounter,rejectionRecallCounter, confusionMatrixCounter) ){
1148  errorLog << "test(const TimeSeriesClassificationData &testData) - Failed to update test metrics at test sample index: " << i << std::endl;
1149  return false;
1150  }
1151 
1152  }
1153 
1154  if( !computeTestMetrics(precisionCounter,recallCounter,rejectionPrecisionCounter,rejectionRecallCounter, confusionMatrixCounter, M) ){
1155  errorLog << "test(const TimeSeriesClassificationData &testData) - Failed to compute test metrics!" << std::endl;
1156  return false;
1157  }
1158 
1159  testTime = timer.getMilliSeconds();
1160 
1161  return true;
1162 }
1163 
1165 
1166  //Clear any previous test results
1167  clearTestResults();
1168 
1169  //Make sure the classification model has been trained
1170  if( !trained ){
1171  errorLog << "test(const ClassificationDataStream &testData) - The classifier has not been trained" << std::endl;
1172  return false;
1173  }
1174 
1175  //Make sure the dimensionality of the test data matches the input Vector's dimensions
1176  if( testData.getNumDimensions() != inputVectorDimensions ){
1177  errorLog << "test(const ClassificationDataStream &testData) - The dimensionality of the test data (" + Util::toString(testData.getNumDimensions()) + ") does not match that of the input Vector dimensions of the pipeline (" << inputVectorDimensions << ")" << std::endl;
1178  return false;
1179  }
1180 
1181  if( !getIsClassifierSet() ){
1182  errorLog << "test(const ClassificationDataStream &testData) - The classifier has not been set" << std::endl;
1183  return false;
1184  }
1185 
1186  //Reset all the modules
1187  reset();
1188 
1189  //Float rejectionPrecisionCounter = 0;
1190  //Float rejectionRecallCounter = 0;
1191  UINT confusionMatrixSize = classifier->getNullRejectionEnabled() ? classifier->getNumClasses()+1 : classifier->getNumClasses();
1192  VectorFloat precisionCounter(getNumClassesInModel(), 0);
1193  VectorFloat recallCounter(getNumClassesInModel(), 0);
1194  VectorFloat confusionMatrixCounter(confusionMatrixSize,0);
1195 
1196  //Resize the test matrix
1197  testConfusionMatrix.resize(confusionMatrixSize,confusionMatrixSize);
1198  testConfusionMatrix.setAllValues(0);
1199 
1200  //Resize the precision and recall Vectors
1201  testPrecision.resize(getNumClassesInModel(), 0);
1202  testRecall.resize(getNumClassesInModel(), 0);
1203  testFMeasure.resize(getNumClassesInModel(), 0);
1204 
1205  //Resize the classification results Vector
1206  testResults.resize(testData.getNumSamples());
1207  numTestSamples = testData.getNumSamples();
1208 
1209  //Start the test timer
1210  Timer timer;
1211  timer.start();
1212 
1213  //Get a copy of the data so we can modify it
1214  ClassificationDataStream data = testData;
1215 
1216  //Run the test
1217  data.resetPlaybackIndex(0); //Make sure that the test data start at 0
1218  for(UINT i=0; i<data.getNumSamples(); i++){
1219  ClassificationSample sample = data.getNextSample();
1220  UINT classLabel = sample.getClassLabel();
1221  VectorFloat testSample = sample.getSample();
1222 
1223  //Pass the test sample through the pipeline
1224  if( !predict( testSample ) ){
1225  errorLog << "test(const ClassificationDataStream &testData) - Prediction Failed! " << classifier->getLastErrorMessage() << std::endl;
1226  return false;
1227  }
1228 
1229  //Update the test metrics
1230  UINT predictedClassLabel = getPredictedClassLabel();
1231 
1232  /* //TODO - Need to update this!
1233  if( !updateTestMetrics(classLabel,predictedClassLabel,precisionCounter,recallCounter,rejectionPrecisionCounter,rejectionRecallCounter, confusionMatrixCounter) ){
1234  errorLog << "test(LabelledContinuousTimeSeriesClassificationData &testData) - Failed to update test metrics at test sample index: " << i << std::endl;
1235  return false;
1236  }
1237  */
1238 
1239  if( classLabel == predictedClassLabel ) testAccuracy++;
1240 
1241  //Store the test results so they can be used later
1242  testResults[i].setClassificationResult(i, classLabel, predictedClassLabel, getUnProcessedPredictedClassLabel(), getClassLikelihoods(), getClassDistances());
1243 
1244  //Notify all observers of the test result
1245  classifier->notifyTestResultsObservers( testResults[i] );
1246 
1247  testingLog << "test iteration: " << i;
1248  testingLog << "\tClassLabel: " << classLabel;
1249  testingLog << "\tPredictedClassLabel: " << predictedClassLabel;
1250  testingLog << "\tLikelihood: " << getMaximumLikelihood() << std::endl;
1251  }
1252 
1253  /* //TODO - Need to update this!
1254  if( !computeTestMetrics(precisionCounter,recallCounter,rejectionPrecisionCounter,rejectionRecallCounter, confusionMatrixCounter, testData.getNumSamples()) ){
1255  errorLog << "test(LabelledContinuousTimeSeriesClassificationData &testData) - Failed to compute test metrics !" << std::endl;
1256  return false;
1257  }
1258  */
1259 
1260  testTime = timer.getMilliSeconds();
1261  testAccuracy = testAccuracy / Float( testData.getNumSamples() ) * 100.0;
1262 
1263  testingLog << "Test complete. Total testing time: " << testTime << std::endl;
1264 
1265  return true;
1266 }
1267 
1269 
1270  //Clear any previous test results
1271  clearTestResults();
1272 
1273  //Make sure the classification model has been trained
1274  if( !trained ){
1275  errorLog << "test(const RegressionData &testData) - Regressifier is not trained" << std::endl;
1276  return false;
1277  }
1278 
1279  //Make sure the dimensionality of the test data matches the input Vector's dimensions
1280  if( testData.getNumInputDimensions() != inputVectorDimensions ){
1281  errorLog << "test(const RegressionData &testData) - The dimensionality of the test data (" << testData.getNumInputDimensions() << ") does not match that of the input Vector dimensions of the pipeline (" << inputVectorDimensions << ")" << std::endl;
1282  return false;
1283  }
1284 
1285  if( !getIsRegressifierSet() ){
1286  errorLog << "test(const RegressionData &testData) - The regressifier has not been set" << std::endl;
1287  return false;
1288  }
1289 
1290  if( regressifier->getNumOutputDimensions() != testData.getNumTargetDimensions() ){
1291  errorLog << "test(const RegressionData &testData) - The size of the output of the regressifier (" << regressifier->getNumOutputDimensions() << ") does not match that of the size of the number of target dimensions (" << testData.getNumTargetDimensions() << ")" << std::endl;
1292  return false;
1293  }
1294 
1295  //Reset all the modules
1296  reset();
1297 
1298  numTestSamples = testData.getNumSamples();
1299  testResults.resize( numTestSamples );
1300 
1301  //Start the test timer
1302  Timer timer;
1303  timer.start();
1304 
1305  //Run the test
1306  testSquaredError = 0;
1307  testRMSError = 0;
1308  for(UINT i=0; i<numTestSamples; i++){
1309  VectorFloat inputVector = testData[i].getInputVector();
1310  VectorFloat targetVector = testData[i].getTargetVector();
1311 
1312  //Pass the test sample through the pipeline
1313  if( !map( inputVector ) ){
1314  errorLog << "test(const RegressionData &testData) - Failed to map input Vector!" << std::endl;
1315  return false;
1316  }
1317 
1318  //Update the RMS error
1319  Float sum = 0;
1320  VectorFloat regressionData = regressifier->getRegressionData();
1321  for(UINT j=0; j<targetVector.size(); j++){
1322  sum += grt_sqr( regressionData[j]-targetVector[j] );
1323  }
1324 
1325  testSquaredError += sum;
1326 
1327  //Keep track of the regression results encase the user needs them later
1328  testResults[i].setRegressionResult(i,regressionData,targetVector);
1329 
1330  //Update any observers
1331  regressifier->notifyTestResultsObservers( testResults[i] );
1332  }
1333 
1334  //Compute the test metrics
1335  testRMSError = sqrt( testSquaredError / Float( testData.getNumSamples() ) );
1336 
1337  testTime = timer.getMilliSeconds();
1338 
1339  return true;
1340 }
1341 
1343 
1344  //Make sure the classification model has been trained
1345  if( !trained ){
1346  errorLog << "predict(const VectorFloat &inputVector) - The classifier has not been trained" << std::endl;
1347  return false;
1348  }
1349 
1350  //Make sure the dimensionality of the input Vector matches the inputVectorDimensions
1351  if( inputVector.size() != inputVectorDimensions ){
1352  errorLog << "predict(const VectorFloat &inputVector) - The dimensionality of the input Vector (" << int(inputVector.size()) << ") does not match that of the input Vector dimensions of the pipeline (" << inputVectorDimensions << ")" << std::endl;
1353  return false;
1354  }
1355 
1356  if( getIsClassifierSet() ){
1357  return predict_classifier( inputVector );
1358  }
1359 
1360  if( getIsRegressifierSet() ){
1361  return predict_regressifier( inputVector );
1362  }
1363 
1364  if( getIsClustererSet() ){
1365  return predict_clusterer( inputVector );
1366  }
1367 
1368  errorLog << "predict(const VectorFloat &inputVector) - Neither a classifier, regressifer or clusterer is set" << std::endl;
1369  return false;
1370 }
1371 
1373 
1374  //Make sure the classification model has been trained
1375  if( !trained ){
1376  errorLog << "predict(const MatrixFloat &inputMatrix) - The classifier has not been trained!" << std::endl;
1377  return false;
1378  }
1379 
1380  //Make sure the dimensionality of the input matrix matches the inputVectorDimensions
1381  if( input.getNumCols() != inputVectorDimensions ){
1382  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - The dimensionality of the input matrix (" << input.getNumCols() << ") does not match that of the input Vector dimensions of the pipeline (" << inputVectorDimensions << ")" << std::endl;
1383  return false;
1384  }
1385 
1386  if( !getIsClassifierSet() ){
1387  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - A classifier has not been set" << std::endl;
1388  return false;
1389  }
1390 
1391  //Get a copy of the input matrix so it can be processed
1392  MatrixFloat inputMatrix = input;
1393 
1394  //Get a pointer to the input matrix so we can pass it down the pipeline
1395  const void *data = static_cast< const void* >( &inputMatrix );
1396  DataType dataType = DATA_TYPE_MATRIX;
1397 
1398  //Setup a temporary matrix and vector
1399  //VectorFloat tmpVector;
1400  //MatrixFloat tmpMatrix;
1401 
1402  //Update the context module
1403  predictionModuleIndex = START_OF_PIPELINE;
1404 
1405  //Perform any pre-processing
1406  /*
1407  if( getIsPreProcessingSet() ){
1408 
1409  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
1410  MatrixFloat tmpMatrix( inputMatrix.getNumRows(), preProcessingModules[moduleIndex]->getNumOutputDimensions() );
1411 
1412  for(UINT i=0; i<inputMatrix.getNumRows(); i++){
1413  if( !preProcessingModules[moduleIndex]->process( inputMatrix.getRow(i) ) ){
1414  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - Failed to PreProcess Input Matrix. PreProcessingModuleIndex: " << moduleIndex << std::endl;
1415  return false;
1416  }
1417  tmpMatrix.setRowVector( preProcessingModules[moduleIndex]->getProcessedData(), i );
1418  }
1419 
1420  //Update the input matrix with the preprocessed data
1421  inputMatrix = tmpMatrix;
1422  }
1423  }
1424  */
1425 
1426  //Update the context module
1427  predictionModuleIndex = AFTER_PREPROCESSING;
1428  //Perform any feature extraction
1429  if( getIsFeatureExtractionSet() ){
1430 
1431  const void *feInput = data;
1432  const void *feOutput = NULL;
1433  const UINT numFeatureExtractionModules = featureExtractionModules.getSize();
1434  DataType inputType = DATA_TYPE_UNKNOWN;
1435  DataType outputType = DATA_TYPE_UNKNOWN;
1436  for(UINT moduleIndex=0; moduleIndex<numFeatureExtractionModules; moduleIndex++){
1437 
1438  inputType = featureExtractionModules[ moduleIndex ]->getInputType();
1439  outputType = featureExtractionModules[ moduleIndex ]->getOutputType();
1440 
1441  //Run the feature extraction algorithm
1442  switch( inputType ){
1443  case DATA_TYPE_VECTOR:
1444  if( !featureExtractionModules[ moduleIndex ]->computeFeatures( *static_cast< const VectorFloat* >( feInput ) ) ){
1445  errorLog << "predict(const MatrixFloat &inputMatrix) - Failed to PreProcess Input Matrix. FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1446  return false;
1447  }
1448  break;
1449  case DATA_TYPE_MATRIX:
1450  if( !featureExtractionModules[ moduleIndex ]->computeFeatures( *static_cast< const MatrixFloat* >( feInput ) ) ){
1451  errorLog << "predict(const MatrixFloat &inputMatrix) - Failed to PreProcess Input Matrix. FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1452  return false;
1453  }
1454  break;
1455  default:
1456  errorLog << "predict(const MatrixFloat &inputMatrix) - Failed to process data. Unknown output data type for FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1457  return false;
1458  break;
1459  }
1460 
1461  //Get the results and store them in the feOutput pointer
1462  switch( outputType ){
1463  case DATA_TYPE_VECTOR:
1464  feOutput = static_cast< const void* >( &featureExtractionModules[ moduleIndex ]->getFeatureVector() );
1465  break;
1466  case DATA_TYPE_MATRIX:
1467  feOutput = static_cast< const void* >( &featureExtractionModules[ moduleIndex ]->getFeatureMatrix() );
1468  break;
1469  default:
1470  errorLog << "predict(const MatrixFloat &inputMatrix) - Failed to process data. Unknown output data type for FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1471  return false;
1472  break;
1473  }
1474 
1475  //If there are more feature extraction modules to process, then set the feInput
1476  if( moduleIndex+1 < numFeatureExtractionModules ){
1477  feInput = feOutput;
1478  }
1479  }
1480 
1481  //Update the data pointer to the data from the last output from the end feature extraction module
1482  data = feOutput;
1483  dataType = outputType;
1484  }
1485 
1486  //Update the context module
1487  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1488 
1489  //Perform the classification
1490  switch( dataType ){
1491  case DATA_TYPE_VECTOR:
1492  if( !classifier->predict_( *(VectorFloat*)data ) ){
1493  errorLog <<"predict_timeseries(const MatrixFloat &inputMatrix) - Prediction Failed! " << classifier->getLastErrorMessage() << std::endl;
1494  return false;
1495  }
1496  break;
1497  case DATA_TYPE_MATRIX:
1498  if( !classifier->predict_( *(MatrixFloat*)data ) ){
1499  errorLog <<"predict_timeseries(const MatrixFloat &inputMatrix) - Prediction Failed! " << classifier->getLastErrorMessage() << std::endl;
1500  return false;
1501  }
1502  break;
1503  default:
1504  errorLog << "predict(const MatrixFloat &inputMatrix) - Failed to run prediction. Unknown data type!" << std::endl;
1505  return false;
1506  break;
1507  }
1508 
1509  predictedClassLabel = classifier->getPredictedClassLabel();
1510 
1511  //Update the context module
1512  //Todo
1513 
1514  //Perform any post processing
1515  predictionModuleIndex = AFTER_CLASSIFIER;
1516 /*
1517  if( getIsPostProcessingSet() ){
1518 
1519  if( pipelineMode != CLASSIFICATION_MODE){
1520  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - Pipeline Mode Is Not in CLASSIFICATION_MODE!" << std::endl;
1521  return false;
1522  }
1523 
1524  VectorFloat data;
1525  for(UINT moduleIndex=0; moduleIndex<postProcessingModules.size(); moduleIndex++){
1526 
1527  //Select which input we should give the postprocessing module
1528  if( postProcessingModules[moduleIndex]->getIsPostProcessingInputModePredictedClassLabel() ){
1529  //Set the input
1530  data.resize(1);
1531  data[0] = predictedClassLabel;
1532 
1533  //Verify that the input size is OK
1534  if( data.size() != postProcessingModules[moduleIndex]->getNumInputDimensions() ){
1535  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - The size of the data Vector (" << int(data.size()) << ") does not match that of the postProcessingModule (" << postProcessingModules[moduleIndex]->getNumInputDimensions() << ") at the moduleIndex: " << moduleIndex << std::endl;
1536  return false;
1537  }
1538 
1539  //Postprocess the data
1540  if( !postProcessingModules[moduleIndex]->process( data ) ){
1541  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - Failed to post process data. PostProcessing moduleIndex: " << moduleIndex << std::endl;
1542  return false;
1543  }
1544 
1545  //Select which output we should update
1546  data = postProcessingModules[moduleIndex]->getProcessedData();
1547  }
1548 
1549  //Select which output we should update
1550  if( postProcessingModules[moduleIndex]->getIsPostProcessingOutputModePredictedClassLabel() ){
1551  //Get the processed predicted class label
1552  data = postProcessingModules[moduleIndex]->getProcessedData();
1553 
1554  //Verify that the output size is OK
1555  if( data.size() != 1 ){
1556  errorLog << "predict_timeseries(const MatrixFloat &inputMatrix) - The size of the processed data Vector (" << int(data.size()) << ") from postProcessingModule at the moduleIndex: " << moduleIndex << " is not equal to 1 even though it is in OutputModePredictedClassLabel!" << std::endl;
1557  return false;
1558  }
1559 
1560  //Update the predicted class label
1561  predictedClassLabel = (UINT)data[0];
1562  }
1563 
1564  }
1565  }
1566 */
1567  //Update the context module
1568  //TODO
1569  predictionModuleIndex = END_OF_PIPELINE;
1570  return true;
1571 }
1572 
1574  return predict_regressifier( inputVector );
1575 }
1576 
1577 bool GestureRecognitionPipeline::predict_classifier(const VectorFloat &input){
1578 
1579  predictedClassLabel = 0;
1580  VectorFloat inputVector = input;
1581 
1582  //Update the context module
1583  predictionModuleIndex = START_OF_PIPELINE;
1584  if( contextModules[ START_OF_PIPELINE ].size() > 0 ){
1585  for(UINT moduleIndex=0; moduleIndex<contextModules[ START_OF_PIPELINE ].size(); moduleIndex++){
1586  if( !contextModules[ START_OF_PIPELINE ][moduleIndex]->process( inputVector ) ){
1587  errorLog << "predict_classifier(const VectorFloat &inputVector) - Context Module Failed at START_OF_PIPELINE. ModuleIndex: " << moduleIndex << std::endl;
1588  return false;
1589  }
1590  if( !contextModules[ START_OF_PIPELINE ][moduleIndex]->getOK() ){
1591  return true;
1592  }
1593  inputVector = contextModules[ START_OF_PIPELINE ][moduleIndex]->getProcessedData();
1594  }
1595  }
1596 
1597  //Perform any pre-processing
1598  if( getIsPreProcessingSet() ){
1599  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
1600  if( !preProcessingModules[moduleIndex]->process( inputVector ) ){
1601  errorLog << "predict_classifier(const VectorFloat &inputVector) - Failed to PreProcess Input Vector. PreProcessingModuleIndex: " << moduleIndex << std::endl;
1602  return false;
1603  }
1604  inputVector = preProcessingModules[moduleIndex]->getProcessedData();
1605  }
1606  }
1607 
1608  //Update the context module
1609  predictionModuleIndex = AFTER_PREPROCESSING;
1610  if( contextModules[ AFTER_PREPROCESSING ].size() ){
1611  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_PREPROCESSING ].size(); moduleIndex++){
1612  if( !contextModules[ AFTER_PREPROCESSING ][moduleIndex]->process( inputVector ) ){
1613  errorLog << "predict_classifier(VectorFloat inputVector) - Context Module Failed at AFTER_PREPROCESSING. ModuleIndex: " << moduleIndex << std::endl;
1614  return false;
1615  }
1616  if( !contextModules[ AFTER_PREPROCESSING ][moduleIndex]->getOK() ){
1617  predictionModuleIndex = AFTER_PREPROCESSING;
1618  return false;
1619  }
1620  inputVector = contextModules[ AFTER_PREPROCESSING ][moduleIndex]->getProcessedData();
1621  }
1622  }
1623 
1624  //Perform any feature extraction
1625  if( getIsFeatureExtractionSet() ){
1626  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
1627  if( !featureExtractionModules[moduleIndex]->computeFeatures( inputVector ) ){
1628  errorLog << "predict_classifier(VectorFloat inputVector) - Failed to compute features from data. FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1629  return false;
1630  }
1631  inputVector = featureExtractionModules[moduleIndex]->getFeatureVector();
1632  }
1633  }
1634 
1635  //Update the context module
1636  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1637  if( contextModules[ AFTER_FEATURE_EXTRACTION ].size() ){
1638  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_FEATURE_EXTRACTION ].size(); moduleIndex++){
1639  if( !contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->process( inputVector ) ){
1640  errorLog << "predict_classifier(VectorFloat inputVector) - Context Module Failed at AFTER_FEATURE_EXTRACTION. ModuleIndex: " << moduleIndex << std::endl;
1641  return false;
1642  }
1643  if( !contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->getOK() ){
1644  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1645  return false;
1646  }
1647  inputVector = contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->getProcessedData();
1648  }
1649  }
1650 
1651  //Perform the classification
1652  if( !classifier->predict(inputVector) ){
1653  errorLog << "predict_classifier(VectorFloat inputVector) - Prediction Failed! " << classifier->getLastErrorMessage() << std::endl;
1654  return false;
1655  }
1656  predictedClassLabel = classifier->getPredictedClassLabel();
1657 
1658  //Update the context module
1659  if( contextModules[ AFTER_CLASSIFIER ].size() ){
1660  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_CLASSIFIER ].size(); moduleIndex++){
1661  if( !contextModules[ AFTER_CLASSIFIER ][moduleIndex]->process( VectorFloat(1,predictedClassLabel) ) ){
1662  errorLog << "predict_classifier(VectorFloat inputVector) - Context Module Failed at AFTER_CLASSIFIER. ModuleIndex: " << moduleIndex << std::endl;
1663  return false;
1664  }
1665  if( !contextModules[ AFTER_CLASSIFIER ][moduleIndex]->getOK() ){
1666  predictionModuleIndex = AFTER_CLASSIFIER;
1667  return false;
1668  }
1669  predictedClassLabel = (UINT)contextModules[ AFTER_CLASSIFIER ][moduleIndex]->getProcessedData()[0];
1670  }
1671  }
1672 
1673  //Perform any post processing
1674  predictionModuleIndex = AFTER_CLASSIFIER;
1675  if( getIsPostProcessingSet() ){
1676 
1677  if( pipelineMode != CLASSIFICATION_MODE){
1678  errorLog << "predict_classifier(VectorFloat inputVector) - Pipeline Mode Is Not in CLASSIFICATION_MODE!" << std::endl;
1679  return false;
1680  }
1681 
1682  VectorFloat data;
1683  for(UINT moduleIndex=0; moduleIndex<postProcessingModules.size(); moduleIndex++){
1684 
1685  //Select which input we should give the postprocessing module
1686  if( postProcessingModules[moduleIndex]->getIsPostProcessingInputModePredictedClassLabel() ){
1687  //Set the input
1688  data.resize(1);
1689  data[0] = predictedClassLabel;
1690 
1691  //Verify that the input size is OK
1692  if( data.size() != postProcessingModules[moduleIndex]->getNumInputDimensions() ){
1693  errorLog << "predict_classifier(VectorFloat inputVector) - The size of the data Vector (" << int(data.size()) << ") does not match that of the postProcessingModule (" << postProcessingModules[moduleIndex]->getNumInputDimensions() << ") at the moduleIndex: " << moduleIndex << std::endl;
1694  return false;
1695  }
1696 
1697  //Postprocess the data
1698  if( !postProcessingModules[moduleIndex]->process( data ) ){
1699  errorLog << "predict_classifier(VectorFloat inputVector) - Failed to post process data. PostProcessing moduleIndex: " << moduleIndex << std::endl;
1700  return false;
1701  }
1702 
1703  //Select which output we should update
1704  data = postProcessingModules[moduleIndex]->getProcessedData();
1705  }
1706 
1707  //Select which output we should update
1708  if( postProcessingModules[moduleIndex]->getIsPostProcessingOutputModePredictedClassLabel() ){
1709  //Get the processed predicted class label
1710  data = postProcessingModules[moduleIndex]->getProcessedData();
1711 
1712  //Verify that the output size is OK
1713  if( data.size() != 1 ){
1714  errorLog << "predict_classifier(VectorFloat inputVector) - The size of the processed data Vector (" << int(data.size()) << ") from postProcessingModule at the moduleIndex: " << moduleIndex << " is not equal to 1 even though it is in OutputModePredictedClassLabel!" << std::endl;
1715  return false;
1716  }
1717 
1718  //Update the predicted class label
1719  predictedClassLabel = (UINT)data[0];
1720  }
1721 
1722  }
1723  }
1724 
1725  //Update the context module
1726  predictionModuleIndex = END_OF_PIPELINE;
1727  if( contextModules[ END_OF_PIPELINE ].size() ){
1728  for(UINT moduleIndex=0; moduleIndex<contextModules[ END_OF_PIPELINE ].size(); moduleIndex++){
1729  if( !contextModules[ END_OF_PIPELINE ][moduleIndex]->process( VectorFloat(1,predictedClassLabel) ) ){
1730  errorLog << "predict_classifier(VectorFloat inputVector) - Context Module Failed at END_OF_PIPELINE. ModuleIndex: " << moduleIndex << std::endl;
1731  return false;
1732  }
1733  if( !contextModules[ END_OF_PIPELINE ][moduleIndex]->getOK() ){
1734  predictionModuleIndex = END_OF_PIPELINE;
1735  return false;
1736  }
1737  predictedClassLabel = (UINT)contextModules[ END_OF_PIPELINE ][moduleIndex]->getProcessedData()[0];
1738  }
1739  }
1740 
1741  return true;
1742 }
1743 
1744 bool GestureRecognitionPipeline::predict_regressifier(const VectorFloat &input){
1745 
1746  VectorFloat inputVector = input;
1747 
1748  //Update the context module
1749  predictionModuleIndex = START_OF_PIPELINE;
1750  if( contextModules[ START_OF_PIPELINE ].size() ){
1751  for(UINT moduleIndex=0; moduleIndex<contextModules[ START_OF_PIPELINE ].size(); moduleIndex++){
1752  if( !contextModules[ START_OF_PIPELINE ][moduleIndex]->process( inputVector ) ){
1753  errorLog << "predict_regressifier(VectorFloat inputVector) - Context Module Failed at START_OF_PIPELINE. ModuleIndex: " << moduleIndex << std::endl;
1754  return false;
1755  }
1756  if( !contextModules[ START_OF_PIPELINE ][moduleIndex]->getOK() ){
1757  return true;
1758  }
1759  inputVector = contextModules[ START_OF_PIPELINE ][moduleIndex]->getProcessedData();
1760  }
1761  }
1762 
1763  //Perform any pre-processing
1764  if( getIsPreProcessingSet() ){
1765  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
1766  if( !preProcessingModules[moduleIndex]->process( inputVector ) ){
1767  errorLog << "predict_regressifier(VectorFloat inputVector) - Failed to PreProcess Input Vector. PreProcessingModuleIndex: " << moduleIndex << std::endl;
1768  return false;
1769  }
1770  inputVector = preProcessingModules[moduleIndex]->getProcessedData();
1771  }
1772  }
1773 
1774  //Update the context module
1775  predictionModuleIndex = AFTER_PREPROCESSING;
1776  if( contextModules[ AFTER_PREPROCESSING ].size() ){
1777  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_PREPROCESSING ].size(); moduleIndex++){
1778  if( !contextModules[ AFTER_PREPROCESSING ][moduleIndex]->process( inputVector ) ){
1779  errorLog << "predict_regressifier(VectorFloat inputVector) - Context Module Failed at AFTER_PREPROCESSING. ModuleIndex: " << moduleIndex << std::endl;
1780  return false;
1781  }
1782  if( !contextModules[ AFTER_PREPROCESSING ][moduleIndex]->getOK() ){
1783  predictionModuleIndex = AFTER_PREPROCESSING;
1784  return false;
1785  }
1786  inputVector = contextModules[ AFTER_PREPROCESSING ][moduleIndex]->getProcessedData();
1787  }
1788  }
1789 
1790  //Perform any feature extraction
1791  if( getIsFeatureExtractionSet() ){
1792  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
1793  if( !featureExtractionModules[moduleIndex]->computeFeatures( inputVector ) ){
1794  errorLog << "predict_regressifier(VectorFloat inputVector) - Failed to compute features from data. FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1795  return false;
1796  }
1797  inputVector = featureExtractionModules[moduleIndex]->getFeatureVector();
1798  }
1799  }
1800 
1801  //Update the context module
1802  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1803  if( contextModules[ AFTER_FEATURE_EXTRACTION ].size() ){
1804  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_FEATURE_EXTRACTION ].size(); moduleIndex++){
1805  if( !contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->process( inputVector ) ){
1806  errorLog << "predict_regressifier(VectorFloat inputVector) - Context Module Failed at AFTER_FEATURE_EXTRACTION. ModuleIndex: " << moduleIndex << std::endl;
1807  return false;
1808  }
1809  if( !contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->getOK() ){
1810  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1811  return false;
1812  }
1813  inputVector = contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->getProcessedData();
1814  }
1815  }
1816 
1817  //Perform the regression
1818  if( !regressifier->predict(inputVector) ){
1819  errorLog << "predict_regressifier(VectorFloat inputVector) - Prediction Failed! " << regressifier->getLastErrorMessage() << std::endl;
1820  return false;
1821  }
1822  regressionData = regressifier->getRegressionData();
1823 
1824  //Update the context module
1825  if( contextModules[ AFTER_CLASSIFIER ].size() ){
1826  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_CLASSIFIER ].size(); moduleIndex++){
1827  if( !contextModules[ AFTER_CLASSIFIER ][moduleIndex]->process( regressionData ) ){
1828  errorLog << "predict_regressifier(VectorFloat inputVector) - Context Module Failed at AFTER_CLASSIFIER. ModuleIndex: " << moduleIndex << std::endl;
1829  return false;
1830  }
1831  if( !contextModules[ AFTER_CLASSIFIER ][moduleIndex]->getOK() ){
1832  predictionModuleIndex = AFTER_CLASSIFIER;
1833  return false;
1834  }
1835  regressionData = contextModules[ AFTER_CLASSIFIER ][moduleIndex]->getProcessedData();
1836  }
1837  }
1838 
1839  //Perform any post processing
1840  predictionModuleIndex = AFTER_CLASSIFIER;
1841  if( getIsPostProcessingSet() ){
1842 
1843  if( pipelineMode != REGRESSION_MODE ){
1844  errorLog << "predict_regressifier(VectorFloat inputVector) - Pipeline Mode Is Not In RegressionMode!" << std::endl;
1845  return false;
1846  }
1847 
1848  for(UINT moduleIndex=0; moduleIndex<postProcessingModules.size(); moduleIndex++){
1849  if( regressionData.size() != postProcessingModules[moduleIndex]->getNumInputDimensions() ){
1850  errorLog << "predict_regressifier(VectorFloat inputVector) - The size of the regression Vector (" << int(regressionData.size()) << ") does not match that of the postProcessingModule (" << postProcessingModules[moduleIndex]->getNumInputDimensions() << ") at the moduleIndex: " << moduleIndex << std::endl;
1851  return false;
1852  }
1853 
1854  if( !postProcessingModules[moduleIndex]->process( regressionData ) ){
1855  errorLog << "predict_regressifier(VectorFloat inputVector) - Failed to post process data. PostProcessing moduleIndex: " << moduleIndex << std::endl;
1856  return false;
1857  }
1858  regressionData = postProcessingModules[moduleIndex]->getProcessedData();
1859  }
1860 
1861  }
1862 
1863  //Update the context module
1864  predictionModuleIndex = END_OF_PIPELINE;
1865  if( contextModules[ END_OF_PIPELINE ].size() ){
1866  for(UINT moduleIndex=0; moduleIndex<contextModules[ END_OF_PIPELINE ].size(); moduleIndex++){
1867  if( !contextModules[ END_OF_PIPELINE ][moduleIndex]->process( inputVector ) ){
1868  errorLog << "predict_regressifier(VectorFloat inputVector) - Context Module Failed at END_OF_PIPELINE. ModuleIndex: " << moduleIndex << std::endl;
1869  return false;
1870  }
1871  if( !contextModules[ END_OF_PIPELINE ][moduleIndex]->getOK() ){
1872  predictionModuleIndex = END_OF_PIPELINE;
1873  return false;
1874  }
1875  regressionData = contextModules[ END_OF_PIPELINE ][moduleIndex]->getProcessedData();
1876  }
1877  }
1878 
1879  return true;
1880 }
1881 
1882 bool GestureRecognitionPipeline::predict_clusterer(const VectorFloat &input){
1883 
1884  VectorFloat inputVector = input;
1885  predictedClusterLabel = 0;
1886 
1887  //Update the context module
1888  predictionModuleIndex = START_OF_PIPELINE;
1889  if( contextModules[ START_OF_PIPELINE ].size() ){
1890  for(UINT moduleIndex=0; moduleIndex<contextModules[ START_OF_PIPELINE ].size(); moduleIndex++){
1891  if( !contextModules[ START_OF_PIPELINE ][moduleIndex]->process( inputVector ) ){
1892  errorLog << "predict_clusterer(VectorFloat inputVector) - Context Module Failed at START_OF_PIPELINE. ModuleIndex: " << moduleIndex << std::endl;
1893  return false;
1894  }
1895  if( !contextModules[ START_OF_PIPELINE ][moduleIndex]->getOK() ){
1896  return true;
1897  }
1898  inputVector = contextModules[ START_OF_PIPELINE ][moduleIndex]->getProcessedData();
1899  }
1900  }
1901 
1902  //Perform any pre-processing
1903  if( getIsPreProcessingSet() ){
1904  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
1905  if( !preProcessingModules[moduleIndex]->process( inputVector ) ){
1906  errorLog << "predict_clusterer(VectorFloat inputVector) - Failed to PreProcess Input Vector. PreProcessingModuleIndex: " << moduleIndex << std::endl;
1907  return false;
1908  }
1909  inputVector = preProcessingModules[moduleIndex]->getProcessedData();
1910  }
1911  }
1912 
1913  //Update the context module
1914  predictionModuleIndex = AFTER_PREPROCESSING;
1915  if( contextModules[ AFTER_PREPROCESSING ].size() ){
1916  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_PREPROCESSING ].size(); moduleIndex++){
1917  if( !contextModules[ AFTER_PREPROCESSING ][moduleIndex]->process( inputVector ) ){
1918  errorLog << "predict_clusterer(VectorFloat inputVector) - Context Module Failed at AFTER_PREPROCESSING. ModuleIndex: " << moduleIndex << std::endl;
1919  return false;
1920  }
1921  if( !contextModules[ AFTER_PREPROCESSING ][moduleIndex]->getOK() ){
1922  predictionModuleIndex = AFTER_PREPROCESSING;
1923  return false;
1924  }
1925  inputVector = contextModules[ AFTER_PREPROCESSING ][moduleIndex]->getProcessedData();
1926  }
1927  }
1928 
1929  //Perform any feature extraction
1930  if( getIsFeatureExtractionSet() ){
1931  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
1932  if( !featureExtractionModules[moduleIndex]->computeFeatures( inputVector ) ){
1933  errorLog << "predict_clusterer(VectorFloat inputVector) - Failed to compute features from data. FeatureExtractionModuleIndex: " << moduleIndex << std::endl;
1934  return false;
1935  }
1936  inputVector = featureExtractionModules[moduleIndex]->getFeatureVector();
1937  }
1938  }
1939 
1940  //Update the context module
1941  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1942  if( contextModules[ AFTER_FEATURE_EXTRACTION ].size() ){
1943  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_FEATURE_EXTRACTION ].size(); moduleIndex++){
1944  if( !contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->process( inputVector ) ){
1945  errorLog << "predict_clusterer(VectorFloat inputVector) - Context Module Failed at AFTER_FEATURE_EXTRACTION. ModuleIndex: " << moduleIndex << std::endl;
1946  return false;
1947  }
1948  if( !contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->getOK() ){
1949  predictionModuleIndex = AFTER_FEATURE_EXTRACTION;
1950  return false;
1951  }
1952  inputVector = contextModules[ AFTER_FEATURE_EXTRACTION ][moduleIndex]->getProcessedData();
1953  }
1954  }
1955 
1956  //Perform the classification
1957  if( !clusterer->predict(inputVector) ){
1958  errorLog << "predict_clusterer(VectorFloat inputVector) - Prediction Failed! " << clusterer->getLastErrorMessage() << std::endl;
1959  return false;
1960  }
1961  predictedClusterLabel = clusterer->getPredictedClusterLabel();
1962 
1963  //Update the context module
1964  if( contextModules[ AFTER_CLASSIFIER ].size() ){
1965  for(UINT moduleIndex=0; moduleIndex<contextModules[ AFTER_CLASSIFIER ].size(); moduleIndex++){
1966  if( !contextModules[ AFTER_CLASSIFIER ][moduleIndex]->process( VectorFloat(1,predictedClusterLabel) ) ){
1967  errorLog << "predict_clusterer(VectorFloat inputVector) - Context Module Failed at AFTER_CLASSIFIER. ModuleIndex: " << moduleIndex << std::endl;
1968  return false;
1969  }
1970  if( !contextModules[ AFTER_CLASSIFIER ][moduleIndex]->getOK() ){
1971  predictionModuleIndex = AFTER_CLASSIFIER;
1972  return false;
1973  }
1974  predictedClusterLabel = (UINT)contextModules[ AFTER_CLASSIFIER ][moduleIndex]->getProcessedData()[0];
1975  }
1976  }
1977 
1978  //Perform any post processing
1979  predictionModuleIndex = AFTER_CLASSIFIER;
1980  if( getIsPostProcessingSet() ){
1981 
1982  if( pipelineMode != CLASSIFICATION_MODE){
1983  errorLog << "predict_clusterer(VectorFloat inputVector) - Pipeline Mode Is Not in CLASSIFICATION_MODE!" << std::endl;
1984  return false;
1985  }
1986 
1987  VectorFloat data;
1988  for(UINT moduleIndex=0; moduleIndex<postProcessingModules.size(); moduleIndex++){
1989 
1990  //Select which input we should give the postprocessing module
1991  if( postProcessingModules[moduleIndex]->getIsPostProcessingInputModePredictedClassLabel() ){
1992  //Set the input
1993  data.resize(1);
1994  data[0] = predictedClusterLabel;
1995 
1996  //Verify that the input size is OK
1997  if( data.size() != postProcessingModules[moduleIndex]->getNumInputDimensions() ){
1998  errorLog << "predict_clusterer(VectorFloat inputVector) - The size of the data Vector (" << int(data.size()) << ") does not match that of the postProcessingModule (" << postProcessingModules[moduleIndex]->getNumInputDimensions() << ") at the moduleIndex: " << moduleIndex << std::endl;
1999  return false;
2000  }
2001 
2002  //Postprocess the data
2003  if( !postProcessingModules[moduleIndex]->process( data ) ){
2004  errorLog << "predict_clusterer(VectorFloat inputVector) - Failed to post process data. PostProcessing moduleIndex: " << moduleIndex << std::endl;
2005  return false;
2006  }
2007 
2008  //Select which output we should update
2009  data = postProcessingModules[moduleIndex]->getProcessedData();
2010  }
2011 
2012  //Select which output we should update
2013  if( postProcessingModules[moduleIndex]->getIsPostProcessingOutputModePredictedClassLabel() ){
2014  //Get the processed predicted class label
2015  data = postProcessingModules[moduleIndex]->getProcessedData();
2016 
2017  //Verify that the output size is OK
2018  if( data.size() != 1 ){
2019  errorLog << "predict_clusterer(VectorFloat inputVector) - The size of the processed data Vector (" << int(data.size()) << ") from postProcessingModule at the moduleIndex: " << moduleIndex << " is not equal to 1 even though it is in OutputModePredictedClassLabel!" << std::endl;
2020  return false;
2021  }
2022 
2023  //Update the predicted cluster label
2024  predictedClusterLabel = (UINT)data[0];
2025  }
2026 
2027  }
2028  }
2029 
2030  //Update the context module
2031  predictionModuleIndex = END_OF_PIPELINE;
2032  if( contextModules[ END_OF_PIPELINE ].size() ){
2033  for(UINT moduleIndex=0; moduleIndex<contextModules[ END_OF_PIPELINE ].size(); moduleIndex++){
2034  if( !contextModules[ END_OF_PIPELINE ][moduleIndex]->process( VectorFloat(1,predictedClassLabel) ) ){
2035  errorLog << "predict_clusterer(VectorFloat inputVector) - Context Module Failed at END_OF_PIPELINE. ModuleIndex: " << moduleIndex << std::endl;
2036  return false;
2037  }
2038  if( !contextModules[ END_OF_PIPELINE ][moduleIndex]->getOK() ){
2039  predictionModuleIndex = END_OF_PIPELINE;
2040  return false;
2041  }
2042  predictedClusterLabel = (UINT)contextModules[ END_OF_PIPELINE ][moduleIndex]->getProcessedData()[0];
2043  }
2044  }
2045 
2046  return true;
2047 }
2048 
2050 
2051  //Reset any pre processing
2052  if( getIsPreProcessingSet() ){
2053  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
2054  if( !preProcessingModules[ moduleIndex ]->reset() ){
2055  errorLog << "Failed To Reset PreProcessingModule " << moduleIndex << std::endl;
2056  return false;
2057  }
2058  }
2059  }
2060 
2061  //Reset any feature extraction
2062  if( getIsFeatureExtractionSet() ){
2063  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
2064  if( !featureExtractionModules[ moduleIndex ]->reset() ){
2065  errorLog << "Failed To Reset FeatureExtractionModule " << moduleIndex << std::endl;
2066  return false;
2067  }
2068  }
2069  }
2070 
2071  //Reset the classifier
2072  if( getIsClassifierSet() ){
2073  if( !classifier->reset() ){
2074  errorLog << "Failed To Reset Classifier! " << classifier->getLastErrorMessage() << std::endl;
2075  return false;
2076  }
2077  }
2078 
2079  //Reset the regressiier
2080  if( getIsRegressifierSet() ){
2081  if( !regressifier->reset() ){
2082  errorLog << "Failed To Reset Regressifier! " << regressifier->getLastErrorMessage() << std::endl;
2083  return false;
2084  }
2085  }
2086 
2087  //Reset the clusterer
2088  if( getIsClustererSet() ){
2089  if( !clusterer->reset() ){
2090  errorLog << "Failed To Reset clusterer! " << clusterer->getLastErrorMessage() << std::endl;
2091  return false;
2092  }
2093  }
2094 
2095  //Reset any post processing
2096  if( getIsPostProcessingSet() ){
2097  for(UINT moduleIndex=0; moduleIndex<postProcessingModules.size(); moduleIndex++){
2098  if( !postProcessingModules[ moduleIndex ]->reset() ){
2099  errorLog << "Failed To Reset PostProcessingModule " << moduleIndex << std::endl;
2100  return false;
2101  }
2102  }
2103  }
2104 
2105  return true;
2106 }
2107 
2108 bool GestureRecognitionPipeline::clearAll(){ return clear(); }
2109 
2111 
2112  //Clear the entire pipeline
2113  clearTestResults();
2114  deleteAllPreProcessingModules();
2115  deleteAllFeatureExtractionModules();
2116  deleteClassifier();
2117  deleteRegressifier();
2118  deleteClusterer();
2119  deleteAllPostProcessingModules();
2120  deleteAllContextModules();
2121 
2122  //Reset the pipeline
2123  return init();
2124 }
2125 
2127 
2128  //Clear any preprocessing module
2129  for(UINT i=0; i<getNumPreProcessingModules(); i++){
2130  preProcessingModules[i]->clear();
2131  }
2132 
2133  //Clear any feature extraction module
2134  for(UINT i=0; i<getNumFeatureExtractionModules(); i++){
2135  featureExtractionModules[i]->clear();
2136  }
2137 
2138  //Clear any ML model
2139  switch( pipelineMode ){
2140  case PIPELINE_MODE_NOT_SET:
2141  break;
2142  case CLASSIFICATION_MODE:
2143  if( getIsClassifierSet() ){
2144  classifier->clear();
2145  }
2146  break;
2147  case REGRESSION_MODE:
2148  if( getIsRegressifierSet() ){
2149  regressifier->clear();
2150  }
2151  break;
2152  case CLUSTER_MODE:
2153  if( getIsClustererSet() ){
2154  clusterer->clear();
2155  }
2156  break;
2157  default:
2158  break;
2159  }
2160 
2161  //Clear any post processing modules
2162  for(UINT i=0; i<getNumPostProcessingModules(); i++){
2163  postProcessingModules[i]->clear();
2164  }
2165 
2166  return true;
2167 }
2168 
2169 bool GestureRecognitionPipeline::save(const std::string &filename) const {
2170  return savePipelineToFile( filename );
2171 }
2172 
2173 bool GestureRecognitionPipeline::savePipelineToFile(const std::string &filename) const {
2174 
2175  if( !initialized ){
2176  errorLog << "Failed to write pipeline to file as the pipeline has not been initialized yet!" << std::endl;
2177  return false;
2178  }
2179 
2180  std::fstream file;
2181 
2182  file.open(filename.c_str(), std::iostream::out );
2183 
2184  if( !file.is_open() ){
2185  errorLog << "Failed to open file with filename: " << filename << std::endl;
2186  return false;
2187  }
2188 
2189  //Write the pipeline header info
2190  file << "GRT_PIPELINE_FILE_V3.0\n";
2191  file << "PipelineMode: " << getPipelineModeAsString() << std::endl;
2192  file << "NumPreprocessingModules: " << getNumPreProcessingModules() << std::endl;
2193  file << "NumFeatureExtractionModules: " << getNumFeatureExtractionModules() << std::endl;
2194  file << "NumPostprocessingModules: " << getNumPostProcessingModules() << std::endl;
2195  file << "Trained: " << getTrained() << std::endl;
2196  file << "Info: " << info << std::endl;
2197 
2198  //Write the module datatype names
2199  file << "PreProcessingModuleDatatypes:";
2200  for(UINT i=0; i<getNumPreProcessingModules(); i++){
2201  file << "\t" << preProcessingModules[i]->getPreProcessingType();
2202  }
2203  file << std::endl;
2204 
2205  file << "FeatureExtractionModuleDatatypes:";
2206  for(UINT i=0; i<getNumFeatureExtractionModules(); i++){
2207  file << "\t" << featureExtractionModules[i]->getFeatureExtractionType();
2208  }
2209  file << std::endl;
2210 
2211  switch( pipelineMode ){
2212  case PIPELINE_MODE_NOT_SET:
2213  break;
2214  case CLASSIFICATION_MODE:
2215  if( getIsClassifierSet() ) file << "ClassificationModuleDatatype:\t" << classifier->getClassifierType() << std::endl;
2216  else file << "ClassificationModuleDatatype:\tCLASSIFIER_NOT_SET" << std::endl;
2217  break;
2218  case REGRESSION_MODE:
2219  if( getIsRegressifierSet() ) file << "RegressionModuleDatatype:\t" << regressifier->getRegressifierType() << std::endl;
2220  else file << "RegressionModuleDatatype:\tREGRESSIFIER_NOT_SET" << std::endl;
2221  break;
2222  case CLUSTER_MODE:
2223  if( getIsClustererSet() ) file << "ClusterModuleDatatype:\t" << clusterer->getClustererType() << std::endl;
2224  else file << "ClusterModuleDatatype:\tCLUSTERER_NOT_SET" << std::endl;
2225  break;
2226  default:
2227  break;
2228  }
2229 
2230  file << "PostProcessingModuleDatatypes:";
2231  for(UINT i=0; i<getNumPostProcessingModules(); i++){
2232  file << "\t" << postProcessingModules[i]->getPostProcessingType();
2233  }
2234  file << std::endl;
2235 
2236  //Write the preprocessing module data to the file
2237  for(UINT i=0; i<getNumPreProcessingModules(); i++){
2238  file << "PreProcessingModule_" << Util::intToString(i+1) << std::endl;
2239  if( !preProcessingModules[i]->saveModelToFile( file ) ){
2240  errorLog << "Failed to write preprocessing module " << i << " settings to file!" << std::endl;
2241  file.close();
2242  return false;
2243  }
2244  }
2245 
2246  //Write the feature extraction module data to the file
2247  for(UINT i=0; i<getNumFeatureExtractionModules(); i++){
2248  file << "FeatureExtractionModule_" << Util::intToString(i+1) << std::endl;
2249  if( !featureExtractionModules[i]->saveModelToFile( file ) ){
2250  errorLog << "Failed to write feature extraction module " << i << " settings to file!" << std::endl;
2251  file.close();
2252  return false;
2253  }
2254  }
2255 
2256  switch( pipelineMode ){
2257  case PIPELINE_MODE_NOT_SET:
2258  break;
2259  case CLASSIFICATION_MODE:
2260  if( getIsClassifierSet() ){
2261  if( !classifier->saveModelToFile( file ) ){
2262  errorLog << "Failed to write classifier model to file!" << std::endl;
2263  file.close();
2264  return false;
2265  }
2266  }
2267  break;
2268  case REGRESSION_MODE:
2269  if( getIsRegressifierSet() ){
2270  if( !regressifier->saveModelToFile( file ) ){
2271  errorLog << "Failed to write regressifier model to file!" << std::endl;
2272  file.close();
2273  return false;
2274  }
2275  }
2276  break;
2277  case CLUSTER_MODE:
2278  if( getIsClustererSet() ){
2279  if( !clusterer->saveModelToFile( file ) ){
2280  errorLog << "Failed to write clusterer model to file!" << std::endl;
2281  file.close();
2282  return false;
2283  }
2284  }
2285  break;
2286  default:
2287  break;
2288  }
2289 
2290  //Write the post processing module data to the file
2291  for(UINT i=0; i<getNumPostProcessingModules(); i++){
2292  file << "PostProcessingModule_" << Util::intToString(i+1) << std::endl;
2293  if( !postProcessingModules[i]->saveModelToFile( file ) ){
2294  errorLog <<"Failed to write post processing module " << i << " settings to file!" << std::endl;
2295  file.close();
2296  return false;
2297  }
2298  }
2299 
2300  //Close the file
2301  file.close();
2302 
2303  return true;
2304 }
2305 
2306 bool GestureRecognitionPipeline::load(const std::string &filename){
2307  return loadPipelineFromFile( filename );
2308 }
2309 
2310 bool GestureRecognitionPipeline::loadPipelineFromFile(const std::string &filename){
2311 
2312  std::fstream file;
2313 
2314  //Clear any previous setup
2315  clear();
2316 
2317  file.open(filename.c_str(), std::iostream::in );
2318 
2319  if( !file.is_open() ){
2320  errorLog << "loadPipelineFromFile(string filename) - Failed to open file with filename: " << filename << std::endl;
2321  return false;
2322  }
2323 
2324  std::string word;
2325 
2326  //Load the file header
2327  file >> word;
2328  if( word != "GRT_PIPELINE_FILE_V3.0" ){
2329  errorLog << "loadPipelineFromFile(string filename) - Failed to read file header" << std::endl;
2330  file.close();
2331  return false;
2332  }
2333 
2334  //Load the pipeline mode
2335  file >> word;
2336  if( word != "PipelineMode:" ){
2337  errorLog << "loadPipelineFromFile(string filename) - Failed to read PipelineMode" << std::endl;
2338  file.close();
2339  return false;
2340  }
2341  file >> word;
2342  pipelineMode = getPipelineModeFromString(word);
2343 
2344  //Load the NumPreprocessingModules
2345  file >> word;
2346  if( word != "NumPreprocessingModules:" ){
2347  errorLog << "loadPipelineFromFile(string filename) - Failed to read NumPreprocessingModules header" << std::endl;
2348  file.close();
2349  return false;
2350  }
2351  unsigned int numPreprocessingModules;
2352  file >> numPreprocessingModules;
2353 
2354  //Load the NumFeatureExtractionModules
2355  file >> word;
2356  if( word != "NumFeatureExtractionModules:" ){
2357  errorLog << "loadPipelineFromFile(string filename) - Failed to read NumFeatureExtractionModules header" << std::endl;
2358  file.close();
2359  return false;
2360  }
2361  unsigned int numFeatureExtractionModules;
2362  file >> numFeatureExtractionModules;
2363 
2364  //Load the NumPostprocessingModules
2365  file >> word;
2366  if( word != "NumPostprocessingModules:" ){
2367  errorLog << "loadPipelineFromFile(string filename) - Failed to read NumPostprocessingModules header" << std::endl;
2368  file.close();
2369  return false;
2370  }
2371  unsigned int numPostprocessingModules;
2372  file >> numPostprocessingModules;
2373 
2374  //Load if the pipeline has been trained
2375  file >> word;
2376  if( word != "Trained:" ){
2377  errorLog << "loadPipelineFromFile(string filename) - Failed to read Trained header" << std::endl;
2378  file.close();
2379  return false;
2380  }
2381  file >> trained;
2382 
2383  //Load the info
2384  file >> word;
2385  if( word != "Info:" ){
2386  errorLog << "loadPipelineFromFile(string filename) - Failed to read Info header" << std::endl;
2387  file.close();
2388  return false;
2389  }
2390  info = "";
2391  //Read the info text
2392  file >> word;
2393  while( word != "PreProcessingModuleDatatypes:" ){
2394  info += word;
2395  file >> word;
2396  }
2397 
2398  //Resize the modules
2399  if( numPreprocessingModules > 0 ) preProcessingModules.resize(numPreprocessingModules,NULL);
2400  if( numFeatureExtractionModules > 0 ) featureExtractionModules.resize(numFeatureExtractionModules,NULL);
2401  if( numPostprocessingModules > 0 ) postProcessingModules.resize(numPostprocessingModules,NULL);
2402 
2403  //Load the preprocessing module datatypes and initialize the modules
2404  if( word != "PreProcessingModuleDatatypes:" ){
2405  errorLog << "loadPipelineFromFile(string filename) - Failed to read PreProcessingModuleDatatypes" << std::endl;
2406  file.close();
2407  return false;
2408  }
2409  for(UINT i=0; i<numPreprocessingModules; i++){
2410  file >> word;
2411  preProcessingModules[i] = PreProcessing::createInstanceFromString( word );
2412  if( preProcessingModules[i] == NULL ){
2413  errorLog << "loadPipelineFromFile(string filename) - Failed to create preprocessing instance from string: " << word << std::endl;
2414  file.close();
2415  return false;
2416  }
2417  }
2418 
2419  //Load the feature extraction module datatypes and initialize the modules
2420  file >> word;
2421  if( word != "FeatureExtractionModuleDatatypes:" ){
2422  errorLog << "loadPipelineFromFile(string filename) - Failed to read FeatureExtractionModuleDatatypes" << std::endl;
2423  file.close();
2424  return false;
2425  }
2426  for(UINT i=0; i<numFeatureExtractionModules; i++){
2427  file >> word;
2428  featureExtractionModules[i] = FeatureExtraction::createInstanceFromString( word );
2429  if( featureExtractionModules[i] == NULL ){
2430  errorLog << "loadPipelineFromFile(string filename) - Failed to create feature extraction instance from string: " << word << std::endl;
2431  file.close();
2432  return false;
2433  }
2434  }
2435 
2436  switch( pipelineMode ){
2437  case PIPELINE_MODE_NOT_SET:
2438  break;
2439  case CLASSIFICATION_MODE:
2440  file >> word;
2441  if( word != "ClassificationModuleDatatype:" ){
2442  errorLog << "loadPipelineFromFile(string filename) - Failed to read ClassificationModuleDatatype" << std::endl;
2443  file.close();
2444  return false;
2445  }
2446  //Load the classifier type
2447  file >> word;
2448 
2449  //Initialize the classifier
2450  classifier = Classifier::createInstanceFromString( word );
2451  if( classifier == NULL ){
2452  errorLog << "loadPipelineFromFile(string filename) - Failed to create classifier instance from string: " << word << std::endl;
2453  file.close();
2454  return false;
2455  }
2456  break;
2457  case REGRESSION_MODE:
2458  file >> word;
2459  if( word != "RegressionModuleDatatype:" ){
2460  errorLog << "loadPipelineFromFile(string filename) - Failed to read RegressionModuleDatatype" << std::endl;
2461  file.close();
2462  return false;
2463  }
2464  //Load the regressifier type
2465  file >> word;
2466 
2467  //Initialize the regressifier
2468  regressifier = Regressifier::createInstanceFromString( word );
2469  if( regressifier == NULL ){
2470  errorLog << "loadPipelineFromFile(string filename) - Failed to create regressifier instance from string: " << word << std::endl;
2471  file.close();
2472  return false;
2473  }
2474  break;
2475  case CLUSTER_MODE:
2476  file >> word;
2477  if( word != "ClusterModuleDatatype:" ){
2478  errorLog << "loadPipelineFromFile(string filename) - Failed to read ClusterModuleDatatype" << std::endl;
2479  file.close();
2480  return false;
2481  }
2482  //Load the clusterer type
2483  file >> word;
2484 
2485  //Initialize the clusterer
2486  clusterer = Clusterer::createInstanceFromString( word );
2487  if( clusterer == NULL ){
2488  errorLog << "loadPipelineFromFile(string filename) - Failed to create clusterer instance from string: " << word << std::endl;
2489  file.close();
2490  return false;
2491  }
2492  break;
2493  default:
2494  break;
2495  }
2496 
2497  //Load the post processing module datatypes and initialize the modules
2498  file >> word;
2499  if( word != "PostProcessingModuleDatatypes:" ){
2500  errorLog << "loadPipelineFromFile(string filename) - Failed to read PostProcessingModuleDatatypes" << std::endl;
2501  file.close();
2502  return false;
2503  }
2504  for(UINT i=0; i<numPostprocessingModules; i++){
2505  file >> word;
2506  postProcessingModules[i] = PostProcessing::createInstanceFromString( word );
2507  }
2508 
2509  //Load the preprocessing module data from the file
2510  for(UINT i=0; i<numPreprocessingModules; i++){
2511  //Load the preprocessing module header
2512  file >> word;
2513  if( !preProcessingModules[i]->loadModelFromFile( file ) ){
2514  errorLog << "Failed to load preprocessing module " << i << " settings from file!" << std::endl;
2515  file.close();
2516  return false;
2517  }
2518  }
2519 
2520  //Load the feature extraction module data from the file
2521  for(UINT i=0; i<numFeatureExtractionModules; i++){
2522  //Load the feature extraction module header
2523  file >> word;
2524  if( !featureExtractionModules[i]->loadModelFromFile( file ) ){
2525  errorLog << "Failed to load feature extraction module " << i << " settings from file!" << std::endl;
2526  file.close();
2527  return false;
2528  }
2529  }
2530 
2531  //Load the classifier or regressifer data
2532  switch( pipelineMode ){
2533  case PIPELINE_MODE_NOT_SET:
2534  break;
2535  case CLASSIFICATION_MODE:
2536  if( !classifier->loadModelFromFile( file ) ){
2537  errorLog << "Failed to load classifier model from file!" << std::endl;
2538  file.close();
2539  return false;
2540  }
2541  break;
2542  case REGRESSION_MODE:
2543  if( !regressifier->loadModelFromFile( file ) ){
2544  errorLog << "Failed to load regressifier model from file!" << std::endl;
2545  file.close();
2546  return false;
2547  }
2548  break;
2549  case CLUSTER_MODE:
2550  if( !clusterer->loadModelFromFile( file ) ){
2551  errorLog << "Failed to load cluster model from file!" << std::endl;
2552  file.close();
2553  return false;
2554  }
2555  break;
2556  default:
2557  break;
2558  }
2559 
2560  //Load the post processing module data from the file
2561  for(UINT i=0; i<numPostprocessingModules; i++){
2562  //Load the post processing module header
2563  file >> word;
2564  if( !postProcessingModules[i]->loadModelFromFile( file ) ){
2565  errorLog << "Failed to load post processing module " << i << " settings from file!" << std::endl;
2566  file.close();
2567  return false;
2568  }
2569  }
2570 
2571  //Close the file
2572  file.close();
2573 
2574  //Set the expected input Vector size
2575  inputVectorDimensions = 0;
2576 
2577  if( numPreprocessingModules > 0 ){
2578  inputVectorDimensions = preProcessingModules[0]->getNumInputDimensions();
2579  }else{
2580  if( numFeatureExtractionModules > 0 ){
2581  inputVectorDimensions = featureExtractionModules[0]->getNumInputDimensions();
2582  }else{
2583  switch( pipelineMode ){
2584  case PIPELINE_MODE_NOT_SET:
2585  break;
2586  case CLASSIFICATION_MODE:
2587  inputVectorDimensions = classifier->getNumInputDimensions();
2588  break;
2589  case REGRESSION_MODE:
2590  inputVectorDimensions = regressifier->getNumInputDimensions();
2591  break;
2592  case CLUSTER_MODE:
2593  inputVectorDimensions = clusterer->getNumInputDimensions();
2594  break;
2595  default:
2596  break;
2597  }
2598  }
2599  }
2600 
2601  //Flag that the pipeline is now initialized
2602  initialized = true;
2603 
2604  return true;
2605 }
2606 
2607 bool GestureRecognitionPipeline::preProcessData(VectorFloat inputVector,bool computeFeatures){
2608 
2609  if( getIsPreProcessingSet() ){
2610  for(UINT moduleIndex=0; moduleIndex<preProcessingModules.size(); moduleIndex++){
2611 
2612  if( inputVector.size() != preProcessingModules[ moduleIndex ]->getNumInputDimensions() ){
2613  errorLog << "preProcessData(VectorFloat inputVector) - The size of the input Vector (" << preProcessingModules[ moduleIndex ]->getNumInputDimensions() << ") does not match that of the PreProcessing Module at moduleIndex: " << moduleIndex << std::endl;
2614  return false;
2615  }
2616 
2617  if( !preProcessingModules[ moduleIndex ]->process( inputVector ) ){
2618  errorLog << "preProcessData(VectorFloat inputVector) - Failed To PreProcess Input Vector. PreProcessing moduleIndex: " << moduleIndex << std::endl;
2619  return false;
2620  }
2621  inputVector = preProcessingModules[ moduleIndex ]->getProcessedData();
2622  }
2623  }
2624 
2625  //Perform any feature extraction
2626  if( getIsFeatureExtractionSet() && computeFeatures ){
2627  for(UINT moduleIndex=0; moduleIndex<featureExtractionModules.size(); moduleIndex++){
2628  if( inputVector.size() != featureExtractionModules[ moduleIndex ]->getNumInputDimensions() ){
2629  errorLog << "FeatureExtraction(VectorFloat inputVector) - The size of the input Vector (" << featureExtractionModules[ moduleIndex ]->getNumInputDimensions() << ") does not match that of the FeatureExtraction Module at moduleIndex: " << moduleIndex << std::endl;
2630  return false;
2631  }
2632 
2633  if( !featureExtractionModules[ moduleIndex ]->computeFeatures( inputVector ) ){
2634  errorLog << "FeatureExtraction(VectorFloat inputVector) - Failed To Compute Features from Input Vector. FeatureExtraction moduleIndex: " << moduleIndex << std::endl;
2635  return false;
2636  }
2637  inputVector = featureExtractionModules[ moduleIndex ]->getFeatureVector();
2638  }
2639  }
2640 
2641  return true;
2642 }
2643 
2646  return initialized;
2647 }
2648 
2650  return trained;
2651 }
2652 
2654  return preProcessingModules.size() > 0;
2655 }
2656 
2658  return featureExtractionModules.size() > 0;
2659 }
2660 
2662  return (classifier!=NULL);
2663 }
2664 
2666  return (regressifier!=NULL);
2667 }
2668 
2670  return (clusterer!=NULL);
2671 }
2672 
2674  return postProcessingModules.size() > 0;
2675 }
2676 
2678  for(UINT i=0; i<NUM_CONTEXT_LEVELS; i++){
2679  if( contextModules[i].size() > 0 ) return true;
2680  }
2681  return false;
2682 }
2683 
2685  return (pipelineMode!=PIPELINE_MODE_NOT_SET);
2686 }
2687 
2689  return (pipelineMode==CLASSIFICATION_MODE);
2690 }
2691 
2693  return pipelineMode==REGRESSION_MODE;
2694 }
2695 
2697 
2698  if( getIsPreProcessingSet() ){
2699  return preProcessingModules[0]->getNumInputDimensions();
2700  }
2701 
2702  if( getIsFeatureExtractionSet() ){
2703  return featureExtractionModules[0]->getNumInputDimensions();
2704  }
2705 
2707  return classifier->getNumInputFeatures();
2708  }
2710  return regressifier->getNumInputFeatures();
2711  }
2712  return 0;
2713 }
2714 
2716  if( getIsClassifierSet() ) return 1; //The output of the pipeline for classification will always be 1
2717  if( getIsRegressifierSet() ){
2718  return regressifier->getNumOutputDimensions();
2719  }
2720  return 0;
2721 }
2722 
2724  return getNumClasses();
2725 }
2726 
2728  UINT numClasses = 0;
2729  if( getIsClassifierSet() ){
2730  numClasses = classifier->getNumClasses();
2731  }
2732  if( getIsClustererSet() ){
2733  numClasses = clusterer->getNumClusters();
2734  }
2735  return numClasses;
2736 }
2737 
2739  return preProcessingModules.getSize();
2740 }
2741 
2743  return featureExtractionModules.getSize();
2744 }
2745 
2747  return postProcessingModules.getSize();
2748 }
2749 
2751  return predictionModuleIndex;
2752 }
2753 
2755 
2756  if( getIsClassifierSet() ){
2757  return predictedClassLabel;
2758  }
2759  if( getIsClustererSet() ){
2760  return predictedClusterLabel;
2761  }
2762  return 0;
2763 }
2764 
2766  if( getIsClassifierSet() ){
2767  return classifier->getPredictedClassLabel();
2768  }
2769  if( getIsClustererSet() ){
2770  return clusterer->getPredictedClusterLabel();
2771  }
2772  return 0;
2773 }
2774 
2776  return numTrainingSamples;
2777 }
2778 
2780  return numTestSamples;
2781 }
2782 
2784  if( getIsClassifierSet() ){
2785  return classifier->getMaximumLikelihood();
2786  }
2787  if( getIsClustererSet() ){
2788  return clusterer->getMaximumLikelihood();
2789  }
2790  return 0;
2791 }
2792 
2794  if( getIsClassifierSet() ){
2795  return classifier->getPhase();
2796  }
2797  return 0;
2798 }
2799 
2801  return (getIsClassifierSet()||getIsRegressifierSet() ? testAccuracy : 0);
2802 }
2803 
2805  return testAccuracy;
2806 }
2807 
2809  return testRMSError;
2810 }
2811 
2813  return testSquaredError;
2814 }
2815 
2816 Float GestureRecognitionPipeline::getTestFMeasure(const UINT classLabel) const{
2817 
2818  if( !getIsClassifierSet() ) return -1;
2819  if( getClassLabels().size() != testFMeasure.size() ) return -1;
2820 
2821  for(UINT i=0; i<testFMeasure.size(); i++){
2822  if( getClassLabels()[i] == classLabel ){
2823  return testFMeasure[i];
2824  }
2825  }
2826  return -1;
2827 }
2828 
2829 Float GestureRecognitionPipeline::getTestPrecision(const UINT classLabel) const{
2830 
2831  if( !getIsClassifierSet() ) return -1;
2832  if( getClassLabels().size() != testPrecision.size() ) return -1;
2833 
2834  for(UINT i=0; i<testPrecision.size(); i++){
2835  if( getClassLabels()[i] == classLabel ){
2836  return testPrecision[i];
2837  }
2838  }
2839  return -1;
2840 }
2841 
2842 Float GestureRecognitionPipeline::getTestRecall(const UINT classLabel) const{
2843 
2844  if( !getIsClassifierSet() ) return -1;
2845  if( getClassLabels().getSize() != testRecall.getSize() ) return -1;
2846 
2847  for(UINT i=0; i<testRecall.getSize(); i++){
2848  if( getClassLabels()[i] == classLabel ){
2849  return testRecall[i];
2850  }
2851  }
2852  return -1;
2853 }
2854 
2856  return testRejectionPrecision;
2857 }
2858 
2860  return testRejectionRecall;
2861 }
2862 
2864  return testTime;
2865 }
2866 
2868  return trainingTime;
2869 }
2870 
2872  return getIsRegressifierSet() ? regressifier->getRootMeanSquaredTrainingError() : 0;
2873 }
2874 
2876  return getIsRegressifierSet() ? regressifier->getTotalSquaredTrainingError() : 0;
2877 }
2878 
2880  return testConfusionMatrix;
2881 }
2882 
2884  TestResult testResults;
2885  testResults.numTrainingSamples = numTrainingSamples;
2886  testResults.numTestSamples = numTestSamples;
2887  testResults.accuracy = testAccuracy;
2888  testResults.rmsError = testRMSError;
2889  testResults.totalSquaredError = testSquaredError;
2890  testResults.trainingTime = trainingTime;
2891  testResults.testTime = testTime;
2892  testResults.rejectionPrecision = testRejectionPrecision;
2893  testResults.rejectionRecall = testRejectionRecall;
2894  testResults.precision = testPrecision;
2895  testResults.recall = testRecall;
2896  testResults.fMeasure = testFMeasure;
2897  testResults.confusionMatrix = testConfusionMatrix;
2898  return testResults;
2899 }
2900 
2902  return testPrecision;
2903 }
2904 
2906  return testRecall;
2907 }
2908 
2910  return testFMeasure;
2911 }
2912 
2914  if( getIsClassifierSet() ){ return classifier->getClassLikelihoods(); }
2915  if( getIsClustererSet() ){ return clusterer->getClusterLikelihoods(); }
2916  else{ return VectorFloat(); }
2917 }
2918 
2920  if( getIsClassifierSet() ){ return classifier->getClassDistances(); }
2921  if( getIsClustererSet() ){ return clusterer->getClusterDistances(); }
2922  else{ return VectorFloat(); }
2923 }
2924 
2926  if( getIsClassifierSet() ){ return classifier->getNullRejectionThresholds(); }
2927  else{ return VectorFloat(); }
2928 }
2929 
2931  return regressionData;
2932 }
2933 
2935  if( getIsRegressifierSet() ) {
2936  return regressifier->getRegressionData();
2937  }
2938  return VectorFloat();
2939 }
2940 
2942  if( getIsPreProcessingSet() ){
2943  return preProcessingModules[ preProcessingModules.size()-1 ]->getProcessedData();
2944  }
2945  return VectorFloat();
2946 }
2947 
2949  if( getIsPreProcessingSet() ){
2950  if( moduleIndex < preProcessingModules.size() ){
2951  return preProcessingModules[ moduleIndex ]->getProcessedData();
2952  }
2953  }
2954  return VectorFloat();
2955 }
2956 
2958  if( getIsFeatureExtractionSet() ){
2959  return featureExtractionModules[ featureExtractionModules.size()-1 ]->getFeatureVector();
2960  }
2961  return VectorFloat();
2962 }
2963 
2965  if( getIsFeatureExtractionSet() ){
2966  if( moduleIndex < featureExtractionModules.size() ){
2967  return featureExtractionModules[ moduleIndex ]->getFeatureVector();
2968  }
2969  }
2970  warningLog << "getFeatureExtractionData(UINT moduleIndex) - Failed to get class labels!" << std::endl;
2971  return VectorFloat();
2972 }
2973 
2975  if( getIsClassifierSet() ){
2976  return classifier->getClassLabels();
2977  }
2978  if( getIsClustererSet() ){
2979  return clusterer->getClusterLabels();
2980  }
2981  warningLog << "getClassLabels() - Failed to get class labels!" << std::endl;
2982  return Vector< UINT>();
2983 }
2984 
2986  return testResults;
2987 }
2988 
2990  return crossValidationResults;
2991 }
2992 
2994  if( moduleIndex < preProcessingModules.size() ){
2995  return preProcessingModules[ moduleIndex ];
2996  }
2997  warningLog << "getPreProcessingModule(const UINT moduleIndex) - Failed to get pre processing module!" << std::endl;
2998  return NULL;
2999 }
3000 
3002  if( moduleIndex < featureExtractionModules.size() ){
3003  return featureExtractionModules[ moduleIndex ];
3004  }
3005  warningLog << "getFeatureExtractionModule(const UINT moduleIndex) - Failed to get feature extraction module!" << std::endl;
3006  return NULL;
3007 }
3008 
3010  return classifier;
3011 }
3012 
3014  return regressifier;
3015 }
3016 
3018  return clusterer;
3019 }
3020 
3022  if( moduleIndex < postProcessingModules.size() ){
3023  return postProcessingModules[ moduleIndex ];
3024  }
3025  warningLog << "getPostProcessingModule(UINT moduleIndex) - Failed to get post processing module!" << std::endl;
3026  return NULL;
3027 }
3028 
3029 Context* GestureRecognitionPipeline::getContextModule(UINT contextLevel,UINT moduleIndex) const{
3030  if( contextLevel < contextModules.size() ){
3031  if( moduleIndex < contextModules[ contextLevel ].size() ){
3032  return contextModules[ contextLevel ][ moduleIndex ];
3033  }
3034  }
3035  warningLog << "getContextModule(UINT contextLevel,UINT moduleIndex) - Failed to get context module!" << std::endl;
3036  return NULL;
3037 }
3038 
3042 
3043 bool GestureRecognitionPipeline::addPreProcessingModule(const PreProcessing &preProcessingModule,UINT insertIndex){
3044 
3045  //Validate the insertIndex is valid
3046  if( insertIndex != INSERT_AT_END_INDEX && insertIndex >= preProcessingModules.size() ){
3047  errorLog << "addPreProcessingModule(const PreProcessing &preProcessingModule) - Invalid insertIndex value!" << std::endl;
3048  return false;
3049  }
3050 
3051  //Create a new instance of the preProcessing and then clone the values across from the reference preProcessing
3052  PreProcessing *newInstance = preProcessingModule.createNewInstance();
3053 
3054  //Verify that the clone was successful
3055  if( !newInstance->deepCopyFrom( &preProcessingModule ) ){
3056  delete newInstance;
3057  newInstance = NULL;
3058  errorLog << "addPreProcessingModule(const PreProcessing &preProcessingModule) - PreProcessing Module Not Set!" << std::endl;
3059  return false;
3060  }
3061 
3062  //Add the new instance to the preProcessingModules
3063  Vector< PreProcessing* >::iterator iter = preProcessingModules.begin();
3064 
3065  if( insertIndex == INSERT_AT_END_INDEX ) iter = preProcessingModules.end();
3066  else iter = preProcessingModules.begin() + insertIndex;
3067 
3068  preProcessingModules.insert(iter, newInstance);
3069 
3070  //The pipeline has been changed, so flag that the pipeline is no longer trained
3071  trained = false;
3072 
3073  return true;
3074 }
3075 
3078  return addPreProcessingModule( preProcessingModule );
3079 }
3080 
3081 bool GestureRecognitionPipeline::addFeatureExtractionModule(const FeatureExtraction &featureExtractionModule,UINT insertIndex){
3082 
3083  //Validate the insertIndex is valid
3084  if( insertIndex != INSERT_AT_END_INDEX && insertIndex >= featureExtractionModules.size() ){
3085  errorLog << "addFeatureExtractionModule(const FeatureExtraction &featureExtractionModule) - Invalid insertIndex value!" << std::endl;
3086  return false;
3087  }
3088 
3089  //Create a new instance of the preProcessing and then clone the values across from the reference preProcessing
3090  FeatureExtraction *newInstance = featureExtractionModule.createNewInstance();
3091 
3092  //Verify that the clone was successful
3093  if( !newInstance->deepCopyFrom( &featureExtractionModule ) ){
3094  delete newInstance;
3095  newInstance = NULL;
3096  errorLog << "addFeatureExtractionModule(const FeatureExtraction &featureExtractionModule - FeatureExtraction Module Not Set!" << std::endl;
3097  return false;
3098  }
3099 
3100  //Add the new instance to the preProcessingModules
3101  Vector< FeatureExtraction* >::iterator iter = featureExtractionModules.begin();
3102 
3103  if( insertIndex == INSERT_AT_END_INDEX ) iter = featureExtractionModules.end();
3104  else iter = featureExtractionModules.begin() + insertIndex;
3105 
3106  featureExtractionModules.insert(iter, newInstance);
3107 
3108  //The pipeline has been changed, so flag that the pipeline is no longer trained
3109  trained = false;
3110 
3111  return true;
3112 }
3113 
3116  return addFeatureExtractionModule( featureExtractionModule );
3117 }
3118 
3120 
3121  //Delete any previous classifier, regressifier or clusterer
3122  deleteClassifier();
3123  deleteRegressifier();
3124  deleteClusterer();
3125 
3126  //Create a new instance of the classifier and then clone the values across from the reference classifier
3127  this->classifier = classifier.createNewInstance();
3128 
3129  if( this->classifier == NULL ){
3130  errorLog << "setClassifier(const Classifier classifier) - Classifier Module Not Set!" << std::endl;
3131  return false;
3132  }
3133 
3134  //Deep copy the data from the rhs classifier into this classifier
3135  if( !this->classifier->deepCopyFrom( &classifier ) ){
3136  deleteClassifier();
3137  pipelineMode = PIPELINE_MODE_NOT_SET;
3138  errorLog << "setClassifier(const Classifier classifier) - Classifier Module Not Set!" << std::endl;
3139  return false;
3140  }
3141 
3142  //Set the mode of the pipeline to classification mode
3143  pipelineMode = CLASSIFICATION_MODE;
3144 
3145  //Flag that the key part of the pipeline has now been initialized
3146  initialized = true;
3147 
3148  //If there is no preprocessing / feature extraction and the classifier is trained, then flag the pipeline is trained
3149  //Otherwise the user needs to train the pipeline
3150  if( !getIsPreProcessingSet() && !getIsFeatureExtractionSet() && classifier.getTrained() ){
3151  inputVectorDimensions = classifier.getNumInputDimensions();
3152  trained = true;
3153  }else trained = false;
3154 
3155  return true;
3156 }
3157 
3159 
3160  //Delete any previous classifier, regressifier or clusterer
3161  deleteClassifier();
3162  deleteRegressifier();
3163  deleteClusterer();
3164 
3165  //Set the mode of the pipeline to regression mode
3166  pipelineMode = REGRESSION_MODE;
3167 
3168  //Create a new instance of the regressifier and then clone the values across from the reference regressifier
3169  this->regressifier = regressifier.createNewInstance();
3170 
3171  //Validate that the regressifier was cloned correctly
3172  if( !this->regressifier->deepCopyFrom( &regressifier ) ){
3173  deleteRegressifier();
3174  pipelineMode = PIPELINE_MODE_NOT_SET;
3175  errorLog << "setRegressifier(const Regressifier &regressifier) - Regressifier Module Not Set!" << std::endl;
3176  return false;
3177  }
3178 
3179  //Flag that the key part of the pipeline has now been initialized
3180  initialized = true;
3181 
3182  //If there is no preprocessing / feature extraction and the regressifier is trained, then flag the pipeline is trained
3183  //Otherwise the user needs to train the pipeline
3185  trained = regressifier.getTrained();
3186  }else trained = false;
3187 
3188  return true;
3189 }
3190 
3192 
3193  //Delete any previous classifier, regressifier or clusterer
3194  deleteClassifier();
3195  deleteRegressifier();
3196  deleteClusterer();
3197 
3198  //Set the mode of the pipeline to cluster mode
3199  pipelineMode = CLUSTER_MODE;
3200 
3201  //Create a new instance of the clusterer and then clone the values across from the reference clusterer
3202  this->clusterer = clusterer.createNewInstance();
3203 
3204  //Validate that the regressifier was cloned correctly
3205  if( !this->clusterer->deepCopyFrom( &clusterer ) ){
3206  deleteClusterer();
3207  pipelineMode = PIPELINE_MODE_NOT_SET;
3208  errorLog << "setClusterer(const Clusterer &clusterer) - Clusterer Module Not Set!" << std::endl;
3209  return false;
3210  }
3211 
3212  //Flag that the key part of the pipeline has now been initialized
3213  initialized = true;
3214 
3215  //If there is no preprocessing / feature extraction and the regressifier is trained, then flag the pipeline is trained
3216  //Otherwise the user needs to train the pipeline
3218  trained = clusterer.getTrained();
3219  }else trained = false;
3220 
3221  return true;
3222 }
3223 
3224 bool GestureRecognitionPipeline::addPostProcessingModule(const PostProcessing &postProcessingModule,UINT insertIndex){
3225 
3226  //Validate the insertIndex is valid
3227  if( insertIndex != INSERT_AT_END_INDEX && insertIndex >= postProcessingModules.size() ){
3228  errorLog << "addPostProcessingModule((const PostProcessing &postProcessingModule) - Invalid insertIndex value!" << std::endl;
3229  return false;
3230  }
3231 
3232  //Create a new instance of the preProcessing and then clone the values across from the reference preProcessing
3233  PostProcessing *newInstance = postProcessingModule.createNewInstance();
3234 
3235  //Verify that the clone was successful
3236  if( !newInstance->deepCopyFrom( &postProcessingModule ) ){
3237  delete newInstance;
3238  newInstance = NULL;
3239  errorLog << "addPostProcessingModule(const PostProcessing &postProcessingModule) - PostProcessing Module Not Set!" << std::endl;
3240  return false;
3241  }
3242 
3243  //Add the new instance to the postProcessingModules
3244  Vector< PostProcessing* >::iterator iter = postProcessingModules.begin();
3245 
3246  if( insertIndex == INSERT_AT_END_INDEX ) iter = postProcessingModules.end();
3247  else iter = postProcessingModules.begin() + insertIndex;
3248 
3249  postProcessingModules.insert(iter, newInstance);
3250 
3251  //Note, we don't change the trained state of the pipeline for post processing modules, as they are added after the core ML module
3252 
3253  return true;
3254 }
3255 
3258  return addPostProcessingModule( postProcessingModule );
3259 }
3260 
3261 bool GestureRecognitionPipeline::addContextModule(const Context &contextModule,UINT contextLevel,UINT insertIndex){
3262 
3263  //Validate the contextLevel is valid
3264  if( contextLevel >= contextModules.size() ){
3265  errorLog << "addContextModule(...) - Invalid contextLevel value!" << std::endl;
3266  return false;
3267  }
3268 
3269  //Validate the insertIndex is valid
3270  if( insertIndex != INSERT_AT_END_INDEX && insertIndex >= contextModules[contextLevel].size() ){
3271  errorLog << "addContextModule(...) - Invalid insertIndex value!" << std::endl;
3272  return false;
3273  }
3274 
3275  //Create a new instance of the preProcessing and then clone the values across from the reference preProcessing
3276  Context *newInstance = contextModule.createNewInstance();
3277 
3278  //Verify that the clone was successful
3279  if( !newInstance->deepCopyFrom( &contextModule ) ){
3280  delete newInstance;
3281  newInstance = NULL;
3282  errorLog << "addContextModule(...) - Context Module Not Set!" << std::endl;
3283  return false;
3284  }
3285 
3286  //Add the new instance to the contextModules
3287  Vector< Context* >::iterator iter = contextModules[ contextLevel ].begin();
3288 
3289  if( insertIndex == INSERT_AT_END_INDEX ) iter = contextModules[ contextLevel ].end();
3290  else iter = contextModules[ contextLevel ].begin() + insertIndex;
3291 
3292  contextModules[ contextLevel ].insert(iter, newInstance);
3293 
3294  return true;
3295 }
3296 
3297 bool GestureRecognitionPipeline::updateContextModule(bool value,UINT contextLevel,UINT moduleIndex){
3298 
3299  //Validate the contextLevel is valid
3300  if( contextLevel >= contextModules.size() ){
3301  errorLog << "updateContextModule(...) - Context Level is out of bounds!" << std::endl;
3302  return false;
3303  }
3304 
3305  //Validate the moduleIndex is valid
3306  if( moduleIndex >= contextModules[contextLevel].size() ){
3307  errorLog << "updateContextModule(...) - Invalid contextLevel value!" << std::endl;
3308  return false;
3309  }
3310 
3311  return contextModules[contextLevel][moduleIndex]->updateContext( value );
3312 }
3313 
3315  deleteAllPreProcessingModules();
3316  return true;
3317 }
3318 
3320  if( moduleIndex >= preProcessingModules.size() ){
3321  errorLog << "removePreProcessingModule(UINT moduleIndex) - Invalid moduleIndex " << moduleIndex << ". The size of the preProcessingModules Vector is " << int(preProcessingModules.size()) << std::endl;
3322  return false;
3323  }
3324 
3325  //Delete the module
3326  delete preProcessingModules[ moduleIndex ];
3327  preProcessingModules[ moduleIndex ] = NULL;
3328  preProcessingModules.erase( preProcessingModules.begin() + moduleIndex );
3329 
3330  //The pipeline has been changed, so flag that the pipeline is no longer trained
3331  trained = false;
3332 
3333  return true;
3334 }
3335 
3337  deleteAllFeatureExtractionModules();
3338  return true;
3339 }
3340 
3342  if( moduleIndex >= featureExtractionModules.size() ){
3343  errorLog << "removeFeatureExtractionModule(UINT moduleIndex) - Invalid moduleIndex " << moduleIndex << ". The size of the featureExtractionModules Vector is " << int(featureExtractionModules.size()) << std::endl;
3344  return false;
3345  }
3346 
3347  //Delete the module
3348  delete featureExtractionModules[ moduleIndex ];
3349  featureExtractionModules[ moduleIndex ] = NULL;
3350  featureExtractionModules.erase( featureExtractionModules.begin() + moduleIndex );
3351 
3352  //The pipeline has been changed, so flag that the pipeline is no longer trained
3353  trained = false;
3354 
3355  return true;
3356 }
3357 
3359  deleteAllPostProcessingModules();
3360  return true;
3361 }
3362 
3364  if( moduleIndex >= postProcessingModules.size() ){
3365  errorLog << "removePostProcessingModule(UINT moduleIndex) - Invalid moduleIndex " << moduleIndex << ". The size of the postProcessingModules Vector is " << int(postProcessingModules.size()) << std::endl;
3366  return false;
3367  }
3368 
3369  //Delete the module
3370  delete postProcessingModules[ moduleIndex ];
3371  postProcessingModules[ moduleIndex ] = NULL;
3372  postProcessingModules.erase( postProcessingModules.begin() + moduleIndex );
3373 
3374  //The pipeline has been changed, so flag that the pipeline is no longer trained
3375  trained = false;
3376 
3377  return true;
3378 }
3379 
3380 bool GestureRecognitionPipeline::removeContextModule(UINT contextLevel,UINT moduleIndex){
3381  if( contextLevel >= NUM_CONTEXT_LEVELS ){
3382  errorLog << "removeContextModule(UINT contextLevel,UINT moduleIndex) - Invalid moduleIndex " << moduleIndex << " is out of bounds!" << std::endl;
3383  return false;
3384  }
3385 
3386  if( moduleIndex >= contextModules[contextLevel].size() ){
3387  errorLog << "removePostProcessingModule(UINT moduleIndex) - Invalid moduleIndex " << moduleIndex << ". The size of the contextModules Vector at context level " << " is " << int(contextModules[contextLevel].size()) << std::endl;
3388  return false;
3389  }
3390 
3391  //Delete the module
3392  delete contextModules[contextLevel][moduleIndex];
3393  contextModules[contextLevel][moduleIndex] = NULL;
3394  contextModules[contextLevel].erase( contextModules[contextLevel].begin() + moduleIndex );
3395  return true;
3396 }
3397 
3399  deleteAllContextModules();
3400  return true;
3401 }
3402 
3404 
3405  numTestSamples = 0;
3406  testAccuracy = 0;
3407  testRMSError = 0;
3408  testSquaredError = 0;
3409  testTime = 0;
3410  testFMeasure.clear();
3411  testPrecision.clear();
3412  testRecall.clear();
3413  testRejectionPrecision = 0;
3414  testRejectionRecall = 0;
3415  testConfusionMatrix.clear();
3416  testResults.clear();
3417  crossValidationResults.clear();
3418 
3419  return true;
3420 }
3421 
3422 bool GestureRecognitionPipeline::setInfo(const std::string &info){
3423  this->info = info;
3424  return true;
3425 }
3426 
3430 
3431 void GestureRecognitionPipeline::deleteAllPreProcessingModules(){
3432  if( preProcessingModules.size() != 0 ){
3433  for(UINT i=0; i<preProcessingModules.size(); i++){
3434  delete preProcessingModules[i];
3435  preProcessingModules[i] = NULL;
3436  }
3437  preProcessingModules.clear();
3438  trained = false;
3439  }
3440 }
3441 
3442 void GestureRecognitionPipeline::deleteAllFeatureExtractionModules(){
3443  if( featureExtractionModules.size() != 0 ){
3444  for(UINT i=0; i<featureExtractionModules.size(); i++){
3445  delete featureExtractionModules[i];
3446  featureExtractionModules[i] = NULL;
3447  }
3448  featureExtractionModules.clear();
3449  trained = false;
3450  }
3451 }
3452 
3453 void GestureRecognitionPipeline::deleteClassifier(){
3454  if( classifier != NULL ){
3455  delete classifier;
3456  classifier = NULL;
3457  }
3458  trained = false;
3459  initialized = false;
3460 }
3461 
3462 void GestureRecognitionPipeline::deleteRegressifier(){
3463  if( regressifier != NULL ){
3464  delete regressifier;
3465  regressifier = NULL;
3466  }
3467  trained = false;
3468  initialized = false;
3469 }
3470 
3471 void GestureRecognitionPipeline::deleteClusterer(){
3472  if( clusterer != NULL ){
3473  delete clusterer;
3474  clusterer = NULL;
3475  }
3476  trained = false;
3477  initialized = false;
3478 }
3479 
3480 void GestureRecognitionPipeline::deleteAllPostProcessingModules(){
3481  if( postProcessingModules.size() != 0 ){
3482  for(UINT i=0; i<postProcessingModules.size(); i++){
3483  delete postProcessingModules[i];
3484  postProcessingModules[i] = NULL;
3485  }
3486  postProcessingModules.clear();
3487  trained = false;
3488  }
3489 }
3490 
3491 void GestureRecognitionPipeline::deleteAllContextModules(){
3492  for(UINT i=0; i<contextModules.size(); i++){
3493  for(UINT j=0; j<contextModules[i].size(); j++){
3494  delete contextModules[i][j];
3495  contextModules[i][j] = NULL;
3496  }
3497  contextModules[i].clear();
3498  }
3499 }
3500 
3501 bool GestureRecognitionPipeline::init(){
3502  initialized = false;
3503  trained = false;
3504  info = "";
3505  pipelineMode = PIPELINE_MODE_NOT_SET;
3506  inputVectorDimensions = 0;
3507  outputVectorDimensions = 0;
3508  predictedClassLabel = 0;
3509  predictedClusterLabel = 0;
3510  predictionModuleIndex = 0;
3511  numTrainingSamples = 0;
3512  numTestSamples = 0;
3513  testAccuracy = 0;
3514  testRMSError = 0;
3515  testSquaredError = 0;
3516  testRejectionPrecision = 0;
3517  testRejectionRecall = 0;
3518  testTime = 0;
3519  trainingTime = 0;
3520  classifier = NULL;
3521  regressifier = NULL;
3522  clusterer = NULL;
3523  contextModules.resize( NUM_CONTEXT_LEVELS );
3524  return true;
3525 }
3526 
3527 bool GestureRecognitionPipeline::updateTestMetrics(const UINT classLabel,const UINT predictedClassLabel,VectorFloat &precisionCounter,VectorFloat &recallCounter,Float &rejectionPrecisionCounter,Float &rejectionRecallCounter,VectorFloat &confusionMatrixCounter){
3528 
3529  const bool nullRejectionEnabled = classifier->getNullRejectionEnabled();
3530 
3531  //Find the index of the classLabel
3532  UINT predictedClassLabelIndex =0;
3533  bool predictedClassLabelIndexFound = false;
3534  for(UINT k=0; k<getNumClassesInModel(); k++){
3535  if( predictedClassLabel == classifier->getClassLabels()[k] ){
3536  predictedClassLabelIndex = k;
3537  predictedClassLabelIndexFound = true;
3538  break;
3539  }
3540  }
3541 
3542  if( !predictedClassLabelIndexFound && (nullRejectionEnabled == false || predictedClassLabel != GRT_DEFAULT_NULL_CLASS_LABEL) ){
3543  errorLog << "Failed to find class label index for label: " << predictedClassLabel << std::endl;
3544  return false;
3545  }
3546 
3547  //Find the index of the class label
3548  UINT actualClassLabelIndex = 0;
3549  for(UINT k=0; k<getNumClassesInModel(); k++){
3550  if( classLabel == classifier->getClassLabels()[k] ){
3551  actualClassLabelIndex = k;
3552  break;
3553  }
3554  }
3555 
3556  //Update the classification accuracy
3557  if( classLabel == predictedClassLabel ){
3558  testAccuracy++;
3559  }
3560 
3561  if( nullRejectionEnabled == false ){
3562 
3563  //Update the precision
3564  if( classLabel == predictedClassLabel ){
3565  //Update the precision value
3566  testPrecision[ predictedClassLabelIndex ]++;
3567  }
3568  //Update the precision counter
3569  precisionCounter[ predictedClassLabelIndex ]++;
3570 
3571  //Update the recall
3572  if( classLabel == predictedClassLabel ){
3573  //Update the recall value
3574  testRecall[ predictedClassLabelIndex ]++;
3575  }
3576  //Update the recall counter
3577  recallCounter[ actualClassLabelIndex ]++;
3578 
3579  //Update the confusion matrix
3580  testConfusionMatrix[ actualClassLabelIndex ][ predictedClassLabelIndex ]++;
3581  confusionMatrixCounter[ actualClassLabelIndex ]++;
3582 
3583  }else{ //Null rejection is enabled
3584  //Update the precision
3585  if( predictedClassLabel != GRT_DEFAULT_NULL_CLASS_LABEL ){
3586  if( classLabel == predictedClassLabel ){
3587  //Update the precision value
3588  testPrecision[ predictedClassLabelIndex ]++;
3589  }
3590  //Update the precision counter
3591  precisionCounter[ predictedClassLabelIndex ]++;
3592  }
3593 
3594  //Update the recall
3595  if( classLabel != GRT_DEFAULT_NULL_CLASS_LABEL ){
3596  if( classLabel == predictedClassLabel ){
3597  //Update the recall value
3598  testRecall[ predictedClassLabelIndex ]++;
3599  }
3600  //Update the recall counter
3601  recallCounter[ actualClassLabelIndex ]++;
3602  }
3603 
3604  //Update the rejection precision
3605  if( predictedClassLabel == GRT_DEFAULT_NULL_CLASS_LABEL ){
3606  if( classLabel == GRT_DEFAULT_NULL_CLASS_LABEL ) testRejectionPrecision++;
3607  rejectionPrecisionCounter++;
3608  }
3609 
3610  //Update the rejection recall
3611  if( classLabel == GRT_DEFAULT_NULL_CLASS_LABEL ){
3612  if( predictedClassLabel == GRT_DEFAULT_NULL_CLASS_LABEL ) testRejectionRecall++;
3613  rejectionRecallCounter++;
3614  }
3615 
3616  //Update the confusion matrix
3617  if( classLabel == GRT_DEFAULT_NULL_CLASS_LABEL ) actualClassLabelIndex = 0;
3618  else actualClassLabelIndex++;
3619  if( predictedClassLabel == GRT_DEFAULT_NULL_CLASS_LABEL ) predictedClassLabelIndex = 0;
3620  else predictedClassLabelIndex++;
3621  testConfusionMatrix[ actualClassLabelIndex ][ predictedClassLabelIndex ]++;
3622  confusionMatrixCounter[ actualClassLabelIndex ]++;
3623  }
3624 
3625  return true;
3626 }
3627 
3628 bool GestureRecognitionPipeline::computeTestMetrics(VectorFloat &precisionCounter,VectorFloat &recallCounter,Float &rejectionPrecisionCounter,Float &rejectionRecallCounter,VectorFloat &confusionMatrixCounter,const UINT numTestSamples){
3629 
3630  //Compute the test metrics
3631  testAccuracy = testAccuracy/Float(numTestSamples) * 100.0;
3632 
3633  for(UINT k=0; k<getNumClassesInModel(); k++){
3634  if( precisionCounter[k] > 0 ) testPrecision[k] /= precisionCounter[k];
3635  else testPrecision[k] = 0;
3636  if( recallCounter[k] > 0 ) testRecall[k] /= recallCounter[k];
3637  else testRecall[k] = 0;
3638 
3639  if( precisionCounter[k] + recallCounter[k] > 0 )
3640  testFMeasure[k] = 2 * ((testPrecision[k]*testRecall[k])/(testPrecision[k]+testRecall[k]));
3641  else testFMeasure[k] = 0;
3642  }
3643  if( rejectionPrecisionCounter > 0 ) testRejectionPrecision /= rejectionPrecisionCounter;
3644  if( rejectionRecallCounter > 0 ) testRejectionRecall /= rejectionRecallCounter;
3645 
3646 
3647  for(UINT r=0; r<confusionMatrixCounter.size(); r++){
3648  if( confusionMatrixCounter[r] > 0 ){
3649  for(UINT c=0; c<testConfusionMatrix.getNumCols(); c++){
3650  testConfusionMatrix[r][c] /= confusionMatrixCounter[r];
3651  }
3652  }
3653  }
3654 
3655  return true;
3656 }
3657 
3659  std::string model = "";
3660 
3661  switch( pipelineMode ){
3662  case PIPELINE_MODE_NOT_SET:
3663  break;
3664  case CLASSIFICATION_MODE:
3665  if( getIsClassifierSet() ){
3666  model += "Classifier: " + classifier->getClassifierType() + "\n";
3667  model += classifier->getModelAsString();
3668  }
3669  break;
3670  case REGRESSION_MODE:
3671  if( getIsRegressifierSet() ){
3672  model += "Regressifier: " + regressifier->getRegressifierType() + "\n";
3673  model += regressifier->getModelAsString();
3674  }
3675  break;
3676  default:
3677  break;
3678  }
3679 
3680  return model;
3681 }
3682 
3684  switch( pipelineMode ){
3685  case PIPELINE_MODE_NOT_SET:
3686  return "PIPELINE_MODE_NOT_SET";
3687  break;
3688  case CLASSIFICATION_MODE:
3689  return "CLASSIFICATION_MODE";
3690  break;
3691  case REGRESSION_MODE:
3692  return "REGRESSION_MODE";
3693  break;
3694  default:
3695  return "ERROR_UNKNWON_PIPELINE_MODE";
3696  break;
3697  }
3698 
3699  return "ERROR_UNKNWON_PIPELINE_MODE";
3700 }
3701 
3702 std::string GestureRecognitionPipeline::getInfo() const{
3703  return info;
3704 }
3705 
3706 UINT GestureRecognitionPipeline::getPipelineModeFromString(std::string pipelineModeAsString) const{
3707  if( pipelineModeAsString == "PIPELINE_MODE_NOT_SET" ){
3708  return PIPELINE_MODE_NOT_SET;
3709  }
3710  if( pipelineModeAsString == "CLASSIFICATION_MODE" ){
3711  return CLASSIFICATION_MODE;
3712  }
3713  if( pipelineModeAsString == "REGRESSION_MODE" ){
3714  return REGRESSION_MODE;
3715  }
3716  return PIPELINE_MODE_NOT_SET;
3717 }
3718 
3719 GRT_END_NAMESPACE
3720 
bool removePostProcessingModule(const UINT moduleIndex)
void clear()
Definition: Matrix.h:522
bool spiltDataIntoKFolds(const UINT K, const bool useStratifiedSampling=false)
virtual bool predict(VectorFloat inputVector)
Definition: MLBase.cpp:112
GestureRecognitionPipeline & operator<<(const PreProcessing &module)
static std::string toString(const int &i)
Definition: Util.cpp:73
virtual bool deepCopyFrom(const PostProcessing *postProcessing)
Definition: Timer.h:43
bool addSample(const VectorFloat &sample)
bool train(const ClassificationData &trainingData)
virtual bool deepCopyFrom(const PreProcessing *rhs)
Definition: PreProcessing.h:57
virtual bool predict_(VectorFloat &inputVector)
Definition: MLBase.cpp:114
bool addSample(UINT classLabel, const VectorFloat &sample)
Vector< UINT > getClassLabels() const
Definition: Classifier.cpp:222
ClassificationData getTestFoldData(const UINT foldIndex) const
VectorFloat getNullRejectionThresholds() const
Definition: Classifier.cpp:217
bool removeContextModule(const UINT contextLevel, const UINT moduleIndex)
PreProcessing * createNewInstance() const
std::string getClassifierType() const
Definition: Classifier.cpp:160
Vector< ClassTracker > getClassTracker() const
virtual UINT getNumClasses() const
Definition: Classifier.cpp:190
VectorFloat getClusterLikelihoods() const
Definition: Clusterer.cpp:247
bool getTimeseriesCompatible() const
Definition: Classifier.h:243
std::string getClustererType() const
Definition: Clusterer.cpp:259
bool resetPlaybackIndex(const UINT playbackIndex)
UINT getNumDimensions() const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
bool setNumDimensions(UINT numDimensions)
RegressionData getTrainingFoldData(const UINT foldIndex) const
virtual bool train(ClassificationData trainingData)
Definition: MLBase.cpp:88
virtual bool deepCopyFrom(const Clusterer *clusterer)
Definition: Clusterer.h:58
bool getTrained() const
Definition: MLBase.cpp:254
Float getRootMeanSquaredTrainingError() const
Definition: MLBase.cpp:234
UINT getNumSamples() const
virtual bool reset()
UINT getNumOutputDimensions() const
Definition: MLBase.cpp:209
Regressifier * createNewInstance() const
T * getData() const
Definition: Matrix.h:583
bool addContextModule(const Context &contextModule, UINT contextLevel, UINT insertIndex=INSERT_AT_END_INDEX)
bool preProcessData(VectorFloat inputVector, bool computeFeatures=true)
static Regressifier * createInstanceFromString(const std::string &regressifierType)
bool setRegressifier(const Regressifier &regressifier)
UINT getNumInputDimensions() const
bool setAllowNullGestureClass(bool allowNullGestureClass)
bool removeFeatureExtractionModule(UINT moduleIndex)
static std::string intToString(const int &i)
Definition: Util.cpp:61
std::string getLastErrorMessage() const
Definition: GRTBase.cpp:54
bool setClassifier(const Classifier &classifier)
signed long getMilliSeconds()
Definition: Timer.h:117
unsigned int getSize() const
Definition: Vector.h:193
Vector< TestInstanceResult > getTestInstanceResults() const
This file contains the GestureRecognitionPipeline class.
static PreProcessing * createInstanceFromString(std::string const &preProcessingType)
bool setAllValues(const T &value)
Definition: Matrix.h:336
bool setInputAndTargetDimensions(const UINT numInputDimensions, const UINT numTargetDimensions)
virtual bool deepCopyFrom(const Regressifier *regressifier)
Definition: Regressifier.h:63
virtual bool deepCopyFrom(const Classifier *classifier)
Definition: Classifier.h:61
bool predict(const VectorFloat &inputVector)
UINT getNumSamples() const
bool load(const std::string &filename)
UINT getNumTargetDimensions() const
ClassificationSample getNextSample()
bool spiltDataIntoKFolds(const UINT K, const bool useStratifiedSampling=false)
Float getTotalSquaredTrainingError() const
Definition: MLBase.cpp:238
Vector< UINT > getClusterLabels() const
Definition: Clusterer.cpp:255
bool addPreProcessingModule(const PreProcessing &preProcessingModule, UINT insertIndex=INSERT_AT_END_INDEX)
bool getNullRejectionEnabled() const
Definition: Classifier.cpp:168
bool setClusterer(const Clusterer &clusterer)
Float getPhase() const
Definition: Classifier.cpp:181
std::string getRegressifierType() const
UINT getPredictedClassLabel() const
Definition: Classifier.cpp:202
GestureRecognitionPipeline & operator=(const GestureRecognitionPipeline &rhs)
virtual bool saveModelToFile(std::string filename) const
Definition: MLBase.cpp:146
FeatureExtraction * createNewInstance() const
bool savePipelineToFile(const std::string &filename) const
UINT getPipelineModeFromString(std::string pipelineMode) const
virtual bool reset()
Definition: Clusterer.cpp:127
static Classifier * createInstanceFromString(std::string const &classifierType)
Definition: Classifier.cpp:28
bool save(const std::string &filename) const
bool reserve(const UINT N)
unsigned int getNumRows() const
Definition: Matrix.h:542
UINT getNumDimensions() const
UINT getNumClasses() const
virtual std::string getModelAsString() const
Definition: MLBase.cpp:187
unsigned int getNumCols() const
Definition: Matrix.h:549
UINT getPredictedClusterLabel() const
Definition: Clusterer.cpp:236
Context * getContextModule(const UINT contextLevel, const UINT moduleIndex) const
virtual bool loadModelFromFile(std::string filename)
Definition: MLBase.cpp:168
Float getMaximumLikelihood() const
Definition: Classifier.cpp:176
Context * createNewInstance() const
Definition: Context.cpp:37
bool setFeatureExtractionModule(const FeatureExtraction &featureExtractionModule)
bool addFeatureExtractionModule(const FeatureExtraction &featureExtractionModule, UINT insertIndex=INSERT_AT_END_INDEX)
bool start()
Definition: Timer.h:64
bool loadPipelineFromFile(const std::string &filename)
virtual bool reset()
Definition: Classifier.cpp:122
UINT getNumInputFeatures() const
Definition: MLBase.cpp:205
Vector< TestResult > getCrossValidationResults() const
FeatureExtraction * getFeatureExtractionModule(const UINT moduleIndex) const
bool setInfo(const std::string &info)
bool map(const VectorFloat &inputVector)
VectorFloat getRow(const unsigned int r) const
Definition: MatrixFloat.h:100
VectorFloat getClassDistances() const
Definition: Classifier.cpp:212
virtual bool train_(ClassificationData &trainingData)
Definition: MLBase.cpp:90
bool notifyTestResultsObservers(const TestInstanceResult &data)
Definition: MLBase.cpp:354
bool addPostProcessingModule(const PostProcessing &postProcessingModule, UINT insertIndex=INSERT_AT_END_INDEX)
bool removePreProcessingModule(UINT moduleIndex)
UINT getNumClusters() const
Definition: Clusterer.cpp:234
bool updateContextModule(bool value, UINT contextLevel=0, UINT moduleIndex=0)
VectorFloat getClassLikelihoods() const
Definition: Classifier.cpp:207
bool setPostProcessingModule(const PostProcessing &postProcessingModule)
virtual bool train_(MatrixFloat &trainingData)
Definition: Clusterer.cpp:113
static PostProcessing * createInstanceFromString(std::string const &postProcessingType)
VectorFloat getRegressionData() const
PostProcessing * getPostProcessingModule(UINT moduleIndex) const
#define INSERT_AT_END_INDEX
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:232
PreProcessing * getPreProcessingModule(const UINT moduleIndex) const
VectorFloat getUnProcessedRegressionData() const
UINT getNumInputDimensions() const
Definition: MLBase.cpp:207
static Clusterer * createInstanceFromString(std::string const &ClustererType)
Definition: Clusterer.cpp:28
VectorFloat getClusterDistances() const
Definition: Clusterer.cpp:251
ClassificationData getTrainingFoldData(const UINT foldIndex) const
RegressionData getTestFoldData(const UINT foldIndex) const
bool test(const ClassificationData &testData)
bool push_back(const Vector< T > &sample)
Definition: Matrix.h:401
virtual bool clear()
Definition: Clusterer.cpp:141
virtual bool clear()
Definition: Classifier.cpp:141
TimeSeriesClassificationData getTrainingFoldData(const UINT foldIndex) const
Float getMaximumLikelihood() const
Definition: Clusterer.cpp:239
bool setPreProcessingModule(const PreProcessing &preProcessingModule)
bool addSample(const VectorFloat &inputVector, const VectorFloat &targetVector)
virtual bool deepCopyFrom(const FeatureExtraction *rhs)
Classifier * createNewInstance() const
Definition: Classifier.cpp:36
bool spiltDataIntoKFolds(const UINT K)
UINT getNumSamples() const
virtual bool clear()
Clusterer * createNewInstance() const
Definition: Clusterer.cpp:36
PostProcessing * createNewInstance() const
TimeSeriesClassificationData getTestFoldData(const UINT foldIndex) const