软间隔
对于线性可分的数据,我们仅仅使用硬间隔便可以求解。但是还有个问题。假如数据本身就线性不可分呢?又或者我们的数据存在噪声,比如途中,显然直线左边有一个噪声,右边也有一个噪声。
对这一类问题,怎么办?
这很好解决。我们直接训练的时候允许其存在一丢丢的错误不久可以了嘛?怎么做?当燃是调整损失函数
minw,b12wTw+g(x)
\min\limits_{w,b}\frac{1}{2}w^Tw+g(x)
w,bmin21wTw+g(x)
这个f(x)可以当作是允许存在一丢丢错误的损失。
如何设置这个损失?令zi=yi(wTxi+b)z_i=y_i(w^Tx_i+b)zi=yi(wTxi+b)直接
g(x)={1,zi<10,zi≥1
g(x)=
\left \{
\begin{matrix}
1,z_i<1 \\
0,z_i\ge1
\end{matrix}
\right.
g(x)={1,zi<10,zi≥1
看起来是一个不错的方法,因为在我们之前提到之中,我们认为yi(wTxi+b)≥1y_i(w^Tx_i+b)\ge1yi(wTxi+b)≥1是所有分类正确的前提,如果为负数,那么则证明是错误的。但是,有一个致命问题——这个函数并不连续,无法求导。而我们求极值就不可避免地使用求导。要知道,不连续的函数是无法求导的。
怎么办?我们不妨这样设定
g(x)=max{0,1−zi}
g(x)=max\left\{0,1-z_i
\right\}
g(x)=max{0,1−zi}
当yi(wTxi+b)<1y_i(w^Tx_i+b)<1yi(wTxi+b)<1,则说明是错误的点,那么我们就用1−yi(wTxi+b)=1−z1-y_i(w^Tx_i+b)=1-z1−yi(wTxi+b)=1−z来代表错误点损失,如果yi(wTxi+b)≥1y_i(w^Tx_i+b)\ge1yi(wTxi+b)≥1代表正确,所以所得就为0,代表无错误点损失。这是他的图像
令δ=max{0,1−zi}\delta=max\left\{0,1-z_i\right\}δ=max{0,1−zi},我们损失函数就可以为
{12wTw+C∑i=1nδi
\left \{
\frac{1}{2}w^Tw+C\sum\limits_{i=1}^n\delta_i
\right.
{21wTw+Ci=1∑nδi
其中C是一个惩罚系数,越大惩罚力度越大,反之越小。
那么约束条件呢?当燃不能沿用之前的。我是这么理解的1−zi1-z_i1−zi的
坐标中,点K1K_1K1是一个错误点,那么1−zi1-z_i1−zi意为线段K1NK_1NK1N,
对于硬间隔的损失函数为
{minw,b12wTws.t.yi(wTxi+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)≥1,i=1,2⋯,n
所以软间隔的损失函数则为
{12wTw+C∑i=1nδis.t.yi(wTxi+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=1∑nδiyi(wTxi+b)+δi≥1δi≥0;i=1,2,⋯,n
以下步骤不做解释,详细可看硬间隔的部分,因为差不多是一样的。
拉格朗日函数
L(w,b,δ,α,β)=12wTw+C∑i=1nδi+∑i=1n[αi(1−δi−yi(wTxi+b))]−∑i=1nβ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=1∑nδi+i=1∑n[αi(1−δi−yi(wTxi+b))]−i=1∑nβiδi
求原问题再求对偶问题,然后对其求导
∂L∂w→w=∑i=1nαiyixi∂L∂b→∑i=1nαiyi=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}
∂w∂L→w=i=1∑nαiyixi∂b∂L→i=1∑nαiyi=0∂δi∂L→αi+βi=C
令βi=C−αi\beta_i=C-\alpha_iβi=C−αi和另外两个求导所得代入拉格朗日函数。最终
maxα∑i=1nαi−12∑i=1n∑j=1nαiyiαjyjxiTxjs.t.0≤αi≤C,i=1.2.⋯ ,n.∑i=1nαiyi=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=1∑nαi−21i=1∑nj=1∑nαiyiαjyjxiTxjs.t.0≤αi≤C,i=1.2.⋯,n.i=1∑nαiyi=0,
可以发现,目标函数和硬间隔是一样的,只是约束条件从alphai≥0alpha_i\ge0alphai≥0变成了0≤αi≤C0\le\alpha_i \le C0≤αi≤C,所以,最终使用SMO算法求解所得应为一样。但是在硬间隔的时候,我们仅仅是求解了,但是还有一个αi≥0\alpha_i\ge0αi≥0是没有使用的,也就是我们所求出来的λ2new\lambda_2^{new}λ2new并非一定是解,因为我们还需要削减。
此处,我们仅仅求软间隔的取值范围,硬间隔的相对比较容易,读者可自求。
对此,我们先求出α2new\alpha_2^{new}α2new的取值范围。
因为:α1oldy1+α2oldy2=−∑i=3nαiyi=K分情况讨论:①:y1=y2(即标签值同号)对第一个等式左右乘以y1得:α1newy1+α2newy2=Ky1→α2new=Ky1−α1new因为:a1new∈[0,C]所以:−a1new∈[−C,0]因为:α1oldy1+α2oldy2=K所以:Ky1−α1new∈[Ky1−C,Ky1]→[α1old+α2old−C,α1old+α2old]因为:α2new=Ky1−α1new所以:α2new∈[α1old+α2old−C,α1old+α2old]又因为:α2∈[0,C]要同时满足这两个条件,就必须:α2∈[max{0,α1old+α2old−C},min{C,α1old+α2old}]同理得②:y1≠y2(标签不同号)即:α2∈[max{0,α2old−α1old},min{C,α2old−α1old+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=3∑nαiyi=Ky1=y2(即标签值同号)α1newy1+α2newy2=Ky1→α2new=Ky1−α1newa1new∈[0,C]−a1new∈[−C,0]α1oldy1+α2oldy2=KKy1−α1new∈[Ky1−C,Ky1]→[α1old+α2old−C,α1old+α2old]α2new=Ky1−α1newα2new∈[α1old+α2old−C,α1old+α2old]α2∈[0,C]α2∈[max{0,α1old+α2old−C},min{C,α1old+α2old}]y1=y2(标签不同号)α2∈[max{0,α2old−α1old},min{C,α2old−α1old+C}]
因此,我们需要对α2new\alpha_2^{new}α2new进行削减。
除此之外。还有一个问题,就是什么时候停止训练?总不能一直训练下去吧?
我们的一个思路是依据新的α\alphaα值,如果全部满足以下,则说明已经是最优解。
{yi(wTxi+b)=1,0<αi<Cyi(wTxi+b)≥1,αi=0yi(wTxi+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−yi(wTxi+b)]=0;−βiδi=0αi≥0;βi≥0[1−δi−yi(wTxi+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.
⎩⎨⎧∂w∂L;∂b∂L;∂δi∂Lαi[1−δi−yi(wTxi+b)]=0;−βiδi=0αi≥0;βi≥0[1−δi−yi(wTxi+b)]≤0;−βiδi≤0
前面我们知道,当δ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<C0<\alpha_2<C0<α2<C,说明其是支持向量,我们知道,依据之前提到的KKT条件。那么x2x_2x2点是支持向量时,有
y2(wTx2+b2new)=1→wTx2+b2new=y2
y_2(w^Tx_2+b_2^{new})=1 \rightarrow{w^Tx_2+b_2^{new}=y_2}
y2(wTx2+b2new)=1→wTx2+b2new=y2
所以
b2new=y2−∑i=1nαiyiKi2=y2−α1newy1K12−α2newy2K22−∑i=3nαiyiKi2
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=y2−i=1∑nαiyiKi2=y2−α1newy1K12−α2newy2K22−i=3∑nαiyiKi2
因为
f(x2)−y2=α1oldy1K12+α2oldy2K22+∑i=3nαiyiKi2+bold−y2移向得:y2−∑i=3nαiyiKi2=−[f(x2)−y2]+α1oldy1K12+α2oldy2K22+bold等式左右同时减去:(α1newy1K12+α2newy2K22)所以依据上一个公式得:b2new=−[f(x2)−y2]+(α1old−α1new)y1K12+(α2old−α2new)y2K22+bold
\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=3∑nαiyiKi2+bold−y2y2−i=3∑nαiyiKi2=−[f(x2)−y2]+α1oldy1K12+α2oldy2K22+bold(α1newy1K12+α2newy2K22)b2new=−[f(x2)−y2]+(α1old−α1new)y1K12+(α2old−α2new)y2K22+bold
令Ei=f(xi)−yiE_i=f(x_i)-y_iEi=f(xi)−yi,得
bnew=b2new=−E2+(α1old−α1new)y1K12+(α2old−α2new)y2K22+bold
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<C0<\alpha_1<C0<α1<C,那么
bnew=b1new=−E1+(α1old−α1new)y1K11+(α2old−α2new)y2K21+bold
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<C0<\alpha_1<C,0<\alpha_2<C0<α1<C,0<α2<C,那么,b1new=b2newb_1^{new}=b_2^{new}b1new=b2new
当αi=0或C\alpha_i=0或Cαi=0或C,此时
bnew=b1new+b2new2
b^{new}=\frac{b_1^{new}+b_2^{new}}{2}
bnew=2b1new+b2new
对于这个式子,我无法理解。书上写的是b1newb_1^{new}b1new和b2newb_2^{new}b2new是bnewb^{new}bnew的取值范围。可是我当ai=0a_i=0ai=0时,此时yi(wTxi+b)≥1y_i(w^Tx_i+b)\ge1yi(wTxi+b)≥1,那么理应新的bnewb^{new}bnew应该要取b1new,bnewb_1^{new},b^{new}b1new,bnew的最大值,如果只是取到中间值,这无疑只能够满足其中的一个条件。后来我觉得,会不会是b1new=b2newb_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所对应的是b1,b2b_1,b_2b1,b2,那么b1≤bnew≤b2b_1\le{b_{new}}\le{b_2}b1≤bnew≤b2,但是问题又来了,假如b1>b2b_1>b_2b1>b2(我并不知道会不会有这种情况,在这里我们姑且算是存在这种情况),那不等式将没有意义了啊?所以,究竟是怎么一回事?
我在网上寻找答案。发现了有一些人是不顾αi\alpha_iαi的取值。直接就是bnew=b1new+b2new2b^{new}=\frac{b_1^{new}+b_2^{new}}{2}bnew=2b1new+b2new,不分任何情况。
后来我又去图书馆,找了一本《机器学习》的书看了一下(书名和作者我记不清了),发现要分不同αi\alpha_iαi取不同的bnewb^{new}bnew,按照我的想法,这种方式也雀食更加合理。我没有看过原始论文,但貌似论文中也是这么写的。
可是,有意思的是,无论分不分类讨论,最终都可以收敛,甚至当属于硬间隔的情况下,在b1new=0,b2new=0b_1^{new}=0,b_2^{new}=0b1new=0,b2new=0下,我直接取最大的一个bnewb^{new}bnew,依然可以收敛。无非就是收敛的快慢的问题。
于是,我就想,有没有一种可能,对于不同的b1new,b2newb_1^{new},b_2^{new}b1new,b2new,我们选择一个新的bnewb^{new}bnew时,只要满足其中一个条件也是可行的?或者说,取一个中间值,也很接近两个条件,是不是也可以呢?
我个人认为是可行的。模型的收敛需要一定的迭代次数,我们固定其余变量而更改两个,但是更改的这两个在其余变量不变的情况下才属于最优值。可一旦其他变量也通过更新改变了,那么第一次改变的那两个变量有可能就不是最优值了。牵一发而动全身,也正是因为如此,我认为对于b的值其实没有必要都把控的对,因为后面还是要改的啊,所以为了简单起见,取一个中间值,脚踏两条船,未尝不是一个方法,反正bbb的取值也是要慢慢收敛的。具体的,可以在代码中尝试。
以上这一段加粗的内容,是个人猜想,正确的可能性不大,只是想说出我的疑惑,书上并无解释,但书上写的是b1newb_1^{new}b1new和b2newb_2^{new}b2new是bnewb^{new}bnew的取值范围,这一句话,似乎打破了我所有的幻想,应该是我脑子不太好使的原因,想了好几天也没想明白。有懂哥解释下,万分感谢。
启发式变量选择
在算法中,我们初始的想法对于所有的拉格朗日算子α,我们是按顺序两个两个地更新,或者随机选取两个。这种方式无疑要耗费大量的时间。
所以,我们选择要更新的变量的时候,最好选择的那个变量刚好需要更新。
那怎么做呢?我们知道,我们最终的结果无外乎三种
{yi(wTxi+b)=1,0<αi<Cyi(wTxi+b)≥1,αi=0yi(wTxi+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,我们可以选择违反了上述公式的点。如何确定其是否违反了上述公式?令
Ei=f(xi)−yi
E_i=f(x_i)-y_i
Ei=f(xi)−yi
所以
yi∗Ei=yif(xi)−1
y_i*E_i=y_if(x_i)-1
yi∗Ei=yif(xi)−1
所以,当yi∗Ei≥0,αi=0y_i*E_i\ge0,\alpha_i=0yi∗Ei≥0,αi=0,当yi∗Ei≤0,αi=Cy_i*E_i\le0,\alpha_i=Cyi∗Ei≤0,αi=C
因此,我们所要的违反上述公式的点就可以写成
(yi*Ei>0 and α>0) or (yi*Ei<0 and α<C)
但是,书上讲的是,此处并不是yi∗Ei>0y_i*E_i>0yi∗Ei>0,而是
(yi*Ei>tol and α>0) or (yi*Ei<-tol and α<C)
此处tol一般取0.001,被称为容忍度。因为我们在训练的过程中,所有的点并不是严格符合KKT条件,所以我们就放缓一点点这样。
我们有了α1\alpha_1α1,那么α2\alpha_2α2呢,我们一般会选择∣E1−E2∣|E_1-E_2|∣E1−E2∣最大的点,依据α2\alpha_2α2的公式,我们知道如果∣E1−E2∣|E_1-E_2|∣E1−E2∣越大,在其他变量不变的情况下,更新的跨度也越大。
但是,在算法中,我选择了最大的那个α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的推导过程了,过程并不研究,如有问题,还望指出,阿里嘎多。