SVM One-Versus-All에 대한 하이퍼 플레인을 그리는 방법은 무엇입니까?

Nov 26 2020

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 위로 이동하면 정확합니다.

선을 그리는 것이 잘못되었거나 몇 가지 훈련 포인트로 인해 분류 기가 올바르게 작동하지 않습니까?

답변

5 meTchaikovsky Dec 01 2020 at 12:38

문제는의 C매개 변수 SVC가 너무 작다는 것입니다 (기본적으로 1.0). 이 게시물 에 따르면 ,

반대로, 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채택 했기 때문에 결과가 더 좋아 보입니다