Ask Your Question
0

Accessing and modifying OpenCV Decision Tree Nodes when using Adaboost

asked 2016-02-23 23:55:26 -0600

petermilani gravatar image

updated 2016-02-25 17:14:44 -0600

Hi All, I am learning a boosted tree from 30000 randomly generated features. The learning is limited to only say the best 100 features. After learning how do I extract from the CvBoost object, the indexes of the features used by the decision tree.

My motivation for doing this is to eliminate the requirement to generate all 30000 features and only compute those features that will be used. I've included a printout of the yml file generated from the CvBoost.save function. I think what I want is the value called sample_count which identifies the feature as shown below in a decision tree of depth 1:

 trees:
      -
         best_tree_idx: -1
         nodes:
            -
               depth: 0
               sample_count: 11556
               value: -1.8339875099775065e+00
               norm_class_idx: 0
               Tn: 0
               complexity: 0
               alpha: 0.
               node_risk: 0.
               tree_risk: 0.
               tree_error: 0.
               splits:
                  - { var:497, quality:8.6223608255386353e-01,
                      le:5.3123302459716797e+00 }
            -
               depth: 1
               sample_count: 10702
               value: -1.8339875099775065e+00
               norm_class_idx: 0
               Tn: 0
               complexity: 0
               alpha: 0.
               node_risk: 0.
               tree_risk: 0.
               tree_error: 0.
            -
               depth: 1
               sample_count: 854
               value: 1.8339875099775065e+00
               norm_class_idx: 1
               Tn: 0
               complexity: 0
               alpha: 0.
               node_risk: 0.
               tree_risk: 0.
               tree_error: 0.

EDIT

Currently I have the following code for accessing the data:

//Interrogate the Decision Tree. Each element is a Decision Tree, making up the classifer
    CvSeq* decisionTree = boostDevice.get_weak_predictors();

    simplifyFeatureSet(decisionTree, firstOrderROIs );

this function is:

inline void Chnftrs::simplifyFeatureSet(CvSeq* decisionTree, std::vector<boost::tuple<int, cv::Rect> >& rois)
{
    //This variable stores the index of the feature used from rois and a pointer to the split so that the variable there can
    //be updated when the rois are pruned and reordered.
    std::vector<boost::tuple<int, CvDTreeSplit* > > featureIdx;

    //Determine the max depth of the tree

    printf("Size of boost %d \n", decisionTree->total);

    for (int i = 0; i < decisionTree->total; i++)
    {
            //Get the root of the tree
            CvBoostTree *tree =0;
            tree = (CvBoostTree*)cvGetSeqElem(decisionTree, i);

            if(tree == 0)
                printf("Tree is NULL\n");
            else
                printf("Tree Addr %ld\n", tree);            

            const CvDTreeNode *root = tree->get_root();

            printf("Class_idx %d, Value %f ", root->sample_count, root->value);

            featureIdx.push_back(boost::tuple<int, CvDTreeSplit*>(root->split->var_idx, root->split)); 

                    //Search down the right hand side
            depthFirstSearch(root->right, featureIdx);

            //Search down the left hand side
            depthFirstSearch(root->left, featureIdx);


    }
}

However when I try to access any members of root such as in root->sample_count I get a segmentation fault. It may be that members of CvTree are unaccessible unless the CvTreeTrainData.shared is set to true (by default it is false). as indicated here

any help would be great

cheers

Peter

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-03-07 17:03:07 -0600

petermilani gravatar image

Okay,

Was able to edit the decision tree by following the methods in source for how the CvBoost classifier saved and read itself from disk. For some reason cvGetSeqElem() does not return valid pointers from the CvSeq object passed to it, for a Decision tree type object.

In order to get a copy of the the Decision Tree the CvSeqReader and the macro cvStartReadSeq worked best. The macro CV_READ_SEQ_ELEM() seems to update itself during the loop getting the next tree in the Seq.:

    CvSeqReader reader;
    cvStartReadSeq( weak, &reader );

     for (int i = 0; i < weak->total; i++)
        {

            CvBoostTree* tree;
            CV_READ_SEQ_ELEM( tree, reader );

                const CvDTreeNode *root = 0;
                root = tree->get_root();

                printf("Root Split VarIdx : %d c: %f, ", root->split->var_idx, root->split->ord.c);

                featureIdx.push_back(boost::tuple<int, CvDTreeSplit*>(root->split->var_idx, root->split)); 

                //Search down the right hand side
                depthFirstSearch(root->right, featureIdx);

                //Search down the left hand side
                depthFirstSearch(root->left, featureIdx);


        }
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-02-23 23:55:26 -0600

Seen: 506 times

Last updated: Mar 07 '16