OpenCV 2.4.9 支持向量机(SVM)说明

9 篇文章 6 订阅
3 篇文章 0 订阅

本文翻译自OpenCV 2.4.9官方文档《opencv2refman.pdf》。

前言

Originally, support vector machines (SVM) was a technique for building an optimal binary (2-class) classifier. Later the technique was extended to regression and clustering problems. SVM is a partial case of kernel-based methods. It maps feature vectors into a higher-dimensional space using a kernel function and builds an optimal linear discriminating function in this space or an optimal hyper-plane that fits into the training data. In case of SVM, the kernel is not defined explicitly. Instead, a distance between any 2 points in the hyper-space needs to be defined.

The solution is optimal, which means that the margin between the separating hyper-plane and the nearest feature vectors from both classes (in case of 2-class classifier) is maximal. The feature vectors that are the closest to the hyper-plane are called support vectors, which means that the position of other vectors does not affect the hyper-plane (the decision function).

SVM implementation in OpenCV is based on LibSVM.

通常来说,支持向量机(SVM)是一种用来构建一个最优二进制分类器(只分为两类)。后来,这项技术被延伸到回归与集群问题。SVM是以核函数方法为基础的众多方法之一,它通过核函数将特征向量映射到高维空间,并在这个空间创造一个最优线性分类函数,或者创造一个适合所有训练数据的最优超平面。在SVM中,核函数定义的并不明确,除此之外,在超平面上任意两点之间的距离都需要被定义。
解决方法是最优的,意味着分割超平面与两个分类(即二类分类器)上距离最近的特征向量之间的距离是最大的。距离超平面最近的特征向量被称为支持向量,就是说其它向量的位置都不会影响超平面(即决策函数)。
SVM在OpenCV中的实现是基于LibSVM的。

CvParamGrid

CvParamGrid

struct CvParamGrid
该结构体代表了统计模型参数的对数网格范围,它通过更新模型参数来优化统计模型准确度,准确度通过交叉验证的计算进行估计。

  • double CvParamGrid::min_val
    • 统计模型参数的最小值;
  • double CvParamGrid::max_val
    • 统计模型参数的最大值;
  • double CvParamGrid::step
    • 迭代统计模型参数的对数步长;

网格决定了统计模型参数值的迭代序列,如下所示:

(min_val,min_val×step,min_val×step2,...,min_val×stepn)

其中 n 是一个最大索引号,满足:
min_val×stepn<max_val

网格已经经过对数化,所以 step一定大于1。

CvParamGrid::CvParamGrid

CvParamGrid的构造函数。

  • C++: CvParamGrid::CvParamGrid()
  • C++: CvParamGrid::CvParamGrid( double min_val, double max_val, double log_step )

整个构造函数初始化了对应的数据成员,默认的构造函数创造的虚拟网格如下:

CvParamGrid::CvParamGrid()
{
    min_val = max_val = step = 0;
}

CvParamGrid::check

检测网格的有效性。

  • C++: bool CvParamGrid::check()

如果网格有效的,则返回true;如;如果无效,则返回false。当且仅当下列情况时,网格是有效的:

  • 网格的下边缘边界小于上边缘边界;
  • 网格的下边缘边界是正值;
  • 网格步长大于1;

CvSVMParams

CvSVMParams

struct CvSVMParams
SVM训练参数。结构体将被初始化,并传递给CvSVM的训练函数。

CvSVMParams::CvSVMParams

CvSVMParams的构造函数。

  • C++: CvSVMParams::CvSVMParams()
  • C++: CvSVMParams::CvSVMParams( int svm_type, int kernel_type, double degree, double gamma, double coef0, double Cvalue, double nu, double p, CvMat* class_weights,CvTermCriteria term_crit )

CvSVMParams()的参数

svm_type

SVM公式类型。可能取值如下:

  • CvSVM::C_SVC C 支持向量分类器。可以分为n类 (n ≥ 2),并允许在带有松弛变量 (outliers) 的惩罚乘子C的情况下的不完善分类;
  • CvSVM::NU_SVCν支持向量分类器。可以分为n类 (n ≥ 2),而且可能存在不完善的分类。参数 ν 替代参数 C 使用,且ν值范围在[0, 1]之内,该值越大,决策边缘越光滑;
  • CvSVM::ONE_CLASS:分布估计(单类SVM)。所有的训练数据都是同一类的,SVM构建了边界,将该类与特征空间的其他部分分离;
  • CvSVM::EPS_SVR ϵ 支持向量回归。训练集特征向量与拟合超平面间的距离一定小于 p 。该分类器的松弛变量 (outliers) 使用的惩罚因子为C
  • CvSVM::NU_SVR ν 支持向量回归。 ν 被用来代替 p

其他具体解释见LibSVM

kernel_type

SVM核函数类型。可能取值如下:

  • CvSVM::LINEAR:线性核。无映射,在原始特征空间中进行线性分类(或回归)。这是速度最快的选项。核函数为:K(xi,xj)=xTixj
  • CvSVM::POLY:多项式核。核函数为: K(xi,xj)=(γxTixj+coef0)degree,γ>0
  • CvSVM::RBF:以半径为基准的函数 (Radial basis function, RBF),在大多情况下的优秀选择。核函数: K(xi,xj)=eγxixj2,γ>0
  • CvSVM::SIGMOID:sigmoid函数。核函数为: K(xi,xj)=tanh(γxTixj+coef0)
degree

核函数的参数 degree ,用于多项式核。

gamma

核函数的参数 γ ,用于多项式核 / RBF核 / Sigmoid核。

coef0

核函数的参数 coef0 ,用于多项式核 / Sigmoid核。

Cvalue

SVM最优问题的参数 C ,用于 C_SVC / EPS_SVR / NU_SVR 分类器。

nu

SVM最优问题的参数ν,用于 NU_SVC / ONE_CLASS / NU_SVR 分类器。

p

SVM最优问题的参数 ϵ ,用于 EPS_SVR 分类器。

class_weights

C_SVC问题中的最优权重,它被分配给特定的分类。这些权重与因子 C 做乘运算,所以第 i 个分类的的参数C值应该为: class_weightsi×C 。因此,这些权重对其他分类的误分类惩罚有一定影响,权重越大,对应分类的数据误分类的惩罚越大。

term_crit

SVM训练迭代的迭代终止标准,用于解决带有约束条件的二次最优规划问题。你也能明确公差与 / 或迭代最大次数。

CvSVMParams()的函数

默认的构造函数使用下列取值初始化该结构体:

CvSVMParams::CvSVMParams() :
svm_type(CvSVM::C_SVC), kernel_type(CvSVM::RBF), degree(0),
gamma(1), coef0(0), C(1), nu(0), p(0), class_weights(0)
{
    term_crit = cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, FLT_EPSILON );
}

CvSVM

class CvSVM : public CvStatModel

支持向量机。

注:
· (Python) 使用SVM的数字识别例程可以在路径 opencv_source/samples/python2/digits.py 下找到;
· (Python) 使用SVM的网格寻找数字识别可以在路径 opencv_source/samples/python2/digits_adjust.py 下找到;
· (Python) 使用SVM的视频数字识别例程可以在路径 opencv_source/samples/python2/digits_video.py 下找到;

CvSVM::CvSVM

默认构造函数与训练构造函数。

  • C++: CvSVM::CvSVM()
  • C++: CvSVM::CvSVM( const Mat& trainData, const Mat& responses, const Mat& varIdx=Mat(), const Mat& sampleIdx=Mat(), CvSVMParams params=CvSVMParams() )
  • C++: CvSVM::CvSVM( const CvMat* trainData, const CvMat* responses, const CvMat* varIdx=0, const CvMat* sampleIdx=0, CvSVMParams params=CvSVMParams() )
  • Python: cv2.SVM( [ trainData, responses [ , varIdx [ , sampleIdx [ , params ]]]] ) →

构造函数与CvStatModel::CvStatModel()有相同的形式。可以在本文档的CvStatModel::train()寻找参数的具体含义。

本文注:
下面从CvStatModel::train()中找到参数列表:

  • C++: 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,] … ) = 0

对于其中参数,解释如下:

CvSVM()的参数

通过使用一组输入特征向量并输出相应值(或响应)的方法,训练函数训练了统计模型。输入 / 输出向量(或输入 / 输出值)都以矩阵形式传递。默认情况下,输入特征向量被存入train_data的列中,所有训练向量的组成(即特征)被连续存储。然而当全部输入集的各特定特征值(特征 / 输入变量)的所有值都是连续存储的情况下,一些算法可以处理转置表达式。如果两种布局都支持,训练方法包含的tflag参数起作用,该参数用来明确数据存储方向,具体如下:

  • tflag=CV_ROW_SAMPLE:特征向量按行存储;
  • tflag=CV_COL_SAMPLE:特征向量按列存储;

训练数据train_data必须使用CV_32FC1格式(32位浮点数,单通道)。返回数据responses通常以一维向量(一行或一列)的形式存储,向量中的数据格式为CV_32SC1(仅在分类问题中)或CV_32FC1,返回数据的每个值与训练数据的每个向量一一对应。相反的,某些类似于各种类型的神经网络,返回数据的类型都为向量形式。
对于分类问题,返回值是离散的分类标签;对于回归问题,返回值是被估计函数的值。一些算法只能处理分类问题,一些算法只能处理回归问题,也有一些算法可以处理两种问题。对于后者,输出参数的类型可以通过两种方式传递:一种是单独的参数,另一种是向量var_type的最后一个元素:

  • CV_VAR_CATEGORICAL:输出值为离散类别标签;
  • CV_VAR_ORDERED( =CV_VAR_NUMERICAL):输出值为顺序排列的,即两个不同的值可以以数字形式拿来对比,而且这是一个回归问题;

输入变量的类型可以通过输入参数var_type指定。大多数算法仅仅可以处理连续输入变量。
很多 ML (机器学习)模型可以用一个指定的特征子集与 / 或指定的训练集的样本子集进行训练。为了使其对我们更加简单,训练方法train函数通常包含参数var_idxsample_idx,前者(即var_idx)用来指定该兴趣的变量(特征),后者(即sample_idx)指定感兴趣的样本。两个向量可以使用整数 (CV_32SC1) 向量(基于0的索引列表),也可以使用8位 (CV_8UC1)的活动变量 / 样本。我们也可以传递NULL空指针来代替众多参数,这样的话所有的变量 / 样本都被用来训练。
此外,当已知训练样本的已知特征存在未知值时,一些算法可以处理丢失的量(例如,我们星期一忘记测量病人A的体温)。参数missing_mask是一个与train_data有相同尺寸的8位矩阵,它被用来标记丢失的值(即用非零值进行标记)。
通常,先前的模型统计在运行训练函数之前都被CvStatModel::clear()清除了,然而一些算法可以选择使用新训练数据更新模型统计,而不是重置它。

CvSVM::train

训练一个SVM。

  • C++: bool CvSVM::train( const Mat& trainData, const Mat& responses, const Mat& varIdx=Mat(), const Mat& sampleIdx=Mat(), CvSVMParams params=CvSVMParams() )
  • C++: bool CvSVM::train( const CvMat* trainData, const CvMat* responses, const CvMat* varIdx=0, const CvMat* sampleIdx=0, CvSVMParams params=CvSVMParams() )
  • Python: cv2.SVM.train( trainData, responses [ , varIdx [ , sampleIdx [ , params ]]] ) → retval

该函数用来训练一个 SVM 模型,它继承了CvStatModel::train()函数的参数列表,但对下列进行了限制:

  • 数据布局仅仅支持CV_ROW_SAMPLE
  • 输入变量全部为连续值;
  • 输出变量可以是离散的 (param.svm = CvSVM::C_SVC 或 param.svm = CvSVM::NU_SVC),也可以是连续的 (param.svm = CvSVM::EPS_SVR 或 param.svm = CvSVM::NU_SVR),也可以不指定 (param.svm = CvSVM::ONE_CLASS)。
  • 不支持丢失测量值;

所有其他参数都被收集进入CvSVMParams结构体。

CvSVM::train_auto

用最优参数训练SVM。

  • C++: bool CvSVM::train_auto( const Mat& trainData, const Mat& responses, const Mat& varIdx, const Mat& sampleIdx, CvSVMParams params, int k_fold = 10,
      CvParamGrid Cgrid = CvSVM::get_default_grid(CvSVM::C),
      CvParamGrid gammaGrid = CvSVM::get_default_grid(CvSVM::GAMMA),
      CvParamGrid pGrid=CvSVM::get_default_grid(CvSVM::P),
      CvParamGrid nuGrid=CvSVM::get_default_grid(CvSVM::NU),
      CvParamGrid coeffGrid=CvSVM::get_default_grid(CvSVM::COEF),
      CvParamGrid degreeGrid=CvSVM::get_default_grid(CvSVM::DEGREE),
      bool balanced=false )
  • C++: bool CvSVM::train_auto( const CvMat* trainData, const CvMat* responses, const CvMat* varIdx, const CvMat* sampleIdx, CvSVMParams params, int kfold=10,
      CvParamGrid Cgrid=get_default_grid(CvSVM::C),
      CvParamGrid gammaGrid=get_default_grid(CvSVM::GAMMA),
      CvParamGrid pGrid=get_default_grid(CvSVM::P),
      CvParamGrid nuGrid=get_default_grid(CvSVM::NU),
      CvParamGrid coeffGrid=get_default_grid(CvSVM::COEF),
      CvParamGrid degreeGrid=get_default_grid(CvSVM::DEGREE),
      bool balanced=false )
  • Python: cv2.SVM.train_auto( trainData, responses, varIdx, sampleIdx, params [ , k_fold [ , Cgrid [ , gammaGrid [ , pGrid [ , nuGrid [ , coeffGrid [ , degreeGrid [ , balanced ]]]]]]]] ) → retval

train_auto()参数

  • k_fold:交叉验证参数。训练集被分成k_fold子集。一个子集被用于测试模型,其余子集组成训练集。所以 SVM 算法总共被执行 k_fold 次;
  • Grid:相关SVM参数的迭代网格;
  • balanced:如果为true,而且问题为二类分类器,那么该函数就创造更平衡的交叉验证子集,子集各分类之间的比例接近在整个训练数据集中比例;

train_auto()函数说明

train_auto()函数通过从CvSVMParams中选择最优参数C, gamma, p, nu, coef0, degree,自动训练 SVM 模型。当测试集误差的交叉验证估计值达到最小值时,参数被认为是最优的。
如果不需要优化某参数,相应的网格步长应该被设置为任意小于等于1的值。例如为了避免gamma选取最优值,则设置 gamma_grid.step = 0,并令gamma_grid.min_val, gamma_grid.max_val设置为任意值。这种情况下,params.gamma的值将被输入参数gamma赋值。
最后,如果需要优化某参数,但相应网格是位置的,我们可以调用函数CvSVM::get_default_grid()。如果要生成一个网格,以gamma为例,则调用函数:CvSVM::get_default_grid(CVSVM::GAMMA)
train_auto()函数可以被用来处理分类问题 (param.svm = CvSVM::C_SVC 或 param.svm = CvSVM::NU_SVC),也可以处理回归问题 (param.svm = CvSVM::EPS_SVR 或 param.svm = CvSVM::NU_SVR)。如果有param.svm_type = CvSVM::ONE_CLASS,则不会生成最优值,且普通带有确定参数的 SVM 将被执行。

CvSVM::predict

预测输入样本的返回值。

  • C++: float CvSVM::predict( const Mat& sample, bool returnDFVal=false ) const
  • C++: float CvSVM::predict( const CvMat* sample, bool returnDFVal=false ) const
  • C++: float CvSVM::predict( const CvMat* samples, CvMat* results ) const
  • Python: cv2.SVM.predict( sample [ , returnDFVal ] ) → retval
  • Python: cv2.SVM.predict_all( samples [ , results ] ) → results

predict()参数

  • sample:预测的单个输入样本;
  • samples:预测的多输入样本;
  • returnDFVal:指定一个返回值的类型。如果为true,且问题为二类分类器,那么该函数返回决策函数值是有符号的间隔距离;如果为false,那么函数返回一个类标签(分类问题),或者返回估计函数值(回归问题);
  • results:输出对应样本的预测返回值;

如果我们通过了一个样本,那么预测结果就会返回。如果我们想要得到几个样本的返回值,那么我们应该用矩阵results来保存预测结果。
该函数与 TBB 库并行运行。

CvSVM::get_default_grid

生成一个 SVM 参数的网格。

  • C++: CvParamGrid CvSVM::get_default_grid( int param_id )

param_id
SVM 参数的 ID,必须从下列表中取值:

  • CvSVM::C
  • CvSVM::GAMMA
  • CvSVM::P
  • CvSVM::NU
  • CvSVM::COEF
  • CvSVM::DEGREE

网格将根据该 ID 参数生成。

该函数根据 SVM 算法的指定参数而生成一个网格,该网格会传递给函数CvSVM::train_auto()

CvSVM::get_params

返回当前 SVM 参数。

  • C++: CvSVMParams CvSVM::get_params() const

在使用函数CvSVM::train_auto()自动训练时,该函数被用来获取最优参数。

CvSVM::get_support_vector

取得若干支持向量与特定的向量。

  • C++: int CvSVM::get_support_vector_count() const
  • C++: const float* CvSVM::get_support_vector( int i ) const
  • Python: cv2.SVM.get_support_vector_count() → retval

i:特定的支持向量的序列;

该方法用来取得一组支持向量。

CvSVM::get_var_count

返回已使用特征的数量(即变量数量);

  • C++: int CvSVM::get_var_count() const
  • Python: cv2.SVM.get_var_count() → retval
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值