123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /**
- * @file DecisionTree.cpp
- * @brief decision tree implementation
- * @author Erik Rodner
- * @date 04/24/2008
- */
- #include <iostream>
- #include "vislearning/classifier/fpclassifier/randomforest/DecisionTree.h"
- #include "vislearning/features/fpfeatures/createFeatures.h"
- using namespace OBJREC;
- using namespace std;
- // refactor-nice.pl: check this substitution
- // old: using namespace ice;
- using namespace NICE;
- DecisionTree::DecisionTree( const Config *_conf, int _maxClassNo ) : conf(_conf)
- {
- root = NULL;
- maxClassNo = _maxClassNo;
- }
- DecisionTree::~DecisionTree()
- {
- deleteNodes ( root );
- }
- void DecisionTree::statistics ( int & depth, int & count ) const
- {
- if ( root == NULL )
- {
- depth = 0;
- count = 0;
- } else {
- root->statistics ( depth, count );
- }
- }
- void DecisionTree::traverse (
- const Example & ce,
- FullVector & distribution )
- {
- assert(root != NULL);
- root->traverse ( ce, distribution );
- }
- void DecisionTree::deleteNodes ( DecisionNode *tree )
- {
- if ( tree != NULL )
- {
- deleteNodes ( tree->left );
- deleteNodes ( tree->right );
- delete tree;
- }
- }
- void DecisionTree::restore (istream & is, int format)
- {
- // indexing
- map<long, DecisionNode *> index;
- map<long, pair<long, long> > descendants;
- index.insert ( pair<long, DecisionNode *> ( 0, NULL ) );
- // refactor-nice.pl: check this substitution
- // old: string tag;
- std::string tag;
- while ( (! is.eof()) && ( (is >> tag) && (tag == "NODE") ) )
- {
- long ind;
- long ind_l;
- long ind_r;
- if (! (is >> ind)) break;
- if (! (is >> ind_l)) break;
- if (! (is >> ind_r)) break;
-
- descendants.insert ( pair<long, pair<long, long> > ( ind, pair<long, long> ( ind_l, ind_r ) ) );
- DecisionNode *node = new DecisionNode();
- index.insert ( pair<long, DecisionNode *> ( ind, node ) );
-
- std::string feature_tag;
-
- is >> feature_tag;
- if ( feature_tag != "LEAF" )
- {
- node->f = createFeatureFromTag ( conf, feature_tag );
- if ( node->f == NULL )
- {
- fprintf (stderr, "Unknown feature description: %s\n",
- feature_tag.c_str() );
- exit(-1);
- }
- node->f->restore ( is, format );
- is >> node->threshold;
- }
-
- FullVector distribution ( maxClassNo+1 );
- int classno;
- double score;
-
- //distribution.restore ( is );
- is >> classno;
- while ( classno >= 0 )
- {
- is >> score;
- if ( classno > maxClassNo )
- {
- fprintf (stderr, "classno: %d; maxClassNo: %d\n", classno, maxClassNo);
- exit(-1);
- }
- distribution[classno] = score;
- is >> classno;
- }
- //distribution.store(cerr);
- node->distribution = distribution;
- }
- // connecting the tree
- for ( map<long, DecisionNode *>::const_iterator i = index.begin();
- i != index.end(); i++ )
- {
- DecisionNode *node = i->second;
- if ( node == NULL ) continue;
- long ind_l = descendants[i->first].first;
- long ind_r = descendants[i->first].second;
- map<long, DecisionNode *>::const_iterator il = index.find ( ind_l );
- map<long, DecisionNode *>::const_iterator ir = index.find ( ind_r );
- if ( ( il == index.end() ) || ( ir == index.end() ) )
- {
- fprintf (stderr, "File inconsistent: unable to build tree\n");
- exit(-1);
- }
- DecisionNode *left = il->second;
- DecisionNode *right = ir->second;
- node->left = left;
- node->right = right;
- }
-
- map<long, DecisionNode *>::const_iterator iroot = index.find ( 1 );
- if ( iroot == index.end() )
- {
- fprintf (stderr, "File inconsistent: unable to build tree (root node not found)\n");
- exit(-1);
- }
- root = iroot->second;
- }
- void DecisionTree::store (ostream & os, int format) const
- {
- if ( root == NULL ) return;
- // indexing
- map<DecisionNode *, pair<long, int> > index;
- index.insert ( pair<DecisionNode *, pair<long, int> > ( NULL, pair<long, int> ( 0, 0 ) ) );
- index.insert ( pair<DecisionNode *, pair<long, int> > ( root, pair<long, int> ( 1, 0 ) ) );
- long maxindex = 1;
- root->indexDescendants ( index, maxindex, 0 );
- for ( map<DecisionNode *, pair<long, int> >::iterator i = index.begin();
- i != index.end();
- i++ )
- {
- DecisionNode *node = i->first;
- if ( node == NULL ) continue;
- long ind = i->second.first;
- long ind_l = index[ node->left ].first;
- long ind_r = index[ node->right ].first;
- os << "NODE " << ind << " " << ind_l << " " << ind_r << endl;
- Feature *f = node->f;
- if ( f != NULL ) {
- f->store ( os, format );
- os << endl;
- os << node->threshold;
- os << endl;
- } else {
- os << "LEAF";
- os << endl;
- }
- const FullVector & distribution = node->distribution;
- for ( int i = 0 ; i < distribution.size() ; i++ )
- os << i << " " << distribution[i] << " ";
- os << -1 << endl;
- //distribution.store ( os );
- }
- }
- void DecisionTree::clear ()
- {
- deleteNodes ( root );
- }
- void DecisionTree::resetCounters ()
- {
- if ( root != NULL )
- root->resetCounters ();
- }
-
- void DecisionTree::indexDescendants ( map<DecisionNode *, pair<long, int> > & index, long & maxindex ) const
- {
- if ( root != NULL )
- root->indexDescendants ( index, maxindex, 0 );
- }
- DecisionNode *DecisionTree::getLeafNode ( Example & pce, int maxdepth )
- {
- return root->getLeafNode ( pce, maxdepth );
- }
- void DecisionTree::getLeaves(DecisionNode *node, vector<DecisionNode*> &leaves)
- {
- if(node->left == NULL && node->right == NULL)
- {
- leaves.push_back(node);
- return;
- }
- getLeaves(node->right, leaves);
- getLeaves(node->left, leaves);
- }
- vector<DecisionNode *> DecisionTree::getAllLeafNodes()
- {
- vector<DecisionNode*> leaves;
- getLeaves(root, leaves);
- return leaves;
- }
- DecisionNode *DecisionTree::pruneTreeEntropy ( DecisionNode *node, double minEntropy )
- {
- if ( node == NULL ) return NULL;
- double entropy = node->distribution.entropy();
- if ( entropy < minEntropy )
- {
- deleteNodes ( node );
- return NULL;
- } else {
- node->left = pruneTreeEntropy ( node->left, minEntropy );
- node->right = pruneTreeEntropy ( node->right, minEntropy );
- return node;
- }
- }
- DecisionNode *DecisionTree::pruneTreeScore ( DecisionNode *node, double minScore )
- {
- if ( node == NULL ) return NULL;
- double score = node->distribution.max();
- if ( score < minScore )
- {
- deleteNodes ( node );
- return NULL;
- } else {
- node->left = pruneTreeScore ( node->left, minScore );
- node->right = pruneTreeScore ( node->right, minScore );
- return node;
- }
- }
- void DecisionTree::pruneTreeScore ( double minScore )
- {
- int depth, count;
- statistics ( depth, count );
- fprintf (stderr, "DecisionTree::pruneTreeScore: depth %d count %d\n", depth, count );
- root = pruneTreeScore ( root, minScore );
- statistics ( depth, count );
- fprintf (stderr, "DecisionTree::pruneTreeScore: depth %d count %d (modified)\n", depth, count );
- }
- void DecisionTree::pruneTreeEntropy ( double minEntropy )
- {
- int depth, count;
- statistics ( depth, count );
- fprintf (stderr, "DecisionTree::entropyTreeScore: depth %d count %d\n", depth, count );
- root = pruneTreeEntropy ( root, minEntropy );
- statistics ( depth, count );
- fprintf (stderr, "DecisionTree::entropyTreeScore: depth %d count %d (modified)\n", depth, count );
- }
- void DecisionTree::normalize (DecisionNode *node)
- {
- if ( node != NULL )
- {
- node->distribution.normalize();
- normalize ( node->left );
- normalize ( node->right );
- }
- }
- void DecisionTree::normalize ()
- {
- normalize ( root );
- }
- void DecisionTree::setRoot ( DecisionNode *newroot )
- {
- root = newroot;
- }
|