收藏 分享(赏)

SVM支持向量机算法及其代码实现.doc

上传人:kpmy5893 文档编号:6546232 上传时间:2019-04-16 格式:DOC 页数:13 大小:68.50KB
下载 相关 举报
SVM支持向量机算法及其代码实现.doc_第1页
第1页 / 共13页
SVM支持向量机算法及其代码实现.doc_第2页
第2页 / 共13页
SVM支持向量机算法及其代码实现.doc_第3页
第3页 / 共13页
SVM支持向量机算法及其代码实现.doc_第4页
第4页 / 共13页
SVM支持向量机算法及其代码实现.doc_第5页
第5页 / 共13页
点击查看更多>>
资源描述

1、支持向量机算法及其代码实现支持向量机(SVM) ,起初由 vapnik 提出时,是作为寻求最优(在一定程度上)二分类器的一种技术。後来它又被拓展到回归和聚类应用。SVM 是一种基于核函数的方法,它通过某些核函数把特征向量映射到高维空间,然後建立一个线性判别函数(或者说是一个高维空间中的能够区分训练数据的最优超平面,参考异或那个经典例子) 。假如 SVM 没有明确定义核函数,高维空间中任意两点距离就需要定义。 解是最优的在某种意义上是两类中距离分割面最近的特征向量和分割面的距离最大化。离分割面最近的特征向量被称为”支撑向量” ,意即其它向量不影响分割面(决策函数) 。 有很多关于 SVM 的参考

2、文献,这是两篇较好的入门文献。 【Burges98】 C. Burges. “A tutorial on support vector machines for pattern recognition“, Knowledge Discovery and Data Mining 2(2), 1998. (available online at 1). LIBSVM - A Library for Support Vector Machines. By Chih-Chung Chang and Chih-Jen Lin (2) CvSVM 支撑矢量机 class CvSVM : public Cv

3、StatModel /继承自基类 CvStatModelpublic:/ SVM typeenum C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 ;/SVC 是SVM 分类器,SVR 是 SVM 回归/ SVM kernel typeenum LINEAR=0, POLY=1, RBF=2, SIGMOID=3 ; /提供四种核函数,分别是线性,多项式,径向基,sigmoid 型函数。CvSVM();virtual CvSVM();CvSVM( const CvMat* _train_data, const CvMa

4、t* _responses,const CvMat* _var_idx=0, const CvMat* _sample_idx=0,CvSVMParams _params=CvSVMParams() );virtual bool train( const CvMat* _train_data, const CvMat* _responses,const CvMat* _var_idx=0, const CvMat* _sample_idx=0,CvSVMParams _params=CvSVMParams() );virtual float predict( const CvMat* _sam

5、ple ) const;virtual int get_support_vector_count() const;virtual const float* get_support_vector(int i) const;virtual void clear();virtual void save( const char* filename, const char* name=0 );virtual void load( const char* filename, const char* name=0 );virtual void write( CvFileStorage* storage, c

6、onst char* name );virtual void read( CvFileStorage* storage, CvFileNode* node );int get_var_count() const return var_idx ? var_idx-cols : var_all; protected:.;CvSVMParamsSVM 训练参数 struct struct CvSVMParamsCvSVMParams();CvSVMParams( int _svm_type, int _kernel_type,double _degree, double _gamma, double

7、 _coef0,double _C, double _nu, double _p,CvMat* _class_weights, CvTermCriteria _term_crit );int svm_type;int kernel_type;double degree; / for polydouble gamma; / for poly/rbf/sigmoiddouble coef0; / for poly/sigmoiddouble C; / for CV_SVM_C_SVC, CV_SVM_EPS_SVR and CV_SVM_NU_SVRdouble nu; / for CV_SVM_

