接触支持向量机(Support Vector Machine, SVM)有很长一段时间了,对它的原理一直懵懵懂懂。有幸在国科大听了兰艳艳老师的课,对SVM有了更加深入的认识,决定写成笔记记录下来,当作是一次回顾,也希望对读者有启发。

一、引入问题

如图1所示,有一堆邮件用点表示,其中绿色的点表示正常邮件,红色的点表示垃圾邮件,需要画出一条分类线将这两种类别的邮件分开。

图1 两种不同的邮件

假设我们找到了很多条直线,它们都能将正常邮件和垃圾邮件分开,如图2所示。那么问题来了,哪一条分类线才是适合这个问题的最好分类线呢?

图2 垃圾邮件的分类线

思考一下找到分类线后我们需要用它来做什么?我们需要用它来分类测试集上的数据,也就是分类未知的数据,那么我们当然是希望它在测试集上表现比较好,而不仅仅是能把训练集全部分对,所以我们要选择泛化误差最小的那条分类线。

这里通俗地解释一下泛化误差的意思:泛化误差就是衡量一个模型推广能力的指标,泛化误差小就是当给我们一个新的数据,模型也有很大可能将数据分为正确的一类。
根据泛化误差的准则,我们需要找到一条有足够容忍度的分类线,它能够容忍数据的轻微波动,这样的分类线推广能力才会强,泛化误差才会小。比如图2中,选择红线、黄线和紫线作为分类线,那么假如靠近分类线的红点稍微向左偏移,模型就会将它判定为绿色的那一类,这样明显是错误的,我们称模型的泛化性较差,推广能力不强,泛化误差较大。而对于图2中的黑线,我们肉眼可见,它的容忍区间很大,也就是它到旁边最近的绿点和红点的间隔较大,即使数据点稍有偏动,模型也能将其正确分类,我们称这样的模型泛化性较强,推广能力较强,泛化误差较小。

二、支持向量机(Support vector machine, SVM)

我们都知道,逻辑回归(Logistic Regression)是一个概率模型,通过计算概率大小来判断类别,概率越大,置信度(confidence)越高,更有把握将数据分到正确的一类。而同样地,在上面的垃圾邮件分类中,经过分析,黑色的线在分类上比其它颜色的线具有更高的confidence能将邮件数据分到正确的类别。那么问题来了,如果没有概率,SVM拿什么来定义confidence?
前面我们已经分析过了,黑色的线比其他线具有更大的容忍区间,因此它的泛化误差更小,confidence更高。而更大的容忍区间意味着邻近的数据点与分类线的距离更大,抗扰动能力更强,我们定义这个距离为间隔(margin),如图3所示,黑色的实线到左右两条黑色的虚线的距离就是margin,用它来衡量confidence大小,即,margin越大,confidence越高。SVM的任务就是找到这样的一条直线,这条直线能够使margin最大,所以SVM又称为最大化间隔(Max Margin)。注意:Max Margin是一种思想,而SVM属于Max Margin的一个典型代表。

图3 SVM的间隔

训练集训练好分类模型之后,将该分类模型用于测试数据上,如图4所示,A,B,C三个点为测试数据点,显然,如果将图中的黑色实线作为分类线,A,B,C三个点都将分为Spam这一类,但是它们三个点的confidence不同,原因是它们到黑色实线的距离不同,A到黑色实线的距离最小,所以将它分为Spam的confidence最小,C到黑色实线的距离最大,所以将它分为Spam的confidence最大。

图4 SVM的测试

三、SVM的数学表达

对于二分类问题,定义标签y∈{−1,1}y\in\lbrace-1, 1\rbracey∈{−1,1}。给定一个训练集(xi,yi),i≤n(x^i, y^i), i\leq n(xi,yi),i≤n,定义函数间隔(Functional margin):
γ^i=yi(wTxi+b)ifyi=1,wTxi+b>0ifyi=−1,wTxi+b<0(1)\hat{\gamma}^i = y^i(w^Tx^i+b) \tag{1} \\ if\quad y^i=1, \quad w^Tx^i+b > 0 \\ if\quad y^i=-1, \quad w^Tx^i+b < 0 γ^​i=yi(wTxi+b)ifyi=1,wTxi+b>0ifyi=−1,wTxi+b<0(1)

无论什么情况,yi(wTxi+b)>0y^i(w^Tx^i+b)>0yi(wTxi+b)>0,模型才能得到一个正确的分类,反映了γ^i\hat{\gamma}^iγ^​i首先是一个正的距离。
补充说明:给定一个正样本,即y=1y=1y=1,我们希望wTxi+bw^Tx^i+bwTxi+b不光大于0,还应该越大越好,这样子我们将其分为正类的confidence越高;同理,对于负样本,我们希望wTxi+bw^Tx^i+bwTxi+b小于0,并且越小越好,所以,对于函数间隔γ^i=yi(wTxi+b)\hat{\gamma}^i = y^i(w^Tx^i+b)γ^​i=yi(wTxi+b),我们希望它越大越好,越大confidence越高。函数间隔虽然不是几何意义上的间隔,但是依然可以作为衡量confidence的标准。也正是因为γ^i\hat{\gamma}^iγ^​i是通过定义一个函数反映了margin的效果,所以称之为函数间隔。
训练集上的所有数据离分类面最近的函数间隔定义为
γ^=min⁡i=1,2,...,nγ^i(2)\hat{\gamma} = \min_{i=1,2,...,n}\hat{\gamma}^i \tag{2} γ^​=i=1,2,...,nmin​γ^​i(2)
称为训练集上的函数间隔。
函数间隔并非真正意义上的几何间隔,几何间隔定义如下:
γi=yi(wTxi+b)∣∣w∣∣2γ=min⁡i=1,2,...,nγi⟹γ=γ^∣∣w∣∣2(3)\gamma^i = y^i\frac{(w^Tx^i+b)}{||w||_2} \tag{3} \\ \gamma = \min_{i=1,2,...,n}\gamma^i \\ \implies \gamma = \frac{\hat{\gamma}}{||w||_2} γi=yi∣∣w∣∣2​(wTxi+b)​γ=i=1,2,...,nmin​γi⟹γ=∣∣w∣∣2​γ^​​(3)
前面有提到过,margin就是距离分类线最近的点到分类线的距离,我们也称为几何margin,它能决定confidence。我们希望算法能够有一个最优的分类线,它应该有足够的容忍度,也就是意味着分类线距离最近邻的那个点都越远越好,即几何margin足够大。基于上面的标准,我们定义如下的算法:
max⁡γ,w,bγs.t.yi(wTxi+b)∣∣w∣∣2≥γ,i=1,2...,n(4)\max_{\gamma,w,b}\gamma \tag{4}\\ s.t.\quad y^i\frac{(w^Tx^i+b)}{||w||_2} \geq \gamma, \quad i=1,2...,n γ,w,bmax​γs.t.yi∣∣w∣∣2​(wTxi+b)​≥γ,i=1,2...,n(4)
上面的式子是一个最大化+约束条件的线性可分问题,这是SVM最早的思想。首先最大化几何margin,然后在约束条件上,任何其他点到分界线的距离都应该大于等于几何margin,因为几何margin就是最近邻点到分界线的距离,其他点的距离必然比它大,这样可以保证在训练样本上所有的点都能分对。
将(4)中公式改写成更容易求解的形式:
(1)利用几何margin和函数margin之间的关系:
max⁡γ,w,bγ^∣∣w∣∣2s.t.yi(wTxi+b)≥γ^,i=1,2...,n(5)\max_{\gamma,w,b}\frac{\hat{\gamma}}{||w||_2} \tag{5}\\ s.t.\quad y^i(w^Tx^i+b) \geq \hat{\gamma}, \quad i=1,2...,n γ,w,bmax​∣∣w∣∣2​γ^​​s.t.yi(wTxi+b)≥γ^​,i=1,2...,n(5)
(2)函数margin是随着www和bbb不断变化的,但是www和bbb如果是同倍数的放大或缩小,并不会影响分类线的位置。我们可以根据这个特性取合适的www,使得γ^=1\hat{\gamma}=1γ^​=1,也就是函数margin等于1,然后将(5)式子进行进一步简化:
min⁡w,b12∣∣w∣∣22s.t.yi(wTxi+b)≥1,i=1,2...,n(6)\min_{w,b}\frac{1}{2}||w||_2^2 \tag{6}\\ s.t.\quad y^i(w^Tx^i+b) \geq 1, \quad i=1,2...,n w,bmin​21​∣∣w∣∣22​s.t.yi(wTxi+b)≥1,i=1,2...,n(6)
这里解释一下为什么max问题变成了min问题:若γ^=1\hat{\gamma}=1γ^​=1,则max⁡γ,w,b1∣∣w∣∣2\max_{\gamma,w,b}\frac{1}{||w||_2}maxγ,w,b​∣∣w∣∣2​1​等价于min⁡w,b12∣∣w∣∣22\min_{w,b}\frac{1}{2}||w||_2^2minw,b​21​∣∣w∣∣22​。(6)式是SVM的基本形式,它是一个凸的二次优化的问题,它的最优解不光存在,而且唯一,因为它找的是12∣∣w∣∣22\frac{1}{2}||w||_2^221​∣∣w∣∣22​下最小的目标值。这个优化问题可用二次优化的方法来求解,但是事实上通常不会这么去做,因为这样一个二次优化问题的复杂度是非常高的。后面我们将介绍SVM的对偶形式,用它来解优化问题会更方便。

四、SVM的对偶形式

在讲对偶形式之前,我们先来回顾一下优化的概念。优化分为三种:(1)无约束优化;(2)等式约束条件;(3)不等式约束条件。无约束优化我们不必赘述,我们来看一下有约束条件的优化问题:
min⁡wf(w)s.t.gi(w)≤0,i=1,2...,khi(w)=0,i=1,2...,l(7)\min_{w}f(w) \tag{7}\\ s.t.\quad g_i(w) \leq 0, \quad i=1,2...,k \\ \quad h_i(w) = 0, \quad i=1,2...,l wmin​f(w)s.t.gi​(w)≤0,i=1,2...,khi​(w)=0,i=1,2...,l(7)
(7)式中含有等式和不等式的约束,而解决含有约束条件的优化问题必然要用到拉格朗日乘数法(Lagrange Multiplier Method)
L(w,α,β)=f(w)+∑i=1kαigi(w)+∑i=1lβihi(w)(8)L(w,\alpha,\beta)=f(w)+\sum_{i=1}^{k}\alpha_ig_i(w)+\sum_{i=1}^{l}\beta_ih_i(w) \tag{8} L(w,α,β)=f(w)+i=1∑k​αi​gi​(w)+i=1∑l​βi​hi​(w)(8)
其中,αi,βi\alpha_i, \beta_iαi​,βi​是拉格朗日乘子。令
θP(w)=max⁡α,β:αi≥0L(w,α,β)=max⁡α,β:αi≥0(f(w)+∑i=1kαigi(w)+∑i=1lβihi(w))(9)\theta_P(w)=\max_{\alpha,\beta:\alpha_i\geq0}L(w,\alpha,\beta) \tag{9}\\ =\max_{\alpha,\beta:\alpha_i\geq0}(f(w)+\sum_{i=1}^{k}\alpha_ig_i(w)+\sum_{i=1}^{l}\beta_ih_i(w)) θP​(w)=α,β:αi​≥0max​L(w,α,β)=α,β:αi​≥0max​(f(w)+i=1∑k​αi​gi​(w)+i=1∑l​βi​hi​(w))(9)
下面证明优化θP(w)\theta_P(w)θP​(w)就是优化f(w)f(w)f(w):
(1)假如www违反任何约束条件,则有gi(w)>0g_i(w)>0gi​(w)>0或者hi(w)≠0h_i(w) \ne 0hi​(w)​=0。当gi(w)>0g_i(w)>0gi​(w)>0,必然有αi≥0\alpha_i\geq0αi​≥0使得αigi(w)=∞\alpha_ig_i(w)=\infinαi​gi​(w)=∞,那么θP(w)=max⁡α,β:αi≥0L(w,α,β)=∞\theta_P(w)=\max_{\alpha,\beta:\alpha_i\geq0}L(w,\alpha,\beta)=\infinθP​(w)=maxα,β:αi​≥0​L(w,α,β)=∞,显然这不是我们想要的最优值。当hi(w)≠0h_i(w) \ne 0hi​(w)​=0,那么必然有βi\beta_iβi​使得βihi(w)=∞\beta_ih_i(w)=\infinβi​hi​(w)=∞,那么θP(w)=max⁡α,β:αi≥0L(w,α,β)=∞\theta_P(w)=\max_{\alpha,\beta:\alpha_i\geq0}L(w,\alpha,\beta)=\infinθP​(w)=maxα,β:αi​≥0​L(w,α,β)=∞,也不是我们想要的最优值。
(2)假如www不违反任何约束条件,则有gi(w)≤0g_i(w)\le0gi​(w)≤0且hi(w)=0h_i(w)=0hi​(w)=0。当gi(w)≤0g_i(w)\le0gi​(w)≤0,且αi≥0\alpha_i\geq0αi​≥0,必然有∑i=1kαigi(w)≤0\sum_{i=1}^{k}\alpha_ig_i(w)\le0∑i=1k​αi​gi​(w)≤0;当hi(w)=0h_i(w)=0hi​(w)=0,无论β\betaβ取任何值,必然有∑i=1lβihi(w)=0\sum_{i=1}^{l}\beta_ih_i(w)=0∑i=1l​βi​hi​(w)=0。因此,θP(w)=max⁡α,β:αi≥0L(w,α,β)=max⁡α,β:αi≥0(f(w)+0+0)=max⁡α,β:αi≥0f(w)=f(w)\theta_P(w)=\max_{\alpha,\beta:\alpha_i\geq0}L(w,\alpha,\beta)=\max_{\alpha,\beta:\alpha_i\geq0}(f(w)+0+0)=\max_{\alpha,\beta:\alpha_i\geq0}f(w)=f(w)θP​(w)=maxα,β:αi​≥0​L(w,α,β)=maxα,β:αi​≥0​(f(w)+0+0)=maxα,β:αi​≥0​f(w)=f(w)。
因此,θP(w)\theta_P(w)θP​(w)就等价于带有约束条件的f(w)f(w)f(w),而
min⁡wf(w)=min⁡wθP(w)=min⁡wmax⁡α,β:αi≥0L(w,α,β)(10)\min_wf(w)=\min_w\theta_P(w)=\min_w\max_{\alpha,\beta:\alpha_i\geq0}L(w,\alpha,\beta) \tag{10} wmin​f(w)=wmin​θP​(w)=wmin​α,β:αi​≥0max​L(w,α,β)(10)
上式与原始问题的解是一样的,定义p∗=min⁡wθP(w)p^*=\min_w\theta_P(w)p∗=minw​θP​(w)是原始问题的最优值。接下来正式进入我们的重头戏——对偶问题

θD(α,β)=min⁡wL(w,α,β)max⁡α,β:αi≥0θD(α,β)=max⁡α,β:αi≥0min⁡wL(w,α,β)(11)\theta_D(\alpha,\beta)=\min_{w}L(w,\alpha,\beta) \tag{11}\\ \max_{\alpha,\beta:\alpha_i\geq0}\theta_D(\alpha,\beta)=\max_{\alpha,\beta:\alpha_i\geq0}\min_{w}L(w,\alpha,\beta) θD​(α,β)=wmin​L(w,α,β)α,β:αi​≥0max​θD​(α,β)=α,β:αi​≥0max​wmin​L(w,α,β)(11)
跟原来的问题相比,原来是min,max问题,现在是max,min问题,将上式的最优值定义为d∗=max⁡α,β:αi≥0θD(α,β)d^*=\max_{\alpha,\beta:\alpha_i\geq0}\theta_D(\alpha,\beta)d∗=maxα,β:αi​≥0​θD​(α,β)。那么d∗d^*d∗和p∗p^*p∗有什么关系?

p∗=min⁡wmax⁡α,β:αi≥0L(w,α,β)≥min⁡wmax⁡α,β:αi≥0min⁡wL(w,α,β)=max⁡α,β:αi≥0min⁡wL(w,α,β)=d∗(12)p^*=\min_w\max_{\alpha,\beta:\alpha_i\geq0}L(w,\alpha,\beta) \ge \min_w\max_{\alpha,\beta:\alpha_i\geq0}\min_wL(w,\alpha,\beta) \tag{12}\\ =\max_{\alpha,\beta:\alpha_i\geq0}\min_{w}L(w,\alpha,\beta)=d^* p∗=wmin​α,β:αi​≥0max​L(w,α,β)≥wmin​α,β:αi​≥0max​wmin​L(w,α,β)=α,β:αi​≥0max​wmin​L(w,α,β)=d∗(12)
由上面的推导可知,d∗≤p∗d^*\le p^*d∗≤p∗。我们将d∗=max⁡α,β:αi≥0θD(α,β)d^*=\max_{\alpha,\beta:\alpha_i\geq0}\theta_D(\alpha,\beta)d∗=maxα,β:αi​≥0​θD​(α,β)称为原始问题的一个对偶问题,并且希望用对偶问题替代原问题求解,复杂度会降低,所以我们希望d∗≤p∗d^*\le p^*d∗≤p∗(弱对偶性)变为d∗=p∗d^*=p^*d∗=p∗(强对偶性)。那么什么时候d∗=p∗d^*=p^*d∗=p∗呢?
假设目标函数f(w)f(w)f(w)和所有不等式约束gi(w)g_i(w)gi​(w)都是凸函数,所有等式约束hi(w)h_i(w)hi​(w)都是仿射的(仿射的含义:存在aia_iai​和bib_ibi​,使得hi(w)=aiTw+bi,ai∈Rn,w∈Rn,bi∈Rh_i(w)=a_i^Tw+b_i,a_i\in R^n,w\in R^n,b_i\in Rhi​(w)=aiT​w+bi​,ai​∈Rn,w∈Rn,bi​∈R,我们可以简单理解仿射类似于线性),并且对于所有的iii都有gi(w)<0g_i(w)<0gi​(w)<0,那么一定存在w∗,α∗,β∗w^*,\alpha^*,\beta^*w∗,α∗,β∗是原始问题和对偶问题的解,即,d∗=p∗=L(w∗,α∗,β∗)d^*=p^*=L(w^*,\alpha^*,\beta^*)d∗=p∗=L(w∗,α∗,β∗)。另外,w∗,α∗,β∗w^*,\alpha^*,\beta^*w∗,α∗,β∗还满足KKT(Karush-Kuhn-Tucker)条件
∂L(w∗,α∗,β∗)∂wi=0,i=1,2,...,Mgi(w∗)≤0,i=1,2,...,khi(w∗)=0,i=1,2,...,lai∗gi(w∗)=0,i=1,2,...,kai∗≥0,i=1,2,...,k(13)\frac{\partial L(w^*,\alpha^*,\beta^*)}{\partial w_i}=0,\quad i=1,2,...,M \tag{13}\\ g_i(w^*)\le0,\quad i=1,2,...,k\\ h_i(w^*)=0,\quad i=1,2,...,l\\ a_i^*g_i(w^*)=0,\quad i=1,2,...,k\\ a_i^*\ge0,\quad i=1,2,...,k ∂wi​∂L(w∗,α∗,β∗)​=0,i=1,2,...,Mgi​(w∗)≤0,i=1,2,...,khi​(w∗)=0,i=1,2,...,lai∗​gi​(w∗)=0,i=1,2,...,kai∗​≥0,i=1,2,...,k(13)
上面的五个式子就是KKT条件的具体内容。如果w∗,α∗,β∗w^*,\alpha^*,\beta^*w∗,α∗,β∗满足KKT条件,那么d∗=p∗d^*=p^*d∗=p∗,即优化对偶问题等价于优化原问题;同样地,如果d∗=p∗d^*=p^*d∗=p∗,那么w∗,α∗,β∗w^*,\alpha^*,\beta^*w∗,α∗,β∗必然满足KKT条件。所以KKT条件是原问题和对偶问题等价的充要条件。至于由KKT条件如何推导出d∗=p∗d^*=p^*d∗=p∗,我也并不是很了解,随着知识的拓展,后面可能会接触到,至少现在我们不必太纠结这一点,只需要知道,满足了KKT条件,我们就能将优化原问题转化为优化对偶问题,极大地减少计算复杂度
OK,回顾了优化和拉格朗日乘数法的概念,了解了对偶问题和KKT条件,我们就将这些知识用在SVM的求解上面。前面我们已经讲过,SVM的基本形式:
min⁡w,b12∣∣w∣∣22s.t.yi(wTxi+b)≥1,i=1,2...,n(14)\min_{w,b}\frac{1}{2}||w||_2^2 \tag{14}\\ s.t.\quad y^i(w^Tx^i+b) \geq 1, \quad i=1,2...,n w,bmin​21​∣∣w∣∣22​s.t.yi(wTxi+b)≥1,i=1,2...,n(14)
写成一般的带不等式约束优化问题:
min⁡w,bf(w)=12∣∣w∣∣22s.t.gi(w)=−yi(wTxi+b)+1≤0,i=1,2...,n(15)\min_{w,b}f(w)=\frac{1}{2}||w||_2^2 \tag{15}\\ s.t.\quad g_i(w)=-y^i(w^Tx^i+b)+1 \le0, \quad i=1,2...,n w,bmin​f(w)=21​∣∣w∣∣22​s.t.gi​(w)=−yi(wTxi+b)+1≤0,i=1,2...,n(15)
因为f(w)=12∣∣w∣∣22f(w)=\frac{1}{2}||w||_2^2f(w)=21​∣∣w∣∣22​是凸的,不等式约束也是凸的(SVM的不等式约束是线性函数,线性函数一定是凸的),所以对偶问题和原始问题的解是一样的,我们可以用拉格朗日对偶形式来求解,也就是min和max可以互换。下图5是SVM的基本形式所对应的图像,两条虚线分别对应wTxi+b=1w^Tx^i+b=1wTxi+b=1和wTxi+b=−1w^Tx^i+b=-1wTxi+b=−1,即,yi(wTxi+b)=1y^i(w^Tx^i+b)=1yi(wTxi+b)=1,而其他的yi(wTxi+b)>1y^i(w^Tx^i+b)>1yi(wTxi+b)>1则表示点不在边界上,在边界以外的位置。

图5 SVM的基本形式

其实SVM为什么叫Support Vector Machine,而不叫Max Margin?因为正如图5所示,最近的向量点(vector)支撑着两条虚线——wTxi+b=1w^Tx^i+b=1wTxi+b=1和wTxi+b=−1w^Tx^i+b=-1wTxi+b=−1,中间那条实线是wTxi+b=0w^Tx^i+b=0wTxi+b=0,是后续用在测试集分类的分类线。这些最近的vector成为support vector。Support vector的特性,就是只有Support vector会对最终的结果有作用。在SVM中会发现,之前有很多算法,比如逻辑回归要做一个极大似然估计,要统计每一个类别有多少个样本,每个训练集都会用到。但是在SVM中其它的vector都没用,只有support vector才有用,极大减少了计算的代价,这是SVM非常神奇的地方。因此,为了突出SVM的这个特点,就将其取名为Support Vector Machine,仅仅需要考虑这几个支撑点就可以了,它们已经完全决定了算法的特性,决定了算法泛化能力的高低,也决定了算法的复杂度。
KKT条件中,实际起作用的只有互补松弛条件——ai∗gi(w∗)=0a_i^*g_i(w^*)=0ai∗​gi​(w∗)=0,其中gi(w)=1−yi(wTxi+b)≤0g_i(w)=1-y^i(w^Tx^i+b) \le0gi​(w)=1−yi(wTxi+b)≤0的几何含义是“点是否虚线边界(margin)上”。如果是在margin上,1−yi(wTxi+b)=01-y^i(w^Tx^i+b)=01−yi(wTxi+b)=0;如果是margin以外,1−yi(wTxi+b)<01-y^i(w^Tx^i+b)<01−yi(wTxi+b)<0。gi(w)≤0g_i(w)\le0gi​(w)≤0就是告诉我们每个点要分对。互补松弛条件的特点在于“松弛”,意思是若ai∗a_i^*ai∗​或者gi(w∗)g_i(w^*)gi​(w∗)有一个等于0,那么另一个就不必为0,这就是松弛的含义——不需要严格出现两个变量都是0的情况,标准放的松一点,有一个为0即可。有这个标准,我们可以分析:
如果gi(w)<0g_i(w)<0gi​(w)<0,即i点在margin以外,由互补松弛条件可得αi=0\alpha_i=0αi​=0;如果gi(w)=0g_i(w)=0gi​(w)=0,即i点在margin上,由互补松弛条件可得αi<0\alpha_i<0αi​<0。根据以上分析,在margin外的点,αi=0\boldsymbol{\alpha_i=0}αi​=0;在margin上的点,αi>0\boldsymbol{\alpha_i>0}αi​>0
将SVM写成拉格朗日乘数法的形式:
L(w,b,α)=12∣∣w∣∣22+∑i=1nαi[1−yi(wTxi+b)](16)L(w,b,\alpha)=\frac{1}{2}||w||_2^2+\sum_{i=1}^n\alpha_i[1-y^i(w^Tx^i+b)] \tag{16} L(w,b,α)=21​∣∣w∣∣22​+i=1∑n​αi​[1−yi(wTxi+b)](16)
只有在margin上的点αi\boldsymbol{\alpha_i}αi​才不为0,结合(16)式可以看出,只有这些点才对结果有作用,margin外的点不对结果产生作用。因此,从KKT条件可知,SVM的support vector在数学上有什么样的作用。
将(16)进行对偶形式优化,先对L(w,b,α)L(w,b,\alpha)L(w,b,α)求min⁡w,b\min_{w,b}minw,b​,再求max⁡α\max_{\alpha}maxα​:
(1)先对L(w,b,α)L(w,b,\alpha)L(w,b,α)求min⁡w,b\min_{w,b}minw,b​,有
∇wL(w,b,α)=w−∑i=1nαiyixi=0⇒w=∑i=1nαiyixi(17)\nabla_wL(w,b,\alpha)=w-\sum_{i=1}^{n}\alpha_iy^ix^i=0 \tag{17}\\ \Rightarrow w=\sum_{i=1}^{n}\alpha_iy^ix^i ∇w​L(w,b,α)=w−i=1∑n​αi​yixi=0⇒w=i=1∑n​αi​yixi(17)
∂L(w,b,α)∂b=∑i=1nαiyi=0(18)\frac{\partial{L(w,b,\alpha)}}{\partial{b}}=\sum_{i=1}^{n}\alpha_iy^i=0 \tag{18} ∂b∂L(w,b,α)​=i=1∑n​αi​yi=0(18)
上面的(18)式体现了bbb不重要,但是告诉我们一个条件。
(2)将(17)(18)代回L(w,b,α)L(w,b,\alpha)L(w,b,α),得到
θD(α)=∑i=1nαi−12∑i,j=1nyiyjαiαj(xi)Txj(19)\theta_D(\alpha)=\sum_{i=1}^{n}\alpha_i-\frac{1}{2}\sum_{i,j=1}^{n}y^iy^j\alpha_i\alpha_j(x^i)^Tx^j \tag{19} θD​(α)=i=1∑n​αi​−21​i,j=1∑n​yiyjαi​αj​(xi)Txj(19)
再求max⁡α\max_{\alpha}maxα​,得到SVM的对偶形式如下:
max⁡α∑i=1nαi−12∑i,j=1nyiyjαiαj(xi)Txjs.t.αi≥0,i=1,2,...,n∑i=1nαiyi=0(20)\max_\alpha\sum_{i=1}^{n}\alpha_i-\frac{1}{2}\sum_{i,j=1}^{n}y^iy^j\alpha_i\alpha_j(x^i)^Tx^j \tag{20} \\ s.t.\quad \alpha_i\ge0,i=1,2,...,n \\ \sum_{i=1}^{n}\alpha_i y^i=0 αmax​i=1∑n​αi​−21​i,j=1∑n​yiyjαi​αj​(xi)Txjs.t.αi​≥0,i=1,2,...,ni=1∑n​αi​yi=0(20)
假设α∗=(α1∗,α2∗...,αn∗)\alpha^*=(\alpha^*_1,\alpha^*_2...,\alpha^*_n)α∗=(α1∗​,α2∗​...,αn∗​)是max⁡α\max_\alphamaxα​的最优解,有
w∗=∑i=1nαi∗yixi(21)w^*=\sum_{i=1}^{n}\alpha_i^*y^ix^i \tag{21} w∗=i=1∑n​αi∗​yixi(21)
存在αj∗>0\alpha^*_j>0αj∗​>0,即,j点在边界上,有
yj((w∗)Txj+b∗)=1⇒(w∗)Txj+b∗=1yj由于yj=±1,故1yj=yj⇒(w∗)Txj+b∗=yj(22)y^j((w^*)^Tx^j+b^*)=1 \tag{22} \\ \Rightarrow (w^*)^Tx^j+b^*=\frac{1}{y^j} \\ 由于y^j=\plusmn1,故\frac{1}{y^j}=y^j \\ \Rightarrow (w^*)^Tx^j+b^*=y^j yj((w∗)Txj+b∗)=1⇒(w∗)Txj+b∗=yj1​由于yj=±1,故yj1​=yj⇒(w∗)Txj+b∗=yj(22)
将(21)式代入(22)式中,得
b∗=yj−∑i=1nαi∗yi(xi)Txj(23)b^*=y^j-\sum_{i=1}^{n}\alpha_i^*y^i(x^i)^Tx^j \tag{23} b∗=yj−i=1∑n​αi∗​yi(xi)Txj(23)
w∗w^*w∗体现了每个样本进行了一个线性加权,每个αi∗\alpha^*_iαi∗​表示该样本i对结果的贡献,在边界外的点都是αi∗=0\alpha_i^*=0αi∗​=0,所以只需要计算support vector的加权值。正样本yi=1y^i=1yi=1对w∗w^*w∗起到正向作用,负样本yi=−1y^i=-1yi=−1对w∗w^*w∗起到负向作用,作用大小由αi∗\alpha_i^*αi∗​决定。上面的结论都是由SVM的对偶形式分析得来的,所以再次体现了对偶形式比原始形式更加重要。如果单从原始形式看的话,没有办法分析这个算法最终是谁影响的,每个点都对其产生怎样的作用。但是如果将其转化为对偶形式,就能清楚地看到每个训练数据是怎样发挥作用的,也就是w,bw,bw,b是受谁的影响?受谁的影响更大?这些信息都可以通过对偶形式获得,所以SVM的对偶形式非常重要。

