《机器学习实战》简化版SMO代码中2个判断条件的思考

《机器学习实战》简化版SMO代码中2个判断条件的思考

最近在看《机器学习实战》,程序清单6-2,代码很长,但是代码解释里面作者有一些细节没有讲解到,通过学习SMO公式推导和看了一些博客,弄明白有2处判断条件,当作记录以后备查,也分享给大家,欢迎讨论交流。

准备工作

公式推导

首先当然是公式推导了,这是必备的,应该先看完公式推导再来编程,不然完全看不懂书里的代码在做什么。这里我查了周志华的《机器学习》、bishop的《Pattern Recognition and Machine Learning》、《Pattern Classification》、《Pattern Recognition》竟然都没有相关的详细推导过程。最后找到了李航的《统计学习方法》的7.4节有SMO非常详尽的从头到尾的推导,和《机器学习实战》书中代码是完全对应的,这里强烈推荐,本文的公式符号包括公式的标号也是按李航的书中书写。当然,想要深一步理解的同学,可以直接去看 platt的论文。《Learning with Kernels》里面也有推导,但是前后章节联系太密,要看懂这本书里面的推导,要前面很多小节都有看过,所以不是很建议。
这里有一篇博客也有详尽的推导过程,和李航的书是一模一样的,估计是书的扫描,不过好像也不是很全

https://blog.csdn.net/lyl771857509/article/details/79433184

代码

这里直接给出原书代码的github地址

https://github.com/pbharrin/machinelearninginaction/tree/master/Ch06

2个判断条件

好了,这里开始进入正题
2个判断条件主要出现在这个代码块中

while (iter < maxIter):
    alphaPairsChanged = 0
    for i in range(m):
        fXi = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T)) + b
        Ei = fXi - float(labelMat[i])#if checks if an example violates KKT conditions
        if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):
            j = selectJrand(i,m)
            fXj = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + b
            Ej = fXj - float(labelMat[j])
            alphaIold = alphas[i].copy(); alphaJold = alphas[j].copy();
            if (labelMat[i] != labelMat[j]):
                L = max(0, alphas[j] - alphas[i])
                H = min(C, C + alphas[j] - alphas[i])
            else:
                L = max(0, alphas[j] + alphas[i] - C)
                H = min(C, alphas[j] + alphas[i])
            if L==H: print "L==H"; continue
            eta = 2.0 * dataMatrix[i,:]*dataMatrix[j,:].T - dataMatrix[i,:]*dataMatrix[i,:].T - dataMatrix[j,:]*dataMatrix[j,:].T
            if eta >= 0: print "eta>=0"; continue
            alphas[j] -= labelMat[j]*(Ei - Ej)/eta
            alphas[j] = clipAlpha(alphas[j],H,L)
            if (abs(alphas[j] - alphaJold) < 0.00001): print "j not moving enough"; continue
            alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])#update i by the same amount as j
                                                                    #the update is in the oppostie direction
            b1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[i,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i,:]*dataMatrix[j,:].T
            b2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[j,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j,:]*dataMatrix[j,:].T
            if (0 < alphas[i]) and (C > alphas[i]): b = b1
            elif (0 < alphas[j]) and (C > alphas[j]): b = b2
            else: b = (b1 + b2)/2.0
            alphaPairsChanged += 1
            print "iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged)

第一个判断条件

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

这个判断条件按原书上写是为了

如果 α \alpha α可以更新进入优化进程

这里主要看 E i E_i Ei的公式, E i = g ( x i ) – y i E_i = g(x_i) – y_i Ei=g(xi)yi。外循环是要找违背KKT条件最严重的样本点(每个样本点对应一个 α \alpha α)。而在这里主要看的KKT条件是 0 &lt; α i &lt; C ⟺ y i g ( x i ) = 1 ( 7.112 ) 0&lt;\alpha_i&lt;C \Longleftrightarrow y_ig(x_i) = 1 \quad (7.112) 0<αi<Cyig(xi)=1(7.112)
这里判断 α \alpha α可以更改进入优化过程的条件写成数学式子是

  • y i E i &lt; − t o l e r y_iE_i &lt; -toler yiEi<toler α i &lt; C \alpha_i&lt;C αi<C 】或【 y i ∗ E i &gt; t o l e r y_i*E_i&gt;toler yiEi>toler α i &gt; C \alpha_i&gt;C αi>C

条件中

y i ∗ E i = y i ∗ ( g ( x i ) – y i ) = y i ∗ g ( x i ) – y i 2 y_i*E_i = y_i*( g(x_i) – y_i) = y_i* g(x_i) – y_i^2 yiEi=yi(g(xi)yi)=yig(xi)yi2

由于 y i = ± 1 y_i=\pm1 yi=±1,有
y i 2 = 1 y_i^2 =1 yi2=1

最后,我们将代码中的原条件化简成

  • y i ∗ g ( x i ) &lt; 1 − t o l e r y_i*g(x_i) &lt; 1-toler yig(xi)<1toler α i &lt; C \alpha_i&lt;C αi<C】 或【 y i ∗ g ( x i ) &gt; 1 + t o l e r y_i*g(x_i)&gt;1+toler yig(xi)>1+toler α i &gt; C \alpha_i&gt;C αi>C

此时重新对比我们所说的的KKT条件

0 &lt; a l p h a [ i ] &lt; C ⟺ y i ∗ g ( x i ) = 1 0&lt;alpha[i]&lt;C \Longleftrightarrow yi*g(xi) = 1 0<alpha[i]<Cyig(xi)=1

我们要找的就是违背这个条件的 α \alpha α与此同时判断这个 α \alpha α值不值得更新


可以看出原条件中“或”字前方的方框是属于"小于违背"的情况,后面的方括号是属于"大于违背"的情况。在前面的方括号里我们之所以只需要限定 α i &lt; C \alpha_i &lt;C αi<C的条件,而不需要它大于0,是因为我们同时在判断这个alpha值不值得更新

所谓更新就是要从违背KKT条件的状态更新到不违背KKT的状态。

对于“小于违背”的情况下,由于 g ( x i ) = ∑ j = 1 N α j y j K ( x i , x j ) + b g(x_i) =\sum_{j=1}^N\alpha_jy_jK(x_i,x_j)+b g(xi)=j=1NαjyjK(xi,xj)+b
也就是, α i \alpha_i αi越大 g ( x i ) g(x_i) g(xi)越大。在这里我们要更新到不违背KKT的状态,就是需要g(xi)越大。所以判断这个 α \alpha α值不值得更新我们只需要判断 α \alpha α是否足够小,有继续增大的空间,但是又不能增大到等于C。故有 α i &lt; C \alpha_i&lt;C αi<C。而不需要判断 α i \alpha_i αi是否大于0。(其实 α i \alpha_i αi应该肯定会大于等于0,由于 α \boldsymbol\alpha α初始化时为全0向量,而后面又有L、H这个机制来保证 α i \alpha_i αi的范围)

第二个判断条件

if eta >= 0: print "eta>=0"; continue

这个判断条件按原书上写

如果eta为0,那么计算新的alpha[j]就比较麻烦了,这里我们就不对此进行详细的介绍

判断 e t a &gt; = 0 eta&gt;=0 eta>=0,个人感觉其实只需要判断 e t a = 0 eta = 0 eta=0就可以了,因为eta是一个完全平方式 (7.107) η = K 11 + K 22 − 2 K 12 = ∥ Φ ( x 1 ) − Φ ( x 2 ) ∥ 2 \eta = K_{11}+K_{22}-2K_{12} =\left \| \Phi(x_1)-\Phi(x_2) \right \|^2 \tag{7.107} η=K11+K222K12=Φ(x1)Φ(x2)2(7.107)
此处数学式子中的 η \eta η为李航书中的式子与代码的eta正好是相反数。
判断eta等于0跳出循环的原因是,在后面更新 α \alpha α的时候,有公式
α 2 n e w , u n c = α 2 o l d + y 2 ( E 1 − E 2 ) η \alpha_2^{new,unc}=\alpha_2^{old}+\frac{y_2(E_1-E_2)}{\eta} α2new,unc=α2old+ηy2(E1E2)
eta作为分母,不能等于0。

最后,感谢这篇博客https://blog.csdn.net/lyl771857509/article/details/79433184,第一个判断条件主要是看这篇博客的注释得到的启发,另外这是博主的第一篇正式博客,由于博主水平所限,文章中难免有错误和不当之处,欢迎读者给予批评指正,也欢迎大家在评论区讨论提问题

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值