支持向量机初步学习
来源:互联网 发布:linux修改用户名及密码 编辑:程序博客网 时间:2024/05/22 23:05
前言
svm需要一定的数学功底,我是亦步亦趋花了一个星期,才渐渐有所了解。出于学习交流目的,我将自己的学习思路整理出来。由于对svm的理解有所不足,如有错误,敬请指正。
svm简介
支持向量机(support vertor machines,SVM)是一种二分类模型。它的基本模型是定义在特征空间上的最大间隔分类器,核技巧使它称为线性分类器。支持向量机的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失最小化问题。支持向量机的学习算法是求解凸二次规划的最优化算法。
最大间隔的分类器
ok,让我们从最简单的线性分类说起,如图:
在一个平面上有两类点,中间的实线表示一个分类器。我们知道,空间中的一个(超)平面(在二维是直线)可以表示为
我们不妨设所有满足f(x)>0的点其y等于1,而f(x)<0的点其y等于-1(至于为什么是1和-1,读者如果感兴趣,可自行查阅相关资料)。当超平面的方程给定后,我们就可以将需要预测的点带入方程,如果得到的值大于0,则分到正类(y=1),如果得到的值小于0,则分到负类(y=-1)。那么,现在剩下的问题就是,怎样确保我们的超平面是分类效果最好的?svm利用间隔最大化求最优超平面。
一般而言,一个点距离超平面的远近可以表示匪类的准确度。在超平面 w*x+b 确定的情况下|w*x+b|可以表示点x距离超平面距离的远近,而标号y可以表示正确。所以,我们用
对于给定训练集T和超平面(w,b),定义超平面关于样本点
(xi,yi) 的函数间隔为
γi^=yi(w∗xi+b)
定义超平面(w,b)关于训练集T的函数间隔为所有样本点函数间隔的最小值即
γ^=mini=1,2...Nγi^
函数间隔虽然可以表示分类,但是如果成比例的改变w和b,函数间隔就会成比例的变化,由此我们引入几何间隔。
γ=γ^||w||
几何距离就是点到超平面的距离
用几何距离来表示间隔显然要比函数间隔好。那么,我们的目的就是使几何距离最大化,即
当然,还有个附加条件
其中
通过求解上面这个问题,我们就可以得到图中超平面的方程。
什么是支持向量?
从图中可以看出,两个支撑着中间间隙的超平面,它们到中间分类超平面的距离相等,即几何间隔γ ,而支撑这两个超平面的点便叫做支持向量。
从原本是问题到对偶问题
之前我们要求解式(2),由于对
到了这一步,可以看出来这是一个二次凸优化问题。由于其特殊结构我们可以通过Lagrange对偶变换来求解出问题。
下面对Lagrange对偶性的进行简单的解释
假定
引入广义拉格朗日函数
这里
然后代入在我们的问题中,有
然后令
则问题转化为
在满足KKT条件的情况下(KKT条件略,但是可证明,我们这个问题是满足KKT条件的),该问题转换为
求解对偶问题
于是接下来我们的任务就是:(1)固定
第一步 先固定
将结果代入式(6)得
第二步 由于有了式(11),问题转化为
要对
用松弛变量处理离群点
在讨论SMO算法之前,我们先说说另一个问题————离群点的处理。我们起初的假设是数据都是线性可分的,假如我们的数据中存在离群点,原有的模型会受到很大的影响,如下图
用黑色圈出来的蓝色点就是一个离群点。如果没有这个点,我们的模型会得到红色实线所示的分类器。但是由于有了这个点,现在得到的分类器会是如虚线所示,显然这个分类器的间隔比之前分类器的间隔要小。要是该离群点还往上一点,我们甚至无法利用我们的模型来构造分类超平面。
为了解决离群点问题,svm在一定程度上可以支持离群点。如上图,将离群点移动到蓝色实线所示的支持平面上,超平面就不会改变了。为此,我们引入了松弛变量
现在有了离群点,约束条件变为
其中C是控制目标函数中2项的权重的参数。然后我们按照之前的步骤对式(12)求偏导,回代,会得到一个和原来一样的目标函数(巧合?)不过由于我们有
SMO算法
到这一步,我们有了式(13)-(15),我们现在来看一看SMO是怎样求解的。
首先,更具KKT条件得出
记
- 式(16)表示分类正常,点在边界内部。
- 式(17)表示点在边界上。
- 式(18)表示点在边界之间。
以下情况会出现不满足:
在引入松弛变量后,上述不满足条件变为
记
我们要将所有不满足条件的
假定需要更新某两个
利用上式,我们可以得到
其中$$\eta = 2*
其中,H和L分别为
然后就有
而关于
1.扫描所有
2.在不违反KKT的乘子中,选取使得
然后,可计算出b
其中,
这样,一次迭代后我们就更新了
最后代码
##SVMimport numpy as np;def load(filename): fr = open(filename); data=[];label=[]; for line in fr.readlines(): lineArr = line.strip().split('\t'); data.append([float(lineArr[0]),float(lineArr[1])]); label.append(float(lineArr[2])); return data,label;#简化版选择alpha_jdef Salphaj(i,m): j = i; while(j==i): j = np.random.uniform(i,m); return int(j);#规范化alpha_jdef clip(aj,H,L): if(aj>=H): aj=H; elif(aj<=L) : aj=L; return aj;def antiKKT(alphai,ui,yi,toler,C): if(yi*ui < -toler and alphai<C or yi*ui > toler and alphai>0 ): return True; return False;def LH(alphai,alphaj,a,C): if(a): return max(0,alphai+alphaj-C),min(C,alphai+alphaj); else: return max(0,alphaj-alphai),min(C,C+alphaj-alphaj);#X:数据 numpy数组格式#Y:标签 numpy数组格式#alpha 参数,numpy数组格式#C:参数 实数def SMO(X,Y,C,toler,max): X = np.mat(X); Y = np.mat(Y).T; m,n = np.shape(X); alpha = np.mat(np.zeros((m,1))); b=0; iter = 0; while(iter<max): change = 0; for i in range(m): xi=X[i,:] yi=Y[i,:] ui = np.multiply(alpha,Y).T*(X*xi.T)+b; ei = float(ui)-float(yi); alphai = alpha[i].copy(); #alphai满足KKT就跳过,选择下一个alphai。否则,选择alphaj进行优化 if(antiKKT(alphai,ei,yi,toler,C)): j = Salphaj(i,m); alphaj = alpha[j].copy(); xj = X[j,:]; yj= Y[j,:]; uj = np.multiply(alpha,Y).T*(X*xj.T)+b; ej = float(uj)-float(yj); L,H = LH(alphai,alphaj,yi==yj,C); if L==H: continue; eta = 2*(xi*xj.T)-(xi*xi.T)-(xj*xj.T); if eta >= 0: continue; alpha[j] = alphaj - yj*(ei-ej)/eta; alpha[j] = clip(alpha[j],H,L); if(abs(alpha[j]-alphaj)<0.00001):continue; alpha[i] = alphai+yi*yj*(alphaj-alpha[j]); b1=b-ei-yi*(alpha[i]-alphai)*(xi*xi.T)-yj*(alpha[j]-alphaj)*(xi*xj.T); b2=b-ej-yi*(alpha[i]-alphai)*(xi*xi.T)-yj*(alpha[j]-alphaj)*(xj*xj.T); if(alpha[i]>0 and alpha[i]<C): b = b1; elif((alpha[j]>0 and alpha[j]<C)): b= b2; else: b = (b1+b2)/2.0; change = change+1; if(change == 0) :iter += 1; else:iter=0; return alpha,b##可视化### x特征矩阵,numpy数组格式### y类标签,numpy数组格式def plotFit(x,y,alpha,b): import matplotlib.pyplot as plt; x1=[]; y1=[]; #类别为1的点 x2=[]; y2=[]; m = np.shape(x)[0]; for i in range(m): if(y[i]==-1) : x1.append(x[i][0]); y1.append(x[i][1]); else: x2.append(x[i][0]); y2.append(x[i][1]); plt.scatter(x1,y1,c='red'); plt.scatter(x2,y2); a=np.arange(2.0,8.0,0.1); x=np.mat(x); y=np.mat(y).T; w= sum(np.multiply(np.multiply(alpha,y),x)); w0 =w[0,0]; w1 = w[0,1]; b0 = b; y = (-w0*a - b[0,0])/w1; plt.plot(a,y); plt.show(); plt.figure(2);data,label = load('testSet.txt');alpha,b = SMO(data,label,0.6,0.001,40);print(alpha[alpha>0]);print(b)plotFit(data,label,alpha,b)
下载在这:github地址
总结
可以看到,svm的思路非常清晰,首先建模利用间隔最大对点进行分类,然后 由此引出求最大间隔超平面的问题,进而将问题转换为求解凸二次规划的问题,引入拉格朗日乘子,在这里,为了处理离群点,引入了松弛变量,然后利用SMO求解该问题,即求得最优超平面。整个一气呵成,充分展现的数学之美。还要说的一点是,我只介绍了svm对线性可分的点进行分类,实际上,对于线性不可分的点,svm在引入核方法之后,也能有很好的性能。可以说核方法才是svm的精髓,大家有兴趣可以去深入学习。
参考资料:支持向量机通俗导论
- 支持向量机初步学习
- 支持向量机学习
- 支持向量机学习
- 支持向量机 学习1
- 支持向量机学习2
- 支持向量机学习3
- 支持向量机SVM学习
- 机器学习-支持向量机
- 机器学习--支持向量机
- 机器学习-支持向量机
- 支持向量机学习笔记
- 20170106 学习支持向量机
- 支持向量机学习笔记
- 【机器学习】支持向量机
- 机器学习-支持向量机
- 机器学习-学习笔记 支持向量机
- 机器学习作业-支持向量机简介
- 机器学习之支持向量机
- C++考前复习——继承构造的顺序
- Java的一些小问题
- 使用Genymotion出现的问题
- 内地孕妇妈妈预约香港诊所验血测性别,注意这些小细节
- Linux 开机 启动 服务
- 支持向量机初步学习
- Kernel编译和链接中的linker script语法详解
- porting android for FreeSkyle imx6 sabre-6q sd-card & nfs
- 卡尔曼滤波 -- 从推导到应用(一)
- css优先级计算法则
- JSP三大指令,九大内置对象,JSP动作标签,EL表达式与函数库
- 手游-放开那三国socket协议分析
- IOS openURL 运行其他的应用程序
- 安卓应用正版盗版识别