在opencv的ml模块中有个统计模型类,而其他的比如朴素贝叶斯分类器、knn、svm等等其他模型都是基于该模型上派生出来的。所以先介绍下该模型。

该类的定义在文件“opencv\sources\modules\ml\include\opencv2\ml\ml.hpp”中:

class CV_EXPORTS_W CvStatModel
{
public:
CvStatModel();
virtual ~CvStatModel(); virtual void clear(); //save函数用来将整个模型状态保持到指定的XML 或者YAML文件中,并按照具体的类看是使用默认的名字还是指定的名字.
//使用了CxCore中的数据持久性功能。
CV_WRAP virtual void save(const char* filename, const char* name = 0) const; // load函数从指定的XML或者YAML中装载模型中指定的或者默认名字部分 //而之前的被装载的模型已经通过CvStatModel::clear()初始化了.
CV_WRAP virtual void load(const char* filename, const char* name = 0); // write函数会以将完整的模型以指定或者默认名字存储到文件中。该函数会被 CvStatModel::save()调用.
virtual void write(CvFileStorage* storage, const char* name) const; // read函数会从文件中指定的节点上读取整个模型。使用函数GetFileNodeByName()来定位节点。
//之前的模型也是需要被函数 CvStatModel::clear()初始化的.
virtual void read(CvFileStorage* storage, CvFileNode* node); //下面这几个函数被注释掉是因为它们不存在该模型中,只是对于其他的ml模型
//来说是有的,所以这里就完全不设定该函数,只是虽然各自派生的ml模型有各
//自的这几个函数,可是行为还是很类似的,所以就统一在该基类中介绍了。
// virtual bool train( const Mat& train_data, [int tflag,] ...,
// const Mat& responses, ..., [const Mat& var_idx,] ...,
// [const Mat& sample_idx,] ... [const Mat& var_type,] ...,
// [const Mat& missing_mask,] <misc_training_alg_params> ...
// )=0; // virtual float predict( const Mat& sample ... ) const=0; protected:
const char* default_model_name;
};

实现部分:

在文件“\opencv\sources\modules\ml\src\inner_functions.cpp”中

#include "precomp.hpp"
//构造函数,对该类唯一的类成员进行赋值
CvStatModel::CvStatModel()
{
default_model_name = "my_stat_model";
}
//虚析构函数,调用虚函数clear()来执行不同的类的清理工作
CvStatModel::~CvStatModel()
{
clear();
}
void CvStatModel::clear(){}
//写函数,将数据写入到指定的文件中
void CvStatModel::save( const char* filename, const char* name ) const
{
//存储文件的指针初始化
CvFileStorage* fs = 0;
//
CV_FUNCNAME( "CvStatModel::save" ); __BEGIN__;
//打开传入该函数的文件
CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_WRITE )); if( !fs )
CV_ERROR( CV_StsError, "Could not open the file storage. Check the path and permissions" );
//如果未传入模型的名字,则写入默认的模型名字
write( fs, name ? name : default_model_name ); __END__;
//释放指向文件的指针
cvReleaseFileStorage( &fs );
} //装载指定文件中的数据
void CvStatModel::load( const char* filename, const char* name )
{
CvFileStorage* fs = 0; CV_FUNCNAME( "CvStatModel::load" ); __BEGIN__; CvFileNode* model_node = 0; CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ));
if( !fs )
EXIT; if( name )
model_node = cvGetFileNodeByName( fs, 0, name );
else
{
CvFileNode* root = cvGetRootFileNode( fs );
if( root->data.seq->total > 0 )
model_node = (CvFileNode*)cvGetSeqElem( root->data.seq, 0 );
} read( fs, model_node ); __END__;
//释放指向文件的指针
cvReleaseFileStorage( &fs );
}
//写函数
void CvStatModel::write( CvFileStorage*, const char* ) const
{
OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::write", "" );
} void CvStatModel::read( CvFileStorage*, CvFileNode* )
{
OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::read", "" );
}

该文件中还有大量的数学计算函数,比如矩阵分解,从GMM上采样等等。

备注:好了这里就主要介绍下几个不存在于该类的函数。

