前言

支持向量机,也即SVM,号称分类算法,甚至机器学习界老大哥。其理论优美,发展相对完善,是非常受到推崇的算法。

本文将讲解的SVM基于一种最流行的实现 - 序列最小优化,也即SMO。

另外还将讲解将SVM扩展到非线性可分的数据集上的大致方法。

预备术语

1. 分割超平面:就是决策边界

2. 间隔:样本点到分割超平面的距离

3. 支持向量:离分割超平面距离最近的样本点

算法原理

在前一篇文章 - 逻辑回归中,讲到了通过拟合直线来进行分类。

而拟合的中心思路是求错误估计函数取得最小值,得到的拟合直线是到各样本点距离和最小的那条直线。

然而,这样的做法很多时候未必是最合适的。

请看下图:

一般来说,逻辑回归得到的直线线段会是B或者C这样的形式。而很显然,从分类算法的健壮性来说,D才是最佳的拟合线段。

SVM分类算法就是基于此思想:找到具有最小间隔的样本点,然后拟合出一个到这些样本点距离和最大的线段/平面。

如何计算最优超平面

1. 首先根据算法思想 - "找到具有最小间隔的样本点,然后拟合出一个到这些样本点距离和最大的线段/平面。" 写出目标函数:

该式子的解就是待求的回归系数。

然而,这是一个嵌套优化问题,非常难进行直接优化求解。为了解这个式子,还需要以下步骤。

2. 不去计算内层的min优化,而是将距离值界定到一个范围 - 大于1,即最近的样本点,也即支持向量到超平面的距离为1。下图可以清楚表示这个意思:

去掉min操作,代之以界定:label * (wTx + b) >= 1。

3. 这样得到的式子就是一个带不等式的优化问题,可以采用拉格朗日乘子法(KKT条件)去求解。

具体步骤推论本文不给出。推导结果为:

另外,可加入松弛系数 C,用于控制 "最大化间隔" 和"保证大部分点的函数间隔小于1.0" 这两个目标的权重。

将 α >= 0 条件改为 C >= α >= 0 即可。

α 是用于求解过程中的一个向量,它和要求的结果回归系数是一一对应的关系。

将其中的 α 解出后,便可依据如下两式子(均为推导过程中出现的式子)进行转换得到回归系数:

说明: 要透彻理解完整的数学推导过程需要一些时间,可参考某位大牛的文章http://blog.csdn.net/v_july_v/article/details/7624837。

使用SMO - 高效优化算法求解 α 值

算法思想:

每次循环中选择两个 α 进行优化处理。一旦找到一对合适的 α,那么就增大其中一个减小另外一个。

所谓合适,是指必须符合两个条件:1. 两个 α 值必须要在 α 分隔边界之外 2. 这两个α 还没有进行过区间化处理或者不在边界上。

使用SMO求解 α 伪代码:

  1. 创建一个 alpha 向量并将其初始化为全0
  2. 当迭代次数小于最大迭代次数(外循环):
  3. 对数据集中的每个向量(内循环):
  4. 如果该数据向量可以被优化
  5. 随机选择另外一个数据向量
  6. 同时优化这两个向量
  7. 如果都不能被优化,推出内循环。
  8. 如果所有向量都没有被优化,则增加迭代数目,继续下一次的循环。

