
文章插图
这样,对偶优化问题就变成:

文章插图
直观地,推理方程(经过代数处理后)为:

文章插图
上面所有方程的完整推导,有很多相关的文章了,我们就不详细介绍了 。
Python/ target=_blank class=infotextkey>Python实现对于实现,我们将使用下面这些库:
import numpy as np# for basic operations over arrays from scipy.spatial import distance # to compute the Gaussian kernel import cvxopt# to solve the dual opt. problem import copy# to copy numpy arrays定义核和SVM超参数,我们将实现常见的三个核函数:
文章插图
class SVM:linear = lambda x, x? , c=0: x @ x?.Tpolynomial = lambda x, x? , Q=5: (1 + x @ x?.T)**Qrbf = lambda x, x?, γ=10: np.exp(-γ*distance.cdist(x, x?,'sqeuclidean'))kernel_funs = {'linear': linear, 'polynomial': polynomial, 'rbf': rbf}为了与其他核保持一致,线性核采用了一个额外的无用的超参数 。kernel_funs接受核函数名称的字符串,并返回相应的内核函数 。继续定义构造函数:
class SVM:linear = lambda x, x? , c=0: x @ x?.Tpolynomial = lambda x, x? , Q=5: (1 + x @ x?.T)**Qrbf = lambda x, x?, γ=10: np.exp(-γ*distance.cdist(x, x?,'sqeuclidean'))kernel_funs = {'linear': linear, 'polynomial': polynomial, 'rbf': rbf}def __init__(self, kernel='rbf', C=1, k=2):# set the hyperparametersself.kernel_str = kernelself.kernel = SVM.kernel_funs[kernel]self.C = C# regularization parameterself.k = k# kernel parameter# trAIning data and support vectors (set later)self.X, y = None, Noneself.αs = None# for multi-class classification (set later)self.multiclass = Falseself.clfs = []SVM有三个主要的超参数,核(我们存储给定的字符串和相应的核函数) , 正则化参数C和核超参数(传递给核函数);它表示多项式核的Q和RBF核的γ 。为了兼容sklearn的形式,我们需要使用fit和predict函数来扩展这个类,定义以下函数,并在稍后将其用作装饰器:
SVMClass = lambda func: setattr(SVM, func.__name__, func) or func拟合SVM对应于通过求解对偶优化问题找到每个点的支持向量α:
文章插图
设α为可变列向量(α?α?…α _n);y为标签(y?α?…y_N)常数列向量;K为常数矩阵,其中K[n,m]计算核在(x, x)处的值 。点积、外积和二次型分别基于索引的等价表达式:

文章插图
可以将对偶优化问题写成矩阵形式如下:

文章插图
这是一个二次规划,CVXOPT的文档中解释如下:

文章插图
可以只使用(P,q)或(P,q,G,h)或(P,q,G,h, A, b)等等来调用它(任何未给出的都将由默认值设置 , 例如1) 。
对于(P, q, G, h, A, b)的值,我们的例子可以做以下比较:

文章插图
为了便于比较,将第一个重写如下:

文章插图
现在很明显(0≤α等价于-α≤0):

文章插图
我们就可以写出如下的fit函数:
@SVMClass def fit(self, X, y, eval_train=False):# if more than two unique labels, call the multiclass versionif len(np.unique(y)) > 2:self.multiclass = Truereturn self.multi_fit(X, y, eval_train)# if labels given in {0,1} change it to {-1,1}if set(np.unique(y)) == {0, 1}: y[y == 0] = -1# ensure y is a Nx1 column vector (needed by CVXOPT)self.y = y.reshape(-1, 1).astype(np.double) # Has to be a column vectorself.X = XN = X.shape[0] # Number of points# compute the kernel over all possible pairs of (x, x') in the data# by Numpy's vectorization this yields the matrix Kself.K = self.kernel(X, X, self.k)### Set up optimization parameters# For 1/2 x^T P x + q^T xP = cvxopt.matrix(self.y @ self.y.T * self.K)q = cvxopt.matrix(-np.ones((N, 1)))# For Ax = bA = cvxopt.matrix(self.y.T)b = cvxopt.matrix(np.zeros(1))# For Gx <= hG = cvxopt.matrix(np.vstack((-np.identity(N),np.identity(N))))h = cvxopt.matrix(np.vstack((np.zeros((N,1)),np.ones((N,1)) * self.C)))# Solvecvxopt.solvers.options['show_progress'] = Falsesol = cvxopt.solvers.qp(P, q, G, h, A, b)self.αs = np.array(sol["x"])# our solution# a Boolean array that flags points which are support vectorsself.is_sv = ((self.αs-1e-3 > 0)&(self.αs <= self.C)).squeeze()# an index of some margin support vectorself.margin_sv = np.argmax((0 < self.αs-1e-3)&(self.αs < self.C-1e-3))if eval_train:print(f"Finished training with accuracy{self.evaluate(X, y)}")
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Python常见异常汇总
- 使用Java AOP实现面向切面编程
- Python的集合模块,使用数据容器处理数据集合
- Python 既是解释型语言,也是编译型语言
- Jest:目前最广泛使用的前端 JavaScript 测试框架
- Python 真的很糟糕吗?
- 怎么选购儿童学习桌
- 连霍高速是从哪里到哪里,连霍高速起始地点是哪里
- 粉扑脏了怎么洗白 粉扑脏了怎么洗
- 欧洲卡车模拟2怎么改MOD,欧洲卡车模拟2怎么使用MOD
