前言

前两篇关于SVM的文章分别总结了SVM基本原理和核函数以及软间隔原理,本文我们就针对前面推导出的SVM对偶问题的一种高效的优化方法-序列最小优化算法(Sequential Minimal Optimization, SMO)的原理进行总结并进行相应的Python实现。

坐标上升算法(Coordinate Ascent)

在SMO算法之前,还是需要总结下坐标上升算法,因为SMO算法的思想与坐标上升算法的思想类似。

坐标上升算法每次通过更新多元函数中的一维,经过多次迭代直到收敛来达到优化函数的目的。简单的讲就是不断地选中一个变量做一维最优化直到函数达到局部最优点。

假设我们需要求解的问题形式为(类似我们SVM的对偶形式):

算法过程伪码:

例子

若我们的优化目标为一个二元函数:

我们先给一个  的初值然后开始迭代。

  1. 先固定  ,把  看做  的一元函数求最优值,可以简单的进行求导获取解析解:
  2. 在固定x2x2, 把ff看成x1x1的一元函数求最优值,得到x1x1的解析解:

按照上面两个过程不断交替的优化  和  ,直到函数收敛。

通过下面的图就可以看出,优化的过程,因为每次只优化一个变量,每次迭代的方向都是沿着坐标轴方向的。

因为每次只是做一维优化,所以每个循环中的优化过程的效率是很高的, 但是迭代的次数会比较多。

序列最小优化算法(SMO)

SMO算法介绍

SMO的思想类似坐标上升算法,我们需要优化一系列的αα的值,我们每次选择尽量少的  来优化,不断迭代直到函数收敛到最优值。

来到SVM的对偶问题上,对偶形式:

subject to  , 

其中我们需要对  进行优化,但是这个凸二次优化问题的其他求解算法的复杂度很高,但是Platt提出的SMO算法可以高效的求解上述对偶问题,他把原始问题的求解  个参数二次规划问题分解成多个二次规划问题求解,每个字问题只需要求解2各参数,节省了时间成本和内存需求。

与坐标上升算法不同的是,我们在SMO算法中我们每次需要选择一对变量  , 因为在SVM中,我们的  并不是完全独立的,而是具有约束的:

因此一个  改变,另一个也要随之变化以满足条件。

SMO算法原理

获得没有修剪的原始解

假设我们选取的两个需要优化的参数为  , 剩下的  则固定,作为常数处理。将SVM优化问题进行展开就可以得到(把与  无关的项合并成常数项  ):

于是就是一个二元函数的优化:

根据约束条件  可以得到  与  的关系:

两边同时乘上  , 由于  得到:

令  ,  ,  的表达式代入得到:

后面我们需要对这个一元函数进行求极值,  对  的一阶导数为0得到:

下面我们稍微对上式进行下变形,使得  能够用更新前的  表示,而不是使用不方便计算的  。

因为SVM对数据点的预测值为: 

则  以及  的值可以表示成:

已知  , 可得到:

将  的表达式代入到  中可以得到: 

我们记  为SVM预测值与真实值的误差: 

令  得到最终的一阶导数表达式:

得到:

这样我们就得到了通过旧的  获取新的  的表达式,  便可以通过  得到。

对原始解进行修剪

上面我们通过对一元函数求极值的方式得到的最优  是未考虑约束条件下的最优解,我们便更正我们上部分得到的  为 , 即:

但是在SVM中我们的  是有约束的,即:

此约束为方形约束(Bosk constraint), 在二维平面中我们可以看到这是个限制在方形区域中的直线(见下图)。

(如左图) 当  时,线性限制条件可以写成:  ,根据  的正负可以得到不同的上下界,因此统一表示成:

  • 下界: 
  • 上界: 

(如右图) 当  时,限制条件可写成:  , 上下界表示成:

  • 下界: 
  • 上界: 

根据得到的上下界,我们可以得到修剪后的  :

得到了  我们便可以根据  得到  :

OK, 这样我们就知道如何将选取的一对  进行优化更新了。

更新阈值b

