收藏 分享(赏)

支持向量机(SVM)的实现.doc

上传人:精品资料 文档编号:10717904 上传时间:2019-12-31 格式:DOC 页数:20 大小:535.06KB
下载 相关 举报
支持向量机(SVM)的实现.doc_第1页
第1页 / 共20页
支持向量机(SVM)的实现.doc_第2页
第2页 / 共20页
支持向量机(SVM)的实现.doc_第3页
第3页 / 共20页
支持向量机(SVM)的实现.doc_第4页
第4页 / 共20页
支持向量机(SVM)的实现.doc_第5页
第5页 / 共20页
点击查看更多>>
资源描述

1、模式识别课程大作业报告支持向量机(SVM)的实现姓名: 学号:专业: 任课教师: 研究生导师: 内容摘要支持向量机是一种十分经典的分类方法,它不仅是模式识别学科中的重要内容,而且在图像处理领域中得到了广泛应用。现在,很多图像检索、图像分类算法的实现都以支持向量机为基础。本次大作业的内容以开源计算机视觉库OpenCV 为基础,编程实现支持向量机分类器,并对标准数据集进行测试,分别计算出训练样本的识别率和测试样本的识别率。本报告的组织结构主要分为 3 大部分。第一部分简述了支持向量机的原理;第二部分介绍了如何利用 OpenCV 来实现支持向量机分类器;第三部分给出在标准数据集上的测试结果。一、支持

2、向量机原理概述在高维空间中的分类问题实际上是寻找一个超平面,将两类样本分开,这个超平面就叫做分类面。两类样本中离分类面最近的样本到分类面的距离称为分类间隔。最优超平面指的是分类间隔最大的超平面。支持向量机实质上提供了一种利用最优超平面进行分类的方法。由最优分类面可以确定两个与其平行的边界超平面。通过拉格朗日法求解最优分类面,最终可以得出结论:实际决定最优分类面位置的只是那些离分类面最近的样本。这些样本就被称为支持向量,它们可能只是训练样本中很少的一部分。支持向量如图 1 所示。图 1图 1 中,H 是最优分类面,H1 和 H2 别是两个边界超平面。实心样本就是支持向量。由于最优超平面完全是由这

3、些支持向量决定的,所以这种方法被称作支持向量机(SVM) 。以上是线性可分的情况,对于线性不可分问题,可以在错分样本上增加一个惩罚因子来干预最优分类面的确定。这样一来,最优分类面不仅由离分类面最近的样本决定,还要由错分的样本决定。这种情况下的支持向量就由两部分组成:一部分是边界支持向量;另一部分是错分支持向量。对于非线性的分类问题,可以通过特征变换将非线性问题转化为新空间中的线性问题。但是这样做的代价是会造成样本维数增加,进而导致计算量急剧增加,这就是所谓的“维度灾难” 。为了避免高维空间中的计算,可以引入核函数的概念。这样一来,无论变换后空间的维数有多高,这个新空间中的线性支持向量机求解都可

4、以在原空间通过核函数来进行。常用的核函数有多项式核、高斯核(径向基核) 、Sigmoid 函数。二、支持向量机的实现OpenCV 是开源计算机视觉库,它在图像处理领域得到了广泛应用。OpenCV 中包含许多计算机视觉领域的经典算法,其中的机器学习代码部分就包含支持向量机的相关内容。OpenCV 中比较经典的机器学习示例是“手写字母分类” 。OpenCV 中给出了用支持向量机实现该示例的代码。本次大作业的任务是研究 OpenCV 中的支持向量机代码,然后将其改写为适用于所有数据库的通用程序,并用标准数据集对算法进行测试。本实验中使用的 OpenCV 版本是2.4.4,实验平台为 Visual S

5、tudio 2010 软件平台。OpenCV 读取的输入数据格式为“.data ”文件。该文件记录了所有数据样本的特征向量和标签。OpenCV 自带的“letter-recognition ”数据集是手写字母数据集。其中共包含 20000 个样本,前 16000 个用来训练,后 4000 个用来测试。样本是 16 维的特征向量。每条样本在文件中按行存放。每行共有 17 个字段,第 1 个字段是样本的标签,以字符形式给出;后面 16 个字段分别是样本的 16个特征,以数字形式给出。所有字段之间均以逗号分隔。图 2图 2 中展示了“.data”文件中样本的存储样式。自行生成“.data”文件的过程

6、十分简单。只需要新建一个“.txt”文件,对其内容进行修改之后,直接把后缀改为“.data”即可。在 OpenCV 给出的支持向量机示例程序中,可调参数大约有十多个,这些参数的调整比较复杂。为了方便使用该程序,可以将其中重要的参数从程序段中挑选出来,并制作宏定义。这些重要参数包括:总样本个数、用于训练的样本个数(总样本个数-训练样本个数=测试样本个数) 、特征向量的维数、选取的核函数类型。可调参数如图 3 所示:图 3 在更换新的数据集时,只需要在宏定义部分修改“PATH”后的路径即可,其他参数的修改也都在这里进行,无需再到代码段内进行修改。其中,宏定义“KERNEL”用来确定 SVM 采用何

7、种核函数。执行程序后,可以显示出训练样本和测试样本的识别率。通过将程序中分类数组的值输出,还可以在原有程序基础上添加显示测试样本标签的功能。对“letter-recognition”数据集进行分类得到的结果如图 4 所示:图 4 图 4 展示了 4000 个测试样本标签和训练样本识别率以及测试样本识别率。可以观察到训练样本的识别率为 64.36%,测试样本的识别率为 60.75%。将图 4 中展示的测试样本标签与“.data”文件中的标签对比,可以直观地观察到哪个数据判断错误。图 5 展示了程序输出的测试样本标签与“.data”文件中标签的对应关系。(a) (b) 图 5 观察图 5 可以发现

8、,第一行字母 P 的识别是正确的,而第三行的预测出现了错误。样本集中的数据为“O” ,但支持向量机将其错分为 “B”。按上述方法可以一一对照测试样本的预测结果是否正确。接下来,采用其他核函数进行分类。图 6 展示的是径向基函数的分类效果。图 6观察图 6 可以看出,采用径向基函数可以获得极高的样本识别率,可达 100%。但是测试样本的识别率为 51.25%,比起线性基函数有所下降,说明其泛化能力(即推广能力)有限。测试表明,对于“letter-recognition” ,采用多项式基函数和 Sigmoid 基函数分类的识别率更低,因此对此数据集的分类应该采用线性核函数。三、标准数据集测试前一部

9、分展示了 OpenCV 自带的“letter-recognition ”数据集的测试效果。为了测试编写的程序的通用性,接下来对其他标准数据集进行测试。数据集可以从“http:/archive.ics.uci.edu/ml/”下载,这个网址上提供了上万个用于机器学习的数据集。接下来分别展示“iris”数据集和“wine”数据集上的测试结果。(1) “iris”数据集“iris”数据集是鸢尾花数据集。其中共包含 150 个样本,每个样本是一个4 维的特征向量,这 4 个特征分别是萼片长度、萼片宽度、花瓣长度和花瓣宽度。数据的标签总共有三类:“S”代表刺芒野古草, “E”代表杂色鸢尾花,“I”代表维

10、尔吉尼卡。它们分别是三种不同的鸢尾花品种。该数据集如图 7 所示:图 7 在本实验中,用前 130 个数据作为训练样本,后 20 个数据作为测试样本。选定相应的参数如图 8 所示:图 8 图 8 中,选取核函数为线性核函数。按照图 8 所示的参数执行程序,得到的结果如图 9 所示:图 9 由图 9 可知,对于“iris”数据集,训练样本的识别率为 98.46%,测试样本的识别率为 90.00%。由数据可以看出,支持向量机对“iris ”数据集的分类效果显然要优于“letter-recognition”数据集。这可能和数据集本身有关, “iris”数据集特征的可分性更好。接下来,变换核函数来观察

11、分类效果。图 10 是采用径向基核函数得到的结果。图 10图 10 中,训练样本的识别率比采用线性核函数时略有提升,但测试样本的识别率没有变化,因此可以认为采用径向基核函数与线性核函数的分类效果是基本相同的。当采用 Sigmoid 函数进行分类时,分类效果显然要差很多。该分类效果如图 11 所示。图 11图 11 中,训练样本和测试样本的识别率都很低,因此“iris ”数据集显然不适合用 Sigmoid 函数进行分类。以上实验结果表明,核函数的选取对于支持向量机的分类效果有至关重要的影响。(2) “wine”数据集“wine”数据集是红酒数据集。其中共包含 178 个样本,每个样本是一个13

12、维的特征向量,其中包含酒精度、年份等特征。数据的标签总共有三类:“M”、 “H”、 “L”。它们分别代表三类不同的红酒。该数据集如图 12 所示:图 12本实验用前 125 个数据作为训练样本,后 53 个数据作为测试样本。选定相应的参数如图 13 所示:2图 13图 13 中,核函数选定为线性核函数。按照上述参数设置执行程序,得到的结果如图 14 所示:图 14由图 14 可得,对于“wine”数据集,训练样本的识别率为 88.00%,测试样本的识别率为 37.74%。训练样本的识别率较高,但测试样本的识别率却较低。这说明该学习过程的泛化能力较差。这可能由于样本数量有限,支持向量机方法很难从

13、这么有限的样本中训练出较为理想的分类器。接下来,尝试采用其他核函数的分类效果。结果发现,其他和函数的分类效果并没有线性核函数的分类效果好。当采用径向基核函数时,训练样本的识别率可达 100%,但测试样本的识别率变得非常低。该结果如图 15 所示。图 15可见,对于“wine ”数据集来讲,采用径向基核函数虽然能使训练样本识别率最高,但其泛化能力最差,因此对解决实际问题没有任何帮助。综合比较上述结果,可以发现径向基函数在大多数情况下都可以获得较高的训练样本识别率,即经验风险很小。但是,测试样本的识别率无法保证,对于某些数据集的泛化能力有限。致 谢今后,我会从事机器学习方向的研究。模式识别课程的内

