如何使用从 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
,我得到了参数w
和b
。使用以下 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 获得的参数绘制非线性决策边界?的主要内容,如果未能解决你的问题,请参考以下文章