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