在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. python 递归和二分法

    一 内置函数 1. revserd 翻转,返回的是迭代器 # 将 s 倒置 s = '不是上海自来水来自海上' # 方法一 print(s[::-1]) # 方法二 s1 = reversed(s) ...

  2. 为什么main方法是public static void?

    Main方法是我们学习Java编程语言时知道的第一个方法,你是否曾经想过为什么main方法是public.static.void的.当然,很多人首先学的是C和C++,但是在Java中main方法与前者 ...

  3. js 匿名函数立即执行问题

    js立即执行函数写法理解 这篇真的写得很清楚了,不光括号可以将函数声明转换成函数表达式然后立即执行,!,+,-,=也都可以转换,但是可能会带来意外的结果,因此一般都用括号实现. 还有关于for (va ...

  4. 纯小白入手 vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单

    vue3.0 CLI 真小白一步一步入手全教程系列:https://www.cnblogs.com/ndos/category/1295752.html 我的 github 地址 - vue3.0St ...

  5. Android逆向 Android平台虚拟机

    一 Dalvik:是Google开发运行在Android平台的Java虚拟机, Android程序编译后会生成dex文件.Dalvik虚拟机下运行Java时,要将字节码通过即时编译器(just in ...

  6. Expo大作战(二十五)--expo sdk api之Admob

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  7. Python Django框架笔记(三):django工作方式简单说明和创建用户界面

    (一)  说明 简单说明下django的工作方式,并举2个例子. (二)  Django工作方式 假定我们有下面这些文件 ,这里在前2篇的基础上增加了 templates目录(存放html文件) 和s ...

  8. Ehcache缓存配置和基本使用

    前言 在java项目广泛的使用中.它是一个开源的.设计于提高在数据从RDBMS中取出来的高花费.高延迟采取的一种缓存方案. 正因为Ehcache具有健壮性(基于java开发).被认证(具有apache ...

  9. 【Redis数据库】再有人问你CAP理论是什么,就把这篇文章发给他

    CAP是Consistency(一致性),Availability(可用性),Partition tolerance(分区容错性)的缩写.在学习redis过程中看到这个名词,查找各位大佬的文章发现这篇 ...

  10. postgresql排序分页时数据重复问题

    当同时排序又分页时,如果排序的字段X不是唯一字段,当多个记录的X字段有同一个值时顺序是随机的. 这个有可能造成分页时数据重复的问题.某一页又把上一页的数据查出来了,其实数据库只有一条记录. 解决办法: ...