opencv svm
SVM训练样本方法总结(用于目标识别)
http://blog.csdn.net/xw20084898/article/details/21389885
SVM
Support Vector Machines是一种有监督的学习分类方法(SVM是一个分类器Classifier,也可以做回归Regression),是一个能够将不同类样本在样本空间分隔的超平面,
即给定一些标记(label)好的训练样本 (监督式学习), SVM算法输出一个最优化的分隔超平面。
(SVM算法的实质是找出一个能够将某个值最大化的超平面,最优分割超平面,最大化训练数据的间隔)
支持向量机方法
是建立在统计学习理论的VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)
和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力(或称泛化能力)
“机”(Machine)是机器学习领域对一些算法的统称,常把算法看做一个机器,或者学习函数。
SVM是一种有监督的学习方法,主要针对小样本数据进行学习、分类和预测,类似的根据样本进行学习的方法还有决策树归纳算法等
SVM的主要思想可以概括为两点 :
(1)针对线性可分情况进行分析,
对于线性不可分的情况,通过使用非线性映射算法将低维输入空间线性不可分的样本转化为高维特征空间使其线性可分,
从而使得高维特征空间采用线性算法对样本的非线性特征进行线性分析成为可能;
(2)它基于结构风险最小化理论之上在特征空间中建构最优分割超平面,使得学习器得到全局最优化,并且在整个样本空间的期望风险以某个概率满足一定上界
SVM的优点:
1、小样本,不需要很多样本,不需要有很多样本并不意味着训练样本的绝对量很少,而是说相对于其他训练分类算法比起来,
同样的问题复杂度下,SVM需求的样本相对是较少的。并且由于SVM引入了核函数,所以对于高维的样本,SVM也能轻松应对。
2、结构风险最小。这种风险是指分类器对问题真实模型的逼近与问题真实解之间的累积误差。
3、非线性,是指SVM擅长应付样本数据线性不可分的情况,主要通过松弛变量(也叫惩罚变量)和核函数技术来实现(SVM的精髓)
间隔
margin 超平面离所有训练样本的最小距离
f(x) = beta0 + beta^T*x,
beta叫做权重向量,beta0 叫做偏置(bias)
最优超平面
|beta0 + beta^T*x| = 1
式中 x 表示离超平面最近的那些点,这些点被称为支持向量, 该超平面也称为canonical超平面(决策面),可依据支持向量计算出分类超平面,再依据超平面对类别进行归类
SVM松弛变量(惩罚变量)
确保噪声样本不会被作为支持向量(而不管它们离超平面的距离有多近)
SVM训练样本:
对于给出的训练样本,要明确每个样本的归类是0还是1,即每个样本都需要标注一个确切的类别标签,提供给SVM训练使用(因SVM是一种有监督的学习分类方法)
对于样本的特征,以及特征的维度,SVM并没有限定,可以使用如Haar、角点、Sift、Surf、直方图等各种特征作为训练样本的表述参与SVM的训练。
Opencv要求训练数据存储在float类型的Mat结构中
类型
它的重要特征是可以处理非完美分类的问题(即训练数据不可以被线性分割),包括线性可分割和不可分割。
svm_type: (CvSVMParams中成员变量 CV_PROP_RW int svm_type;)
SVM的类型:
CvSVM::C_SVC:
C类支持向量分类机,n类分组(n≥2),允许用异常值惩罚因子C进行不完全分类。
CvSVM::NU_SVC:
类支持向量分类机,n类似然不完全分类的分类器。参数为取代C(其值在区间【0,1】中,nu越大,决策边界越平滑)。
CvSVM::ONE_CLASS:
单分类器,所有的训练数据提取自同一个类,然后SVM建立了一个分界线以分割该类在特征空间中所占区域和其它类在特征空间中所占区域。
CvSVM::EPS_SVR:
类支持向量回归机,训练集中的特征向量和拟合出来的超平面的距离需要小于p。异常值惩罚因子C被采用。
CvSVM::NU_SVR:
类支持向量回归机,代替了p。
<2> kernel_type: SVM的内核类型(4种):
核函数
为了将训练样本映射到更有利于线性分割的样本集中。映射的结果是增加了样本向量的维度。
SVM核函数是SVM的关键,核函数的作用就是在保证不增加算法复杂度的情况下将完全不可分问题转化为可分或达到近似可分的状态
(低维空间向量集通常难于划分,可将它们映射到高维空间,选用适当的核函数,就可以得到高维空间的分类函数)
在SVM理论中,采用不同的核函数将导致不同的SVM算法。在确定了核函数之后,由于确定核函数的已知数据也存在一定的误差,考虑到推广性问题,
因此引入了 松弛系数(用以处理样本数据可能存在的噪声问题) 以及 惩罚系数 两个参变量来加以校正。在确定了核函数基础上,再经过大量对比实验等将这两个系数取定
常用的核函数有以下4种:
⑴ 线性核函数
⑵ 多项式核函数
⑶ 径向基(RBF)核函数(高斯核函数)
⑷ Sigmoid 核函数(二层神经网络核函数)
kernel_type: (CvSVMParams中成员变量 CV_PROP_RW int kernel_type;)
SVM的内核类型(:
CvSVM::LINEAR:
线性内核,没有任何向量映射至高维空间(表示不需要进行高维空间映射),线性区分(或回归)在原始特征空间中被完成,这是最快的选择
CvSVM::POLY:
多项式内核:
CvSVM::RBF:
基于径向的函数,对于大多数情况都是一个较好的选择:
CvSVM::SIGMOID:
Sigmoid函数内核:
径向基(RBF)核函数(高斯核函数):
K(x, x1) = exp{-|x-x1|^2/σ^2}
它可将原始空间映射到无穷维空间。对于参数σ,如果选的很大,高次特征上的权重实际上衰减得非常快,如果选得很小,则可以将任意的数据映射为线性可分(过小则可能出现非常严重的过拟合问题)
径向基(RBF)核函数的参数选取
(分类器的好坏取决于参数C、σ的确定。参数选择的好坏直接影响到分类器性能的好坏)
惩罚因子C
控制着使间隔 margin 最大且错误率最小的折中,就是在确定的特征空间中调节学习机器的置信范围和经验风险的比例
参数σ
是RBF核函数参数,主要影响样本数据在高维特征空间中分布的复杂程度。
常用的C、σ参数选择方法:
1、网格法(OpenCV中SVM用到)
2、双线性法
3、梯度下降搜索法
4、遗传算法
验证核函数性能的方法(衡量泛化能力):
1、单一验证估计
2、K 折交叉验证(OpenCV中SVM用到)
3、留一法
算法终止条件
SVM训练的过程是一个通过迭代方式解决约束条件下的二次优化问题,可以设定一个最大迭代次数和容许误差的组合,以允许算法在适当的条件下停止计算
// SVM training parameters
struct CV_EXPORTS_W_MAP CvSVMParams
{
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 );
//degree: 内核函数(POLY)的参数degree。
//gamma: 内核函数(POLY/ RBF/ SIGMOID)的参数 。
//coef0: 内核函数(POLY/ SIGMOID)的参数coef0。
//Cvalue: SVM类型 (C_SVC/ EPS_SVR/ NU_SVR)的参数C。
//nu: SVM类型 (NU_SVC/ ONE_CLASS/ NU_SVR)的参数 。
//p: SVM类型 (EPS_SVR)的参数 。
//class_weights: C_SVC中的可选权重,赋给指定的类,乘以C以后变成class_weights×C。所以这些权重影响不同类别的错误分类惩罚项。权重越大,某一类别的误分类数据的惩罚项就越大。
//term_crit: SVM的迭代训练过程的中止条件,解决部分受约束二次最优问题。您可以指定的公差和/或最大迭代次数。
CV_PROP_RW int svm_type;
CV_PROP_RW int kernel_type;
CV_PROP_RW double degree; // for poly
CV_PROP_RW double gamma; // for poly/rbf/sigmoid
CV_PROP_RW double coef0; // for poly/sigmoid
CV_PROP_RW double C; // for CV_SVM_C_SVC, CV_SVM_EPS_SVR and CV_SVM_NU_SVR
CV_PROP_RW double nu; // for CV_SVM_NU_SVC, CV_SVM_ONE_CLASS, and CV_SVM_NU_SVR
CV_PROP_RW double p; // for CV_SVM_EPS_SVR
CvMat* class_weights; // for CV_SVM_C_SVC
CV_PROP_RW CvTermCriteria term_crit; // termination criteria
};
// SVM model
class CV_EXPORTS_W CvSVM : public CvStatModel
{
public:
// SVM type
enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };
// SVM kernel type
enum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3 };
// SVM params type
enum { C=0, GAMMA=1, P=2, NU=3, COEF=4, DEGREE=5 };
...
CV_WRAP CvSVM( const cv::Mat& trainData, const cv::Mat& responses,
const cv::Mat& varIdx=cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(),
CvSVMParams params=CvSVMParams() );
CV_WRAP virtual bool train( const cv::Mat& trainData, const cv::Mat& responses,
const cv::Mat& varIdx=cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(),
CvSVMParams params=CvSVMParams() );
//trainData: 训练数据,必须是CV_32FC1 (32位浮点类型,单通道)。数据必须是CV_ROW_SAMPLE的,即特征向量以行来存储。
//responses: 响应数据,通常是1D向量存储在CV_32SC1 (仅仅用在分类问题上)或者CV_32FC1格式。
//varIdx: 指定感兴趣的特征。可以是整数(32sC1)向量,例如以0为开始的索引,或者8位(8uC1)的使用的特征或者样本的掩码。用户也可以传入NULL指针,用来表示训练中使用所有变量/样本。
//sampleIdx: 指定感兴趣的样本。描述同varIdx。
//params: SVM参数
CV_WRAP virtual bool train_auto( const cv::Mat& trainData, const cv::Mat& responses,
const cv::Mat& varIdx, const cv::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);
CV_WRAP virtual float predict( const cv::Mat& sample, bool returnDFVal=false ) const;
CV_WRAP_AS(predict_all) void predict( cv::InputArray samples, cv::OutputArray results ) const;
CV_WRAP virtual int get_support_vector_count() const; //获取到支持向量的数量信息
virtual const float* get_support_vector(int i) const; //根据索引号来获取指定位置的支持向量
};
线性可分情况,SVM使用:
(1)准备训练样本及其类别标签( trainingDataMat,labelsMat )
(2)设置训练参数(CvSVMParams)
(3)对SVM进行训练( CvSVM:: train)
(4)对新的输入样本进行预测( CvSVM:: predict)
(5)获取支持向量( CvSVM:: get_support_vector_count ,CvSVM:: get_support_vector )
SVM处理流程:
1、收集数据:相关性分析、特征选择 (如主成份分析PCA)。
2、归一化数据:根据实际要求,将数据的取值范围转化为统一的区间如[a,b], a,b为整数
3、分训练集和测试集
利用抽样技术将数据集分为训练集和测试集。抽样技术有分层抽样,简单抽样(等概率抽样)。 一般训练集数量大于测试集数量 ,就是要保证足够的训练样例。
4、数据转化为软件(接口)所支持的格式
5、核函数选取(优先考虑RBF)
6、使用交叉验证(cross-validation)寻找最佳参数C和Υ
7、使用最佳参数C和Υ来训练整个训练集,得出模型
8、测试:利用测试集测试模型,得到精度
9. 识别分类:两个类超平面的形成,意味着目标函数的形成,然后代入待识别样本,判定属于那个类