机器学习笔记——支持向量机SMO算法完整版代码分析

本文详细解读《机器学习实战》中的SMO算法,包括外循环和内循环的逻辑,参数类分析,KKT条件判断以及eCache参数的作用。通过对外循环的非边界与边界优化切换策略,内循环的参数优化步骤的解析,帮助理解SMO算法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

机器学习笔记——支持向量机SMO算法完整版代码分析

代码参考书籍:《机器学习实战》

\qquad 关于支持向量机的一些笔记整理可参考:机器学习笔记——支持向量机的一些整理

\qquad 在前两次阅读SMO算法时,并未搞懂代码中的一些部分是什么作用,此处对书中的代码进行一个解读,这里以《机器学习实战》当中的SMO完整版为例。

代码大体分析

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

\qquad 在进行代码前先对SMO算法进行大体的分析,要完成支持向量机对“最大间隔”的寻找及对参数的优化,那么总体可以分为两个部分:第一寻找出可以优化的点 x x x(按照前面的介绍中一般为先寻找非边界样本进行优化,然后利用边界样本进行优化);第二利用“最大步长”找到 x x x对应的优化点 y y y进行优化。 不断重复上述的循环优化,直至精度达到一定程度,或者达到最大循环次数结束迭代。

\qquad 那么就可以考虑两个循环:外循环寻找 x x x点,同时进行非边界样本优化和边界样本优化的切换,同时控制整个算法程序的循环结束判断;内循环进行参数的优化。这里只对几个有疑问的点进行笔记,文章最后给出完整的代码。

外循环

\qquad 首先进行外循环的分析,在迭代的最初,我们将所有的参数( b b b α \alpha α)都初始化定义为0,那么也就是说在最初所有的点都在边界上,所以在一开始我们之间将其视为边界情况进行优化,进行整个样本数据的遍历。在第一次样本遍历后检测是否存在非边界可优化样本,然后进行非边界情况、边界情况的切换优化。伪代码如下:

初始化参数为0
未达到最大循环次数、参数仍可进行优化
	属于非边界情况
		参数优化
	属于边界情况
		参数优化

\qquad 接着的问题是如何判断是否存在非边界情况,这里用的是numpy.nonzero方法,提取出非边界情况样本的index,然后进行遍历。

\qquad 然后是如何进行非边界和边界情况的切换,看下面的外代码, a l p h a P a i r s C h a n g e d alphaPairsChanged alphaPairsChanged用于统计是否迭代对参数进行了优化,有优化则返回1,没有优化或不满足KKT条件则返回0。这里的方法是设置了一个 e n t i r e S e t entireSet entireSet参数,同时结合是否仍能优化来进行判断,可以看到一开始是遍历整个样本集的,因为所有的参数都在边界上,当第一次遍历完成后, e n t i r e S e t entireSet entireSet变为 F a l s e False False,那么第二次循环就会遍历非边界的点,而在非边界的点无法再进行优化时( a l p h a P a i r s C h a n g e d = 0 alphaPairsChanged=0 alphaPairsChanged=0), e n t i r e S e t entireSet entireSet被转换为 T r u e True True,于是下一次循环会遍历整个样本集,而此时样本集中的非边界情况对参数已经无法优化了,那么有优化的就是边界情况。

\qquad 通过这种方式达到了非边界、边界情况优化的切换,当两者都无法进行优化同时达到最大循环次数就结束迭代。

def svmSmo(datapath,C,toler,maxIters=40):
    """
    主函数、外循环
    """
    # 统计大循环次数
    iters = 0
    # 用于切换边界、非边界情况
    entireSet = True
    # 统计在边界、非边界情况下是否进行了优化,若当前没有不再有优化则进行切换
    alphaPairsChanged =0
    # 循环结束条件:达到最大迭代次数或迭代无法提高精度(非边界、边界情况下都无法再进行优化)
    while (iters < maxIters) and ((alphaPairsChanged > 0) or (entireSet)):
        # 每次循环重新统计
        alphaPairsChanged =0
        # 最初将所有的alpha都定义为0,所以先遍历整个训练集
        if entireSet:
            for i in range(oS.m):
                alphaPairsChanged += innerL(oS,i)
            iters += 1
        else:
            # 用nonzero方法筛选出非边界情况:即alpha!=0oralpha!=C的情况
            nonBond = np.nonzero((oS.alpha.A > 0)*(oS.alpha.A < oS.C))[0]
            for i in nonBond:
                alphaPairsChanged += innerL(oS,i)
            iters += 1
        # 切换边界、非边界操作,同时结合着大循环的结束判断来理解
        # 若第一次循环,则为遍历整个数据集;第一次循环完成后则先遍历非边界情况,再遍历边界情况,所以第一次True后则将其转换为False
        if entireSet:
            entireSet = False
        # 将非边界情况的迭代结束条件设置为不再有精度提升,这时要考虑边界情况,则再次将entireSet设置为True,利用这种方法进行边界、非边界情况的切换
        elif alphaPairsChanged == 0:
            entireSet = True

参数类

\qquad 外循环当中使用了一个参数类Parameter,用于存储各种参数,在一开始并不明白 e C a c h e eCache eCache的作用,在后面的内循环中对其作用进行介绍。

class parameter:
    """
    参数定义:toler为可容忍的误差或说精度;C为惩罚因子;eCache用于存储Ei,在选择最优j的时候要用到
    """
    def __init__(self,dataMat,labelMat
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值