当我们更新了一对  之后都需要重新计算阈值  ,因为  关系到我们  的计算,关系到下次优化的时候误差  的计算。

为了使得被优化的样本都满足KKT条件,

当  不在边界,即  , 根据KKT条件可知相应的数据点为支持向量,满足  , 两边同时乘上  得到  , 进而得到  的值:

其中上式的前两项可以写成:

当  , 可以得到bnew2b2new的表达式(推导同上):

当  和  都有效的时候他们是相等的, 即  。

当两个乘子  都在边界上,且  时,  之间的值就是和KKT条件一直的阈值。SMO选择他们的中点作为新的阈值:

简化版SMO算法实现

这里我主要针对SMO中已选取的一对  值的优化过程进行下Python实现,其中  的选取直接使用傻瓜的遍历方式,并使用100数据点进行训练。

首先是一些辅助函数,用来帮助加载数据,修剪  的值以及随机选取 

def load_data(filename):dataset, labels = [], []with open(filename, 'r') as f:for line in f:x, y, label = [float(i) for i in line.strip().split()]dataset.append([x, y])labels.append(label)return dataset, labels
def clip(alpha, L, H):''' 修建alpha的值到L和H之间.'''if alpha < L:return Lelif alpha > H:return Helse:return alpha
def select_j(i, m):''' 在m中随机选择除了i之外剩余的数'''l = list(range(m))seq = l[: i] + l[i+1:]return random.choice(seq)

为了能在最后绘制SVM分割线,我们需要根据获取的  ,数据点以及标签来获取  的值:

def get_w(alphas, dataset, labels):''' 通过已知数据点和拉格朗日乘子获得分割超平面参数w'''alphas, dataset, labels = np.array(alphas), np.array(dataset), np.array(labels)yx = labels.reshape(1, -1).T*np.array([1, 1])*datasetw = np.dot(yx.T, alphas)return w.tolist()

简化版SMO算法的实现,即便没有添加启发式的  选取,SMO算法仍然有比较多的公式需要实现,我本人按照上文的推导进行实现的时候就因为写错了一个下标算法一直跑不出想要的结果。

此实现主要包含两重循环,外层循环是控制最大迭代步数,此迭代步数是在每次有优化一对αα之后进行判断所选取的  是否已被优化,如果没有则进行加一,如果连续max_iter步数之后仍然没有  被优化,则我们就认为所有的  基本已经被优化,优化便可以终止了.

def simple_smo(dataset, labels, C, max_iter):''' 简化版SMO算法实现,未使用启发式方法对alpha对进行选择.:param dataset: 所有特征数据向量:param labels: 所有的数据标签:param C: 软间隔常数, 0 <= alpha_i <= C:param max_iter: 外层循环最大迭代次数'''dataset = np.array(dataset)m, n = dataset.shapelabels = np.array(labels)# 初始化参数alphas = np.zeros(m)b = 0it = 0def f(x):"SVM分类器函数 y = w^Tx + b"# Kernel function vector.x = np.matrix(x).Tdata = np.matrix(dataset)ks = data*x# Predictive value.wx = np.matrix(alphas*labels)*ksfx = wx + breturn fx[0, 0]while it < max_iter:pair_changed = 0for i in range(m):a_i, x_i, y_i = alphas[i], dataset[i], labels[i]fx_i = f(x_i)E_i = fx_i - y_ij = select_j(i, m)a_j, x_j, y_j = alphas[j], dataset[j], labels[j]fx_j = f(x_j)E_j = fx_j - y_jK_ii, K_jj, K_ij = np.dot(x_i, x_i), np.dot(x_j, x_j), np.dot(x_i, x_j)eta = K_ii + K_jj - 2*K_ijif eta <= 0:print('WARNING  eta <= 0')continue# 获取更新的alpha对a_i_old, a_j_old = a_i, a_ja_j_new = a_j_old + y_j*(E_i - E_j)/eta# 对alpha进行修剪if y_i != y_j:L = max(0, a_j_old - a_i_old)H = min(C, C + a_j_old - a_i_old)else:L = max(0, a_i_old + a_j_old - C)H = min(C, a_j_old + a_i_old)a_j_new = clip(a_j_new, L, H)a_i_new = a_i_old + y_i*y_j*(a_j_old - a_j_new)if abs(a_j_new - a_j_old) < 0.00001:#print('WARNING   alpha_j not moving enough')continuealphas[i], alphas[j] = a_i_new, a_j_new# 更新阈值bb_i = -E_i - y_i*K_ii*(a_i_new - a_i_old) - y_j*K_ij*(a_j_new - a_j_old) + bb_j = -E_j - y_i*K_ij*(a_i_new - a_i_old) - y_j*K_jj*(a_j_new - a_j_old) + bif 0 < a_i_new < C:b = b_ielif 0 < a_j_new < C:b = b_jelse:b = (b_i + b_j)/2pair_changed += 1print('INFO   iteration:{}  i:{}  pair_changed:{}'.format(it, i, pair_changed))if pair_changed == 0:it += 1else:it = 0print('iteration number: {}'.format(it))return alphas, b

