1.间隔与支持向量
给定训练样本集D={(x1,y1),(x2,y2),...,(x4,y4)},yi属于{-1,1}。分类学习的最基本的想法就是基于训练集D在样本空间中找到一个划分的超平面,能将不同的类别的样本分开。但是能将训练样本分开的超平面可能有很多个如下图,我们的目标就是尽可能找到最好的划分超平面。
直观上来说应该去找位于两类训练样本正中间的划分超平面,如上面最右的那张图,因为该划分超平面对训练样本局部扰动性的容忍性最好。例如,由于训练集的局限性或者噪声的影响,在上面最左的图中,假设有个样本点×落在左下角那个×的附近,由于这个×样本可能会落在超平面另一侧,故该超平面会把这个×误分类成○。而最右的图受到的影响最小。换而言之,最右的这个划分超平面所产生的分类结果是最鲁棒的,对未见示例的泛化能力最强。
在样本空间中,划分超平面可以通过如下线性方程来描述:
其中w=(w1;w2;...wd)为法向量,决定了超平面的方向;b为位移项,决定了超平面与原点之间的距离。所以划分超平面可被法向量w和位移b确定,下面我们将其记为(w,b),利用点到平面的距离公式,得到样本空间中的任意点x到超平面之间的距离为
假设超平面能将训练样本正确分类,即对于所有在D中的样本点,(xi,yi)∈D,若yi=+1则有
若yi=-1则有
令
如下图所示距离超平面最近的这几个训练点使得上面的式子成立,它们被称为支持向量(support vector),两个异类支持向量到超平面的距离之和为
它被称为间隔
欲找到最大间隔的划分超平面,也就是要找到能满足 上式中约束的参数w和b,使得γ最大,即:
显然,为了最大化间隔,仅需要最大化
这等价于最小化
于是约束式子可重写为
这就是支持向量机(Support Vector Machine,简称SVM)的基本型。
2.对偶问题
我们希望求解下面的式子来得到大间隔的划分超平面所对应的模型
其中w和b是模型参数。对SVM的基本型中的每个约束移项再添加拉格朗日乘子αi≥0,最后累加得到该问题的拉格朗日函数为
令L(w,b,α)对w和b的偏导为0可得:
将得到的这两个式子代入到L(w,b,α)中即可把w和b消去就得到了SVM基本型的对偶问题
3.软间隔和正规化
在前面的讨论中,我们一直假定训练样本在样本空间或者特征空间都是线性可分,即存在一个超平面能将不同类的样本完全划分开。然而在现实任务中往往很难确定合适的核函数使得训练样本在特征空间中线性可分。即便恰好找到了某个核函数使得训练集在特征空间中线性可分,也很难断定这个线性可分的结果不是由于过拟合所造成的
解决该问题的一个办法是允许支持向量在一些样本上出错,所以就有了软间隔的概念,如下图所示:
软间隔是允许某些样本不满足约束
当然在最大化间隔的同时,不满足约束的样本应尽可能少,于是优化目标函数可写为
其中C为常数,l 0/1是“0/1损失函数”
显然当C无穷大时,优化目标函数使得所有样本均满足约束,当C取有限值时,优化目标函数允许一些样本不满足约束。
然而01损失函数非凸非连续,数学性质不太好使得优化目标函数不容易求解。于是人们一般使用替代损失函数,这类函数一般具有较好的数学性质,如它们通常是凸的连续函数且是01损失函数的上界。下图给出了三种常用的替代损失函数
引入松弛变量ξi 于是优化目标函数可以重写为
这就是常用的“软间隔支持向量机”
参考代码
import numpy as np
import pylab as pl
from sklearn import svm
np.random.seed(0)
X = np.r_[np.random.randn(20,2)-[2,2],np.random.randn(20,2)+[2,2]]
Y = [0] * 20+[1] * 20
clf=svm.SVC(kernel='linear')
clf.fit(X,Y)
w=clf.coef_[0]
a=-w[0]/w[1]
xx=np.linspace(-5,5)
yy=a*xx-(clf.intercept_[0])/w[1]
b=clf.support_vectors_[0]
yy_down=a*xx+(b[1]-a*b[0])
b=clf.support_vectors_[-1]
yy_up=a*xx+(b[1]-a*b[0])
print("w:",w)
print("a:",a)
print("suport_vectors_:",clf.support_vectors_)
print("clf.coef_:",clf.coef_)
pl.plot(xx,yy,'k-')
pl.plot(xx,yy_down,'k--')
pl.plot(xx,yy_up,'k--')
pl.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,0],s=80,facecolors='none')
pl.scatter(X[:,0],X[:,1],c=Y,cmap=pl.cm.Paired)
pl.axis('tight')
pl.show()
实验结果
总结
使用SVM时,数据线性情况分成线性可分和线性不可分,在线性可分情形下:可以问题转化为一个凸优化问题,然后用格朗日乘子法简化,最后用SMO算法解决。不可分情形下:通过引入松弛变量和替代损失函数,把问题转化为一个凸优化问题,然后用格朗日乘子法简化,最后用SMO算法解决。