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.
ClusterTree.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 "ClusterTree.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register the ClusterTreeNode with the Node base class
27 RegisterNode< ClusterTreeNode > ClusterTreeNode::registerModule("ClusterTreeNode");
28 
29 //Register the ClusterTree module with the Clusterer base class
30 RegisterClustererModule< ClusterTree > ClusterTree::registerModule("ClusterTree");
31 
32 ClusterTree::ClusterTree(const UINT numSplittingSteps,const UINT minNumSamplesPerNode,const UINT maxDepth,const bool removeFeaturesAtEachSpilt,const UINT trainingMode,const bool useScaling,const Float minRMSErrorPerNode){
33  tree = NULL;
35  this->numSplittingSteps = numSplittingSteps;
36  this->minNumSamplesPerNode = minNumSamplesPerNode;
37  this->maxDepth = maxDepth;
38  this->removeFeaturesAtEachSpilt = removeFeaturesAtEachSpilt;
39  this->trainingMode = trainingMode;
40  this->minRMSErrorPerNode = minRMSErrorPerNode;
41  Clusterer::classType = "ClusterTree";
42  clustererType = Clusterer::classType;
43  Clusterer::debugLog.setProceedingText("[DEBUG ClusterTree]");
44  Clusterer::errorLog.setProceedingText("[ERROR ClusterTree]");
45  Clusterer::trainingLog.setProceedingText("[TRAINING ClusterTree]");
46  Clusterer::warningLog.setProceedingText("[WARNING ClusterTree]");
47 }
48 
50  tree = NULL;
52  Clusterer::classType = "ClusterTree";
53  clustererType = Clusterer::classType;
54  Clusterer::debugLog.setProceedingText("[DEBUG ClusterTree]");
55  Clusterer::errorLog.setProceedingText("[ERROR ClusterTree]");
56  Clusterer::trainingLog.setProceedingText("[TRAINING ClusterTree]");
57  Clusterer::warningLog.setProceedingText("[WARNING ClusterTree]");
58  *this = rhs;
59 }
60 
62 {
63  clear();
64 }
65 
67  if( this != &rhs ){
68  //Clear this tree
69  this->clear();
70 
71  if( rhs.getTrained() ){
72  //Deep copy the tree
73  this->tree = (ClusterTreeNode*)rhs.deepCopyTree();
74  }
75 
76  this->numSplittingSteps = rhs.numSplittingSteps;
77  this->minNumSamplesPerNode = rhs.minNumSamplesPerNode;
78  this->maxDepth = rhs.maxDepth;
79  this->removeFeaturesAtEachSpilt = rhs.removeFeaturesAtEachSpilt;
80  this->trainingMode = rhs.trainingMode;
81  this->minRMSErrorPerNode = rhs.minRMSErrorPerNode;
83 
84  //Copy the base variables
85  copyBaseVariables( (Clusterer*)&rhs );
86  }
87  return *this;
88 }
89 
90 bool ClusterTree::deepCopyFrom(const Clusterer *clusterer){
91 
92  if( clusterer == NULL ) return false;
93 
94  if( this->getClustererType() == clusterer->getClustererType() ){
95 
96  ClusterTree *ptr = (ClusterTree*)clusterer;
97 
98  //Clear this tree
99  this->clear();
100 
101  if( ptr->getTrained() ){
102  //Deep copy the tree
103  this->tree = (ClusterTreeNode*)ptr->deepCopyTree();
104  }
105 
106  this->numSplittingSteps = ptr->numSplittingSteps;
107  this->minNumSamplesPerNode = ptr->minNumSamplesPerNode;
108  this->maxDepth = ptr->maxDepth;
109  this->removeFeaturesAtEachSpilt = ptr->removeFeaturesAtEachSpilt;
110  this->trainingMode = ptr->trainingMode;
111  this->minRMSErrorPerNode = ptr->minRMSErrorPerNode;
113 
114  //Copy the base classifier variables
115  return copyBaseVariables( clusterer );
116  }
117  return false;
118 }
119 
120 bool ClusterTree::train_(MatrixFloat &trainingData){
121 
122  //Clear any previous model
123  clear();
124 
125  const unsigned int M = trainingData.getNumRows();
126  const unsigned int N = trainingData.getNumCols();
127 
128  if( M == 0 ){
129  Clusterer::errorLog << "train_(MatrixFloat &trainingData) - Training data has zero samples!" << std::endl;
130  return false;
131  }
132 
133  numInputDimensions = N;
134  numOutputDimensions = 1;
135  ranges = trainingData.getRanges();
136 
137  //Scale the training data if needed
138  if( useScaling ){
139  //Scale the training data between 0 and 1
140  trainingData.scale(0, 1);
141  }
142 
143  //Setup the valid features - at this point all features can be used
144  Vector< UINT > features(N);
145  for(UINT i=0; i<N; i++){
146  features[i] = i;
147  }
148 
149  //Build the tree
150  UINT clusterLabel = 0;
151  UINT nodeID = 0;
152  tree = buildTree( trainingData, NULL, features, clusterLabel, nodeID );
153  numClusters = clusterLabel;
154 
155  if( tree == NULL ){
156  clear();
157  Clusterer::errorLog << "train_(MatrixFloat &trainingData) - Failed to build tree!" << std::endl;
158  return false;
159  }
160 
161  //Flag that the algorithm has been trained
162  trained = true;
163 
164  //Setup the cluster labels
165  clusterLabels.resize(numClusters);
166  for(UINT i=0; i<numClusters; i++){
167  clusterLabels[i] = i+1;
168  }
169  clusterLikelihoods.resize(numClusters,0);
170  clusterDistances.resize(numClusters,0);
171 
172  return true;
173 }
174 
176 
177  if( !trained ){
178  Clusterer::errorLog << "predict_(VectorFloat &inputVector) - Model Not Trained!" << std::endl;
179  return false;
180  }
181 
182  if( tree == NULL ){
183  Clusterer::errorLog << "predict_(VectorFloat &inputVector) - DecisionTree pointer is null!" << std::endl;
184  return false;
185  }
186 
187  if( inputVector.size() != numInputDimensions ){
188  Clusterer::errorLog << "predict_(VectorFloat &inputVector) - The size of the input Vector (" << inputVector.size() << ") does not match the num features in the model (" << numInputDimensions << std::endl;
189  return false;
190  }
191 
192  if( useScaling ){
193  for(UINT n=0; n<numInputDimensions; n++){
194  inputVector[n] = scale(inputVector[n], ranges[n].minValue, ranges[n].maxValue, 0, 1);
195  }
196  }
197 
198  VectorFloat clusterLabel(1);
199  if( !tree->predict( inputVector, clusterLabel ) ){
200  Clusterer::errorLog << "predict_(VectorFloat &inputVector) - Failed to predict!" << std::endl;
201  return false;
202  }
203  predictedClusterLabel = (UINT)clusterLabel[0];
204 
205  return true;
206 }
207 
209 
210  //Clear the base variables
212 
213  if( tree != NULL ){
214  tree->clear();
215  delete tree;
216  tree = NULL;
217  }
218 
219  return true;
220 }
221 
222 bool ClusterTree::print() const{
223  if( tree != NULL )
224  return tree->print();
225  return false;
226 }
227 
228 bool ClusterTree::saveModelToFile( std::fstream &file ) const{
229 
230  if( !file.is_open() )
231  {
232  Clusterer::errorLog <<"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
233  return false;
234  }
235 
236  //Write the header info
237  file << "GRT_CLUSTER_TREE_MODEL_FILE_V1.0" << std::endl;
238 
239  //Write the clusterer settings to the file
240  if( !saveClustererSettingsToFile(file) ){
241  Clusterer::errorLog <<"saveModelToFile(fstream &file) - Failed to save clusterer settings to file!" << std::endl;
242  return false;
243  }
244 
245  file << "NumSplittingSteps: " << numSplittingSteps << std::endl;
246  file << "MinNumSamplesPerNode: " << minNumSamplesPerNode << std::endl;
247  file << "MaxDepth: " << maxDepth << std::endl;
248  file << "RemoveFeaturesAtEachSpilt: " << removeFeaturesAtEachSpilt << std::endl;
249  file << "TrainingMode: " << trainingMode << std::endl;
250  file << "MinRMSErrorPerNode: " << minRMSErrorPerNode << std::endl;
251  file << "TreeBuilt: " << (tree != NULL ? 1 : 0) << std::endl;
252 
253  if( tree != NULL ){
254  file << "Tree:\n";
255  if( !tree->save( file ) ){
256  Clusterer::errorLog << "saveModelToFile(fstream &file) - Failed to save tree to file!" << std::endl;
257  return false;
258  }
259  }
260 
261  return true;
262 }
263 
264 bool ClusterTree::loadModelFromFile( std::fstream &file ){
265 
266  clear();
267 
268  if(!file.is_open())
269  {
270  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not open file to load model" << std::endl;
271  return false;
272  }
273 
274  std::string word;
275 
276  //Find the file type header
277  file >> word;
278  if(word != "GRT_CLUSTER_TREE_MODEL_FILE_V1.0"){
279  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find Model File Header" << std::endl;
280  return false;
281  }
282 
283  //Load the base settings from the file
284  if( !loadClustererSettingsFromFile(file) ){
285  Clusterer::errorLog << "loadModelFromFile(string filename) - Failed to load base settings from file!" << std::endl;
286  return false;
287  }
288 
289  file >> word;
290  if(word != "NumSplittingSteps:"){
291  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the NumSplittingSteps!" << std::endl;
292  return false;
293  }
294  file >> numSplittingSteps;
295 
296  file >> word;
297  if(word != "MinNumSamplesPerNode:"){
298  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the MinNumSamplesPerNode!" << std::endl;
299  return false;
300  }
301  file >> minNumSamplesPerNode;
302 
303  file >> word;
304  if(word != "MaxDepth:"){
305  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the MaxDepth!" << std::endl;
306  return false;
307  }
308  file >> maxDepth;
309 
310  file >> word;
311  if(word != "RemoveFeaturesAtEachSpilt:"){
312  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the RemoveFeaturesAtEachSpilt!" << std::endl;
313  return false;
314  }
315  file >> removeFeaturesAtEachSpilt;
316 
317  file >> word;
318  if(word != "TrainingMode:"){
319  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the TrainingMode!" << std::endl;
320  return false;
321  }
322  file >> trainingMode;
323 
324  file >> word;
325  if(word != "MinRMSErrorPerNode:"){
326  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the MinRMSErrorPerNode!" << std::endl;
327  return false;
328  }
329  file >> minRMSErrorPerNode;
330 
331  file >> word;
332  if(word != "TreeBuilt:"){
333  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the TreeBuilt!" << std::endl;
334  return false;
335  }
336  file >> trained;
337 
338  if( trained ){
339  file >> word;
340  if(word != "Tree:"){
341  Clusterer::errorLog << "loadModelFromFile(string filename) - Could not find the Tree!" << std::endl;
342  return false;
343  }
344 
345  //Create a new tree
346  tree = new ClusterTreeNode;
347 
348  if( tree == NULL ){
349  clear();
350  Clusterer::errorLog << "loadModelFromFile(fstream &file) - Failed to create new RegressionTreeNode!" << std::endl;
351  return false;
352  }
353 
354  tree->setParent( NULL );
355  if( !tree->load( file ) ){
356  clear();
357  Clusterer::errorLog << "loadModelFromFile(fstream &file) - Failed to load tree from file!" << std::endl;
358  return false;
359  }
360 
361  //Setup the cluster labels
362  clusterLabels.resize(numClusters);
363  for(UINT i=0; i<numClusters; i++){
364  clusterLabels[i] = i+1;
365  }
366  clusterLikelihoods.resize(numClusters,0);
367  clusterDistances.resize(numClusters,0);
368  }
369 
370  return true;
371 }
372 
374 
375  if( tree == NULL ){
376  return NULL;
377  }
378 
379  return (ClusterTreeNode*)tree->deepCopyNode();
380 }
381 
383  return (ClusterTreeNode*)tree;
384 }
385 
387  return predictedClusterLabel;
388 }
389 
391  return minRMSErrorPerNode;
392 }
393 
394 bool ClusterTree::setMinRMSErrorPerNode(const Float minRMSErrorPerNode){
395  this->minRMSErrorPerNode = minRMSErrorPerNode;
396  return true;
397 }
398 
399 ClusterTreeNode* ClusterTree::buildTree(const MatrixFloat &trainingData,ClusterTreeNode *parent,Vector< UINT > features,UINT &clusterLabel,UINT nodeID){
400 
401  const UINT M = trainingData.getNumRows();
402 
403  //Update the nodeID
404 
405  //Get the depth
406  UINT depth = 0;
407 
408  if( parent != NULL )
409  depth = parent->getDepth() + 1;
410 
411  //If there are no training data then return NULL
412  if( M == 0 )
413  return NULL;
414 
415  //Create the new node
416  ClusterTreeNode *node = new ClusterTreeNode;
417 
418  if( node == NULL )
419  return NULL;
420 
421  //Set the parent
422  node->initNode( parent, depth, nodeID );
423 
424  //If there are no features left then create a leaf node and return
425  if( features.getSize() == 0 || M < minNumSamplesPerNode || depth >= maxDepth ){
426 
427  //Update the clusterLabel
428  clusterLabel++;
429 
430  //Flag that this is a leaf node
431  node->setIsLeafNode( true );
432 
433  //Set the node - the feature and threshold are both 0
434  node->set( M, 0, 0, clusterLabel );
435 
436  Clusterer::trainingLog << "Reached leaf node. Depth: " << depth << " NumSamples: " << M << std::endl;
437 
438  return node;
439  }
440 
441  //Compute the best spilt point
442  UINT featureIndex = 0;
443  Float threshold = 0;
444  Float minError = 0;
445  if( !computeBestSpilt( trainingData, features, featureIndex, threshold, minError ) ){
446  delete node;
447  return NULL;
448  }
449 
450  Clusterer::trainingLog << "Depth: " << depth << " FeatureIndex: " << featureIndex << " Threshold: " << threshold << " MinError: " << minError << std::endl;
451 
452  //If the minError is below the minRMSError then create a leaf node and return
453  if( minError <= minRMSErrorPerNode ){
454  //Update the clusterLabel
455  clusterLabel++;
456 
457  //Flag that this is a leaf node
458  node->setIsLeafNode( true );
459 
460  //Set the node
461  node->set( M, featureIndex, threshold, clusterLabel );
462 
463  Clusterer::trainingLog << "Reached leaf node. Depth: " << depth << " NumSamples: " << M << std::endl;
464 
465  return node;
466  }
467 
468  //Set the node (any node that is not a leaf node has a cluster label of 0
469  node->set( M, featureIndex, threshold, 0 );
470 
471  //Remove the selected feature so we will not use it again
472  if( removeFeaturesAtEachSpilt ){
473  for(UINT i=0; i<features.getSize(); i++){
474  if( features[i] == featureIndex ){
475  features.erase( features.begin()+i );
476  break;
477  }
478  }
479  }
480 
481  //Split the data
482  MatrixFloat lhs;
483  MatrixFloat rhs;
484 
485  for(UINT i=0; i<M; i++){
486  if( node->predict( trainingData.getRow(i) ) ){
487  rhs.push_back(trainingData.getRow(i));
488  }else lhs.push_back(trainingData.getRow(i));
489  }
490 
491  //Run the recursive tree building on the children
492  node->setLeftChild( buildTree( lhs, node, features, clusterLabel, nodeID ) );
493  node->setRightChild( buildTree( rhs, node, features, clusterLabel, nodeID ) );
494 
495  return node;
496 }
497 
498 bool ClusterTree::computeBestSpilt( const MatrixFloat &trainingData, const Vector< UINT > &features, UINT &featureIndex, Float &threshold, Float &minError ){
499 
500  switch( trainingMode ){
501  case BEST_ITERATIVE_SPILT:
502  return computeBestSpiltBestIterativeSpilt( trainingData, features, featureIndex, threshold, minError );
503  break;
504  case BEST_RANDOM_SPLIT:
505  return computeBestSpiltBestRandomSpilt( trainingData, features, featureIndex, threshold, minError );
506  break;
507  default:
508  Clusterer::errorLog << "Uknown trainingMode!" << std::endl;
509  return false;
510  break;
511  }
512 
513  return true;
514 }
515 
516 bool ClusterTree::computeBestSpiltBestIterativeSpilt( const MatrixFloat &trainingData, const Vector< UINT > &features, UINT &featureIndex, Float &threshold, Float &minError ){
517 
518  const UINT M = trainingData.getNumRows();
519  const UINT N = (UINT)features.size();
520 
521  //Clusterer::debugLog << "computeBestSpiltBestIterativeSpilt() M: " << M << std::endl;
522 
523  if( N == 0 ) return false;
524 
526  UINT bestFeatureIndex = 0;
527  UINT groupID = 0;
528  Float bestThreshold = 0;
529  Float error = 0;
530  Float minRange = 0;
531  Float maxRange = 0;
532  Float step = 0;
533  Vector< UINT > groupIndex(M);
534  Vector< Float > groupCounter(2);
535  Vector< Float > groupMean(2);
536  Vector< Float > groupMSE(2);
537  Vector< MinMax > ranges = trainingData.getRanges();
538 
539  //Loop over each feature and try and find the best split point
540  for(UINT n=0; n<N; n++){
541  minRange = ranges[n].minValue;
542  maxRange = ranges[n].maxValue;
543  step = (maxRange-minRange)/Float(numSplittingSteps);
544  threshold = minRange;
545  featureIndex = features[n];
546 
547  while( threshold <= maxRange ){
548 
549  //Reset the counters to zero
550  groupCounter[0] = groupCounter[1] = 0;
551  groupMean[0] = groupMean[1] = 0;
552  groupMSE[0] = groupMSE[1] = 0;
553 
554  //Iterate over each sample and work out what group it falls into
555  for(UINT i=0; i<M; i++){
556  groupID = trainingData[i][featureIndex] >= threshold ? 1 : 0;
557  groupIndex[i] = groupID;
558 
559  //Update the group mean and group counters
560  groupMean[ groupID ] += trainingData[i][featureIndex];
561  groupCounter[ groupID ]++;
562  }
563 
564  //Compute the group mean
565  groupMean[0] /= (groupCounter[0] > 0 ? groupCounter[0] : 1);
566  groupMean[1] /= (groupCounter[1] > 0 ? groupCounter[1] : 1);
567 
568  //Compute the MSE for each group
569  for(UINT i=0; i<M; i++){
570  groupMSE[ groupIndex[i] ] += grt_sqr( groupMean[ groupIndex[i] ] - trainingData[i][featureIndex] );
571  }
572  groupMSE[0] /= (groupCounter[0] > 0 ? groupCounter[0] : 1);
573  groupMSE[1] /= (groupCounter[1] > 0 ? groupCounter[1] : 1);
574 
575  error = grt_sqrt( groupMSE[0] + groupMSE[1] );
576 
577  //Store the best threshold and feature index
578  if( error < minError ){
579  minError = error;
580  bestThreshold = threshold;
581  bestFeatureIndex = featureIndex;
582  }
583 
584  //Update the threshold
585  threshold += step;
586  }
587  }
588 
589  //Set the best feature index and threshold
590  featureIndex = bestFeatureIndex;
591  threshold = bestThreshold;
592 
593  return true;
594 }
595 
596 bool ClusterTree::computeBestSpiltBestRandomSpilt( const MatrixFloat &trainingData, const Vector< UINT > &features, UINT &featureIndex, Float &threshold, Float &minError ){
597 
598  const UINT M = trainingData.getNumRows();
599  const UINT N = (UINT)features.size();
600 
601  Clusterer::debugLog << "computeBestSpiltBestRandomSpilt() M: " << M << std::endl;
602 
603  if( N == 0 ) return false;
604 
606  UINT bestFeatureIndex = 0;
607  UINT groupID = 0;
608  Float bestThreshold = 0;
609  Float error = 0;
610  Vector< UINT > groupIndex(M);
611  Vector< Float > groupCounter(2);
612  Vector< Float > groupMean(2);
613  Vector< Float > groupMSE(2);
614  Vector< MinMax > ranges = trainingData.getRanges();
615 
616  //Loop over each feature and try and find the best split point
617  for(UINT n=0; n<N; n++){
618  featureIndex = features[n];
619 
620  for(UINT m=0; m<numSplittingSteps; m++){
621  //Randomly select a threshold value
622  threshold = random.getRandomNumberUniform(ranges[n].minValue,ranges[n].maxValue);
623 
624  //Reset the counters to zero
625  groupCounter[0] = groupCounter[1] = 0;
626  groupMean[0] = groupMean[1] = 0;
627  groupMSE[0] = groupMSE[1] = 0;
628 
629  //Iterate over each sample and work out what group it falls into
630  for(UINT i=0; i<M; i++){
631  groupID = trainingData[i][featureIndex] >= threshold ? 1 : 0;
632  groupIndex[i] = groupID;
633 
634  //Update the group mean and group counters
635  groupMean[ groupID ] += trainingData[i][featureIndex];
636  groupCounter[ groupID ]++;
637  }
638 
639  //Compute the group mean
640  groupMean[0] /= (groupCounter[0] > 0 ? groupCounter[0] : 1);
641  groupMean[1] /= (groupCounter[1] > 0 ? groupCounter[1] : 1);
642 
643  //Compute the MSE for each group
644  for(UINT i=0; i<M; i++){
645  groupMSE[ groupIndex[i] ] += MLBase::SQR( groupMean[ groupIndex[i] ] - trainingData[i][featureIndex] );
646  }
647  groupMSE[0] /= (groupCounter[0] > 0 ? groupCounter[0] : 1);
648  groupMSE[1] /= (groupCounter[1] > 0 ? groupCounter[1] : 1);
649 
650  error = sqrt( groupMSE[0] + groupMSE[1] );
651 
652  //Store the best threshold and feature index
653  if( error < minError ){
654  minError = error;
655  bestThreshold = threshold;
656  bestFeatureIndex = featureIndex;
657  }
658  }
659  }
660 
661  //Set the best feature index and threshold
662  featureIndex = bestFeatureIndex;
663  threshold = bestThreshold;
664 
665  return true;
666 }
667 
668 GRT_END_NAMESPACE
669 
const ClusterTreeNode * getTree() const
virtual bool train_(MatrixFloat &trainingData)
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
bool setMinRMSErrorPerNode(const Float minRMSErrorPerNode)
virtual ~ClusterTree(void)
Definition: ClusterTree.cpp:61
This class implements a Cluster Tree. This can be used to automatically build a cluster model (where ...
virtual bool print() const
Definition: Node.cpp:109
std::string getClustererType() const
Definition: Clusterer.cpp:260
virtual bool saveModelToFile(std::fstream &file) const
bool scale(const Float minTarget, const Float maxTarget)
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
bool getTrained() const
Definition: MLBase.cpp:259
UINT getDepth() const
Definition: Node.cpp:308
virtual bool predict(const VectorFloat &x)
UINT getSize() const
Definition: Vector.h:191
bool copyBaseVariables(const Clusterer *clusterer)
Definition: Clusterer.cpp:87
bool loadClustererSettingsFromFile(std::fstream &file)
Definition: Clusterer.cpp:179
bool set(const UINT nodeSize, const UINT featureIndex, const Float threshold, const UINT clusterLabel)
ClusterTreeNode * deepCopyTree() const
virtual bool save(std::fstream &file) const
Definition: Node.cpp:140
UINT predictedClusterLabel
Stores the predicted cluster label from the most recent predict( )
Definition: Clusterer.h:250
virtual Node * deepCopyNode() const
Definition: Node.cpp:276
bool saveClustererSettingsToFile(std::fstream &file) const
Definition: Clusterer.cpp:157
ClusterTree & operator=(const ClusterTree &rhs)
Definition: ClusterTree.cpp:66
UINT numClusters
Number of clusters in the model.
Definition: Clusterer.h:249
virtual bool clear()
Definition: Node.cpp:70
unsigned int getNumRows() const
Definition: Matrix.h:542
unsigned int getNumCols() const
Definition: Matrix.h:549
virtual bool deepCopyFrom(const Clusterer *cluster)
Definition: ClusterTree.cpp:90
virtual bool predict_(VectorFloat &inputVector)
virtual bool clear()
virtual bool print() const
virtual bool loadModelFromFile(std::fstream &file)
VectorFloat getRow(const unsigned int r) const
Definition: MatrixFloat.h:100
Vector< MinMax > getRanges() const
Float getRandomNumberUniform(Float minRange=0.0, Float maxRange=1.0)
Definition: Random.h:198
ClusterTree(const UINT numSplittingSteps=100, const UINT minNumSamplesPerNode=5, const UINT maxDepth=10, const bool removeFeaturesAtEachSpilt=false, const UINT trainingMode=BEST_ITERATIVE_SPILT, const bool useScaling=false, const Float minRMSErrorPerNode=0.01)
Definition: ClusterTree.cpp:32
UINT getPredictedClusterLabel() const
bool push_back(const Vector< T > &sample)
Definition: Matrix.h:401
virtual bool clear()
Definition: Clusterer.cpp:142
virtual bool load(std::fstream &file)
Definition: Node.cpp:182
virtual bool predict(const VectorFloat &x)
Definition: Node.cpp:60
Float getMinRMSErrorPerNode() const