SVM基本概念及Python实现代码
SVM(support vector machine)⽀持向量机:
线性分类:
先从线性可分的数据讲起,如果需要分类的数据都是线性可分的,那么只需要⼀根直线f(x)=wx+b就可以分开了,类似这样:
这种⽅法被称为:线性分类器,⼀个线性分类器的学习⽬标便是要在n维的数据空间中到⼀个超平⾯(hyper plane)。也就是说,数据不总是⼆维的,⽐如,三维的超平⾯是⾯。但是有个问题:
上述两种超平⾯,都可以将数据进⾏分类,由此可推出,其实能有⽆数个超平⾯能将数据划分,但是哪条最优呢?
最⼤间隔分类器Maximum Margin Classifier:
简称MMH, 对⼀个数据点进⾏分类,当超平⾯离数据点的“间隔”越⼤,分类的确信度(confidence)也越⼤。所以,为了使得分类的确信度尽量⾼,需要让所选择的超平⾯能够最⼤化这个“间隔”值。这个间隔就是下图中的Gap的⼀半。
⽤以⽣成⽀持向量的点,如上图XO,被称为⽀持向量点,因此SVM有⼀个优点,就是即使有⼤量的数据,但是⽀持向量点是固定的,因此即使再次训练⼤量数据,这个超平⾯也可能不会变化。
⾮线性分类:
数据⼤多数情况都不可能是线性的,那如何分割⾮线性数据呢?
解决⽅法是将数据放到⾼维度上再进⾏分割,如下图:
当f(x)=x时,这组数据是个直线,如上半部分,但是当我把这组数据变为f(x)=x^2时,这组数据就变成了下半部分的样⼦,也就可以被红线所分割。
⽐如说,我这⾥有⼀组三维的数据X=(x1,x2,x3),线性不可分割,因此我需要将他转换到六维空间去。因此我们可以假设六个维度分别是:x1,x2,x3,x1^2,x1*x2,x1*x3,当然还能继续展开,但是六维的话这样就⾜够了。
新的决策超平⾯:d(Z)=WZ+b,解出W和b后带⼊⽅程,因此这组数据的超平⾯应该是:
d(Z)=w1x1+w2x2+w3x3+w4*x1^2+w5x1x2+w6x1x3+b但是⼜有个新问题,转换⾼纬度⼀般是以内积(dot product)的⽅式进⾏的,但是内积的算法复杂度⾮常⼤。
核函数Kernel:
我们会经常遇到线性不可分的样例,此时,我们的常⽤做法是把样例特征映射到⾼维空间中去。但进⼀步,如果凡是遇到线性不可分的样例,⼀律映射到⾼维空间,那么这个维度⼤⼩是会⾼到可怕的,⽽且内积⽅式复杂度太⼤。此时,核函数就隆重登场了,核函数的价值在于它虽然也是讲特征进⾏从低维到⾼维的转换,但核函数绝就绝在它事先在低维上进⾏计算,⽽将实质上的分类效果表现在了⾼维上,也就如上⽂所说的避免了直接在⾼维空间中的复杂计算。
⼏种常⽤核函数:
h度多项式核函数(Polynomial Kernel of Degree h)
⾼斯径向基和函数(Gaussian radial basis function Kernel)
S型核函数(Sigmoid function Kernel)
图像分类,通常使⽤⾼斯径向基和函数,因为分类较为平滑,⽂字不适⽤⾼斯径向基和函数。没有标准的答案,可以尝试各种核函数,根据精确度判定。
松弛变量:
数据本⾝可能有噪点,会使得原本线性可分的数据需要映射到⾼维度去。对于这种偏离正常位置很远的数据点,我们称之为 outlier ,在我们原来的 SVM 模型⾥,outlier 的存在有可能造成很⼤的影响,因为超平⾯本⾝就是只有少数⼏个 support vector 组成的,如果这些support vector ⾥⼜存在 outlier 的话,其影响就很⼤了。
因此排除outlier点,可以相应的提⾼模型准确率和避免Overfitting的⽅式。
解决多分类问题:
经典的SVM只给出了⼆类分类的算法,现实中数据可能需要解决多类的分类问题。因此可以多次运⾏SVM,产⽣多个超平⾯,如需要分类1-10种产品,⾸先到1和2-10的超平⾯,再寻2和1,3-10的超平⾯,以此类推,最后需要测试数据时,按照相应的距离或者分布判定。
SVM与其他机器学习算法对⽐(图):
Python实现⽅式:
线性,基础:
from sklearn import svm
x = [[2,0,1],[1,1,2],[2,3,3]]
y = [0,0,1] #分类标记
clf = svm.SVC(kernel = 'linear') #SVM模块,svc,线性核函数
clf.fit(x,y)
print(clf)
print(clf.support_vectors_) #⽀持向量点
print(clf.support_) #⽀持向量点的索引
print(clf.n_support_) #每个class有⼏个⽀持向量点
print(clf.predict([2,0,3])) #预测
线性,展⽰图:
from sklearn import svm
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
x = np.r_[np.random.randn(20,2)-[2,2],np.random.randn(20,2)+[2,2]] #正态分布来产⽣数字,20⾏2列*2 y = [0]*20+[1]*20 #20个class0,20个class1
clf = svm.SVC(kernel='linear')
clf.fit(x,y)
w = f_[0] #获取w
a = -w[0]/w[1] #斜率
#画图划线
xx = np.linspace(-5,5) #(-5,5)之间x的值
yy = a*xx-(clf.intercept_[0])/w[1] #xx带⼊y,截距
#画出与点相切的线
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])
linspace函数pythonprint("W:",w)
print("a:",a)
print("support_vectors_:",clf.support_vectors_)
print("f_:",f_)
plt.figure(figsize=(8,4))
plt.plot(xx,yy)
plt.plot(xx,yy_down)
plt.plot(xx,yy_up)
plt.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1],s=80)
plt.scatter(x[:,0],x[:,1],c=y,Paired) #[:,0]列切⽚,第0列
plt.axis('tight')
plt.show()
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论