支持向量机(SVM)的实现
- 格式:doc
- 大小:580.50 KB
- 文档页数:24
实验报告实验名称:机器学习:线性支持向量机算法实现学员: 张麻子学号: *********** 培养类型:硕士年级:专业:所属学院:计算机学院指导教员:****** 职称:副教授实验室:实验日期:ﻬ一、实验目得与要求实验目得:验证SVM(支持向量机)机器学习算法学习情况要求:自主完成。
二、实验内容与原理支持向量机(Support Vector Machine,SVM)得基本模型就是在特征空间上找到最佳得分离超平面使得训练集上正负样本间隔最大。
SVM就是用来解决二分类问题得有监督学习算法。
通过引入了核方法之后SVM也可以用来解决非线性问题。
但本次实验只针对线性二分类问题。
SVM算法分割原则:最小间距最大化,即找距离分割超平面最近得有效点距离超平面距离与最大。
对于线性问题:假设存在超平面可最优分割样本集为两类,则样本集到超平面距离为:需压求取:由于该问题为对偶问题,可变换为:可用拉格朗日乘数法求解。
但由于本实验中得数据集不可以完美得分为两类,即存在躁点。
可引入正则化参数C,用来调节模型得复杂度与训练误差。
作出对应得拉格朗日乘式:对应得KKT条件为:故得出需求解得对偶问题:本次实验使用python编译器,编写程序,数据集共有270个案例,挑选其中70%作为训练数据,剩下30%作为测试数据。
进行了两个实验,一个就是取C值为1,直接进行SVM训练;另外一个就是利用交叉验证方法,求取在前面情况下得最优C值.三、实验器材实验环境:windows7操作系统+python编译器。
四、实验数据(关键源码附后)实验数据:来自UCI机器学习数据库,以Heart Disease数据集为例。
五、操作方法与实验步骤1、选取C=1,训练比例7:3,利用python库sklearn下得SVM()函数进行训练,后对测试集进行测试;2、选取训练比例7:3,C=np、linspace(0、0001,1,30)}。
利用交叉验证方法求出C值得最优解。
支持向量机(SVM)、支持向量机回归(SVR):原理简述及其MATLAB实例一、基础知识1、关于拉格朗日乘子法和KKT条件1)关于拉格朗日乘子法2)关于KKT条件2、范数1)向量的范数2)矩阵的范数3)L0、L1与L2范数、核范数二、SVM概述1、简介2、SVM算法原理1)线性支持向量机2)非线性支持向量机二、SVR:SVM的改进、解决回归拟合问题三、多分类的SVM1. one-against-all2. one-against-one四、QP(二次规划)求解五、SVM的MATLAB实现:Libsvm1、Libsvm工具箱使用说明2、重要函数:3、示例支持向量机(SVM):原理及其MATLAB实例一、基础知识1、关于拉格朗日乘子法和KKT条件1)关于拉格朗日乘子法首先来了解拉格朗日乘子法,为什么需要拉格朗日乘子法呢?记住,有需要拉格朗日乘子法的地方,必然是一个组合优化问题。
那么带约束的优化问题很好说,就比如说下面这个:这是一个带等式约束的优化问题,有目标值,有约束条件。
那么你可以想想,假设没有约束条件这个问题是怎么求解的呢?是不是直接 f 对各个 x 求导等于 0,解 x 就可以了,可以看到没有约束的话,求导为0,那么各个x均为0吧,这样f=0了,最小。
但是x都为0不满足约束条件呀,那么问题就来了。
有了约束不能直接求导,那么如果把约束去掉不就可以了吗?怎么去掉呢?这才需要拉格朗日方法。
既然是等式约束,那么我们把这个约束乘一个系数加到目标函数中去,这样就相当于既考虑了原目标函数,也考虑了约束条件。
现在这个优化目标函数就没有约束条件了吧,既然如此,求法就简单了,分别对x求导等于0,如下:把它在带到约束条件中去,可以看到,2个变量两个等式,可以求解,最终可以得到,这样再带回去求x就可以了。
那么一个带等式约束的优化问题就通过拉格朗日乘子法完美的解决了。
更高一层的,带有不等式的约束问题怎么办?那么就需要用更一般化的拉格朗日乘子法,即KKT条件,来解决这种问题了。
支持向量机的基本原理
支持向量机(Support Vector Machine, SVM)是一种二分类模型,其基本原理是找到一个最优的超平面来进行数据的划分。
其基本思想是将样本空间映射到高维特征空间,找到一个超平面使得正负样本之间的间隔最大化,从而实现分类。
具体来说,SVM的基本原理包括以下几个步骤:
1. 寻找最优超平面:将样本空间映射到高维特征空间,使得样本在特征空间中线性可分。
然后寻找一个超平面来最大化两个不同类别样本的间隔(也称为“分类间隔”)。
2. 构建优化问题:SVM通过解决一个凸二次规划问题来求解最优超平面。
该优化问题的目标是最大化分类间隔,同时限制样本的分类正确性。
3. 核函数技巧:在实际应用中,数据通常是非线性可分的。
通过引入核函数的技巧,可以将非线性问题转化为高维或无限维的线性问题。
常用的核函数有线性核、多项式核、高斯核等。
4. 寻找支持向量:在求解优化问题时,只有一部分样本点对于最优超平面的确定起到决定性作用,这些样本点被称为“支持向量”。
支持向量决定了超平面的位置。
5. 分类决策函数:在得到最优超平面后,可以通过计算样本点到超平面的距离来进行分类。
对于新的样本点,根据其距离超平面的远近来判断其所属类别。
支持向量机的基本原理可以简单概括为在高维特征空间中找到一个最优超平面,使得样本的分类间隔最大化。
通过引入核函数的技巧,SVM也可以处理非线性可分的问题。
支持向量机具有理论基础牢固、分类效果好等优点,在实际应用中得到了广泛的应用。
支持向量机算法的原理支持向量机(Support Vector Machine,SVM)是一种广泛应用于分类和回归问题的机器学习算法。
它的原理基于统计学习理论中的结构风险最小化原则,通过寻找一个最优的超平面来实现数据的分类。
在SVM中,数据被看作是高维空间中的点,每个点都有一个与之对应的特征向量。
这些特征向量的维度取决于特征的数量。
SVM的目标是找到一个超平面,使得其能够尽可能地将不同类别的数据点分隔开。
超平面是一个d维空间中的d-1维子空间,其中d为特征向量的维度。
在二维空间中,超平面即为一条直线,可以完全将两类数据点分开。
在更高维的空间中,超平面可以是一个曲面或者是一个超平面的组合。
为了找到最优的超平面,SVM引入了支持向量的概念。
支持向量是离超平面最近的数据点,它们决定了超平面的位置和方向。
通过最大化支持向量到超平面的距离,SVM能够找到一个最优的超平面,使得分类误差最小化。
SVM的核心思想是将低维空间中的数据映射到高维空间中,使得原本线性不可分的数据变得线性可分。
这一映射是通过核函数实现的。
核函数能够计算两个数据点在高维空间中的内积,从而避免了显式地进行高维空间的计算。
常用的核函数有线性核、多项式核和高斯核等。
SVM的训练过程可以简化为一个凸优化问题。
通过最小化结构风险函数,SVM能够找到一个最优的超平面,使得分类误差最小化。
结构风险函数由经验风险项和正则化项组成。
经验风险项衡量了分类器在训练集上的错误率,正则化项则防止过拟合。
SVM的优点是具有较好的泛化性能和较强的鲁棒性。
由于最大化支持向量到超平面的距离,SVM对异常值不敏感,能够有效地处理噪声数据。
此外,SVM还可以通过引入松弛变量来处理非线性可分的问题。
然而,SVM也存在一些限制。
首先,SVM对于大规模数据集的训练时间较长,且对内存消耗较大。
其次,选择合适的核函数和参数是一个挑战性的问题,不同的核函数和参数可能会导致不同的分类结果。
支持向量机回归代理模型python -回复什么是支持向量机回归代理模型,以及如何使用Python来实现该模型。
第一步:理解支持向量机回归代理模型支持向量机(Support Vector Machine,简称SVM)是一种常用的监督学习算法,可以用于分类和回归问题。
相比于其他机器学习算法,SVM在较小的数据集上也能表现出色。
在传统的SVM中,我们的目标是构建一个超平面,将不同类别的样本分开。
但在SVM回归中,我们的目标是找到一个函数,尽可能地拟合训练数据,并在超平面两侧保持一组边界。
支持向量机回归代理模型是一种近似SVM回归问题的算法。
它通过建立一个替代模型,然后在特征空间内寻找支持向量,来逼近真正的SVM回归解决方案。
这种代理模型通常会简化计算,并且在处理大规模数据集时表现出色。
第二步:使用Python实现支持向量机回归代理模型Python提供了许多机器学习库,包括用于支持向量机的库。
在这个示例中,我们将使用scikit-learn库来实现支持向量机回归代理模型。
首先,我们需要安装scikit-learn库。
在命令行中运行以下命令:pythonpip install -U scikit-learn安装完成后,我们可以开始编写Python代码。
导入必要的库和模块:pythonfrom sklearn import svmimport numpy as npimport matplotlib.pyplot as plt生成训练数据集:pythonX = np.sort(5 * np.random.rand(200, 1), axis=0)y = np.sin(X).ravel()y[::5] += 3 * (0.5 - np.random.rand(40))创建支持向量机回归代理模型(SVR)对象,并拟合数据:pythonsvr_rbf = svm.SVR(kernel='rbf', C=1e3, gamma=0.1) svr_lin = svm.SVR(kernel='linear', C=1e3)svr_poly = svm.SVR(kernel='poly', C=1e3, degree=2) svr_rbf.fit(X, y)svr_lin.fit(X, y)svr_poly.fit(X, y)预测并绘制结果:pythonX_test = np.arange(0.0, 5.0, 0.1)[:, np.newaxis]y_rbf = svr_rbf.predict(X_test)y_lin = svr_lin.predict(X_test)y_poly = svr_poly.predict(X_test)plt.scatter(X, y, color='darkorange', label='data')plt.plot(X_test, y_rbf, color='navy', lw=2, label='RBF model')plt.plot(X_test, y_lin, color='c', lw=2, label='Linear model')plt.plot(X_test, y_poly, color='cornflowerblue', lw=2,label='Polynomial model')plt.xlabel('data')plt.ylabel('target')plt.title('Support Vector Regression')plt.legend()plt.show()这段代码将生成一个简单的数据集,并使用不同的内核函数(高斯核、线性核和多项式核)构建支持向量机回归代理模型。
量子支持向量机代码的实现量子机器学习是量子计算运用于机器学习的一种新兴的计算模式,其是在量子计算机上实现机器学习算法的一种方法。
量子计算利用量子比特和量子幺正操作来处理信息,符合纠缠和测量原则,因此可以在一定程度上加快和优化传统机器学习算法的运算速度和效果。
支持向量机(SVM)是机器学习领域中常用的分类算法之一,其目标是找到一个最佳的决策面来将数据集划分成不同的类别。
在传统计算机上,实现SVM算法的代码并不复杂,但是在量子计算机上实现SVM算法的过程却要复杂许多。
量子支持向量机(Q-SVM)是一种在量子计算机上执行的支持向量机算法,其具有显著的计算优势。
Q-SVM算法能够快速、准确地进行特征映射,从而对数据进行分类。
在实现Q-SVM算法时,需要借助到一些量子算法和统计学的概念,比如量子模拟、量子傅里叶变换和最小二乘等。
因此,在实现Q-SVM算法时需要掌握这些基本概念。
在本文中,我们主要探讨如何实现量子支持向量机的代码。
在实现Q-SVM算法的过程中,主要分为三个步骤:初始化、分类和重构。
具体步骤如下:1. 初始化在初始化过程中,首先需要对输入的数据进行量子特征映射,将数据转换为量子比特。
在进行量子特征映射的过程中,可以借助于量子傅里叶变换等量子算法来实现。
2. 分类在分类过程中,需要利用到量子门的操作,通过对量子比特的幺正操作,将数据映射到不同的类别。
同时,也需要利用到特定的量子算法进行优化和加速。
3. 重构在分类完成后,需要将量子比特重新转换为经典比特,得到最终的分类结果。
在这个过程中,需要利用到最小二乘等概念和工具,以加快重构的速度。
总体来说,实现量子支持向量机算法的代码比较复杂,需要掌握一些量子算法和统计学的概念,并且需要在传统计算机的基础上进行一定的改进和优化。
对于初学者来说,可以先尝试实现传统支持向量机算法的代码,并逐步过渡到量子支持向量机算法的实现。
对于从事量子机器学习研究的专业人员来说,也可以借助量子计算机和量子编程平台进行快速实现和迭代。
利⽤R语⾔实现⽀持向量机(SVM)数据挖掘案例利⽤R语⾔实现⽀持向量机(SVM)数据挖掘案例建⽴模型svm()函数在建⽴⽀持向量机模型的时候有两种建⽴⽅式。
简单地说,⼀种是根据既定公式建⽴模型;⽽另外⼀种⽅式则是根据所给的数据模型建⽴模型。
根据函数的第⼀种使⽤格式,针对上述数据建模时,应该先确定所建⽴的模型所使⽤的数据,然后再确定所建⽴模型的结果变量和特征变来那个。
代码如下:library(e1071)data(iris)#建⽴svm模型model <- svm(Species~.,data = iris)在使⽤第⼀种格式建⽴模型时,如果使⽤数据中的全部特征变量作为模型特征变量时,可以简要地使⽤“Species~.”中的“.”代替全部的特征变量。
根据函数的第⼆种使⽤格式,在针对iris数据建⽴模型时,⾸先应该将结果变量和特征变量分别提取出来。
结果变量⽤⼀个向量表⽰,⽽特征向量⽤⼀个矩阵表⽰。
在确定好数据后还应根据数据分析所使⽤的核函数以及核函数所对应的参数值,通常默认使⽤⾼斯内积函数作为核函数,具体分析代码如下:#提取iris数据中除第5列以外的数据作为特征变量x <- iris[,-5]#提取iris数据中第5列数据作为结果变量y <- iris[,5]#建⽴svm模型model <- svm(x,y,kernel = "radial", gamma = if(is.vector(x)) 1 else 1/ncol(x))在使⽤第⼆种格式建⽴模型时,不需要特别强调所建⽴模型的哪个是,函数会⾃动将所有输⼊的特征变量数据作为建⽴模型所需要的特征变来那个。
在上述过程中,确定核函数的gamma系数时所使⽤的R语⾔所代表的意思为:如果特征向量是向量则gamma值取1,否则gamma值为特征向量个数的倒数。
结果分析summary(model)Call:svm.default(x = x, y = y, kernel = "radial", gamma = if (is.vector(x)) 1 else 1/ncol(x))Parameters:SVM-Type: C-classificationSVM-Kernel: radialcost: 1gamma: 0.25Number of Support Vectors: 51( 8 22 21 )Number of Classes: 3Levels:setosa versicolor virginica通过summary()函数可以得到关于模型的相关信息。
请简述 SVM(支持向量机)的原理以及如何处理非线性问题。
支持向量机(Support Vector Machine,SVM)是一种常用的机器学习算法,常用于分类和回归问题。
它的原理是基于统计学习理论和结构风险最小化原则,通过寻找最优超平面来实现分类。
SVM在处理非线性问题时,可以通过核函数的引入来将数据映射到高维空间,从而实现非线性分类。
一、SVM原理支持向量机是一种二分类模型,它的基本思想是在特征空间中找到一个超平面来将不同类别的样本分开。
具体而言,SVM通过寻找一个最优超平面来最大化样本间的间隔,并将样本分为两个不同类别。
1.1 线性可分情况在特征空间中,假设有两个不同类别的样本点,并且这两个类别可以被一个超平面完全分开。
这时候我们可以找到无数个满足条件的超平面,但我们要寻找具有最大间隔(Margin)的超平面。
Margin是指离超平面最近的训练样本点到该超平面之间距离之和。
我们要选择具有最大Margin值(即支持向量)对应的决策函数作为我们模型中使用。
1.2 线性不可分情况在实际问题中,很多情况下样本不是线性可分的,这时候我们需要引入松弛变量(Slack Variable)来处理这种情况。
松弛变量允许样本点处于超平面错误的一侧,通过引入惩罚项来平衡Margin和错误分类的数量。
通过引入松弛变量,我们可以将线性不可分问题转化为线性可分问题。
同时,为了防止过拟合现象的发生,我们可以在目标函数中加入正则化项。
1.3 目标函数在SVM中,目标函数是一个凸二次规划问题。
我们需要最小化目标函数,并找到最优解。
二、处理非线性问题SVM最初是用于处理线性可分或近似线性可分的数据集。
然而,在实际应用中,很多数据集是非线性的。
为了解决这个问题,SVM引入了核函数(Kernel Function)。
核函数可以将数据从低维空间映射到高维空间,在高维空间中找到一个超平面来实现非线性分类。
通过核技巧(Kernel Trick),SVM 可以在低维空间中计算高维空间中样本点之间的内积。
模式识别课程大作业报告——支持向量机(SVM)的实现:学号:专业:任课教师:研究生导师:容摘要支持向量机是一种十分经典的分类方法,它不仅是模式识别学科中的重要容,而且在图像处理领域中得到了广泛应用。
现在,很多图像检索、图像分类算法的实现都以支持向量机为基础。
本次大作业的容以开源计算机视觉库OpenCV 为基础,编程实现支持向量机分类器,并对标准数据集进行测试,分别计算出训练样本的识别率和测试样本的识别率。
本报告的组织结构主要分为3大部分。
第一部分简述了支持向量机的原理;第二部分介绍了如何利用OpenCV来实现支持向量机分类器;第三部分给出在标准数据集上的测试结果。
一、支持向量机原理概述在高维空间中的分类问题实际上是寻找一个超平面,将两类样本分开,这个超平面就叫做分类面。
两类样本中离分类面最近的样本到分类面的距离称为分类间隔。
最优超平面指的是分类间隔最大的超平面。
支持向量机实质上提供了一种利用最优超平面进行分类的方法。
由最优分类面可以确定两个与其平行的边界超平面。
通过拉格朗日法求解最优分类面,最终可以得出结论:实际决定最优分类面位置的只是那些离分类面最近的样本。
这些样本就被称为支持向量,它们可能只是训练样本中很少的一部分。
支持向量如图1所示。
图1图1中,H是最优分类面,H1和H2别是两个边界超平面。
实心样本就是支持向量。
由于最优超平面完全是由这些支持向量决定的,所以这种方法被称作支持向量机(SVM)。
以上是线性可分的情况,对于线性不可分问题,可以在错分样本上增加一个惩罚因子来干预最优分类面的确定。
这样一来,最优分类面不仅由离分类面最近的样本决定,还要由错分的样本决定。
这种情况下的支持向量就由两部分组成:一部分是边界支持向量;另一部分是错分支持向量。
对于非线性的分类问题,可以通过特征变换将非线性问题转化为新空间中的线性问题。
但是这样做的代价是会造成样本维数增加,进而导致计算量急剧增加,这就是所谓的“维度灾难”。
为了避免高维空间中的计算,可以引入核函数的概念。
这样一来,无论变换后空间的维数有多高,这个新空间中的线性支持向量机求解都可以在原空间通过核函数来进行。
常用的核函数有多项式核、高斯核(径向基核)、Sigmoid函数。
二、支持向量机的实现OpenCV是开源计算机视觉库,它在图像处理领域得到了广泛应用。
OpenCV中包含许多计算机视觉领域的经典算法,其中的机器学习代码部分就包含支持向量机的相关容。
OpenCV中比较经典的机器学习示例是“手写字母分类”。
OpenCV中给出了用支持向量机实现该示例的代码。
本次大作业的任务是研究OpenCV中的支持向量机代码,然后将其改写为适用于所有数据库的通用程序,并用标准数据集对算法进行测试。
本实验中使用的OpenCV版本是2.4.4,实验平台为Visual Studio 2010软件平台。
OpenCV读取的输入数据格式为“.data”文件。
该文件记录了所有数据样本的特征向量和标签。
OpenCV自带的“letter-recognition”数据集是手写字母数据集。
其中共包含20000个样本,前16000个用来训练,后4000个用来测试。
样本是16维的特征向量。
每条样本在文件中按行存放。
每行共有17个字段,第1个字段是样本的标签,以字符形式给出;后面16个字段分别是样本的16个特征,以数字形式给出。
所有字段之间均以逗号分隔。
图2图2中展示了“.data”文件中样本的存储样式。
自行生成“.data”文件的过程十分简单。
只需要新建一个“.txt”文件,对其容进行修改之后,直接把后缀改为“.data”即可。
在OpenCV给出的支持向量机示例程序中,可调参数大约有十多个,这些参数的调整比较复杂。
为了方便使用该程序,可以将其中重要的参数从程序段中挑选出来,并制作宏定义。
这些重要参数包括:总样本个数、用于训练的样本个数(总样本个数-训练样本个数=测试样本个数)、特征向量的维数、选取的核函数类型。
可调参数如图3所示:图3在更换新的数据集时,只需要在宏定义部分修改“PATH”后的路径即可,其他参数的修改也都在这里进行,无需再到代码段进行修改。
其中,宏定义“KERNEL”用来确定SVM采用何种核函数。
执行程序后,可以显示出训练样本和测试样本的识别率。
通过将程序中分类数组的值输出,还可以在原有程序基础上添加显示测试样本标签的功能。
对“letter-recognition”数据集进行分类得到的结果如图4所示:图4图4展示了4000个测试样本标签和训练样本识别率以及测试样本识别率。
可以观察到训练样本的识别率为64.36%,测试样本的识别率为60.75%。
将图4中展示的测试样本标签与“.data”文件中的标签对比,可以直观地观察到哪个数据判断错误。
图5展示了程序输出的测试样本标签与“.data”文件中标签的对应关系。
(a) (b)图5观察图5可以发现,第一行字母P的识别是正确的,而第三行的预测出现了错误。
样本集中的数据为“O”,但支持向量机将其错分为“B”。
按上述方法可以一一对照测试样本的预测结果是否正确。
接下来,采用其他核函数进行分类。
图6展示的是径向基函数的分类效果。
图6观察图6可以看出,采用径向基函数可以获得极高的样本识别率,可达100%。
但是测试样本的识别率为51.25%,比起线性基函数有所下降,说明其泛化能力(即推广能力)有限。
测试表明,对于“letter-recognition”,采用多项式基函数和Sigmoid基函数分类的识别率更低,因此对此数据集的分类应该采用线性核函数。
三、标准数据集测试前一部分展示了OpenCV自带的“letter-recognition”数据集的测试效果。
为了测试编写的程序的通用性,接下来对其他标准数据集进行测试。
数据集可以从“/ml/”下载,这个网址上提供了上万个用于机器学习的数据集。
接下来分别展示“iris”数据集和“wine”数据集上的测试结果。
(1)“iris”数据集“iris”数据集是鸢尾花数据集。
其中共包含150个样本,每个样本是一个4维的特征向量,这4个特征分别是萼片长度、萼片宽度、花瓣长度和花瓣宽度。
数据的标签总共有三类:“S”代表刺芒野古草,“E”代表杂色鸢尾花,“I”代表维尔吉尼卡。
它们分别是三种不同的鸢尾花品种。
该数据集如图7所示:图7在本实验中,用前130个数据作为训练样本,后20个数据作为测试样本。
选定相应的参数如图8所示:图8图8中,选取核函数为线性核函数。
按照图8所示的参数执行程序,得到的结果如图9所示:图9由图9可知,对于“iris”数据集,训练样本的识别率为98.46%,测试样本的识别率为90.00%。
由数据可以看出,支持向量机对“iris”数据集的分类效果显然要优于“letter-recognition”数据集。
这可能和数据集本身有关,“iris”数据集特征的可分性更好。
接下来,变换核函数来观察分类效果。
图10是采用径向基核函数得到的结果。
图10图10中,训练样本的识别率比采用线性核函数时略有提升,但测试样本的识别率没有变化,因此可以认为采用径向基核函数与线性核函数的分类效果是基本相同的。
当采用Sigmoid函数进行分类时,分类效果显然要差很多。
该分类效果如图11所示。
图11图11中,训练样本和测试样本的识别率都很低,因此“iris”数据集显然不适合用Sigmoid函数进行分类。
以上实验结果表明,核函数的选取对于支持向量机的分类效果有至关重要的影响。
(2)“wine”数据集“wine”数据集是红酒数据集。
其中共包含178个样本,每个样本是一个13维的特征向量,其中包含酒精度、年份等特征。
数据的标签总共有三类:“M”、“H”、“L”。
它们分别代表三类不同的红酒。
该数据集如图12所示:图12本实验用前125个数据作为训练样本,后53个数据作为测试样本。
选定相应的参数如图13所示:2图13图13中,核函数选定为线性核函数。
按照上述参数设置执行程序,得到的结果如图14所示:图14由图14可得,对于“wine”数据集,训练样本的识别率为88.00%,测试样本的识别率为37.74%。
训练样本的识别率较高,但测试样本的识别率却较低。
这说明该学习过程的泛化能力较差。
这可能由于样本数量有限,支持向量机方法很难从这么有限的样本中训练出较为理想的分类器。
接下来,尝试采用其他核函数的分类效果。
结果发现,其他和函数的分类效果并没有线性核函数的分类效果好。
当采用径向基核函数时,训练样本的识别率可达100%,但测试样本的识别率变得非常低。
该结果如图15所示。
图15可见,对于“wine”数据集来讲,采用径向基核函数虽然能使训练样本识别率最高,但其泛化能力最差,因此对解决实际问题没有任何帮助。
综合比较上述结果,可以发现径向基函数在大多数情况下都可以获得较高的训练样本识别率,即经验风险很小。
但是,测试样本的识别率无法保证,对于某些数据集的泛化能力有限。
致今后,我会从事机器学习方向的研究。
模式识别课程的容对我的专业方向有很大帮助,令我受益匪浅。
尤其是在本次大作业过程中,支持向量机的编程实现工作大大加深了我对支持向量机原理的理解,为我今后的研究工作打下了坚实基础。
模式识别课程的学习是我研究道路上的一个良好开端,具有十分重要的意义。
本学期的模式识别课程令我受益颇多。
在此,诚挚地感建更老师的辛勤付出!附录:源程序代码#include "opencv2/core/core_c.h"#include "opencv2/ml/ml.hpp"#include <cstdio>#include <vector>/*******************设置文件路径********************/ #define PATH "./letter-recognition.data"/*******************设置样本个数********************/ #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 buf[M+2];float* el_ptr;CvSeqReader reader;int i, j;if( !f )return 0;el_ptr = new float[var_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_ptr[0] = buf[0];ptr = buf+2;for( i = 1; i <= var_count; i++ )int n = 0;sscanf( ptr, "%f%n", el_ptr + i, &n );ptr += n + 1;}if( i <= var_count )break;cvSeqPush( seq, el_ptr );}fclose(f);*data = cvCreateMat( seq->total, var_count, CV_32F ); *responses = cvCreateMat( seq->total, 1, CV_32F );cvStartReadSeq( seq, &reader );for( i = 0; i < seq->total; i++ ){const float* sdata = (float*)reader.ptr + 1;float* ddata = data[0]->data.fl + var_count*i;float* dr = responses[0]->data.fl + i;for( j = 0; j < var_count; j++ )ddata[j] = sdata[j];*dr = sdata[-1];CV_NEXT_SEQ_ELEM( seq->elem_size, reader );}cvReleaseMemStorage( &storage );delete[] el_ptr;}/*********************支持向量机分类器*************************/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, &data, &responses );if( !ok ){printf( "无法读取数据库%s\n", data_filename );return -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, &train_data, 0, ntrain_samples );CvMat* train_resp = cvCreateMat( ntrain_samples, 1, CV_32FC1);for (int i = 0; i < ntrain_samples; i++)train_resp->data.fl[i] = responses->data.fl[i];svm.train(&train_data, train_resp, 0, 0, param);/**************************开始对测试样本分类***************************/ std::vector<float> _sample(var_count * (nsamples_all));CvMat sample = cvMat( nsamples_all , VECTOR, CV_32FC1, &_sample[0] );std::vector<float> true_results(nsamples_all );for (int j = 0; j < nsamples_all; j++){float *s = data->data.fl + j * var_count;for (int i = 0; i < var_count; i++){sample.data.fl[(j) * var_count + i] = s[i];}true_results[j] = responses->data.fl[j];}CvMat *result = cvCreateMat(1, nsamples_all, CV_32FC1);printf("分类中...\n");svm.predict(&sample, result);/**************************显示测试样本的标签**************************/printf("测试样本的标签预测结果如下:\n");for (int i = ntrain_samples; i < nsamples_all ; i++){printf("测试样本%d=%c\n",i-ntrain_samples+1,char(result->data.fl[i]));}/**************************计算识别率**************************/ printf("/****显示识别率****/\n");//训练样本识别率int true_resp = 0;for (int i = 0; i < ntrain_samples; i++){if (result->data.fl[i] == true_results[i])true_resp++;}printf("训练样本识别率= %.2f%%\n", (float)true_resp / (ntrain_samples) * 100);//测试样本识别率true_resp = 0;for (int i = ntrain_samples; i < nsamples_all; i++){if (result->data.fl[i] == true_results[i])true_resp++;}printf("测试样本识别率= %.2f%%\n", (float)true_resp / (nsamples_all-ntrain_samples) * 100);cvReleaseMat( &train_resp );cvReleaseMat( &result );cvReleaseMat( &data );cvReleaseMat( &responses );return 0;}int main( 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(argv[i],"-data") == 0 ){i++;data_filename = argv[i];}else if( strcmp(argv[i],"-save") == 0 ){i++;filename_to_save = argv[i];}else if( strcmp(argv[i],"-load") == 0){i++;filename_to_load = argv[i];}elsebreak;}build_svm_classifier( data_filename );return 0;}。