目录

1 基于最大间隔分隔数据

2 寻找最大间隔

2.1 分类器求解的优化问题

2.2 SVM应用的一般流程

3 SMO高效优化算法

3.1 Platt的SMO算法

3.2应用简化版SMO算法处理小规模数据集

4 利用完整Platt SMO算法加速优化

5 在复杂数据上应用核函数

5.1 利用核函数将数据映射到高维空间

5.2径向基核函数

5.3 在测试中用到核函数

6 手写识别问题回顾

7 本章小结


本章涉及到的向相关代码和数据

SVM有很多种实现方法,但是这里学习最流行的一种,即序列最小化(SMO)算法。在此之后,将介绍如何使用一种称为核函数的方式奖SVM拓展到更多数据集上

1 基于最大间隔分隔数据

优点:泛化错误率低,计算开销不大,结果易解释

缺点:对参数调节喝核函数的选择敏感,原始分类器不加修饰仅适用于处理二类问题

适用数据类型:数值型数据与标称型数据

支持向量就是离分割超平面最近的那些点,然后找到最大化支持向量到分割面的距离,需要找到此问题的优化求解方法

2 寻找最大间隔

2.1 分类器求解的优化问题

使用海维赛德阶跃函数来进行分类的计算

为了找到分割最好的那一条线,我们在这里选择得到最大化支持向量的最大化间隔

2.2 SVM应用的一般流程

①收集数据:可以使用任意方法

②准备数据:需要数值型数据

③分析数据:有助于可视化分隔超平面

④训练算法:SVM的大部分时间都源于训练,该过程主要实现两个参数的调优

⑤测试算法:十分简单的计算过程就可以实现

⑥使用算法:几乎所有的分类问题都可以使用SVM,值得一提的是,SVM本身是一个二类分类器,对多类问题应用SVM需要对代码做出一些修改

3 SMO高效优化算法

①最小化的目标函数

②在优化过程中必须遵循约束条件

3.1 Platt的SMO算法

SMO表示序列最小化。PLatt的SMO算法是将大优化问题分解为多个小优化问题来求解。这些小优化问题往往很容易求解,并且对他们进行顺序求解的结果与将他们整体来求解的结果是完全一致的。在结果完全相同的条件下,SMO算法的求解时间就会短很多。

SMO算法的目标是求出一系列alpha和b,一旦求出了这些alpha,就很容易计算出权重向量w,并得到分割超平面。

SMO算法的工作原理为:每次循环中选择两个alpha进行优化处理。一旦找到一对合适的alpha,那么就增大其中一个同时减小另一个。这里所谓的合适就是指两个alpha必须要符合一定的条件,条件之一就是这两个alpha必须要在间隔边界之外,而这第二个条件则是这两个alpha还没有进行区间化处理或者不在边界上。

3.2应用简化版SMO算法处理小规模数据集

platt SMO的实现需要大量的代码。因此我们对算法进行简化处理,以便大致了解算法的基本工作思路,之后再基于简化版给出完整版。简化版虽然量少但执行速度慢。

# SMO算法中的辅助函数# 打开文件并对其进行逐行分析,从而得到每行的类标签和整个数据矩阵
def loadDataSet(fileName):dataMat=[]labelMat=[]fr=open(fileName)# 读取文件# 按行读取for line in fr.readlines():# 将每一行的数据进行分割lineArr=line.strip().split('\t')# 前两列为x,y值dataMat.append([float(lineArr[0]),float(lineArr[1])])# 第三列为标签值labelMat.append(float(lineArr[2]))# 返回数据集和标签集return dataMat,labelMat# 只要函数值不等于输入值i,函数就会进行随机选择
import random
#         i输入下标,m为总数
def selectJrand(i,m):j=iwhile(j==i):j=int(random.uniform(0,m))return j# 用于调整大于H或是小于L的alpha的值
def clipAlpha(aj,H,L):# 大于H的值取Hif aj>H:aj=H# 小于L的值取Lif L>aj:aj=Lreturn aj

