python机器学习——SVM支持向量机
背景与原理:
支持向量机是一种用来解决分类问题的算法,其原理大致可理解为:对于所有维的数据点,我们希望能够找到一个维的直线(平面,超平面),使得在这个超平面一侧的点属于同一类,另一侧的点属于另一类。而我们在寻找这个超平面的时候,我们只需要找到最接近划分超平面的点,而一个维空间中的点等同于一个维向量,所以这些点就可以被称为支持向量。
在一个维空间中,一个超平面可以用表示,比如一条二维空间中的直线可以表示成,而一个三维空间中的平面可以表示成,以此类推。而维空间的一个超平面会把维空间中的点分成三部分:对一个维空间中的点和超平面,若,说明在超平面的一侧,而若,说明在超平面上,若,说明在超平面的另一侧,也就是说,当我们给定了一个超平面之后,空间中的所有点就自然被这个超平面分成了两类(如果忽略超平面上的点)
线性可分支持向量机:
首先我们考虑线性可分的点,即客观存在一个超平面,使得两类数据点分别分布在超平面的两侧,那么不难想见,这样的超平面有无穷多个,但为了模型的泛化性能,我们希望选取的超平面应该是位于两组数据集中间的(个人理解:考虑一种极端情况:这个超平面是贴着某一类的数据点经过的,那么在实际情况中,属于这类的数据点很可能有些稍微散布到了这条直线外,这样这个分类器的性能就不够好了,而如果位于中间,即使有些数据点相较于训练数据有些往外散布,也能较为正确地分类。)
那么由计算几何中的已知公式,我们可以看到:维空间中任意一个点到一个给定超平面的距离为,其中。而假设对于第组数据,其类别为,由于我们要根据数据点在超平面的哪一侧确定类别,因此我们实际是要求数据点的位置与数据点的类别相匹配,那么我们的类别也非常自然地选取1/-1,而是否匹配则可以由的正负性来度量,如果为正我们认为是相匹配的。
那么这个问题就变成了:对于一组数据,其中是维向量,我们要求一个维超平面,而如果令,那么我们要最大化,而约束条件则是(这个约束条件有点唬人:的取值只有1/-1,所以不影响左边这个东西的绝对值,而一定小于等于左边这个东西的绝对值,因此这个约束条件实际只约束了符号)
那么令(这并不影响超平面),这样就得到了约束条件:(对超平面的所有参数除以同一个值并不改变这个超平面,只是让约束条件更好看了)
而在这个约束条件下,我们可以看到,于是(由的定义立得),于是我们实际上要最大化的是,那么也就是最小化,而这不好求解,所以我们要求最小化(这些变化都是为了计算简便)
这样我们的问题就转化为了:在的条件下,最小化
那么这是个条件最值,我们应用拉格朗日乘子法,构造拉格朗日函数:
这个问题并不好求解,因为参数个数等于数据集大小了,因此我们考虑改进:设
那么可以看到,在所有的约束条件都成立时,后面要减掉的那一项一定非负,这样的话对于所有的,应该取对应的才能取得最大值,而最后能取得的最大值就是前面那项,于是此时的
而如果有某个约束条件不成立,后面要减掉的那一项是个负值,这样的话对应的越大,整个函数值越大,这样
这样的话我们如果我们想在所有约束条件成立的情况下最小化,我们实际上就是在最小化,即我们要进行的是这样的操作:
而可以证明,这个问题与其对偶问题:
是等价的,因此我们来解决这个对偶问题:首先我们对和求偏导:
这样我们直接代入,可得我们要进行的任务是:
这样实际就是
取个符号变成等价的问题:
这样最后的问题就确定了:我们要在非负的条件下最小化,求出最小的后我们就可以计算出:
同时一定存在一个(否则),那么对于这个,有:
代入上面求出的,即得到:
这里有一个逻辑:我们上文已经提到了,对于所有的,应该取对应的,也就是说只有才会产生非零的,而由于只能为1/-1,因此移项即得。
而这同样也启示我们:训练完成后,大部分样本都不需要保留,支持向量机只与处于边界位置的支持向量有关。
当然了,这并不是线性问题的结束,因为真实生活中,很难存在绝对线性可分的数据,大多数的数据在分割位置上是有交叉的,这样的话上面的理论模型就不好用了。
因此我们退一步,允许有一定的偏移,同时在损失函数中增加一个惩罚项,也即我们要最小化
其中表示一个分类错误的程度,而是惩罚系数,越大代表我们对分类错误的惩罚越大。
因此整个算法流程为:
(1)给定训练集,其中,选取惩罚参数
(2)最小化,约束条件是和(这个求解过程与无惩罚项的时候类似,这里不展开了)
(3),找到,对于这个,,得到超平面
(4)分类函数即为
非线性可分支持向量机:
在现实生活中,很多数据并不是线性可分的,比如二维空间按一个圆内和圆外对点进行分类,这显然不是一个线性可分的问题,那么对于这种问题我们的处理方法是将其映射到更高维度的空间中去,以期在更高维度的空间中其是线性可分的。
但是在上述讨论过程中我们可以看到,我们需要的其实并不是真正的高维空间中的点是什么,我们只需要计算出两个点之间的点积!
那么如果我们设函数把投影到高维空间,那我们只需要一个函数,这样的话我们就只需最小化
而不需要得知某个投影到高维空间中具体是什么了。
所以我们实际上要选取的是,这个又被称为核函数,常用的核函数有多项式核,高斯核和线性核(线性核存在的意义是统一了所有的支持向量机的形式,这样无论是什么问题我们都要选取一个核然后操作,而不用根据是否是线性可分选取不同的形式了)
因此所有的支持向量机的算法步骤为:
(1)给定训练集,其中,选取惩罚参数和核函数
(2)最小化,约束条件是和
(3)找到,对于这个,,得到超平面
(4)分类函数即为
代码实现:
import numpy as np import math import matplotlib.pyplot as plt from sklearn import svm x=np.arange(0.,10.,0.02) y=5-2*x/3+np.random.randn(500) now=0 dataset=[] for i in range(0,500): typ = -1 if 2*x[i]+3*y[i] <= 15: if abs(np.random.randn(1)[0])<2: typ = 1 else: typ = -1 else: if abs(np.random.randn(1)[0]) < 2: typ = -1 else: typ = 1 dataset.append([x[i],y[i],typ]) X=(np.array(dataset)[:,0:2]) Y=(np.array(dataset)[:,2]) model=svm.SVC(C=1.0,kernel='linear').fit(X,Y) for i in range(0,500): if Y[i]==1: plt.scatter(X[i,0],X[i,1],c='r') else: plt.scatter(X[i,0],X[i,1],c='b') w=model.coef_ b=model.intercept_ plt.plot(X[:,0],-(w[0][0]/w[0][1])*X[:,0]-b[0]/w[0][1],c='g',linewidth=3) plt.show()
支持向量机的代码不好实现,这里直接调了库,要分类的数据和之前逻辑回归是的是一样的,分类效果如下:
可以看到分类效果还是很不错的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY