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.
FiniteStateMachine.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 
21 #include "FiniteStateMachine.h"
22 
23 GRT_BEGIN_NAMESPACE
24 
25 //Register the FiniteStateMachine module with the Classifier base class
26 RegisterClassifierModule< FiniteStateMachine > FiniteStateMachine::registerModule("FiniteStateMachine");
27 
28 FiniteStateMachine::FiniteStateMachine(const UINT numParticles,const UINT numClustersPerState,const Float stateTransitionSmoothingCoeff,const Float measurementNoise)
29 {
30  this->numParticles = numParticles;
31  this->numClustersPerState = numClustersPerState;
32  this->stateTransitionSmoothingCoeff = stateTransitionSmoothingCoeff;
33  this->measurementNoise = measurementNoise;
34  classType = "FiniteStateMachine";
35  classifierType = classType;
36  classifierMode = TIMESERIES_CLASSIFIER_MODE;
37  debugLog.setProceedingText("[DEBUG FiniteStateMachine]");
38  errorLog.setProceedingText("[ERROR FiniteStateMachine]");
39  trainingLog.setProceedingText("[TRAINING FiniteStateMachine]");
40  warningLog.setProceedingText("[WARNING FiniteStateMachine]");
41 
42  //Set the learning settings that will be used to build the KMeans model
43  minChange = 1.0e-5;
44  minNumEpochs = 0;
45  maxNumEpochs = 1000;
46 }
47 
49  classType = "FiniteStateMachine";
50  classifierType = classType;
51  classifierMode = STANDARD_CLASSIFIER_MODE;
52  debugLog.setProceedingText("[DEBUG FiniteStateMachine]");
53  errorLog.setProceedingText("[ERROR FiniteStateMachine]");
54  trainingLog.setProceedingText("[TRAINING FiniteStateMachine]");
55  warningLog.setProceedingText("[WARNING FiniteStateMachine]");
56  *this = rhs;
57 }
58 
60 {
61 }
62 
64  if( this != &rhs ){
65 
66  this->clear();
67 
68  //Classifier variables
69  copyBaseVariables( (Classifier*)&rhs );
70 
71  //Copy the FiniteStateMachine variable
72  this->numParticles = rhs.numParticles;
73  this->numClustersPerState = rhs.numClustersPerState;
74  this->stateTransitionSmoothingCoeff = rhs.stateTransitionSmoothingCoeff;
75  this->measurementNoise = rhs.measurementNoise;
76  this->particles = rhs.particles;
77  this->stateTransitions = rhs.stateTransitions;
78  this->stateEmissions = rhs.stateEmissions;
79 
80  if( rhs.trained ){
81  this->initParticles();
82  }
83  }
84  return *this;
85 }
86 
88 
89  if( classifier == NULL ) return false;
90 
91  if( this->getClassifierType() == classifier->getClassifierType() ){
92 
93  FiniteStateMachine *ptr = (FiniteStateMachine*)classifier;
94 
95  this->clear();
96 
97  //Clone the classifier variables
98  if( !copyBaseVariables( classifier ) ){
99  errorLog << "deepCopyFrom(const Classifier *classifier) - Failed to deep copy classifier base class!" << std::endl;
100  return false;
101  }
102 
103  this->numParticles = ptr->numParticles;
104  this->numClustersPerState = ptr->numClustersPerState;
105  this->stateTransitionSmoothingCoeff = ptr->stateTransitionSmoothingCoeff;
106  this->measurementNoise = ptr->measurementNoise;
107  this->particles = ptr->particles;
108  this->stateTransitions = ptr->stateTransitions;
109  this->stateEmissions = ptr->stateEmissions;
110 
111  if( ptr->trained ){
112  this->initParticles();
113  }
114 
115  return true;
116  }
117  return false;
118 }
119 
121 
122  const unsigned int M = trainingData.getNumSamples();
123  const unsigned int N = trainingData.getNumDimensions();
124 
125  if( M == 0 ){
126  errorLog << "train_(ClassificationData &trainingData) - Training data has zero samples!" << std::endl;
127  clear();
128  return false;
129  }
130 
131  //Convert the classification data into a continuous time stream
133  timeseries.setNumDimensions( N );
134 
135  for(unsigned int i=0; i<M; i++){
136  timeseries.addSample(trainingData[i].getClassLabel(), trainingData[i].getSample());
137  }
138 
139  //Train the particle filter
140  if( !train_( timeseries ) ){
141  clear();
142  errorLog << "train_(ClassificationData &trainingData) - Failed to train particle filter!" << std::endl;
143  return false;
144  }
145 
146  return true;
147 }
148 
150 
151  const unsigned int M = trainingData.getNumSamples();
152  const unsigned int N = trainingData.getNumDimensions();
153 
154  if( M == 0 ){
155  errorLog << "train_(TimeSeriesClassificationData &trainingData) - Training data has zero samples!" << std::endl;
156  clear();
157  return false;
158  }
159 
160  //Convert the timeseries classification data into a continuous time stream
162  timeseries.setNumDimensions( N );
163 
164  for(unsigned int i=0; i<M; i++){
165  for(unsigned int j=0; j<trainingData[i].getLength(); j++){
166  timeseries.addSample(trainingData[i].getClassLabel(), trainingData[i].getData().getRow(j));
167  }
168  }
169 
170  //Train the particle filter
171  if( !train_( timeseries ) ){
172  clear();
173  errorLog << "train_(TimeSeriesClassificationData &trainingData) - Failed to train particle filter!" << std::endl;
174  return false;
175  }
176 
177  return true;
178 }
179 
181 
182  //Clear any previous model
183  clear();
184 
185  const UINT M = data.getNumSamples();
186  const UINT N = data.getNumDimensions();
187  const UINT K = data.getNumClasses();
188 
189  if( M == 0 ){
190  return false;
191  }
192 
193  numInputDimensions = N;
194  numClasses = K;
195  ranges = data.getRanges();
196 
197  //Scale the training data if needed
198  if( useScaling ){
199  //Scale the training data between 0 and 1
200  data.scale(0, 1);
201  }
202 
203  stateTransitions.resize(K, K);
204  stateTransitions.setAllValues(0);
205 
206  //Get a copy of the class labels, each class label is a state
207  classLabels = data.getClassLabels();
208 
209  //Count how many times we transitiion from one state to another
210  UINT lastStateIndex = getClassLabelIndexValue( data[0].getClassLabel() );
211  UINT currentStateIndex = 0;
212  for(UINT i=1; i<data.getNumSamples(); i++){
213  currentStateIndex = getClassLabelIndexValue( data[i].getClassLabel() );
214  stateTransitions[ lastStateIndex ][ currentStateIndex ]++;
215  lastStateIndex = currentStateIndex;
216  }
217 
218  //Normalize the state transitions
219  Float sum = 0;
220  for(UINT i=0; i<K; i++){
221  sum = 0;
222  for(UINT j=0; j<K; j++){
223  sum += stateTransitions[i][j] + stateTransitionSmoothingCoeff;
224  }
225  for(UINT j=0; j<K; j++){
226  stateTransitions[i][j] /= sum;
227  }
228  }
229 
230  //Build the state emissions model for each state
231  for(UINT k=0; k<K; k++){
232 
233  //Get the data that belongs to the current state
234  MatrixFloat classData;
235  for(UINT i=0; i<M; i++){
236  if( data[i].getClassLabel() == classLabels[k] ){
237  classData.push_back( data[i].getSample() );
238  }
239  }
240 
241  //Make sure there are enough training samples to support the numClustersPerState
242  if( classData.getNumRows() < numClustersPerState ){
243  errorLog << "train_(TimeSeriesClassificationDataStream &trainingData) - There are not enough samples in state " << classLabels[k] << "! You should reduce the numClustersPerState to: " << classData.getNumRows() << std::endl;
244  clear();
245  return false;
246  }
247 
248  //Use KMeans to find a clusters within the state data
249  KMeans kmeans;
250  kmeans.setNumClusters( numClustersPerState );
251  kmeans.setMinChange( minChange );
252  kmeans.setMinNumEpochs( minNumEpochs );
253  kmeans.setMaxNumEpochs( maxNumEpochs );
254 
255  if( !kmeans.train_( classData ) ){
256  errorLog << "train_(TimeSeriesClassificationDataStream &trainingData) - Failed to train kmeans cluster for class k: " << classLabels[k] << std::endl;
257  clear();
258  return false;
259  }
260 
261  //Add the clusters for this state to the stateEmissions vector
262  stateEmissions.push_back( kmeans.getClusters() );
263  }
264 
265  //Flag the model is trained
266  trained = true;
267 
268  //Init the particles
269  initParticles();
270 
271  //Reset the particles to random starting states
272  reset();
273 
274  print();
275 
276  return true;
277 }
278 
280 
281  if( !trained ){
282  errorLog << "predict_(VectorFloat &inputVector) - Model Not Trained!" << std::endl;
283  return false;
284  }
285 
286  predictedClassLabel = 0;
287  maxLikelihood = -10000;
288 
289  if( inputVector.size() != numInputDimensions ){
290  errorLog << "predict_(VectorFloat &inputVector) - The size of the input vector (" << inputVector.size() << ") does not match the num features in the model (" << numInputDimensions << std::endl;
291  return false;
292  }
293 
294  if( useScaling ){
295  for(UINT n=0; n<numInputDimensions; n++){
296  inputVector[n] = scale(inputVector[n], ranges[n].minValue, ranges[n].maxValue, 0, 1);
297  }
298  }
299 
300  if( classLikelihoods.size() != numClasses ) classLikelihoods.resize(numClasses,0);
301  if( classDistances.size() != numClasses ) classDistances.resize(numClasses,0);
302 
303  std::fill(classLikelihoods.begin(),classLikelihoods.end(),0);
304  std::fill(classDistances.begin(),classDistances.end(),0);
305 
306  //Update the particle filter
307  particles.filter( inputVector );
308 
309  //Compute the state estimation
310  Float sum = 0;
311  for(UINT i=0; i<numParticles; i++){
312  sum += particles[i].w;
313  classLikelihoods[ particles[i].currentState ] += particles[i].w;
314  classDistances[ particles[i].currentState ] += particles[i].w;
315  }
316 
317  //Normalize the class likelihoods
318  maxLikelihood = 0;
319  predictedClassLabel = 0;
320  for(UINT i=0; i<numClasses; i++){
321  classLikelihoods[ i ] /= sum;
322 
323  if( classLikelihoods[i] > maxLikelihood ){
324  maxLikelihood = classLikelihoods[i];
325  predictedClassLabel = classLabels[i];
326  }
327  }
328 
329  return true;
330 }
331 
333 
334  if( trained ){
335  //Randomize the particles starting states
336  for(UINT i=0; i<numParticles; i++){
337  particles[i].currentState = random.getRandomNumberInt(0, numClasses);
338  particles[i].w = 0;
339  }
340  }
341 
342  return true;
343 }
344 
346 
347  //Clear the Classifier variables
349 
350  //Clear the model
351  stateTransitions.clear();
352  stateEmissions.clear();
353  pt.clear();
354  pe.clear();
355  particles.clear();
356 
357  return true;
358 }
359 
361 
362  infoLog << "FiniteStateMachineModel" << std::endl;
363  infoLog << "NumParticles: " << numParticles << std::endl;
364  infoLog << "NumClustersPerState: " << numClustersPerState << std::endl;
365  infoLog << "StateTransitionSmoothingCoeff: " << stateTransitionSmoothingCoeff << std::endl;
366 
367  if( trained ){
368  infoLog << "StateTransitions: " << std::endl;
369  for(unsigned int i=0; i<stateTransitions.getNumRows(); i++){
370  for(unsigned int j=0; j<stateTransitions.getNumCols(); j++){
371  infoLog << stateTransitions[i][j] << " ";
372  }
373  infoLog << std::endl;
374  }
375 
376  infoLog << "StateEmissions: " << std::endl;
377  for(unsigned int k=0; k<stateEmissions.size(); k++){
378  for(unsigned int i=0; i<stateEmissions[k].getNumRows(); i++){
379  for(unsigned int j=0; j<stateEmissions[k].getNumCols(); j++){
380  infoLog << stateEmissions[k][i][j] << " ";
381  }
382  infoLog << std::endl;
383  }
384  }
385  }
386 
387  return true;
388 }
389 
390 bool FiniteStateMachine::saveModelToFile( std::fstream &file ) const{
391 
392  if(!file.is_open())
393  {
394  errorLog <<"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
395  return false;
396  }
397 
398  //Write the header info
399  file << "GRT_FSM_MODEL_FILE_V1.0\n";
400 
401  //Write the classifier settings to the file
403  errorLog << "saveModelToFile(fstream &file) - Failed to save classifier base settings to file!" << std::endl;
404  return false;
405  }
406 
407  file << "NumParticles: " << numParticles << std::endl;
408  file << "NumClustersPerState: " << numClustersPerState << std::endl;
409  file << "StateTransitionSmoothingCoeff: " << stateTransitionSmoothingCoeff << std::endl;
410 
411  if( trained ){
412  file << "StateTransitions:" << std::endl;
413  for(unsigned int i=0; i<stateTransitions.getNumRows(); i++){
414  for(unsigned int j=0; j<stateTransitions.getNumCols(); j++){
415  file << stateTransitions[i][j] << " ";
416  }
417  file << std::endl;
418  }
419 
420  file << "StateEmissions:" << std::endl;
421  for(unsigned int k=0; k<numClasses; k++){
422  for(unsigned int i=0; i<stateEmissions[k].getNumRows(); i++){
423  for(unsigned int j=0; j<stateEmissions[k].getNumCols(); j++){
424  file << stateEmissions[k][i][j] << " ";
425  }
426  file << std::endl;
427  }
428  }
429 
430  if( !useScaling ){
431  file << "Ranges: " << std::endl;
432  for(UINT i=0; i<ranges.size(); i++){
433  file << ranges[i].minValue << "\t" << ranges[i].maxValue << std::endl;
434  }
435  }
436  }
437 
438  return true;
439 }
440 
441 bool FiniteStateMachine::loadModelFromFile( std::fstream &file ){
442 
443  //Clear any previous model
444  clear();
445 
446  if(!file.is_open())
447  {
448  errorLog << "loadModelFromFile(string filename) - Could not open file to load model" << std::endl;
449  return false;
450  }
451 
452  std::string word;
453 
454  //Find the file type header
455  file >> word;
456  if( word != "GRT_FSM_MODEL_FILE_V1.0" ){
457  errorLog << "loadModelFromFile(string filename) - Could not find Model File Header" << std::endl;
458  return false;
459  }
460 
461  //Load the base settings from the file
463  errorLog << "loadModelFromFile(string filename) - Failed to load base settings from file!" << std::endl;
464  return false;
465  }
466 
467  //Find the NumParticles header
468  file >> word;
469  if( word != "NumParticles:" ){
470  errorLog << "loadModelFromFile(string filename) - Could not find NumParticles Header" << std::endl;
471  return false;
472  }
473  file >> numParticles;
474 
475  //Find the NumClustersPerState header
476  file >> word;
477  if( word != "NumClustersPerState:" ){
478  errorLog << "loadModelFromFile(string filename) - Could not find NumClustersPerState Header" << std::endl;
479  return false;
480  }
481  file >> numClustersPerState;
482 
483  //Find the StateTransitionSmoothingCoeff header
484  file >> word;
485  if( word != "StateTransitionSmoothingCoeff:" ){
486  errorLog << "loadModelFromFile(string filename) - Could not find stateTransitionSmoothingCoeff Header" << std::endl;
487  return false;
488  }
489  file >> stateTransitionSmoothingCoeff;
490 
491  if( trained ){
492 
493  //Find the StateTransitions header
494  file >> word;
495  if( word != "StateTransitions:" ){
496  errorLog << "loadModelFromFile(string filename) - Could not find StateTransitions Header" << std::endl;
497  return false;
498  }
499  stateTransitions.resize(numClasses, numClasses);
500 
501  for(unsigned int i=0; i<stateTransitions.getNumRows(); i++){
502  for(unsigned int j=0; j<stateTransitions.getNumCols(); j++){
503  file >> stateTransitions[i][j];
504  }
505  }
506 
507  //Find the StateEmissions header
508  file >> word;
509  if( word != "StateEmissions:" ){
510  errorLog << "loadModelFromFile(string filename) - Could not find StateEmissions Header" << std::endl;
511  return false;
512  }
513  stateEmissions.resize( numClasses );
514 
515  for(unsigned int k=0; k<numClasses; k++){
516  stateEmissions[k].resize( numClustersPerState, numInputDimensions );
517  for(unsigned int i=0; i<stateEmissions[k].getNumRows(); i++){
518  for(unsigned int j=0; j<stateEmissions[k].getNumCols(); j++){
519  file >> stateEmissions[k][i][j];
520  }
521  }
522  }
523 
524  if( !useScaling ){
525  //Load if the Ranges
526  file >> word;
527  if( word != "Ranges:" ){
528  errorLog << "loadModelFromFile(string filename) - Failed to read Ranges header!" << std::endl;
529  clear();
530  return false;
531  }
532  ranges.resize(numInputDimensions);
533 
534  for(UINT i=0; i<ranges.size(); i++){
535  file >> ranges[i].minValue;
536  file >> ranges[i].maxValue;
537  }
538  }
539 
540  initParticles();
541  }
542 
543  return true;
544 }
545 
546 bool FiniteStateMachine::recomputePT(){
547 
548  if( !trained ){
549  warningLog << "recomputePT() - Failed to init particles, the model has not been trained!" << std::endl;
550  return false;
551  }
552 
553  pt.clear();
554 
555  //Build pt, this is simply the state transitions formated as indexed Floats to make the prediction stage more efficient
556  const UINT K = stateTransitions.getNumRows();
557  for(UINT i=0; i<K; i++){
558  Vector< IndexedDouble > model(K);
559  for(UINT j=0; j<K; j++){
560  model[j].index = j;
561  model[j].value = stateTransitions[i][j];
562  }
563  pt.push_back( model );
564  }
565 
566  return true;
567 }
568 
569 bool FiniteStateMachine::recomputePE(){
570 
571  if( !trained ){
572  warningLog << "recomputePE() - Failed to init particles, the model has not been trained!" << std::endl;
573  return false;
574  }
575 
576  pe.clear();
577 
578  const UINT K = stateEmissions.getSize();
579 
580  //Run over each state (k)
581  for(UINT k=0; k<K; k++){
582 
583  //For each state, convert the Matrix of emissions data to a vector of vectors (this format is more efficient for the particle filter)
584  Vector< VectorFloat > model;
585  model.reserve( numClustersPerState );
586  for(UINT i=0; i<stateEmissions[k].getNumRows(); i++){
587  model.push_back( stateEmissions[k].getRow(i) );
588  }
589 
590  pe.push_back( model );
591  }
592 
593  return true;
594 }
595 
596 bool FiniteStateMachine::initParticles(){
597 
598  if( !trained ){
599  warningLog << "initParticles() - Failed to init particles, the model has not been trained!" << std::endl;
600  return false;
601  }
602 
603  //Init the particles
604  Vector< VectorFloat > initModel( numInputDimensions, VectorFloat(2,0) );
605  VectorFloat initProcessNoise( numInputDimensions, 0 ); //Process noise is ignored for the FSM particle filter
606  VectorFloat initMeasurementNoise( numInputDimensions, 0 );
607 
608  //Setup the init model
609  for(unsigned int i=0; i<numInputDimensions; i++){
610  initModel[i][0] = useScaling ? 0 : ranges[i].minValue;
611  initModel[i][1] = useScaling ? 1 : ranges[i].maxValue;
612  }
613 
614  //Set the measurement noise
615  for(unsigned int i=0; i<numInputDimensions; i++){
616  initMeasurementNoise[i] = measurementNoise;
617  }
618 
619  particles.init(numParticles, initModel, initProcessNoise, initMeasurementNoise);
620 
621  recomputePT();
622  recomputePE();
623 
624  //Set the lookup table references
625  particles.setLookupTables( pt, pe );
626 
627  //Reset the particles
628  reset();
629 
630  return true;
631 }
632 
633 bool FiniteStateMachine::setNumParticles(const UINT numParticles){
634 
635  clear();
636 
637  this->numParticles = numParticles;
638 
639  return true;
640 }
641 
642 bool FiniteStateMachine::setNumClustersPerState(const UINT numClustersPerState){
643 
644  clear();
645 
646  this->numClustersPerState = numClustersPerState;
647 
648  return true;
649 }
650 
651 bool FiniteStateMachine::setStateTransitionSmoothingCoeff(const Float stateTransitionSmoothingCoeff){
652 
653  clear();
654 
655  this->stateTransitionSmoothingCoeff = stateTransitionSmoothingCoeff;
656 
657  return true;
658 }
659 
660 bool FiniteStateMachine::setMeasurementNoise(const Float measurementNoise){
661 
662  clear();
663 
664  this->measurementNoise = measurementNoise;
665 
666  return true;
667 }
668 
669 GRT_END_NAMESPACE
670 
void clear()
Definition: Matrix.h:522
bool saveBaseSettingsToFile(std::fstream &file) const
Definition: Classifier.cpp:255
virtual bool filter(SENSOR_DATA &data)
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
Definition: MLBase.h:339
std::string getClassifierType() const
Definition: Classifier.cpp:160
FiniteStateMachine(const UINT numParticles=200, const UINT numClustersPerState=20, const Float stateTransitionSmoothingCoeff=0.0, const Float measurementNoise=10.0)
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
virtual bool train_(MatrixFloat &data)
Definition: KMeans.cpp:162
virtual bool print() const
UINT getClassLabelIndexValue(UINT classLabel) const
Definition: Classifier.cpp:194
bool scale(const Float minTarget, const Float maxTarget)
bool setMinChange(const Float minChange)
Definition: MLBase.cpp:282
Vector< UINT > getClassLabels() const
unsigned int getSize() const
Definition: Vector.h:193
bool setAllValues(const T &value)
Definition: Matrix.h:336
UINT getNumSamples() const
virtual ~FiniteStateMachine(void)
virtual bool deepCopyFrom(const Classifier *classifier)
bool copyBaseVariables(const Classifier *classifier)
Definition: Classifier.cpp:92
Vector< Vector< IndexedDouble > > pt
This stores the stateTransitions matrix in a format more efficient for the particle filter...
bool loadBaseSettingsFromFile(std::fstream &file)
Definition: Classifier.cpp:302
unsigned int getNumRows() const
Definition: Matrix.h:542
UINT getNumDimensions() const
virtual bool clear()
unsigned int getNumCols() const
Definition: Matrix.h:549
bool addSample(const UINT classLabel, const VectorFloat &sample)
bool setMinNumEpochs(const UINT minNumEpochs)
Definition: MLBase.cpp:277
virtual bool train_(ClassificationData &trainingData)
virtual bool saveModelToFile(std::fstream &file) const
bool setNumDimensions(const UINT numDimensions)
int getRandomNumberInt(int minRange, int maxRange)
Definition: Random.h:88
Definition: KMeans.h:41
virtual bool predict_(VectorFloat &inputVector)
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:232
Vector< MinMax > getRanges() const
Vector< Vector< VectorFloat > > pe
This stores the stateEmissions model in a format more efficient for the particle filter.
virtual bool init(const unsigned int numParticles, const Vector< VectorFloat > &initModel, const VectorFloat &processNoise, const VectorFloat &measurementNoise)
bool setMaxNumEpochs(const UINT maxNumEpochs)
Definition: MLBase.cpp:268
bool push_back(const Vector< T > &sample)
Definition: Matrix.h:401
virtual bool clear()
Definition: Classifier.cpp:141
virtual bool loadModelFromFile(std::fstream &file)
FiniteStateMachine & operator=(const FiniteStateMachine &rhs)
bool setNumClusters(const UINT numClusters)
Definition: Clusterer.cpp:265