运行上面函数读取数据

dataArr,labelArr=loadDataSet('testSet.txt')
# 可以看出这里的分类标签是1和-1,而不是1和0
labelArr

运行得到的结果为:

先写出数据集中的二维点的分布函数

# 画出待分类数据的二维分布
import numpy as np
def plotBestFit(dataMat,labelMat):import matplotlib.pyplot as plt# getA()函数将矩阵转化为数组# weights=wei.getA()# 加载数据dataArr=np.array(dataMat)n=np.shape(dataArr)[0]xcord1=[]ycord1=[]xcord2=[]ycord2=[]# print(labelMat)for i in range(n):if int(labelMat[i])==1:xcord1.append(dataArr[i][0])ycord1.append(dataArr[i][1])else:xcord2.append(dataArr[i][0])ycord2.append(dataArr[i][1])fig=plt.figure()ax=fig.add_subplot(111)# print(xcord1)# print(ycord1)ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')ax.scatter(xcord2,ycord2,s=30,c='green')# arange()函数用于创造等差数组# 起始点 终止点 步长# x=np.arange(-3.0,3.0,0.1)# y=(-weights[0]-weights[1]*x)/weights[2]# ax.plot(x,y)# 添加xy轴标签plt.xlabel('X1')plt.ylabel('X2')# 显示图像plt.show()

调用上述函数

plotBestFit(dataArr,labelArr)

得到二维点的分布结果:

接下来写SMO函数的具体实现,他的伪代码大致如下:

创建一个alpha向量并将其初始化为0向量

当迭代次数小于最大迭代次数时:(外循环)

对数据集中的每个数据向量:(内循环)

如果该数据向量可以被优化:

随机选择另外一个数据向量

同时优化这两个向量

如果两个向量都不能被优化,推出内循环

如果所有向量都没有被优化,增加迭代次数,继续下一次循环

简化版的代码如下:

# 简化版的smo算法
from numpy import *
# 构建函数时,采用通用的接口,这样就可以对算法和数据源进行组合和配对处理
#    输入参数:数据集,类别标签,常数C,容错率,取消最大的循环次数
def smoSimple(dataMatIn, classLabels, C, toler, maxIter):# 将数列转化为矩阵dataMatrix = mat(dataMatIn)# .transpose()函数映射坐标轴labelMat = mat(classLabels).transpose()b = 0; # 得到矩阵的长和宽m,n = shape(dataMatrix)# 得到一个m行1列全部是0的矩阵alphas = mat(zeros((m,1)))iter = 0while (iter < maxIter):alphaPairsChanged = 0for i in range(m):fXi = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T)) + bEi = fXi - float(labelMat[i])#if checks if an example violates KKT conditions# 如果alpha可以更改则进入优化过程if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):j = selectJrand(i,m)fXj = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + bEj = fXj - float(labelMat[j])alphaIold = alphas[i].copy()alphaJold = alphas[j].copy()# 保证alpha在0和C之间if (labelMat[i] != labelMat[j]):L = max(0, alphas[j] - alphas[i])H = min(C, C + alphas[j] - alphas[i])else:L = max(0, alphas[j] + alphas[i] - C)H = min(C, alphas[j] + alphas[i])if L==H: print ("L==H"); continueeta = 2.0 * dataMatrix[i,:]*dataMatrix[j,:].T - dataMatrix[i,:]*dataMatrix[i,:].T - dataMatrix[j,:]*dataMatrix[j,:].Tif eta >= 0: print ("eta>=0"); continuealphas[j] -= labelMat[j]*(Ei - Ej)/etaalphas[j] = clipAlpha(alphas[j],H,L)if (abs(alphas[j] - alphaJold) < 0.00001): print ("j not moving enough"); continuealphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])#update i by the same amount as j#the update is in the oppostie directionb1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[i,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i,:]*dataMatrix[j,:].Tb2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[j,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j,:]*dataMatrix[j,:].Tif (0 < alphas[i]) and (C > alphas[i]): b = b1elif (0 < alphas[j]) and (C > alphas[j]): b = b2else: b = (b1 + b2)/2.0alphaPairsChanged += 1print ("iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))if (alphaPairsChanged == 0): iter += 1else: iter = 0print ("iteration number: %d" % iter)return b,alphas

