机器学习实战 支持向量机SVM 代码解析

《机器学习实战》用代码实现了算法,理解源代码更有助于我们掌握算法,但是比较适合有一定基础的小伙伴。svm这章代码看起来风轻云淡,实则对于新手来说有(shi)点(fen)晦涩,必须先搞清楚svm原理和具体推导优化步骤。这里推荐一个知乎的回答,支持向量机 SVM(非常详细)。这篇文章只推到了优化目标公式,最后的优化过程用的是序列最小最优化(SMO)算法。具体过程参见SMO算法详解

下面是github 上写了注释的代码svm支持向量机

smoSimple(dataMatIn, classLabels, C, toler, maxIter):
"""smoSimple
Args:dataMatIn    特征集合classLabels  类别标签C   松弛变量(常量值),允许有些数据点可以处于分隔面的错误一侧。控制最大化间隔和保证大部分的函数间隔小于1.0这两个目标的权重。可以通过调节该参数达到不同的结果。toler   容错率(是指在某个体系中能减小一些因素或选择对某个系统产生不稳定的概率。)maxIter 退出前最大的循环次数
Returns:b       模型的常量值alphas  拉格朗日乘子
"""
dataMatrix = mat(dataMatIn)
# 矩阵转置 和 .T 一样的功能
labelMat = mat(classLabels).transpose()
m, n = shape(dataMatrix)# 初始化 b和alphas(alpha有点类似权重值。)
b = 0
alphas = mat(zeros((m, 1)))# 没有任何alpha改变的情况下遍历数据的次数
iter = 0
while (iter < maxIter):# w = calcWs(alphas, dataMatIn, classLabels)# print("w:", w)# 记录alpha是否已经进行优化,每次循环时设为0,然后再对整个集合顺序遍历alphaPairsChanged = 0for i in range(m):# print 'alphas=', alphas# print 'labelMat=', labelMat# print 'multiply(alphas, labelMat)=', multiply(alphas, labelMat)# 我们预测的类别 y[i] = w^Tx[i]+b; 其中因为 w = Σ(1~n) a[n]*label[n]*x[n]fXi = float(multiply(alphas, labelMat).T*(dataMatrix*dataMatrix[i, :].T)) + b# 预测结果与真实结果比对,计算误差EiEi = fXi - float(labelMat[i])# 约束条件 (KKT条件是解决最优化问题的时用到的一种方法。我们这里提到的最优化问题通常是指对于给定的某一函数,求其在指定作用域上的全局最小值)# 0<=alphas[i]<=C,但由于0和C是边界值,我们无法进行优化,因为需要增加一个alphas和降低一个alphas。# 表示发生错误的概率:labelMat[i]*Ei 如果超出了 toler, 才需要优化。至于正负号,我们考虑绝对值就对了。'''# 检验训练样本(xi, yi)是否满足KKT条件yi*f(i) >= 1 and alpha = 0 (outside the boundary)yi*f(i) == 1 and 0<alpha< C (on the boundary)yi*f(i) <= 1 and alpha = C (between the boundary)'''if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):

对于条件((labelMat[i]*Ei < -toler) and (alphas[i] < C)):
αi<C,即对于边界上或边界外的点,
当yi=1时,labelMat[i]*Ei=yi(wxi+b-yi)=f(i)-1<-toler,f(i)<1-toler;当yi=-1时,f(i)>-1+toler
也就是边界以外的点xi经过wxi+b分类后得到的结果超出了设置的容错率,即分类错误,需要继续优化
同理,对于条件((labelMat[i]*Ei > toler) and (alphas[i] > 0)):
当yi=1时,labelMat[i]*Ei=yi(f(i)-yi)=f(i)-1>toler,即f(i)>toler+1;当yi=-1时,f(i)<-1-toler,说明样本i是边界外的点。那么αi,也就是样本i对优化目标限制条件的贡献应该为零,而条件alphas[i]>0却使样本i对限制条件的贡献大于零,说明αi是不对的,需要继续优化。

插播一条对αi的理解:SVM就是一个不等式约束的优化问题,约束条件就是每个正样本到分类面(超平面)的(带符号的)距离大于+1/ω,每个负样本到超平面的距离小于-1/ω,优化目标就是1/ω。通俗来说就是把每个样本都分类正确的情况下,要使正样本和负样本到超平面的距离最大,距离越大就越安全。要想把所有样本都分类正确其实不需要把所有样本到超平面的距离都求出来然后让他们大于1/ω,只需要让那些离超平面最近的点(也就是支持向量)到超平面的距离大于1/ω就行了。也就是说边界以外的样本对超平面的优化是没有约束的。
回到我们构造的Lagrange函数:
         L(x,α)=f(x)+∑αihi(x)