五、SVM的软间隔形式

前面我们已经得到了SVM的对偶形式,并且得到了w∗w^*w∗和b∗b^*b∗的表达式,但是计算出w∗w^*w∗和b∗b^*b∗的关键在于我们如何求出αi∗\alpha_i^*αi∗​,这个后续将会介绍。我们先看另外一个问题。
我们前面介绍的SVM应对的问题是线性可分的情况,称为硬间隔(Hard Margin)的SVM。如果问题是线性不可分的情况,也就是无法用一个分类面完全将不同类的数据分开,总会有误差的存在,如图6所示,那应该怎么办?

图6 线性不可分

有两种方法:一种是用核的方法将数据映射到高维空间的方法;另外一种是引入一个松弛变量的方法,这种方法也称为软间隔(Soft Margin)的SVM。本节只会介绍有松弛变量的方法。

假设问题不再是线性可分了,意味着总会有误差的存在。soft margin的想法就是反正你总要有误差了,那我就给你一定的容忍度,但是我只要把误差惩罚在算法里面就可以了,因此引入一个叫做松弛变量的变量,记为ξ\xiξ,如图7所示。

图7 软间隔

本来左上方蓝色的点应该属于右下方才是正确的分类,但不幸的是,这个点没办法被黑色的直线正确分类,从而产生一个误差,这个误差我们记为ξi\xi_iξi​,它是图中橙色的直线。之前hard margin是两种情况,一种是点在margin上,一种是点在margin外。而soft margin是三种情况:(1)点在margin上;(2)点在margin外且分对;(3)点被分错。分错的点我们才会给它一个容忍度,也就是松弛变量。图7中两个分错的点松弛变量为ξi\xi_iξi​和ξj\xi_jξj​。hard margin要求算法一定要把所有点分对,soft margin就是比较好说话的人,它不要求算法一定要把所有点都分对,不要求ξi\xi_iξi​非要等于0,但是要尽可能小。 在SVM的基本格式中加入一个惩罚项∑i=1nξi\sum_{i=1}^n\xi_i∑i=1n​ξi​:
min⁡w,b12∣∣w∣∣22+C∑i=1nξis.t.yi(wTxi+b)≥1−ξi,i=1,2...,nξi≥0,i=1,2,...,n(24)\min_{w,b}\frac{1}{2}||w||_2^2+C\sum_{i=1}^n\xi_i \tag{24}\\ s.t.\quad y^i(w^Tx^i+b) \geq 1-\xi_i, \quad i=1,2...,n \\ \xi_i \ge0, i=1,2,...,n w,bmin​21​∣∣w∣∣22​+Ci=1∑n​ξi​s.t.yi(wTxi+b)≥1−ξi​,i=1,2...,nξi​≥0,i=1,2,...,n(24)
既然有松弛变量让算法有一定容忍度,那就要交一定罚金,罚金的倍数为(24)中的CCC。soft margin的SVM形式仍然是凸的二次优化问题,因为它仍然要求www,而www仍是范数平方的形式。当然,对这个形式仍然可用拉格朗日的技巧来求它的对偶形式,由于ξi≥0\xi_i\ge0ξi​≥0也是个不等式约束,拉格朗日会变成这样的一个形式:
L(w,b,ξ,α,η)=12∣∣w∣∣22+C∑i=1nξi−∑i=1nαi[yi(wTxi+b)−1+ξi]−∑i=1nηiξi(25)L(w,b,\xi,\alpha,\eta)=\frac{1}{2}||w||_2^2+C\sum_{i=1}^n\xi_i \\ -\sum_{i=1}^n\alpha_i[y^i(w^Tx^i+b)-1+\xi_i]-\sum_{i=1}^n\eta_i\xi_i \tag{25} L(w,b,ξ,α,η)=21​∣∣w∣∣22​+Ci=1∑n​ξi​−i=1∑n​αi​[yi(wTxi+b)−1+ξi​]−i=1∑n​ηi​ξi​(25)
下面的步骤跟前面做法一样,过程如下:
∇wL(w,b,ξ,α,η)=w−∑i=1nαiyixi=0⇒w=∑i=1nαiyixi(26)\nabla_wL(w,b,\xi,\alpha,\eta)=w-\sum_{i=1}^{n}\alpha_iy^ix^i=0 \tag{26}\\ \Rightarrow w=\sum_{i=1}^{n}\alpha_iy^ix^i ∇w​L(w,b,ξ,α,η)=w−i=1∑n​αi​yixi=0⇒w=i=1∑n​αi​yixi(26)
∂L(w,b,ξ,α,η)∂b=∑i=1nαiyi=0(27)\frac{\partial{L(w,b,\xi,\alpha,\eta)}}{\partial{b}}=\sum_{i=1}^{n}\alpha_iy^i=0 \tag{27} ∂b∂L(w,b,ξ,α,η)​=i=1∑n​αi​yi=0(27)
∂L(w,b,ξ,α,η)∂ξi=C−αi−ηi=0(28)\frac{\partial{L(w,b,\xi,\alpha,\eta)}}{\partial{\xi_i}}=C-\alpha_i-\eta_i=0 \tag{28} ∂ξi​∂L(w,b,ξ,α,η)​=C−αi​−ηi​=0(28)
代回原拉格朗日式子中,得到
θD(α)=∑i=1nαi−12∑i,j=1nyiyjαiαj(xi)Txj(29)\theta_D(\alpha)=\sum_{i=1}^{n}\alpha_i-\frac{1}{2}\sum_{i,j=1}^{n}y^iy^j\alpha_i\alpha_j(x^i)^Tx^j \tag{29} θD​(α)=i=1∑n​αi​−21​i,j=1∑n​yiyjαi​αj​(xi)Txj(29)
得到新的soft margin情况之下的一个对偶问题的形式:
max⁡α∑i=1nαi−12∑i,j=1nyiyjαiαj(xi)Txjs.t.0≤αi≤C,i=1,2,...,n∑i=1nαiyi=0(30)\max_\alpha\sum_{i=1}^{n}\alpha_i-\frac{1}{2}\sum_{i,j=1}^{n}y^iy^j\alpha_i\alpha_j(x^i)^Tx^j \tag{30} \\ s.t.\quad 0\le\alpha_i\le C,i=1,2,...,n \\ \sum_{i=1}^{n}\alpha_i y^i=0 αmax​i=1∑n​αi​−21​i,j=1∑n​yiyjαi​αj​(xi)Txjs.t.0≤αi​≤C,i=1,2,...,ni=1∑n​αi​yi=0(30)
我们可以对比一下它和hard margin对偶问题的差别在哪里?是不是只多了一个αi≤C\alpha_i\le Cαi​≤C。那αi\alpha_iαi​代表每个训练数据的重要性。在hard margin里,αi\alpha_iαi​是可以无限大的,代表那些support vector的权重可以无限大。而在soft margin中,αi\alpha_iαi​无法无限大,有一个CCC限界。接着同hard margin一样的方式,得到
w∗=∑i=1nαi∗yixi(31)w^*=\sum_{i=1}^{n}\alpha_i^*y^ix^i \tag{31} w∗=i=1∑n​αi∗​yixi(31)
b∗=yj−∑i=1nαi∗yi(xi)Txj(32)b^*=y^j-\sum_{i=1}^{n}\alpha_i^*y^i(x^i)^Tx^j \tag{32} b∗=yj−i=1∑n​αi∗​yi(xi)Txj(32)
分类超平面:
∑i=1nαi∗yi(xi)Tx+b∗=0(33)\sum_{i=1}^{n}\alpha_i^*y^i(x^i)^Tx+b^*=0 \tag{33} i=1∑n​αi∗​yi(xi)Tx+b∗=0(33)
决策函数:
fw,b(x)=sign(∑i=1nαi∗yi(xi)Tx+b∗)(34)f_{w,b}(x)=sign(\sum_{i=1}^{n}\alpha_i^*y^i(x^i)^Tx+b^*) \tag{34} fw,b​(x)=sign(i=1∑n​αi∗​yi(xi)Tx+b∗)(34)
soft margin对比hard margin的KKT条件,多了两个变化:

αi∗gi(w∗)=αi∗[yi(wTxi+b)−1+ξi]=0(35)\alpha_i^*g_i(w^*)=\alpha_i^*[y^i(w^Tx^i+b)-1+\xi_i]=0 \tag{35} αi∗​gi​(w∗)=αi∗​[yi(wTxi+b)−1+ξi​]=0(35)
ηi∗ξi=0(36)\eta_i^*\xi_i=0 \tag{36} ηi∗​ξi​=0(36)
对照图8,我们看看不同αi∗\alpha_i^*αi∗​的取值对应的不同情况:
如果αi∗=0\alpha_i^*=0αi∗​=0,由(28)式可知,C=αi∗+ηi∗C=\alpha_i^*+\eta_i^*C=αi∗​+ηi∗​,所以ηi∗=C\eta_i^*=Cηi∗​=C,又由(36)式可知,ξi=0\xi_i=0ξi​=0,故gi(w∗)=−[yi((w∗)Txi+b∗)−1+ξi]=−[yi((w∗)Txi+b∗)−1]≤0g_i(w^*)=-[y^i((w^*)^Tx^i+b^*)-1+\xi_i]=-[y^i((w^*)^Tx^i+b^*)-1]\le0gi​(w∗)=−[yi((w∗)Txi+b∗)−1+ξi​]=−[yi((w∗)Txi+b∗)−1]≤0,所以yi((w∗)Txi+b∗)≥1y^i((w^*)^Tx^i+b^*)\ge1yi((w∗)Txi+b∗)≥1,表示分为正确的一类。
如果0≤αi∗≤C0\le\alpha_i^*\le C0≤αi∗​≤C,由(35)式可知,gi(w∗)=0g_i(w^*)=0gi​(w∗)=0;由(28)式可知,C=αi∗+ηi∗⇒0<ηi<CC=\alpha_i^*+\eta_i^*\Rightarrow0<\eta_i<CC=αi∗​+ηi∗​⇒0<ηi​<C;由(36)式可知,ξi=0\xi_i=0ξi​=0,将其代入gi(w∗)=0g_i(w^*)=0gi​(w∗)=0,得到yi((w∗)Txi+b)=1y^i((w^*)^Tx^i+b)=1yi((w∗)Txi+b)=1,表示被分对且在边界上。
如果αi∗=C\alpha_i^*=Cαi∗​=C,由(28)式可知,C=αi∗+ηi∗⇒ηi=0C=\alpha_i^*+\eta_i^*\Rightarrow\eta_i=0C=αi∗​+ηi∗​⇒ηi​=0;由(35)式可知,gi(w∗)=0⇒yi((w∗)Txi+b∗)=1−ξig_i(w^*)=0\Rightarrow y^i((w^*)^Tx^i+b^*)=1-\xi_igi​(w∗)=0⇒yi((w∗)Txi+b∗)=1−ξi​;又因为ξi≥0⇒yi((w∗)Txi+b∗)≤1\xi_i\ge0\Rightarrow y^i((w^*)^Tx^i+b^*)\le1ξi​≥0⇒yi((w∗)Txi+b∗)≤1,表示要么在边界上,要么被分错。