1、模型训练函数

 bool CvStatModel::train(const Mat& train_data, [int tflag,] ..., const Mat& responses, ..., [const
Mat& var_idx,] ..., [const Mat& sample_idx,] ... [const Mat& var_type,] ...,
[const Mat& missing_mask,] <misc_training_alg_params> ... ) = 0

该函数是通过输入特征向量和对应的输出目标值(responses)来训练模型的。输入和输出的向量/值都是以矩阵的形式传递的。默认情况下输入特征向量是以train_data rows,也就是一个训练样本中所有的成分(特征)是连续存储的。不过一些算法是需要处理它们的转置形式的,只要当基于所有的输入集合中的特征都是连续存储的(个人:其实也就是存储成一个矩阵而不是链表).如果两种布局都支持的话,那么该方法将会有个tflag参数用来指定具体的情况。

• tflag=CV_ROW_SAMPLE 特征向量以行形式存储;

• tflag=CV_COL_SAMPLE 特征向量以列形式存储。

train_data 必须是 CV_32FC1 (32位浮点类型,单通道) 格式的. 而Responses通常存储成1D向量(一行或者一列)形式 ,格式有: CV_32SC1(只在分类的时候用); CV_32FC1, 其中一个输入向量对应着一个目标值.

对于分类问题来说, responses 是离散的标签;

对于回归问题来说,responses 是模型函数需要逼近的值。

一些算法只能用来分类;一些算法只能用来回归;还有一些能用在两方面。对于回归来说,输出变量的类型既可以是通过独立的参数传递也可以是var_type向量的最后一个元素:

• CV_VAR_CATEGORICAL 输出变量是离散的类别标签;

• CV_VAR_ORDERED(=CV_VAR_NUMERICAL) 输出的值是有序的,也就是说两个不同的值可以进行数值对比,当然这是一个回归问题。

输入变量的类型可以通过var_type指定。大多数算法只能处理有序的输入变量。

许多ML模型会在一个特征子集或者是训练集中样本子集上进行训练,为了能够容易的在不同状态间选择,该函数还包含了var_idx 和 sample_idx 这两个参数。前者是用来指定感兴趣的变量(特征);后者是用来指定感兴趣的样本。这两个向量都是整型向量 (CV_32SC1) ,(当然是基于0开始索引的)或者是基于激活的变量/样本的8位 (CV_8UC1)标记。当传递一个NULL指针给这两个参数时,也就意味着所有的变量/样本都会用来训练。

另外,许多算法可以处理缺失的值的情况,也就是说当某个具体的训练样本的特征的值是未知的(比如,忘记测量一个病人在礼拜一时候的体温)参数 missing_mask,是一个与train_data 具有相同size的8位的矩阵,它用来标记缺失的值(即该标记矩阵中非0值)

通常来说,在进入到训练阶段之前的模型的状态是需要调用CvStatModel::clear()来重置的 ;不过某些算法会让你选择是否使用新的训练数据来更新模型的状态而不是重置他们。

float CvStatModel::predict(const Mat& sample, ...) const

该函数用来对一个新的样本进行预测其response。在分类问题中,该方法返回一个类别标签;在回归问题上,盖方法返回一个函数值 。输入的样本必须与传递给train函数中train_data一样大的特征维度。如果var_idx 参数传递给了train,那么记得,也同时只提取必须的特征给该函数。后缀的const表示该预测函数不会影响到模型的内部状态,所以该方法可以安全的在不同的线程中被调用。