实现及测试代码:

  1. #!/usr/bin/env python
  2. # -*- coding:UTF-8 -*-
  3.  
  4. '''
  5. Created on 20**-**-**
  6.  
  7. @author: fangmeng
  8. '''
  9.  
  10. from numpy import *
  11. from time import sleep
  12.  
  13. #=====================================
  14. # 输入:
  15. # fileName: 数据文件
  16. # 输出:
  17. # dataMat: 测试数据集
  18. # labelMat: 测试分类标签集
  19. #=====================================
  20. def loadDataSet(fileName):
  21. '载入数据'
  22.  
  23. dataMat = []; labelMat = []
  24. fr = open(fileName)
  25. for line in fr.readlines():
  26. lineArr = line.strip().split('\t')
  27. dataMat.append([float(lineArr[0]), float(lineArr[1])])
  28. labelMat.append(float(lineArr[2]))
  29. return dataMat,labelMat
  30.  
  31. #=====================================
  32. # 输入:
  33. # i: 返回结果不等于该参数
  34. # m: 指定随机范围的参数
  35. # 输出:
  36. # j: 0-m内不等于i的一个随机数
  37. #=====================================
  38. def selectJrand(i,m):
  39. '随机取数'
  40.  
  41. j=i
  42. while (j==i):
  43. j = int(random.uniform(0,m))
  44. return j
  45.  
  46. #=====================================
  47. # 输入:
  48. # aj: 数据对象
  49. # H: 数据对象最大值
  50. # L: 数据对象最小值
  51. # 输出:
  52. # aj: 定界后的数据对象。最大H 最小L
  53. #=====================================
  54. def clipAlpha(aj,H,L):
  55. '为aj定界'
  56.  
  57. if aj > H:
  58. aj = H
  59. if L > aj:
  60. aj = L
  61. return aj
  62.  
  63. #=====================================
  64. # 输入:
  65. # dataMatIn: 数据集
  66. # classLabels: 分类标签集
  67. # C: 松弛参数
  68. # toler: 荣错率
  69. # maxIter: 最大循环次数
  70. # 输出:
  71. # b: 偏移
  72. # alphas: 拉格朗日对偶因子
  73. #=====================================
  74. def smoSimple(dataMatIn, classLabels, C, toler, maxIter):
  75. 'SMO算法求解alpha'
  76.  
  77. # 数据格式转化
  78. dataMatrix = mat(dataMatIn);
  79. labelMat = mat(classLabels).transpose()
  80. m,n = shape(dataMatrix)
  81. alphas = mat(zeros((m,1)))
  82.  
  83. iter = 0
  84. b = 0
  85. while (iter < maxIter):
  86. # alpha 改变标记
  87. alphaPairsChanged = 0
  88.  
  89. # 对所有数据集
  90. for i in range(m):
  91. # 预测结果
  92. fXi = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T)) + b
  93. # 预测结果与实际的差值
  94. Ei = fXi - float(labelMat[i])
  95. # 如果差值太大则进行优化
  96. if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):
  97. # 随机选择另外一个样本
  98. j = selectJrand(i,m)
  99. # 计算另外一个样本的预测结果以及差值
  100. fXj = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + b
  101. Ej = fXj - float(labelMat[j])
  102. # 暂存当前alpha值对
  103. alphaIold = alphas[i].copy();
  104. alphaJold = alphas[j].copy();
  105. # 确定alpha的最大最小值
  106. if (labelMat[i] != labelMat[j]):
  107. L = max(0, alphas[j] - alphas[i])
  108. H = min(C, C + alphas[j] - alphas[i])
  109. else:
  110. L = max(0, alphas[j] + alphas[i] - C)
  111. H = min(C, alphas[j] + alphas[i])
  112. if L==H:
  113. pass
  114. # eta为alphas[j]的最优修改量
  115. eta = 2.0 * dataMatrix[i,:]*dataMatrix[j,:].T - dataMatrix[i,:]*dataMatrix[i,:].T - dataMatrix[j,:]*dataMatrix[j,:].T
  116. if eta >= 0:
  117. print "eta>=0"; continue
  118. # 订正alphas[j]
  119. alphas[j] -= labelMat[j]*(Ei - Ej)/eta
  120. alphas[j] = clipAlpha(alphas[j],H,L)
  121. # 如果alphas[j]发生了轻微变化
  122. if (abs(alphas[j] - alphaJold) < 0.00001):
  123. continue
  124. # 订正alphas[i]
  125. alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])
  126.  
  127. # 订正b
  128. b1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[i,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i,:]*dataMatrix[j,:].T
  129. b2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[j,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j,:]*dataMatrix[j,:].T
  130. if (0 < alphas[i]) and (C > alphas[i]): b = b1
  131. elif (0 < alphas[j]) and (C > alphas[j]): b = b2
  132. else: b = (b1 + b2)/2.0
  133.  
  134. # 更新修改标记参数
  135. alphaPairsChanged += 1
  136.  
  137. if (alphaPairsChanged == 0): iter += 1
  138. else: iter = 0
  139.  
  140. return b,alphas
  141.  
  142. def test():
  143. '测试'
  144.  
  145. dataArr, labelArr = loadDataSet('/home/fangmeng/testSet.txt')
  146. b, alphas = smoSimple(dataArr, labelArr, 0.6, 0.001, 40)
  147. print b
  148. print alphas[alphas>0]
  149.  
  150. if __name__ == '__main__':
  151. test()

其中,testSet.txt数据文件格式为三列,前两列特征,最后一列分类结果。

测试结果:

结果具有随机性,多次运行的结果不一定一致。

得到 alphas 数组和 b 向量就能直接算到回归系数了,参考上述代码 93 行,稍作变换即可。

非线性可分情况的大致解决思路

当数据分析图类似如下的情况:

则显然无法拟合出一条直线来。碰到这种情况的解决办法是使用核函数 - 将在低维处理非线性问题转换为在高维处理线性问题。

也就是说,将在SMO中所有出现了向量内积的地方都替换成核函数处理。

具体的用法,代码本文不做讲解。

小结

支持向量机是分类算法中目前用的最多的,也是最为完善的。

关于支持向量机的讨论远远不会止于此,本文初衷仅仅是对这个算法有一定的了解,认识。

若是在以后的工作中需要用到这方面的知识,还需要全面深入的学习,研究。

