SVM支持向量机+python代码复现(三)

软间隔

在这里插入图片描述

​ 对于线性可分的数据,我们仅仅使用硬间隔便可以求解。但是还有个问题。假如数据本身就线性不可分呢?又或者我们的数据存在噪声,比如途中,显然直线左边有一个噪声,右边也有一个噪声。

​ 对这一类问题,怎么办?

​ 这很好解决。我们直接训练的时候允许其存在一丢丢的错误不久可以了嘛?怎么做?当燃是调整损失函数
min ⁡ w , b 1 2 w T w + g ( x ) \min\limits_{w,b}\frac{1}{2}w^Tw+g(x) w,bmin21wTw+g(x)
​ 这个f(x)可以当作是允许存在一丢丢错误的损失。

​ 如何设置这个损失?令 z i = y i ( w T x i + b ) z_i=y_i(w^Tx_i+b) zi=yi(wTxi+b)直接
g ( x ) = { 1 , z i < 1 0 , z i ≥ 1 g(x)= \left \{ \begin{matrix} 1,z_i<1 \\ 0,z_i\ge1 \end{matrix} \right. g(x)={1zi<10,zi1
​ 看起来是一个不错的方法,因为在我们之前提到之中,我们认为 y i ( w T x i + b ) ≥ 1 y_i(w^Tx_i+b)\ge1 yi(wTxi+b)1是所有分类正确的前提,如果为负数,那么则证明是错误的。但是,有一个致命问题——这个函数并不连续,无法求导。而我们求极值就不可避免地使用求导。要知道,不连续的函数是无法求导的。

​ 怎么办?我们不妨这样设定
g ( x ) = m a x { 0 , 1 − z i } g(x)=max\left\{0,1-z_i \right\} g(x)=max{0,1zi}
​ 当 y i ( w T x i + b ) < 1 y_i(w^Tx_i+b)<1 yi(wTxi+b)<1,则说明是错误的点,那么我们就用 1 − y i ( w T x i + b ) = 1 − z 1-y_i(w^Tx_i+b)=1-z 1yi(wTxi+b)=1z来代表错误点损失,如果 y i ( w T x i + b ) ≥ 1 y_i(w^Tx_i+b)\ge1 yi(wTxi+b)1代表正确,所以所得就为0,代表无错误点损失。这是他的图像

在这里插入图片描述

​ 令 δ = m a x { 0 , 1 − z i } \delta=max\left\{0,1-z_i\right\} δ=max{0,1zi},我们损失函数就可以为
{ 1 2 w T w + C ∑ i = 1 n δ i \left \{ \frac{1}{2}w^Tw+C\sum\limits_{i=1}^n\delta_i \right. {21wTw+Ci=1nδi
​ 其中C是一个惩罚系数,越大惩罚力度越大,反之越小。

​ 那么约束条件呢?当燃不能沿用之前的。我是这么理解的 1 − z i 1-z_i 1zi

在这里插入图片描述

​ 坐标中,点 K 1 K_1 K1是一个错误点,那么 1 − z i 1-z_i 1zi意为线段 K 1 N K_1N K1N

在这里插入图片描述

​ 对于硬间隔的损失函数为
{ min ⁡ w , b 1 2 w T w s . t . y i ( w T x i + b ) ≥ 1 , i = 1 , 2 ⋯   , n \begin{equation} \begin{aligned} \left\{ \begin{matrix} &\min\limits_{w,b}\frac{1}{2}w^Tw \\&s.t.\hspace{1cm} &y_i(w^Tx_i+b)\ge1,i=1,2 \cdots ,n \end{matrix} \right. \end{aligned} \end{equation} {w,bmin21wTws.t.yi(wTxi+b)1i=1,2,n
​ 所以软间隔的损失函数则为
{ 1 2 w T w + C ∑ i = 1 n δ i s . t . y i ( w T x i + b ) + δ i ≥ 1 δ i ≥ 0 ; i = 1 , 2 , ⋯   , n \begin{equation} \begin{aligned} \left \{ \begin{matrix} &\frac{1}{2}w^Tw+C\sum\limits_{i=1}^n\delta_i\\ s.t.\hspace{1cm} &y_i(w^Tx_i+b)+\delta_i\ge1\\ &\delta_i\ge0;i=1,2,\cdots,n \end{matrix} \right. \end{aligned} \end{equation} s.t.21wTw+Ci=1nδiyi(wTxi+b)+δi1δi0;i=1,2,,n
​ 以下步骤不做解释,详细可看硬间隔的部分,因为差不多是一样的。

​ 拉格朗日函数
L ( w , b , δ , α , β ) = 1 2 w T w + C ∑ i = 1 n δ i + ∑ i = 1 n [ α i ( 1 − δ i − y i ( w T x i + b ) ) ] − ∑ i = 1 n β i δ i L(w,b,\delta,\alpha,\beta)=\frac{1}{2}w^Tw+C\sum\limits_{i=1}^n\delta_i+\sum\limits_{i=1}^n\left[ \alpha_i(1-\delta_i-y_i(w^Tx_i+b))\right]-\sum\limits_{i=1}^n\beta_i\delta_i L(w,b,δ,α,β)=21wTw+Ci=1nδi+i=1n[αi(1δiyi(wTxi+b))]i=1nβiδi
​ 求原问题再求对偶问题,然后对其求导
∂ L ∂ w → w = ∑ i = 1 n α i y i x i ∂ L ∂ b → ∑ i = 1 n α i y i = 0 ∂ L ∂ δ i → α i + β i = C \begin{equation} \begin{aligned} &\frac{\partial{L}}{\partial{w}}\rightarrow w=\sum\limits_{i=1}^n\alpha_iy_ix_i \\&\frac{\partial{L}}{\partial{b}}\rightarrow\sum\limits_{i=1}^n\alpha_iy_i=0 \\&\frac{\partial{L}}{\partial{\delta_i}}\rightarrow \alpha_i+\beta_i=C \end{aligned} \end{equation} wLw=i=1nαiyixibLi=1nαiyi=0δiLαi+βi=C
​ 令 β i = C − α i \beta_i=C-\alpha_i βi=Cαi和另外两个求导所得代入拉格朗日函数。最终
max ⁡ α ∑ i = 1 n α i − 1 2 ∑ i = 1 n ∑ j = 1 n α i y i α j y j x i T x j s . t . 0 ≤ α i ≤ C , i = 1.2. ⋯   , n . ∑ i = 1 n α i y i = 0 , \begin{equation} \begin{aligned} &\max\limits_{\alpha}\sum\limits_{i=1}^n\alpha_i-\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\alpha_iy_i\alpha_jy_jx_i^Tx_j \\&s.t. \hspace{1cm} 0\le\alpha_i \le C,i=1.2.\cdots,n.\\&\hspace{2cm}\sum\limits_{i=1}^n\alpha_iy_i=0, \end{aligned} \end{equation} αmaxi=1nαi21i=1nj=1nαiyiαjyjxiTxjs.t.0αiC,i=1.2.,n.i=1nαiyi=0
​ 可以发现,目标函数和硬间隔是一样的,只是约束条件从 a l p h a i ≥ 0 alpha_i\ge0 alphai0变成了 0 ≤ α i ≤ C 0\le\alpha_i \le C 0αiC,所以,最终使用SMO算法求解所得应为一样。但是在硬间隔的时候,我们仅仅是求解了,但是还有一个 α i ≥ 0 \alpha_i\ge0 αi0是没有使用的,也就是我们所求出来的 λ 2 n e w \lambda_2^{new} λ2new并非一定是解,因为我们还需要削减。

​ 此处,我们仅仅求软间隔的取值范围,硬间隔的相对比较容易,读者可自求。

​ 对此,我们先求出 α 2 n e w \alpha_2^{new} α2new的取值范围。
因为: α 1 o l d y 1 + α 2 o l d y 2 = − ∑ i = 3 n α i y i = K 分情况讨论: ①: y 1 = y 2 ( 即标签值同号 ) 对第一个等式左右乘以 y 1 得: α 1 n e w y 1 + α 2 n e w y 2 = K y 1 → α 2 n e w = K y 1 − α 1 n e w 因为: a 1 n e w ∈ [ 0 , C ] 所以: − a 1 n e w ∈ [ − C , 0 ] 因为: α 1 o l d y 1 + α 2 o l d y 2 = K 所以: K y 1 − α 1 n e w ∈ [ K y 1 − C , K y 1 ] → [ α 1 o l d + α 2 o l d − C , α 1 o l d + α 2 o l d ] 因为: α 2 n e w = K y 1 − α 1 n e w 所以: α 2 n e w ∈ [ α 1 o l d + α 2 o l d − C , α 1 o l d + α 2 o l d ] 又因为: α 2 ∈ [ 0 , C ] 要同时满足这两个条件,就必须: α 2 ∈ [ max ⁡ { 0 , α 1 o l d + α 2 o l d − C } , m i n { C , α 1 o l d + α 2 o l d } ] 同理得②: y 1 ≠ y 2 ( 标签不同号 ) 即: α 2 ∈ [ max ⁡ { 0 , α 2 o l d − α 1 o l d } , m i n { C , α 2 o l d − α 1 o l d + C } ] \begin{equation} \begin{aligned} 因为:& \alpha_1^{old}y_1+\alpha_2^{old}y_2=-\sum_{i=3}^n\alpha_iy_i=K \\分情况讨论:& \\①:&y_1={y_2}(即标签值同号) \\对第一个等式左右乘以y_1得:&\alpha_1^{new}y_1+\alpha_2^{new}y_2=Ky_1\rightarrow \alpha_2^{new}=Ky_1-\alpha_1^{new} \\因为:&a_1^{new}\in[0,C] \\所以:&-a_1^{new}\in[-C,0] \\因为:&\alpha_1^{old}y_1+\alpha_2^{old}y_2=K \\所以:&Ky_1-\alpha_1^{new}\in[Ky_1-C,Ky_1]\rightarrow[\alpha_1^{old}+\alpha_2^{old}-C,\alpha_1^{old}+\alpha_2^{old}] \\因为:&\alpha_2^{new}=Ky_1-\alpha_1^{new} \\所以:&\alpha_2^{new}\in[\alpha_1^{old}+\alpha_2^{old}-C,\alpha_1^{old}+\alpha_2^{old}] \\又因为:&\alpha_2\in[0,C] \\要同时满足这两个条件,就必须:&\alpha_2\in\left[\max\left\{0,\alpha_1^{old}+\alpha_2^{old}-C\right\},min\left\{C,\alpha_1^{old}+\alpha_2^{old}\right\}\right] \\同理得②:&y_1\neq{y_2}(标签不同号)\\ 即:&\alpha_2\in\left[\max\left\{0,\alpha_2^{old}-\alpha_1^{old}\right\},min\left\{C,\alpha_2^{old}-\alpha_1^{old}+C\right\}\right] \end{aligned} \end{equation} 因为:分情况讨论:对第一个等式左右乘以y1得:因为:所以:因为:所以:因为:所以:又因为:要同时满足这两个条件,就必须:同理得即:α1oldy1+α2oldy2=i=3nαiyi=Ky1=y2(即标签值同号)α1newy1+α2newy2=Ky1α2new=Ky1α1newa1new[0,C]a1new[C,0]α1oldy1+α2oldy2=KKy1α1new[Ky1C,Ky1][α1old+α2oldC,α1old+α2old]α2new=Ky1α1newα2new[α1old+α2oldC,α1old+α2old]α2[0,C]α2[max{0,α1old+α2oldC},min{C,α1old+α2old}]y1=y2(标签不同号)α2[max{0,α2oldα1old},min{C,α2oldα1old+C}]
​ 因此,我们需要对 α 2 n e w \alpha_2^{new} α2new进行削减。

​ 除此之外。还有一个问题,就是什么时候停止训练?总不能一直训练下去吧?

​ 我们的一个思路是依据新的 α \alpha α值,如果全部满足以下,则说明已经是最优解。
{ y i ( w T x i + b ) = 1 , 0 < α i < C y i ( w T x i + b ) ≥ 1 , α i = 0 y i ( w T x i + b ) ≤ 1 , α i = C \begin{equation} \begin{aligned} \left\{ \begin{matrix} &y_i(w^Tx_i+b)=1,0<\alpha_i<{C}\\ &y_i(w^Tx_i+b)\ge1,\alpha_i=0\\ &y_i(w^Tx_i+b)\le1,\alpha_i=C \end{matrix} \right. \end{aligned} \end{equation} yi(wTxi+b)=1,0<αi<Cyi(wTxi+b)1,αi=0yi(wTxi+b)1,αi=C

​ 怎么得到的,先看一下KKT条件
{ ∂ L ∂ w ; ∂ L ∂ b ; ∂ L ∂ δ i α i [ 1 − δ i − y i ( w T x i + b ) ] = 0 ; − β i δ i = 0 α i ≥ 0 ; β i ≥ 0 [ 1 − δ i − y i ( w T x i + b ) ] ≤ 0 ; − β i δ i ≤ 0 \left\{ \begin{matrix} \frac{\partial{L}}{\partial{w}};\frac{\partial{L}}{\partial{b}};\frac{\partial{L}}{\partial{\delta_i}}\\ \alpha_i[1-\delta_i-y_i(w^Tx_i+b)]=0; -\beta_i\delta_i=0 \\\alpha_i\ge0;\beta_i\ge0 \\{[1-\delta_i-y_i(w^Tx_i+b)]\le0};-\beta_i\delta_i\le0 \end{matrix} \right. wL;bL;δiLαi[1δiyi(wTxi+b)]=0;βiδi=0αi0;βi0[1δiyi(wTxi+b)]0;βiδi0
​ 前面我们知道,当 δ i ≠ 0 \delta_i\neq0 δi=0代表我们允许的错误点,那么对应的要使得 β i δ i = 0 \beta_i\delta_i=0 βiδi=0,所以 β i = 0 \beta_i=0 βi=0,依据 α i + β i = C \alpha_i+\beta_i=C αi+βi=C,所以当有错误点时,此时 α i = C \alpha_i=C αi=C

​ 我们知道,我们需要计算出新的b。那么如何计算b呢?假如我们循环第一次得到的 α 2 \alpha_2 α2,如果 0 < α 2 < C 0<\alpha_2<C 0<α2<C,说明其是支持向量,我们知道,依据之前提到的KKT条件。那么 x 2 x_2 x2点是支持向量时,有
y 2 ( w T x 2 + b 2 n e w ) = 1 → w T x 2 + b 2 n e w = y 2 y_2(w^Tx_2+b_2^{new})=1 \rightarrow{w^Tx_2+b_2^{new}=y_2} y2(wTx2+b2new)=1wTx2+b2new=y2
​ 所以
b 2 n e w = y 2 − ∑ i = 1 n α i y i K i 2 = y 2 − α 1 n e w y 1 K 12 − α 2 n e w y 2 K 22 − ∑ i = 3 n α i y i K i 2 b_2^{new}=y_{2}-\sum\limits_{i=1}^n\alpha_iy_iK_{i2}=y_2-\alpha_1^{new}y_1K_{12}-\alpha_2^{new}y_2K_{22}-\sum\limits_{i=3}^n\alpha_iy_iK_{i2} b2new=y2i=1nαiyiKi2=y2α1newy1K12α2newy2K22i=3nαiyiKi2
​ 因为
f ( x 2 ) − y 2 = α 1 o l d y 1 K 12 + α 2 o l d y 2 K 22 + ∑ i = 3 n α i y i K i 2 + b o l d − y 2 移向得: y 2 − ∑ i = 3 n α i y i K i 2 = − [ f ( x 2 ) − y 2 ] + α 1 o l d y 1 K 12 + α 2 o l d y 2 K 22 + b o l d 等式左右同时减去: ( α 1 n e w y 1 K 12 + α 2 n e w y 2 K 22 ) 所以依据上一个公式得: b 2 n e w = − [ f ( x 2 ) − y 2 ] + ( α 1 o l d − α 1 n e w ) y 1 K 12 + ( α 2 o l d − α 2 n e w ) y 2 K 22 + b o l d \begin{equation} \begin{aligned} &f(x_2)-y_2=\alpha_1^{old}y_1K_{12}+\alpha_2^{old}y_2K_{22}+\sum\limits_{i=3}^n\alpha_iy_iK_{i2}+b^{old}-y_2 \\移向得:&y_2-\sum\limits_{i=3}^n\alpha_iy_iK_{i2}=-[f(x_2)-y_2]+\alpha_1^{old}y_1K_{12}+\alpha_2^{old}y_2K_{22}+b^{old} \\等式左右同时减去:&(\alpha_1^{new}y_1K_{12}+\alpha_2^{new}y_2K_{22}) \\所以依据上一个公式得:&b_2^{new}=-[f(x_2)-y_2]+(\alpha_1^{old}-\alpha_1^{new})y_1K_{12}+(\alpha_2^{old}-\alpha_2^{new})y_2K_{22}+b^{old} \end{aligned} \end{equation} 移向得:等式左右同时减去:所以依据上一个公式得:f(x2)y2=α1oldy1K12+α2oldy2K22+i=3nαiyiKi2+boldy2y2i=3nαiyiKi2=[f(x2)y2]+α1oldy1K12+α2oldy2K22+bold(α1newy1K12+α2newy2K22)b2new=[f(x2)y2]+(α1oldα1new)y1K12+(α2oldα2new)y2K22+bold
​ 令 E i = f ( x i ) − y i E_i=f(x_i)-y_i Ei=f(xi)yi,得


b n e w = b 2 n e w = − E 2 + ( α 1 o l d − α 1 n e w ) y 1 K 12 + ( α 2 o l d − α 2 n e w ) y 2 K 22 + b o l d b^{new}=b_2^{new}=-E_2+(\alpha_1^{old}-\alpha_1^{new})y_1K_{12}+(\alpha_2^{old}-\alpha_2^{new})y_2K_{22}+b^{old} bnew=b2new=E2+(α1oldα1new)y1K12+(α2oldα2new)y2K22+bold
​ 同理如果 0 < α 1 < C 0<\alpha_1<C 0<α1<C,那么
b n e w = b 1 n e w = − E 1 + ( α 1 o l d − α 1 n e w ) y 1 K 11 + ( α 2 o l d − α 2 n e w ) y 2 K 21 + b o l d b^{new}=b_1^{new}=-E_1+(\alpha_1^{old}-\alpha_1^{new})y_1K_{11}+(\alpha_2^{old}-\alpha_2^{new})y_2K_{21}+b^{old} bnew=b1new=E1+(α1oldα1new)y1K11+(α2oldα2new)y2K21+bold
​ 当 0 < α 1 < C , 0 < α 2 < C 0<\alpha_1<C,0<\alpha_2<C 0<α1<C,0<α2<C,那么, b 1 n e w = b 2 n e w b_1^{new}=b_2^{new} b1new=b2new

​ 当 α i = 0 或 C \alpha_i=0或C αi=0C,此时
b n e w = b 1 n e w + b 2 n e w 2 b^{new}=\frac{b_1^{new}+b_2^{new}}{2} bnew=2b1new+b2new
对于这个式子,我无法理解。书上写的是 b 1 n e w b_1^{new} b1new b 2 n e w b_2^{new} b2new b n e w b^{new} bnew的取值范围。可是我当 a i = 0 a_i=0 ai=0时,此时 y i ( w T x i + b ) ≥ 1 y_i(w^Tx_i+b)\ge1 yi(wTxi+b)1,那么理应新的 b n e w b^{new} bnew应该要取 b 1 n e w , b n e w b_1^{new},b^{new} b1new,bnew的最大值,如果只是取到中间值,这无疑只能够满足其中的一个条件。后来我觉得,会不会是 b 1 n e w = b 2 n e w b_1^{new}=b_2^{new} b1new=b2new,结果我发现也不恒等。再者,如果说 α 1 = 0 , α 2 = C \alpha_1=0,\alpha_2=C α1=0,α2=C,而 α 1 \alpha_1 α1所对应的是 b 1 , b 2 b_1,b_2 b1,b2,那么 b 1 ≤ b n e w ≤ b 2 b_1\le{b_{new}}\le{b_2} b1bnewb2,但是问题又来了,假如 b 1 > b 2 b_1>b_2 b1>b2(我并不知道会不会有这种情况,在这里我们姑且算是存在这种情况),那不等式将没有意义了啊?所以,究竟是怎么一回事?

我在网上寻找答案。发现了有一些人是不顾 α i \alpha_i αi的取值。直接就是 b n e w = b 1 n e w + b 2 n e w 2 b^{new}=\frac{b_1^{new}+b_2^{new}}{2} bnew=2b1new+b2new,不分任何情况。

后来我又去图书馆,找了一本《机器学习》的书看了一下(书名和作者我记不清了),发现要分不同 α i \alpha_i αi取不同的 b n e w b^{new} bnew,按照我的想法,这种方式也雀食更加合理。我没有看过原始论文,但貌似论文中也是这么写的。

可是,有意思的是,无论分不分类讨论,最终都可以收敛,甚至当属于硬间隔的情况下,在 b 1 n e w = 0 , b 2 n e w = 0 b_1^{new}=0,b_2^{new}=0 b1new=0,b2new=0下,我直接取最大的一个 b n e w b^{new} bnew,依然可以收敛。无非就是收敛的快慢的问题。

于是,我就想,有没有一种可能,对于不同的 b 1 n e w , b 2 n e w b_1^{new},b_2^{new} b1new,b2new,我们选择一个新的 b n e w b^{new} bnew时,只要满足其中一个条件也是可行的?或者说,取一个中间值,也很接近两个条件,是不是也可以呢?

我个人认为是可行的。模型的收敛需要一定的迭代次数,我们固定其余变量而更改两个,但是更改的这两个在其余变量不变的情况下才属于最优值。可一旦其他变量也通过更新改变了,那么第一次改变的那两个变量有可能就不是最优值了。牵一发而动全身,也正是因为如此,我认为对于b的值其实没有必要都把控的对,因为后面还是要改的啊,所以为了简单起见,取一个中间值,脚踏两条船,未尝不是一个方法,反正 b b b的取值也是要慢慢收敛的。具体的,可以在代码中尝试。

以上这一段加粗的内容,是个人猜想,正确的可能性不大,只是想说出我的疑惑,书上并无解释,但书上写的是 b 1 n e w b_1^{new} b1new b 2 n e w b_2^{new} b2new b n e w b^{new} bnew的取值范围,这一句话,似乎打破了我所有的幻想,应该是我脑子不太好使的原因,想了好几天也没想明白。有懂哥解释下,万分感谢。

启发式变量选择

​ 在算法中,我们初始的想法对于所有的拉格朗日算子α,我们是按顺序两个两个地更新,或者随机选取两个。这种方式无疑要耗费大量的时间。

​ 所以,我们选择要更新的变量的时候,最好选择的那个变量刚好需要更新。

​ 那怎么做呢?我们知道,我们最终的结果无外乎三种
{ y i ( w T x i + b ) = 1 , 0 < α i < C y i ( w T x i + b ) ≥ 1 , α i = 0 y i ( w T x i + b ) ≤ 1 , α i = C \begin{equation} \begin{aligned} \left\{ \begin{matrix} &y_i(w^Tx_i+b)=1,0<\alpha_i<{C}\\ &y_i(w^Tx_i+b)\ge1,\alpha_i=0\\ &y_i(w^Tx_i+b)\le1,\alpha_i=C \end{matrix} \right. \end{aligned} \end{equation} yi(wTxi+b)=1,0<αi<Cyi(wTxi+b)1,αi=0yi(wTxi+b)1,αi=C
​ 因为我们每一次要选择两个变量算子,因此这第一个 α 1 \alpha_1 α1,我们可以选择违反了上述公式的点。如何确定其是否违反了上述公式?令
E i = f ( x i ) − y i E_i=f(x_i)-y_i Ei=f(xi)yi
​ 所以
y i ∗ E i = y i f ( x i ) − 1 y_i*E_i=y_if(x_i)-1 yiEi=yif(xi)1
​ 所以,当 y i ∗ E i ≥ 0 , α i = 0 y_i*E_i\ge0,\alpha_i=0 yiEi0,αi=0,当 y i ∗ E i ≤ 0 , α i = C y_i*E_i\le0,\alpha_i=C yiEi0,αi=C

​ 因此,我们所要的违反上述公式的点就可以写成

(yi*Ei>0 and α>0) or (yi*Ei<0 and α<C)

​ 但是,书上讲的是,此处并不是 y i ∗ E i > 0 y_i*E_i>0 yiEi>0,而是

(yi*Ei>tol and α>0) or (yi*Ei<-tol and α<C)

​ 此处tol一般取0.001,被称为容忍度。因为我们在训练的过程中,所有的点并不是严格符合KKT条件,所以我们就放缓一点点这样。

​ 我们有了 α 1 \alpha_1 α1,那么 α 2 \alpha_2 α2呢,我们一般会选择 ∣ E 1 − E 2 ∣ |E_1-E_2| E1E2最大的点,依据 α 2 \alpha_2 α2的公式,我们知道如果 ∣ E 1 − E 2 ∣ |E_1-E_2| E1E2越大,在其他变量不变的情况下,更新的跨度也越大。

​ 但是,在算法中,我选择了最大的那个 α 2 \alpha_2 α2,其会导致模型无法收敛,而在有一些文章中,有人也表示如果无法收敛,可以选择遍历所有的点作为 α 2 \alpha_2 α2,或者随机选择一个。

​ 因此,为了简单起见,我在代码中。 α 2 \alpha_2 α2我直接随机选择,这样的收敛速度或许会比不上选择最大的,但是依然可以收敛。

至于核函数,我觉得不用懂原理,可以直接用就行。在这里为了可视化过程,就不用核函数了,因为有了核函数,那么直线的权重就算不出来了。

代码复现

在这里插入图片描述

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
plt.ion()
class SVM():
    def __init__(self):
        pass
    def train(self,x,y):
        self.x=x #数据点 ,维度(n,2)
        self.w=np.zeros((self.x.shape[1],1)) #初始化全为0的w权重,维度(2,1)
        self.y=y #标签值
        self.C=1.0 #惩罚系数
        self.tol=1e-3 #容忍度
        self.alpha=np.zeros((self.x.shape[0],1)) #初始化全为0的α值
        self.b=np.zeros(1) #初始化偏置项
        self.alpha_copy=np.ones((self.x.shape[0],1)) #生成一份复制的α,初始值设置和真正的α不同,用于判断是否模型收敛
        flag = 1 #记录
        for epoch in range(500):#循环500次
            if (self.alpha_copy==self.alpha).all(): #判断是否一样
                if flag==100: #如果循环了一百次都一样,则认为模型已经收敛
                    print("结束循环")
                    print("w:",self.w)
                    exit()
                else: #否则继续迭代更新,并计数加一
                    flag+=1
                    self.updata() #更新α
            else:
                # 如果并不全部一样,则认为数据更新过了,把新的α赋给复制的那一份,然后进行更新
                self.alpha_copy = self.alpha.copy()
                flag=0
                self.updata()
        print(self.w)
    def updata(self):
        for i in np.arange(0, self.x.shape[0]): #迭代所有的点
            self.w = self.x.T @ (self.y * self.alpha) #计算出w
            y1 = self.y[i] #取出a1的标签值
            alpha1_old = self.alpha[i] #取出a1
            E1 = self.w.T @ self.x[i] + self.b - y1 #计算E1
            #判断是否违法KKT条件
            if ((E1 * y1 > self.tol and alpha1_old > 0) or (E1 * y1 < -self.tol and alpha1_old < self.C)):
                #随机选取一个点作为a2,但是不能与a1相等
                j = i
                while j == i:
                    j = np.random.choice(self.alpha.shape[0], size=1)[0]
                alpha2_old = self.alpha[j] #取出a2
                y2 = self.y[j] #取出a2的标签值
                E2 = self.w.T @ self.x[j] + self.b - y2 #计算E2
                K11 = self.x[i].T @ self.x[i]
                K22 = self.x[j].T @ self.x[j]
                K12 = self.x[i].T @ self.x[j]
                eta = K11 + K22 - 2 * K12 #计算η
                if eta == 0: #如果等于0无意义,直接跳过计算
                    continue
                alpha2_unclip = alpha2_old + y2 * (E1 - E2) / eta #计算没有剪裁过的a2
                if y1 == y2:
                    L = max(0, alpha1_old + alpha2_old - self.C)
                    R = min(self.C, alpha1_old + alpha2_old)
                else:
                    L = max(0, alpha2_old - alpha1_old)
                    R = min(self.C, alpha2_old - alpha1_old + self.C)
                alpha2 = np.clip(alpha2_unclip, L, R) #剪裁a2
                alpha1 = alpha1_old + (alpha2_old - alpha2) * y1 * y2 #计算a1
                self.alpha[i], self.alpha[j] = alpha1, alpha2 #修改α,将新的赋值过去
                #计算b1,b2
                new_b1 = -E1 + (alpha1_old - alpha1) * y1 * K11 + \
                         (alpha2_old - alpha2) * y2 * K12 + self.b
                new_b2 = -E2 + (alpha1_old - alpha1) * y1 * K12 + \
                         (alpha2_old - alpha2) * y2 * K22 + self.b
                #计算新的w,画图用的,按理说不用计算
                self.w = self.x.T @ (self.y * self.alpha)
                # 分类讨论决定新的b的取值
                if 0 < alpha1 < self.C:
                    self.b = new_b1
                elif 0 < alpha2 < self.C:
                    self.b = new_b2
                else:
                    self.b = (new_b1 + new_b2) / 2
        figure_plot(x, y, self.w, self.b) #绘图函数

def figure_plot(x,y,w,b):
    #绘图函数
    color_map={-1:"r",1:"b"}
    color=[color_map[i] for i in y.squeeze()]
    x_1=np.arange(-2.5,3)
    x_2=(-w[0]*x_1-b.reshape(-1))/(w[1]+1e-3)
    plt.cla()
    plt.scatter(x[:,0],x[:,1],c=color)
    plt.plot(x_1,x_2)
    plt.xlim((-2.5, 2.5))
    plt.ylim((-2.5, 3))
    plt.pause(0.1)
if __name__ == '__main__':
    x1=stats.norm.rvs(5,1,(100,2)) #第一类数据
    y1=np.ones((100,1)) #第一类数据的类别
    x2=stats.norm.rvs(0,1 ,(100,2)) #第二类数据
    y2 = np.ones((100, 1))*-1 #第二类数据类别
    #合并数据
    x=np.concatenate((x1,x2),axis=0)
    y=np.concatenate((y1,y2),axis=0)
    x_mean=np.mean(x,axis=0) #均值
    x_std=np.std(x,axis=0)  #标准差
    x=(x-x_mean)/x_std #标准化数据
    svm=SVM() #初始化
    svm.train(x,y) #训练

结束

​ 以上就是我学习到了SVM的推导过程了,过程并不研究,如有问题,还望指出,阿里嘎多。

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值