GestureRecognitionToolkit  Version: 0.2.5
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
RegressionTree.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 "RegressionTree.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
26 //Register the RegressionTreeNode with the Node base class
27 RegisterNode< RegressionTreeNode > RegressionTreeNode::registerModule("RegressionTreeNode");
28 
29 //Define the string that will be used to identify the object
30 const std::string RegressionTree::id = "RegressionTree";
31 std::string RegressionTree::getId() { return RegressionTree::id; }
32 
33 //Register the RegressionTree module with the Regressifier base class
35 
36 RegressionTree::RegressionTree(const UINT numSplittingSteps,const UINT minNumSamplesPerNode,const UINT maxDepth,const bool removeFeaturesAtEachSpilt,const Tree::TrainingMode trainingMode,const bool useScaling,const Float minRMSErrorPerNode) : Regressifier( RegressionTree::getId() )
37 {
38  tree = NULL;
39  this->numSplittingSteps = numSplittingSteps;
40  this->minNumSamplesPerNode = minNumSamplesPerNode;
41  this->maxDepth = maxDepth;
42  this->removeFeaturesAtEachSpilt = removeFeaturesAtEachSpilt;
43  this->trainingMode = trainingMode;
44  this->useScaling = useScaling;
45  this->minRMSErrorPerNode = minRMSErrorPerNode;
46 }
47 
49 {
50  tree = NULL;
51  *this = rhs;
52 }
53 
55 {
56  clear();
57 }
58 
60  if( this != &rhs ){
61  //Clear this tree
62  this->clear();
63 
64  if( rhs.getTrained() ){
65  //Deep copy the tree
66  this->tree = dynamic_cast< RegressionTreeNode* >( rhs.deepCopyTree() );
67  }
68 
69  this->numSplittingSteps = rhs.numSplittingSteps;
70  this->minNumSamplesPerNode = rhs.minNumSamplesPerNode;
71  this->maxDepth = rhs.maxDepth;
72  this->removeFeaturesAtEachSpilt = rhs.removeFeaturesAtEachSpilt;
73  this->trainingMode = rhs.trainingMode;
74  this->minRMSErrorPerNode = rhs.minRMSErrorPerNode;
75 
76  //Copy the base variables
78  }
79  return *this;
80 }
81 
82 bool RegressionTree::deepCopyFrom(const Regressifier *regressifier){
83 
84  if( regressifier == NULL ) return false;
85 
86  if( this->getId() == regressifier->getId() ){
87 
88  const RegressionTree *ptr = dynamic_cast<const RegressionTree*>(regressifier);
89 
90  //Clear this tree
91  this->clear();
92 
93  if( ptr->getTrained() ){
94  //Deep copy the tree
95  this->tree = dynamic_cast< RegressionTreeNode* >( ptr->deepCopyTree() );
96  }
97 
98  this->numSplittingSteps = ptr->numSplittingSteps;
99  this->minNumSamplesPerNode = ptr->minNumSamplesPerNode;
100  this->maxDepth = ptr->maxDepth;
101  this->removeFeaturesAtEachSpilt = ptr->removeFeaturesAtEachSpilt;
102  this->trainingMode = ptr->trainingMode;
103  this->minRMSErrorPerNode = ptr->minRMSErrorPerNode;
104 
105  //Copy the base variables
106  return copyBaseVariables( regressifier );
107  }
108  return false;
109 }
110 
112 
113  //Clear any previous model
114  clear();
115 
116  const unsigned int M = trainingData.getNumSamples();
117  const unsigned int N = trainingData.getNumInputDimensions();
118  const unsigned int T = trainingData.getNumTargetDimensions();
119 
120  if( M == 0 ){
121  Regressifier::errorLog << "train_(RegressionData &trainingData) - Training data has zero samples!" << std::endl;
122  return false;
123  }
124 
125  numInputDimensions = N;
126  numOutputDimensions = T;
127  inputVectorRanges = trainingData.getInputRanges();
128  targetVectorRanges = trainingData.getTargetRanges();
129 
130  //Scale the training data if needed
131  if( useScaling ){
132  //Scale the training data between 0 and 1
133  trainingData.scale(0, 1);
134  }
135 
136  //Setup the valid features - at this point all features can be used
137  Vector< UINT > features(N);
138  for(UINT i=0; i<N; i++){
139  features[i] = i;
140  }
141 
142  //Build the tree
143  UINT nodeID = 0;
144  tree = buildTree( trainingData, NULL, features, nodeID );
145 
146  if( tree == NULL ){
147  clear();
148  Regressifier::errorLog << "train_(RegressionData &trainingData) - Failed to build tree!" << std::endl;
149  return false;
150  }
151 
152  //Flag that the algorithm has been trained
153  trained = true;
154 
155  return true;
156 }
157 
159 
160  if( !trained ){
161  Regressifier::errorLog << "predict_(VectorFloat &inputVector) - Model Not Trained!" << std::endl;
162  return false;
163  }
164 
165  if( tree == NULL ){
166  Regressifier::errorLog << "predict_(VectorFloat &inputVector) - Tree pointer is null!" << std::endl;
167  return false;
168  }
169 
170  if( inputVector.size() != numInputDimensions ){
171  Regressifier::errorLog << "predict_(VectorFloat &inputVector) - The size of the input Vector (" << inputVector.size() << ") does not match the num features in the model (" << numInputDimensions << std::endl;
172  return false;
173  }
174 
175  if( useScaling ){
176  for(UINT n=0; n<numInputDimensions; n++){
177  inputVector[n] = scale(inputVector[n], inputVectorRanges[n].minValue, inputVectorRanges[n].maxValue, 0, 1);
178  }
179  }
180 
181  if( !tree->predict_( inputVector, regressionData ) ){
182  Regressifier::errorLog << "predict_(VectorFloat &inputVector) - Failed to predict!" << std::endl;
183  return false;
184  }
185 
186  return true;
187 }
188 
190 
191  //Clear the Classifier variables
193 
194  if( tree != NULL ){
195  tree->clear();
196  delete tree;
197  tree = NULL;
198  }
199 
200  return true;
201 }
202 
204  if( tree != NULL )
205  return tree->print();
206  return false;
207 }
208 
209 bool RegressionTree::save( std::fstream &file ) const{
210 
211  if(!file.is_open())
212  {
213  Regressifier::errorLog <<"save(fstream &file) - The file is not open!" << std::endl;
214  return false;
215  }
216 
217  //Write the header info
218  file << "GRT_REGRESSION_TREE_MODEL_FILE_V1.0\n";
219 
220  //Write the classifier settings to the file
222  Regressifier::errorLog <<"save(fstream &file) - Failed to save classifier base settings to file!" << std::endl;
223  return false;
224  }
225 
226  file << "NumSplittingSteps: " << numSplittingSteps << std::endl;
227  file << "MinNumSamplesPerNode: " << minNumSamplesPerNode << std::endl;
228  file << "MaxDepth: " << maxDepth << std::endl;
229  file << "RemoveFeaturesAtEachSpilt: " << removeFeaturesAtEachSpilt << std::endl;
230  file << "TrainingMode: " << trainingMode << std::endl;
231  file << "TreeBuilt: " << (tree != NULL ? 1 : 0) << std::endl;
232 
233  if( tree != NULL ){
234  file << "Tree:\n";
235  if( !tree->save( file ) ){
236  Regressifier::errorLog << "save(fstream &file) - Failed to save tree to file!" << std::endl;
237  return false;
238  }
239  }
240 
241  return true;
242 }
243 
244 bool RegressionTree::load( std::fstream &file ){
245 
246  clear();
247 
248  if(!file.is_open())
249  {
250  Regressifier::errorLog << "load(string filename) - Could not open file to load model" << std::endl;
251  return false;
252  }
253 
254  std::string word;
255  file >> word;
256 
257  //Find the file type header
258  if(word != "GRT_REGRESSION_TREE_MODEL_FILE_V1.0"){
259  Regressifier::errorLog << "load(string filename) - Could not find Model File Header" << std::endl;
260  return false;
261  }
262 
263  //Load the base settings from the file
265  Regressifier::errorLog << "load(string filename) - Failed to load base settings from file!" << std::endl;
266  return false;
267  }
268 
269  file >> word;
270  if(word != "NumSplittingSteps:"){
271  Regressifier::errorLog << "load(string filename) - Could not find the NumSplittingSteps!" << std::endl;
272  return false;
273  }
274  file >> numSplittingSteps;
275 
276  file >> word;
277  if(word != "MinNumSamplesPerNode:"){
278  Regressifier::errorLog << "load(string filename) - Could not find the MinNumSamplesPerNode!" << std::endl;
279  return false;
280  }
281  file >> minNumSamplesPerNode;
282 
283  file >> word;
284  if(word != "MaxDepth:"){
285  Regressifier::errorLog << "load(string filename) - Could not find the MaxDepth!" << std::endl;
286  return false;
287  }
288  file >> maxDepth;
289 
290  file >> word;
291  if(word != "RemoveFeaturesAtEachSpilt:"){
292  Regressifier::errorLog << "load(string filename) - Could not find the RemoveFeaturesAtEachSpilt!" << std::endl;
293  return false;
294  }
295  file >> removeFeaturesAtEachSpilt;
296 
297  file >> word;
298  if(word != "TrainingMode:"){
299  Regressifier::errorLog << "load(string filename) - Could not find the TrainingMode!" << std::endl;
300  return false;
301  }
302  UINT tempTrainingMode;
303  file >> tempTrainingMode;
304  trainingMode = static_cast< Tree::TrainingMode >( tempTrainingMode );
305 
306  file >> word;
307  if(word != "TreeBuilt:"){
308  Regressifier::errorLog << "load(string filename) - Could not find the TreeBuilt!" << std::endl;
309  return false;
310  }
311  file >> trained;
312 
313  if( trained ){
314  file >> word;
315  if(word != "Tree:"){
316  Regressifier::errorLog << "load(string filename) - Could not find the Tree!" << std::endl;
317  return false;
318  }
319 
320  //Create a new tree
321  tree = new RegressionTreeNode;
322 
323  if( tree == NULL ){
324  clear();
325  Regressifier::errorLog << "load(fstream &file) - Failed to create new RegressionTreeNode!" << std::endl;
326  return false;
327  }
328 
329  tree->setParent( NULL );
330  if( !tree->load( file ) ){
331  clear();
332  Regressifier::errorLog << "load(fstream &file) - Failed to load tree from file!" << std::endl;
333  return false;
334  }
335  }
336 
337  return true;
338 }
339 
341 
342  if( tree == NULL ){
343  return NULL;
344  }
345 
346  return dynamic_cast<RegressionTreeNode*>(tree->deepCopy());
347 }
348 
350  return dynamic_cast< RegressionTreeNode* >( tree );
351 }
352 
354  return minRMSErrorPerNode;
355 }
356 
357 Tree::TrainingMode RegressionTree::getTrainingMode() const{
358  return trainingMode;
359 }
360 
362  return numSplittingSteps;
363 }
364 
366  return minNumSamplesPerNode;
367 }
368 
370  return maxDepth;
371 }
372 
374 
375  if( tree == NULL ){
376  return 0;
377  }
378 
379  return tree->getPredictedNodeID();
380 }
381 
383  return removeFeaturesAtEachSpilt;
384 }
385 
386 bool RegressionTree::setTrainingMode(const Tree::TrainingMode trainingMode){
387  if( trainingMode >= Tree::BEST_ITERATIVE_SPILT && trainingMode < Tree::NUM_TRAINING_MODES ){
388  this->trainingMode = trainingMode;
389  return true;
390  }
391  warningLog << "Unknown trainingMode: " << trainingMode << std::endl;
392  return false;
393 }
394 
395 bool RegressionTree::setNumSplittingSteps(const UINT numSplittingSteps){
396  if( numSplittingSteps > 0 ){
397  this->numSplittingSteps = numSplittingSteps;
398  return true;
399  }
400  warningLog << "setNumSplittingSteps(const UINT numSplittingSteps) - The number of splitting steps must be greater than zero!" << std::endl;
401  return false;
402 }
403 
404 bool RegressionTree::setMinNumSamplesPerNode(const UINT minNumSamplesPerNode){
405  if( minNumSamplesPerNode > 0 ){
406  this->minNumSamplesPerNode = minNumSamplesPerNode;
407  return true;
408  }
409  warningLog << "setMinNumSamplesPerNode(const UINT minNumSamplesPerNode) - The minimum number of samples per node must be greater than zero!" << std::endl;
410  return false;
411 }
412 
413 bool RegressionTree::setMaxDepth(const UINT maxDepth){
414  if( maxDepth > 0 ){
415  this->maxDepth = maxDepth;
416  return true;
417  }
418  warningLog << "setMaxDepth(const UINT maxDepth) - The maximum depth must be greater than zero!" << std::endl;
419  return false;
420 }
421 
422 bool RegressionTree::setRemoveFeaturesAtEachSpilt(const bool removeFeaturesAtEachSpilt){
423  this->removeFeaturesAtEachSpilt = removeFeaturesAtEachSpilt;
424  return true;
425 }
426 
427 bool RegressionTree::setMinRMSErrorPerNode(const Float minRMSErrorPerNode){
428  this->minRMSErrorPerNode = minRMSErrorPerNode;
429  return true;
430 }
431 
432 RegressionTreeNode* RegressionTree::buildTree(const RegressionData &trainingData,RegressionTreeNode *parent,Vector< UINT > features,UINT nodeID){
433 
434  const UINT M = trainingData.getNumSamples();
435  const UINT N = trainingData.getNumInputDimensions();
436  const UINT T = trainingData.getNumTargetDimensions();
437  VectorFloat regressionData(T);
438 
439  //Update the nodeID
440 
441  //Get the depth
442  UINT depth = 0;
443 
444  if( parent != NULL )
445  depth = parent->getDepth() + 1;
446 
447  //If there are no training data then return NULL
448  if( trainingData.getNumSamples() == 0 )
449  return NULL;
450 
451  //Create the new node
453 
454  if( node == NULL )
455  return NULL;
456 
457  //Set the parent
458  node->initNode( parent, depth, nodeID );
459 
460  //If there are no features left then create a leaf node and return
461  if( features.size() == 0 || M < minNumSamplesPerNode || depth >= maxDepth ){
462 
463  //Flag that this is a leaf node
464  node->setIsLeafNode( true );
465 
466  //Compute the regression data that will be stored at this node
467  computeNodeRegressionData( trainingData, regressionData );
468 
469  //Set the node
470  node->set( trainingData.getNumSamples(), 0, 0, regressionData );
471 
472  Regressifier::trainingLog << "Reached leaf node. Depth: " << depth << " NumSamples: " << trainingData.getNumSamples() << std::endl;
473 
474  return node;
475  }
476 
477  //Compute the best spilt point
478  UINT featureIndex = 0;
479  Float threshold = 0;
480  Float minError = 0;
481  if( !computeBestSpilt( trainingData, features, featureIndex, threshold, minError ) ){
482  delete node;
483  return NULL;
484  }
485 
486  trainingLog << "Depth: " << depth << " FeatureIndex: " << featureIndex << " Threshold: " << threshold << " MinError: " << minError << std::endl;
487 
488  //If the minError is below the minRMSError then create a leaf node and return
489  if( minError <= minRMSErrorPerNode ){
490  //Compute the regression data that will be stored at this node
491  computeNodeRegressionData( trainingData, regressionData );
492 
493  //Set the node
494  node->set( trainingData.getNumSamples(), featureIndex, threshold, regressionData );
495 
496  trainingLog << "Reached leaf node. Depth: " << depth << " NumSamples: " << M << std::endl;
497 
498  return node;
499  }
500 
501  //Set the node
502  node->set( trainingData.getNumSamples(), featureIndex, threshold, regressionData );
503 
504  //Remove the selected feature so we will not use it again
505  if( removeFeaturesAtEachSpilt ){
506  for(UINT i=0; i<features.getSize(); i++){
507  if( features[i] == featureIndex ){
508  features.erase( features.begin()+i );
509  break;
510  }
511  }
512  }
513 
514  //Split the data
515  RegressionData lhs(N,T);
516  RegressionData rhs(N,T);
517 
518  for(UINT i=0; i<M; i++){
519  if( node->predict( trainingData[i].getInputVector() ) ){
520  rhs.addSample(trainingData[i].getInputVector(), trainingData[i].getTargetVector());
521  }else lhs.addSample(trainingData[i].getInputVector(), trainingData[i].getTargetVector());
522  }
523 
524  //Run the recursive tree building on the children
525  node->setLeftChild( buildTree( lhs, node, features, nodeID ) );
526  node->setRightChild( buildTree( rhs, node, features, nodeID ) );
527 
528  return node;
529 }
530 
531 bool RegressionTree::computeBestSpilt( const RegressionData &trainingData, const Vector< UINT > &features, UINT &featureIndex, Float &threshold, Float &minError ){
532 
533  switch( trainingMode ){
534  case Tree::BEST_ITERATIVE_SPILT:
535  return computeBestSpiltBestIterativeSpilt( trainingData, features, featureIndex, threshold, minError );
536  break;
537  case Tree::BEST_RANDOM_SPLIT:
538  //return computeBestSpiltBestRandomSpilt( trainingData, features, featureIndex, threshold, minError );
539  break;
540  default:
541  Regressifier::errorLog << "Uknown trainingMode!" << std::endl;
542  return false;
543  break;
544  }
545 
546  return false;
547 }
548 
549 bool RegressionTree::computeBestSpiltBestIterativeSpilt( const RegressionData &trainingData, const Vector< UINT > &features, UINT &featureIndex, Float &threshold, Float &minError ){
550 
551  const UINT M = trainingData.getNumSamples();
552  const UINT N = (UINT)features.size();
553 
554  if( N == 0 ) return false;
555 
557  UINT bestFeatureIndex = 0;
558  UINT groupID = 0;
559  Float bestThreshold = 0;
560  Float error = 0;
561  Float minRange = 0;
562  Float maxRange = 0;
563  Float step = 0;
564  Vector< UINT > groupIndex(M);
565  VectorFloat groupCounter(2,0);
566  VectorFloat groupMean(2,0);
567  VectorFloat groupMSE(2,0);
568  Vector< MinMax > ranges = trainingData.getInputRanges();
569 
570  //Loop over each feature and try and find the best split point
571  for(UINT n=0; n<N; n++){
572  minRange = ranges[n].minValue;
573  maxRange = ranges[n].maxValue;
574  step = (maxRange-minRange)/Float(numSplittingSteps);
575  threshold = minRange;
576  featureIndex = features[n];
577  while( threshold <= maxRange ){
578 
579  //Iterate over each sample and work out what group it falls into
580  for(UINT i=0; i<M; i++){
581  groupID = trainingData[i].getInputVector()[featureIndex] >= threshold ? 1 : 0;
582  groupIndex[i] = groupID;
583  groupMean[ groupID ] += trainingData[i].getInputVector()[featureIndex];
584  groupCounter[ groupID ]++;
585  }
586  groupMean[0] /= groupCounter[0] > 0 ? groupCounter[0] : 1;
587  groupMean[1] /= groupCounter[1] > 0 ? groupCounter[1] : 1;
588 
589  //Compute the MSE for each group
590  for(UINT i=0; i<M; i++){
591  groupMSE[ groupIndex[i] ] += grt_sqr( groupMean[ groupIndex[i] ] - trainingData[ i ].getInputVector()[features[n]] );
592  }
593  groupMSE[0] /= groupCounter[0] > 0 ? groupCounter[0] : 1;
594  groupMSE[1] /= groupCounter[1] > 0 ? groupCounter[1] : 1;
595 
596  error = sqrt( groupMSE[0] + groupMSE[1] );
597 
598  //Store the best threshold and feature index
599  if( error < minError ){
600  minError = error;
601  bestThreshold = threshold;
602  bestFeatureIndex = featureIndex;
603  }
604 
605  //Update the threshold
606  threshold += step;
607  }
608  }
609 
610  //Set the best feature index and threshold
611  featureIndex = bestFeatureIndex;
612  threshold = bestThreshold;
613 
614  return true;
615 }
616 
617 /*
618 bool RegressionTree::computeBestSpiltBestRandomSpilt( const RegressionData &trainingData, const Vector< UINT > &features, const Vector< UINT > &classLabels, UINT &featureIndex, Float &threshold, Float &minError ){
619 
620 const UINT M = trainingData.getNumSamples();
621 const UINT N = (UINT)features.size();
622 const UINT K = (UINT)classLabels.size();
623 
624 if( N == 0 ) return false;
625 
626 minError = numeric_limits<Float>::max();
627 UINT bestFeatureIndex = 0;
628 Float bestThreshold = 0;
629 Float error = 0;
630 Float giniIndexL = 0;
631 Float giniIndexR = 0;
632 Float weightL = 0;
633 Float weightR = 0;
634 Vector< UINT > groupIndex(M);
635 VectorFloat groupCounter(2,0);
636 Vector< MinMax > ranges = trainingData.getRanges();
637 
638 MatrixDouble classProbabilities(K,2);
639 
640 //Loop over each feature and try and find the best split point
641 for(UINT n=0; n<N; n++){
642 for(UINT m=0; m<numSplittingSteps; m++){
643 //Randomly choose the threshold
644 threshold = random.getRandomNumberUniform(ranges[n].minValue,ranges[n].maxValue);
645 
646 //Iterate over each sample and work out if it should be in the lhs (0) or rhs (1) group
647 groupCounter[0] = groupCounter[1] = 0;
648 classProbabilities.setAllValues(0);
649 for(UINT i=0; i<M; i++){
650 groupIndex[i] = trainingData[ i ][ features[n] ] >= threshold ? 1 : 0;
651 groupCounter[ groupIndex[i] ]++;
652 classProbabilities[ getClassLabelIndexValue(trainingData[i].getClassLabel()) ][ groupIndex[i] ]++;
653 }
654 
655 //Compute the class probabilities for the lhs group and rhs group
656 for(UINT k=0; k<K; k++){
657 classProbabilities[k][0] = groupCounter[0]>0 ? classProbabilities[k][0]/groupCounter[0] : 0;
658 classProbabilities[k][1] = groupCounter[1]>0 ? classProbabilities[k][1]/groupCounter[1] : 0;
659 }
660 
661 //Compute the Gini index for the lhs and rhs groups
662 giniIndexL = giniIndexR = 0;
663 for(UINT k=0; k<K; k++){
664 giniIndexL += classProbabilities[k][0] * (1.0-classProbabilities[k][0]);
665 giniIndexR += classProbabilities[k][1] * (1.0-classProbabilities[k][1]);
666 }
667 weightL = groupCounter[0]/M;
668 weightR = groupCounter[1]/M;
669 error = (giniIndexL*weightL) + (giniIndexR*weightR);
670 
671 //Store the best threshold and feature index
672 if( error < minError ){
673 minError = error;
674 bestThreshold = threshold;
675 bestFeatureIndex = n;
676 }
677 }
678 }
679 
680 //Set the best feature index and threshold
681 featureIndex = bestFeatureIndex;
682 threshold = bestThreshold;
683 
684 return true;
685 }
686 
687 */
688 
689 //Compute the regression data that will be stored at this node
690 bool RegressionTree::computeNodeRegressionData( const RegressionData &trainingData, VectorFloat &regressionData ){
691 
692  const UINT M = trainingData.getNumSamples();
693  const UINT N = trainingData.getNumInputDimensions();
694  const UINT T = trainingData.getNumTargetDimensions();
695 
696  if( M == 0 ){
697  Regressifier::errorLog << "computeNodeRegressionData(...) - Failed to compute regression data, there are zero training samples!" << std::endl;
698  return false;
699  }
700 
701  //Make sure the regression data is the correct size
702  regressionData.clear();
703  regressionData.resize( T, 0 );
704 
705  //The regression data at this node is simply an average over all the training data at this node
706  for(unsigned int j=0; j<N; j++){
707  for(unsigned int i=0; i<M; i++){
708  regressionData[j] += trainingData[i].getTargetVector()[j];
709  }
710  regressionData[j] /= M;
711  }
712 
713  return true;
714 }
715 
716 GRT_END_NAMESPACE
std::string getId() const
Definition: GRTBase.cpp:85
virtual bool predict(VectorFloat inputVector)
Definition: MLBase.cpp:135
bool setMinNumSamplesPerNode(const UINT minNumSamplesPerNode)
virtual bool print() const override
bool setMaxDepth(const UINT maxDepth)
Float getMinRMSErrorPerNode() const
virtual bool train_(RegressionData &trainingData) override
static std::string getId()
virtual bool predict_(VectorFloat &x) override
Definition: Node.cpp:56
virtual bool load(std::fstream &file) override
virtual bool deepCopyFrom(const Regressifier *regressifier) override
virtual bool clear() override
Vector< MinMax > getInputRanges() const
const RegressionTreeNode * getTree() const
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
bool getTrained() const
Definition: MLBase.cpp:294
virtual bool predict_(VectorFloat &inputVector) override
UINT getDepth() const
Definition: Node.cpp:304
UINT getMinNumSamplesPerNode() const
UINT getSize() const
Definition: Vector.h:201
bool copyBaseVariables(const Regressifier *regressifier)
UINT getNumInputDimensions() const
bool set(const UINT nodeSize, const UINT featureIndex, const Float threshold, const VectorFloat &regressionData)
bool getRemoveFeaturesAtEachSpilt() const
bool setTrainingMode(const Tree::TrainingMode trainingMode)
This class implements a basic Regression Tree.
UINT getPredictedNodeID() const
Vector< MinMax > getTargetRanges() const
bool saveBaseSettingsToFile(std::fstream &file) const
bool scale(const Float minTarget, const Float maxTarget)
UINT getNumTargetDimensions() const
bool setMinRMSErrorPerNode(const Float minRMSErrorPerNode)
RegressionTree & operator=(const RegressionTree &rhs)
virtual bool save(std::fstream &file) const override
Definition: Node.cpp:136
bool loadBaseSettingsFromFile(std::fstream &file)
bool setNumSplittingSteps(const UINT numSplittingSteps)
UINT getPredictedNodeID() const
Definition: Node.cpp:312
UINT getNumSplittingSteps() const
virtual bool clear() override
bool setRemoveFeaturesAtEachSpilt(const bool removeFeaturesAtEachSpilt)
virtual bool print() const override
Definition: Node.cpp:105
Node * tree
<Tell the compiler we are using the base class predict method to stop hidden virtual function warning...
RegressionTreeNode * deepCopyTree() const
virtual bool save(std::fstream &file) const override
RegressionTree(const UINT numSplittingSteps=100, const UINT minNumSamplesPerNode=5, const UINT maxDepth=10, const bool removeFeaturesAtEachSpilt=false, const Tree::TrainingMode trainingMode=Tree::BEST_ITERATIVE_SPILT, const bool useScaling=false, const Float minRMSErrorPerNode=0.01)
virtual bool load(std::fstream &file) override
Definition: Node.cpp:178
Tree::TrainingMode getTrainingMode() const
virtual ~RegressionTree(void)
UINT getMaxDepth() const
virtual bool clear() override
Definition: Node.cpp:66
bool addSample(const VectorFloat &inputVector, const VectorFloat &targetVector)
UINT getNumSamples() const
virtual Node * deepCopy() const
Definition: Node.cpp:272
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
Definition: GRTBase.h:184