opencv7-ml之统计模型的更多相关文章

  1. 关于ML.NET v0.6的发布说明

    ML.NET 0.6版本提供了几项令人兴奋的新增功能: 用于构建和使用机器学习模型的新API 我们主要关注的是发布用于构建和使用模型的新ML.NET API的第一次迭代.这些新的,更灵活的API支持新 ...

  2. ML(1): 入门理论

    机器学习相关的文章太多,选取一篇本人认为最赞的,copy文章中部分经典供自己学习,摘抄至 http://www.cnblogs.com/subconscious/p/4107357.html#firs ...

  3. [ML] I'm back for Machine Learning

    Hi, Long time no see. Briefly, I plan to step into this new area, data analysis. In the past few yea ...

  4. ANN:ML方法与概率图模型

    一.ML方法分类:          产生式模型和判别式模型 假定输入x,类别标签y         -  产生式模型(生成模型)估计联合概率P(x,y),因可以根据联合概率来生成样本:HMMs   ...

  5. Spark2 ML 学习札记

    摘要: 1.pipeline 模式 1.1相关概念 1.2代码示例 2.特征提取,转换以及特征选择 2.1特征提取 2.2特征转换 2.3特征选择 3.模型选择与参数选择 3.1 交叉验证 3.2 训 ...

  6. [Machine Learning & Algorithm]CAML机器学习系列2:深入浅出ML之Entropy-Based家族

    声明:本博客整理自博友@zhouyong计算广告与机器学习-技术共享平台,尊重原创,欢迎感兴趣的博友查看原文. 写在前面 记得在<Pattern Recognition And Machine ...

  7. [Machine Learning & Algorithm]CAML机器学习系列1:深入浅出ML之Regression家族

    声明:本博客整理自博友@zhouyong计算广告与机器学习-技术共享平台,尊重原创,欢迎感兴趣的博友查看原文. 符号定义 这里定义<深入浅出ML>系列中涉及到的公式符号,如无特殊说明,符号 ...

  8. 机器学习 - ML

    CNCC - 2016 | 机器学习(原文链接) Machine Learning - ML,机器学习起源于人工智能,是AI的一个分支. 机器学习的理论基础:计算学习理论 - Computationa ...

  9. ML 基础知识

    A computer program is said to learn from experience E with respect to some task T and some performan ...

随机推荐

  1. 【 js 基础 】【 源码学习 】柯里化和箭头函数

    最近在看 redux 的源码,代码结构很简单,主要就是6个文件,其中 index.js 负责将剩余5个文件中定义的方法 export 出来,其他5个文件各自负责一个方法的实现. 大部分代码比较简单,很 ...

  2. python学习之老男孩python全栈第九期_day010知识点总结

    def qqxing(l = []): # 可变数据类型 l.append(1) print(l)qqxing() # [1]qqxing([]) # [1]qqxing() # [1, 1]qqxi ...

  3. JS中String与Array的一些常用方法

    真是恨透了这些类似于substring substr slice 要么长得像,要么就功能相近的方法... 1⃣️string 1.substring(start开始位置的索引,end结束位置索引) 截 ...

  4. 关于animation的一些简单基础和使用方法记载

    第一次写博客,只是单纯的想把我自己的一些心得和使用过的css3的animation的一些方法记录和总结,方便下次使用,我写的这些都是刚入门适合做一些简单的动画动作,过于复杂的还有待发掘或者使用别的方法 ...

  5. JAVA:函数的定义、使用

      本文内容: 什么是函数 函数的定义格式 函数的重载(overload): 函数的调用使用注意 关于形式参数的使用 首发时间:2017-06-23 修改时间:2018-03-21:修改了布局,修改了 ...

  6. Problem2-Project Euler

    Even Fibonacci numbers   Each new term in the Fibonacci sequence is generated by adding the previous ...

  7. 无法将数据库从SINGLE_USER模式切换回MULTI_USER模式(Error 5064),及查找SQL Server数据库中用户spid(非SQL Server系统spid)的方法

    今天公司SQL Server数据库无意间变为SINGLE_USER模式了,而且使用如下语句切换回MULTI_USER失败: ALTER DATABASE [MyDB] SET MULTI_USER W ...

  8. 新建maven工程使用webapp插件弹出javax.servlet.http.HttpServlet was not found on the Java Build Path异常

    检查pom.xml文件中是否引用javax.servlet,引用如下所示:

  9. Java计算大整数

    import java.util.*; import java.math.*; //BigInteger类型在这个包里 public class Gcc_test { public static vo ...

  10. 网工最实用最常用的网络命令之一——Ping 命令详解(一)

    Ping是Windows.Unix和Linux系统下的一个命令.ping也属于一个通信协议,是TCP/IP协议的一部分.利用“ping”命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障. ...