SVM的SMO算法实现.docx
- 文档编号:12304428
- 上传时间:2023-04-18
- 格式:DOCX
- 页数:24
- 大小:291.03KB
SVM的SMO算法实现.docx
《SVM的SMO算法实现.docx》由会员分享,可在线阅读,更多相关《SVM的SMO算法实现.docx(24页珍藏版)》请在冰豆网上搜索。
SVM的SMO算法实现
SVM的SMO算法实现
自研0谭李(006334)吴翔(006333)
摘要
支持向量机(SupportVectorMachine)是一种新近出现的解决模式识别问题的有效工具。
它的数学模型可以归结为一个有约束的二次规划问题。
如何快速准确地解这个二次规划,是SVM推广应用中的一个重要环节。
我们尝试了数种可能的方法,用程序实现了其中最有效的一种——SMO算法(SequentialMinimalOptimizationalgorithm),并用块算法的思想(Chunking)对其作出了改进。
本文将先给出待解决的数学模型,介绍我们所做的一些尝试,然后着重讨论SMO算法的原理、程序实现及其独特优势,最后阐述我们自己的一些新思想,主要是经过改进的ChunkingSMO算法,并在附录中介绍SVM的基本原理。
SVM的数学模型
这里简要介绍支持向量机(SVM)数学模型的引出过程,关于SVM的详细介绍将在附录中给出。
支持向量机的原理是用分类超平面将空间中两类样本点正确分离,并取得最大边缘(正样本与负样本到超平面的最小距离)这样,原问题为一个有约束非线性规划问题:
范数最小的满足约束的w就是最优分类超平面的法向量。
目标函数是严格上凹的二次型,约束函数是下凹的,这是一个严格凸规划。
按照最优化理论中凸二次规划的解法,我们把它转化为Wolfe对偶问题来求解:
其中αi正是样本点xi的Lagrange乘子。
Kuhn-Tunker条件定理指出,无效约束所对应的Lagrange乘子一定为0,在这里的物理意义也就是说非支持向量xi(对应着原问题中的约束yi(w’xi+b)-1>0)的Lagrange乘子一定为0。
这样分类规则就仅由恰好在超平面边缘上的少数支持向量(对应着约束yi(w’xi+b)-1=0)决定,而与其它样本无关。
“支持向量机”这一名称由此而来。
对于非线形情况,只需将对偶问题中的点积用卷积核函数K(xi,xj)代替。
对于样本点不可分的情况,构造软边缘分类面,最终得到的Wolfe对偶问题与原来相似,只是α多了一个上限约束。
这个上限C代表着对错分样本的惩罚力度,在边缘之内的样本对分类面的构造所起的作用是有限制的,这就是所谓“软边缘”的含义。
最后,由于求最大值可以转化为取负求最小值,这一数学模型最终表达为:
其中H是一个半正定的对称阵[yiyjK(xi,xj)]li,j=1(线性的情况也就是(XY)T(XY),X=[x1,x2,…,xl],Y=diag(y1,y2,…,yl),)α=[α1,α2,…,αl]T
这个对偶问题仍是一个有约束的二次规划,它的Kuhn-Tucker条件(在SVM的文献中多称为Kaush-Kuhn-Tucker条件)也可等价地表示为
其中ui就是分类面(在非线性下不一定是超平面)函数作用在xi上的输出:
这一KKT条件在我们的问题中有其具体的物理意义:
第一种情况是说xi是非支持向量,在分类面边缘以外,其Lagrange乘子为0,对分类面的构造没有影响;第二种情况是说xi是正好在分类面上的支持向量,对应着非零的Lagrange乘子;第三种情况是说xi在分类面边缘以内甚至被错分,其Lagrange乘子受到上限的限制而为C。
关于二次规划算法的探索
Wolfe对偶问题比原始问题易于处理,它把问题转化成了在非负象限内对以样本的Lagrange乘子为变量的半正定的二次函数Wolfe进行优化,并服从一个的等式约束。
但由于问题规模比较大,再加上目标函数的二次型已不是正定的,而且约束个数较多,又是等式约束和不等式约束的混合问题,在样本点不可分时还要加以上限的约束。
这种复杂局面使得很多高效的算法对此束手无策,SVM方法至今未能得到广泛的应用,难以找到快速的算法不能不说是一个重要的原因。
二次规划是一种常见的优化问题,关于二次规划有一套比较成熟的理论。
最初我们试图把这个问题作为一个纯数学问题来对待,从寻优理论中找到一种能解决我们的问题的数值方法,但是可以说是以失败告终。
不过,我们还是了解到不少二次规划的一般方法,并从中总结了一些经验。
在二次规划中,条件极值问题的通常解法有罚函数法和单纯形法。
罚函数法在以往曾被作为一种标准的SVM算法。
其基本思想是将解不满足约束条件的程度作为惩罚项加在目标函数中,将条件极值问题转化为无条件极值问题来处理,求得其解后增大惩罚力度,将上一步的结果作为下次寻优的起始迭代点,再求解无条件极值问题,直到解满足约束为止。
其中的无约束极值问题可以用共轭梯度法求解。
典型的共轭梯度法针对的是对称正定的二次规划问题,进行n步迭代一定得到最优解。
对于半正定的问题,共轭梯度法也会是可行的,但n步迭代不能结束,算法的停止条件应设为梯度范数在允许误差范围内(也就是说目标函数没有很大下降余地了算法就结束)。
我实验室成员曾对此算法进行过研究,并向我介绍了他们当时的工作。
此算法用C语言实现后效果并不理想,当样本点增加到30个时算法开始变慢,并经常出现不收敛的现象。
这是因为梯度范数并不能准确地代表目标函数的下降余地,有时迭代一步调整太大,“过犹不及”,导致了一种“矫枉过正”的局面。
解决的办法是调整惩罚因子大小以及修正迭代步长计算公式。
因此程序的执行伴随着试探性的调试过程,这需要调试者充分了解这种算法的原理并具有丰富的调试经验。
样本数目进一步增多,算法将完全不能收敛。
我们参考了算法的C语言源程序,没有找到可作重大改进的地方。
也许共轭梯度法本身并不适合我们的问题。
单纯形法是先随机找到一个可行点作为初值点,构造以可行点为顶点的单纯形,然后按某种搜索策略逐步缩小单纯形,直至各顶点间的距离在允许误差范围内为止。
单纯形法解决的问题标准形式正与我们的问题相符,我实验室成员也对这种算法进行过研究,发现计算结果与初值关系较大,如果能凭先验经验选择一个离最优解较近的初值点,算法就能很快收敛,否则很容易陷入死循环。
而这正违背了支持向量机法的初衷之一:
仅凭科学的模式识别方法而不是先验知识来作出划分。
这种方法看来也不可行。
其它各种文献中介绍的一些二次规划方法大多是针对某种特殊问题的,如要求目标函数的Hessian矩阵对称正定,或只能解决单纯的等式约束问题,或只能解决单纯的不等式约束问题,都很难符合我们的要求。
另外,Matlab的Optimization软件包里有一个适用于各种二次规划问题的现成程序Quadprog,我们用Matlab编了一个程序调用这个函数,有一定效果,但样本个数增加到200个时,不但计算较慢,而且结果很不理想,这可能与数值方法所特有的误差积累效应有关。
Matlab的函数是针对很一般的二次规划问题的,不可能考虑到我们这个问题本身的特点,效率不高也在我们意料之中。
SMO算法
在大量地查阅二次规划的一般方法的同时,我们也在努力从SVM本身的角度寻求解答,也就是说,问题所提供的信息并不完全包含在这个二次规划的数学问题中,从问题本身的物理意义出发还是有可能做出突破的。
最终我们果然在JohnC.Platt1999年的一篇论文[2]中找到了这样的方法。
一.SMO算法的原理
这一被称为“顺次最小优化”的算法和以往的一些SVM改进算法一样,是把整个二次规划问题分解为很多易于处理的小问题(后面我们将探讨SMO与以往SVM改进算法之间的联系),所不同的是,只有SMO算法把问题分解到可能达到的最小规模:
每次优化只处理两个样本的优化问题,并且用解析的方法进行处理。
我们将会看到,这种与众不同的方法带来了一系列不可比拟的优势。
对SVM来说,一次至少要同时对两个样本进行优化(就是优化它们对应的Lagrange乘子),这是因为等式约束的存在使得我们不可能单独优化一个变量。
所谓“最小优化”的最大好处就是使得我们可以用解析的方法求解每一个最小规模的优化问题,从而完全避免了迭代算法。
当然,这样一次“最小优化”不可能保证其结果就是所优化的Lagrange乘子的最终结果,但会使目标函数向极小值迈进一步。
我们再对其它Lagrange乘子做最小优化,直到所有乘子都符合KKT条件时,目标函数达到最小,算法结束。
这样,SMO算法要解决两个问题:
一是怎样解决两个变量的优化问题,二是怎样决定先对哪些Lagrange乘子进行优化。
二.两个Lagrange乘子的优化问题(子程序takeStep)
我们在这里不妨设正在优化的两个Lagrange乘子对应的样本正是第一个和第二个,对两个Lagrange乘子α1和α2,在其他乘子不改变的情况下,它们的约束条件应表达为正方形内的一条线段。
(如图1)
α2=Cα2=C
α1=0a1=Cα1=0α1=C
α2=0α2=0
在这条线段上求一个函数的极值,相当于一个一维的极值问题。
我们可以把α1用α2表示,对α2求无条件极值,如果目标函数是严格上凹的,最小值就一定在这一极值点(极值点在区间内)或在区间端点(极值点在区间外)。
α2确定后,α1也就确定下来了。
因此我们先找到α2优化区间的上下限制,再在这个区间中对α2求最小值。
由图1我们容易得到α2的上下限应为:
L=max(0,α2-α1),H=min(C,C+α2–α1),若y1与y2异号;
L=max(0,α2+α1-C),H=min(C,α2+α1),若y1与y2同号;
令s=y1y2标志这两个样本是否同类,则有
L=max(0,α2+sα1-1/2(s+1)C),H=min(C,α2+sα1–1/2(s-1)C)
而α1和α2在本次优化中所服从的等式约束为:
α1+sα2=α01+sα02=d
下面我们推导求最小值点α2的公式:
由于只有α1,α2两个变量需要考虑,目标函数可以写成
Wolfe(α1,α2)=1/2K11α21+1/2K22α22+sK12α1α2+y1α1v1+y2α2v2-α1-α2+常数
其中Kij=K(xi,xj),vi=y3α03Ki3+…+ylα0lKil=ui+b0-y1α01K1i–y2α01K2i
上标为0的量表示是本次优化之前Lagrange乘子的原值。
将α2用α1表示并代入目标函数:
Wolfe(α2)=1/2K11(d-sα2)2+1/2K22α22+sK12(d-sα2)α2
+y1(d-sα2)v1–d+sα2+y2α2v2-α2+常数
对α2求导:
dWolfe(α2)/dα2
=-sK11(d-sα2)+K22α2-K12α2+sK12(d-sα2)-y2v2+s+y2v2-1=0
如果Wolfe函数总是严格上凹的,即二阶导数K11+K22-2K12>0,那么驻点必为极小值点,无条件的极值点就为
α2=[s(K11-K12)d+y2(v1-v2)+1-s]/(K11+K22-2K12)
将d,v与α0,u之间关系代入,就得到用上一步的α02,u1,u2表示的α2的无条件最优点:
α2=[α02(K11+K22-2K12)+y2(u1-u2+y2-y1)]/(K11+K22-2K12)
令η=K11+K22-2K12为目标函数的二阶导数,Ei=ui-yi为第i个训练样本的“误差”,这个式子又可以写为
α2=α02+y2(E1-E2)/η
除非核函数K不满足Mercer条件(也就是说不能作为核函数),η不会出现负值。
但η=0是可以出现的情况。
这时我们计算目标函数在线段两个端点上的取值,并将Lagrange乘子修正到目标函数较小的端点上:
f1=y1(E1+b)-α1K(x1,x1)-sα2K(x1,x1)
f2=y2(E2+b)-sα1K(x1,x2)-α2K(x2,x2)
L1=α1+s(α2-L)
H1=α1+s(α2-H)
WolfeL=L1f1+Lf2+1/2L21K(x1,x1)+1/2L2K(x2,x2)+sLL1K(x1,x2)
WolfeH=H1f1+Hf2+1/2H21K(x1,x1)+1/2H2K(x2,x2)+sHH1K(x1,x2)
当两个端点上取得相同的目标函数值时,目标函数在整条线段上的取值都会是一样的(因为它是上凹的),这时不必对α1,α2作出修正。
α2的无条件极值确定后,再考虑上下限的限制,最终的α2为
最后,由等式约束确定α1:
α1*=α1+s(α2-α2*)
三.选择待优化Lagrange乘子的试探找点法
事实上即使我们不采用任何找点法,只是按顺序抽取αi,αj的所有组合进行优化,目标函数也会不断下降,直到任一对αi,αj都不能继续优化,目标函数就会收敛到极小值。
我们采取某种找点方法只是为了使算法收敛得更快。
这种试探法先选择最有可能需要优化的α2,再针对这样的α2选择最有可能取得较大修正步长的α1。
这样,我们在程序中使用两个层次的循环:
内层循环(子程序examineExample)针对违反KKT条件的样本选择另一个样本与它配对优化(指优化它们的Lagrange乘子),选择的依据是尽量使这样一对样本能取得最大优化步长。
对其中一个Lagrange乘子α2来说优化步长为|(E1-E2)/η|,但由于核函数估算耗时较大,我们只用|E1-E2|来大致估计有可能取得的步长大小。
也就是说,选出使得|E1-E2|最大的样本作为第二个样本。
需要注意的是,这样的步长估计是比较粗略的,选择出来的一对样本有时非但不能“一劳永逸”地“一步到位”,反而不能作出进一步调整,(例如η=0的情况,最小优化问题的二次型只是半正定的)。
这时我们遍历所有非边界样本(非边界样本就是Lagrange乘子不在边界0或C上的样本),继续寻找能与α2配对优化的α1,如果这样的样本在非边界样本中找不到,再遍历所有样本。
这两次遍历都是从随机位置开始的,以免算法总是在一开始遍历就向固定的方向偏差。
在极端退化的情形,找不到与α2配对能作出进一步调整的α1,这时我们放弃第一个样本。
外层循环(主程序smo)遍历非边界样本或所有样本:
优先选择遍历非边界样本,因为非边界样本更有可能需要调整,而边界样本常常不能得到进一步调整而留在边界上(可以想象大部分样本都很明显不可能是支持向量,它们的Lagrange乘子一旦取得零值就无需再调整)。
循环遍历非边界样本并选出它们当中违反KKT条件的样本进行调整,直到非边界样本全部满足KKT条件为止。
当某一次遍历发现没有非边界样本得到调整时,就遍历所有样本,以检验是否整个集合也都满足KKT条件。
如果在整个集合的检验中又有样本被进一步优化,就有必要再遍历非边界样本。
这样,外层循环不停地在“遍历所有样本”和“遍历非边界样本”之间切换,直到整个训练集都满足KKT条件为止。
以上用KKT条件对样本所作检验都是达到一定精度就可以了,例如正侧的非边界样本的输出ui可以在1的一定公差范围之内,通常这一公差(tolerance)取0.001,如果要求十分精确的输出算法就不能很快收敛。
四.每次最小优化后的重置工作
每做完一次最小优化,必须更新每个样本的误差(ErrorCache),以便用修正过的分类面对其它样本再做KKT检验,以及选择第二个配对优化样本时估计步长之用。
更新ErrorCache首先要重置阈值b。
我们可直接利用刚刚被优化的两个样本的信息在原阈值b0基础上作简单修正,而不需要调用所有支持向量重新计算b。
最小优化后的α1*如果不在边界上,b的计算公式为:
b1=E1+y1(α1*-α10)K(x1,x1)+y2(α2*-α20)K(x1,x2)+b0
最小优化后的α2*如果不在边界上,b的计算公式为:
b2=E2+y1(α1*-α10)K(x1,x2)+y2(α2*-α20)K(x2,x2)+b0
α1*,α2*都不在边界上时,b1和b2是相等的。
两个Lagrange乘子都在边界上时,b1和b2以及它们之间的数都可作为符合KKT条件的阈值。
这时SMO算法选择最安全的b1,b2之中点作为阈值。
非线性的情况,误差的计算要用到所有已找到的支持向量及它们的Lagrange乘子:
线性的情况则是先重置分类超平面的法向量w,再根据uj=w’xj-b计算输出uj和误差Ej=uj-yj。
同阈值的重置一样,法向量的重置也不需要调用所有的支持向量,只需在原来的法向量基础上作改动:
w*=w+y1(α1*-α1)x1+y2(α2*-α2)x2
大部分重置工作都是以简单的非循环计算来完成的,这使得需要做很多次最小优化的SMO算法不必在每次优化后的重置中花费太多时间。
但是我们也看到,非线性的情况误差的重置必须与所有支持向量逐个计算核函数,而且核函数的计算本身就比点积复杂,于是非线性的情况误差的重置将成为算法速度的瓶颈。
五.SMO算法的特点和优势
SMO算法和以往流行的SVM优化算法如块算法、固定工作样本集法相比,既有共同点,又有自己的独特之处。
共同点在于它们都是把一个大的优化问题分解为很多小问题来处理。
块算法在每一步中将新加入样本中违反KKT条件的样本与原有的支持向量一起组成小问题的样本集进行优化,优化完毕后只保留其中的支持向量,再加进来新的样本进入下一步。
固定工作样本集法是每一步只收集新加入样本中“最坏”的样本,并将原来保留的支持向量集中“较好”的替换出去,以保持样本集大小不变。
SMO则是把每一步的优化问题缩减到了最小,它可以看作是固定工作样本集法的一种特殊情况:
把工作样本集的大小固定为2,并且每一步用两个新的Lagrange乘子替换原有的全部乘子。
SMO的最大特色在于它可以采用解析的方法而完全避免了二次规划数值解法的复杂迭代过程。
这不但大大节省了计算时间,而且不会牵涉到迭代法造成的误差积累(其它一些算法中这种误差积累带来了很大的麻烦)。
理论上SMO的每一步最小优化都不会造成任何误差积累,而如果用双精度数计算,舍入误差几乎可以忽略,于是所有的误差只在于最后一遍检验时以多大的公差要求所有Lagrange乘子满足KKT条件。
可以说SMO算法在速度和精度两方面都得到了保证。
SMO在内存的节省上也颇具特色。
我们看到,由于SMO不涉及二次规划数值解法,就不必将核函数矩阵整个存在内存里,而数值解法每步迭代都要拿这个矩阵作运算。
(4000个样本的核函数矩阵需要128M内存!
)于是SMO使用的内存是与样本集大小成线性增长的,而不象以往的算法那样成平方增长。
在我们的程序中SMO算法最多占用十几兆内存。
SMO使得存储空间问题不再是SVM应用中的另一个瓶颈。
SMO算法对线性支持向量机最为有效,对非线性则不能发挥出全部优势,这是因为线性情况下每次最小优化后的重置工作都是很简单的运算,而非线性时有一步加权求和,占用了主要的时间。
其他算法对线性和非线性区别不大,因为凡是涉及二次规划数值解的算法都把大量时间花在求数值解的运算中了。
当大多数Lagrange乘子都在边界上时,SMO算法的效果会更好。
尽管SMO的计算时间仍比训练集大小增长快得多,但比起其它方法来还是增长得慢一个等级。
因此SMO较适合大数量的样本。
我们通过自己的计算切实发现SMO算法的确是一个不可多得的好创意。
它建立在前人的启发基础之上,又是一个具有划时代意义的新方法。
我们自己的新思想
一.新思想之一——SMO算法与Chunking结合
虽然SMO算法在速度方面已表现出了出众的性能,我们认为仍有可望对其进行改进。
我们想到的一种方法是将Chunking的思路与SMO算法结合起来。
具体地说,就是用类似于块算法的方法将样本集分成许多小块,每一步将原有的支持向量集合并到下一个块中,用SMO算法优化,然后只保留得到的支持向量,继续合并到下一个块中。
这样,如果支持向量的个数不随样本个数线性增长(经常见到的情况是很大的样本集并不比小样本集有更多的支持向量),我们有可望得到一个计算量随样本个数成线性增长的支持向量机。
这种方法是有风险的,因为支持向量并不能完全代表一个样本集。
冒然将样本子集中的非支持向量丢弃,可能丢弃的是整个样本集的真正支持向量。
对于这种风险,我们是这么看待的:
样本集的子集也是可以反映整个集合的特征的,基于子集作出的分类完全违背整个集合的总体概率分布只是小概率事件。
为了减少支持向量的丢失,我们还可以做一些技术上的处理,例如遍历过所有子集以后再将剩下的支持向量合并到第一个子集再作优化,进行第二次遍历。
由于经过第一次遍历得到的支持向量总是会包含整个集合的大部分特征,可以想见第二次遍历不会象第一次那样从盲目开始,因而一定会少丢失一些支持向量。
如此遍历数次,得到的支持向量集就不会有太大偏差了。
我们借鉴块算法的思路而又不完全采用其策略(把原有支持向量和下一个块合并优化而不只是和下一个块中违反KKT条件的点合并优化),也是为了减少支持向量的丢失。
在每一步加入多少新样本的问题上,也有一番斟酌。
我们考虑一次加入n个样本和分k次每次加入n/k个样本(也就是以不同方法取得同样的进展)哪一种计算量小:
我们令原有支持向量个数为n0,并假设在这n个样本处理完后支持向量并没有显著增加(我们针对的就是样本很多,支持向量很少的一类问题),再设SMO算法平均计算量是样本个数的函数t(nx),那么我们要比较的两个计算量分别是kt(n0+n/k)和t(n0+n)。
可以想象,当n0>>n时,t(n0+n)并不比t(n0+n/k)大多少,于是kt(n0+n/k)约为t(n0+n)的k倍;而当n较大,t增长又很快,使t(n0+n)>>t(n0+n/k)时,前一种办法有可能取得更高的效率。
这说明n太大和太小都不一定好,一定存在一个最优的“步长”,可以取得最快的进展速度。
我们将所追求的这种“最高效率”表达为求η=t(n0+n)/n的极大值。
不妨将n作为连续的量,做一个定性的估计:
令η对n导数等于0,得nt’=t。
如果t是指数函数t(n)=ean-1,n就应该是一个常数1/a;如果t是幂函数t(n)=na,n就应该是n0的固定倍数n0/(a-1).
如果有一个对SMO算法复杂度的精确估计,我们无疑能找到一种最优的添加新样本子集的方法在Chunking中使用。
遗憾的是这种估计是非常困难的。
我们在实验中只发现SMO算法平均复杂度随样本个数的增长速度一定远远超过线性函数,但每次个别的计算都有很多其他因素对实际计算时间起着更大的影响。
John在[3]中提到SMO的算法平均复杂度应与n~n2.2成正比,这样每次新加入的样本个数应与现有支持向量个数相当或更多。
如果t确实是随n成幂函数增长,我们可以设置每步“步长”固定为现有支持向量数的p倍,在试验中根据经验调整p以取得最短计算时间。
不管怎么样,这种“ChunkingSMO”的新算法一定可以使计算量随样本个数成线性增长(前提是所针对的问题不会有太多的支持向量)。
我们用程序实现了这一算法,对于某些种类的样本集可以说是效果惊人。
这使得我们已经可以对上百万个训练样本进行操作。
二.新思想之二——SMO反用于解决二次规划问题
SVM的数学模型已经告诉我们,支持向量机的分类问题就等价于一个有约束二次规划问题。
二者之中任何一个有了突破,另一个就也可以得到解决。
我们的本意是找一种二次规划的数值方法应用到SVM的实现算法中,结果发现数学上已有的方法基本上都不能解决问题,反而是从SVM的方向找到了高效的算法,这使得我们有理由猜测,这种算法如能反用在数学中,有可能解决一类尚无有效方法的大型二次规划问题,(据我们了解,二次规划虽然有很多成熟的方法,上万阶二次规划的快速算法却并不多见)并应用到其它学科同一数学模型的问题中去。
我们认为SMO算法可以用于如下形式的二次规划问题:
其中c,d为任意列向量,H为半正定阵。
β=[β1,β2,…,βl]T
这一问题与我们的SVM模型几乎是一样的,唯一的实质性区别在于SVM中我们知道H=(XY)T(X
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SVM SMO 算法 实现