OpenCv中基于决策树的分类任务代码解读(二)

/*****************************************************************************************************************
文件说明:
        OpenCv中,决策树训练程序的分析
开发环境:
        Vs2012+OpenCv2.4.9+Win10
时间地点:
        陕西师范大学 问津楼 2017.5.18
作    者:
        九 月
******************************************************************************************************************/
#include "opencv2/core/core_c.h"
#include "opencv2/ml/ml.hpp"
#include <stdio.h>
#include <assert.h>
#include <iostream>

static void help()
{
	std::cout<<"[1]This program demonstrated the use of OpenCv's decision tree function for learning and predicating data."<<std::endl;
	std::cout<<"[2]The sample demonstrates how to build a decision tree for classifying mushrooom."<<std::endl;
	std::cout<<"[3]loads the mushroom database, which is a text file, containing"<<std::endl;
	std::cout<<"[4]one training sample per row, all the input variables and the output variable are categorical"<<std::endl;
	std::cout<<"[5]the values are encoded by characters"<<std::endl;
}
/*****************************************************************************************************************
函数原型:
        static int mushroom_read_database( const char* filename, CvMat** data, CvMat** missing, CvMat** responses )
函数功能:
        从文件araricuslepiota.data中读取数据,这个函数过于特殊,并不具有通用性,他只对三个数组进行赋值:
		   1)浮点数组data[][]:数组的行数是数据样本的数目,列数是特征的数目(这里是22),所有的特征都从类别字母转换为
		         浮点数字
		   2)单字节类型矩阵missing[][]:用"true"或者"1"表示数据文件里的缺失特征,缺失特征在数据文件中里用问号表示,
		         本数组的其他值为0
		   3)浮点向量responses[],里面包含有毒p的字符和无毒的字符e对应的浮点值
参数说明:
        1)const char* filename------训练数据样本的文件路径
		2)CvMat** data--------------用于存储数据样本的数组,行数为样本的个数,列数为特征属性的个数
		3)CvMat** missing-----------用于存储数据文件缺失特征的矩阵
		4)CvMat** responses---------浮点向量,用于表示有毒和无毒
******************************************************************************************************************/
static int mushroom_read_database( const char* filename, CvMat** data, CvMat** missing, CvMat** responses )
{
    const int M = 1024;
    FILE* f      = fopen( filename, "rt" );
    
	CvMemStorage* storage = NULL;
    CvSeq*        seq     = NULL;
    
	char         buf[M+2];
	char*        ptr     = NULL;
    float*       el_ptr  = NULL;
    CvSeqReader   reader;

    int    i;
	int    j;
	int    var_count = 0;

    if(!f )
	{
		std::cout<<"[Notice]The data file fails to open!"<<std::endl;
        return 0;
	}

    if( !fgets( buf, M, f ))                     //[1]read the first line and determine the number of variables
    {
		std::cout<<"[Notice]The data fails to read!"<<std::endl;
        fclose(f);
        return 0;
    }

    for( ptr = buf; *ptr != '\0'; ptr++ )
	{
        var_count += (*ptr == ',');
	}
	std::cout<<"[Information]The number of characteristic attributes in training data = "<<var_count<<std::endl;
    assert( ptr - buf == (var_count+1)*2 );      //[2]特征属性23个,逗号分隔符22个,字符串结束符\0,故ptr-buf==46个字节

    el_ptr  = new float[var_count+1];           //[3]create temporary memory storage to store the whole database
    storage = cvCreateMemStorage();
    seq     = cvCreateSeq( 0, sizeof(*seq), (var_count+1)*sizeof(float), storage );

    for(;;)
    {
        for( i = 0; i <= var_count; i++ )
        {
            int c = buf[i*2];
            el_ptr[i] = (c == '?') ? -1.f : (float)c;
        }
        if( i != var_count+1 )
		{
            break;
		}
        cvSeqPush( seq, el_ptr );
        if( !fgets( buf, M, f ) || !strchr( buf, ',' ) )
		{
            break;
		}
    }
    fclose(f);
	std::cout<<"[Information]The number of training sample = "<<seq->total<<std::endl;
                                                //[4]allocate the output matrices and copy the base there
    *data      = cvCreateMat( seq->total, var_count, CV_32F );   //[1]用于存储训练所需要的全部样本
    *missing   = cvCreateMat( seq->total, var_count, CV_8U );    //[2]存储缺失的特征
    *responses = cvCreateMat( seq->total, 1, CV_32F );           //[3]存储类别标签

    cvStartReadSeq( seq, &reader );

    for( i = 0; i < seq->total; i++ )
    {
        const float* sdata = (float*)reader.ptr + 1;

        float* ddata = data[0]->data.fl + var_count*i;
        float* dr    = responses[0]->data.fl + i;
        
		uchar* dm     = missing[0]->data.ptr + var_count*i;

        for( j = 0; j < var_count; j++ )
        {
            ddata[j] = sdata[j];
            dm[j]    = sdata[j] < 0;
        }
        *dr = sdata[-1];                        //[5]数组下标为-1,这个对于静态数组来说,是数组的越界访问,但此块这个是有意义的
		                                        //   代表的是这个数组首地址向前偏移一个存储空间的地址
        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
    }

    cvReleaseMemStorage( &storage );
    delete [] el_ptr;
    return 1;
}
/*****************************************************************************************************************
函数原型:
       static CvDTree* mushroom_create_dtree( const CvMat* data, const CvMat* missing,const CvMat* responses, 
	                                          float p_weight )
函数说明:
       创建决策树
参数说明:
       1)const CvMat* data--------训练样本的所有数据
	   2)const CvMat* missing-----缺失的特征数据
	   3)const CvMat* responses---类别标签
	   4)float p_weight-----------权重
******************************************************************************************************************/
static CvDTree* mushroom_create_dtree( const CvMat* data, const CvMat* missing,const CvMat* responses, float p_weight )
{
    CvDTree* dtree;                                     //[1]定义一个决策树类的类对象指针
    CvMat*   var_type;                                  //[2]变量的类型

    int      i        = 0;
	int      hr1      = 0;
	int      hr2      = 0;
	int      p_total  = 0;

    float    priors[] = { 1, p_weight };

    var_type = cvCreateMat( data->cols + 1, 1, CV_8U ); //[3]创建一个行向量

    cvSet( var_type, cvScalarAll(CV_VAR_CATEGORICAL) ); //[4]all the variables are categorical

    dtree = new CvDTree;                                //[5]实例化类对象
    //【1】开始训练决策树
    dtree->train( data,                                 //[1]训练样本数据
		          CV_ROW_SAMPLE,                        //[2]行为样本向量,列为特征属性
				  responses,                            //[3]类别标签
				  0,                                    //[4]varIdx
				  0,                                    //[5]sampleIdx
				  var_type,                             //[6]输出的值是数值类型
				  missing,                              //[7]缺失的数据
                  CvDTreeParams( 8,                     //[1]树的最大可能深度---------max depth
                                 10,                    //[2]每个节点最小的样本数量---min sample count
                                 0,                     //[3]回归树的终止标准---------regression accuracy: N/A here
                                 true,                 //[4]计算代理分割和变量的重要性compute surrogate split, as we have missing data
                                 15,                    //[5]最大的分类类别max number of categories (use sub-optimal algorithm for larger numbers)
                                 10,                    //[6]进行交叉验证修剪树the number of cross-validation folds
                                 true,                 //[7]更加严格的修剪树,使树更紧凑use 1SE rule => smaller tree
                                 true,                 //[8]移除修剪之后的树的分支-----throw away the pruned tree branches
                                 priors                 //[9]错误分类的代价-------------the array of priors, the bigger p_weight, the more attention
                                                        // to the poisonous mushrooms(a mushroom will be judjed to be poisonous with bigger chance)
                                 ));
    //【2】计算训练数据集合中的命中率compute hit-rate on the training database, demonstrates predict usage.
	std::cout<<data->rows<<std::endl;
    for( i = 0; i < data->rows; i++ )
    {
        CvMat   sample;
		CvMat   mask;
        cvGetRow( data,    &sample, i );                //[1]cvGetRow取出指定行的地址,让sample指向这个地址
        cvGetRow( missing, &mask, i );
		double r = dtree->predict( &sample, &mask )->value;
        int    d = fabs(r - responses->data.fl[i]) > FLT_EPSILON;
        if( d )                                                         //[0]进入这个分支语句块,说明分类错误
        {
            if( r == 'p' )                                              //[1]将无毒的误认为有毒的
			{
                hr2++;
			}
            else                                                        //[2]将有毒的误认为无毒的
			{
				hr1++;
			}
        }
        p_total += responses->data.fl[i] == 'p';                         //[3]毒蘑菇的总数,这个是提供的监督学习的标签总数
    }
	double poisonousMisPreditc = (double)hr1*100/p_total;               //[4]将有毒的误认为无毒的概率
	double unPoisonousMisPredi = (double)hr2*100/(data->rows - p_total);//[5]将无毒的误认为有毒的概率

	std::cout<<"[Information]Poisonous   mushrooms mis-predicted:"<<hr1<<"个----"<<poisonousMisPreditc<<std::endl;
	std::cout<<"[Information]unPoisonous mushrooms mis-predicted:"<<hr2<<"个----"<<unPoisonousMisPredi<<std::endl;

    cvReleaseMat( &var_type );
    return dtree;
}


static const char* var_desc[] =
{
    "[1]cap shape (bell=b,conical=c,convex=x,flat=f)",
    "[2]cap surface (fibrous=f,grooves=g,scaly=y,smooth=s)",
    "[3]cap color (brown=n,buff=b,cinnamon=c,gray=g,green=r,\n\tpink=p,purple=u,red=e,white=w,yellow=y)",
    "[4]bruises? (bruises=t,no=f)",
    "[5]odor (almond=a,anise=l,creosote=c,fishy=y,foul=f,\n\tmusty=m,none=n,pungent=p,spicy=s)",
    "[6]gill attachment (attached=a,descending=d,free=f,notched=n)",
    "[7]gill spacing (close=c,crowded=w,distant=d)",
    "[8]gill size (broad=b,narrow=n)",
    "[9]gill color (black=k,brown=n,buff=b,chocolate=h,gray=g,\n\tgreen=r,orange=o,pink=p,purple=u,red=e,white=w,yellow=y)",
    "[10]stalk shape (enlarging=e,tapering=t)",
    "[11]stalk root (bulbous=b,club=c,cup=u,equal=e,rhizomorphs=z,rooted=r)",
    "[12]stalk surface above ring (ibrous=f,scaly=y,silky=k,smooth=s)",
    "[13]stalk surface below ring (ibrous=f,scaly=y,silky=k,smooth=s)",
    "[14]stalk color above ring (brown=n,buff=b,cinnamon=c,gray=g,orange=o,\n\tpink=p,red=e,white=w,yellow=y)",
    "[15]stalk color below ring (brown=n,buff=b,cinnamon=c,gray=g,orange=o,\n\tpink=p,red=e,white=w,yellow=y)",
    "[16]veil type (partial=p,universal=u)",
    "[17]veil color (brown=n,orange=o,white=w,yellow=y)",
    "[18]ring number (none=n,one=o,two=t)",
    "[19]ring type (cobwebby=c,evanescent=e,flaring=f,large=l,\n\tnone=n,pendant=p,sheathing=s,zone=z)",
    "[20]spore print color (black=k,brown=n,buff=b,chocolate=h,green=r,\n\torange=o,purple=u,white=w,yellow=y)",
    "[21]population (abundant=a,clustered=c,numerous=n,\n\tscattered=s,several=v,solitary=y)",
    "[22]habitat (grasses=g,leaves=l,meadows=m,paths=p\n\turban=u,waste=w,woods=d)",
    0
};
/*****************************************************************************************************************
函数原型:
      static void print_variable_importance( CvDTree* dtree )
函数说明:
       输出变量的重要性
参数说明:
       CvDTree* dtree-------训练好的决策树模型
函数说明:
       virtual const CvMat* get_var_importance()
函数说明:
       这个函数返回一个N*1的双精度向量(CV_64FC1),向量包含每个特征的重要性,1代表最重要,0代表完全不重要,不重要的
	   特征在第二次训练中可以排除。
******************************************************************************************************************/
static void print_variable_importance( CvDTree* dtree )
{
    const CvMat* var_importance = dtree->get_var_importance();//[1]获得一个N*1的双精度向量,向量包含每个特征的重要性
    int   i;
    char  input[1000];

    if( !var_importance )
    {
        printf( "Error: Variable importance can not be retrieved\n" );
        return;
    }
	std::cout<<"[Information]Print variable importance information? (y/n)"<<std::endl;
    int values_read = scanf( "%1s", input );
	CV_Assert(values_read == 1);

    if( input[0] != 'y' && input[0] != 'Y' )
	{
        return;
	}

    for( i = 0; i < var_importance->cols*var_importance->rows; i++ )
    {
        double val = var_importance->data.db[i];
        char   buf[100];
        int    len = (int)(strchr( var_desc[i], '(' ) - var_desc[i] - 1);
        strncpy( buf, var_desc[i], len );
        buf[len] = '\0';
        printf( "%s", buf );
        printf( ": %g%%\n", val*100. );
    }
}
/*****************************************************************************************************************
函数原型:
      static void interactive_classification( CvDTree* dtree )
函数说明:
       交互式分类
参数说明:
       CvDTree* dtree----已经构建并且训练好的决策树
******************************************************************************************************************/
static void interactive_classification( CvDTree* dtree )
{
    char  input[1000];
    const CvDTreeNode*   root;                 //[1]定义一个决策树节点类的类对象指针(动态的分配类对象的存储空间)
    CvDTreeTrainData*    data;                  //[2]定义一个决策树训练数据类对象的对象指针

    if( !dtree )
	{
        return;
	}

    root = dtree->get_root();                   //[3]得到这个决策树的根节点
    data = dtree->get_data();                   //[4]得到训练这个决策树的训练数据

    for(;;)
    {
        const CvDTreeNode* node;
		std::cout<<"[Information]Start/Proceed with interactive mushroom classification (y/n): "<<std::endl;
        int values_read = scanf( "%1s", input );
        CV_Assert(values_read == 1);

        if( input[0] != 'y' && input[0] != 'Y' )
		{
            break;
		}
		std::cout<<"[Information]Enter 1-letter answers, '?' for missing/unknown value... "<<std::endl;
        /*****************************************************************************************************
		模块说明:
		        1)custom version of predict
				2)自定义版本的预测
		******************************************************************************************************/
        node = root;
        for(;;)
        {
            CvDTreeSplit* split = node->split;     //[1]指向分裂节点列表中,第一个分裂节点的地址
            int dir = 0;
			                                       //[2]如果这个节点的左子树为空或者分裂列表为空或者Tn小于
            if( !node->left || node->Tn <= dtree->get_pruned_tree_idx() || !node->split )
			{
                break;
			}
			                                       //[3]如果分裂列表不为空,则对节点中的数据进行分裂
            for( ; split != 0; )
            {
                int vi    = split->var_idx;
				int j     = 0;
                int count = data->cat_count->data.i[vi];
                const int* map = data->cat_map->data.i + data->cat_ofs->data.i[vi];

                printf( "%s: ", var_desc[vi] );
                values_read = scanf( "%1s", input );
                CV_Assert(values_read == 1);

                if( input[0] == '?' )
                {
                    split = split->next;
                    continue;
                }

                // convert the input character to the normalized value of the variable
                for( j = 0; j < count; j++ )
				{
                    if( map[j] == input[0] )
                        break;
				}
                if( j < count )
                {
                    dir = (split->subset[j>>5] & (1 << (j&31))) ? -1 : 1;
                    if( split->inversed )
                        dir = -dir;
                    break;
                }
                else
                    printf( "Error: unrecognized value\n" );
            }

            if( !dir )
            {
                printf( "Impossible to classify the sample\n");
                node = 0;
                break;
            }
            node = dir < 0 ? node->left : node->right;
        }

        if( node )
            printf( "Prediction result: the mushroom is %s\n",node->class_idx == 0 ? "EDIBLE" : "POISONOUS" );
        printf( "\n-----------------------------\n" );
    }
}


int main( int argc, char** argv )
{
	const char* base_path = argc >= 2 ? argv[1] : "agaricus-lepiota.data";
	help();

    CvMat*   data        = 0;                                   //[1]训练样本的所有训练数据
	CvMat*   missing     = 0;                                   //[2]训练样本中的缺失特征
	CvMat*   responses   = 0;                                   //[3]特征所对应的类别标签
	CvDTree* dtree       = NULL;                                //[4]构建的决策树
	//[1]Load the training database
    if( !mushroom_read_database( base_path, &data, &missing, &responses ) )
    {
        printf( "\nUnable to load the training database\n\n");
        help();
        return -1;
    }
	//[2]create decision tree
    dtree = mushroom_create_dtree( data, missing, responses,10);//[5]poisonous mushrooms will have 10x higher weight in the decision tree
    cvReleaseMat( &data );
    cvReleaseMat( &missing );
    cvReleaseMat( &responses );
	dtree->save("decisionTree.xml");                            //[6]Save trained decision tree model
	//[3]Print the importance of variables
    print_variable_importance( dtree );
	//[4]interactive classification
    interactive_classification( dtree );

    return 0;
}

训练好的决策树模型如下所示:

<?xml version="1.0"?>
<opencv_storage>
<my_tree type_id="opencv-ml-tree">
  <is_classifier>1</is_classifier>
  <var_all>22</var_all>
  <var_count>22</var_count>
  <ord_var_count>0</ord_var_count>
  <cat_var_count>22</cat_var_count>
  <training_params>
    <use_surrogates>1</use_surrogates>
    <max_categories>15</max_categories>
    <max_depth>8</max_depth>
    <min_sample_count>10</min_sample_count>
    <cross_validation_folds>10</cross_validation_folds>
    <use_1se_rule>1</use_1se_rule>
    <truncate_pruned_tree>1</truncate_pruned_tree>
    <priors type_id="opencv-matrix">
      <rows>1</rows>
      <cols>2</cols>
      <dt>d</dt>
      <data>
        9.0909090909090912e-002 9.0909090909090917e-001</data></priors></training_params>
  <var_type>
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1</var_type>
  <cat_count type_id="opencv-matrix">
    <rows>1</rows>
    <cols>23</cols>
    <dt>i</dt>
    <data>
      6 4 10 2 9 2 2 2 12 2 4 4 4 9 9 1 4 3 5 9 6 7 2</data></cat_count>
  <cat_map type_id="opencv-matrix">
    <rows>1</rows>
    <cols>118</cols>
    <dt>i</dt>
    <data>
      98 99 102 107 115 120 102 103 115 121 98 99 101 103 110 112 114
      117 119 121 102 116 97 99 102 108 109 110 112 115 121 97 102 99
      119 98 110 98 101 103 104 107 110 111 112 114 117 119 121 101 116
      98 99 101 114 102 107 115 121 102 107 115 121 98 99 101 103 110
      111 112 119 121 98 99 101 103 110 111 112 119 121 112 110 111 119
      121 110 111 116 101 102 108 110 112 98 104 107 110 111 114 117 119
      121 97 99 110 115 118 121 100 103 108 109 112 117 119 101 112</data></cat_map>
  <best_tree_idx>0</best_tree_idx>
  <nodes>
    <_>
      <depth>0</depth>
      <sample_count>8124</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>6</Tn>
      <complexity>2</complexity>
      <alpha>1.9516601443603793e+002</alpha>
      <node_risk>3.5826002261066151e+002</node_risk>
      <tree_risk>1.2716584050787026e+002</tree_risk>
      <tree_error>1.5552656752761109e+001</tree_error>
      <splits>
        <_><var>4</var>
          <quality>3.7367382812500000e+003</quality>
          <in>
            0 3 4 5</in></_>
        <_><var>17</var>
          <quality>3.3980202636718750e+003</quality>
          <not_in>
            1</not_in></_>
        <_><var>20</var>
          <quality>3.3933579101562500e+003</quality>
          <not_in>
            3 4 5</not_in></_>
        <_><var>14</var>
          <quality>3.3835061035156250e+003</quality>
          <in>
            1 2 3 5 8</in></_>
        <_><var>13</var>
          <quality>3.3696267089843750e+003</quality>
          <in>
            1 2 3 5 8</in></_>
        <_><var>12</var>
          <quality>3.3444282226562500e+003</quality>
          <in>
            3</in></_>
        <_><var>0</var>
          <quality>3.3420148925781250e+003</quality>
          <not_in>
            2 3 5</not_in></_>
        <_><var>19</var>
          <quality>3.3396667480468750e+003</quality>
          <in>
            0 4 5 6 8</in></_>
        <_><var>8</var>
          <quality>3.3326784667968750e+003</quality>
          <in>
            1 6 8 10 11</in></_>
        <_><var>21</var>
          <quality>3.3291037597656250e+003</quality>
          <in>
            3 6</in></_>
        <_><var>18</var>
          <quality>3.2968125000000000e+003</quality>
          <in>
            1 3</in></_>
        <_><var>5</var>
          <quality>3.2928229980468750e+003</quality>
          <not_in>
            1</not_in></_>
        <_><var>6</var>
          <quality>3.2891840820312500e+003</quality>
          <not_in>
            0</not_in></_>
        <_><var>16</var>
          <quality>3.2841481933593750e+003</quality>
          <not_in>
            2</not_in></_>
        <_><var>2</var>
          <quality>3.2772849121093750e+003</quality>
          <in>
            1 6 7</in></_>
        <_><var>11</var>
          <quality>3.2699399414062500e+003</quality>
          <in>
            3</in></_>
        <_><var>1</var>
          <quality>3.2651784667968750e+003</quality>
          <in>
            1</in></_></splits></_>
    <_>
      <depth>1</depth>
      <sample_count>4364</sample_count>
      <value>101.</value>
      <norm_class_idx>0</norm_class_idx>
      <Tn>5</Tn>
      <complexity>1</complexity>
      <alpha>8.3490129576484932e+001</alpha>
      <node_risk>1.4271849726063135e+002</node_risk>
      <tree_risk>1.2716584050787026e+002</tree_risk>
      <tree_error>1.5552656752761109e+001</tree_error>
      <splits>
        <_><var>19</var>
          <quality>4.2798199462890625e+002</quality>
          <not_in>
            5 7</not_in></_>
        <_><var>17</var>
          <quality>3.8697598266601562e+002</quality>
          <in>
            1</in></_>
        <_><var>8</var>
          <quality>3.5670404052734375e+002</quality>
          <in>
            3 4 5 6 7 9</in></_>
        <_><var>9</var>
          <quality>3.5234011840820312e+002</quality>
          <not_in>
            0</not_in></_>
        <_><var>14</var>
          <quality>3.3520046997070312e+002</quality>
          <in>
            3 5 6 7</in></_>
        <_><var>11</var>
          <quality>3.3520046997070312e+002</quality>
          <not_in>
            1 3</not_in></_>
        <_><var>12</var>
          <quality>3.2123580932617187e+002</quality>
          <not_in>
            1 3</not_in></_>
        <_><var>2</var>
          <quality>3.2094995117187500e+002</quality>
          <not_in>
            0 1 5</not_in></_>
        <_><var>0</var>
          <quality>3.1832653808593750e+002</quality>
          <not_in>
            0 1 3</not_in></_>
        <_><var>20</var>
          <quality>3.1568289184570312e+002</quality>
          <not_in>
            1 4</not_in></_>
        <_><var>13</var>
          <quality>3.0669943237304687e+002</quality>
          <in>
            3 5 6 7</in></_>
        <_><var>18</var>
          <quality>2.9230087280273437e+002</quality>
          <not_in>
            2 3</not_in></_>
        <_><var>4</var>
          <quality>2.9230087280273437e+002</quality>
          <in>
            0 3 5</in></_>
        <_><var>21</var>
          <quality>2.8967745971679687e+002</quality>
          <not_in>
            2 3 6</not_in></_>
        <_><var>7</var>
          <quality>2.8771493530273437e+002</quality>
          <not_in>
            1</not_in></_>
        <_><var>16</var>
          <quality>2.7041720581054687e+002</quality>
          <not_in>
            3</not_in></_>
        <_><var>3</var>
          <quality>2.6886837768554687e+002</quality>
          <not_in>
            0</not_in></_>
        <_><var>1</var>
          <quality>2.6729098510742187e+002</quality>
          <not_in>
            1</not_in></_>
        <_><var>5</var>
          <quality>2.6426815795898437e+002</quality>
          <not_in>
            0</not_in></_></splits></_>
    <_>
      <depth>2</depth>
      <sample_count>3632</sample_count>
      <value>101.</value>
      <norm_class_idx>0</norm_class_idx>
      <Tn>2147483647</Tn>
      <complexity>1</complexity>
      <alpha>0.</alpha>
      <node_risk>0.</node_risk>
      <tree_risk>0.</tree_risk>
      <tree_error>0.</tree_error></_>
    <_>
      <depth>2</depth>
      <sample_count>732</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>4</Tn>
      <complexity>1</complexity>
      <alpha>2.4179146012696748e+001</alpha>
      <node_risk>4.9039394729976522e+001</node_risk>
      <tree_risk>4.3675710931385325e+001</tree_risk>
      <tree_error>5.3636837985911825e+000</tree_error>
      <splits>
        <_><var>20</var>
          <quality>1.5394233703613281e+002</quality>
          <not_in>
            1 4</not_in></_>
        <_><var>12</var>
          <quality>1.4191304016113281e+002</quality>
          <in>
            1</in></_>
        <_><var>2</var>
          <quality>1.4191304016113281e+002</quality>
          <in>
            3</in></_>
        <_><var>8</var>
          <quality>1.3863232421875000e+002</quality>
          <in>
            7</in></_>
        <_><var>6</var>
          <quality>1.3672332763671875e+002</quality>
          <not_in>
            0</not_in></_>
        <_><var>13</var>
          <quality>1.3316447448730469e+002</quality>
          <in>
            4</in></_>
        <_><var>21</var>
          <quality>1.3261767578125000e+002</quality>
          <in>
            4</in></_></splits></_>
    <_>
      <depth>3</depth>
      <sample_count>320</sample_count>
      <value>101.</value>
      <norm_class_idx>0</norm_class_idx>
      <Tn>2147483647</Tn>
      <complexity>1</complexity>
      <alpha>0.</alpha>
      <node_risk>0.</node_risk>
      <tree_risk>0.</tree_risk>
      <tree_error>0.</tree_error></_>
    <_>
      <depth>3</depth>
      <sample_count>412</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>3</Tn>
      <complexity>1</complexity>
      <alpha>1.5920775719627784e+001</alpha>
      <node_risk>2.1795286546656229e+001</node_risk>
      <tree_risk>1.9496564918688577e+001</tree_risk>
      <tree_error>2.2987216279676481e+000</tree_error>
      <splits>
        <_><var>21</var>
          <quality>1.5656806945800781e+002</quality>
          <in>
            4 5 6</in></_>
        <_><var>14</var>
          <quality>1.4749317932128906e+002</quality>
          <in>
            2</in></_>
        <_><var>13</var>
          <quality>1.4749317932128906e+002</quality>
          <in>
            2</in></_>
        <_><var>8</var>
          <quality>1.4749317932128906e+002</quality>
          <in>
            1</in></_>
        <_><var>2</var>
          <quality>1.4003878784179687e+002</quality>
          <in>
            3</in></_></splits></_>
    <_>
      <depth>4</depth>
      <sample_count>208</sample_count>
      <value>101.</value>
      <norm_class_idx>0</norm_class_idx>
      <Tn>2147483647</Tn>
      <complexity>1</complexity>
      <alpha>0.</alpha>
      <node_risk>0.</node_risk>
      <tree_risk>0.</tree_risk>
      <tree_error>0.</tree_error></_>
    <_>
      <depth>4</depth>
      <sample_count>204</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>2</Tn>
      <complexity>1</complexity>
      <alpha>1.7027567614575219e+000</alpha>
      <node_risk>4.0866162274980411e+000</node_risk>
      <tree_risk>3.5757891990607931e+000</tree_risk>
      <tree_error>5.1082702843725514e-001</tree_error>
      <splits>
        <_><var>11</var>
          <quality>1.4277618408203125e+002</quality>
          <in>
            0</in></_></splits></_>
    <_>
      <depth>5</depth>
      <sample_count>24</sample_count>
      <value>101.</value>
      <norm_class_idx>0</norm_class_idx>
      <Tn>2147483647</Tn>
      <complexity>1</complexity>
      <alpha>0.</alpha>
      <node_risk>0.</node_risk>
      <tree_risk>0.</tree_risk>
      <tree_error>0.</tree_error></_>
    <_>
      <depth>5</depth>
      <sample_count>180</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>1</Tn>
      <complexity>1</complexity>
      <alpha>8.5137838072876093e-001</alpha>
      <node_risk>2.0433081137490205e+000</node_risk>
      <tree_risk>1.8730324376032712e+000</tree_risk>
      <tree_error>1.7027567614575112e-001</tree_error>
      <splits>
        <_><var>12</var>
          <quality>1.4273301696777344e+002</quality>
          <in>
            0</in></_></splits></_>
    <_>
      <depth>6</depth>
      <sample_count>12</sample_count>
      <value>101.</value>
      <norm_class_idx>0</norm_class_idx>
      <Tn>2147483647</Tn>
      <complexity>1</complexity>
      <alpha>0.</alpha>
      <node_risk>0.</node_risk>
      <tree_risk>0.</tree_risk>
      <tree_error>0.</tree_error></_>
    <_>
      <depth>6</depth>
      <sample_count>168</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>0</Tn>
      <complexity>1</complexity>
      <alpha>5.1082702843725514e-001</alpha>
      <node_risk>1.0216540568745245e+000</node_risk>
      <tree_risk>1.0216540568745103e+000</tree_risk>
      <tree_error>0.</tree_error></_>
    <_>
      <depth>1</depth>
      <sample_count>3760</sample_count>
      <value>112.</value>
      <norm_class_idx>1</norm_class_idx>
      <Tn>2147483647</Tn>
      <complexity>1</complexity>
      <alpha>0.</alpha>
      <node_risk>0.</node_risk>
      <tree_risk>0.</tree_risk>
      <tree_error>0.</tree_error></_></nodes></my_tree>
</opencv_storage>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值