第八篇:支持向量机 (SVM)分类器原理分析与基本应用的更多相关文章

  1. 支持向量机 (SVM)分类器原理分析与基本应用

    前言 支持向量机,也即SVM,号称分类算法,甚至机器学习界老大哥.其理论优美,发展相对完善,是非常受到推崇的算法. 本文将讲解的SVM基于一种最流行的实现 - 序列最小优化,也即SMO. 另外还将讲解 ...

  2. Stanford机器学习---第八讲. 支持向量机SVM

    原文: http://blog.csdn.net/abcjennifer/article/details/7849812 本栏目(Machine learning)包括单参数的线性回归.多参数的线性回 ...

  3. 大数据-10-Spark入门之支持向量机SVM分类器

    简介 支持向量机SVM是一种二分类模型.它的基本模型是定义在特征空间上的间隔最大的线性分类器.支持向量机学习方法包含3种模型:线性可分支持向量机.线性支持向量机及非线性支持向量机.当训练数据线性可分时 ...

  4. opencv 支持向量机SVM分类器

    支持向量机SVM是从线性可分情况下的最优分类面提出的.所谓最优分类,就是要求分类线不但能够将两类无错误的分开,而且两类之间的分类间隔最大,前者是保证经验风险最小(为0),而通过后面的讨论我们看到,使分 ...

  5. Mybatis插件原理分析(二)

    在上一篇中Mybatis插件原理分析(一)中我们主要介绍了一下Mybatis插件相关的几个类的源码,并对源码进行了一些解释,接下来我们通过一个简单的插件实现来对Mybatis插件的运行流程进行分析. ...

  6. 一步步教你轻松学支持向量机SVM算法之案例篇2

    一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...

  7. 一步步教你轻松学支持向量机SVM算法之理论篇1

    一步步教你轻松学支持向量机SVM算法之理论篇1 (白宁超 2018年10月22日10:03:35) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...

  8. 支持向量机(SVM)原理详解

    SVM简介 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机:SVM还包括核技巧, ...

  9. 第八篇:支持向量机 (Support Vector Machine)

    前言 本文讲解如何使用R语言中e1071包中的SVM函数进行分类操作,并以一个关于鸢尾花分类的实例演示具体分类步骤. 分析总体流程 1. 载入并了解数据集:2. 对数据集进行训练并生成模型:3. 在此 ...

随机推荐

  1. SHU 第15届上海大学程序设计联赛夏季赛[热身赛] 第三题(G题) - 英语成绩

    看完题目就觉得是个图论题…… 每个人的成绩就是vertice,两个人的分数差就是edge,那么肯定类似于一种relax的方式,不断将每个人的成绩的min往上提, 当然,单纯的遍历一遍G.E肯定不可能就 ...

  2. POJ - 3026 Borg Maze bfs+最小生成树。

    http://poj.org/problem?id=3026 题意:给你一个迷宫,里面有 ‘S’起点,‘A’标记,‘#’墙壁,‘ ’空地.求从S出发,经过所有A所需要的最短路.你有一个特殊能力,当走到 ...

  3. The Concept of a Process

    COMPPUTER SCIENCE AN OVERVIEW 11th Edition One of the most fundamental concepts of modern operating ...

  4. Linux 下用 crontab 设置定时执行python 程序

    Linux 下用 crontab 设置定时执行python 程序 方法/步骤   1,先大概了解crontab,/etc/crontab 就是crontab 的配置文件. crontab命令详解可以查 ...

  5. LoadRunner-参数化(连接数据库)

    多用户并发测试,用户信息来自数据库,对脚本中accounts值替换为参数后,打开参数列表. 1.点击 Data Wizard...:选择Specify SQL statement manu: 2.点击 ...

  6. LoadRunner-关联(自动关联和手动关联)

    使用LR录制脚本,新建课程:每次新建课程都会产生一个新的courseid和partid,直接使用录制的脚本执行是不行的.所以用到了关联. 注:关联分手动和自动关联,自动关联搜索出一些不必要关联的数据, ...

  7. mysql 用户与权限

    1.用户 1)创建用户   "create user '用户'@'host' identified by '密码';" 在5.7以后的版本中要求密码包含至少一个大写字母,一个小写字 ...

  8. (3.11)mysql基础深入——mysql文件分类与配置文件管理

    (3.11)mysql基础深入——mysql文件分类与管理 关键词:mysql配置文件,mysql参数文件,mysql中的my.cnf 目录:mysql数据库文件分类: [1]参数文件:my.cnf ...

  9. 学习Linux二(创建、删除文件和文件夹命令)

     转自:http://www.cnblogs.com/zf2011/archive/2011/05/17/2049155.html 今天学习了几个命令,是创建.删除文件和文件夹的,在linux里,文件 ...

  10. /etc/issue 查看系统版本号

    查看系统版本号 [root@mysql bin]# cat /etc/issue CentOS release 6.4 (Final) Kernel \r on an \m