机器学习三人行(系列七)----支持向量机实践指南(附代码)
通过对系列六的学习,我们学习了逻辑回归算法,详情戳下面链接:
机器学习三人行(系列六)----Logistic和Softmax回归实战剖析(附代码)
关注公众号“智能算法”即可一起学习整个系列的文章。
文末查看本文代码关键字,公众号回复关键字下载代码。
其实逻辑回归算法和今天要讲的支持向量机有些类似,他们都是从感知机发展而来,支持向量机是一个非常强大而且应用面很广的机器学习算法,能够胜任线性分类器,非线性分类器,线性回归问题,非线性回归问题中,甚至是离群值检测中,是应用最广泛的机器学习算法之一,本文剖析支持向量机在实践中的应用。
一、线性支持向量机
我们以一些图来解释支持向量机的基本原理,下图是对鸢尾花数据集分类,可以发现两种花能够很轻松的通过直线划分出来,因为该数据集是线性可分的,左图是三种可能的分类方式,虚线基本没有办法将两种类别划分,另外两条倒是能够成功的划分,但是它们的决策边界距离实例太近了,如果用来预测新实例的话,肯定表现不好。相反右边图中的决策边界是支持向量机学习到的,图中的实线不但能够成功将两类划分出来,而且尽可能的远离距离最近的实例。支持向量机可以认为是在距离最近的实例间找到距离它们最远的决策边界,因此支持向量机也称最大间隔分类器。
注意到上图中,如果在距离决策边界很远的地方加入大量的训练实例并不会影响到决策边界,决策边界完全由不同类别距离最近的几个边缘实例决定的,即上图中圈出来的部分,这些实例被称为支持向量。
二、软间隔最大化
如果所有实例能够严格的分布在分离间隔的两侧,此时的支持向量机是根据硬间隔最大化,上面讨论的支持向量机就是这种,那么这里涉及两个问题:1,硬间隔分类器只在线性可分情况下可用,2、对离群值比较敏感。如下图中:
左图中多了一个离群值,此时没有办法找到硬间隔,因此没办法使用上面的支持向量机,右图由于出现一个离群值导致决策边界右移,严重影响了模型的泛化能力。
为了避免上面说的问题,我们需要一个更加灵活的模型,能够在最大间隔和误分类点之间寻找一个平衡,从而使得数据集变得可分类。因此获取的支持向量机是根据软间隔最大化计算的。
在Skicit-learn中,支持向量机是通过超参数C,来控制这个平衡的,C越小,能够获取到更宽的的分类间隔,但是有很多的误分类点,下图中就展示了在线性不可分的数据集上,两种不同软间隔支持向量机。
左图是使用较小的超参数C计算的支持向量机,决策间隔较大,但是出现很多的样本在分类间隔中导致不可分,右图是使用较大的参数C计算的支持向量机,得到了较小的决策间隔,较少的误分类点。
另外,如果你的训练的软间隔支持向量机出现了过拟合情况,也可以通过降低超参数C的值来达到正则化的目的。
下面我们通过支持向量机来对Iris进行分类。
svm_clf.predict([[5.5, 1.7]]),得到分类的结果为1。这里和上节讲解的逻辑回归不同,并不会输出预测概率,而是直接输出预测分类值。你还可以使用scikit-learn的SVC(kernel="linear",C=1)来训练支持向量机模型,但是比较的慢,特别是在数据集比较大时,因此并不推荐,另外还有使用SGDClassifier训练支持向量机的,通过设置SGDClassifier(loss="hinge",alpha=1/(m*C)),这是使用系列五中正则化的随机梯度下降方法来训练一个线性支持向量机,SGDClassifier训练的支持向量机虽然没有LinearSVC收敛的速度快,但是在处理大型数据集(特别是电脑的配置无法训练的数据集)和在线分类任务上很有用的。
三、线性不可分支持向量机
虽然线性支持向量机非常的高效,而且在很多数据集上效果出奇的好,但是有很多的数据集并不是线性可分的,而且加入超参数C之后,效果还是很差。一种处理这种非线性数据集的方法是加入更多的特征,比如多项式特征,在一些情况下,可以将非线性数据集变成线性可分。如下图中,左图是一个简单的数据集中只有一个特征X1,这个数据集并不是线性可分的,但是我们加入第二个特征X2,X2=(X1*X1)之后,变成一个2维的数据集了,此时数据集变成线性可分了。
因此我们对非线性数据集训练支持向量机之前,加入一个多项式的特征。我们通过一个实例来看一下怎么应用,下图是一个月牙形的数据集。通过
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=100, noise=0.15, random_state=42)产生。
很明显数据集是线性不可分的情况,我们来看加入一个多项式之后再训练支持向量机。
分类之后的结果如下:
在训练之前加入一些多项式特征是一个简单但是高效的特征处理方法,在各种机器学习算法都是有效果的,但是一个低次多项式并不能处理一些非常复杂的数据集,而高次多项式生成的大量特征会使得训练出来的模型非常的慢。幸运的是,我们通过支持向量机中核技巧来解决这个问题,通过核技巧加入多项式特征不仅能够得到和上面一样的结果,甚至是高次的多项式。下面来试一下。
代码中degree是选择多项式的幂次,coef0是控制通过多项式对模型的影响程度,即下图中的r。下面我们通过加入3次的多项式和10次的多项式,来看看它们分别效果。
很显然,右图出现了过拟合现象,可以尝试降低多项式的幂次,相反如果出现欠拟合,可以适当的加大多项式的幂次。对于选择最优的幂次和r,可以通过网格搜索的方式寻找。
四、高斯核函数
另外一个处理非线性问题的方式是,使用一个相似性函数,计算每个实例和选定的标识的相似度作为特征加入到训练集中。例如:还是选用前面使用的只有一维特征X1的数据集,在x1 = -2和x1 = 1处加入两个标识,接下来定义一个相似性函数,高斯核函数,选定γ = 0.3。
高斯核函数能够比较x和 ℓ的相似度,并映射到0到1。然后我们来计算新特征,例如,实例x1 = -1处,距离第一个标识距离是1,距离第二个标识是2,因此新的特征,x 2 = exp (–0.3 × 1*1) ≈ 0.74和 x 3 = exp (–0.3 × 2*2 ) ≈ 0.30。实例由x1 = -1,转变成了(0.74,0.3)上面了。因此将所有点转换之后变成下图的右图,数据集变得线性可分。
但是,上面的标识应该如何选取呢,一个简单的方法是对数据集上的每个实例都创建一个标识,这会创建很多维度,也增加了转换之后数据集的线性可分的概率。这个方法的缺点是,如果一个训练集有m个实例,n个特征,转换之后的数据集就有m个实例,m个特征。一旦训练集非常大,会导致出现很大数量的特征,增加计算的时间。
和多项式特征方法一样,支持向量机算法中也加入了高斯核函数的方法,还是使用月牙形数据集,使用方法如下:
通过设置不同的gamma和C可以获取不同的分类效果。
和之前一样gamma和C像是正则化参数,如果出现过拟合或欠拟合,可以调整这两个参数值来达到最优的结果。
五、回归问题
文章刚开始出,我们提到支持向量机还能解决线性回归问题和非线性回归问题。使用的方法是通过转换我们的模型训练的目标。处理回归问题不再是像分类问题中,保证尽量少错误分类的情况,在两个类别间寻找最大的分类间隔,而是保证尽量多的数据落在回归线上的同时,使得尽量多的实例包括在间隔中。我们通过在一些随机的线性数据中训练一个支持向量机回归模型,如下图:
上图中 ϵ控制着回归问题中间隔的大小。在间隔中间加入更多的训练实例并不会影响模型的预测,因此支持向量机回归模型对ϵ是不敏感的。scikit-learn中是使用LinearSVR来训练回归模型的。
对应上图中左边的回归模型。而处理非线性回归任务,同样可以使用核机器的支持向量机模型解决。
通过设置不同的C和ϵ,得到不同的模型效果。
左图中是加入比较小的正则化约束即参数C,右边加入较大的正则化约束。
六、内容总结
本文是从实践的角度学习了支持向量机,包括分类问题中线性可分支持向量机,线性不可分。线性可分涉及到硬间隔分类,线性不可分涉及到软间隔分类,多项式核技巧和高斯核技巧。和回归问题中支持向量机的使用,基于支持向量机回归问题的特性,我们可以通过设置支持向量机的间隔大小,将支持向量机应用到离群值的检测中。本文没有涉及到支持向量机相关的理论说明,如果有兴趣可以通过查看公众号更多有关支持向量机的内容。
(如需更好的了解相关知识,欢迎加入智能算法社区,在“智能算法”公众号发送“社区”,即可加入算法微信群和QQ群)
本文代码回复关键字:svm_code