这篇主要是针对SVM在实际应用中的实践。这个过程重点在于参数的选择,模型的选择。蛮有意思的。
参考的内容是sklearn官网的Example\Support Vector Machine
note:本文的顺序是按照模型的复杂程度,样本分类的复杂程度,维度的逐级增加进行。
Platform & Environment: python 3.6 (anaconda\spider)
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs
-
线性完全可分问题 hard margin classfication
We can find such a "street" that the margin should be as wide as possible.
x, y = make_blobs(n_samples=40, centers=2, random_state=6)
#centers就是数据分布点,我们现在解决的是二分类问题,\
#那么就需要两个center,数据点都分别围绕着center进行分布
#random_state确定一个数字后,每次运行都会出现相同的随机数。
plt.scatter(x[:,0],x[:,1],c=y,s=30,cmap=plt.cm.Paired)
#plt.scatter中的c代表color,cmap代表colormap,可选
#s是size, c=y是标签分类和plt.cm.Paired联合使用
![](https://img.haomeiwen.com/i8570704/c50a5ab28acd167b.png)
#选择kernel
clf=svm.SVC(kernel='linear', C=1000)
#惩罚参数C大就是要放大所有点到分隔区间的函数间隔,导致分隔区间变窄,\
#就是说更看重分类的效果,不允许分类错误
clf.fit(x,y)
clf.support_vectors_ #支持向量
clf.coef_ #w向量参数
clf.intercept_#截距b
clf.support_ #支持向量index
#plot hyperplane
ax=plt.gca()
xlim=ax.get_xlim()
ylim=ax.get_ylim()
xx=np.linspace(xlim[0],xlim[1],30)
yy=np.linspace(ylim[0],ylim[1],30)
XX,YY=np.meshgrid(xx,yy)
xy = np.vstack([XX.ravel(),YY.ravel()]).T #vstack垂直方向
Z=clf.decision_function(xy).reshape(XX.shape)
ax.contour(XX,YY,Z, colors='k',levels=[-1,0,1],alpha=0.5,linestyles=['--','-','--'])
#这里的level是指函数间隔,我们可以选择不同的函数间隔进行可视化
#alpha是粗细
![](https://img.haomeiwen.com/i8570704/be0b5fe7b5505e5e.png)
#显示出我们的支持向量
ax.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1],s=600,linewidth=1,facecolors='none',edgecolors='y')
![](https://img.haomeiwen.com/i8570704/22d3b878f962fd27.png)
-
非线性SVM
np.random.seed(0)
X=np.random.randn(300,2)
Y=np.logical_xor(X[:,0]>0, X[:,1]>0)
xx,yy = np.meshgrid(np.linspace(-3,3,500),np.linspace(-3,3,500))
#fit
clf = svm.SVC() #所有参数采用默认
clf.fit(X,Y)
xy = np.vstack([xx.ravel(),yy.ravel()]).T
Z=clf.decision_function(xy).reshape(xx.shape)
plt.imshow(Z, interpolation='nearest',extent=(xx.min(),xx.max(), yy.min(),yy.max(),),aspect='auto',origin='lower',cmap=plt.cm.PuOr_r) #这一段是背景设置
plt.contour(xx,yy,Z,levels=[0],linewidths=2,linestyle='--')
plt.scatter(X[:,0],X[:,1],s=30,c=Y,cmap=plt.cm.Paired, edgecolors='k')
可视化
![](https://img.haomeiwen.com/i8570704/7adc4ba1c590df81.png)
在这里需要强调的是,sklearn中的案例用的是NuSVC,而我在这里直接用的SVC,这个我也纠结一下,实际上,NuSVC和SVC仅仅有一处差别,那就惩罚参数C,在NuSVC中是没有C的,而增加了一个变量Nu,官方定义就是通过Nu来控制错误率,并且给Nu赋予了一个取值范围(0,1],这实际上和我们所说的惩罚参数C类似,所以,不必纠结于此。
具体情况请参考这篇博文:https://www.cnblogs.com/pinard/p/6117515.html
这里的SVC我没有定义kernel使用的是默认的,在SVC模块里,默认的是rbf,也就是高斯核函数。
-
不同kernel对同种数据的分类效果比对
#创造数据
X=np.c_[(.4,-.7),(-1.5,-1),(-1.4,-.9),(-1.3,-1.2),(-1.1,-.2),(-1.2,-.4),(-.5,1.2),(-1.5,2.1),(1,1),(1.3,.8),(1.2,.5),(.2,-2),(.5,-2.4),(.2,-2.3),(0,-2.7),(1.3,2.1)].T
Y=[0]*8+[1]*8
figurenum=1
for kernel in ('linear','poly','rbf'):
clf = svm.SVC(kernel=kernel,gamma=1)
clf.fit(X,Y)
plt.subplot(2,2,figurenum)
x_min=-3
x_max=3
y_min=-3
y_max=3
XX,YY=np.meshgrid(np.linspace(x_min,x_max,200),np.linspace(y_min,y_max,200))
xy=np.vstack([XX.ravel(),YY.ravel()]).T
Z=clf.decision_function(xy).reshape(XX.shape)
plt.pcolormesh(XX, YY, Z > 0, cmap=plt.cm.Paired)
plt.contour(XX,YY,Z,colors=['k','k','k'],levels=[-.5,0,.5],linestyles=['--','-','--'])
plt.scatter(X[:,0],X[:,1],c =Y, s=30,cmap=plt.cm.Paired, edgecolors='k')
plt.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1], s=80,facecolors='none', edgecolors='k')
plt.xlim(x_min, x_max)
plt.ylim(y_min,y_max)
plt.xticks(())
plt.yticks(())
figurenum+=1
首先kernel的参数gamma在这里调用
我们先用默认的gamma值,0.5(1/num_features)
![](https://img.haomeiwen.com/i8570704/51098869e50109a2.png)
我们发现欠拟合的特征。
![](https://img.haomeiwen.com/i8570704/fa38a3321acf00c2.png)
完美拟合。
![](https://img.haomeiwen.com/i8570704/f628f26218330fbc.png)
上图是过拟合的特征。
同时我们在算法里将函数间隔显示的是[-.5, .5],我们发现,gamma对于线性可分问题,影响几乎没有,这个我们在核函数的公式就可以知道;在'poly'核的应用中,gamma较小时会出现欠拟合的现象;在'rbf'高斯核的应用中,gamma值对其影响比较敏感,gamma太小会造成欠拟合,gamma太大又会造成过拟合。
网友评论