机器学习 jupyter Python 有监督学习 SVM算法

前言-小故事

SVM的英文全称是Support Vector Machines,我们叫它支持向量机。支持向量机是我们用于分类的一种算法。让我们以一个小故事的形式,开启我们的SVM之旅吧。
在很久以前的情人节,一位大侠要去救他的爱人,但天空中的魔鬼和他玩了一个游戏。魔鬼在桌子上似乎有规律放了两种颜色的球,说:"你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。
在这里插入图片描述
于是大侠这样放,干的不错!
在这里插入图片描述
然后魔鬼,又在桌上放了更多的球,似乎有一个球站错了阵营。显然,大侠需要对棍做出调整。
在这里插入图片描述
SVM就是试图把棍放在最佳位置,好让在棍的两边有尽可能大的间隙。这个间隙就是球到棍的距离。
在这里插入图片描述
现在好了,即使魔鬼放了更多的球,棍仍然是一个好的分界线。
在这里插入图片描述
魔鬼看到大侠已经学会了一个trick(方法、招式),于是魔鬼给了大侠一个新的挑战。(线性不可分)
在这里插入图片描述
现在,大侠没有棍可以很好帮他分开两种球了,现在怎么办呢?当然像所有武侠片中一样大侠桌子一拍,球飞到空中。然后,凭借大侠的轻功,大侠抓起一张纸,插到了两种球的中间。(低维空间中线性不可分的转化到高维空间)
在这里插入图片描述
现在,从空中的魔鬼的角度看这些球,这些球看起来像是被一条曲线分开了。
在这里插入图片描述

总结:

1.球就是样本点
2.棍子就是决策边界
3.拍桌子是核函数
4.纸就是超平面

一、SVM初识-线性可分

1.决策边界

SVM分类也是寻找合适的决策边界,为方便理解,以二分类为例。假设存在二分类样本,我们一定可以找到一个超平面将类别分开,但是通常会存在很多这样的超平面,如下图所示,那么到底取哪个?
注:在平面上找决策边界,在三维立体找平面,三维以上找超平面
在这里插入图片描述
直观来看,应该取H3那条红线,因为这条线对样本的“容忍性”最好,也就是说样本发生微小变化,不会影响分类结果,但是其他细线,如果样本发生微小变化,都会使得分类结果发生变化,也就是说H3作为决策边界,其鲁棒性最好。

2.边际

SVM寻找区分两个类别的超平面,使得边际最大化。
边际:b11和b12之间的距离,叫做B这条决策边界的边际(margin),也有叫“间隔”,记为d,当然也有把b11和B1的距离叫边际的.显然拥有更大的边际的决策边界泛化能力更强,边际就是与决策边界平行且与最近两旁样本点的切线!
在这里插入图片描述

3.支持向量

支持向量:与b11和b12相交的样本点叫支持向量(距离分类超平面最近的样本点,每个类别都有支持向量),如上图。
支持向量就是在在策边界的方程上的样本点。

3.1向量内积

在这里插入图片描述

4.决策边界的方程

在这里插入图片描述
为什么总是1或-1呢?
在这里插入图片描述

在这里插入图片描述
此时,寻找样本点到决策边界的最近近距离转化为凸优化问题。

5.凸优化问题

5.1转化过程

在这里插入图片描述

5.2凸优化问题原理(不做深入)

在这里插入图片描述
在这里插入图片描述

6.具体案列

6.1画出样本点的散点图

在这里插入图片描述

6.2利用SVM算法找到一个分类的超平面

6.2.1定义模型

from sklearn import svm
#1.定义模型
model=svm.SVC(kernel='linear')
#model=svm.SVR  regssion(回归)  class(分类)

6.2.2训练模型

model.fit(x_data,y_data)

6.2.3打印支持向量机相关信息

print('支持向量的坐标:',model.support_vectors_)#支持向量的坐标
print('支持向量的样本点的索引值:',model.support_)#支持向量的样本点的索引值
print('每个类别有几个支持向量:',model.n_support_)#每个类别有几个支持向量

运行结果:
在这里插入图片描述

6.2.4 画出分类超平面和支持向量的分界线,算出其相关系数

print('分类超平面的系数',model.coef_)#分类超平面的系数
print('分类超平面的截距',model.intercept_)#分类超平面的截距
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
x=np.array([[0],[150]])
y=(-model.intercept_-x*model.coef_[0][0])/model.coef_[0][1]
plot()
plt.plot(x,y,c='k',label='分类超平面')

其中,
在这里插入图片描述

y_down=(-model.intercept_+1-x*model.coef_[0][0])/model.coef_[0][1]
y_up=(-model.intercept_-1-x*model.coef_[0][0])/model.coef_[0][1]
plt.plot(x,y_down,'b--',linewidth=0.5)
plt.plot(x,y_up,'r--',linewidth=0.5)
plt.legend()
print(model.score(x_data,y_data))