图8 软间隔的三种情况

由上面的分析可知,只有分错和在边界上的点它们的αi∗\alpha_i^*αi∗​才不为0,也就是只有这些点才起作用,其中分错的点作用最大,它们的αi∗=C\alpha_i^*=Cαi∗​=C。
OK,接下来我们思考一个问题,CCC到底是什么?CCC其实就是容忍程度,就是一个点分错,给它的惩罚有多大。soft margin的目标函数为min⁡w,b12∣∣w∣∣22+C∑i=1nξi\min_{w,b}\frac{1}{2}||w||_2^2+C\sum_{i=1}^n\xi_iminw,b​21​∣∣w∣∣22​+C∑i=1n​ξi​,当CCC越小,惩罚越小,那么可以容忍的犯错点越多;反之,当CCC越大,惩罚越大,那么可以容忍的犯错点就越少。所以CCC作为超参数,在实际应用中对它的调节很重要。
其实很多算法都有一个损失函数,我们来看一下SVM的损失函数是什么。(24)式是SVM的优化目标,下式便是它的损失函数的优化:
min⁡w,b∑i=1n[1−yi(wTxi+b)]++λ∣∣w∣∣22(37)\min_{w,b}\sum_{i=1}^n[1-y^i(w^Tx^i+b)]_++\lambda||w||_2^2 \tag{37} w,bmin​i=1∑n​[1−yi(wTxi+b)]+​+λ∣∣w∣∣22​(37)
分析一下这个损失函数如何得到的:
由约束条件可知,1−yi(wTxi+b)≤ξi1-y^i(w^Tx^i+b)\le\xi_i1−yi(wTxi+b)≤ξi​。只有当1−yi(wTxi+b)>01-y^i(w^Tx^i+b)>01−yi(wTxi+b)>0,结合ξi≥0\xi_i\ge0ξi​≥0,约束条件变为ξi≥1−yi(wTxi+b)\xi_i\ge1-y^i(w^Tx^i+b)ξi​≥1−yi(wTxi+b);当1−yi(wTxi+b)≤01-y^i(w^Tx^i+b)\le01−yi(wTxi+b)≤0,结合ξi≥0\xi_i\ge0ξi​≥0,约束条件变为ξi≥0\xi_i\ge0ξi​≥0;所以1−yi(wTxi+b)>01-y^i(w^Tx^i+b)>01−yi(wTxi+b)>0时,1−yi(wTxi+b)1-y^i(w^Tx^i+b)1−yi(wTxi+b)这个式子才有意义,我们取这个式子的正部作为损失函数的一项(正部的含义是当式子大于0时等于它本身,当式子小于等于0时等于0),还有一项是λ∣∣w∣∣22\lambda||w||_2^2λ∣∣w∣∣22​,其中λ=1C\lambda=\frac{1}{C}λ=C1​。所以带约束的优化函数就等于这个损失函数。下面是L(f,x,y)=[1−y(wTx+b)]+L(f,x,y)=[1-y(w^Tx+b)]_+L(f,x,y)=[1−y(wTx+b)]+​这个损失函数的图像:

图9 Hinge Loss Function

图9中绿色的线就是损失函数的图像,这个损失又叫hinge损失,横轴为yf(x)yf(x)yf(x)。我们知道,回归的真实损失为平方损失,二分类的真实损失为0,1损失。当二分类为0时表示分对,等于1时表示分错。在图9中,yf(x)<0yf(x)<0yf(x)<0是有错,就是红色的那条线。绿色的线是红色线的上界。对分类而言损失函数不好分析,它是个截断函数,而且有参数www需要学习和估计,并且它是个非凸函数,在中间截断处没有梯度,没办法用导数方法直接求解,所以求解很困难、麻烦。人们想要给他们找到替代的损失,每找一个替代损失就会出现新的算法,找的过程就是在找一些凸的上界,不同算法可以画到函数图像来看,如图10所示。

图10 不同算法的损失函数对比

归根结底就会发现,这些算法好不好从理论上在于目标函数与真实目标函数有多接近,从这个意义上可以衡量不同算法之间性能上的差异。

详解支持向量机(Support Vector Machine, SVM)相关推荐

  1. 支持向量机(support vector machine)(SVM)(1)

    背景 对于两类问题,给定数据,使用线性函数,如何分类? 方案1(只看黑色分界线,红色不用管) 方案2(只看黑色分界线,红色不用管) 哪一个更好? 第二个好,将两类数据分得更开,而且: 建模 有了目标之 ...

  2. [机器学习] 分类 --- Support Vector Machine (SVM)

    1. 基本概念 支持向量机(Support Vector Machine, SVM)的基本模型是在特征空间上找到最佳的分离超平面使得训练集上正负样本间隔最大.SVM是用来解决二分类问题的有监督学习算法 ...

  3. 【翻译论文】An Architecture Combining Convolutional Neural Network (CNN) and Support Vector Machine (SVM)

    [翻译论文]An Architecture Combining Convolutional Neural Network (CNN) and Support Vector Machine (SVM) ...

  4. OpenCV3.3中支持向量机(Support Vector Machines, SVM)实现简介及使用

    OpenCV 3.3中给出了支持向量机(Support Vector Machines)的实现,即cv::ml::SVM类,此类的声明在include/opencv2/ml.hpp文件中,实现在mod ...

  5. 【李宏毅2020 ML/DL】补充:Support Vector Machine (SVM)

    我已经有两年 ML 经历,这系列课主要用来查缺补漏,会记录一些细节的.自己不知道的东西. 本次笔记补充视频 BV1JE411g7XF 的缺失部分.在另一个UP主上传的2017课程BV13x411v7U ...

  6. 支持向量机(Support Vector Machine, SVM)基础知识

    这篇文章仅介绍支持向量机的基础知识,不涉及特别复杂的求解.不清楚基础知识的小伙伴可以看一下这篇文章. 首先呢,支持向量机解决的是将数据点分成两类的问题.本文只考虑线性分类器.对于二维的数据而言,就是要 ...

  7. 李宏毅机器学习笔记(2016年的课程):Support Vector Machine (SVM)

    目录 1. 各种loss函数 2.线性SVM 3.kernel 3.1 前言 3.2 各种 kernel 3.3 kernel VS 神经网络 1. 各种loss函数 f = np.arange(-3 ...

  8. 西瓜书+实战+吴恩达机器学习(十)监督学习之支持向量机 Support Vector Machine

    文章目录 0. 前言 1. 拉格朗日乘子法 2. SVM参数求解方法 3. 软间隔 4. 核方法 5. 支持向量回归 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔,我会非常开心的~ 0. 前 ...

  9. 机器学习中的数学基础(4.1):支持向量机Support Vector Machine(SVM)

    SVM可以说是一个很经典的二分类问题,属于有监督学习算法的一种.看过那么多的博客知乎解释SVM我一定要自己总结一篇,加深一下自己的理解. 带着问题去读文章会发现,柳暗花明又一村,瞬间李敏浩出现在眼前的 ...

最新文章

  1. 大脑芯片公司Neuralink计划在人脑内植入芯片,他们到底想干什么?
  2. ZOJ Monthly, June 2014 月赛BCDEFGH题题解
  3. 负载均衡的几种常用方案
  4. 【 Sublime Text 】如何使用Sublime Text快速生成代码模板
  5. 【任务脚本】0616吐槽tb坑爹活动,预测看好jd活动,更新汇总战绩,DIY净水器预告...
  6. 基于R-CNN的物体检测-CVPR 2014
  7. 大数据在互联网金融行业中的应用
  8. Python学习笔记 (1)Hello World(环境搭建+输出Hello World!)...
  9. mvnrepository总是出现烦人的one more step验证
  10. 荣耀智慧屏功能曝光 首发华为鸿蒙OS,荣耀智慧屏功能曝光:首发华为鸿蒙OS,全场景智慧体验...
  11. abap视图字段限制_【第八章】视图
  12. CentOS搭建安装SVN
  13. Java一键生成图表
  14. Android中AppWidget的分析与应用:AppWidgetProvider .
  15. 一分钟教你学会配置eslint,还在为风格单双引号,对象末位逗号要不要,引用各种报错而烦恼?(建议收藏!详细中文注释)...
  16. 定时执行失败原因分析
  17. Unity3D加密工具:Virbox Protector Unity3D版
  18. excel文件保护忘记密码解除
  19. 沃趣陈栋ORACLE认证,QData-Oracle-数据库一体机---沃趣科技.pdf
  20. Keil AC5/Keil AC6/IAR指定数据绝对存储地址

热门文章

  1. wms软件第三方仓储的四大好处
  2. Tkinter超市收银小程序(附源码),看完这一篇你还不会Tkinter吗,快来试试吧
  3. 智能电磁流量计与智能电磁水表,应用及各自难点分析
  4. selenium实现bilibili模拟登录
  5. C#调用迅雷下载,调用迅雷影音播放
  6. 【组件】24系列EEPROM/FRAM通用接口
  7. 右键新建里面没有记事本和word以及excel简单解决
  8. 用同文输入法,实现五笔双键布局
  9. 传统零售布局O2O 蓄势全渠道谋反击
  10. 综述二 | 最全的目标检测大综述(附下载链接)