1 引 言
在前面几章中,掌柜已经陆续介绍了多种分类算法模型,相信各位读者朋友对于机器学习也算是有了一定的了解。在接下来的这一些列文章中,掌柜将开始逐步介绍下一个分类模型——支持向量机。支持向量机(Support Vector Machine, SVM)可以算得上是机器学习算法中最为经典的模型。之所以称之为经典是因为支持向量机的背后有着完美的数学推导与证明。当然,也正是因为这个原因使得学习SVM有着较高的门槛。因此,在接下来的内容中,掌柜将会尽可能以最通俗的表达来介绍SVM中的相关原理。
2 支持向量机
2.1 SVM思想
什么是支持向量机呢?初学者刚接触到这个算法时基本上都会被这个名字所困扰,到底什么叫“向量机”,听起来总觉得怪怪的。因此首先需要明白的是,支持向量机其实和“机”一点关系也没有,算法的关键在于“支持向量”。如图1所示为4种不同模型对同一个数据集分类后的决策边界图。可以看到尽管每个模型都能准确地将数据集分成两类,但是从各自的决策边界到两边样本点的距离来看却有着很大的区别。
为了能更加清楚的进行观察,下面将4个决策边界放到一张图中,如图2所示。
如图2所示,图中左边从上到下分别为模型(d)(a)(b)(c)在数据集上的决策边界。可以发现模型(c)的泛化能力应该会是最差的,因为从数据的分布位置来看真实的决策面应该是一条左高右低倾斜的直线。其次是模型(b)的泛化能力,因为从图2可以看出模型(b)的决策面太过于偏向方块形的样本点。因为在评估分类决策面优劣的一个原则就是,当没有明确的先验知识告诉我们决策面应该偏向于哪边时,最好的做法应该是居于中间位置,也就是类似于模型(a)和模型(d)的决策面。那么模型(a)和模型(d)谁又更胜一筹呢?进一步,可以将(a)和(d)这两个模型各自到两侧样本点距离可视化出来,如图3所示。
从图3中一眼便可以看出,模型(d)的决策面要更居于“中间”(事实上就是在中间),而模型(a)的决策面也是略微偏向于方块形的样本点。因此在这4个模型中,模型(d)的泛化能力通常情况下都会是最强的。此时有读者可能就会问,假如把模型(a)中的决策面向上平移一点,使得其也居于两条虚线之间,那么此时应该选择谁呢?答案当然依旧是模型(d),原因在于模型(d)的决策面还满足另外一个条件,到两条虚线的距离最大。换句话说也就是,模型(d)中两条虚线之间的距离要大于模型(a)中两条虚线之间的距离。
说到这里,相信各位读者已经猜到,模型(d)对应的就是支持向量机模型,同时虚线上的两个样本点就被称为支持向量。可以发现,最终对决策面其决定性作用的也只有这两个样本点,说得通俗点就是仅根据这两个点就能训练得到模型(d)。
因此,这里可以得出的结论就是,通过支持向量机我们便能够得到一个最优超平面,该超平面满足到左右两侧最近样本点的间隔相同,且离左右最近样本点的间隔最大。不过那又该如何来找到这个超平面呢?
2.2 SVM原理
2.2.1超平面的表达
在正式定义距离之前,这里先回顾一下超平面的表达式
其中
从上述表达式可知,当通过某种方法找到参数
2.2.2函数间隔
上面说到SVM的核心思想就是最大化间隔,既然是最大化间隔那总得有个度量间隔的方法才行。根据中学知识可知,当超平面
如图4所示,其中直线方程为
同时还可以注意到,只要分类正确,
且定义训练集中样本点到超平面的函数间隔中的最小值为
但是此时可以发现,如果在式
2.2.3 几何间隔
所谓几何间隔(Geometric Margin),就是样本点到直线实实在在的距离。只要直线不发生改变,那么间隔就不会发生任何改变,这样就避免了在函数间隔中所存在的问题。那么应该如何来表示几何间隔呢?如图5所示,线段
如图5所示,直线方程为
又因为
因此可以通过化简等式
现在,假设有一直线
所以根据式
因此几何距离计算公式为
当然,这只是当样本
故,根据图4可知,样本点
此时可以发现,同函数间隔类似只要在分类正确的情况下几何间隔也都满足条件
同时,函数间隔与几何间隔存在以下关系
可以发现,几何间隔其实就是在函数间隔的基础上施加了一个约束限制。此时我们已经有了对于间隔度量的方式,所以下一步自然就是最大化这个间隔来求得分类超平面。
2.2.4 最大间隔分类器
什么是最大间隔分类器(Maximum Margin Classifiers) 呢?上面说到,有了间隔的度量方式后,接着就是最大化这一间隔,然后求得超平面
因为在式
其中
①
② 同时要使得样本中所有的几何距离都大于
所以,进一步由式
此时可以发现,约束条件由几何间隔变成了函数间隔,准确说应该既是函数间隔同样也是几何间隔。因此,既然可以看作函数间隔,那么令
所以,式
但是对于
之所以要进行这样的处理,是因为这样可以将其转换为一个典型的凸优化问题,并用现有的方法进行求解;而在前面乘以
2.2.5 函数间隔的性质
在2.2.1节优化问题的化简过程中掌柜直接将函数间隔设置为了1,不过相信对于不少读者来说在这一点上仍旧比较疑惑。当然,这也是一个在学习SVM中最典型的问题,因此接下来就这点进行一个简要的说明。
假设现在有如下函数间隔
那么对等式
此时令
接着再把式
不过需要明白的是,式
例如现有如下平面方程
某正样本
进一步在等式
虽然此时的
2.2.6 小结
在本节中,掌柜首先通过一个引例介绍了支持向量机的核心思想;接着介绍了支持向量机中衡量间隔的两种度量方式,即函数间隔和几何间隔;然后介绍了如何通过结合函数间隔与几何间隔来建模支持向量机的优化问题;最后还介绍了SVM中的一个经典问题,函数间隔为什么可以设为1。
3 SVM示例代码与线性不可分
在前面两节内容中,掌柜介绍了支持向量机的基本思想以及对应的数学原理。不过说一千道一万,还是不如自己亲手来做一做。在接下来的内容中,掌柜将首先介绍如何通过sklearn来搭建相应的SVM分类模型,然后将接着介绍如何处理SVM中的线性不可分问题。
3.1 线性SVM示例代码
在sklearn中可以通过from sklearn.svm import SVC
这句代码就能够导入SVM分类模型了。有读者可能会觉得奇怪,为什么导入的是一个叫SVC的东西?这是因为其实SVM不仅可以用来分类,它同样也能用于回归问题,因此SVC其实就是支持向量分类的意思。
点击进入SVC定义的地方便可以发现里面有很多超参数可以进行设置
xxxxxxxxxx
711 def __init__(self,
22 C=1.0,
33 kernel='rbf',
44 degree=3,
55 gamma='scale',
66 coef0=0.0,
77 decision_function_shape='ovr'):
在上述代码中只列举了SVM中常见的一些超参数。不过这里暂时只对kernel这个参数进行介绍,其它的参数等介绍完相关原理后再进行解释。根据前面两节内容可知SVM是一个线性分类器,因此这里只需要将参数kernel
设置为kernel='linear'
便能达到这一目的。
在完成SVC的导入工作后,根据如下代码便可以使用线性SVM进行分类建模,完整实例代码参见Book/Chapter09/01_linear_svm.py文件。
xxxxxxxxxx
611 def train(x_train, x_test, y_train, y_test):
22 model = SVC(kernel='linear')
33 model.fit(x_train, y_train)
44 y_pre = model.predict(x_test)
55 print(f"准确率为:{model.score(x_test, y_test)}")
66 # 准确率为:0.975925925925926
上述代码就是通过sklearn实现线性SVM的全部代码。可以看出,在sklearn中使用一个模型的步骤依旧是掌柜在5.3.1节中总结的3步走:建模、训练和预测。同时,由于这里的超参数kernel暂时只有一个取值,因此也不需要进行模型选择。从最后在测试集上的结果来看,线性SVM分类器的表现在准确率上有着不错的结果。
3.2 从线性不可分谈起
根据2节内容中SVM的思想来看,到目前为止谈到的情况都是线性可分的,也就是说总能找到一个超平面将数据集分开。可事实上却是,在大多数场景中各个类别之间都是线性不可分的,即类似如图6所示的情况。
对于图6中这种情况应该怎么才能将其分开呢?在4.2.4节中掌柜介绍过,这类问题可以使用特征映射的方法将原来的输入特征映射到更高维度的空间,然后再找寻一个超平面将数据集中不同类别的样本进行分类,如图7所示。
如图7所示,现在我们已经用一个超平面完美的将不同类别的样本进行了分开。不过此时有读者可能会疑惑到这还是刚刚的数据集么?之前明明在二维平面,现在却跑到三维空间。虽然数据集确确实实已经不是同一个数据集了,但是每个数据样本所对应的类别却依旧和原来的一样,只不过现在给它穿上了一件“马甲”。也就是说,假如
在介绍完特征映射的基本思想后,下面掌柜就来介绍如何在SVM中将低维特征映射到高维空间中。
3.3 将低维特征映射到高维空间
所谓将低维特征映射到高维空间指的是用一定的映射关系,将原始特征映射到更高维度的空间。比如通过一个函数
根据式
其中
按照上面提到的通过函数
虽然这样一来算是一定程度上解决了SVM中线性不可分的难题,但是又出现了一个新的问题——“维度爆炸”。
假设现有数据集
此时各位读者应该会发现这个过程的计算量太大了,整体复杂度为
3.4 SVM中的核技巧
设
说得简单点就是,存在某个映射能够找到一个与之对应的核函数
现假设式