簡體   English   中英

如何使用從 cvxopt.solvers 獲得的參數 plot 非線性決策邊界?

[英]How to plot the non-linear decision boundary using the parameters obtained from the cvxopt.solvers?

我試圖從這里理解 SVM。 在了解內核時,我遇到了以下 plot。 (由我根據此處給出的數據繪制)

在此處輸入圖像描述

通過使用這些數據和cvxopt.solvers我獲得了參數wb 使用以下 python 代碼,其中我使用 2 次多項式 kernel 並獲得決策邊界,如代碼旁邊的 plot 所示。

import numpy as np
from succinctly.datasets import get_dataset, non_separable_poly as nsp
import matplotlib.pyplot as plt
from cvxopt import matrix as cvxopt_matrix
import cvxopt.solvers

C=1000 #hard margin 
X_data, y_data = get_dataset(nsp.get_training_examples)
x1= np.arange(0,20,1)
degree=2

def compute_w(multipliers, X, y):
    return np.sum(multipliers[i] * y[i] * X[i]for i in range(len(y)))

def compute_b(w, X, y):
    return np.sum([y[i] - np.dot(w, X[i])for i in range(len(X))])/len(X)

def polynomial_kernel(a, b, degree, constant=0):
    result = sum([a[i] * b[i] for i in range(len(a))]) + constant
    return pow(result, degree)

def decision_boundary(x_1,w,b,degree):
    if degree==1:
        b1=b
        a1= -w[0]/w[1]
        c1=-b1/w[1]
        y1=a1*x1+c1
        return y1
    elif degree>1:
        y1= np.sqrt(w[0]*x_1**2 + w[1]*x_1**1 + b + np.log(128))
        return y1[::-1]
m = X_data.shape[0]

# Gram matrix - The matrix of all possible inner products of X.
K = np.array([polynomial_kernel(X_data[i], X_data[j],degree)for j in range(m) for i in range(m)]).reshape((m, m))

P = cvxopt.matrix(np.outer(y_data, y_data) * K)
q = cvxopt.matrix(-1 * np.ones(m))

# Equality constraints
A = cvxopt.matrix(y_data, (1, m))
b = cvxopt.matrix(0.0)

# Inequality constraints
G = cvxopt_matrix(np.vstack((np.eye(m)*-1,np.eye(m))))
h = cvxopt_matrix(np.hstack((np.zeros(m), np.ones(m) * C)))

# Solve the problem
solution = cvxopt.solvers.qp(P, q, G, h, A, b)

# Lagrange multipliers
multipliers = np.ravel(solution['x'])

# Support vectors have positive multipliers.
has_positive_multiplier = multipliers > 1e-7
sv_multipliers = multipliers[has_positive_multiplier]

support_vectors = X_data[has_positive_multiplier]
support_vectors_y = y_data[has_positive_multiplier]

w = compute_w(multipliers, X_data, y_data)
b = compute_b(w, support_vectors, support_vectors_y) 

a0=X_data[0:8,0]
b0=X_data[0:8,1]
c0=X_data[8:16,0]
d0=X_data[8:16,1]

fig = plt.figure(figsize=(6,6))

plt.plot(a0,b0,"r^",c0,d0,"b*",markersize=8)

# Adding decision boundary to plot
bound = decision_boundary(x1,w,b,degree)
plt.plot(x1, bound, 'k', lw=1)

plt.title('Figure 6:A straight line cannot separate the data',fontsize=14)

plt.xlabel(r'$x$',fontsize=14)
plt.ylabel(r'$y$',fontsize=14)
# Turn on the minor TICKS, which are required for the minor GRID
plt.minorticks_on()

# Customize the major grid
plt.grid(which='major', linestyle='-', linewidth='0.3', color='black')
# Customize the minor grid

plt.grid(which='minor', linestyle=':', linewidth='0.3', color='black')
plt.legend(["Class0", "Class1"], loc="upper right",prop=dict(size=8))
plt.ylim(0,20)
plt.xlim(0,20)
plt.show()

在此處輸入圖像描述

但我想 plot 可以分離數據的非線性決策邊界,如下所示。

在此處輸入圖像描述

我知道我需要選擇一個合適的多項式方程,但是如何找到它和 plot 的決策邊界? 注意:這里我得到 plot 非線性決策邊界的想法

在這里,我使用sklearn- svm.NuSVC()而不是cvxopt.solver 我認為本書作者也使用 scikit-learn 來解決非線性 SVM 問題,但沒有明確提及。

所以這里是 python 代碼

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from succinctly.datasets import get_dataset, non_separable_poly as nsp


xx, yy = np.meshgrid(np.linspace(0, 20, 500),
                     np.linspace(0, 20, 500))

X_data, y_data = get_dataset(nsp.get_training_examples)

fig = plt.figure(figsize=(16,5))
fig.suptitle("Figure 10: A SVM using a polynomial kernel is able to separate the data (degree=1,2,6)", fontsize=14)

for k,degree in enumerate([1,2,6]):
    d=degree
    ax=plt.subplot(1, 3, k + 1)
    if d==1:
        C=0.5
    elif d>1:
        C=0.1
    # fit the model
    clf = svm.NuSVC(nu=C,kernel='poly',degree=d ,gamma='auto')
    clf.fit(X_data, y_data)

    a0=X_data[0:8,0]
    b0=X_data[0:8,1]
    c0=X_data[8:16,0]
    d0=X_data[8:16,1]

    plt.plot(a0,b0,"r^",c0,d0,"b*",markersize=8)

    # plot the decision function for each datapoint on the grid
    Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)

    contours = plt.contour(xx, yy, Z, levels=[0], linewidths=1,linestyles='-')

    plt.xlabel(r'$x$',fontsize=14)
    plt.ylabel(r'$y$',fontsize=14)
    # Turn on the minor TICKS, which are required for the minor GRID
    plt.minorticks_on()

    # Customize the major grid
    plt.grid(which='major', linestyle='-', linewidth='0.3', color='black')
    # Customize the minor grid

    plt.grid(which='minor', linestyle=':', linewidth='0.3', color='black')
    plt.legend(["Class0", "Class1"], loc="upper right",prop=dict(size=8))
    ax.set_title(" A polynomial kernel with degree={}".format(degree))
plt.show() 

結果附在這里: 在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM