Opencv249源码分析Extremely randomized trees文档格式.docx
- 文档编号:21214652
- 上传时间:2023-01-28
- 格式:DOCX
- 页数:34
- 大小:28.96KB
Opencv249源码分析Extremely randomized trees文档格式.docx
《Opencv249源码分析Extremely randomized trees文档格式.docx》由会员分享,可在线阅读,更多相关《Opencv249源码分析Extremely randomized trees文档格式.docx(34页珍藏版)》请在冰豆网上搜索。
constCvMat*responses,constCvMat*varIdx=0,
constCvMat*sampleIdx=0,constCvMat*varType=0,
constCvMat*missingDataMask=0,
CvRTParamsparams=CvRTParams());
CV_WRAPvirtualbooltrain(constcv:
:
Mat&
trainData,inttflag,
constcv:
responses,constcv:
varIdx=cv:
Mat(),
sampleIdx=cv:
Mat(),constcv:
varType=cv:
missingDataMask=cv:
virtualbooltrain(CvMLData*data,CvRTParamsparams=CvRTParams());
protected:
virtualstd:
stringgetName()const;
virtualboolgrow_forest(constCvTermCriteriaterm_crit);
};
我们从CvERTrees类可以看出,它没有预测函数predict,因此,如果要进行ET的预测,调用的是它的父类CvRTrees内的predict函数。
在训练样本时,CvERTrees类与CvRTrees类的训练过程是完全一致的,即在train函数内再调用grow_forest函数,而且两个类的train函数的输入参数的形式也是完全一样的。
但在grow_forest函数内会有一点不同,那就是CvERTrees类中的grow_forest函数把全体训练样本都当成OOB样本,因此它不需要随机样本掩码矩阵变量sample_idx_mask_for_tree,而表示样本索引值变量的sample_idx_for_tree保存的就是正常顺序的训练样本的索引值。
ET算法与随机森林算法最大的不同就在于节点的分叉上,而这一点是体现在CvForestERTree类上的:
classCV_EXPORTSCvForestERTree:
publicCvForestTree
virtualdoublecalc_node_dir(CvDTreeNode*node);
virtualCvDTreeSplit*find_split_ord_class(CvDTreeNode*n,intvi,
floatinit_quality=0,CvDTreeSplit*_split=0,uchar*ext_buf=0);
virtualCvDTreeSplit*find_split_cat_class(CvDTreeNode*n,intvi,
virtualCvDTreeSplit*find_split_ord_reg(CvDTreeNode*n,intvi,
virtualCvDTreeSplit*find_split_cat_reg(CvDTreeNode*n,intvi,
virtualvoidsplit_node_data(CvDTreeNode*n);
CvForestERTree类定义了一些专用于ET算法的计算分叉、得到最佳分叉属性的函数,下面我们就逐一介绍这些函数。
按最佳分叉属性标注该节点的所有样本是被分配到左分支还是右分支:
doubleCvForestERTree:
calc_node_dir(CvDTreeNode*node)
//表示特征属性的种类是属于左分支还是右分支,-1为左分支,1为右分支,如果该特征属性缺失,则为0
char*dir=(char*)data->
direction->
data.ptr;
//n表示该节点的样本数量,vi表示分类的最佳特征属性
inti,n=node->
sample_count,vi=node->
split->
var_idx;
doubleL,R;
assert(!
node->
inversed);
//确保分叉不反转
if(data->
get_var_type(vi)>
=0)//splitoncategoricalvar
//表示该特征属性是种类的形式
{
//开辟一块内存空间
cv:
AutoBuffer<
uchar>
inn_buf(n*sizeof(int)*(!
data->
have_priors?
1:
2));
int*labels_buf=(int*)(uchar*)inn_buf;
//labels指向该特征属性中各个样本所对应的种类,get_cat_var_data函数在ER算法中被重新定义
constint*labels=data->
get_cat_var_data(node,vi,labels_buf);
//subset数组的每一位表示特征属性的种类,左分支的种类位是1,右分支的是0
constint*subset=node->
subset;
if(!
have_priors)//无先验概率
intsum=0,sum_abs=0;
for(i=0;
i<
n;
i++)//遍历该节点的所有样本
intidx=labels[i];
//表示该样本的特征属性的种类
//d为-1表示idx(特征属性的种类)属于左分支,为1表示属于右分支,如果没有该特征属性,则d为0
intd=(((idx>
=0)&
&
(!
is_buf_16u))||((idx!
=65535)&
(data->
is_buf_16u)))?
CV_DTREE_CAT_DIR(idx,subset):
0;
//sum表示d累加求和,因为d也可能为负值,所以sum的含义为右分支比左分支多出的特征属性种类;
sum_abs表示d的绝对值之和,表示的含义为被分叉的特征属性种类
sum+=d;
sum_abs+=d&
1;
dir[i]=(char)d;
//赋值
}
//L和R分别表示左右分支的特征属性的种类数量
R=(sum_abs+sum)>
>
L=(sum_abs-sum)>
else//有先验概率
constdouble*priors=data->
priors_mult->
data.db;
//得到先验概率
doublesum=0,sum_abs=0;
int*responses_buf=labels_buf+n;
//responses指向该节点样本的分类,即响应值
constint*responses=data->
get_class_labels(node,responses_buf);
doublew=priors[responses[i]];
//得到该响应值的先验概率
intd=idx>
=0?
sum+=d*w;
sum_abs+=(d&
1)*w;
//增加了先验概率
R=(sum_abs+sum)*0.5;
L=(sum_abs-sum)*0.5;
else//splitonorderedvar
//表示该特征属性是数值的形式
//得到分叉属性的值split_val,如果样本的分叉属性的值小于该值,则被分叉为左节点,否则为右节点
floatsplit_val=node->
ord.c;
//为该特征属性开辟一块内存空间
inn_buf(n*(sizeof(int)*(!
2)+sizeof(float)));
float*val_buf=(float*)(uchar*)inn_buf;
//用于存储各个样本当前特征属性的值
int*missing_buf=(int*)(val_buf+n);
//表示各个样本是否缺失当前特征属性
constfloat*val=0;
//指向数组val_buf
constint*missing=0;
//指向数组missing_buf
//get_ord_var_data函数在ER算法中被重新定义,各个样本的vi特征属性的值存储在val_buf数组内,各个样本是否缺失该特征属性用missing_buf数组表示
data->
get_ord_var_data(node,vi,val_buf,missing_buf,&
val,&
missing,0);
L=R=0;
i++)//遍历所有样本
if(missing[i])//该样本缺失vi这个特征属性
dir[i]=(char)0;
//方向信息赋值为0
else
if(val[i]<
split_val)//左分支
dir[i]=(char)-1;
//方向信息赋值为-1
L++;
//左分支计数
else//右分支
dir[i]=(char)1;
//方向信息赋值为1
R++;
//右分支计数
int*responses_buf=missing_buf+n;
L+=w;
R+=w;
node->
maxlr=MAX(L,R);
//表示左右分支最大值
returnnode->
quality/(L+R);
//得到规范化系数
}
特征为数值的分类树的分叉方法:
CvDTreeSplit*CvForestERTree:
find_split_ord_class(CvDTreeNode*node,intvi,floatinit_quality,CvDTreeSplit*_split,
uchar*_ext_buf)
constfloatepsilon=FLT_EPSILON*2;
//定义一个最小常数
constfloatsplit_delta=(1+FLT_EPSILON)*FLT_EPSILON;
//定义另一个常数
intn=node->
sample_count;
//该节点的样本数量
intm=data->
get_num_classes();
//样本数据的分类数
//为该特征属性vi开辟一块内存空间
inn_buf;
_ext_buf)
inn_buf.allocate(n*(2*sizeof(int)+sizeof(float)));
uchar*ext_buf=_ext_buf?
_ext_buf:
(uchar*)inn_buf;
float*values_buf=(float*)ext_buf;
//用于存储各个样本在特征属性vi的值
int*missing_buf=(int*)(values_buf+n);
constfloat*values=0;
//指向数组values_buf
//得到数组values_buf和missing_buf
get_ord_var_data(node,vi,values_buf,missing_buf,&
values,&
get_class_labels(node,responses_buf);
doublelbest_val=0,rbest_val=0,best_val=init_quality,split_val=0;
//得到不同分类的先验概率
data.db:
boolis_find_split=false;
//表示是否找到了分叉属性
floatpmin,pmax;
//分别表示样本的特征属性vi的最小值和最大值
intsmpi=0;
//表示缺失特征属性的样本索引值
//得到第一个不缺失vi特征属性的样本
while(missing[smpi]&
(smpi<
n))
smpi++;
assert(smpi<
n);
//确保smpi的正确
//初始化pmin和pmax
pmin=values[smpi];
pmax=pmin;
for(;
smpi<
smpi++)//遍历样本,得到pmin和pmax
floatptemp=values[smpi];
//得到当前样本的vi的值
intms=missing[smpi];
//当前样本是否缺失该vi值
if(ms)continue;
//缺失则遍历下一个样本
if(ptemp<
pmin)//更新pmin值
pmin=ptemp;
if(ptemp>
pmax)//更新pmax值
pmax=ptemp;
floatfdiff=pmax-pmin;
//pmax与pmin的差值
//差值大于一个常数,表示前面计算的结果是有意义的,也就是得到了分叉属性
if(fdiff>
epsilon)
is_find_split=true;
//表示找到了分叉属性
RNG*rng=data->
rng;
//表示随机数
//随机数为0和1之间的任意数,split_val为pmax与pmin之间任意一个数
split_val=pmin+rng->
uniform(0.f,1.f)*fdiff;
//如果split_val太接近pmax或pmin,则split_val为一个定值
if(split_val-pmin<
=FLT_EPSILON)
split_val=pmin+split_delta;
if(pmax-split_val<
split_val=pmax-split_delta;
//calculateGiniindex
//计算基尼指数
if(!
priors)//样本没有先验概率
int>
lrc(m*2);
//lc和rc分别表示分类的左、右分支
int*lc=lrc,*rc=lc+m;
intL=0,R=0;
//表示左、右分支的样本数
//initarraysofclassinstancecountersonbothsidesofthesplit
for(inti=0;
m;
i++)//数组lc和rc清零
lc[i]=0;
rc[i]=0;
for(intsi=0;
si<
si++)//遍历所有样本
intr=responses[si];
//该样本的响应值
floatval=values[si];
//该样本的特征属性vi的值
intms=missing[si];
if(val<
split_val)//左分支
lc[r]++;
rc[r]++;
//得到分类后的基尼指数best_val
for(inti=0;
i++)
lbest_val+=lc[i]*lc[i];
rbe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Opencv249源码分析Extremely randomized trees Opencv249 源码 分析 Extremely