调用简化版的代码:

b,alphas=smoSimple(dataArr,labelArr,0.6,0.001,40)

运行得到的结果为:

分别查看b和支持向量的alpha的值如下

并且写代码筛选出得到的支持向量:

shape(alphas[alphas>0])
for i in range(100):if alphas[i]>0.0:print(dataArr[i],labelArr[i])

运行得到的支持向量为5个支持向量

4 利用完整Platt SMO算法加速优化

在几百个点组成的小规模数据集上,简化版SMO算法的运行是么样问题的,但是在更大的数据集上的运行速度就会变慢。在完整版中,实现alpha的更改和代数运算的优化环节一模一样。在优化过程中唯一不同的就是选择alpha的方式。完整版的Platt SMO算法应用了一些那个提速的启发方法。

Platt SMO算法时通过一个外循环来选择第一个alpha的值,并且其选择过程会在两种方式之间交替:一种方式是在所有数据集上进行单遍扫描,另一种方式则是在非边界alpha中实现单遍扫描。而那些所谓非边界alpha指的就是那些不等于边界0或C的alpha值。对整个数据集的扫描相当容易,而实现非边界alpha值的扫描时,首先需要建立这些alpha值的列表,然后子啊对这个表进行遍历。同时该步骤会跳过那些一职的不会改变的alpha值。

在选择第一个alpha值的时后,算法会通过一个内循环来选择第二个alpha的值,在优化过程中,会通过最大化步长的方式来获得第二个alpha值。再简化版SMO算法中,我们会选择j之后计算错误率Ej。但在这里,我们会建立一个全局的缓存用于保存误差值,并从中选择使得步长或者说是Ei-Ej最大的alpha值

