转载请注明作者和出处:https://blog.csdn.net/weixin_45814668
知乎:https://www.zhihu.com/people/qiongjian0427
Git:https://github.com/qiongjian/Machine-learning/
运行环境:anaconda—jupyter notebook
Python版本: Python3.x
更多精彩内容,尽在微信公众号,欢迎您的关注:
1. 优化目标函数和约束条件
经过拉格朗日乘子法得到的优化目标函数为:
约束条件为:
但是,对于上述目标函数,是存在一个假设的,即数据100%线性可分。但我们知道几乎所有数据都不那么"干净"。这时我们就可以通过引入所谓的松弛变量(slack variable),来允许有些数据点可以处于超平面的错误的一侧。这样我们的优化目标就能保持仍然不变,但是此时我们的约束条件为:
SMO算法原理与实战求解
2. Platt的SMO算法
1996年,John Platt发布了一个称为SMO的强大算法,用于训练SVM。
SMO表示序列最小化(Sequential Minimal Optimizaion)。Platt的SMO算法是将大优化问题分解为多个小优化问题来求解的。这些小优化问题往往很容易求解,并且对它们进行顺序求解的结果与将它们作为整体来求解的结果完全一致的。在结果完全相同的同时,SMO算法的求解时间短很多。
SMO算法的目标是求出一系列alpha和b,一旦求出了这些alpha,就很容易计算出权重向量w并得到分隔超平面。
SMO算法的工作原理是:每次循环中选择两个alpha进行优化处理。一旦找到了一对合适的alpha,那么就增大其中一个同时减小另一个。
这里所谓的"合适"就是指两个alpha必须符合以下两个条件,条件之一就是两个alpha必须要在间隔边界之外,而且第二个条件则是这两个alpha还没有进进行过区间化处理或者不在边界上。
3. 简化版SMO算法
3.1 数据集
关注微信公众号,回复SVM1下载数据集。
数据集图片如下:
3.2 辅助函数
首先在数据集上遍历每一个alpha , 然后在剩下的alpha集合中随机选择另一个alpha,从而构建alpha对。这里有一点相当重要,就是我们要同时改变两个alpha 。若是改变一个,约束条件中的第二个可能会失效。
def loadDataSet(fileName):#打开文件并逐行解析
dataMat = []; labelMat = []
fr = open(fileName)
for line in fr.readlines():
lineArr = line.strip().split('\t')
dataMat.append([float(lineArr[0]), float(lineArr[1])]) #添加数据
labelMat.append(float(lineArr[2])) #添加标签
return dataMat,labelMat
#辅助函数1,随机选择一个整数
def selectJrand(i, m):#i是alpha下标,m是alpha个数
j = i
while (j == i):
j = int(random.uniform(0, m))
return j
#辅助函数2,调整大于H或小于L的alpha值
def clipAlpha(aj,H,L):
if aj > H:
aj = H
if L > aj:
aj = L
return aj
运行结果
dataArr,labelArr=loadDataSet('testSet.txt')
labelArr
SMO函数的伪代码大致如下:
创建一个alpha向量并将其初始化为0向量
当迭代次数小于最大迭代次数时(外循环) :
对数据集中的每个数据向量(内循环):
如果该数据向量可以被优化:
随机选择另一个数据向量
同时优化这两个向量
如果两个向量都不能被优化,退出内循环
如果所有向量都没被优化,增加迭代次数,继续下一次循环
import numpy as np
import random
def smoSimple(dataMatIn, classLabels, C, toler, maxIter):#dataMatIn数据集, classLabels类别标签, C常数, toler容错率, maxIter最大循环次数
#转换为numpy的mat存储
dataMatrix =np. mat(dataMatIn); labelMat = np