其中,
在这里插入图片描述
运行结果:
在这里插入图片描述

二、非线性-SVM

2.1非线性情况

在实际分类当中,我们会遇到非线性的情况。例如如下图所示
原先在一维空间中我们不可能画一个直线或者一个平面将样本点分类,通过转化到二维空间就变得线性可分。
在这里插入图片描述
总结:样本点在低维空间中线性不可分,通过将低维空间的非线性问题映射到高维空间中,就变成线性可分的。
接下来,我们再来看一个例子。如下图所示,样本点原先在二维空间中找不到一个直线将其分类(非线性情况),通过映射到三维空间。我们就可以很容易找到一个平面将其分隔开(线性情况),也就是大侠拍桌子。
在这里插入图片描述
在这里插入图片描述

2.2低维数据升级到高维数据的数学原理(了解)

为什么低维数据升级到高维数据之后,就可以把低维度数据线性可分?
在提升维度后,原本非线性的数据点变得线性可分,这在数学上是有严格证明的,即Cover定理。
Cover定理可以定性地描述为:将复杂的模式分类问题非线性地投射到高维空间将比投射到低维空间更可能是线性可分的,当空间的维数D越大时,在该空间的N个数据点间的线性可分的概率就越大。
所以人们就努力的寻找一种映射,这映射能将样本从原始空间(低维数据)转变到高维特征空间,从而把低维空间中线性不可分的两类点变成线性可分的。这种映射ϕ(X) 又可称为“特征构建”,映射后的向量可称之为“特征向量”。

2.3映射问题

在这里插入图片描述
将原先的数据映射到高维空间会出现的问题:
1.维度灾难:
红色的地方是要使用映射后的样本向量做内积,假设原先的特征是n维,现在把它映射到n^2维 。这样就会产生维灾难,高维空间计算量比较大,计算内积是不现实的。
2.线性不可分:
选取的某些非线性映射虽然将低维度映射到高纬度,但是发现仍然是线性不可分。那么如何选取合理的非线性转化。

2.3核函数

2.3.1核函数的定义和作用

幸运的是,在计算中发现,我们需要的只是两个向量在新的映射空间中的内积结果,而映射函数到底是怎么样的其实并不需要知道。于是这样就引入了核函数的概念。
核函数事先在低维上计算,而将实质上的分类效果表现在了高维上,也就是包含映射,内积,相似度的逻辑。消除掉把低维向量往高维映射的过程。避免了直接在高维空间内的复杂计算。
即核函数除了能够完成特征映射,而且还能把特征映射之后的内积结果直接返回针对于刚刚提到的2个问题,我们可以通过构造核函数来解决这个问题。
核函数的特点:我们可以通过构造核函数使得运算结果等同于非线性映射,同时运算量要远远小于非线性映射。核函数是低维转换为高维的工具。

函数Kernel(x,y)是一个关于x和y的函数!而与φ无关!这是一个多么好的性质!我们再也不用管φ具体是什么映射关系了,只需要最后计算Kernel(x,y)就可以得到他们在高维空间中的内积

2.3.1常见的核函数

线性核函数(在二维平面上用):
在这里插入图片描述
多项式核函数:
在这里插入图片描述
高斯径向基核函数(RBF):
在这里插入图片描述
该核函数(RBF)是应用最广的一个,无论大样本还是小样本都有比较好的性能,而且其相对于多项式核函数参数要少,因此大多数情况下在不知道用什么核函数的时候,优先使用高斯核函数.。
关于RBF函数参数gamma的选取:
Gamma值选的过大,带高斯核的SVM可以模拟任何非线性数据。存在训练准确率很高,但是测试准确率不高的可能,即过拟合。 Gamma值选的过小,无法在测试集上得到特别高的准确率,也会影响测试集的准确率。
S型核函数:
在这里插入图片描述

2.4具体例子

2.4.1读取数据,画出散点图

部分样本点:
在这里插入图片描述
在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt
#读取数据
dataSet = np.genfromtxt('ex2data2.txt',delimiter=',')
# print(dataSet)
# x1 = dataSet[:,2]
x_data = dataSet[:,:-1]
y_data = dataSet[:,-1]
def plot():
    plt.scatter(x_data[y_data==0,0],x_data[y_data==0,1],c='r',marker='*',label='label0')
    plt.scatter(x_data[y_data==1,0],x_data[y_data==1,1],c='b',marker='^',label='label1')
    plt.legend()
plot()
plt.show()

运行结果:
在这里插入图片描述

2.4.2引入SVM分类器