其中αi是样本i对优化目标f(x)约束的权重,边界外的点对超平面没有约束,所以αi等于零。对于下图中的坏点,αi就代表无法正确分类的样本对目标函数的惩罚,应该取一个较大的值,假如我们设定它为C。而对于刚好位于边界上的点(支持向量),他们的权重应该大于零而小于C。这其实就是所谓的KKT条件了。
我们看到αi对样本i的各个维度的值其实是没有调节作用的,它是通过调整每个支持向量在限制条件中的权重,而每个支持向量的不同维度特征值又是不同的,从而影响了ω在各个维度的值,最终影响超平面。

另外画了张图来帮助理解

            # 如果满足优化的条件,我们就随机选取非i的一个点,进行优化比较j = selectJrand(i, m)# 预测j的结果fXj = float(multiply(alphas, labelMat).T*(dataMatrix*dataMatrix[j, :].T)) + bEj = fXj - float(labelMat[j])alphaIold = alphas[i].copy()alphaJold = alphas[j].copy()# L和H用于将alphas[j]调整到0-C之间。如果L==H,就不做任何改变,直接执行continue语句# labelMat[i] != labelMat[j] 表示异侧,就相减,否则是同侧,就相加。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是alphas[j]的最优修改量,如果eta==0,需要退出for循环的当前迭代过程# 参考《统计学习方法》李航-P125~P128<序列最小最优化算法>eta = 2.0 * dataMatrix[i, :]*dataMatrix[j, :].T - dataMatrix[i, :]*dataMatrix[i, :].T - dataMatrix[j, :]*dataMatrix[j, :].Tif eta >= 0:print("eta>=0")continue# 计算出一个新的alphas[j]值alphas[j] -= labelMat[j]*(Ei - Ej)/eta# 并使用辅助函数,以及L和H对其进行调整alphas[j] = clipAlpha(alphas[j], H, L)# 检查alpha[j]是否只是轻微的改变,如果是的话,就退出for循环。if (abs(alphas[j] - alphaJold) < 0.00001):print("j not moving enough")continue# 然后alphas[i]和alphas[j]同样进行改变,虽然改变的大小一样,但是改变的方向正好相反alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])# 在对alpha[i], alpha[j] 进行优化之后,给这两个alpha值设置一个常数b。# w= Σ[1~n] ai*yi*xi => b = yj- Σ[1~n] ai*yi(xi*xj)# 所以:  b1 - b = (y1-y) - Σ[1~n] yi*(a1-a)*(xi*x1)# 为什么减2遍? 因为是 减去Σ[1~n],正好2个变量i和j,所以减2遍b1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i, :]*dataMatrix[i, :].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i, :]*dataMatrix[j, :].Tb2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i, :]*dataMatrix[j, :].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j, :]*dataMatrix[j, :].Tif (0 < alphas[i]) and (C > alphas[i]):b = b1elif (0 < alphas[j]) and (C > alphas[j]):b = b2else:b = (b1 + b2)/2.0

这里b的更新注释讲得比较简略,也没有说明后面的if条件是怎么来的。b的更新需要使得优化后的α满足KKT条件,更详尽的推导可以参考知乎b值更新公式推导

            alphaPairsChanged += 1print("iter: %d i:%d, pairs changed %d" % (iter, i, alphaPairsChanged))# 在for循环外,检查alpha值是否做了更新,如果更新则将iter设为0后继续运行程序# 直到更新完毕后,iter次循环无变化,才退出循环。if (alphaPairsChanged == 0):iter += 1

什么情况下alphaPairsChanged 会等于零呢:
遍历所有样本,每个样本都满足以下条件之一
1. 满足KKT条件
2. 满足第一个continue条件,L=H。新的α取值范围上限等于下限,无法优化
3. 满足第二个continue条件,eata=0。最佳优化值为零
当所有样本要么满足KKT条件,不满足KKT条件的点也没有了优化的空间,自然可以进行下一次循环了。

    else:iter = 0print("iteration number: %d" % iter)
return b, alphas

看完这个之后应该对SVM有了比较全面的了解了,推荐再去看一下吴恩达老师对SVM的讲解,吴恩达机器学习。虽然讲的是一个东西,但是用的是完全不同的思路。首先借助逻辑回归的代价函数构造了一个满足SVM模型的代价函数,然后就直接求代价函数最小值就好了。是不是很神奇,其实是跟拉格朗日乘子法殊途同归了。优化目标和约束条件都是一样的,Andrew还以向量内积的角度解释了svm最后为什么会找到最大间隔的超平面,妙啊。
  看看不同的思路,融会贯通,不禁感叹前辈们都太聪明了吧!