# 建立一个数据结构来保存所有重要的数据
class optStruct:def __init__(self,dataMatIn,classLabels,C,toler):self.X=dataMatIn                      #数据集self.labelMat=classLabels             #标签集self.C=C                              #常数Cself.tol=toler                        #容错率self.m=shape(dataMatIn)[0]            #数据集的列self.alphas=mat(zeros((self.m,1)))    #alpha矩阵self.b=0                              #参数bself.eCache=mat(zeros((self.m,2)))# 对于给定的alpha值,计算E值并返回
# 使用频繁,直接单独拎出来
def calcEk(oS,k):fXk=float(multiply(oS.alphas,oS.labelMat).T*(oS.X*oS.X[k,:].T))+oS.bEk=fXk-float(oS.labelMat[k])return Ek# 用于选择第二个alpha或者说内循环的alpha的值
def selectJ(i,oS,Ei):maxK=-1maxDeltaE=0Ej=0oS.eCache[i]=[1,Ei]validEcacheList=nonzero(oS.eCache[:,0].A)[0]if(len(validEcacheList))>1:for k in validEcacheList:if k==i:continueEk=calcEk(oS,k)deltaE=abs(Ei-Ek)if(deltaE>maxDeltaE):maxK=kmaxDeltaE=deltaEEj=Ekreturn maxK,Ejelse:j=selectJrand(i,oS.m)Ej=calcEk(oS,j)return j,Ej# 计算误差值并存入缓存
def updateEk(oS,k):Ek=calcEk(oS,k)oS.eCache[k]=[1,Ek]# 用于寻找决策边界的优化例程
def innerL(i,oS):Ei=calcEk(oS,i)# 是否进行优化if((oS.labelMat[i]*Ei<-oS.tol)and(oS.alphas[i]<oS.C))or((oS.labelMat[i]*Ei>oS.tol)and(oS.alphas[i]>0)):j,Ej=selectJ(i,oS,Ei)alphaIold=oS.alphas[i].copy()alphaJold=oS.alphas[j].copy()if(oS.labelMat[i]!=oS.labelMat[j]):L=max(0,oS.alphas[j]-oS.alphas[i])H=min(oS.C,oS.C+oS.alphas[j]-oS.alphas[i])else:L=max(0,oS.alphas[j]+oS.alphas[i]-oS.C)H=min(oS.C,oS.alphas[j]+oS.alphas[i])if L==H: print ("L==H")return 0eta = 2.0 * oS.X[i,:]*oS.X[j,:].T - oS.X[i,:]*oS.X[i,:].T - oS.X[j,:]*oS.X[j,:].Tif eta >= 0: print ("eta>=0") return 0oS.alphas[j] -= oS.labelMat[j]*(Ei - Ej)/etaoS.alphas[j] = clipAlpha(oS.alphas[j],H,L)updateEk(oS, j) #added this for the Ecacheif (abs(oS.alphas[j] - alphaJold) < 0.00001): print ("j not moving enough")return 0oS.alphas[i] += oS.labelMat[j]*oS.labelMat[i]*(alphaJold - oS.alphas[j])#update i by the same amount as jupdateEk(oS, i) #added this for the Ecache                    #the update is in the oppostie directionb1 = oS.b - Ei- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.X[i,:]*oS.X[i,:].T - oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.X[i,:]*oS.X[j,:].Tb2 = oS.b - Ej- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.X[i,:]*oS.X[j,:].T - oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.X[j,:]*oS.X[j,:].Tif (0 < oS.alphas[i]) and (oS.C > oS.alphas[i]): oS.b = b1elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2else: oS.b = (b1 + b2)/2.0return 1else: return 0# 外循环代码
def smoP(dataMatIn,classLabels,C,toler,maxIter,kTup=('lin',0)):# 初始化一个结构体oS=optStruct(mat(dataMatIn),mat(classLabels).transpose(),C,toler)iter=0     #记录循环次数entireSet=TruealphaPairsChanged=0# 进入循环# 如果循环次数没有达到最大上限  and while(iter<maxIter)and ((alphaPairsChanged>0)or(entireSet)):alphaPairsChanged=0if entireSet:# 对数据集中的每个数据向量for i in range(oS.m):alphaPairsChanged+=innerL(i,oS)print("fullSet,iter:%d i:%d,pairs changed %d" %(iter,i,alphaPairsChanged))iter+=1else:nonBoundIs=nonzero((oS.alphas.A>0)*(oS.alphas.A<C))[0]for i in nonBoundIs:alphaPairsChanged+=innerL(i,oS)print("non-bound,iter:%d i:%d,pairs changed %d" %(iter,i,alphaPairsChanged))iter+=1# 使下次能够进入循环if entireSet:entireSet=Falseelif(alphaPairsChanged==0):entireSet=Trueprint("iteration number:%d"%iter)# 返回训练得到的b和alpha矩阵return oS.b,oS.alphas

利用上述代码进行SMO的计算

# 打开文件,读取数据
dataArr,labelArr=loadDataSet('testSet.txt')
# 将数据进行支持向量机训练
b,alphas=smoP(dataArr,labelArr,0.6,0.001,40)

运行得到的结果为:

再次查看b和支持向量的值:

计算最终起作用的(斜率)?

def calcWs(alphas,dataArr,classLabels):X=mat(dataArr)labelMat=mat(classLabels).transpose()m,n=shape(X)w=zeros((n,1))for i in range(m):# 最终起作用的只有支持向量w+=multiply(alphas[i]*labelMat[i],X[i,:].T)return w

调用上述函数并使用一个数据进行检验

ws=calcWs(alphas,dataArr,labelArr)
datMat=mat(dataArr)
datMat[0]*mat(ws)+b

得到的结果为

结果是小于0 的

因此查看该数据的分类:

是-1,因此测试的结果正确。

5 在复杂数据上应用核函数

前面我们用的数据就是讨论线性可分的情况。接下来,我们就要使用一种称为核函数的工具将数据转换为已于分类器理解的形式

5.1 利用核函数将数据映射到高维空间

我们将数据从一个特征空间转换为另一个特征空间。再新空间下,我们可以很容易利用已有的工具对数据进行处理。在通常情况下,这种映射将为从低维特征空间映射到高维空间。

这种从某个特征空间到另一个特征空间的映射是通过核函数来实现的。他能够报数据从某个很难处理的形式转换为另一个较容易处理的形式。经过空间转换之后,我们可以在高维空间中解决线性问题,这也就等价于在地位空间中解决非线性问题。

SVM优化中一个特别好的地方就是,所有的运算都可以写成内积的形式,向量的内积指的是两个向量相乘,之后得到的单个标量或是数值。把内积替换成核函数,而不做简化处理,这种方式被称为核技巧。

核函数不仅仅应用于向量机,很多其他的机器学习算法也都有用到核函数。

5.2径向基核函数

径向基函数是SVM中常用到的一种核函数,他是一个采用向量作为自变量的函数,能够基于向量距离运算输出一个标量。

这里 我们应用径向基函数的高斯版本,将数据从特征空间映射到更高维的空间,具体来说是映射到一个更高维的空间

# 转换核函数
def kernelTrans(X,A,kTup):m,n=shape(X)K=mat(zeros((m,1)))if kTup[0]=='lin':K=X*A.Telif kTup[0]=='rbf':for j in range(m):deltaRow=X[j,:]-AK[j]=deltaRow*deltaRow.TK=exp(K/(-1*kTup[1]**2))else:raise NameError('Houston We Have a Problem--That Kernel is not recognized')return K# 定义一个新的结构体,加入核函数
class optStruct:def __init__(self,dataMatIn,classLabels,C,toler,kTup):self.X=dataMatInself.labelMat=classLabelsself.C=Cself.tol=tolerself.m=shape(dataMatIn)[0]self.alphas=mat(zeros((self.m,1)))self.b=0self.eCache=mat(zeros((self.m,2)))self.K=mat(zeros((self.m,self.m)))# 计算核函数# 引入一个新变量kTupfor i in range(self.m):# 计算高斯函数的值self.K[:,i]=kernelTrans(self.X,self.X[i,:],kTup)# 重新更改上文中提到的innerL()和calcLEk()函数的部分代码
# 用于寻找决策边界的优化例程
def innerL(i,oS):Ei=calcEk(oS,i)# 是否进行优化if((oS.labelMat[i]*Ei<-oS.tol)and(oS.alphas[i]<oS.C))or((oS.labelMat[i]*Ei>oS.tol)and(oS.alphas[i]>0)):j,Ej=selectJ(i,oS,Ei)alphaIold=oS.alphas[i].copy()alphaJold=oS.alphas[j].copy()if(oS.labelMat[i]!=oS.labelMat[j]):L=max(0,oS.alphas[j]-oS.alphas[i])H=min(oS.C,oS.C+oS.alphas[j]-oS.alphas[i])else:L=max(0,oS.alphas[j]+oS.alphas[i]-oS.C)H=min(oS.C,oS.alphas[j]+oS.alphas[i])if L==H: print ("L==H")return 0eta = 2.0 * oS.K[i,j]-oS.K[i,i]-oS.K[j,j]if eta >= 0: print ("eta>=0") return 0oS.alphas[j] -= oS.labelMat[j]*(Ei - Ej)/etaoS.alphas[j] = clipAlpha(oS.alphas[j],H,L)updateEk(oS, j) #added this for the Ecacheif (abs(oS.alphas[j] - alphaJold) < 0.00001): print ("j not moving enough")return 0oS.alphas[i] += oS.labelMat[j]*oS.labelMat[i]*(alphaJold - oS.alphas[j])#update i by the same amount as jupdateEk(oS, i) #added this for the Ecache                    #the update is in the oppostie directionb1 = oS.b - Ei- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.K[i,i] - oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.K[i,j]b2 = oS.b - Ej- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.K[i,j] - oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.K[j,j]if (0 < oS.alphas[i]) and (oS.C > oS.alphas[i]): oS.b = b1elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2else: oS.b = (b1 + b2)/2.0return 1else: return 0# 外循环代码
def smoP(dataMatIn,classLabels,C,toler,maxIter,kTup=('lin',0)):# 初始化一个结构体oS=optStruct(mat(dataMatIn),mat(classLabels).transpose(),C,toler,kTup)iter=0     #记录循环次数entireSet=TruealphaPairsChanged=0# 进入循环# 如果循环次数没有达到最大上限  and while(iter<maxIter)and ((alphaPairsChanged>0)or(entireSet)):alphaPairsChanged=0if entireSet:# 对数据集中的每个数据向量for i in range(oS.m):alphaPairsChanged+=innerL(i,oS)print("fullSet,iter:%d i:%d,pairs changed %d" %(iter,i,alphaPairsChanged))iter+=1else:nonBoundIs=nonzero((oS.alphas.A>0)*(oS.alphas.A<C))[0]for i in nonBoundIs:alphaPairsChanged+=innerL(i,oS)print("non-bound,iter:%d i:%d,pairs changed %d" %(iter,i,alphaPairsChanged))iter+=1# 使下次能够进入循环if entireSet:entireSet=Falseelif(alphaPairsChanged==0):entireSet=Trueprint("iteration number:%d"%iter)# 返回训练得到的b和alpha矩阵return oS.b,oS.alphasdef calcEk(oS,k):fXk=float(multiply(oS.alphas,oS.labelMat).T*oS.K[:,k]+oS.b)Ek=fXk-float(oS.labelMat[k])return Ek

5.3 在测试中用到核函数

def testRbf(k1=1.3):dataArr,labelArr=loadDataSet('testSetRBF.txt')plotBestFit(dataArr,labelArr)b,alphas=smoP(dataArr,labelArr,200,0.0001,10000,('rbf',k1))datMat=mat(dataArr)labelMat=mat(labelArr).transpose()svInd=nonzero(alphas.A>0)[0]sVs=datMat[svInd]labelSV=labelMat[svInd]print('there are %d Support Vectors' % shape(sVs)[0])m,n=shape(datMat)errorCount=0for i in range(m):kernelEval=kernelTrans(sVs,datMat[i,:],('rbf',k1))predict=kernelEval.T*multiply(labelSV,alphas[svInd])+bif sign(predict)!=sign(labelArr[i]):errorCount+=1print('the training error rate is :%f' % (float(errorCount)/m))dataArr,labelArr=loadDataSet('testSetRBF2.txt')errorCount=0datMat=mat(dataArr)labelMat=mat(labelArr).transpose()m,n=shape(datMat)for i in range(m):kernelEval=kernelTrans(sVs,datMat[i,:],('rbf',k1))predict=kernelEval.T*multiply(labelSV,alphas[svInd])+bif sign(predict)!=sign(labelArr[i]):errorCount+=1print("the test error rate is :%f" %(float(errorCount)/m))

调用上述函数:

testRbf()

得到的输出结果为:

可以看出数据测试的错误率为0.27

6 手写识别问题回顾

基于SVM的数字识别

①收集数据:提供的文本文件

②准备数据:基于二值图像构建向量

③分析数据:对图像向量进行目测

④训练数据:采用两种不同的核函数,并对径向基核函数采用不同的设置来运行SMO算法

⑤测试算法:编写一个函数来测试不同的核函数并计算错误率

⑥使用算法:一个图像识别的完整应用还需要一些图像处理的知识

from random import triangulardef img2vector(filename):returnVect=zeros((1,1024))fr=open(filename)# 按行读取矩阵for i in range(32):lineStr=fr.readline()for j in range(32):returnVect[0,32*i+j]=int (lineStr[j])return returnVectdef loadImages(dirName):from os import listdirhwLabels = []trainingFileList = listdir(dirName)           #load the training setm = len(trainingFileList)trainingMat = zeros((m,1024))for i in range(m):fileNameStr = trainingFileList[i]fileStr = fileNameStr.split('.')[0]     #take off .txtclassNumStr = int(fileStr.split('_')[0])if classNumStr == 9: hwLabels.append(-1)else: hwLabels.append(1)trainingMat[i,:] = img2vector('%s/%s' % (dirName, fileNameStr))return trainingMat, hwLabels def testDigits(kTup=('rbf',10)):dataArr,labelArr=loadImages('digits/trainingDigits')b,alphas=smoP(dataArr,labelArr,100,0.001,10000,kTup)datMat=mat(dataArr)labelMat=mat(labelArr).transpose()svInd=nonzero(alphas.A>0)[0]sVs=datMat[svInd]labelSV=labelMat[svInd]print("there are %d Support Vectors"%shape(sVs)[0])m,n=shape(datMat)errorCount=0for i in range(m):kernelEval=kernelTrans(sVs,datMat[i,:],kTup)predict=kernelEval.T*multiply(labelSV,alphas[svInd])+bif sign(predict)!=sign(labelArr[i]):errorCount+=1print("the training error rate is:%f" % (float(errorCount)/m))dataArr,labelArr=loadImages('digits/testDigits')errorCount=0datMat=mat(dataArr)labelMat=mat(labelArr).transpose()m,n=shape(datMat)for i in range(m):kernelEval=kernelTrans(sVs,datMat[i,:],kTup)predict=kernelEval.T*multiply(labelSV,alphas[svInd])+bif sign(predict)!=sign(labelArr[i]):errorCount+=1print("the test error rate is :%f" % (float(errorCount)/m))

调用上述函数:

testDigits(('rbf',20))

得到的结果为为:

因此一旦碰到数字9,则输出类别标签-1,否则输出+1。本质上,支持向量机是-个二类分类器,其分类结果不是+1就是-1。由于这里只做二类分类,因此除了1和9之外的数字都被去掉了。

7 本章小结

支持向量机是一种分类器。之所以称为“机”,是因为它会产生一个二值决策的结果,即它是一种决策机。支持向量机的泛化错误率较低,也就是说他具有良好的学习能力,并且学到的结果具有良好的推广性。

支持向量机试图通过求解一个二次元问题来最大化分类间隔,再过去,训练支持向量机常采用非常复杂并且低效的二次规划问题,john Platt引入了SMO算法,此算法可以通过每次只优化2个alpha值来加快SVM的训练速度。

核方法或者说是核技巧会将数据从一个低维空间映射到一个高维空间,可以将一个在低维空间中的非线性问题转换为高维空间的一个线性问题来研究

《机器学习实战》6.支持向量机(SVM)相关推荐

  1. 机器学习算法の03 支持向量机SVM

    机器学习算法の03 支持向量机SVM SVM的基本概念 线性可分支持向量机 非线性支持向量机和核函数 线性支持向量机与松弛变量 LR与SVM的区别与联系 SVM的基本概念 基本概念: 支持向量机(su ...

  2. 机器学习算法 08 —— 支持向量机SVM算法(核函数、手写数字识别案例)

    文章目录 系列文章 支持向量机SVM算法 1 SVM算法简介 1.1 引入 1.2 算法定义 2 SVM算法原理 2.1 线性可分支持向量机 2.2 SVM计算过程与算法步骤(有点难,我也没理解透,建 ...

  3. 机器学习-分类之支持向量机(SVM)原理及实战

    支持向量机(SVM) 简介 支持向量机(Support Vector Machine,SVM),是常见的一种判别方法.在机器学习领域,是一个监督学习模型,通常用来进行模式识别.分类及回归分析.与其他算 ...

  4. 机器学习实战:支持向量机

    支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning)方式对数据进行二元分类(binary classification)的广义 ...

  5. svm多分类_人工智能科普|机器学习重点知识——支持向量机SVM

    作为模式识别或者机器学习的爱好者,同学们一定听说过支持向量机这个概念,这可是一个,在机器学习中避不开的重要问题. 其实关于这个知识点,有一则很通俗有趣的传说: 很久以前,一个村庄里住着一位退隐的大侠, ...

  6. 最小二乘法支持向量机一般用在什么场合_人工智能科普|机器学习重点知识——支持向量机SVM...

    作为模式识别或者机器学习的爱好者,同学们一定听说过支持向量机这个概念,这可是一个,在机器学习中避不开的重要问题. 其实关于这个知识点,有一则很通俗有趣的传说: 很久以前,一个村庄里住着一位退隐的大侠, ...

  7. 机器学习模型3——支持向量机SVM

    前置知识 拉格朗日乘子法 支持向量机SVM SVM:SVM全称是supported vector machine(⽀持向量机),即寻找到⼀个超平⾯使样本分成两类,并且间隔最⼤. SVM能够执⾏线性或⾮ ...

  8. python机器学习库sklearn——支持向量机svm

    分享一个朋友的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!大家可以看看是否对自己有帮助:点击打开 全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 支持向量机svm的相关的知 ...

  9. 机器学习实战之支持向量机(SVM)(三)SMO高效优化算法

    转载请注明作者和出处:https://blog.csdn.net/weixin_45814668 知乎:https://www.zhihu.com/people/qiongjian0427 Git:h ...

  10. 机器学习实战5-sklearn训练SVM模型分类回归(make_moons数据集)

    先上公式推导吓吓萌新...嘻嘻 上图中两个决策边界(虚线)的间隔为,可以把它看做求两条平行直线的距离,只是这里是超直线罢了, 例如:两平行线方程分别是:Ax+By+C1=0和Ax+By+C2=0 则它 ...

最新文章

  1. java中public_java中public class与class的区别详解
  2. 计算 1+2!+3!+4!+...20!=?
  3. 搭建一个互联网公司后台服务架构及运维架构需要的技术
  4. springboot定时删除log4j_SpringBoot整合log4j2进行日志配置及防坑指南
  5. ”天空之城”的主题曲《君をのせて》
  6. 【Python - OpenCV】数字图像项目实战(四) - 位姿估计
  7. 解决post请求跨域请求第三方服务器
  8. 【DS基础】静态链表
  9. tp5 验证码 验证不正确 (跨域问题)
  10. AD参数微分非线性(DNL)与积分非线性(INL)
  11. openStack 常见问题及解决
  12. QT Creator 应用程序*.exe文件打包发布详细教程【绿色便携形式 和 安装包形式】
  13. 快手怎么保存别人视频,用批量下载热门视频软件
  14. 关于Window10系统无法打开Microsoft Store(应用商店)解决方案
  15. MATLAB获取屏幕大小
  16. 浏览器内核 css浏览器的兼容性写法
  17. WPS 加载项开发说明
  18. 借助Bilibili Evolved和aria2批量下载b站视频
  19. Golang(1)-简介及特性
  20. 基于MATLAB编程的粒子群算法优化BP神经网络风电功率预测,基于PSO-BP的风电功率预测

热门文章

  1. java导出html word文档_java生成带html样式的word文件
  2. 大学android五子棋课程目的,拓展性课程(五子棋)教案.pdf
  3. 地质灾害监测预警系统解决方案
  4. iOS 加载、滑动翻阅大量图片解决方案详解
  5. “新能源拐点”热议潮未退,小鹏却已经从华尔街赶到了港交所
  6. 台式计算机系统重新安装软件,教你台式机如何重装系统
  7. 【计算理论】图灵机 ( 图灵机示例 )
  8. 小鸟云安全组在哪里?怎么设置?
  9. clickhouse多副本
  10. 微信公众号被动消息回复实现