机器学习算法实践-Platt SMO和遗传算法优化SVM

技术

專 欄

picture.image

PytLab,Python 中文社区专栏作者。主要从事科学计算与高性能计算领域的应用,主要语言为Python,C,C++。熟悉数值算法(最优化方法,蒙特卡洛算法等)与并行化 算法(MPI,OpenMP等多线程以及多进程并行化)以及python优化方法,经常使用C++给python写扩展。
知乎专栏:化学狗码砖的日常blog:http://pytlab.org

github:https://github.com/PytLab

前言

之前实现了简单的SMO算法来优化SVM的对偶问题,其中在选取 picture.image 的时候使用的是两重循环通过完全随机的方式选取,具体的实现参考《机器学习算法实践-SVM中的SMO算法》。

本文在之前简化版SMO算法的基础上实现了使用启发式选取 picture.image 对的方式的Platt SMO算法来优化SVM。另外由于最近自己也实现了一个遗传算法框架GAFT,便也尝试使用遗传算法对于SVM的原始形式进行了优化。

对于本文算法的相应实现,参考: https://github.com/PytLab/MLBox/tree/master/svm

遗传算法框架GAFT项目地址:https://github.com/PytLab/gaft

正文
SMO中启发式选择变量

在SMO算法中,我们每次需要选取一对 picture.image 来进行优化,通过启发式的选取我们可以更高效的选取待优化的变量使得目标函数下降的最快。

针对第一个 picture.image 和第二个 picture.image Platt SMO采取不同的启发式手段。

第一个变量的选择

第一个变量的选择为外循环,与之前便利整个 picture.image 列表不同,在这里我们在整个样本集和非边界样本集间进行交替:

1、首先我们对整个训练集进行遍历, 检查是否违反KKT条件,如果改点的 picture.imagepicture.image , picture.image 违反了KKT条件则说明改点需要进行优化。
Karush-Kuhn-Tucker(KKT)条件是正定二次规划问题最优点的充分必要条件。针对SVM对偶问题,KKT条件非常简单:

picture.image

2、在遍历了整个训练集并优化了相应的αα后第二轮迭代我们仅仅需要遍历其中的非边界αα. 所谓的非边界 picture.image 就是指那些不等于边界0或者C的 picture.image 值。 同样这些点仍然需要检查是否违反KKT条件并进行优化.

之后就是不断地在两个数据集中来回交替,最终所有的 picture.image 都满足KKT条件的时候,算法中止。

为了能够快速选取有最大步长的 picture.image ,我们需要对所有数据对应的误差进行缓存,因此特地写了个SVMUtil类来保存svm中重要的变量以及一些辅助方法:

picture.image

下面为第一个变量选择交替遍历的大致代码,相应完整的Python实现(完整实现见 https://github.com/PytLab/MLBox/blob/master/svm/svm\_platt\_smo.py ):

picture.image

第二个变量的选择

SMO中的第二个变量的选择过程为内循环,当我们已经选取第一个 picture.image 之后,我们希望我们选取的第二个变量 picture.image 优化后能有较大的变化。根据我们之前推导的式子

picture.image

可以知道,新的 picture.image 的变化依赖于 picture.image , 当 picture.image 为正时, 那么选择最小的 picture.image 作为 picture.image ,通常将每个样本的 picture.image 缓存到一个列表中,通过在列表中选择具有 picture.image 来近似最大化步长。

有时候按照上述的启发式方式仍不能够是的函数值有足够的下降,这是按下述步骤进行选择:

在非边界数据集上选择能够使函数值足够下降的样本作为第二个变量
如果非边界数据集上没有,则在整个数据仅上进行第二个变量的选择
如果仍然没有则重新选择第一个 picture.image

第二个变量选取的Python实现:

picture.image

KKT条件允许一定的误差

在Platt论文中的KKT条件的判断中有一个tolerance允许一定的误差,相应的Python实现:

picture.image

关于Platt SMO的完整实现详见: https://github.com/PytLab/MLBox/blob/master/svm/svm\_platt\_smo.py

针对之前的数据集我们使用Platt SMO进行优化可以得到:

picture.image

将分割线和支持向量可视化:

picture.image

可见通过Platt SMO优化出来的支持向量与简化版的SMO算法有些许不同。

使用遗传算法优化SVM

由于最近自己写了个遗传算法框架,遗传算法作为一个启发式无导型的搜索算法非常易用,于是我就尝试使用遗传算法来优化SVM。

使用遗传算法优化,我们就可以直接优化SVM的最初形式了也就是最直观的形式:

picture.image

顺便再安利下自己的遗传算法框架,在此框架的帮助下,优化SVM算法我们只需要写几十行的Python代码即可。其中最主要的就是编写适应度函数,根据上面的公式我们需要计算数据集中每个点到分割线的距离并返回最小的距离即可,然后放到遗传算法中进行进化迭代。

遗传算法框架GAFT项目地址: https://github.com/PytLab/gaft , 使用方法详见README。

Ok, 我们开始构建种群用于进化迭代。

创建个体与种群

对于二维数据点,我们需要优化的参数只有三个也就是 picture.image 和 b , 个体的定义如下:

picture.image

种群大小这里取600,创建种群

picture.image

创建遗传算子和GA引擎

这里没有什么特别的,直接使用框架中内置的算子就好了。

picture.image

适应度函数

这一部分只要把上面svm初始形式描述出来就好了,只需要三行代码:

picture.image

开始迭代

这里迭代300代种群

picture.image

绘制遗传算法优化的分割线

picture.image

得到的分割曲线如下图:

完整的代码详见: https://github.com/PytLab/MLBox/blob/master/svm/svm\_ga.py

总结

本文对SVM的优化进行了介绍,主要实现了Platt SMO算法优化SVM模型,并尝试使用遗传算法框架GAFT对初始SVM进行了优化。

参考

picture.image


picture.image

长按扫描关注Python中文社区,

获取更多技术干货!

Python 中 文 社 区

Python中文开发者的精神家园

合作、投稿请联系微信:

pythonpost

— 人生苦短,我用Python —
1MEwnaxmMz7BPTYzBdj751DPyHWikNoeFS

本文为作者原创作品,未经作者授权同意禁止转载

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
高性能存储虚拟化方案 NVMe over Fabric 在火山引擎的演进
在云计算中,虚拟化存储扮演着重要角色,其中 iSCSI 协议在业界开放、流行多年。近年来,拥有更优性能的 NVMe over Fabrics 协议也得到了发展。本次分享介绍了 NVMe over Fabrics 在云原生和虚拟化方向的演进工作和成果。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论