14、容对我的专业方向有很大帮助,令我受益匪浅。尤其是在本次大作业过程中,支持向量机的编程实现工作大大加深了我对支持向量机原理的理解,为我今后的研究工作打下了坚实基础。模式识别课程的学习是我研究道路上的一个良好开端,具有十分重要的意义。本学期的模式识别课程令我受益颇多。在此,诚挚地感谢李建更老师的辛勤付出!附录:源程序代码#include “opencv2/core/core_c.h“#include “opencv2/ml/ml.hpp“#include #include /*设置文件路径 */#define PATH “./letter-recognition.data“/*设置样本个数 */#

15、define SAMPLE 20000/*设置训练样本个数 */#define TRAIN 16000/*设置特征向量维数 */#define VECTOR 16/*/*读取数据 */static intread_num_class_data( const char* filename, int var_count,CvMat* data, CvMat* responses )const int M = 1024;FILE* f = fopen( filename, “rt“ );CvMemStorage* storage;CvSeq* seq;char bufM+2;float* el_pt

16、r;CvSeqReader reader;int i, j;if( !f )return 0;el_ptr = new floatvar_count+1;storage = cvCreateMemStorage();seq = cvCreateSeq( 0, sizeof(*seq), (var_count+1)*sizeof(float), storage );for(;)char* ptr;if( !fgets( buf, M, f ) | !strchr( buf, , ) )break;el_ptr0 = buf0;ptr = buf+2;for( i = 1; i total, va

17、r_count, CV_32F );*responses = cvCreateMat( seq-total, 1, CV_32F );cvStartReadSeq( seq, for( i = 0; i total; i+ )const float* sdata = (float*)reader.ptr + 1;float* ddata = data0-data.fl + var_count*i;float* dr = responses0-data.fl + i;for( j = 0; j elem_size, reader );cvReleaseMemStorage( delete el_

18、ptr;return 1;/*支持向量机分类器 */staticint build_svm_classifier( char* data_filename )CvMat* data = 0;CvMat* responses = 0;CvMat train_data;int nsamples_all = 0, ntrain_samples = 0;int var_count;CvSVM svm;int ok = read_num_class_data( data_filename, VECTOR, if( !ok )printf( “无法读取数据库 %sn“, data_filename );r

19、eturn -1;/* SVM 参数 */CvSVMParams param;param.kernel_type=CvSVM:LINEAR;param.svm_type=CvSVM:C_SVC;param.C=1;/*/printf( “数据库 %s 已经被加载n“, data_filename );nsamples_all = SAMPLE;ntrain_samples = TRAIN;var_count = data-cols;/*训练分类器*/printf( “正在训练 SVM 分类器.n“);cvGetRows( data, CvMat* train_resp = cvCreateMa

20、t( ntrain_samples, 1, CV_32FC1);for (int i = 0; i data.fli = responses-data.fli;svm.train(/*开始对测试样本分类*/std:vector _sample(var_count * (nsamples_all);CvMat sample = cvMat( nsamples_all , VECTOR, CV_32FC1, std:vector true_results(nsamples_all );for (int j = 0; j data.fl + j * var_count;for (int i = 0;

21、 i data.flj;CvMat *result = cvCreateMat(1, nsamples_all, CV_32FC1);printf(“分类中.n“);svm.predict(/*显示测试样本的标签*/printf(“测试样本的标签预测结果如下:n“);for (int i = ntrain_samples; i data.fli);/*计算识别率*/printf(“/*显示识别率*/n“);/训练样本识别率int true_resp = 0;for (int i = 0; i data.fli = true_resultsi)true_resp+;printf(“训练样本识别率

22、 = %.2f%n“, (float)true_resp / (ntrain_samples) * 100);/测试样本识别率true_resp = 0;for (int i = ntrain_samples; i data.fli = true_resultsi)true_resp+;printf(“测试样本识别率 = %.2f%n“, (float)true_resp / (nsamples_all-ntrain_samples) * 100);cvReleaseMat( cvReleaseMat( cvReleaseMat( cvReleaseMat( return 0;int main

23、( int argc, char *argv )char* filename_to_save = 0;char* filename_to_load = 0;char default_data_filename = PATH;char* data_filename = default_data_filename;int i;for( i = 1; i argc; i+ )if( strcmp(argvi,“-data“) = 0 )i+;data_filename = argvi;else if( strcmp(argvi,“-save“) = 0 )i+;filename_to_save = argvi;else if( strcmp(argvi,“-load“) = 0)i+;filename_to_load = argvi;elsebreak;build_svm_classifier( data_filename );return 0;

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

当前位置:首页 > 企业管理 > 管理学资料

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


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

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

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