支持向量机(SVM)是一种二类分类模型。它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;支持向量机还包括核技巧,这使它成为实质上的非线性分类器。支持向量机的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,支持向量机的学习算法是求解凸二次规划的最优算法。
定义一(线性可分支持向量机):
给定线性可分训练数据集,通过间隔最大化或等价地求解相应的凸二次规划问题学习得到的分离超平面为
函数间隔:对于给定的训练数据集和超平面(w,b),定义超平面(w,b)关于样本点( xi,yi x i , y i )的函数间隔为
线性支持向量机学习算法
输入:训练数据集 T=(x1,y1),(x2,y2),⋯,(xN,xN) T = ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , x N ) ,其中, xi∈χ=Rn,y∈Υ={−1,+1},i=1,2,⋯,N; x i ∈ χ = R n , y ∈ Υ = { − 1 , + 1 } , i = 1 , 2 , ⋯ , N ;
输出:分离超平面和分类决策函数。
(1)选择惩罚参数C>0,构造并求解凸二次规划问题
Python代码实现
SMO算法求解线性可分支持向量机代码
from numpy import *
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
def selectJrand(i,m):
j = i
while(j==i):
j = int(random.uniform(0,m))
return j
def clipAlpha(aj,H,L):
if aj > H:
aj = H
if L > aj:
aj = L
return aj
def smoSimple(dataMatIn,classLabels,C,toler,maxIter):
dataMatrix = mat(dataMatIn);labelMat = mat(classLabels).transpose()
b = 0; m,n = shape(dataMatrix)
alphas = mat(zeros((m,1)))
iter = 0
while(iter0
for i in range(m):
fXi = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T))+b
Ei = fXi - float(labelMat[i])
if ((labelMat[i]*Ei < - toler) and (alphas[i]or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):
j = selectJrand(i,m)
fXj = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T))+b
Ej = fXj - float(labelMat[j])
alphaIold = alphas[i].copy()
alphaJold = alphas[j].copy()
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");
continue
eta = 2.0*dataMatrix[i,:]*dataMatrix[j,:].T-dataMatrix[i,:]*dataMatrix[i,:].T-dataMatrix[j,:]*dataMatrix[j,:].T
if eta >=0:
# print("eta>=0");
continue
alphas[j] -= labelMat[j] *(Ei - Ej)/eta
alphas[j] = clipAlpha(alphas[j],H,L)
if(abs(alphas[j]-alphaJold) < 0.000001):
# print("j not moving enough");
continue
alphas[i] += labelMat[j]*labelMat[i]*(alphaJold-alphas[j])
b1 = b - Ei -labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[i,:].T - labelMat[j]*(alphas[j]-alphaJold)*\
dataMatrix[i,:]*dataMatrix[j,:].T
b2 = b - Ej - labelMat[i]*(alphas[i]-alphaIold)*labelMat[j]*alphas[j]*(alphas[j]-alphaJold)*dataMatrix[j,:]*dataMatrix[j,:].T
if (0 < alphas[i]) and (C > alphas[i]): b = b1
elif (0and (C > alphas[j]): b = b2
else: b = (b1+b2)/2.0
alphaPairsChanged += 1
# print("iter:%d i:%d,pairs changed %d "%(iter,i,alphaPairsChanged))
if(alphaPairsChanged == 0): iter += 1
else: iter = 0
# print("iteration number: %d"% iter)
return b,alphas
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
def plotData(dataArr,labelArr,ws,b):
import matplotlib.pyplot as plt
fig = plt.figure()
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
xPlotx,xPloty,oPlotx,oPloty = [],[],[],[]
for i in range(len(labelArr)):
label = labelArr[i]
if label == 1:
xPlotx.append(dataArr[i][0])
xPloty.append(dataArr[i][1])
elif label == -1:
oPlotx.append(dataArr[i][0])
oPloty.append(dataArr[i][1])
plt.title("SVM")
pPlot1,pPlot2 = plt.plot(xPlotx,xPloty,'bx',oPlotx,oPloty,'ro')
#Plot the split line
w0 = ws[0][0]
w1 = ws[1][0]
x = linspace(1,8,100)
y = -(w0/w1)*x-b[0][0]/w1
pSplitPlot = plt.plot(x,y,'k',lw=1)
plt.show()
绘制线性可分支持向量机超平面,所用的数据集SVM.rar
dataArr,labelArr = loadDataSet('./SVM/testSet.txt')
# print(labelArr)
b,alphas = smoSimple(dataArr,labelArr,0.6,0.001,40)
ws = calcWs(alphas,dataArr,labelArr)
b = array(b)
plotData(dataArr,labelArr,ws,b)
支持向量机是一种分类器,称为“机”是因为它会产生一个二值决策结果,即决策“机”。支持向量机的泛化错误率较低,具有良好的学习能力,且学到的结果具有很好的推广性,这些优点使得支持向量机十分流行。John Platt引入了SMO算法,此算法可以通过每次优化两个alpha值来加快SVM的训练速度。
核方法或者说核技巧会将数据(有时是非线性数据),从一个低维空间映射到一个高维空间,可以将一个在低维空间中的非线性问题转换为高维空间下的线性问题来求解,核方法不仅在SVM中适用,还可以用于其他算法中。而其中的径向基函数是一个常用的度量两个方向距离的核函数。
常用的核函数
1、多项式核函数(polynomial kernel function)