Ok, 下面我们就用训练数据对SVM进行优化, 并对最后优化的分割线以及数据点进行可视化

if '__main__' == __name__:# 加载训练数据dataset, labels = load_data('testSet.txt')# 使用简化版SMO算法优化SVMalphas, b = simple_smo(dataset, labels, 0.6, 40)# 分类数据点classified_pts = {'+1': [], '-1': []}for point, label in zip(dataset, labels):if label == 1.0:classified_pts['+1'].append(point)else:classified_pts['-1'].append(point)fig = plt.figure()ax = fig.add_subplot(111)# 绘制数据点for label, pts in classified_pts.items():pts = np.array(pts)ax.scatter(pts[:, 0], pts[:, 1], label=label)# 绘制分割线w = get_w(alphas, dataset, labels)x1, _ = max(dataset, key=lambda x: x[0])x2, _ = min(dataset, key=lambda x: x[0])a1, a2 = wy1, y2 = (-b - a1*x1)/a2, (-b - a1*x2)/a2ax.plot([x1, x2], [y1, y2])# 绘制支持向量for i, alpha in enumerate(alphas):if abs(alpha) > 1e-3:x, y = dataset[i]ax.scatter([x], [y], s=150, c='none', alpha=0.7,linewidth=1.5, edgecolor='#AB3319')plt.show()

优化最后我们可以看到针对100个数据的  只有少部分是大于零的,即对应的数据点就是支持向量:

为了能直观的显示支持向量,我将其标注了出来,最终可视化的效果如下图:

总结

本文从坐标上升算法开始介绍,并对SMO算法的原理进行了简单的推导,针对SMO算法中对αα对的优化并使用了Python进行了简化版的SMO实现,并针对小数据集进行了训练得到了对应优化后的SVM。

实现代码以及训练数据链接: https://github.com/PytLab/MLBox/tree/master/svm

原文链接:https://zhuanlan.zhihu.com/p/29212107

