http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&diff=8617&oldid=8616#Boosting
Boosting
一般的机器学习方法是监督学习方法:训练数据由输入和期望的输出组成,然后对非训练数据进行预测输出,也就是找出输入x与输出y之间的函数关系F: y = F(x)。根据输出的精确特性又可以分为分类和回归。
Boosting 是个非常强大的学习方法, 它也是一个监督的分类学习方法。它组合许多“弱”分类器来产生一个强大的分类器组[HTF01]。一个弱分类器的性能只是比随机选择好一点,因此它可以被设计的非常简单并且不会有太大的计算花费。将很多弱分类器结合起来组成一个集成的类似于SVM或者神经网络的强分类器。
在设计boosting分类器的时候最常用的弱分类器是决策树。通常每个树只具有一个节点的这种最简单的决策树就足够了。
Boosting模型的学习时间里在N个训练样本{(xi,yi)}1N 其中 xi ∈ RK 并且 yi ∈ {−1, +1}。xi是一个K维向量。每一维对应你所要分类的问题中的一个特征。输出的两类为-1和+1。
几种不同的boosting如离散AdaBoost, 实数AdaBoost, LogitBoost和Gentle AdaBoost[FHT98]。它们有非常类似的总体结构。因此,我们只需要了解下面表格中最基础的两类:离散AdaBoost和实数Adaboost算法。为每一个样本初始化使它们具有相同的权值(step 2)。然后一个弱分类器f(x)在具有权值的训练数据上进行训练。计算错误率和换算系数cm(step 3b). 被错分的样本的权重会增加。所有的权重进行归一化,并继续寻找若其他分类器M-1次。最后得到的分类器F(x)是这些独立的弱分类器的和的符号函数(step 4)。
- 给定N样本 (,) 其中
- 初始化权值
- 重复 for m = 1,2,…,M:
- 根据每个训练数据的计算。
- 计算 .
- 更新权值 , 并归一化使 Σ = 1.
- 输出分类器.
两类问题的算法:训练(step 1~3)和估计(step 4)
注意:作为传统的boosting算法,上述的算法只可以解决两类问题。对于多类的分类问题可以使用AdaBoost.MH算法将其简化为两类分类的问题,但同时需要较大的训练数据,可以在[FHT98]中找到相应的说明。
为了减少计算的时间复杂度而不减少精度,可以使用influence trimming方法。随着训练算法的进行和集合中树的数量的增加和信任度的增加,大部分的训练数据被正确的分类,从而这些样本的权重不断的降低。具有较低相关权重的样本对弱分类器的训练有较低的影响。因此这些样本会在训练分类器时排除在外而不对分类器造成较大影响。控制这个过程的参数是weight_trim_rate。只有样本的每小部分的weight_trim_rate的总和较大时才会被用于弱分类器的训练。注意每个样本的系数在每个循环中被重新计算。一些已经删除的样本可能会在训练更多的分类器时被再次使用。[FHT98].
[HTF01] Hastie, T., Tibshirani, R., Friedman, J. H. The Elements of Statistical Learning: Data Mining, Inference, and Prediction. Springer Series in Statistics. 2001.
[FHT98] Friedman, J. H., Hastie, T. and Tibshirani, R. Additive Logistic Regression: a Statistical View of Boosting. Technical Report, Dept. of Statistics, Stanford University, 1998.
CvBoostParams
Boosting 训练参数
struct CvBoostParams : public CvDTreeParams
{
int boost_type;
int weak_count;
int split_criteria;
double weight_trim_rate;
CvBoostParams();
CvBoostParams( int boost_type, int weak_count, double weight_trim_rate,
int max_depth, bool use_surrogates, const float* priors );
};
-
boost_type
- CvBoost::DISCRETE - 离散 AdaBoost
- CvBoost::REAL - 实数 AdaBoost
- CvBoost::LOGIT - LogitBoost
- CvBoost::GENTLE - Gentle AdaBoost
- Gentle AdaBoost 和实数 AdaBoost 是最经常的选择。 weak_count
- 建立的弱分类器的个数。 split_criteria
- 分裂准则, 用以为弱分类树选择最优的分裂系数。构造函数:
- CvBoost::DEFAULT - 为特定的boosting算法选择默认系数;见下文。
- CvBoost::GINI - 使用 Gini 索引。这是实数AdaBoost的默认方法; 也可以被用做离散AdaBoost。
- CvBoost::MISCLASS - 使用误分类速率。这是离散AdaBoost的默认方法; 也可以被用做实数AdaBoost。
- CvBoost::SQERR - 使用最小二乘准则. 这是LogitBoost和Gentle AdaBoost的默认选择和唯一选择。 weight_trim_rate
- The weight trimming ratio, 在0到1之间,参考上面的讨论。 如果这个系数小于等于0或者大于1,那么这个trimming将不会被使用,所有的样本都会在每个循环中使用。其默认值为0.95
-
Boosting type, 下面的一种
这个结构从CvDTreeParams继承,但不是所有的决策树参数都支持。特别的,cross-validation不被支持。
CvBoostTree
弱分类树
class CvBoostTree: public CvDTree
{
public:
CvBoostTree();
virtual ~CvBoostTree();
virtual bool train( CvDTreeTrainData* _train_data,
const CvMat* subsample_idx, CvBoost* ensemble );
virtual void scale( double s );
virtual void read( CvFileStorage* fs, CvFileNode* node,
CvBoost* ensemble, CvDTreeTrainData* _data );
virtual void clear();
protected:
...
CvBoost* ensemble;
};
作为一个boost树分类器CvBoost的组成部分,这个弱分类器是从CvDTree派生得来的。通常,不需要直接使用弱分类器,虽然它们可以作为CvBoost::weak的元素序列通过CvBoost::get_weak_predictions来访问。
注意:在LogitBoost和Gentle AdaBoost的情况下,每一个若预测器是一个递归树,而不是分类树。甚至在离散AdaBoost和实数AdaBoost的情况下,CvBoost::predict的返回值(CvDTreeNode::value)也不是输出的类别标号;一个负数代表为类别#0,一个正数代表类别#1。而这些数只是权重。每一个独立的树的权重可以通过函数CvBoostTree::scale增加或减少。
CvBoost
Boost树分类器
class CvBoost : public CvStatModel
{
public:
// Boosting type
enum { DISCRETE=0, REAL=1, LOGIT=2, GENTLE=3 };
// Splitting criteria
enum { DEFAULT=0, GINI=1, MISCLASS=3, SQERR=4 };
CvBoost();
virtual ~CvBoost();
CvBoost( const CvMat* _train_data, int _tflag,
const CvMat* _responses, const CvMat* _var_idx=0,
const CvMat* _sample_idx=0, const CvMat* _var_type=0,
const CvMat* _missing_mask=0,
CvBoostParams params=CvBoostParams() );
virtual bool train( const CvMat* _train_data, int _tflag,
const CvMat* _responses, const CvMat* _var_idx=0,
const CvMat* _sample_idx=0, const CvMat* _var_type=0,
const CvMat* _missing_mask=0,
CvBoostParams params=CvBoostParams(),
bool update=false );
virtual float predict( const CvMat* _sample, const CvMat* _missing=0,
CvMat* weak_responses=0, CvSlice slice=CV_WHOLE_SEQ,
bool raw_mode=false ) const;
virtual void prune( CvSlice slice );
virtual void clear();
virtual void write( CvFileStorage* storage, const char* name );
virtual void read( CvFileStorage* storage, CvFileNode* node );
CvSeq* get_weak_predictors();
const CvBoostParams& get_params() const;
...
protected:
virtual bool set_params( const CvBoostParams& _params );
virtual void update_weights( CvBoostTree* tree );
virtual void trim_weights();
virtual void write_params( CvFileStorage* fs );
virtual void read_params( CvFileStorage* fs, CvFileNode* node );
CvDTreeTrainData* data;
CvBoostParams params;
CvSeq* weak;
...
};
CvBoost::train
训练boost树分类器
bool CvBoost::train( const CvMat* _train_data, int _tflag,
const CvMat* _responses, const CvMat* _var_idx=0,
const CvMat* _sample_idx=0, const CvMat* _var_type=0,
const CvMat* _missing_mask=0,
CvBoostParams params=CvBoostParams(),
bool update=false );
这个分类函数使用的是最通常的模板,最后一个参数update表示分类器是否需要更新(例如,新的弱分类树是否被加入到已存在的总和里), 或者是分类器是否需要重新建立。返回必须是类别,boost树不能用于递归的建立,且必须是两类。注:如_train_data的维数是data_number*featureDim,则_responses的维数为data_number*1,_var_type的维数为featureDim+1*1,也就是说_var_type的维数是特征维数+1。并且,训练样本的样本数有一定的限制,样本的个数最低为10个,否则会报错。
CvBoost::predict
预测对输入样本的响应
float CvBoost::predict( const CvMat* sample, const CvMat* missing=0,
CvMat* weak_responses=0, CvSlice slice=CV_WHOLE_SEQ,
bool raw_mode=false ) const;
-
sample
- 输入样本。 missing
- 输入的sample中可能存在一些缺少的测量(即一部分测量可能没有观测到),因此需要用一个掩模来指出这些部分。要处理缺少的测量,弱分类器必须包含替代的方法(参见CvDTreeParams::use_surrogates)。 weak_reponses
- 可选的输出参数,weak_reponses是一个浮点数向量,向量中每一个浮点数都对应一个独立弱分类器的响应。向量中元素的数量必须与弱分类器的数量相等。 slice
- 弱分类器响应中用于预测的连续子集。默认情况下使用所有的弱分类器。 raw_mode
- 与在CvDTree::predict中的意思相同。一般而言被设为false。
CvBoost::predict方法通过总体的树运行样本,返回输出的加权类标签。
CvBoost::prune
移除指定的弱分类器
void CvBoost::prune( CvSlice slice );
这个方法从结果中移除指定的弱分类器。请注意不要将这个方法与一个目前还不支持的移除单独决策树的方法混淆起来。
CvBoost::get_weak_predictors
返回弱分类树的结果
CvSeq* CvBoost::get_weak_predictors();
这个方法返回弱分类器的结果。每个元素的结果都是一个指向CvBoostTree类的指针(或者也可能指向它的一些派生)。