【问题标题】:Extract decision boundary with scikit-learn linear SVM使用 scikit-learn 线性 SVM 提取决策边界
【发布时间】:2014-07-10 18:00:21
【问题描述】:

我有一个非常简单的一维分类问题:一个值列表 [0, 0.5, 2] 及其关联的类 [0, 1, 2]。我想得到这些类之间的分类边界。

调整iris example(用于可视化目的),摆脱非线性模型:

X = np.array([[x, 1] for x in [0, 0.5, 2]]) 
Y = np.array([1, 0, 2])

C = 1.0  # SVM regularization parameter
svc = svm.SVC(kernel='linear', C=C).fit(X, Y)
lin_svc = svm.LinearSVC(C=C).fit(X, Y)

给出以下结果:

LinearSVC 返回垃圾(为什么?),但带有线性内核的 SVC 工作正常。所以我想得到边界值,你可以用图形猜测:~0.25 和~1.25。

这就是我迷路的地方:svc.coef_ 返回

array([[ 0.5       ,  0.        ],
       [-1.33333333,  0.        ],
       [-1.        ,  0.        ]])

svc.intercept_ 返回array([-0.125 , 1.66666667, 1. ])。 这不是明确的。

我一定是错过了一些愚蠢的东西,如何获得这些值?它们似乎很容易计算,在 x 轴上迭代以找到边界是很荒谬的......

【问题讨论】:

    标签: python classification scikit-learn svm


    【解决方案1】:

    从 SVM 获取决策线,演示 1

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import svm
    from sklearn.datasets import make_blobs
    # we create 40 separable points
    X, y = make_blobs(n_samples=40, centers=2, random_state=6)
    # fit the model, don't regularize for illustration purposes
    clf = svm.SVC(kernel='linear', C=1000)
    clf.fit(X, y)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
    # plot the decision function
    ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    # create grid to evaluate model
    xx = np.linspace(xlim[0], xlim[1], 30)
    yy = np.linspace(ylim[0], ylim[1], 30)
    YY, XX = np.meshgrid(yy, xx)
    xy = np.vstack([XX.ravel(), YY.ravel()]).T
    Z = clf.decision_function(xy).reshape(XX.shape)
    # plot decision boundary and margins
    ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])
    # plot support vectors
    ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=100,
               linewidth=1, facecolors='none')
    plt.show()
    

    打印:

    逼近 SVM 的分离 n-1 维超平面,演示 2

    import numpy as np
    import mlpy
    from sklearn import svm
    from sklearn.svm import SVC
    import matplotlib.pyplot as plt
    np.random.seed(0)
    mean1, cov1, n1 = [1, 5], [[1,1],[1,2]], 200  # 200 samples of class 1
    x1 = np.random.multivariate_normal(mean1, cov1, n1)
    y1 = np.ones(n1, dtype=np.int)
    
    mean2, cov2, n2 = [2.5, 2.5], [[1,0],[0,1]], 300 # 300 samples of class -1
    x2 = np.random.multivariate_normal(mean2, cov2, n2)
    y2 = 0 * np.ones(n2, dtype=np.int)
    X = np.concatenate((x1, x2), axis=0) # concatenate the 1 and -1 samples
    y = np.concatenate((y1, y2))
    clf = svm.SVC()
    #fit the hyperplane between the clouds of data, should be fast as hell
    clf.fit(X, y)
    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)
    
    production_point = [1., 2.5]
    
    answer = clf.predict([production_point])
    print("Answer: " + str(answer))
    plt.plot(x1[:,0], x1[:,1], 'ob', x2[:,0], x2[:,1], 'or', markersize = 5)
    colormap = ['r', 'b']
    color = colormap[answer[0]]
    plt.plot(production_point[0], production_point[1], 'o' + str(color), markersize=20)
    
    #I want to draw the decision lines
    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)
    YY, XX = np.meshgrid(yy, xx)
    xy = np.vstack([XX.ravel(), YY.ravel()]).T
    Z = clf.decision_function(xy).reshape(XX.shape)
    ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])
    plt.show()
    

    打印:

    这些超平面都像箭头一样笔直,它们只是在更高维度上是笔直的,仅仅被限制在 3 维空间中的凡人无法理解。这些超平面通过创造性的内核函数被投射到更高的维度,而不是为了您的观看乐趣而变平回可见维度。这是一段视频,试图让您直观地了解演示 2 中发生的事情:https://www.youtube.com/watch?v=3liCbRZPrZA

    【讨论】:

    【解决方案2】:

    根据 coef_ 和 intercept_ 计算的精确边界


    我认为这是一个很好的问题,并且无法在文档中的任何地方找到通用答案。这个网站确实需要 Latex,但无论如何,我会尽我所能,不...

    通常,超平面由其单位法线和与原点的偏移量定义。所以我们希望找到某种形式的决策函数:x dot n + d > 0(其中>当然可以替换为>=)。

    SVM Margins Example 的情况下,我们可以操纵它们开始的方程式以阐明其概念意义。首先,让我们建立用coef 来表示coef_[0]intercept 来表示intercept_[0] 的符号方便性,因为这些数组只有1 个值。然后一些简单的替换产生方程:

    y + coef[0]*x/coef[1] + intercept/coef[1] = 0
    

    乘以coef[1],得到

    coef[1]*y + coef[0]*x + intercept = 0
    

    因此我们看到系数和截距函数大致如其名称所暗示的那样。应用符号的一种快速概括应该可以清楚地说明答案 - 我们将用单个向量 x 替换 xy

    coef[0]*x[0] + coef[1]*x[1] + intercept = 0
    

    一般来说,svm 分类器的 coef_ 和 intercept_ 成员的维度与训练它的数据集相匹配,因此我们可以将此方程外推到任意维度的数据。并且为了避免让任何人误入歧途,这里是使用来自 svm 的原始变量名称的最终广义决策边界

    coef_[0][0]*x[0] + coef_[0][1]*x[1] + coef_[0][2]*x[2] + ... + coef_[0][n-1]*x[n-1] + intercept_[0] = 0
    

    其中数据的维度为n

    或者更简洁:

    sum(coef_[0][i]*x[i]) + intercept_[0] = 0
    

    其中i 在输入数据的维度范围内求和。

    【讨论】:

      【解决方案3】:

      我有同样的问题,最终在sklearn documentation找到了解决方案。

      给定权重 W=svc.coef_[0] 和截距 I=svc.intercept_ ,决策边界是直线

      y = a*x - b
      

      a = -W[0]/W[1]
      b = I[0]/W[1]
      

      【讨论】:

      • 我觉得应该是W=svc.coef[0]
      • @Tom:没错!现已修复。
      猜你喜欢
      • 2018-12-20
      • 2019-09-10
      • 2016-07-13
      • 2018-02-04
      • 2013-12-13
      • 2021-07-30
      • 2016-03-18
      • 2015-07-07
      • 2014-03-15
      相关资源
      最近更新 更多