从零开始-Machine Learning学习笔记(13)-SMO算法中的启发式变量选择

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kabuto_hui/article/details/80474120

​ 在SMO算法中,如果使用遍历所有的 α i ,再随机选择第二个变量进行优化,也能实现功能,但是算法速度非常的慢,为了提高算法的运算速度,目前一般采用一种启发式的变量选择。

​ 在周志华先生的《机器学习》中提到:

只需要选取的 α i α j 中有一个不满足KKT条件,目标函数就会在迭代会变化的幅度增大。只管看来,KKT条件违背程度越大,变量更新后可能导致目标函数数值的变化幅度就会越大。于是,SMO可以首先取违背KKT条件程度最大的向量,第二个变量选取一个使目标函数减小最快的变量。

1.第一个变量的选择

​ 第一变量的选择称为外循环;需要选择一个违反KKT条件的变量。而与原优化问题对应的KKT条件为:

y i f ( x i ) 1       , α i = 0 y i f ( x i ) = 1       , 0 < α i < C y i f ( x i ) 1       , α i = C

怎样才算是违反KKT条件呢?

1)如果 α i < C ,却有 y i f ( x i ) < 1 ,本来它应该等于1的。

2)如果 α i > 0 ,却有 y i f ( x i ) > 1 ,本来它应该等于1的。

上述的两个情况,就是违背KKT的情况,我们对上面的两个情况进行变形如下:

y i E i = y i ( f ( x i ) y i ) = y i f ( x i ) 1

于是违反KKT条件的两种情况可以描述为:

1)如果 α i < C ,并且有 y i E i < 0 ,即 y i f ( x i ) < 1

2)如果 α i > 0 ,并且有 y i E i > 0 ,即 y i f ( x i ) > 1

于是我们在写代码的时候判断条件可以写成这样:

if (y[i]E[i]>0 and alpha[i]>0) or (y[i]E[i]<0 and alpha[i]<C):

但是我们在《Machine Learning in Action》一书中关于第一个变量选择时使用的判断条件为:

 if ((oS.labelMat[i]*Ei < -oS.tol) and (oS.alphas[i] < oS.C)) or ((oS.labelMat[i]*Ei > oS.tol)        and (oS.alphas[i] > 0)):

这里我稍做一下解释,oS.labelMat[i]相当于y[i],oS.C相当于C,唯一的不同是多了一个oS.tol,这个变量是干嘛用的,我之前也不了解,于是我去查了一下发现oS.tol是一个被称之为容错率的东西,这是用来干嘛的呢。

​ 我在支持向量机SMO算法内循环的一个问题?中找到了答案,他是这么说的:

至于这里的容错率,是由于KKT条件本身是比较严苛的,所以需要设定一个容忍值,只要误差在容忍值的范围内则优化可以结束。

所以到这里我们明白了这个tol变量是容忍值,我们回过头去看书中关于函数的调用时,这个容忍值一般设为0.001。

2.第二个变量的选择

假设在外循环中找到的第一个变量记为α1,那么第二个变量的选择我希望能使α2有较大的变化。由于α2是依赖于|E1−E2|,当Ei为正时,那么选择最小的Ei作为E2 ,如果Ei为负,选择最大Ei作为E2,通常为每个样本的Ei保存在一个列表中,选择最大的|E1−E2|来近似最大化步长。

在《Machine Learning in Action》中我们可以看到关于第二变量的代码如下:

def selectJ(i, oS, Ei):         #this is the second choice -heurstic, and calcs Ej
    maxK = -1; maxDeltaE = 0; Ej = 0
    oS.eCache[i] = [1,Ei]  #set valid #choose the alpha that gives the maximum delta E
    validEcacheList = nonzero(oS.eCache[:,0].A)[0]
    if (len(validEcacheList)) > 1:
        for k in validEcacheList:   #loop through valid Ecache values and find the one that maximizes delta E
            if k == i: continue #don't calc for i, waste of time
            Ek = calcEk(oS, k)
            deltaE = abs(Ei - Ek)
            if (deltaE > maxDeltaE):
                maxK = k; maxDeltaE = deltaE; Ej = Ek
        return maxK, Ej
    else:   #in this case (first time around) we don't have any valid eCache values
        j = selectJrand(i, oS.m)
        Ej = calcEk(oS, j)
    return j, Ej

参考资料:

【机器学习详解】SMO算法剖析

SMO算法总结

机器学习入门笔记:(4.3)SMO算法

周志华《机器学习》

《Machine Learning in Action》

猜你喜欢

转载自blog.csdn.net/kabuto_hui/article/details/80474120