8 支持向量机
8.1 原理
8.1.1 线性可分与线性不可分
- 在左边的图,我们可以用一条直线区分不同的两类事件;叫做线性可分;
- 在右边的图,我们找不到一条直线区分不同的两类事件;叫做线性不可分。
在线性不可分的情形下,我们可以将它投射到三维空间不同高度达到线性可分。
8.1.2 支持向量机原理
在2维空间中
代码语言:javascript复制y=kx b:为一条直线
y1=kx b t
y2=kx b-t
为两条平行,位于y两侧,与y距离相等的两条直线,我们如果可以通过一种算法把需要进行二分法的事件映射到y1上侧与y2下侧,就达到二分类目的了。
在3维空间中
代码语言:javascript复制z=kx b:为一个直面
z1=kx b t
z2=kx b-t
为两个直面,位于z两侧,与z距离相等的两个直面,我们如果可以通过一种算法把需要进行二分法的事件映射到z1上侧与z2下侧,就达到二分类目的了。
同样在n维空间中
代码语言:javascript复制xn=kx1 b:为一个直n-1维空间中
xn1=kx1 b t
xn2=kx1 b-t
为两个直n-1维空间中,位于xn两侧,与xn距离相等的两个n-1维空间,我们如果可以通过一种算法把需要进行二分法的事件映射到xn 1上侧与xn 2下侧,就达到二分类目的了。
8.1.3 支持向量机原理的代码实验
下面我们来用2维情形,通过代码来实现支持向量机原理。
代码语言:javascript复制def svm_base():
myutil = util()
PI = 3.1415926
x = np.linspace(0,50,100)
y = 0 * x
y0 = 0 * x
y1 = y 20
y2 = y - 20
plt.plot(x,y,c='black',linestyle='dashdot')
plt.plot(x,y0,c='black')
plt.plot(x,y1,c='green')
plt.plot(x,y2,c='green')
a = np.random.random([50,1])*50
c = np.random.random([50]).reshape(-1,1)
b =np.array([[0 for col in range(2)] for row in range(50)])
for i in range(50):
b[i][0] = int(a[i])
b[i][1] = 0
if int(a[i]) % 2 ==0:
c[i] = 0
else:
c[i] = 1
plt.scatter(b[:,0],b[:,1],c=c,cmap=plt.cm.spring,s=30)
title = u"一维空间内的奇偶数是不可以进行线性分割的"
myutil.show_pic(title)
#################################################
# 分离
x = np.linspace(0,50,100)
y = 0 * x
y0 = 0 * x
y1 = y 20
y2 = y - 20
plt.plot(x,y,c='black')
plt.plot(x,y0,c='black',linestyle='dashdot')
plt.plot(x,y1,c='green')
plt.plot(x,y2,c='green')
for i in range(50):
if c[i] == 0:
b[i][1] = 20 random.randint(0,40)
else:
b[i][1] = -20-random.randint(0,40)
plt.scatter(b[:,0],b[:,1],c=c,cmap=plt.cm.spring,s=30)
title = u"分离到二维空间中可以进行线性分割的"
myutil.show_pic(title)
############################################
# 旋转
for i in range(50):
x = b[i][0]
y = b[i][1]
b[i][0] = x*math.cos(PI/4) - y*math.sin(PI/4)
b[i][1] = x*math.sin(PI/4) y*math.cos(PI/4)
plt.scatter(b[:,0],b[:,1],c=c,cmap=plt.cm.spring,s=30)
x = np.linspace(min(b[:,0])-5,max(b[:,0]) 5,100)
yx = np.linspace(-60,100,100)
xx = np.linspace(0,0,100)
y = x
y0 = 0 * x
y1 = x 20
y2 = x - 20
plt.plot(x,y,c='black')
plt.plot(x,y0,c='black',linestyle='dashdot') # X轴
plt.plot(xx,yx,c='black',linestyle='dashdot')# Y轴
plt.plot(x,y1,c='green')
plt.plot(x,y2,c='green')
title = u"为了更普遍性,进行旋转"
myutil.show_pic(title)
##########################################
# 移动
for i in range(50):
y = b[i][1]
b[i][1] = y 40
plt.scatter(b[:,0],b[:,1],c=c,cmap=plt.cm.spring,s=30)
x = np.linspace(min(b[:,0])-5,max(b[:,0]) 5,100)
yx = np.linspace(-20,140,100)
xx = np.linspace(0,0,100)
y = x 40
y0 = 0 * x
y1 = x 20 40
y2 = x - 20 40
plt.plot(x,y,c='black')
plt.plot(x,y0,c='black',linestyle='dashdot') # X轴
plt.plot(xx,yx,c='black',linestyle='dashdot')# Y轴
plt.plot(x,y1,c='green')
plt.plot(x,y2,c='green')
title = u"进一步更普遍性,进行平移"
myutil.show_pic(title)
8.1.4 支持向量机的分类
最大边界超平面: Maximum Margin Separating Hyperplane。中间这条线到和所有支持向量的距离都是最大的。
离这个超平面最近的点就是"支持向量",点到超平面的距离叫做间隔,支持向量机的意思就是使超平面和支持向量之间的间隔尽可能的大。
支持向量机分为:
- SVM=Support Vector Machine:支持向量机
- SVC=Support Vector Classification :支持向量机用于分类
- SVR=Support Vector Regression :支持向量机用于回归分析
SVC与SVR又分为线性向量机分类算法LinearSVC与LinearSVR
下表为sklearn中支持SVC、SVR、LinearSVC与LinearSVR用到的类。
方法 | 解释 |
---|---|
sklearn.svm.SVC | 支持向量机分类算法 |
sklearn.svm.SVR | 支持向量机回归算法 |
sklearn.svm.LinearSVC | 线性向量机分类算法 |
sklearn.svm.LinearSVR | 线性向量机回归算法 |
8.1.5 支持向量机的核
支持向量机还有一个很重要的概念:核
代码语言:javascript复制def sigmoid(x):
return 1. / (1 np.exp(-x))
def kernel():
myutil = util()
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(-40, 40, 100)
y = np.linspace(-40, 40, 100)
z = x*y 40
ax.plot(x, y, z, label=u"线性核")
ax.legend()
title = u"线性核"
myutil.show_pic(title)
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(-40, 40, 100)
y = np.linspace(-40, 40, 100)
z = (5*x*y 4)**3
ax.plot(x, y, z, label=u"多项式核")
ax.legend()
title = u"多项式核"
myutil.show_pic(title)
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(-40, 40, 100)
y = np.linspace(-40, 40, 100)
z = sigmoid(5*x*y 4)
ax.plot(x, y, z, label=u"Sigmoid核")
ax.legend()
title = u"Sigmoid核"
myutil.show_pic(title)
包括线性核、多项核和和Sigmoid核。
1.线性核(Linear Kernel)
线性核,主要用于线性可分的情况,我们可以看到特征空间到输入空间的维度是一样的,在原始空间中寻找最优线性分类器,具有参数少速度快的优势。对于线性可分数据,其分类效果很理想,因此我们通常首先尝试用线性核函数来做分类,看看效果如何,如果不行再换别的。
2.多项式核(Polynomial Kernel)
多项式核函数可以实现将低维的输入空间映射到高纬的特征空间多项式核适合于正交归一化(向量正交且模为1)数据。属于全局核函数,允许相距很远的数据点对核函数的值有影响。参数d越大,映射的维度越高,计算量就会越大。但是多项式核函数的参数多,当多项式的阶数d比较高的时候,由于学习复杂性也会过高,易出现“过拟合"现象,核矩阵的元素值将趋于无穷大或者无穷小,计算复杂度会大到无法计算。
3,Sigmoid核(Sigmoid Kernel)
Sigmoid核函数来源于神经网络,被广泛用于深度学习和机器学习中
采用Sigmoid函数作为核函数时,支持向量机实现的就是一种多层感知器神经网络。
还有径向基核函数(Radial Basis Function)/ 高斯核(Gaussian Kernel)、字符串核函数、傅立叶核和样条核。