8、NU_SVC, CV_SVM_ONE_CLASS, and CV_SVM_NU_SVRdouble p; / for CV_SVM_EPS_SVRCvMat* class_weights; / for CV_SVM_C_SVCCvTermCriteria term_crit; / termination criteria;svm_type,SVM 的类型: CvSVM:C_SVC - n(n=2)分类器,允许用异常值惩罚因子 C 进行不完全分类。 CvSVM:NU_SVC - n 类似然不完全分类的分类器。参数 nu 取代了 c,其值在区间【0,1 】中,nu 越大,决策边界越平滑。 CvSV

9、M:ONE_CLASS - 单分类器,所有的训练数据提取自同一个类里,然後 SVM 建立了一个分界线以分割该类在特征空间中所占区域和其它类在特征空间中所占区域。 CvSVM:EPS_SVR - 回归。 训练集中的特征向量和拟合出来的超平面的距离需要小于 p。异常值惩罚因子 C 被采用。 CvSVM:NU_SVR - 回归;nu 代替了 p kernel_type/核类型: CvSVM:LINEAR - 没有任何向映射至高维空间,线性区分(或回归)在原始特征空间中被完成,这是最快的选择。 d(x,y) = x?y = (x,y) CvSVM:POLY - 多项式核: d(x,y) = (gamm

10、a*(x?y)+coef0)degree CvSVM:RBF - 径向基,对于大多数情况都是一个较好的选择:d(x,y) = exp(-gamma*|x-y|2) CvSVM:SIGMOID - sigmoid 函数被用作核函数: d(x,y) = tanh(gamma*(x?y)+coef0) degree, gamma, coef0:都是核函数的参数,具体的参见上面的核函数的方程。 C, nu, p:在一般的 SVM 优化求解时的参数。 class_weights: Optional weights, assigned to particular classes. They are mul

11、tiplied by C and thus affect the mis-classification penalty for different classes. The larger weight, the larger penalty on mis-classification of data from the certain class. term_crit: Termination procedure for iterative SVM training procedure (which solves a partial case of constrained quadratic o

12、ptimization problem) The structure needs to be initialized and passed to the training method of CvSVM CvSVM:train 训练 SVM bool CvSVM:train( const CvMat* _train_data, const CvMat* _responses,const CvMat* _var_idx=0, const CvMat* _sample_idx=0,CvSVMParams _params=CvSVMParams() );The method trains SVM m

13、odel. It follows the conventions of generic train “method“ with the following limitations: only CV_ROW_SAMPLE data layout is supported, the input variables are all ordered, the output variables can be either categorical (_params.svm_type=CvSVM:C_SVC or _params.svm_type=CvSVM:NU_SVC) or ordered (_par

14、ams.svm_type=CvSVM:EPS_SVR or _params.svm_type=CvSVM:NU_SVR) or not required at all (_params.svm_type=CvSVM:ONE_CLASS), missing measurements are not supported. 所有的参数都被集成在 CvSVMParams 这个结构中。 CvSVM:get_support_vector*得到支撑矢量和特殊矢量的数 int CvSVM:get_support_vector_count() const;const float* CvSVM:get_suppo

15、rt_vector(int i) const;这个方法可以被用来得到支撑矢量的集合。 补充:在 WindowsXP+OpenCVRC1 平台下整合 OpenCV 与 libSVM 虽然从 RC1 版开始 opencv开始增设 ML 类,提供对常见的分类器和回归算法的支持。但是尚存在一些问题,比如说例子少(官方许诺说很快会提供一批新例子,见 CVS 版) 。单说 SVM 这种算法,它自己提供了一套比较完备的函数,但是并不见得优于老牌的 libsvm(它也应该参考过 libsvm,至于是否效率优于 libsvm,我并没有作过测试,官方也没有什么说法,但是 libsvm 持续开源更新,是公认的现存的

16、开源 SVM 库中最易上手,性能最好的库) 。所以在你的程序里整合opencv 和 libSVM 还是一种比较好的解决方案。在 VC 中整合有些小地方需要注意,这篇文档主要是提供把图象作为 SVM 输入时程序遇到的这些小问题的解决方案。希望大家遇到问题时,多去读 libSVM 的源码,它本身也是开源的,C 代码写得也很优秀,数据结构定义得也比较好。 首先是 SVM 的训练,这部分我并没有整合到 VC 里,直接使用它提供的 python 程序,虽然网格搜索这种简易搜索也可以自己写,但是识别时只需要训练生成的 SVMmodel 文件即可,所以可以和主程序分离开。至于 python 在 window

