SVM介绍
这部分的理论知识参考之前写的文章:“吴恩达机器学习”学习笔记
OpenCV3.x下SVM接口介绍
OpenCV3.x与OpenCV2.x中SVM的接口有了很大变化,在接口上使用了虚函数取代以前的定义。
下面介绍几个常用的接口,及其参数意义。
初始化函数
定义如下:
1 | CV_WRAP static Ptr<SVM> create(); |
参数设置函数
然后是一些设置SVM参数的函数:
1 | CV_WRAP virtual int getType() const = 0; |
具体的作用可以参考OpenCV文档,这里只介绍两个常用的函数:
1 | //设置SVM类型 |
这个函数用于设置SVM类型,OpenCV提供了五种类型:
1 | Types { |
注解:NU即$\nu$,EPS即$\epsilon$。SVC为分类模型,SVR为回归模型。
一般我们使用SVM进行二分类或者多分类任务,选择第一种SVM::C_SVC
即可。
还有一个函数就是:
1 | CV_WRAP virtual void setKernel(int kernelType) = 0; |
这个函数用于设置SVM的核函数类型,我们知道,通过选择SVM的核函数可以使SVM处理高阶、非线性问题。OpenCV提供几种核函数:
1 | enum KernelTypes { |
一般情况下使用高斯核函数可以很好处理大部分情况。
训练函数
OpenCV3.x中SVM的提供了训练函数也与2.x不同,如下:
1 | virtual bool trainAuto( const Ptr<TrainData>& data, int kFold = 10, |
trainAuto
可以在训练过程中自动优化SVM中的那些参数,而使用train
函数时,参数被固定,所以推荐使用trainAuto
函数。
在准备训练数据的时候,有下面几点需要注意,否则函数会报错
- SVM的训练函数是
ROW_SAMPLE
类型的,也就是说,送入SVM训练的特征需要reshape
成一个行向量,所有训练数据全部保存在一个Mat
中,一个训练样本就是Mat
中的一行,最后还要讲这个Mat
转换成CV_32F
类型,例如,如果有k个样本,每个样本原本维度是$(h,w)$,则转换后Mat
的维度为$(k,h∗w)$ - 对于多分类问题,label矩阵的行数要与样本数量一致,也就是每个样本要在label矩阵中有一个对应的标签,label的列数为1,因为对于一个样本,SVM输出一个值,我们在训练前需要做的就是设计这个值与样本的对应关系。对于有k个样本的情况,label的维度是$(k,1)$
预测函数
函数定义如下:
1 | float predict(cv::InputArrat samples, cv::OutputArray results = noArray(), int flags = 0) const; |
其中samples
就是需要预测的样本,这里样本同样要转换成ROW_SAMPLE
和CV_32F
格式,对于单个测试样本的情况,预测结果直接通过函数返回值返回,而如果samples
中有多个样本,就需要传进result
参数,预测结果以列向量的方式保存在result
数组中。假如有k个样本,每个样本原本的维度为$(h,w)$,则samples
的维度为$(k,h∗w)$,最终预测结果result
维度为$(k,1)$
样例程序
1 |
|