如何使用从 cvxopt.solvers 获得的参数绘制非线性决策边界?

Posted

技术标签:

【中文标题】如何使用从 cvxopt.solvers 获得的参数绘制非线性决策边界?【英文标题】:How to plot the non-linear decision boundary using the parameters obtained from the cvxopt.solvers? 【发布时间】:2020-10-06 12:51:46 【问题描述】:

我试图从here 理解 SVM。在了解内核时,我遇到了以下情节。 (由我根据here中给出的数据绘制)

通过使用这个数据和cvxopt.solvers,我得到了参数wb。使用以下 python 代码,其中我使用 2 次多项式内核并获得决策边界,如代码旁边的图所示。

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()

但我想绘制可以分离数据的非线性决策边界,如下所示。

我知道我需要选择一个适当的多项式方程,但是如何找到它并绘制决策边界? 注意:来自here 我得到了绘制非线性决策边界的想法

【问题讨论】:

【参考方案1】:

这里我使用sklearn- svm.NuSVC() 而不是cvxopt.solver。我认为这个book作者也使用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() 

结果附在这里:

【讨论】:

以上是关于如何使用从 cvxopt.solvers 获得的参数绘制非线性决策边界?的主要内容,如果未能解决你的问题,请参考以下文章

python圆角三角形的参值

Qt Creator - 未获得某些 OpenCV 构造函数的函数参数提示

Laravel单一作业类被分派了多次,不同的参数被覆盖了

正确的参数数

弧长的参方程表示形式

Java 函数的参数说