机器学习算法实践-SVM中的SMO算法相关推荐

  1. 【机器学习系列】之SVM核函数和SMO算法

    作者:張張張張 github地址:https://github.com/zhanghekai [转载请注明出处,谢谢!] [机器学习系列]之SVM硬间隔和软间隔 [机器学习系列]之SVM核函数和SMO ...

  2. 【机器学习】解释对偶的概念及SVM中的对偶算法?(面试回答)

    对偶的概念? (1)概念 对偶一般来说是以一对一的方式,常常通过某个对合算子,把一种概念.公理或数学结构转化为另一种概念.公理或数学结构:如果A的对偶是B,那么B的对偶是A.在强对偶性成立的情况下由对 ...

  3. svd降维 python案例_菜菜的机器学习sklearn实战-----sklearn中的降维算法PCA和SVD

    菜菜的机器学习sklearn实战-----sklearn中的降维算法PCA和SVD 概述 从什么叫维度说开来 简单讲,shape中返回了几个数字就是几维. 一张表最多就是一维 当一个数组中存在2张3行 ...

  4. 机器学习:SVM训练,SMO算法描述,启发式选择样本或变量

    文章目录 优化目标: 优化步骤: 对偶问题本质: 选择第一个样本点标准: 选择第一个样本点标准为:最不满足KKT条件的样本 如何判断样本点是否满足KKT条件? 满足和不满足KKT的情况: 量化不满足K ...

  5. python svm核函数_机器学习算法实践-SVM核函数和软间隔

    前言 上文中简单总结了对于线性可分数据的SVM的算法原理,本文对于非线性可分以及有噪声存在的时候我们需要对基本SVM算法的改进进行下总结其中包括: 核函数在SVM算法中的使用 引入松弛变量和惩罚函数的 ...

  6. 模型算法_详解SVM模型之SMO算法

    今天是机器学习专题第35篇文章,我们继续SVM模型的原理,今天我们来讲解的是SMO算法. 公式回顾 在之前的文章当中我们对硬间隔以及软间隔问题都进行了分析和公式推导,我们发现软间隔和硬间隔的形式非常接 ...

  7. 详解SVM支持向量机算法(四:坐标上升和SMO算法)

    作者:RayChiu_Labloy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 目录 背景 坐标上升算法 定义 过程 举个求解的栗子 基于坐标上升的SMO算法 SMO ...

  8. SVM笔记之SMO算法

    目录 SMO序列最小最优化算法 变量更新 更新变量的选取 bbb和误差EiE_iEi​的计算 SMO序列最小最优化算法 SMO算法实际上用于SVM对偶问题求解中α∗\boldsymbol{\alpha ...

  9. SVM——详细讲解SMO算法优化两个变量以及变量的选择

    一.SMO(序列最小最优化)优化两个变量 以非线性支持向量机的对偶问题为例,使用SMO算法求解该对偶问题的最优参数α* . 非线性支持向量机的对偶问题如下: 对偶问题转换:(如何转换请看这篇博客) 存 ...

最新文章

  1. aes js 加盐值 解密_crypto-js aes加密解密
  2. 深入理解 CAP 定理
  3. 关于微信公众平台表情代码的记录
  4. python中char的用法_如何从C++返回char **并使用cType在Python中填充它?
  5. iphone:MKMapView
  6. js 正则表达式总结
  7. 百度seo排名点击器app_手机端百度搜索排名seo优化_百度移动端整站关键词排名优化...
  8. Word vba之遍历段落、识别固定段头、设置样式
  9. 仿淘宝网站基于html网页模板设计静态网页模板参考.rar(项目源码)
  10. OneNote 提示不能使用个人账户登录( 亲测可用)
  11. protel99se进阶视频教程(手把手教你画51单片机开发板)
  12. 网页视频之ACC格式解析
  13. 手机百度浏览器怎么设置繁体字_繁体字转换简体字在线转换_有什么软件可以把繁...
  14. java特别描述错误的是,关于javac命令作用的描述错误的是
  15. cocos2dx_lua读取unity手机游戏本地文件
  16. 中级会计 科学计算机,听说中级会计机考系统计算器你还不会使用?还不快点关注...
  17. 运放基本结构及频响(一)
  18. 单片机音乐播放器课程设计C语言,单片机课程设计简易音乐播放器
  19. win系统压缩/解压.tar.gz 文件的方法
  20. 2018年第20周(2018-5-18)周末总结

热门文章

  1. Linux中netstat -anp命令
  2. 低功耗、高性能智能开发主板MED3568
  3. SCA可达性分析基础知识普及
  4. 计算机中存在旧版本的mf驱动程序,mf驱动程序安装指南.pdf
  5. python使用pandas打不开excel文件
  6. hbuilderx 使用总结
  7. 计算适合打印的图纸大小
  8. 北大青鸟 JQuery 制作特效 第一章 课后简答题
  9. 华为5500网络限流配置_华为Eudemon 防火墙BT限流测试方案
  10. 从懵懂娃娃到社会行业大佬,这中间经历的过程的概括性思考