OpenCV学习笔记(9)-ML库的通用类

ML库中的所有程序都是用C++写的,它们都继承于CvStatModel类.CvStatModel中有两套方法来对磁盘进行模型的读/写操作:保存操作的save()和write(),读操作的load()和read().对于机器学习模型,应该使用简单的save()和load(),它们实际上把复杂的write()和read()函数进行了封装,能够从硬盘读/写XML和YAML文件.CvStatModel中还有机器学习中两个最重要的方法,即predict()和train(),它们的形式随算法变化,以后讨论.

基类 CvStatModel中的函数

save(const char* filename,const char* name =0)     将训练出的模型以XML或YAML格式保存到硬盘,此方法用于存储

load(const char* filename,const char* name = 0)    首先需要调用clear()函数,然后通过此函数装载XML或YAML格式的模型.此方法用于调用

clear() 释放所有内存.为重用做准备

bool tran(-data points-,[flags],-responses-,[flags etc]) ;   此训练函数从输入的数据集上学习一个模型.算法不同时,训练函数的输入参数也有所不同

float predict(const CvMat* sample[,]) const;   训练之后,使用此函数来预测一个新数据样本的标签或者值

构造函数,析构函数

CvStatModel(); 默认构造函数,以及将创建并训练模型功能

CvStatModel(const CvMat* tran_data...);  集成的构造函数

cvStatModel::~CvStatModel(); 机器学习模型的析构函数

读写支持(实际应用时请使用svae和load函数)

write(CvFileStorage* storage,const char* name);  通用的写CvFileStorage结构的函数,位于cxcore库中,在此处被save()函数调用

read(CvFileStorage* storage,CvFileNode* node);  通用的读CvFileStorage结构的函数,位于cxcore库中,在此处被load()函数调用

训练

训练的函数原型如下

bool CvStatModel::train(const CvMat* train_data,[int tflag]..., const CvMat* responses,...,[const CvMat* var_idx,]...,[const CvMat* sample_idx,]...,[const CvMat* var_type,]...,[const CvMat* missing_mask,]...);

机器学习分train()方法根据具体的算法呈现不同的形式.所有的算法都是以一个指向CvMat矩阵的指针作为训练数据.矩阵必须是32FC1(32位浮点单通道)类型.CvMat结构可以支持多通道矩阵,但是机器学习只采用单通道矩阵.一般情况下,这个矩阵以行排列数据样本,每个数据样本,每个数据样本被表示为一个行向量.矩阵的每一列,表示某个变量在不同数据样本中的不同取值,这样组成了一个二维的数据矩阵.请石刻牢记输入数据矩阵的构成方式(行,列)=(数据样本,特征变量).但是,有的算法可以直接处理转置后的输入矩阵.针对这些算法,可以使用蚕食tflag想算法表明训练数据是以列排列的.这样便不需要转置一个大的数据矩阵,如果算法可以处理行排列和列排列两种情况,可以使用下面的标记.

tflag = CV_ROW_SAMPLE  特征向量以行排列(默认)

tflag = CV_COL_SAMPLE 特征向量以列排列

读者可能要问:如果我的数据不是浮点型,而是字符或整型,怎么办?答案是:只要在写入CvMat的时候,把它们转换成32位浮点数.如果特征或标签是字符,就把ASCII字符转换成浮点数.整型也一样.只要转换是唯一的,就没有问题-但是请记住,有些算法对特征的方差不一致比较敏感.最好先归一化特征的方差.基于树的算法(决策树,随机森林和boosting)支持类别变量和数值变量,OpenCVML库中的其他算法只支持数值输入.使数值输入的算法能够处理类别数据的常用方法是把类别数据表示成0-1编码.例如,如果输入的颜色变量有7个不同的值,则把他们替换成7个二进制变量,变量有且仅有一位是1.

返回的参数responses可以是类别标签(如蘑菇分类中的"有毒"和"无毒"标签);也可以是连续的数值(如温度计测的人体温度).返回值尝尝是一个一维向量,向量的每个值对应一个输入数据样本:但是神经网络例外,神经网络的每个数据样本都返回一个向量.返回值有两种类型:对于分类问题,类型是整型(32SC1);对于回归问题,类型是32位浮点型(32FC1).显然,一些算法只能处理分类问题,一些算法只能处理回归问题,一些算法两类问题都能处理.在最后一种情况下,输出变量的类型要么以一个单独的参数返回,要么以向量var_type的最后一个元素返回,可以如下设置:

CV_VAR_CATEGORICAL 输出的值是离散类型标签

CV_VAR_ORDERED(= CV_CAR_NUMERICAL)输出的值是数值类型标签,就是说,不同的值可以作为数来比较,这是一个回归问题.

输入数据的类型也可以用var_type来指定.但是,回归类型的算法只能处理有序输入.有的时候,需要把类别数据一一映射到有序数据,但是这样做有的时候会出问题,因为"伪"有序数据会因物理基础的缺乏而可能大幅震荡.

ML库中的很多模型可以选择训练特定数据子集和/或特定特征子集.为了方便用户,train()方法包含了向量参数var_idx和sample_idx.默认为NULL,即使用所有数据.可以用它们来指定使用哪些数据样本和使用哪些特征.这两个向量要么是单通道整型(CV_32SC1)向量,要么是单通道8位数据(CV_8UC1)--非0代表有效.读入一堆数据却只想使用一部分数据来训练,一部分数据来分类,不想把数据分成2个矩阵的时候,参数sample_idx尤其有用.

另外,一些算法可以处理数据丢失的情况.例如,当用户使用的是人工采集的数据的时候,很可能会丢失测量数据.这中情况下,参数missing_mask--一个与train_data同样大小的8位矩阵--将被用来标记丢失的数据(非0的标记元素).一些算法不能处理数据丢失,所以丢失的数据样本必须由用户采用插值的方法合成,或者在训练中抛弃不完整的数据样本.其他算法(像决策树和朴素贝叶斯)通过不同的方法来处理数据丢失.决策树使用"代理分裂",朴素贝叶斯推断数据值.

通常在训练之前,前面提到的模型都可以用clear()来清除.但有些算法可以随时用新数据更新模型,而不是每次训练都从头处理所有数据.

预测

指定训练函数train()中使用哪些特征的参数var_idx将被程序记住.调用预测函数predict()的时候,并随后被用来从输入参数中抽取出需要的部分数据.

Predict()函数的基本形式如下

float CvStatMode::predict(

const CvMat* sample

[, ]

)const;

这个函数可对新输入的数据向量进行预测.如果是分类问题,它会返回一个类别标签.如果是回归问题,它会返回一个数值标签.注意,输入的样本格式必须和训练样本的格式完全一样.可选参数prediction_params由算法指定,可以用来在基于树的预测方法中指定缺失的特征的值等.函数后缀const告诉我们:预测不影响模型的内部状态.因此,这个方法可以并行调用.它可以在网络服务器从多客户端获取图像之中,可以用用在机器人加速场景扫描之中.

训练迭代次数

尽管迭代控制体CvTermCriteria已经在其他章谈论过,但由于它被广泛应用于很多机器算法中,所以在重复下

typedef struct CvTermCriteria
{
    int    type;  /* may be combination of
                     CV_TERMCRIT_ITER
                     CV_TERMCRIT_EPS */
    int    max_iter;
    double epsilon;
}
CvTermCriteria;
整型参数max_iter设置了算法的最大迭代次数.参数epsilon设置误差停止标准,当误差在此参数之下,则算法停止.最后,参数type设置了应该使用哪个标准,也可以同事使用(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS).term_crit.tyoe可以使用的值定义如下:

#define CV_TERMCRIT_ITER    1
#define CV_TERMCRIT_NUMBER  CV_TERMCRIT_ITER
#define CV_TERMCRIT_EPS     2
现在我们转向OpenCV中的具体算法.我们首先讨论最常用的Mahalanobis距离,然后深入介绍一个无监督算法(K均值);这两个算法在cxcore库中.然后我们讨论机器学习库中的正态贝叶斯分类器和决策树算法(决策树,boosting,随机森林,Haar级联).对于其他的函数,我们仅给出简短表述和用法示例.






你可能感兴趣的:(openCV)