前言
在经过前面漫长的 SVM 学习之后,是时候学习怎么实现 SVM 了。其实,SVM 常常表现得很好并且有着高效的训练算法,这使得 SVM 曾经非常盛行。只是近些年来,由于深度学习起势,SVM 才不再那么盛行,但它依旧是很好用的分类算法。所以探究 SVM 的原理及思想显得非常有必要,那么现在我们就谈谈 SMO 算法。
首先,在前面的 SVM 学习中,我们有如下对偶问题:
并且需要满足KKT条件:
- 当 \(\alpha_{i}=0\), \(y_{i}\left( w^{T}x_{i}+b\right) \geq 1\);
- 当 \(0<\alpha _{i}<C\), \(y_{i}\left( w^{T}x_{i}+b\right)=1\);
- 当 \(\alpha_{i}=C\), \(y_{i}\left( w^{T}x_{i}+b\right) \leq 1\)。
那么,由于一个训练样本 \(\left(x_{i},y_{i}\right)\) 对应一个 \(\alpha_{i}\),因此我们只需要找到这样一组 \(\alpha_{i}\) 满足上述条件,这就是该对偶问题的最优解。有了这组 \(\alpha_{i}\) ,\(w\)、b 以及分类函数 \(f\left(x\right)\)就可以顺其自然地得到求解。
上述对偶问题是个凸二次规划问题,它具有全局最优解。一般可以使用现有的 QP 工具来进行求解。但是,当训练容量非常大的时候,训练算法反而耗时且低效。因此,有必要寻找更优的求解算法来代替实现。虽然出现了很多优化算法,但比较著名的是一个叫做 John C. Platt 的研究者提出的序列最小化算法 (Sequential Minimal Optimization,简称 SMO)。而它的思想是:将大优化的问题分解成多个小优化的问题。这些小问题往往比较容易求解,然后对他们进行顺序求解。这样之后得到的结果与将他们作为整体来求解的结果完全一致并且最重要的是 SMO 的求解时间更短了。
在介绍 SMO 之前,先介绍下坐标梯度下降算法,这也是 SMO 中利用到的简单的算法思想。
坐标梯度下降(上升)
坐标下降是一种非梯度优化算法(坐标下降用于优化最小值,而坐标上升用于优化最大值,可通过加负号相互转换)。因为算法在每次迭代中,只会从当前点处沿一个坐标方向进行一维搜索以求得一个函数的局部极小值,并在迭代的过程中不断变化优化的坐标方向,直至函数得到收敛。
例如,我们要寻找函数 \(f\left( x,y\right) =5x^{2}-6xy+5y^{2}\) 的最小值。那么坐标优化的迭代过程如下图所示:
我们从某个起始点开始寻找,然后沿着一个方向往等高线上数值小的高度前进(类似下山),在前进的时候,可以改变方向,例如此处可以往上或往右走,直至不断走向中心点,也就是收敛到最优解。
SMO 算法
SMO 算法和坐标梯度下降思想差不多,只是 SMO 一次迭代优化的是两个变量 \(\alpha_{i}\)、\(\alpha_{j}\)。所以它的思想就是将带有多个优化变量的二次规划大问题分解为多个只含两个优化变量的二次规划小问题,这样既节省了时间成本也降低了内存消耗。
那么为什么需要一次优化两个变量呢?这是因为在 SVM 中存在着 \(\sum ^{m}_{i=1}\alpha _{i}y_{i}=c\) 约束,这是一个线性组合关系。而 SMO 在优化前会先固定暂时不进行优化的变量,那么如果仅优化一个变量,那么这个变量就会被其他已固定的参数表示出来,则它就不再是变量,因此,需要再找一个变量。即 SMO 算法先要确定一对 \(\alpha_{i},\alpha_{j}\),其他的变量则先固定。
那么固定参数之后,就可以得到 \(\alpha_{i}\) 和 \(\alpha_{j}\) 的等式关系了。即:
那么我们就可以消去上述对偶问题中的 \(\alpha_{i}\)了,然后就得到了仅关于 \(\alpha_{j}\) 的单变量二次规划问题,然后利用费马引理进行求解即可。解出 \(\alpha_{j}\) 之后,\(\alpha_{i}\) 便可由等式轻易推出,这样就是一次迭代过程。迭代一次仅调整两个拉格朗日乘子。那么这样看来,SMO 之所以高效的原因就在于它是对单变量进行优化,可想而知单变量的收敛速度是比较快的。
总之,一次迭代的三个步骤是:
- 确定一对 \(\left(\alpha_{i},\alpha_{j}\right)\);
- 固定其他 (m-2) 个变量后,消去其中一个变量,得到含单变量的优化式子;
- 根据优化后的 \(\alpha_{i},\alpha_{j}\),更新阈值 b。
关于 \(\alpha_{i}\) 和 \(\alpha_{j}\) 的 选择
现在我们需要从 m 个变量中确定两个变量,那么可能的组合非常多。如何确定到底是哪一对呢?首先,我们的优化目标其实就是尽量使大部分的样本都满足 KKT 条件,即大部分的样本都能得到正确分类。那么,我们就需要先纠正违反 KKT 条件最严重的那个样本对应的优化变量,就好像先把最难的事情做了,接下来再做简单的事,这样就会很轻松。那么第二个变量怎么选?它选择的标准是必须有足够大的变化,也就是能够对目标函数沿着优化方向下降幅度最大的那个变量。这样选择的依据是,对它们进行更新可以加快目标函数的收敛速度。SMO 算法公式推导
求解未被修剪的 \(\alpha^{new,unclipped}_{i}\) ,\(\alpha^{new,unclipped}_{j}\)
首先,我们把 SVM 中对偶问题的目标函数写为:
并且用 \(k_{i,j}\) 代替 \(k\left( x_{i},x_{j}\right)\) 表示。
然后,假设我们选中的待优化变量为 \(\alpha_{1}\) ,\(\alpha_{2}\) 。那么 \(\alpha_{3}\),\(\alpha_{4}\),…,\(\alpha_{m}\) 则被固定,当做常数处理。那么将 SVM 的优化问题展开后得到:
其中将与 \(\alpha_{1}\)、\(\alpha_{2}\) 无关的 \(C_{1}\) 和 \(\sum ^{m}_{i=3}\sum ^{m}_{j=3}\alpha _{i}y_{i}\alpha _{j}y_{j}k_{i,j}\) 合并为常数项 C。
又已知 \(\alpha_{1} y_{1}+\alpha_{2}y_{2}=\xi\) ,\(y_{i}y_{i}=1\),然后等式两边同时乘上 \(y_{1}\) 得到:
另外,记 \(v_{1}=\sum ^{m}_{i=3}\alpha _{i}y_{i}k_{i,1}\),\(v_{2}=\sum ^{m}_{i=3}\alpha _{i}y_{i}k_{i,2}\),最后将所有式子带入 \(w\left( \alpha_{1},\alpha _{2}\right)\) 得到:
接下来利用费马引理求极值,令 \(w\) 对 \(\alpha_{2}\) 的导数为零,得:
然后,现在我们要将 \(\xi\) 消去。
已知 SVM 分类函数公式:\(f\left( x_{i}\right) =\sum ^{m}_{i=1}\alpha _{i}y_{i}k_{i,i}+b\),那么:
得到: \(v_{1}-v_{2}=f\left( x_{1}\right) -f\left( x_{2}\right) -k_{1,1}\xi+k_{1,2}\xi +\left( k_{1,1}+k_{2,2}-2k_{1,2}\right) y_{2}\alpha _{2}\)
现在,我们需要区别下迭代前和迭代之后的变量。其实我们固定的 m-2 个拉格朗日乘子都是上一次迭代的值,所以 \(v_{1}\) 和 \(v_{2}\) 所表示的式子都是前一次迭代的量,那么,由他们推导出来的 \(\alpha_{1}\) 和 \(\alpha_{2}\) 当然也是前一次迭代的量。
那么现在我们以 old 和 new 上角标分别区别前一次迭代和当前迭代的优化量,那么区分后式子改为:
接下来,合并两个式子,再得:
然后,我们记 \(E_{i}\) 为 SVM 的预测值和实际值的误差: \(E_{i}=f\left( x_{i}\right) -y_{i}\),并且令 \(\eta=k_{1,1}+k_{2,2}-2k_{1,2}\),所以最终的一阶求导公式为:
那么就可以解出:
修剪解出的最优解
上面解出的 \(\alpha_{1}\) 和 \(\alpha_{2}\) 并未考虑约束条件。那么,现在我们需要将约束条件加上,然后对所求出的最优解进行范围的修剪以得到最终满足约束条件的最优解。
即:
由于约束条件 \(0\leq \alpha _{1}\leq C\) 、 \(0\leq \alpha _{2}\leq C\) 以及 \(\alpha_{1} y_{1}+\alpha_{2}y_{2}=k, \quad k为常数\) 的存在,所以我们需要给 \(\alpha _{1}\) 和 \(\alpha _{2}\) 找到区间 \(\left[L,H\right]\)。由于只有两个变量,因此约束可以用二维空间中的图形来表示,如下图所示(方形约束)。
那么对于约束 \(\alpha_{1} y_{1}+\alpha_{2}y_{2}=k\)
根据左图:当 \(y_{1}\neq y_{2}\) 时,此约束简化为:\(\alpha_{1}-\alpha_{2}=k\),那么根据 k 的正负可以得到上下界为:
- 下界:\(L=\max \left( 0,\alpha ^{old}_{2}-\alpha ^{old}_{1}\right) \);
- 上界:\(H=\min \left( C,C+\alpha ^{old}_{2}-\alpha ^{old}_{1}\right)\)。
根据右图:当 \(y_{1}= y_{2}\) 时,此约束简化为:\(\alpha_{1}+\alpha_{2}=k\),上下界表示为:
- 下界:\(L=\max \left( 0,\alpha ^{old}_{1}+\alpha ^{old}_{2}-C\right) \);
- 上界:\(H=\min \left( C,\alpha ^{old}_{1}+\alpha ^{old}_{2}\right)\)。
那么,有了上下界之后,如果优化之后的 \(\alpha_{1}\) 和 \(\alpha_{2}\)跑出了边界,那么我们就需要纠正它,所以有:
得到了 \(\alpha ^{new}_{2}\),再根据 \(\alpha^{new}_{1} y_{1}+\alpha^{new}_{2}y_{2}=\alpha^{old}_{1} y_{1}+\alpha^{old}_{2}y_{2}\) ,然后两边同乘以 \(y_{1}\) 可解出 \(\alpha ^{new}_{1}\),即:
这样,我们就得到了两个优化的拉格朗日乘子 \(\alpha^{new}_{1}\) 和 \(\alpha^{new}_{2}\)
计算更新后的阈值 b
在每一次迭代中,优化 \(\alpha^{new}_{1}\) 和 \(\alpha^{new}_{2}\) 之后,就要更新阈值 \(b\)。那么为了使得被优化的样本都满足 KKT 条件,此时需要分为样本在边界上和样本不在边界上两种情况进行讨论。
- 当优化后的 \(\alpha^{new}_{1}\) 不在边界上,也就是满足约束 \(0\leq \alpha^{new}_{1}\leq C\) ,那么根据 KKT 条件得知该样本为支持向量,所以 \(y_{1}f\left( x_{1}\right) =1\),则阈值 \(b_{1}\)是有效的。那么两边同时乘以 \(y_{1}\),并展开式子得: \(\sum ^{m}_{i=1}\alpha _{i}y_{i}k_{i,1}+b=y_{1}\),那么解出 \(b^{new}_{1}\) 为:同理可计算出 \(b^{new}_{2}\):另外,当 \(b^{new}_{1}\) 和 \(b^{new}_{2}\) 均有效时,\(b^{new}=b^{new}_{1}=b^{new}_{2}\)
- 当优化后的 \(\alpha^{new}_{1}\) 和 \(\alpha^{new}_{2}\) 都在边界上,即 (\(\alpha^{new}_{1}=0\) 或 \(\alpha^{new}_{1}=C\),同时 \(\alpha^{new}_{2}=0\) 或 \(\alpha^{new}_{2}=C\)),那么在 \(b^{new}_{1}\) 和 \(b^{new}_{2}\) 之间的阈值都是满足 KKT 条件的,一般我们取它们的中间值来更新阈值,即:\(b^{new}=\dfrac {b^{new}_{1}+b^{new}_{2}}{2}\)。
参考
[1] Sequential Minimal Optimization:
A Fast Algorithm for Training Support Vector Machines by John C. Platt
[2] 机器学习算法与Python实践之(四)支持向量机(SVM)实现 by zouxy
[3] 机器学习算法实践-SVM中的SMO算法 by PytLab酱