SVM(支持向量机)
1.SVM基本概念
支持向量机(support vector machines,SVM)是一种二分类模型,它将实例的特征向量映射为空间中的一些点,SVM 的目的就是想要画出一条线,以 “最好地” 区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。SVM 适合中小型数据样本、非线性、高维的分类问题。

因为其核心理念是:支持向量样本会对识别的问题起关键性作用。支持向量也就是离分类超平面(Hyper plane)最近的样本点。
超平面是分割输入变量空间的线。在SVM中,选择超平面以最佳地将输入变量空间中的点与它们的类(0级或1级)分开。在二维中,您可以将其视为一条线,并假设我们的所有输入点都可以被这条线完全分开。SVM学习算法找到导致超平面最好地分离类的系数,使得可以区分两个类别并且能使间隔(margin)最大的划分超平面。比较好的划分超平面,样本局部扰动时对它的影响最小、产生的分类结果最鲁棒、对未见示例的泛化能力最强。

下图展现的是,三位空间下的划分:

2.核函数
在线性 SVM 中转化为最优化问题时求解的公式计算都是以内积(dot product)形式出现的。因为内积的算法复杂度非常大,所以我们利用核函数来取代计算非线性映射函数的内积。
简单地说,核函数是计算两个向量在隐式映射后空间中的内积的函数。核函数通过先对特征向量做内积,然后用函数 K 进行变换,这有利于避开直接在高维空间中计算,大大简化问题求解。并且这等价于先对向量做核映射然后再做内积。
1.线性核函数(Linear Kernel)

主要用于线性可分的情况。在原始空间中寻找最优线性分类器,具有参数少,速度快的优势。通常,我们首先采用线性核函数先进行分类尝试。
2.多项式核函数(Polynomial Kernel)

多项式核函数可以实现将低维的输入空间映射到高纬的特征空间,属于全局核函数,参数d越大,映射的维度也越高,计算量就会越大,容易出现“过拟合”的现象
3.高斯核函数(Gaussian Kernel)

高斯核函数是一种局部性较强的函数,改函数是应用最广的一个,无论在大样本或者在小样本都有比较好的性能,且相对于多项式核函数来说参数更少。当数据点距离中心点变远时,取值会变小。高斯核函数对数据中存在的噪声有着较好的抗干扰能力,由于其很强的局部性,其参数决定了函数作用范围,随着参数σ的增大而减弱。
4.Sigmoid核函数(Sigmoid Kernel)

