【问题标题】:How to draw the hyperplanes for SVM One-Versus-All?如何为 SVM One-Versus-All 绘制超平面?
【发布时间】:2021-03-09 06:29:15
【问题描述】:

当 SVM-OVA 执行如下操作时,我试图绘制超平面:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
x = np.array([[1,1.1],[1,2],[2,1]])
y = np.array([0,100,250])
classifier = OneVsRestClassifier(SVC(kernel='linear'))

根据Plot hyperplane Linear SVM python这个问题的答案,我写了如下代码:

fig, ax = plt.subplots()
# create a mesh to plot in
x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
xx2, yy2 = np.meshgrid(np.arange(x_min, x_max, .2),np.arange(y_min, y_max, .2))
Z = classifier.predict(np.c_[xx2.ravel(), yy2.ravel()])
Z = Z.reshape(xx2.shape)
ax.contourf(xx2, yy2, Z, cmap=plt.cm.winter, alpha=0.3)
ax.scatter(x[:, 0], x[:, 1], c=y, cmap=plt.cm.winter, s=25)

# First line: class1 vs (class2 U class3)
w = classifier.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (classifier.intercept_[0]) / w[1]
ax.plot(xx,yy)

# Second line: class2 vs (class1 U class3)
w = classifier.coef_[1]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (classifier.intercept_[1]) / w[1]
ax.plot(xx,yy)

# Third line: class 3 vs (class2 U class1)
w = classifier.coef_[2]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (classifier.intercept_[2]) / w[1]
ax.plot(xx,yy)

然而,这是我得到的:

线条显然是错误的:实际上,角度系数似乎正确,但截距却不正确。特别是,橙色线向下平移 0.5 表示正确,绿色向左平移 0.5 表示正确,蓝色线向上平移 1.5 表示正确。

是我画的线不对,还是分类器因为训练点少而不能正常工作?

【问题讨论】:

    标签: python machine-learning scikit-learn svm multiclass-classification


    【解决方案1】:

    问题是SVCC参数太小(默认1.0)。根据this post

    相反,一个非常小的 C 值将导致优化器寻找一个更大边距的分离超平面,即使该超平面错误分类更多点。

    因此,解决方案是使用更大的C,例如1e5

    import matplotlib.pyplot as plt
    import numpy as np
    from sklearn.svm import SVC
    from sklearn.multiclass import OneVsRestClassifier
    
    
    x = np.array([[1,1.1],[1,2],[2,1]])
    y = np.array([0,100,250])
    classifier = OneVsRestClassifier(SVC(C=1e5,kernel='linear'))
    classifier.fit(x,y)
    
    fig, ax = plt.subplots()
    # create a mesh to plot in
    x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
    y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
    xx2, yy2 = np.meshgrid(np.arange(x_min, x_max, .2),np.arange(y_min, y_max, .2))
    Z = classifier.predict(np.c_[xx2.ravel(), yy2.ravel()])
    Z = Z.reshape(xx2.shape)
    ax.contourf(xx2, yy2, Z, cmap=plt.cm.winter, alpha=0.3)
    ax.scatter(x[:, 0], x[:, 1], c=y, cmap=plt.cm.winter, s=25)
    
    def reconstruct(w,b):
    
        k = - w[0] / w[1]
        b = - b[0] / w[1]
    
        if k >= 0:
            x0 = max((y_min-b)/k,x_min)
            x1 = min((y_max-b)/k,x_max)
        else:
            x0 = max((y_max-b)/k,x_min)
            x1 = min((y_min-b)/k,x_max)
        if np.abs(x0) == np.inf: x0 = x_min
        if np.abs(x1) == np.inf: x1 = x_max
        
        xx = np.linspace(x0,x1)
        yy = k*xx+b
    
        return xx,yy
    
    xx,yy = reconstruct(classifier.coef_[0],classifier.intercept_[0])
    ax.plot(xx,yy,'r')
    xx,yy = reconstruct(classifier.coef_[1],classifier.intercept_[1])
    ax.plot(xx,yy,'g')
    xx,yy = reconstruct(classifier.coef_[2],classifier.intercept_[2])
    ax.plot(xx,yy,'b')
    

    这一次,因为采用了更大的C,结果看起来更好

    【讨论】:

      猜你喜欢
      • 2018-06-18
      • 2016-07-20
      • 2014-07-13
      • 2018-03-12
      • 2013-12-01
      • 2020-01-28
      • 2016-06-19
      • 2011-12-22
      相关资源
      最近更新 更多