使用Python从零实现多分类SVM

本文将首先简要概述支持向量机及其训练和推理方程,然后将其转换为代码以开发支持向量机模型。之后然后将其扩展成多分类的场景,并通过使用sci-kit learn测试我们的模型来结束。  
svm概述
支持向量机的目标是拟合获得最大边缘的超平面(两个类中最近点的距离)。可以直观地表明,这样的超平面(a)比没有最大化边际的超平面(b)具有更好的泛化特性和对噪声的鲁棒性。  为了实现这一点,svm通过求解以下优化问题找到超平面的w和b:      它试图找到w,b,使最近点的距离最大化,并正确分类所有内容(如y取±1的约束)。这可以被证明相当于以下优化问题:    可以写出等价的对偶优化问题      这个问题的解决方案产生了一个拉格朗日乘数,我们假设数据集中的每个点的大小为m:(α 1, α 2,…,α _n)。目标函数在α中明显是二次的,约束是线性的,这意味着它可以很容易地用二次规划求解。一旦找到解,由对偶的推导可知:      注意,只有具有α>0的点才定义超平面(对和有贡献)。这些被称为支持向量。因此当给定一个新例子x时,返回其预测y=±1的预测方程为:      这种支持向量机的基本形式被称为硬边界支持向量机(hard margin svm),因为它解决的优化问题(如上所述)强制要求训练中的所有点必须被正确分类。但在实际场景中,可能存在一些噪声,阻止或限制了完美分离数据的超平面,在这种情况下,优化问题将不返回或返回一个糟糕的解决方案。      软边界支持向量机(soft margin svm)通过引入c常数(用户给定的超参数)来适应优化问题,该常数控制它应该有多“硬”。特别地,它将原优化问题修改为:      它允许每个点产生一些错误λ(例如,在超平面的错误一侧),并且通过将它们在目标函数中的总和加权c来减少它们。当c趋于无穷时(一般情况下肯定不会),它就等于硬边界。与此同时,较小的c将允许更多的“违规行为”(以换取更大的支持;例如,更小的w (w)。  可以证明,等价对偶问题只有在约束每个点的α≤c时才会发生变化。      由于允许违例,支持向量(带有α>0的点)不再都在边界的边缘。任何错误的支持向量都具有α=c,而非支持向量(α=0)不能发生错误。我们称潜在错误(α=c)的支持向量为“非错误编剧支持向量”和其他纯粹的支持向量(没有违规;“边界支持向量”(0<α 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 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(ffinished training with accuracy{self.evaluate(x, y)}) 我们确保这是一个二进制问题,并且二进制标签按照支持向量机(±1)的假设设置,并且y是一个维数为(n,1)的列向量。然后求解求解(α₁α₂…α _n) 的优化问题。  使用(α₁α₂…α _n) _来获得在与支持向量对应的任何索引处为1的标志数组,然后可以通过仅对支持向量和(xₛ,yₛ)的边界支持向量的索引求和来应用预测方程。我们确实假设非支持向量可能不完全具有α=0,如果它的α≤1e-3,那么这是近似为零(cvxopt结果可能不是最终精确的)。同样假设非边际支持向量可能不完全具有α=c。  下面就是预测的方法,预测方程为:    @svmclassdef predict(self, x_t):if self.multiclass: return self.multi_predict(x_t)# compute (xₛ, yₛ)xₛ, yₛ = self.x[self.margin_sv, np.newaxis], self.y[self.margin_sv]# find support vectorsαs, y, x= self.αs[self.is_sv], self.y[self.is_sv], self.x[self.is_sv]# compute the second termb = yₛ - np.sum(αs * y * self.kernel(x, xₛ, self.k), axis=0)# compute the scorescore = np.sum(αs * y * self.kernel(x, x_t, self.k), axis=0) + breturn np.sign(score).astype(int), score  我们还可以实现一个评估方法来计算精度(在上面的fit中使用)。@svmclassdef evaluate(self, x,y): outputs, _ = self.predict(x)accuracy = np.sum(outputs == y) / len(y)return round(accuracy, 2) 最后测试我们的完整代码:from sklearn.datasets import make_classificationimport numpy as np# load the datasetnp.random.seed(1)x, y = make_classification(n_samples=2500, n_features=5, n_redundant=0, n_informative=5, n_classes=2, class_sep=0.3)# test implemented svmsvm = svm(kernel='rbf', k=1)svm.fit(x, y, eval_train=true)y_pred, _ = svm.predict(x)print(faccuracy: {np.sum(y==y_pred)/y.shape[0]}) #0.9108# test with scikitfrom sklearn.svm import svcclf = svc(kernel='rbf', c=1, gamma=1)clf.fit(x, y)y_pred = clf.predict(x)print(faccuracy: {sum(y==y_pred)/y.shape[0]}) #0.9108  
多分类svm
我们都知道svm的目标是二元分类,如果要将模型推广到多类则需要为每个类训练一个二元svm分类器,然后对每个类进行循环,并将属于它的点重新标记为+1,并将所有其他类的点重新标记为-1。  当给定k个类时,训练的结果是k个分类器,其中第i个分类器在数据上进行训练,第i个分类器被标记为+1,所有其他分类器被标记为-1。@svmclassdef multi_fit(self, x, y, eval_train=false):self.k = len(np.unique(y)) # number of classes# for each pair of classesfor i in range(self.k):# get the data for the pairxs, ys = x, copy.copy(y)# change the labels to -1 and 1ys[ys!=i], ys[ys==i] = -1, +1# fit the classifierclf = svm(kernel=self.kernel_str, c=self.c, k=self.k)clf.fit(xs, ys)# save the classifierself.clfs.append(clf)if eval_train: print(ffinished training with accuracy {self.evaluate(x, y)})  然后,为了对新示例执行预测,我们选择相应分类器最自信(得分最高)的类。@svmclassdef multi_predict(self, x):# get the predictions from all classifiersn = x.shape[0]preds = np.zeros((n, self.k))for i, clf in enumerate(self.clfs):_, preds[:, i] = clf.predict(x)# get the argmax and the corresponding scorereturn np.argmax(preds, axis=1), np.max(preds, axis=1) 完整测试代码:from sklearn.datasets import make_classificationimport numpy as np# load the datasetnp.random.seed(1)x, y = make_classification(n_samples=500, n_features=2, n_redundant=0, n_informative=2, n_classes=4, n_clusters_per_class=1, class_sep=0.3)# test svmsvm = svm(kernel='rbf', k=4)svm.fit(x, y, eval_train=true)y_pred = svm.predict(x)print(faccuracy: {np.sum(y==y_pred)/y.shape[0]}) # 0.65# test with scikitfrom sklearn.multiclass import onevsrestclassifierfrom sklearn.svm import svcclf = onevsrestclassifier(svc(kernel='rbf', c=1, gamma=4)).fit(x, y)y_pred = clf.predict(x)print(faccuracy: {sum(y==y_pred)/y.shape[0]}) # 0.65 绘制每个决策区域的图示,得到以下图:      可以看到,我们的实现与sci-kit learn结果相当,说明在算法实现上没有问题。注意:svm默认支持ovr(没有如上所示的显式调用),它是特定于svm的进一步优化。  
总结
我们使用python实现了支持向量机(svm)学习算法,并且包括了软边界和常用的三个核函数。我们还将svm扩展到多分类的场景,并使用sci-kit learn验证了我们的实现。希望通过本文你可以更好的了解svm。

用于24位ADC的抗混叠滤波器
高价值货物在运输过程中的冲击、温湿度气压和光照监测(带 GPS跟踪定位)
5G工业路由器与工业网关有区别吗?
网络变压器中的直流电阻对阻断EMI有怎样的影响?
移动电源上亚马逊平台销售是做UL2056的测试报告吗?
使用Python从零实现多分类SVM
大联大友尚集团推出基于onsemi和GaN System产品的65W PD电源方案
带有同步器的NoC结构是解决FPGA高速时序收敛的关键原因吗?
具有函数信号发生器和计数器的功能仪器的设计与实现
Flexpoint推触觉手套开发套件 允许用户DIY自己的触感手套
音圈马达无人机助力城市管理
低成本小功率超声波清洗电源线路板设计
区块链将如何解决会计行业中的一些问题
运用RS9116 Wi-Fi入门套件开发低功耗、多协议物联网应用
Credo Dove系列产品全部具有哪些Credo 数字信号处理技术的关键特性?
百度召开内部沟通会 所有岗位员工涨薪
一体化速印机的分辨率
全面进攻服务器市场,ARM的优势如何?
2018年LED产业形势展望
全球首款可量产的基于RISC-V的工业级高性能边缘应用处理器