在opencv源代码中如何确定树桩分类器阈值?如何确定树桩的左右边的返回值?

原创 2015年07月08日 16:56:58

源代码在opencv库里面的cvboost.cpp文件里面,宏ICV_DEF_FIND_STUMP_THRESHOLD( suffix, type, error )的总体思路是通过定义带参数的宏,把参数传递给宏内部的函数,然后进行一系列的计算,并最终根据一定的算法找到合适的阈值。具体解析如下:

#define ICV_DEF_FIND_STUMP_THRESHOLD( suffix, type, error )                              \
static int icvFindStumpThreshold_##suffix(                                               \
        uchar* data, size_t datastep, //训练样本的  特征-样本数据                        \
        uchar* wdata, size_t wstep, //wdata是样本的权重矩阵                               \
        uchar* ydata, size_t ystep, //ydata是样本的类别矩阵                               \
        uchar* idxdata, size_t idxstep, int num, //idxdata是样本根据特征值大小排序后的索引数据,样本按照特征值的大小升序排列  \
        float* lerror, //左边不纯度                                                       \
        float* rerror, //右边不纯度                                                       \
        float* threshold, float* left, float* right,                                     \
        float* sumw, float* sumwy, float* sumwyy )                                       \
{                                                                                        \
    int found = 0;                                                                       \
    float wyl  = 0.0F;                                                                   \
    float wl   = 0.0F;                                                                   \
    float wyyl = 0.0F;                                                                   \
    float wyr  = 0.0F;                                                                   \
    float wr   = 0.0F;                                                                   \
                                                                                         \
    float curleft  = 0.0F;                                                               \
    float curright = 0.0F;                                                               \
    float* prevval = NULL;                                                               \
    float* curval  = NULL;                                                               \
    float curlerror = 0.0F;                                                              \
    float currerror = 0.0F;                                                              \
                                                                                         \
    int i = 0;                                                                           \
    int idx = 0;                                                                         \
                                                                                         \
    if( *sumw == FLT_MAX )                                                               \
    {                                                                                    \
        /* calculate sums */                                                             \
        float *y = NULL;                                                                 \
        float *w = NULL;                                                                 \
        float wy = 0.0F;                                                                 \
                                                                                         \
        *sumw   = 0.0F;                                                                  \
        *sumwy  = 0.0F;                                                                  \
        *sumwyy = 0.0F;                                                                  \
        for( i = 0; i < num; i++ )                                                       \
        {                                                                                \
            idx = (int) ( *((type*) (idxdata + i*idxstep)) );//根据样本的数据和step确定其样本索引序号idx  \
            w = (float*) (wdata + idx * wstep);                                          \
            *sumw += *w;                        //计算权重和                              \
            y = (float*) (ydata + idx * ystep);                                          \
            wy = (*w) * (*y);                   //计算权重w和类别y的乘积                  \
            *sumwy += wy;                                                                \
            *sumwyy += wy * (*y);                                                        \
        }                                                                                \
    }                                                                                    \
                                                                                         \
    for( i = 0; i < num; i++ )                                                           \
    {                                                                                    \
        idx = (int) ( *((type*) (idxdata + i*idxstep)) );                                \
        curval = (float*) (data + idx * datastep);                                       \
         /* for debug purpose */                                                         \
        if( i > 0 ) assert( (*prevval) <= (*curval) );                                   \
                                                                                         \
        wyr  = *sumwy - wyl;//计算在当前特征值以前的去除重复的特征值后的权重和类别乘积和\
        wr   = *sumw  - wl;  //计算在当前特征值以前的去除重复的特征值后的权重和          \
                                                                                         \
        if( wl > 0.0 ) curleft = wyl / wl;    //在剔除出有相同特征值的样本中,计算正样本比重(因为负样本的类别为0)\
        else curleft = 0.0F;                                                             \
                                                                                         \
        if( wr > 0.0 ) curright = wyr / wr;   //在未剔除出的样本中,计算正样本的权重和比重 \
        else curright = 0.0F;                                                            \
                                                                                         \
        error                                                                            \
                                                                                         \
        if( curlerror + currerror < (*lerror) + (*rerror) )//如果当前的不纯度和小于原来的不纯度和\
        {                                                                                \
            (*lerror) = curlerror;                                                       \
            (*rerror) = currerror;                                                       \
            *threshold = *curval;                                                        \
            if( i > 0 ) {   
/************************树桩分类器的阈值:0.5*(当前特征值值与前一个特征值的和)*************************/               
                *threshold = 0.5F * (*threshold + *prevval); //阈值的大小为0.5*(当前特征值值与前一个特征值的和)  \
            }                                                                            \
            *left  = curleft;//树桩分类器的左边的返回值                                   \
            *right = curright;//树桩分类器右边的返回值                                    \
            found = 1;                                                                   \
        }                                                                                \
                                                                                         \
        do                                                                               \
        {   //在计算参数时,也就是计算与当前特征值重复的特征值的相关参数                 \
            wl  += *((float*) (wdata + idx * wstep));                                    \
            wyl += (*((float*) (wdata + idx * wstep)))                                   \
                * (*((float*) (ydata + idx * ystep)));                                   \
            wyyl += *((float*) (wdata + idx * wstep))                                    \
                * (*((float*) (ydata + idx * ystep)))                                    \
                * (*((float*) (ydata + idx * ystep)));                                   \
        }                                                                                \
        while( (++i) < num &&                                                            \
            ( *((float*) (data + (idx =                                                  \
                (int) ( *((type*) (idxdata + i*idxstep))) ) * datastep))                 \
                == *curval ) );
   /*
    *do-while作用:计算与当前重复特征值的wl,wyl,wyyl。
    *while括号里的含义是当i<num时,并且idxdata中的第++i个特征值与当前的特征值相等时,就执行
    *do-while循环里的内容。对于同一个特征值,如果做阈值的话,对于分类结果只能是同一种情况
    *,所以要跳过对同一个相等的特征值来确定阈值的情况,另一个作用是这样也无形中加快了训练
    *过程。
    */
                                                                                         \
        --i;                                                                             \
        prevval = curval;  //把当前特征值变成前一个,依次遍历所有的特征值,并最终选择一个最优的阈值 \
    } /* for each value */                                                               \
                                                                                         \
    return found;                                                                        \
} 