机器学习实战 支持向量机SVM 代码解析相关推荐

  1. 基于pyhton3.6-机器学习实战-支持向量机SVM代码解释

    本人是一名数学系研究生,于2017年底第一次接触python和机器学习,作为一名新手,欢迎与大家交流. 我主要给大家讲解代码,理论部分给大家推荐3本书: <机器学习实战中文版> <机 ...

  2. 【机器学习】支持向量机(SVM)代码练习

    本课程是中国大学慕课<机器学习>的"支持向量机"章节的课后代码. 课程地址: https://www.icourse163.org/course/WZU-1464096 ...

  3. 转载-机器学习实战之SVM

    出处:https://www.cnblogs.com/zy230530/p/6901277.html 机器学习实战之SVM 一引言: 支持向量机这部分确实很多,想要真正的去理解它,不仅仅知道理论,还要 ...

  4. apriori算法代码_资源 | 《机器学习实战》及代码(基于Python3)

    〇.<机器学习实战> 今天推荐给大家的是<机器学习实战>这本书. 机器学习作为人工智能研究领域中一个极其重要的研究方向(一文章看懂人工智能.机器学习和深度学习),在当下极其热门 ...

  5. 《机器学习实战》配套代码下载

    <机器学习实战>配套代码资源下载网址:http://www.ituring.com.cn/book/1021(图灵社区),网址里有随书下载,可以下载配套资源.

  6. 机器学习实战——决策树(代码)

    最近在学习Peter Harrington的<机器学习实战>,代码与书中的略有不同,但可以顺利运行. from math import log import operator# 计算熵 d ...

  7. 机器学习实战之SVM

    一引言: 支持向量机这部分确实很多,想要真正的去理解它,不仅仅知道理论,还要进行相关的代码编写和测试,二者想和结合,才能更好的帮助我们理解SVM这一非常优秀的分类算法 支持向量机是一种二类分类算法,假 ...

  8. 机器学习之支持向量机SVM之python实现ROC曲线绘制(二分类和多分类)

    目录 一.ROC曲线 二.TP.FP.TN.FN 三. python绘制ROC曲线(二分类) 1.思路 2.关键代码 3.完整代码 四. python绘制ROC曲线(多分类) 五.参考文献 一.ROC ...

  9. MATLAB支持向量机SVM代码实现

    本栏目(Machine learning)包括单参数的线性回归.多参数的线性回归.Octave Tutorial.Logistic Regression.Regularization.神经网络.机器学 ...

最新文章

  1. Tensor VS NumPy
  2. 多键开关 android8.0,手机桌面多键开关(SwitchPro Widget )
  3. eclipse的操作
  4. 超声波测距的数据应该如何显示到七针oled上_一文读懂京东方、TCL华星、三星显示和LGD之间的复杂关系...
  5. 报表软件JS开发引用HTML DOM的windows对象
  6. 回顾2020年(1)
  7. autoload.php beanbun_PHP爬虫框架Beanbun使用
  8. EXCEL:如何设置某一列不能修改
  9. 中国双酚F树脂市场趋势报告、技术动态创新及市场预测
  10. OSError: exception: access violation writing 0x000000003F800000
  11. 解密档案:CTF密码学之RSA攻击算法
  12. ubuntu 使用惠普HP打印机
  13. 主流视频通话SDK比较【转】
  14. 雷神ZERO游戏本和ROG冰刃5Plus的 区别 选哪个
  15. 核显 linux 软件,同样的核显,看在线视频ubuntu更卡 - Linux系统与应用 - LinuxApp - 水木社区...
  16. w7计算机休眠网络就断了,设置Win7电脑休眠时不断开WiFi教程
  17. 【大数据开发】SparkSQL——RDD、DataFrame、DataSet相互转换、DSL常用方法、SQL风格语法、Spark读写操作、获取Column对象的方式
  18. synaptics linux驱动程序,Synaptics
  19. android2.3.7刷机包,【新蜂】联想A789 刷机包 V3.2 (Android 4.0.4) 稳定流畅 纯净省电 完整ROOT...
  20. 手动搭建redis集群

热门文章

  1. netty udp接收超过2048字节数据
  2. 半导体行业十万级净化车间尘埃粒子监测
  3. UG NX二次开发(C#)-CAM-加工模板、程序、方法、刀具和几何体的读取
  4. 诺贝尔奖大数据告诉你:最聪明的星座是谁
  5. python lambda if语句_菜鸟提问: lambda 后接if
  6. h5 android 滚动条卡顿,h5页面滑动卡顿解决方法
  7. 微信小程序自定义选中样式打小勾
  8. 双非(湖大)学子保研夏令营简历优质修改辅导
  9. PMP每日⑤题(七)
  10. Unity Input 通过蓝牙手柄控制游戏