美文网首页
支持向量机SVM

支持向量机SVM

作者: 不会忘的名字 | 来源:发表于2018-12-29 11:54 被阅读0次

    支持向量机SVM(Support Vector Machine)

    【关键词】支持向量,最大几何间隔,拉格朗日乘子法

    一、支持向量机的原理

    Support Vector Machine。支持向量机,其含义是通过支持向量运算的分类器。其中“机”的意思是机器,可以理解为分类器。
    那么什么是支持向量呢?在求解的过程中,会发现只根据部分数据就可以确定分类器,这些数据称为支持向量。
    见下图,在一个二维环境中,其中点R,S,G点和其它靠近中间黑线的点可以看作为支持向量,它们可以决定分类器,也就是黑线的具体参数。

    SVM原理图.png

    解决的问题:

    • 线性分类

    在训练数据中,每个数据都有n个的属性和一个二类类别标志,我们可以认为这些数据在一个n维空间里。我们的目标是找到一个n-1维的超平面(hyperplane),这个超平面可以将数据分成两部分,每部分数据都属于同一个类别。
    其实这样的超平面有很多,我们要找到一个最佳的。因此,增加一个约束条件:这个超平面到每边最近数据点的距离是最大的。也成为最大间隔超平面(maximum-margin hyperplane)。这个分类器也成为最大间隔分类器(maximum-margin classifier)。
    支持向量机是一个二类分类器。

    • 非线性分类

    SVM的一个优势是支持非线性分类。它结合使用拉格朗日乘子法和KKT条件,以及核函数可以产生非线性分类器。

    SVM的目的是要找到一个线性分类的最佳超平面 f(x)=xw+b=0。求 w 和 b。
    首先通过两个分类的最近点,找到f(x)的约束条件。
    有了约束条件,就可以通过拉格朗日乘子法和KKT条件来求解,这时,问题变成了求拉格朗日乘子αi 和 b。
    对于异常点的情况,加入松弛变量ξ来处理。
    非线性分类的问题:映射到高维度、使用核函数。

    二.实战

    1.画出决策边界

    • 导包sklearn.svm
    import numpy as np
    from sklearn.svm import SVC,SVR
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    • 随机生成数据,并且进行训练np.r_[]
      生成数据
    from sklearn.datasets import make_blobs
    
    data, target = make_blobs(centers=2)
    plt.scatter(data[:,0], data[:,1], c=target)
    
    生成数据图片.png
    • 训练模型,并训练
    **如果是直线可以划分开的话,需要指定线性的核函数**
    svc = SVC(kernel='linear')
    svc.fit(data, target)
    
    out:SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
      decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
      max_iter=-1, probability=False, random_state=None, shrinking=True,
      tol=0.001, verbose=False)
    
    # 支持向量
    sv = svc.support_vectors_
    sv
    
    out:array([[4.23522683, 9.19250893],
           [6.23760702, 7.88434105],
           [2.00382811, 3.16498141]])
    
    • 提取系数获取斜率
    # 斜率
    w1, w2 = svc.coef_[0,0], svc.coef_[0,1]
    display(w1, w2)
    out:-0.17459676838526306
        -0.26715404312361524
    
    • 线性方程的截距
    # 截距
    b = svc.intercept_
    
    # 画出支持向量的点  alpha透明度
    plt.scatter(data[:,0], data[:,1], c=target)
    plt.scatter(sv[:,0], sv[:,1],c=[0,1,2] ,cmap='rainbow', s=200, alpha=0.5)
    
    支持向量显示点.png
    # 实际的方程:
    y = w1*x1 + w2*x2 + b   # 这是一个空间坐标方程3个未知数
    # 令y=0, 压缩到2维上.直线可以划分开,求2维上线性方程
    0 = w1*x + w2*y + b
    
    x = np.linspace(0, 8, 100)
    y = -w1/w2 * x - b/w2
    
    # 画出分割线
    plt.scatter(data[:,0], data[:,1], c=target)
    plt.scatter(sv[:,0], sv[:,1],c=[0,1,2] ,cmap='rainbow', s=200, alpha=0.5)
    plt.plot(x, y, c='r')
    
    分割线图.png
    # 求上边界
    # 已知斜率,和线上的点,求截距
    # y_up = x_up * (-w1/w2) + b_up
    b_up = y_up + x_up*(w1/w2)
    
    b_up = sv[0,1] + sv[0,0]* (w1/w2)
    b_up
    out:11.960413579746653
    
    plt.scatter(data[:,0], data[:,1], c=target)
    plt.scatter(sv[:,0], sv[:,1],c=[0,1,2] ,cmap='rainbow', s=200, alpha=0.5)
    plt.plot(x, y, c='r')
    # 画上边界
    plt.plot(x, -x*w1/w2 + b_up, c='k')
    
    包含上边界图.png
    # 下截距
    y_down = -(w1/w2) * x_down + b_down
    b_down = y_down + w1/w2*x_down
    
    b_down = sv[2,1] + w1/w2 * sv[2,0]
    b_down
    out:4.474570094543953
    
    plt.scatter(data[:,0], data[:,1], c=target)
    plt.scatter(sv[:,0], sv[:,1],c=[0,1,2] ,cmap='rainbow', s=200, alpha=0.5)
    plt.plot(x, y, c='r')
    # 画上边界
    plt.plot(x, -x*w1/w2 + b_up, c='k')
    
    # 画出下边界
    plt.plot(x, -x*w1/w2 + b_down, c='b')
    
    画出下边界完成所有画图.png

    注:先画出分割线,求得斜率. 在分别求得上下边界的截距画出上下边界的直线.

    2、SVM分离坐标点

    • 导包
    import numpy as np
    from sklearn.svm import SVC
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    • 生成数据
    # 生成一堆随机点.
    X_train = np.random.randn(300, 2)
    plt.scatter(X_train[:,0], X_train[:,1])
    
    随机生成的正态数据.png
    # python中认为空字符串, 空列表,空字典,空集合,空的东西,还有0,都是False,除此之外都是True.
    n1 = np.array([0,2,3])
    n2 = np.array([2,3,4])
    np.logical_xor(n1,n2)
    out:array([ True, False, False])
    
    # 借助异或的思想,实现数据的分类
    target = np.logical_xor(X_train[:,0]>0, X_train[:,1]>0)
    # 实际上python会把True当成1,False当成0.
    plt.scatter(X_train[:,0], X_train[:,1], c=target)
    
    异或分类数据.png
    • 训练
    svc = SVC()
    svc.fit(X_train, target)
    
    out:SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
      decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
      max_iter=-1, probability=False, random_state=None, shrinking=True,
      tol=0.001, verbose=False)
    
    • 创造-3到3范围的点以及meshgrid
    xmin, xmax = X_train[:,0].min(), X_train[:,0].max()
    ymin, ymax = X_train[:,1].min(), X_train[:,1].max()
    x,y = np.linspace(xmin, xmax, 1000), np.linspace(ymin, ymax,1000)
    X,Y = np.meshgrid(x,y)
    X_test = np.c_[X.ravel(), Y.ravel()]
    
    • 绘制图形
      绘制测试点到分离超平面的距离(decision_function)
      绘制轮廓线
      绘制训练点
    distance = svc.decision_function(X_test)
    # 在超平面之上面的点
    (distance>0).sum()
    out:511785
    # 在超平面之下面的点
    (distance<0).sum()
    out:488215
    
    • 画图
    plt.figure(figsize=(8,8))
    Z = distance.reshape(1000, 1000)
    plt.show(Z, cmap='PuOr_r', extent=[xmin, xmax, ymin, ymax])
    plt.contour(X, Y, Z)
    
    plt.scatter(X_train[:,0], X_train[:,1], c=target)
    
    类似等高线的超平面图.png

    3、使用多种核函数对iris数据集进行分类

    • 导包,获取鸢尾花数据
    from sklearn.svm import SVC
    from sklearn.datasets import load_iris
    
    iris = load_iris()
    data = iris.data[:,0:2]
    target = iris.target
    
    • 图片背景点
    xmin, xmax = data[:,0].min(), data[:,0].max()
    ymin, ymax = data[:,1].min(), data[:,1].max()
    x,y = np.linspace(xmin, xmax, 1000), np.linspace(ymin, ymax, 1000)
    X, Y = np.meshgrid(x,y)
    X_test = np.c_[X.ravel(),Y.ravel()]
    
    • 提取数据只提取两个特征,方便画图
      创建支持向量机的模型(kernel):'linear'线性, 'poly'(多项式),
      'rbf'(Radial Basis Function:基于半径函数).
      LinearSVC 是优化过的对大数据里有更好效果的线性核函数
    # 线性核函数
    svc = SVC(kernel='linear')
    svc.fit(data, target)
    # 预测
    y_linear = svc.predict(X_test)
    
    # 半径
    svc = SVC(kernel='rbf')
    svc.fit(data, target)
    y_rbf = svc.predict(X_test)
    
    # 多项式
    svc = SVC(kernel='poly')
    svc.fit(data, target)
    y_poly = svc.predict(X_test)
    
    from sklearn.svm import LinearSVC
    # LinearSVC 是优化过的对大数据里有更好效果的线性核函数
    svc_linear = LinearSVC()
    svc_linear.fit(data, target)
    y_Linear = svc_linear.predict(X_test)
    
    • 画4个图,做一个横向对比
    # 画4个图,做一个横向对比
    plt.figure(figsize=(4* 5,4* 4))
    axes1 = plt.subplot(2,2,1)
    axes1.pcolormesh(X,Y, y_linear.reshape(1000,1000))
    axes1.scatter(data[:,0], data[:,1], c=target, cmap='rainbow')
    
    axes2 = plt.subplot(2,2,2)
    axes2.pcolormesh(X,Y, y_Linear.reshape(1000,1000))
    axes2.scatter(data[:,0], data[:,1], c=target, cmap='rainbow')
    
    axes3 = plt.subplot(2,2,3)
    axes3.pcolormesh(X,Y, y_rbf.reshape(1000,1000))
    axes3.scatter(data[:,0], data[:,1], c=target, cmap='rainbow')
    
    axes4 = plt.subplot(2,2,4)
    axes4.pcolormesh(X,Y, y_poly.reshape(1000,1000))
    axes4.scatter(data[:,0], data[:,1], c=target, cmap='rainbow')
    
    四种对比图.png

    4、使用SVM多种核函数进行回归

    • 导包
    from sklearn.svm import SVR
    
    • 自定义样本点rand,并且生成sin值
    X_train = np.random.rand(100) * 10
    y_train = np.sin(X_train)
    plt.scatter(X_train, y_train)
    
    自定义生成的sin值.png
    • 数据加噪
    y_train[::4] += 0.3 * np.random.randn(25)
    plt.scatter(X_train, y_train)
    
    加噪声的图片.png
    • 建立模型,训练数据,并预测数据,预测训练数据就行
    # 预测数据
    X_test = np.linspace(0,10, 1000).reshape(-1,1)
    # 线性核函数
    svr_linear = SVR(kernel='linear')
    svr_linear.fit(X_train.reshape(-1,1),y_train)
    # 预测
    y_linear = svr_linear.predict(X_test)
    
    svr_rbf = SVR(kernel='rbf')
    svr_rbf.fit(X_train.reshape(-1,1),y_train)
    # 预测
    y_rbf = svr_rbf.predict(X_test)
    
    svr_poly = SVR(kernel='poly')
    svr_poly.fit(X_train.reshape(-1,1),y_train)
    # 预测
    y_poly = svr_poly.predict(X_test)
    
    • 绘制图形,观察三种支持向量机内核不同
    plt.figure(figsize=(12,9))
    plt.plot(X_test, y_linear, label='linear')
    plt.plot(X_test, y_rbf, label='rbf')
    plt.plot(X_test, y_poly, label='poly')
    plt.scatter(X_train, y_train)
    plt.legend()
    
    拟合曲线.png
    • 计算拟合得分
    svr_rbf.score(X_train.reshape(-1,1) ,y_train)
    out:0.9079373035139664
    
    svr_linear.score(X_train.reshape(-1,1) ,y_train)
    out:-0.0016745395323372048
    
    svr_poly.score(X_train.reshape(-1,1) ,y_train)
    out:0.011116368287051204
    

    注:从上面拟合曲线和拟合得分来看, 基于半径的核函数, 回归拟合程度最好.

    相关文章

      网友评论

          本文标题:支持向量机SVM

          本文链接:https://www.haomeiwen.com/subject/xqrqlqtx.html