17、s 下的使用,还是要设置一下的,首先要在系统环境变量 path 里把 python 的路径设进去,libsvm 画训练等高线图还需要 gnuplot 的支持,打开 python 源程序(grid.py) ,把 gnuplot_exe 设置成你机器里的安装路径,这样才能正确的运行程序。然後就是改步长和搜索范围,官方建议是先用大步长搜索,搜到最优值後再用小步长在小范围内搜索(我觉得这有可能会陷入局部最优,不过近似出的结果还可以接受) 。我用的 python 版本是 2.4,gnuplot4.0。 常用 libSVM 资料链接 官方站点,有一些 tutorial 和测试数据 哈工大的机器学习论坛,非

18、常好 上交的一个研究生还写过 libsvm2.6 版的代码中文注释,源链接找不着了,大家自己搜搜吧,写得很好,上海交通大学模式分析与机器智能实验室。本文来自 CSDN 博客,转载请标明出处:http:/ 支持向量机 SMO 算法 实现 机器学习 如果对 SVM 原理不是很懂的,可以先看一下入门的视频,对帮助理解很有用的,然后再深入一点可以看看这几篇入门文章,作者写得挺详细,看完以后 SVM 的基础就了解得差不多了,再然后买本支持向量机导论作者是 Nello Cristianini 和 John Shawe-Taylor,电子工业出版社的。然后把书本后面的那个 SMO 算法实现就基本上弄懂了 S

19、VM 是怎么一回事,最后再编写一个 SVM 库出来,比如说像 libsvm 等工具使用,呵呵,差不多就这样。这些是我学习 SVM 的整个过程,也算是经验吧。下面是 SVM 的简化版 SMO 算法,我将结合 Java 代码来解释一下整个 SVM 的学习训练过程,即所谓的 train 训练过程。那么什么是 SMO 算法呢?SMO 算法的目的无非是找出一个函数 f(x),这个函数能让我们把输入的数据 x 进行分类。既然是分类肯定需要一个评判的标准,比如分出来有两种情况 A 和 B,那么怎么样才能说 x是属于 A 类的,或不是 B 类的呢?就是需要有个边界,就好像两个国家一样有边界,如果边界越明显,则

20、就越容易区分,因此,我们的目标是最大化边界的宽度,使得非常容易的区分是 A 类还是 B 类。在 SVM 中,要最大化边界则需要最小化这个数值:w:是参量,值越大边界越明显 C 代表惩罚系数,即如果某个 x 是属于某一类,但是它偏离了该类,跑到边界上后者其他类的地方去了,C 越大表明越不想放弃这个点,边界就会缩小代表:松散变量但问题似乎还不好解,又因为 SVM 是一个凸二次规划问题,凸二次规划问题有最优解,于是问题转换成下列形式(KKT 条件):(1)这里的 ai 是拉格朗日乘子 (问题通过拉格朗日乘法数来求解)对于(a)的情况,表明 ai 是正常分类,在边界内部(我们知道正确分类的点 yi*f

21、(xi)=0)对于(b)的情况,表明了 ai 是支持向量,在边界上对于(c)的情况,表明了 ai 是在两条边界之间而最优解需要满足 KKT 条件,即满足( a) (b) (c)条件都满足以下几种情况出现将会出现不满足:yiui=1 但是 ai0 则是不满足的而原本 ai=0yiui=1 但是 ai=0 或者 ai=C 则表明不满足的,而原本应该是 0= 1 and alpha = 0 (正确分类) 36. * yi*f(i) = 1 and 0= 0 42. * 如果 ri 0 并且 alpha 0 则违反了 KKT 条件 45. * 因为原本 ri 0 对应的应该是 alpha =0 46.

22、 */ 47. if (yi * Ei tol 62. else 63. /如果边界上没有,就随便选一个 j != i 的 aj 64. j = RandomSelect(i); 65. 66. double Ej = getE(j); 67. 68. /保存当前的 ai 和 aj 69. double oldAi = ai; 70. double oldAj = aj; 71. 72. /* 73. * 计算乘子的范围 U, V 74. * 参考公式 (4) 75. */ 76. double L, H; 77. if (yi != yj) 78. L = Math.max(0, aj -

23、ai); 79. H = Math.min(C, C - ai + aj); 80. else 81. L = Math.max(0, ai + aj - C); 82. H = Math.min(0, ai + aj); 83. 84. 85. 86. /* 87. * 如果 eta 等于 0 或者大于 0 则表明 a 最优值应该在 L 或者 U 上 88. */ 89. double eta = 2 * k(i, j) - k(i, i) - k(j, j);/公式(3) 90. 91. if (eta = 0) 92. continue; 93. 94. aj = aj - yj * (

24、Ei - Ej)/ eta;/公式(2) 95. if (0 H) 101. aj = H; 102. 103. if (Math.abs(aj - oldAj) = 1 and alpha = 0 (正确分类)* yi*f(i) = 1 and 0= 0* 如果 ri 0 并且 alpha 0 则违反了 KKT 条件* 因为原本 ri 0 对应的应该是 alpha =0*/if (yi * Ei tol else /如果边界上没有,就随便选一个 j != i 的 ajj = RandomSelect(i);double Ej = getE(j);/保存当前的 ai 和 ajdouble ol

25、dAi = ai;double oldAj = aj;/* 计算乘子的范围 U, V* 参考公式(4)*/double L, H;if (yi != yj) L = Math.max(0, aj - ai);H = Math.min(C, C - ai + aj); else L = Math.max(0, ai + aj - C);H = Math.min(0, ai + aj);/* 如果 eta 等于 0 或者大于 0 则表明 a 最优值应该在 L 或者 U 上*/double eta = 2 * k(i, j) - k(i, i) - k(j, j);/公式(3)if (eta = 0

26、)continue;aj = aj - yj * (Ei - Ej)/ eta;/公式 (2)if (0 H) aj = H;if (Math.abs(aj - oldAj) 1e-5)continue;ai = ai + yi * yj * (oldAj - aj);if (0 ai /* 计算 b1, b2* 参照公式(6)*/double b1 = b - Ei - yi * (ai - oldAi) * k(i, i) - yj * (aj - oldAj) * k(i, j);double b2 = b - Ej - yi * (ai - oldAi) * k(i, j) - yj

27、* (aj - oldAj) * k(j, j);if (0 ai else if (0 aj else b = (b1 + b2) / 2;num_changed_alphas = num_changed_alphas + 1;if (num_changed_alphas = 0) passes+; else passes = 0;return new SVMModel(a, y, b);运行后的结果还算可以吧,测试数据主要是用了 libsvm 的 heart_scale 的数据。预测的正确率达到 73%以上。如果我把核函数从线性的改为基于 RBF 将会更好点。最后,说到 SVM 算法实现包,应该有很多,包括 svm light,libsvm,有 matlab 本身自带的svm 工具包等。另外,完整的代码,我将上传到 CSDN 下载地址上提供下载。点击这里下载。如理解有误敬请指正!谢谢!我的邮箱:chen-我的其他博客:百度:http:/ http:/ CSDN 博客,转载请标明出处:http:/

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 网络科技 > 数据结构与算法

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报