简体   繁体   English

如何为 SVM One-Versus-All 绘制超平面?

[英]How to draw the hyperplanes for SVM One-Versus-All?

I was trying to draw the hyperplanes when SVM-OVA was performed as following:当 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'))

Based on the answer to this question Plot hyperplane Linear SVM python , I wrote the following code:基于对这个问题Plot 超平面线性 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)

However, this is what I obtained:但是,这是我得到的:

在此处输入图像描述

The lines are clearly wrong: actually, the angular coefficients seem correct, but not the intercepts.线条显然是错误的:实际上,angular 系数似乎正确,但截距不正确。 In particular, the orange line would be correct if translated by 0.5 down, the green one if translated by 0.5 left and the blue one if translated by 1.5 up.特别是,如果向下平移 0.5,橙色线是正确的,如果向左平移 0.5,则绿色线是正确的,如果向上平移 1.5,则蓝色线是正确的。

Am I wrong to draw the lines, or the classifier does not work correctly because of the few training points?是我画的线不对,还是分类器因为训练点少而不能正常工作?

The problem is the C parameter of SVC is too small (by default 1.0 ).问题是SVCC参数太小(默认为1.0 )。 According to this post ,根据这篇文章

Conversely, a very small value of C will cause the optimizer to look for a larger-margin separating hyperplane, even if that hyperplane misclassifies more points.相反,一个非常小的值 C 将导致优化器寻找更大边距的分离超平面,即使该超平面错误分类更多点。

Therefore, the solution is to use a much larger C , for example 1e5因此,解决方案是使用更大的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')

This time, because a much larger C is adopted, the result looks better这次因为采用了更大的C ,所以效果看起来更好

输出

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM