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