zoukankan      html  css  js  c++  java
  • 机器学习算法(五): 基于支持向量机的分类预测

    目录

    1. Demo实践
    2. 支持向量机
    3. 软间隔
    4. 超平面

    一、Demo实践 

    #Step1:库函数导入
    ## 基础函数库
    import numpy as np
    ## 导入画图库
    import matplotlib.pyplot as plt
    import seaborn as sns
    ## 导入逻辑回归模型函数
    from sklearn import svm
    
    #Step2:构建数据集并进行模型训练
    
    ## 构造数据集
    x_fearures = np.array([[-1, -2], [-2, -1], [-3, -2], [1, 3], [2, 1], [3, 2]])
    y_label = np.array([0, 0, 0, 1, 1, 1])
    ## 调用SVC模型 (支持向量机分类)
    svc = svm.SVC(kernel='linear')
    ## 用SVM模型拟合构造的数据集
    svc = svc.fit(x_fearures, y_label) 
    
    #Step3:模型参数查看
    ## 查看其对应模型的w
    print('the weight of Logistic Regression:',svc.coef_)
    #the weight of Logistic Regression: [[0.33364706 0.33270588]]
    ## 查看其对应模型的w0
    print('the intercept(w0) of Logistic Regression:',svc.intercept_)
    #the intercept(w0) of Logistic Regression: [-0.00031373]
    
    #Step4:模型预测
    ## 模型预测
    y_train_pred = svc.predict(x_fearures)
    print('The predction result:',y_train_pred) #The predction result: [0 0 0 1 1 1]
    
    #Step5:模型可视化 
    #由于此处选择的线性核函数,所以在此我们可以将svm进行可视化
    # 最佳函数
    x_range = np.linspace(-3, 3)
    w = svc.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_range - (svc.intercept_[0]) / w[1]
    # 可视化决策边界
    plt.figure()
    plt.scatter(x_fearures[:,0],x_fearures[:,1], c=y_label, s=50, cmap='viridis')
    plt.plot(x_range, y_3, '-c')
    plt.show()

     

     可以对照之前的逻辑回归模型的决策边界,我们可以发现两个决策边界是有一定差异的(可以对比两者在X,Y轴 上的截距),这说明这两个不同在相同数据集上找到的判别线是不同的,而这不同的原因其实是由于两者选择的 最优目标是不一致的。接下来我们进行SVM的一些简单介绍。

    二、支持向量机

    我们常常会碰到这样的一个问题,首先给你一些分属于两个类别的数据

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.datasets.samples_generator import make_blobs
    %matplotlib inline
    # 画图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=60, cmap=plt.cm.Paired)

    现在需要一个线性分类器,将这些数据分开来。
    我们可能会有多种分法:

    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    x_fit = np.linspace(0, 3)
    # 画函数
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    y_2 = -0.3 * x_fit + 3
    plt.plot(x_fit, y_2, '-k')

    那么现在有一个问题,两个分类器,哪一个更好呢?
    为了判断好坏,我们需要引入一个准则:好的分类器不仅仅是能够很好的分开已有的数据集,还能对未知数据集 进行两个的划分。
    假设,现在有一个属于红色数据点的新数据(3, 2.8)

    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    plt.scatter([3], [2.8], c='#cccc00', marker='<', s=100, cmap=plt.cm.Paired)
    x_fit = np.linspace(0, 3)
    # 画函数
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    y_2 = -0.3 * x_fit + 3
    plt.plot(x_fit, y_2, '-k')

    可以看到,此时黑色的线会把这个新的数据集分错,而蓝色的线不会。
    我们刚刚举的例子可能会带有一些主观性。
    那么如何客观的评判两条线的健壮性呢?
    此时,我们需要引入一个非常重要的概念:最大间隔
    最大间隔刻画着当前分类器与数据集的边界,以这两个分类器为例:

    可以看到, 蓝色的线最大间隔是大于黑色的线的。
    所以我们会选择蓝色的线作为我们的分类器。

    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画图
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    # 画边距
    plt.fill_between(x_fit, y_1 - 0.6, y_1 + 0.6, edgecolor='none', color='#AAAAAA', alpha=0.4)

    那么,我们现在的分类器是最优分类器吗?
    或者说,有没有更好的分类器,它具有更大的间隔
    答案是有的。
    为了找出最优分类器,我们需要引入我们今天的主角:SVM

    from sklearn.svm import SVC
    # SVM 函数
    clf = SVC(kernel='linear')
    clf.fit(X, y)          
                     
    # 最佳函数
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_fit - (clf.intercept_[0]) / w[1]
    # 最大边距 下届
    b_down = clf.support_vectors_[0]
    y_down = a* x_fit + b_down[1] - a * b_down[0]
    # 最大边距 上届
    b_up = clf.support_vectors_[-1]
    y_up = a* x_fit + b_up[1] - a * b_up[0]                 
                     
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画函数
    plt.plot(x_fit, y_3, '-c')
    # 画边距
    plt.fill_between(x_fit, y_down, y_up, edgecolor='none', color='#AAAAAA', alpha=0.4)
    # 画支持向量
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none')         

    全部代码如下(折叠)

    # -*- coding: utf-8 -*-
    """
    Created on Tue Aug 11 10:12:48 2020
    
    @author: Admin
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.datasets.samples_generator import make_blobs
    %matplotlib inline
    # 画图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=60, cmap=plt.cm.Paired)
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    x_fit = np.linspace(0, 3)
    # 画函数
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    y_2 = -0.3 * x_fit + 3
    plt.plot(x_fit, y_2, '-k')
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    plt.scatter([3], [2.8], c='#cccc00', marker='<', s=100, cmap=plt.cm.Paired)
    x_fit = np.linspace(0, 3)
    # 画函数
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    y_2 = -0.3 * x_fit + 3
    plt.plot(x_fit, y_2, '-k')
    
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    x_fit = np.linspace(0, 3)
    # 画函数
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    # 画边距
    plt.fill_between(x_fit, y_1 - 0.6, y_1 + 0.6, edgecolor='none', color='#AAAAAA', alpha=0.4)
    y_2 = -0.3 * x_fit + 3
    plt.plot(x_fit, y_2, '-k')
    plt.fill_between(x_fit, y_2 - 0.4, y_2 + 0.4, edgecolor='none', color='#AAAAAA', alpha=0.4)
                     
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画图
    y_1 = 1 * x_fit + 0.8
    plt.plot(x_fit, y_1, '-c')
    # 画边距
    plt.fill_between(x_fit, y_1 - 0.6, y_1 + 0.6, edgecolor='none', color='#AAAAAA', alpha=0.4)
    
    from sklearn.svm import SVC
    # SVM 函数
    clf = SVC(kernel='linear')
    clf.fit(X, y)          
                     
    # 最佳函数
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_fit - (clf.intercept_[0]) / w[1]
    # 最大边距 下届
    b_down = clf.support_vectors_[0]
    y_down = a* x_fit + b_down[1] - a * b_down[0]
    # 最大边距 上届
    b_up = clf.support_vectors_[-1]
    y_up = a* x_fit + b_up[1] - a * b_up[0]                 
                     
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画函数
    plt.plot(x_fit, y_3, '-c')
    # 画边距
    plt.fill_between(x_fit, y_down, y_up, edgecolor='none', color='#AAAAAA', alpha=0.4)
    # 画支持向量
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none')                
    View Code

    三、软间隔

    但很多时候,我们拿到的数据是这样子的

    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.9)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)

    这种情况并不容易找到这样的最大间隔。
    于是我们就有了软间隔,相比于硬间隔而言,我们允许个别数据出现在间隔带中
    我们知道,如果没有一个原则进行约束,满足软间隔的分类器也会出现很多条。
    所以需要对分错的数据进行惩罚,SVC 函数中,有一个参数 C 就是惩罚参数
    惩罚参数越小,容忍性就越大
    以 C=1 为例子,比如说:

    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.9)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 惩罚参数:C=1
    clf = SVC(C=1, kernel='linear')
    clf.fit(X, y)
    # 最佳函数
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_fit - (clf.intercept_[0]) / w[1]
    # 最大边距 下界
    b_down = clf.support_vectors_[0]
    y_down = a* x_fit + b_down[1] - a * b_down[0]
    # 最大边距 上界
    b_up = clf.support_vectors_[-1]
    y_up = a* x_fit + b_up[1] - a * b_up[0]
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画函数
    plt.plot(x_fit, y_3, '-c')
    # 画边距
    plt.fill_between(x_fit, y_down, y_up, edgecolor='none', color='#AAAAAA', alpha=0.4)
    # 画支持向量
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none')

     

    惩罚参数 C=0.2 时,SVM 会更具包容性,从而兼容更多的错分样本:

    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.9)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 惩罚参数:C=0.2
    clf = SVC(C=0.2, kernel='linear')
    clf.fit(X, y)
    x_fit = np.linspace(-1.5, 4)
    # 最佳函数
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_fit - (clf.intercept_[0]) / w[1]
    # 最大边距 下届
    b_down = clf.support_vectors_[10]
    y_down = a* x_fit + b_down[1] - a * b_down[0]
    # 最大边距 上届
    b_up = clf.support_vectors_[1]
    y_up = a* x_fit + b_up[1] - a * b_up[0]
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画函数
    plt.plot(x_fit, y_3, '-c')
    # 画边距
    plt.fill_between(x_fit, y_down, y_up, edgecolor='none', color='#AAAAAA', alpha=0.4)
    # 画支持向量
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none'

     

    全部代码如下(已折叠)

    # -*- coding: utf-8 -*-
    """
    Created on Tue Aug 11 10:12:48 2020
    
    @author: Admin
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.datasets.samples_generator import make_blobs
    %matplotlib inline
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.9)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.9)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 惩罚参数:C=1
    clf = SVC(C=1, kernel='linear')
    clf.fit(X, y)
    # 最佳函数
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_fit - (clf.intercept_[0]) / w[1]
    # 最大边距 下界
    b_down = clf.support_vectors_[0]
    y_down = a* x_fit + b_down[1] - a * b_down[0]
    # 最大边距 上界
    b_up = clf.support_vectors_[-1]
    y_up = a* x_fit + b_up[1] - a * b_up[0]
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画函数
    plt.plot(x_fit, y_3, '-c')
    # 画边距
    plt.fill_between(x_fit, y_down, y_up, edgecolor='none', color='#AAAAAA', alpha=0.4)
    # 画支持向量
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none')
    
    
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.9)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 惩罚参数:C=0.2
    clf = SVC(C=0.2, kernel='linear')
    clf.fit(X, y)
    x_fit = np.linspace(-1.5, 4)
    # 最佳函数
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*x_fit - (clf.intercept_[0]) / w[1]
    # 最大边距 下届
    b_down = clf.support_vectors_[10]
    y_down = a* x_fit + b_down[1] - a * b_down[0]
    # 最大边距 上届
    b_up = clf.support_vectors_[1]
    y_up = a* x_fit + b_up[1] - a * b_up[0]
    # 画散点图
    X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    # 画函数
    plt.plot(x_fit, y_3, '-c')
    # 画边距
    plt.fill_between(x_fit, y_down, y_up, edgecolor='none', color='#AAAAAA', alpha=0.4)
    # 画支持向量
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none')
    View Code

     

    四、超平面

     如果我们遇到这样的数据集,没有办法利用线性分类器进行分类

    from sklearn.datasets.samples_generator import make_circles
    # 画散点图
    X, y = make_circles(100, factor=.1, noise=.1, random_state=2019)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    clf = SVC(kernel='linear').fit(X, y)
    # 最佳函数
    x_fit = np.linspace(-1.5, 1.5)
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*X - (clf.intercept_[0]) / w[1]
    plt.plot(X, y_3, '-c')

    我们可以将二维(低维)空间的数据映射到三维(高维)空间中。
    此时,我们便可以通过一个超平面对数据进行划分。
    所以,我们映射的目的在于使用 SVM 在高维空间找到超平面的能力

    from mpl_toolkits.mplot3d import Axes3D
    # 数据映射
    r = np.exp(-(X[:, 0] ** 2 + X[:, 1] ** 2))
    ax = plt.subplot(projection='3d')
    ax.scatter3D(X[:, 0], X[:, 1], r, c=y, s=50, cmap=plt.cm.Paired)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    x_1, y_1 = np.meshgrid(np.linspace(-1, 1), np.linspace(-1, 1))
    z = 0.01*x_1 + 0.01*y_1 + 0.5
    ax.plot_surface(x_1, y_1, z, alpha=0.3)

    在 SVC 中,我们可以用高斯核函数来实现这以功能:kernel='rbf'

    # 画图
    X, y = make_circles(100, factor=.1, noise=.1, random_state=2019)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    clf = SVC(kernel='rbf')
    clf.fit(X, y)
    ax = plt.gca()
    x = np.linspace(-1, 1)
    y = np.linspace(-1, 1)
    x_1, y_1 = np.meshgrid(x, y)
    P = np.zeros_like(x_1)
    for i, xi in enumerate(x):
        for j, yj in enumerate(y):
            P[i, j] = clf.decision_function(np.array([[xi, yj]]))
    ax.contour(x_1, y_1, P, colors='k', levels=[-1, 0, 0.9], alpha=0.5,
     linestyles=['--', '-', '--'])
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none');

    此时便完成了非线性分类。
    SVM 的基础知识的直观感受到此就结束了。

    代码(已折叠)

    # -*- coding: utf-8 -*-
    """
    Created on Tue Aug 11 10:12:48 2020
    
    @author: Admin
    """
    import numpy as np
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    from sklearn.datasets.samples_generator import make_circles
    # 画散点图
    X, y = make_circles(100, factor=.1, noise=.1, random_state=2019)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    clf = SVC(kernel='linear').fit(X, y)
    # 最佳函数
    x_fit = np.linspace(-1.5, 1.5)
    w = clf.coef_[0]
    a = -w[0] / w[1]
    y_3 = a*X - (clf.intercept_[0]) / w[1]
    plt.plot(X, y_3, '-c')
    
    
    from mpl_toolkits.mplot3d import Axes3D
    # 数据映射
    r = np.exp(-(X[:, 0] ** 2 + X[:, 1] ** 2))
    ax = plt.subplot(projection='3d')
    ax.scatter3D(X[:, 0], X[:, 1], r, c=y, s=50, cmap=plt.cm.Paired)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    x_1, y_1 = np.meshgrid(np.linspace(-1, 1), np.linspace(-1, 1))
    z = 0.01*x_1 + 0.01*y_1 + 0.5
    ax.plot_surface(x_1, y_1, z, alpha=0.3)
    
    # 画图
    X, y = make_circles(100, factor=.1, noise=.1, random_state=2019)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Paired)
    clf = SVC(kernel='rbf')
    clf.fit(X, y)
    ax = plt.gca()
    x = np.linspace(-1, 1)
    y = np.linspace(-1, 1)
    x_1, y_1 = np.meshgrid(x, y)
    P = np.zeros_like(x_1)
    for i, xi in enumerate(x):
        for j, yj in enumerate(y):
            P[i, j] = clf.decision_function(np.array([[xi, yj]]))
    ax.contour(x_1, y_1, P, colors='k', levels=[-1, 0, 0.9], alpha=0.5,
     linestyles=['--', '-', '--'])
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], edgecolor='b',
     s=80, facecolors='none');
    View Code

    文章转自:https://developer.aliyun.com/ai/scenario/b6c1ef3172d84236ae10c3b91798a796

  • 相关阅读:
    SGU 495 Kids and Prizes 概率DP 或 数学推理
    poj 2799 IP Networks 模拟 位运算
    uva 202 Repeating Decimals 模拟
    poj 3158 Kickdown 字符串匹配?
    uva 1595 Symmetry 暴力
    uva 201 Squares 暴力
    uva 1594 Ducci Sequence 哈希
    uva 1368 DNA Consensus String 字符串
    数字、字符串、列表的常用操作
    if条件判断 流程控制
  • 原文地址:https://www.cnblogs.com/cgmcoding/p/13559376.html
Copyright © 2011-2022 走看看