浅谈ROC与PR曲线-分类器阈值确定

ROC曲线 受试者工作特征 PR曲线 查准率-查全率。
  • zzyy0929
  • zzyy0929
  • 2017年11月02日 09:30
  • 189

Rocchio算法,其他分类算法通用阈值确定方法

通过对PR曲线的绘制,了解阈值设定对PR值影响的状况,这里假定P,R都是重要的,采用角平分线和该曲线的交点,交点处为PR值达到最佳的点,作为调和平均数F-measure,P,R均取高值,该指标才可能高...
  • pennyliang
  • pennyliang
  • 2007年01月10日 15:45
  • 2651

Boosting分类器

(原文)http://blog.csdn.net/liulina603/article/details/8632934
  • chaoshengmingyue
  • chaoshengmingyue
  • 2015年11月16日 22:16
  • 1416

弹窗的确定按钮是放左边还是右边

虽然是细节,然后放左放右仍然是经常遇到的问题,虽然最普通的处理方式是参考别的游戏或者统一放一边培养玩家习惯,但是不够深入,仍然想分析一下 1.弹窗主要分为两类     1.1普通的弹窗:     一般...
  • TinoTino
  • TinoTino
  • 2016年01月30日 17:02
  • 1080

opencv图像阈值设置

opencv python 图像阈值设置
  • u010682375
  • u010682375
  • 2017年03月31日 17:30
  • 1256

bzoj 1935 && bzoj 4322 离线+树状数组

题意:给定n个点,多次询问某个矩阵中包含多少点 如果暴力二维树状数组的话O(nlogn*logn+mlogn*logn)复杂度原地爆炸 那么我们就把二维树状数组通过一些方法变成一维,就能降下去一个...
  • Eirlys_North
  • Eirlys_North
  • 2017年04月16日 14:37
  • 145

在opencv中,强分类器阈值是如何确定的?虚警率是怎么计算的?

在opencv中,强分类器阈值的确定实在函数icvCreateCARTStageClassifier中,具体强分类器的阈值的求解方式和虚警率的计算如下 CvIntHaarClassifier* icv...
  • ding977921830
  • ding977921830
  • 2015年07月16日 10:56
  • 2080

机器学习(周志华) 参考答案 第十二章 计算理论学习

机器学习(周志华) 参考答案 第十二章 计算理论学习机器学习(周志华西瓜书) 参考答案 总目录 http://blog.csdn.net/icefire_tyh/article/details/520...
  • icefire_tyh
  • icefire_tyh
  • 2016年08月21日 23:59
  • 1936

决策树、SVM及集成方法

- 选择的算法:决策树、集成方法、支撑向量机 决策树 模型在真实世界中也应用场景 在金融方面使用决策树建模分析,用于评估用户的信用、贷款违约率等;在电子商务中,可以根据用...
  • wuxiaosi808
  • wuxiaosi808
  • 2017年08月22日 10:43
  • 182

opencv阈值法分割图像

opencv阈值法分割图像 from: http://www.cnblogs.com/skyseraph/archive/2010/12/21/1913058.html 1。手动设定...
  • cserchen
  • cserchen
  • 2011年10月13日 15:04
  • 14131
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在opencv源代码中如何确定树桩分类器阈值?如何确定树桩的左右边的返回值?
举报原因:
原因补充:

(最多只允许输入30个字)