采用Sigmoid函数作为核函数时,支持向量机实现的就是一种多层感知器神经网络,该核函数被广泛运用于深度学习和机器学习中。
5.如何选择
吴恩达教授曾经给出过一系列的选择核函数的方法:
- 当样本的特征很多时,特征的维数很高,这是往往样本线性可分,可考虑用线性核函数的SVM或LR
- 当样本的数量很多,但特征较少时,可以手动添加一些特征,使样本线性可分,再考虑用线性核函数的SVM或LR。
- 当样特征维度不高时,样本数量也不多时,考虑用高斯核函数
3.硬间隔和软间隔
3.1硬间隔
所谓硬间隔就是指给定的数据集线性可分,所有的样本点都严格的分布在间隔边界的两侧,,并且最小几何距离最大
3.2软间隔
所谓软间隔就是指给定的数据集并不是线性可分的,但为了解决这个问题允许一定量的样本点越过间隔边界
公式推导有些复杂,这里只介绍了概念...
4.SVM小结
SVM 一个很好的性质了:分类的平面,只跟部分数据(support vector)有关,而且是最“相似”,最容易“相互混淆”的那部分数据,与其他的绝大部分数据都无关。我们移走或者增加那些本身就距离很远的数据,对于分类结果没有改变,但是如果我们能给出更多的“相似”的数据,打上精准的标签,那分类结果就会更精确。
优点:
- 可以解决高维问题,即大型特征空间;
- 对于数据的要求很低,不要求数据符合什么样的分布,只要存在边界就可以,模糊的边界也可以。
- 解决小样本下机器学习问题;
- 能够处理非线性特征的相互作用;
- 无局部极小值问题;(相对于神经网络等算法)
- 无需依赖整个数据;
- 过拟合的概率不高,泛化能力强,因为决定那条线的数据量很少;
缺点:
- 当观测样本很多时,效率并不是很高;
- 对非线性问题没有通用解决方案,有时候很难找到一个合适的核函数;
- 对于核函数的高维映射解释力不强,尤其是径向基函数;
- 常规SVM只支持二分类,解决多分类问题存在困难
- 对缺失数据敏感;
5.代码实现
对于svm的SVC参数,我们主要关注以下几个部分
- C:惩罚参数,默认值为1。C越大,对误分类的惩罚增大,趋向于全部分对的状况,这样对训练集的测试率很高,但泛化能力较弱。C越小,对误分类的惩罚减小,允许容错,泛化能力较强。
- kernel:核函数,默认值是rbf,也可以是'linear','poly','sigmid','precomputed',不同的核函数对应有不同的参数,比如对于rbf,gamma就是他的参数,一般取1/n。如何选择kernel,则需要具体问题、具体分析。
5.1线性SVM
import numpy as np from sklearn.datasets import load_iris import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler from sklearn.svm import LinearSVC from matplotlib.colors import ListedColormap import warnings def plot_decision_boundary(model,axis): x0,x1=np.meshgrid( np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1), np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1) ) x_new=np.c_[x0.ravel(),x1.ravel()] y_predict=model.predict(x_new) zz=y_predict.reshape(x0.shape) custom_cmap=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9']) plt.contourf(x0,x1,zz,linewidth=5,cmap=custom_cmap) w = model.coef_[0] b = model.intercept_[0] plot_x = np.linspace(axis[0],axis[1],200) up_y = -w[0]/w[1]*plot_x - b/w[1] + 1/w[1] down_y = -w[0]/w[1]*plot_x - b/w[1] - 1/w[1] up_index = (up_y>=axis[2]) & (up_y<=axis[3]) down_index = (down_y>=axis[2]) & (down_y<=axis[3]) plt.plot(plot_x[up_index],up_y[up_index],c='black') plt.plot(plot_x[down_index],down_y[down_index],c='black') warnings.filterwarnings("ignore") data = load_iris() x = data.data y = data.target x = x[y<2,:2] y = y[y<2] scaler = StandardScaler() scaler.fit(x) x = scaler.transform(x) svc = LinearSVC(C=1e9) svc.fit(x,y) plot_decision_boundary(svc,axis=[-3,3,-3,3]) plt.scatter(x[y==0,0],x[y==0,1],c='r') plt.scatter(x[y==1,0],x[y==1,1],c='b') plt.show()
5.2非线性-多项式特征
1 import numpy as np 2 from sklearn import datasets 3 import matplotlib.pyplot as plt 4 from sklearn.preprocessing import PolynomialFeatures,StandardScaler 5 from sklearn.svm import LinearSVC 6 from sklearn.pipeline import Pipeline 7 from matplotlib.colors import ListedColormap 8 import warnings 9 10 def plot_decision_boundary(model,axis): 11 x0,x1=np.meshgrid( 12 np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1), 13 np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1) 14 ) 15 x_new=np.c_[x0.ravel(),x1.ravel()] 16 y_predict=model.predict(x_new) 17 zz=y_predict.reshape(x0.shape) 18 custom_cmap=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9']) 19 plt.contourf(x0,x1,zz,linewidth=5,cmap=custom_cmap) 20 21 def PolynomialSVC(degree,C=1.0): 22 return Pipeline([ 23 ('poly',PolynomialFeatures(degree=degree)), 24 ('std_scaler',StandardScaler()), 25 ('linearSVC',LinearSVC(C=1e9)) 26 ]) 27 28 warnings.filterwarnings("ignore") 29 poly_svc = PolynomialSVC(degree=3) 30 X,y = datasets.make_moons(noise=0.15,random_state=666) 31 poly_svc.fit(X,y) 32 plot_decision_boundary(poly_svc,axis=[-1.5,2.5,-1.0,1.5]) 33 plt.scatter(X[y==0,0],X[y==0,1],c='red') 34 plt.scatter(X[y==1,0],X[y==1,1],c='blue') 35 plt.show()
5.3非线性-核方法
from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC from sklearn.pipeline import Pipeline from sklearn import datasets from matplotlib.colors import ListedColormap import numpy as np import matplotlib.pyplot as plt import warnings def plot_decision_boundary(model,axis): x0,x1=np.meshgrid( np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1), np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1) ) x_new=np.c_[x0.ravel(),x1.ravel()] y_predict=model.predict(x_new) zz=y_predict.reshape(x0.shape) custom_cmap=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9']) plt.contourf(x0,x1,zz,linewidth=5,cmap=custom_cmap) def RBFKernelSVC(gamma=1.0): return Pipeline([ ('std_scaler',StandardScaler()), ('svc',SVC(kernel='rbf',gamma=gamma)) ]) warnings.filterwarnings("ignore") X,y = datasets.make_moons(noise=0.15,random_state=666) svc = RBFKernelSVC(gamma=100) svc.fit(X,y) plot_decision_boundary(svc,axis=[-1.5,2.5,-1.0,1.5]) plt.scatter(X[y==0,0],X[y==0,1],c='red') plt.scatter(X[y==1,0],X[y==1,1],c='blue') plt.show()
参考链接:机器学习--支持向量机 (SVM)算法的原理及优缺点 - 泰初 - 博客园 (cnblogs.com)

浙公网安备 33010602011771号