libsvm最新源代码(版本3.21)理解解析(三)

来源:互联网 发布:sql注入与防御 编辑:程序博客网 时间:2024/05/17 09:36

一、回顾

      上篇博文,我们讲述了LIBSVM的SMO算法中的三个算法。本节我们介绍LIBSVM在SMO算法中使用的其他一些技巧和算法。

二、Shrinking

      当我们更新α向量的时候,很可能在循环中期,有相当多的α已经达到收敛,在循环的后半部分已经不再变化了。论文中详细介绍了shrinking的原理支持,当然,我们只关心结果,那就是:在整个循环中,大部分的α元素在循环后期已经不再改变,而只有少部分的α在更新。而这大部分的α都有一个共同点,它们基本都是界上元素,也就是那些α=0或者α=C的元素,因此,不在更新这些α将节省出大量时间。这种移除这些α的技术称为shrinking(压缩)。
      那么,我们就必须挑选出需要进行压缩的元素,将他们移除工作集。在LIBSVM中,将符合下方条件的α进行shriking压缩:

      其中,t为所要进行压缩的α的下标标号。可以看出,要想进行压缩,首先需要判断α是否到达边界,即α=0或者α=C,其次,我们还需要计算出M(α)和m(α),M(α)和m(α)上篇博文已经介绍过含义了。
      接着,我们需要解决的何时做压缩,在LIBSVM中,至少1000次α迭代后便会进行压缩,代码中将压缩计数器的值设为,l为样本数量,每进行一次α迭代,便会将计数器值减1,当计数器值为0时便会进行压缩操作。
      当然,压缩有时候会失误,会将一些仍会更新的α值移除,也就是说,符合压缩条件的大部分都是不再改变的α,但是仍会有小部分的α仍会进行改变,我们不应该将其移除。基于此,LIBSVM中,会在第一次满足下式进行梯度更新操作:

      梯度更新是为了让压缩基于更准确的信息,实际上,就是更新所有的梯度,然后基于这些更新的梯度,再计算调整压缩集合。至于梯度是什么,看上面30式,压缩集的计算需要用到梯度(即导数)。
      在LIBSVM中,还加了一层保险,那就是达到截止条件(下式)时,也会进行梯度的更新,然后重新计算工作集:


     在LIBSVM中,如何将要压缩元素的α移出去呢?代码中采用的是交换,从α[1],α[2]...,α[l]中顺序找一个压缩元素假设为α[i],然后再倒序找一个非压缩元素α[j],然后交换α[i]和α[j],这样,就能保证α数组前面的全是非压缩元素(活跃元素),后面的全是压缩元素(非活跃元素),在代码中,活跃元素与非活跃元素的分割标号为active_size,即a[1]..a[active_size-1]全是活跃元素,而α[active_size]...a[l]全是非活跃元素,即压缩元素。
     至此,shrinking技术基本介绍完毕。

三、Caching

     在LIBSVM中,会将用过的Q(i,j)进行缓存,缓存的结构是一个双向链表,采取的策略是“最近最少使用”算法,即用到Q(i,j)则寻找链表,若找到返回,未找到则摘除最早的那个结点,然后计算新值并加入双向链表末尾。详细的Caching见代码,因未仔细研究也不是本文重点,暂不介绍。

四、梯度重构

     在上面第二节中,我们曾强调,当α迭代循环满足31式或者32式时,我们需要重新计算梯度。在一开始初始化梯度或者每次迭代更新梯度时,梯度的计算公式为:。但是,当满足31式或者32式,为了节省时间,我们不再采用这个公式更新,而是采用:
其中:
因为,当i属于工作集时,我们在寻找工作集的时候已经重新计算过了,所以34式针对的式i不属于工作集的,也就是那些压缩元素的,即i属于(active_size,.....l)。这个公式的含义实际上就是,只不过这里引入了一个。梯度本来等于Qα+p,也就是:
     
至于为什么转换成了34式,是因为这里不再将α按序号分类,而是按α=0,α=C和0<α<C三类分,当α=0时,就等于0,因此直接省略;当α=C时,=*C,所以对于所有的α=C的之和就是,即
然后剩下的便是0<α<C的:
    
所以34式就包含了刚才介绍的这三部分:

为什么要分成三部分计算,这是因为在LIBSVM这样做会重复利用,节省时间。

五、多分类

     SVM实现多分类有一对其余、一对一等方法,在LIBSVM中,采用的是一对一方法。
     一对一方法表示,每两中分类之间训练一个SVM二分类的分类器,假设有k个分类结果,则需要训练k(k-1)/2个二分类分类器。当训练完毕需要预测时,每个分类器都会进行结果预测,多结果进行投票,最终得票多的分类结果即为预测结果。

六、交叉验证

     在LIBSVM中,交叉验证通常总是用来进行参数选择。在LIBSVM中,采取k折交叉验证,即将样本平均分为k份,循环选取其中的k-1份作为样本进行训练,剩下的一份进行验证检验,求出预测正确率。这样,会进行k次交叉验证,求平均值,即为当前选择的参数的识别率。通过不断进行k折交叉验证,即可求得最准确的参数值。通常采用如下网格搜索进行参数搜索选择:
//参数1,如Cfor i=1 to C_Count    //参数2,如r    for j=1 to r_Count//参数n...(k折交叉验证)...//参数nend for //参数2end for //参数1
     即,有几个参数就有几层循环,循环遍历试出最优参数。

七、总结

     本文介绍了LIBSVM常用的小算法,下篇博文中将会完全结合代码把以前讲过的内容分析。


0 0
原创粉丝点击