使用支持向量机(SVM) 算法进行分类
1 支持向量机(SVM)的基本概念
SVM是一种分类算法,其侧重于模式识别方面。使用SVM可以大大提高分类的准确性。
分类相当于模式识别的子集合,模式识别重点在于对已知数据进行特征发现与提取。
SVM重点在于解决线性可分的问题。但很多时候,实际的问题是线性不可分的。SVM的思想就是将线性不可分的问题转化线性可分的问题。那么如何来是实现呢?就是将空间映射到多维空间。如把二维空间映射到三维空间。以增加维数来减少方程的次数。
比如,在二维空间中,不得不用 f(x)=ax2+b+c 这个曲线将两类样本分开,而不是用一条直线将它们分开,这样就是一个线性不可分的问题。为了解决这个问题,我们可以使用换元法将即 x^2=y1 , x=y2 , 这样一来替换为 z=a'y1+b'y2+c' 这个线性方程,从而转换到了高维空间,代价是维度的增加引入了更多的变量。这样我们就完成了从线性不可分问题到线性可分问题的转换。
所谓支持向量,即在每一类样本集中,过离separating hyper plane 最近的样本做一个与separating hyper plane 平行的线/超平面。有几个分类,就有几个这种直线/超平面,这样的直线/超平面就叫做支持向量(Support Vector)。
2 核函数
那么找到一个线/超平面来完成二分类成为问题的关键。这个线/超平面的函数被我们成为“核函数”。常见的核函数有:
- 线性核函数————linear
- 多项式核函数————poly
- 径向基核函数————rbf(用得较多)
- Sigmoid核函数————sigmoid
那么如何来选择合适的核函数呢?答案就是比较不同核函数的分类的准确率。在实际处理分类问题时,分别计算几种核函数的分类性能,将准确率最高的核函数作为最终用于预测分类的核函数即可。在本文的例子中,我们使用画图的方式来判断分类性能的好坏。
使用模型不同,转换的方式不同,在多维空间中的图形就不同,分类的效果就不同。
网上关于SVM、线性可不可分、核函数的博文很多,如http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html 。这里就不再赘述。
3 比较分类效果与子图的划分
为了比较不同分类器的准确性,我们采用绘制散点图,然后人工观察来判断。我们将两个类的点在坐标系中用不同颜色表示出来,同时标出训练数据,看预测点与训练点的在图中的重叠情况。重叠越紧密,说明分类的效果越准确。
在绘图的时候,我们希望在一个平面中同时展现多幅图片,这时使用matplotlib模块的子图(subplot)来展现。
subplot的参数
subplot(横向划分个数,纵向划分个数,当前定位)
第一个参数代表的是横向要划分的子图个数,第二个参数代表的是纵向要划分的子图的个数,第三个参数表示当前的定位。
使用示例一:
使用示例二:
使用示例三:
4 源码
应用场景
假设在第一象限有10个点,它们分别是[0, 0], [1, 1], ... , [9, 9]。它们[0,0],[1,1],[2,2],[3,3]属于“0”这个类(类标签为0),另外6个点属于“1”这个类(类标签为1)。
现在第一象限构造900*900个点,纵横坐标方向上相邻的点距离为0.01。
[ 0.00, 0.00],[ 0.01, 0.00], [ 0.02, 0.00],..., [ 8.97, 8.99], [ 8.98, 8.99],[ 8.99, 8.99]
这样,布满区间的点作为预测数据,用各种分类模型进行二分类。最后通过绘图模块给不同类的点上色以判断分类性能。
import numpy as npy
import matplotlib.pyplot as plt
from sklearn import svm
x=[]#存储样本数据
y=[]#存储类标号
for i in range(0,10):#构造10个点作为训练数据
if(i<=3):#if(i<=3 or i>=8):
x.append([i,i])
y.append(0)
else:
x.append([i,i])
y.append(1)
train_x=npy.array(x)#转换为数组
train_y=npy.array(y)
'''
创建svm分类器的格式:
svm.SVC(kernel=某个核函数).fit(训练样本,类标签)
'''
#linear
linear_svc=svm.SVC(kernel="linear").fit(train_x,train_y)
#poly 要定义维度,degree决定了多项式的最高次幂.关于SVC参数的意义请参见文章后头的内容。
poly_svc=svm.SVC(kernel="poly",degree=4).fit(train_x,train_y)
#径向基核函数(这时SVC默认的核函数)
rbf_svc=svm.SVC().fit(train_x,y)
#Sigmoid
sigmoid_svc=svm.SVC(kernel="sigmoid").fit(train_x,train_y)
#下面就可以进行预测了
x1,x2=npy.meshgrid(npy.arange(train_x[:,0].min(),train_x[:,0].max(),0.01),npy.arange(train_x[:,1].min(),train_x[:,1].max(),0.01))
#先生成各个点。定义最小值和最大值后,定义隔多少值建立一个点。
#npy.arange(train_x[:,1].min(),train_x[:,1].max(),0.01))返回的是900个元素的数组
#meshgrid函数用来产生矩阵。上面的语句也是就是numpy.meshgrid(numpy.arange(0,9,0.01),numpy.arange(0,9,0.01))
'''
x1是矩阵
[[ 0. , 0.01, 0.02, ..., 8.97, 8.98, 8.99],
[ 0. , 0.01, 0.02, ..., 8.97, 8.98, 8.99],
[ 0. , 0.01, 0.02, ..., 8.97, 8.98, 8.99],
...,
[ 0. , 0.01, 0.02, ..., 8.97, 8.98, 8.99],
[ 0. , 0.01, 0.02, ..., 8.97, 8.98, 8.99],
[ 0. , 0.01, 0.02, ..., 8.97, 8.98, 8.99]]
x2是矩阵
[[ 0. , 0. , 0. , ..., 0. , 0. , 0. ],
[ 0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01],
[ 0.02, 0.02, 0.02, ..., 0.02, 0.02, 0.02],
...,
[ 8.97, 8.97, 8.97, ..., 8.97, 8.97, 8.97],
[ 8.98, 8.98, 8.98, ..., 8.98, 8.98, 8.98],
[ 8.99, 8.99, 8.99, ..., 8.99, 8.99, 8.99]]
'''
splocation=1
for i in [linear_svc,poly_svc,rbf_svc,sigmoid_svc]:#遍历各个模型以便绘图,以看哪个核函数的准确率更高
rst = i.predict(npy.c_[x1.ravel(),x2.ravel()])#横坐标和纵坐标的组合。x1.ravel()和x2.ravel()都是长度为810000的数组。c_[]用来将前后两个数组串联成一个810000行、2列的矩阵。
#因为上面用到了四种分类模型,那么一个2×2的图就能够显示完全了。
plt.subplot(2,2,splocation)#第一个参数代表的是横向要划分的子图个数,第二个参数代表的是纵向要划分的子图的个数,第三个参数表示当前的定位
plt.contourf(x1,x2,rst.reshape(x1.shape))#contourf用来填充颜色。(当前横坐标,当前纵坐标,预测的分类结果(转为x1的规模维数))
#训练数据的点也绘制出来
for j in range(0,len(y)):
if(int(y[j])==0):
plt.plot(train_x[j:j+1,0],train_x[j:j+1],"yo")#y代表黄色,o代表散点图
else:
plt.plot(train_x[j:j+1,0],train_x[j:j+1],"ko")#类别为1填充为黑色。k代表黑色
splocation+=1
plt.show()
运行结果:
可见,在这种分布的情况下,前三种分类模型的性能无异。让我们改一下训练数据的类型分布。if(i<=3 or i>=8):我们把[0,0],[1,1],[2,2],[3,3],[8,8],[9,9]当作“0”这个类,将[4,4],[5,5],[6,6],[7,7]作为“1”这个类,在进行一下预测。结果如下图所示:
可见,在比较这种分布下,径向基核函数表现出更好的分类性能。
5 SVC的参数
具体参数的意义与使用请参见链接:http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html
- C:目标函数的惩罚系数C,用来平衡分类间隔margin和错分样本的,default C = 1.0;
C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。
kernel :核函数,默认是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’
degree :多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。
gamma : ‘rbf’,‘poly’ 和‘sigmoid’的核函数参数。默认是’auto’,则gamma=1/n_features
coef0 :核函数的常数项。对于‘poly’和 ‘sigmoid’有用。
probability :是否采用概率估计。默认为False。要采用的话必须先于调用fit,这个过程会增加用时。
shrinking :是否采用shrinking heuristic方法,默认为true
tol :停止训练的误差值大小,默认为1e-3
cache_size :核函数cache缓存大小,默认为200
class_weight :类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)
verbose :允许冗余输出。跟多线程有关系。默认为False。
max_iter :最大迭代次数。-1为无限制。
decision_function_shape :是否返回模型中每一个类别的样本的ovr决策函数,或者ovo决策函数。 默认为None
random_state :数据洗牌时的种子值,int值
主要调节的参数有:C、kernel、degree、gamma、coef0。
6 推广
官方文档是学习的绝佳利器。传送门:http://scikit-learn.org/dev/modules/svm.html
6.1 多分类
SVM算法最初是为二值分类问题设计的,当处理多类问题时,就需要构造合适的多类分类器。目前,构造SVM多类分类器的方法主要有两类:一类是直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题“一次性”实现多类分类。这种方法看似简单,但其计算复杂度比较高,实现起来比较困难,只适合用于小型问题中;另一类是间接法,主要是通过组合多个二分类器来实现多分类器的构造,常见的方法有one-against-one和one-against-all两种。
- 一对多法(one-versus-rest,简称1-v-r SVMs)。训练时依次把某个类别的样本归为一类,其他剩余的样本归为另一类,这样k个类别的样本就构造出了k个SVM。分类时将未知样本分类为具有最大分类函数值的那类。
- 一对一法(one-versus-one,简称1-v-1 SVMs)。其做法是在任意两类样本之间设计一个SVM,因此k个类别的样本就需要设计k(k-1)/2个SVM。当对一个未知样本进行分类时,最后得票最多的类别即为该未知样本的类别。Libsvm中的多类分类就是根据这个方法实现的。
- 层次支持向量机(H-SVMs)。层次分类法首先将所有类别分成两个子类,再将子类进一步划分成两个次级子类,如此循环,直到得到一个单独的类别为止。 对c和d两种方法的详细说明可以参考论文《支持向量机在多类分类问题中的推广》(计算机工程与应用。2004)
- 其他多类分类方法。除了以上几种方法外,还有有向无环图SVM(Directed Acyclic Graph SVMs,简称DAG-SVMs)和对类别进行二进制编码的纠错编码SVMs。
6.2 回归
支持分类的支持向量机可以推广到解决回归问题,这种方法称为支持向量回归。
支持向量分类所产生的模型仅仅依赖于训练数据的一个子集,因为构建模型的成本函数不关心在超出边界范围的点,类似的,通过支持向量回归产生的模型依赖于训练数据的一个子集,因为构建模型的函数忽略了靠近预测模型的数据集。
有三种不同的实现方式:支持向量回归SVR,nusvr和linearsvr。linearsvr提供了比SVR更快实施但只考虑线性核函数,而nusvr实现比SVR和linearsvr略有不同。
作为分类类别,训练函数将X,y作为向量,在这种情况下y是浮点数
使用支持向量机(SVM) 算法进行分类的更多相关文章
- 一步步教你轻松学支持向量机SVM算法之案例篇2
一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
- 一步步教你轻松学支持向量机SVM算法之理论篇1
一步步教你轻松学支持向量机SVM算法之理论篇1 (白宁超 2018年10月22日10:03:35) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
- 4、2支持向量机SVM算法实践
支持向量机SVM算法实践 利用Python构建一个完整的SVM分类器,包含SVM分类器的训练和利用SVM分类器对未知数据的分类, 一.训练SVM模型 首先构建SVM模型相关的类 class SVM: ...
- 机器学习:Python中如何使用支持向量机(SVM)算法
(简单介绍一下支持向量机,详细介绍尤其是算法过程可以查阅其他资) 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别.分类(异 ...
- 支持向量机(SVM)算法
- 机器学习集成算法--- 朴素贝叶斯,k-近邻算法,决策树,支持向量机(SVM),Logistic回归
朴素贝叶斯: 是使用概率论来分类的算法.其中朴素:各特征条件独立:贝叶斯:根据贝叶斯定理.这里,只要分别估计出,特征 Χi 在每一类的条件概率就可以了.类别 y 的先验概率可以通过训练集算出 k-近邻 ...
- 转:机器学习中的算法(2)-支持向量机(SVM)基础
机器学习中的算法(2)-支持向量机(SVM)基础 转:http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html 版 ...
- 机器学习算法 - 支持向量机SVM
在上两节中,我们讲解了机器学习的决策树和k-近邻算法,本节我们讲解另外一种分类算法:支持向量机SVM. SVM是迄今为止最好使用的分类器之一,它可以不加修改即可直接使用,从而得到低错误率的结果. [案 ...
- SVM算法
本文主要介绍支持向量机理论推导及其工程应用. 1 基本介绍 支持向量机算法是一个有效的分类算法,可用于分类.回归等任务,在传统的机器学习任务中,通过人工构造.选择特征,然后使用支持向量机作为训练器,可 ...
随机推荐
- tensorFlow 三种启动图的用法
tf.Session(),tf.InteractivesSession(),tf.train.Supervisor().managed_session() 用法的区别: tf.Session() 构 ...
- C# DataReader
//1 连接字符串 string connectionString = "server=127.0.0.1;integrated security=true;database=MSPetSh ...
- 1-自己动手编写ArrayList集合
学习集合的原理,这是一个很简单的代码,没有索引下标越界判断,异常处理等,不够健壮,后面会继续更新完善代码..... 只是入门学习一下 package my; /*** * 自己动手编写一个ArrayL ...
- python数据类型总结
按存值个数区分 标量/原子类型 数字,字符串 容器类型 列表,元组,字典 按可变不可变区分 可变 列表,字典 不可变 数字,字符串,元组 按访问顺序区分 直接访问 数字 顺序访问(序列类型) 字符串, ...
- 最精简的自定义.net 开发框架
一. 通过自定义的HttpModule和HttpHandler,重写url,自定义路由规则,实现 Web API功能. 简单说 就是 请求路径 例如 service/method, 那么就指向当前应 ...
- Java - 34 Java 文档注释
Java 文档注释 Java只是三种注释方式.前两种分别是// 和/* */,第三种被称作说明注释,它以/** 开始,以 */结束. 说明注释允许你在程序中嵌入关于程序的信息.你可以使用javadoc ...
- [SQL Server]无法创建 SSIS 运行时对象,请验证 DTS.dll 是否可用及是否已注册
很大可能是SQL Server Management Studio(SSMS)版本与当前操作系统不兼容造成的,与数据库本身没有关系,这种情况基本无解,不过可以使用其他机器连本机数据库导入导出数据. 今 ...
- [Unity插件]AI行为树使用总结
参考链接: https://blog.csdn.net/linxinfa/article/details/72937709 https://blog.csdn.net/wanghaodiablo/ar ...
- 干净win7要做几步才能运行第一个Spring MVC 写的动态web程序
干净win7要做几步才能运行第一个Spring MVC 写的动态web程序: 1. 下载安装jdk 2. 配置Java环境变量 3. 测试一下第1,2两步是否完全成功:http://jingyan.b ...
- python if all
#encoding:utf-8 s=['1','9']sta='56789'# if all(t not in sta for t in s):# print staif all(t not ...