机器学习之支持向量机——基于Scikit-Learn

《Python数据科学手册》笔记

一、支持向量机概念

       画一条到最近点边界、有宽度的线条(二维空间中的直线或曲线)或者流体形体(多维空间中的曲线、曲面等概念)将各类分开,选择边界最大的那条线即是模型的最优解,支持向量机就是一个边界最大化评估器。有些点正好在边界线上,这些点正是拟合的关键支持点,被称为支持向量,任何在正确分类一侧原理边界线的点都不会影响拟合结果。

二、支持向量机优缺点

1.优点:

①模型依赖的支持向量比较少

②一旦模型训练完成,预测阶段的速度非常快

③对于高维数据的学习效果非常好(模型只受边界线附近的点的影响)

④与核方法的配合极具通用性,能够适用于不同类型的数据

⑤即可用于分类,也可用于回归

2.缺点:

①大样本学习的计算成本非常高

②训练效果非常依赖于边界软化参数C的选择是否合理

③预测结果不能直接进行概率解释

另,如果计算资源足以支撑SVM对数据集的训练和交叉检验,那么它一定能获得极好的效果。

三、边界问题

1.核函数SVM模型

遇到非线性可分的数据时,可能就需要将SVM模型与核函数结合使用了。(核函数的介绍可以参照我之前的博客机器学习之线性回归——基于Scikit-Learn

例如左边的非线性可分数据,就可以用一个以数据圆圈为中心的径向基函数来将数据投影到高维空间,如右图,从而使线性分割器可以排上用场(一个平面即可分割)。

上述例子完美的将两类数据进行了分离,但是这是建立在将径向基函数集中到正确位置的前提下,因此,基函数的选择非常重要。让模型自动指出最合适的基函数的方法为:计算基函数在数据集上每个点的变换结果,让SVM算法熊所有结果中筛选出最优解(计算量大)。在Scikit-Learn中,直接应用核函数化的SVM模型将线性核转变为RBF核,设置kernel模型超参数即可

2.软化边界

当各类数据之间有一些重叠时,不可能找到一条线将各类数据完全分开,例如下图。针对这个问题,SVM用修正因子来“软化边界”。它允许一些点位于边界线之内,边界线的硬度可以通过超参数C来控制。C很大,边界就较硬,允许很少数据点在边界内生产,C很小,边界线比较软,有一些数据就可以穿越边界线。

四、相关代码

1. 带边界线(虚线)和支持向量(圆圈)的支持向量机分类器拟合数据

(第1个图)

#产生样本数据
from sklearn.datasets.samples_generator import make_blobs
X,y = make_blobs(n_samples=50,centers=2,random_state=0,cluster_std=0.60)

#拟合支持向量机
from sklearn.svm import SVC
model = SVC(kernel='linear',C=1E10)
model.fit(X,y)

#画二维SVC决策边界
def plot_svc_decision_function(model,ax=None,plot_support=True):
    if ax is None:
        ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    #创建评估模型的网络
    x = np.linspace(xlim[0],xlim[1],30)
    y = np.linspace(ylim[0],ylim[1],30)
    Y,X = np.meshgrid(y,x)
    xy = np.vstack([X.ravel(),Y.ravel()]).T
    P = model.decision_function(xy).reshape(X.shape)
    #画决策边界和边界
    ax.contour(X,Y,P,colors='k',levels=[-1,0,1],alpha=0.5,linestyles=['--','-','--'])
    
    #画支持向量
    if plot_support:
        ax.scatter(model.support_vectors_[:,0],model.support_vectors_[:,1],s=300,linewidth=1,alpha=0.3)
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
        
plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap='autumn')
plot_svc_decision_function(model)

2.径向基函数将数据投影到高维空间

(第2,3个图)

from sklearn.datasets.samples_generator import make_circles
X,y = make_circles(100,factor=.1,noise=.1)

from mpl_toolkits import mplot3d
r = np.exp(-(X**2).sum(1))

def plot_3D(elev=30,azim=30,X=X,y=y):
    ax = plt.subplot(projection='3d')
    ax.scatter3D(X[:,0],X[:,1],r,c=y,s=50,cmap='autumn')
    ax.view_init(elev=elev,azim=azim)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('r')

#plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap='autumn') 
plot_3D()

猜你喜欢

转载自blog.csdn.net/elma_tww/article/details/88118048