#引入SVM分类器
from sklearn import svm
#C代表对错误样本点的惩罚力度,C越大,代表惩罚越厉害
model = svm.SVC(kernel='rbf',C=10000)
# model = svm.SVC(kernel='rbf')
model.fit(x_data,y_data)
model.score(x_data,y_data)
# print(model.predict(x_data))
#gamma=1/2𝜎^2设的太大,𝜎会很小,高斯分布长得又高又瘦,会造成只会作用于支持向量样本附近,
#对于未知样本分类效果很差,存在训练准确率可以很高,
#(如果让无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合

运行结果:
在这里插入图片描述

2.4.3决策边界可视化

#可视化
'''
决策边界可视化
'''
#获取数据所在的范围
x_min,x_max = x_data[:,0].min()-1,x_data[:,0].max()+1
y_min,y_max = x_data[:,1].min()-1,x_data[:,1].max()+1

#利用meshgrid获取网格矩阵
#arange(start, end, step),与range()类似,也不含终止值。但是返回一个array对象
xx,yy = np.meshgrid(np.arange(x_min,x_max,0.02), 
                   np.arange(y_min,y_max,0.02))
# print('分割横坐标',np.arange(x_min,x_max,0.02))
# print('xx',xx)
# print('yy',yy.shape)
'''
np.r_按行进行组合array(上下)
np.c_按列进行组合(左右)
例如:
a = np.array([1,2,3])
b = np.array([5,2,5])
np.r_[a,b]
array([1, 2, 3, 5, 2, 5])
np.c_[a,b]
array([[1, 5],
       [2, 2],
       [3, 5]])
'''

x_new = np.c_[xx.ravel(),yy.ravel()]#reval将数据进行扁平化,将多维数据转化为1维
print(type(x_new))
z = model.predict(x_new)
# print(len(z))
z = z.reshape(xx.shape)#转化数组
#画出等高线图
cs = plt.contourf(xx,yy,z)#z代表高度,高度不一样显示的颜色也不一样
plot()
plt.show()

运行结果:
在这里插入图片描述

三、线性不可分

3.1线性不可分问题的描述

在这里插入图片描述
SVM的基本形态是一个硬间隔分类器,它要求所有样本都满足硬间隔约束(即函数间隔要大于1),所以当数据集有噪声点时,SVM为了把噪声点也划分正确,超平面就会向另外一个类的样本靠拢,这就使得划分超平面的几何间距变小,降低模型的泛化性能。除此之外,当噪声点混入另外一个类时,对于硬间隔分类器而言,这就变成了一个线性不可分的问题。

3.2硬间隔,软间隔

硬间隔:完全分类准确,其损失值为0;只要找出两个异类正中间的那个平面;硬间隔的分类法其结果容易受少数点的控制,这是很危险的。
软间隔:允许一定量的样本分类错误。

3.3松弛变量和惩罚系数

在某些情况下,样本不是线性可分的,存在一些干扰的数据。如图存在一个红色的样本点和一个蓝色样本点分类错误的情况,但是出现分错的这些样本点是极个别的情况。
针对这种情况我们引入了松弛变量和惩罚系数。
在这里插入图片描述

3.3.1松弛变量和惩罚系数

在这里插入图片描述
分类标准:
在这里插入图片描述
目标函数:
在这里插入图片描述
线性不可分,通过引入松弛变量和惩罚因子:
在这里插入图片描述
这个式子有这么几点要注意:
(1)并非所有的样本点都有一个松弛变量与其对应。实际上只有“离群点”才有,或者也可以这么看,所有没离群的点松弛变量都等于0(对负类来说,离群点就是在前面图中,跑到H2右侧的那些负样本点,对正类来说,就是跑到H1左侧的那些正样本点)。
(2)松弛变量的值实际上标示出了对应的点到底离群有多远,值越大,点就越远。
(3)惩罚因子C决定了你有多重视离群点带来的损失,显然当所有离群点的松弛变量的和一定时,你定的C越大,对目标函数的损失也越大,此时就暗示着你非常不愿意放弃这些离群点,最极端的情况是你把C定为无限大,这样只要稍有一个点离群,目标函数的值马上变成无限大,马上让问题变成无解,这就退化成了硬间隔问题。
(4)惩罚因子C不是一个变量,整个优化问题在解的时候,C是一个你必须事先指定的值

引入松弛变量之后,目标函数转化为:
在这里插入图片描述
总结:
其实两者还有微妙的不同。一般的过程应该是这样,还以文本分类为例。在原始的低维空间中,样本线性的不可分,无论你怎么找分类平面,总会有大量的离群点,此时用核函数向高维空间映射一下,虽然结果仍然是不可分的,但比原始空间里的要更加接近线性可分的状态(就是达到了近似线性可分的状态),此时再用松弛变量处理那些少数“冥顽不化”的离群点,就简单有效得多了。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值