支持向量机SVM的学习

20201102 -

0. 引言

支持向量机作为一种常用的机器学习算法,应用非常广泛,原始的SVM只能支持线性数据,而通过核函数的方式,可以使其应用于非线性数据。之前学习过SVM的具体过程,也在sklearn中进行过调优,但是都没有记录。而且上次学习已经是很久之前了,这次重新翻出来,了解了解具体原理,但是不对其中深层次的数学过程进行推导,能够明白各个公式是什么作用即可。

本篇文章先从《Hands-On Machine Learning with Scikit-Learn and TensorFlow》这本书开始,然后再去看一些其他的原理及实践文章,先从这本书看起的原因正是因为他由浅入深的介绍手段非常好,更容易理解。

1. 基础入门阶段

本小节主要参考《Hands-On Machine Learning with Scikit-Learn and TensorFlow》引文版,第五章,基本上对该章节进行了详细的阅读,并记录其中的关键点;有兴趣的读者可以直接阅读原书,本文仅仅是自己对部分内容的总结,不免有所疏漏

  • SVM适用于线性或非线性的分类,回归,异常检测
  • 适用于小型或中等级别的数据集

1.1 线性SVM分类的思想

该部分是最初的SVM提出的思想,针对线性数据应该如何划分,通过统计学习理论中的一些概念来实现最终目标(具体等后续看到了再记录)。这里应该记录的主要是SVM到底是采用了什么样的思想,或者说什么样的目标来实现分类。在之前的时候,我也连结果这部分内容。假设有两部分线性可分的数据,那么可能存在着非常多的直线(假设是二维数据)能够将两部分的数据划分开,但是哪一条直线是划分效果最好的呢?来看一下书中的解释。
在这里插入图片描述
上图中,左边的两条实现都能实现类别的划分;但实际上SVM的思想,要达到的目标是右边的呈现出来的实线。先来说明两个概念,在右边图中,实线代表着线性SVM的分类边界,而虚线上的点指的是支持向量。有了这两个概念之后,来看文章关于SVM的描述:SVM的分类边界,在将两个类别分类开来之后的同时,能够保证这个分类边界与最近的样本点保持最远的距离,这个样本点就是支持向量,可以把SVM想象为拟合了一个非常宽的街道。这种被称为是大幅度分类(翻译不太准确,原文是large margin classification)。这个支持向量起到了非常关键的作用,当有了支持向量之后,如果添加了更多的样本,但是这个样本并不在这个“街道”里面,那么他对分类边界是完全没有影响的。增量学习过程应该也会利用这个思想。
而且SVM对特征的量纲非常敏感,不同量纲在图像上表象出来的分解边界是不一样的,如下图所示。
在这里插入图片描述
如上图所示,当没有进行归一化的时候,分解边界退化为一天水平线。但是实际上,我觉得这里还是要看是不是影响了分类过程的运算性能。

1.2 软边界分类

前面提到的过程,是希望能够尽量让分类边界与点的距离变大,也就是不允许有点在接到中间,也就是两个平行的支持向量的中间,也被称为硬边界分类。但是这种方式呢,存在很大的局限性:

  • 对异常点非常敏感,假设有一个异常点,某个类别的点出现在了两外一个类别中,那么将无法找到合是的分类边界
  • 仅仅当数据是线性可分的时候才可以用(此时不考虑核方法)

在这里插入图片描述
可以看到上图,一种不可能分类,另一种分类效果很差。这个时候可以使用一种软边界的分类方法:保持分类的“街道”越大越好,同时限制违反上面条件的程度(margin violaions)(样本在街道上,甚至于在分界面的另一边),soft margin classification。
在sklearn的库中,其中的SVM模型的参数 C C C就是控制这个东西的: C C C越小,街道越大,违反限制的程度越大(更多数量的样本可以在街道上),通过控制整个超参,可以缓解过拟合的情况。
需要注意的是,SVM分类器无法输出每个样本所属类别的概率,不过我记得,是有一定手段来实现的,可能说原生的无法输出而已。在原文的后续内容中,开始通过代码来进行展示,代码示例:

svm_clf = Pipeline((
	("scaler", StandardScaler()),
	("linear_svc",LinearSVC((C=1, loss = "hinge")),
))

这里是使用的是LinearSVC这个方法, 不过这个方法我之前没有使用过,都是直接使用的SVC,SVC(kernel="linear", C=1),但是书中提示,这种方法会更慢,大数据集上就更慢了。另一个选项是使用SGDClassifier(loss = "hinge", alpha=1/(m*C)),这种方法也没有LinearSVC快,但能够处理大数据集,或者处理在线分类的任务,不过这种的话,我就更没有用过了。同时,使用LinearSVC时,一定要注意归一化,同时设置loss="hinge",还有要考虑是否设置dual参数,不过暂时没有具体弄过,这部分的区别就是不同的实现而已,后面会展开。

1.3 处理非线性数据

1.3.1 增加更多特征

一种处理非线性数据的方式就是增加多项式特征,例如增加一个x^2的特征。
在这里插入图片描述
代码如下:

polynomial_svm_clf = Pipeline((
        ("poly_features", PolynomialFeatures(degree=3)),
        ("scaler", StandardScaler()),
        ("svm_clf", LinearSVC(C=10, loss="hinge"))
    ))

但是这种方法有一个坏处,那就是本质上他需要进行变换之后再进行SVM的处理;当增加的特征少的时候,不容易得到较好的拟合效果,增加的特征过多又会导致计算量变大。而SVM自身具备了处理非线性数据的能力,也就是核函数(核方法,核技巧)。

1.3.2 核方法

核方法是一种能够在原始空间中计算点积的方式,这样就能从原始数据空间的线性不可分得到线性可分的高维空间;而他神奇之处在与并不用真正的将这部分特征变换到高维空间。
(注:如果一开始看这部分内容的时候,如果没有从数学上了解过SVM,那么可能很难明白这句话;实际上,就是因为在求解SVM的过程中,存在一个点积(两个样本之间),而直接替换这个点积为核函数,就是变换之后的点积,这个在数学上是成立的。具体可以看下本博客中的另一篇文章《核方法学习》,这样交叉着看来,就能明白为什么核函数这么有用,最起码在使用SVM的时候。

from sklearn.svm import SVC
poly_kernel_svm_clf = Pipeline((
        ("scaler", StandardScaler()),
        ("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))
    ))
poly_kernel_svm_clf.fit(X, y)

在这里插入图片描述
而通过控制二项式次数也可以调节过拟合的效果。

1.3.3 增加相似度特征

另一种增加特征来处理非线性数据的方法是,增加相似度特征(其实就是RBF核,后面细讲)。

add features computed using a similarity function that measures how much each instance resembles a particular landmark.

在该部分例子中,使用的事高斯径向基函数(所谓的相似度函数)。
在这里插入图片描述
上图中的含义就是,选择两个样本,作为比较的比准,比如上面左图中,利用两个圆圈来作为基准,而通过变换之后,得到了右边的图。这样也能线性可分。而为了找到这个基准点,可以将每个数据点做为基准来进行计算。

1.3.4 高斯核函数(RBF)

rbf_kernel_svm_clf = Pipeline((
        ("scaler", StandardScaler()),
        ("svm_clf", SVC(kernel="rbf", gamma=5, C=0.001))
    ))
rbf_kernel_svm_clf.fit(X, y)

在这里插入图片描述
而通过控制 γ \gamma γgamma这个参数,同样可以调节过拟合与欠拟合:模型过拟合,可以减小 γ \gamma γ,模型欠拟合可以增大 γ \gamma γ

小技巧:在不知道选择什么核函数的时候,可以先使用线性核,然后是高斯RBF核。

1.3.5 计算复杂度

  • LinearSVC类是基于liblinear实现的,这个库针对线性SVM实现了一个优化算法, 这也是为什么前面代码中为什么要使用损失函数的原因,训练时间的复杂度是 O ( m × n ) O(m\times n) O(m×n)
  • SVC类是基于libsvm实现的,支持核方法;训练时间的复杂度在 O ( m 2 × n ) O(m^2\times n) O(m2×n) O ( m 3 × n ) O(m^3\times n) O(m3×n),当大数据集的时候,这种方法就非常慢了。不过该方法对于稀疏的特征,具备很好的适应性,这里没明白,需要更多的实践。
    大致的比较如下:
    在这里插入图片描述

1.4 SVM的数学原理

在介绍SVM数学原理之前,书籍还简单介绍了SVR,这里不展开讲了。其实学习了前面的内容,然后能够明白怎么调优,调整哪些参数能够怎么实现更好的分类效果,在实际应用中就已经足够了(对于我这样的非数学学生来说),而且平时的确是这样直接使用的,没有什么不好的效果。但是为了能够对SVM有一个更深入的理解,还是要简单理解一下大致的数学原理,本篇文章也不会对对这部分进行研究,什么拉朗朗日算子等等,这些高数的东西我认识他,他不认识我。所以,大致能明白原理就好。

1.4.1 线性SVM的决策函数

从二维平面上来看,SVM是要寻求一个平面,这个平面能够切分两个类别的数据,大致的分类函数如下:
y ^ = { 0 if w T ⋅ x + b < 0 , 1 if w T ⋅ x + b ≥ 0 \hat y= \begin{cases} 0& {\text{if}} \quad \textbf w^T\cdot \textbf x + b < 0, \\ 1& {\text{if}} \quad \textbf w^T\cdot \textbf x + b \geq 0 \end{cases} y^={01ifwTx+b<0,ifwTx+b0

那么在三位空间中可以看到这个具体的交叉点,在二维上体现出来就是一条直线。
在这里插入图片描述
实际上,我能理解这个图想传达的意思,但是总感觉这个图画的好像不对,或者说他文章并没有具体说清楚。实际上应该是这么回事,线性的决策平面,是通过两个变量,然后得到一个数值,形成了三位空间上平面,这个是能够理解。然后,其中第三维等于0的地方,这两个平面的交汇部分就是决策函数为零的地方,也就是一条直线。实际上上图中,如果是把点绘制到斜着的这个平面,那就应该是所传达的意思了。
而训练SVM的过程,就是要找打这个权值和偏差,这样就知道了最终的决策函数;同时,这个决策函数还要能够将这个边界越宽越好,根据是否容忍误分类来区分是软分界还是硬分界(就是前面说到的内容)。但是前面的内容依然仅仅是从直观感受上来说明要达到什么样的分类效果,那么从数学角度应该怎么描述呢?也就是说,怎么把前面描述的内容转化到最终的目标函数呢?这里才是后续能够继续求解的关键内容。

1.4.2 训练目标

在实际看这个具体的目标函数之前,我来思考一下,就是用自己的语言把前面的内容表达出来。
首先,已经知道这个线性的SVM就是通过一个决策函数来完成,大致的公式如下:
y ^ = w T ⋅ x + b f ( x ) = s i g n ( y ) \hat y=\textbf w^T\cdot \textbf x+b\\ f(x)=sign(y) y^=wTx+bf(x)=sign(y)
在二维情况下,就是找到一个平面;而仅仅找到这个平面还不行,正如最前面所说,这种平面会有很多,同时还要找到一个支持向量的边,让这个抽象的"街道"最大。而前面也提到,决策函数等于 ± 1 \pm 1 ±1的位置,正是支持向量的位置,在硬分界的场景下,这个是距离分界边界最大的位置,然后选取这个中间的位置让两边的点都距离这个最近即可。(而实际上,因为两个参数都可以缩放,实际上 ± 1 \pm 1 ±1是可以随便选取的)。(不过我仅有的这个数学知识已经不足以让我自己推导出这个公式了,还是看看书上的说法)。
对于硬分界的线性SVM来说, 要求解出来所有的样本点都能满足一个函数,当(分类标签) y = 1 时 y=1时 y=1 t = 1 t=1 t=1,而 y = − 1 y=-1 y=1 t = − 1 t=-1 t=1,那么也就是说,对于所有的样本点,应满足 t ( i ) ( w T ⋅ x ( i ) + b ≥ 1 t^{(i)}(\textbf w^T\cdot \textbf x^{(i)}+b\geq1 t(i)(wTx(i)+b1。但是这里只满足了一个条件,就是能够将样本正确分类,还需要另外一个条件,这个条件看书上是怎么说的。因为平面的斜率正好是 ∥ w ∥ \|\textbf w\| w,如果将斜率除以2,那么这个决策函数等于 ± 1 \pm 1 ±1的位置将是原来的两倍,具体可见图。
在这里插入图片描述
那么也就是说,说当偏差 b b b固定的时候, ∥ w ∥ \|\textbf w\| w越小越好,而且本来 b b b估计在计算过程中也被略去了,特别是前面也提到要进行归一化。(不过关于 b b b的内容是我自己感觉的,后续可能要参考更权威的书籍来查证)。那么好了,我要得到一个边界,这个边界越大越好,那就必须最小化 ∥ w ∥ \|\textbf w\| w才可以,那么最终将得到一下的目标函数:
minimize w , b 1 2 w T ⋅ w subject to t ( i ) ⟮ w T ⋅ x ( i ) + b ⟯ ≥ 1 for i = 1 , 2 , . . . , m \mathop{\text {minimize}}\limits_{\textbf w,b} \qquad \frac{1}{2}\textbf w^T\cdot \textbf w \\ \text {subject to} \qquad t_{(i)}\lgroup\textbf w^T\cdot \textbf x^{(i)}+b\rgroup\geq 1 \quad\text{for}\quad i = 1,2,...,m w,bminimize21wTwsubject tot(i)wTx(i)+b1fori=1,2,...,m
关于这部分的求解,这里就不再展开了,有兴趣的可以先看看这本书,这里直接贴出解决方案:
在这里插入图片描述
其中的点积,正是前面核方法中要说明的,直接替换这个点积,就能得到相应的核方法下的目标。

1.5 小节

本部分主要按照《Hands-On Machine Learning with Scikit-Learn and TensorFlow》这本书第五章进行了学习,能够得到相应的理解,当然依然是比较浅显的理解,但是已经能够明白大致的原理,而且通过公式中的点积也知道了为什么要使用核方法。后续可以看看一些文章,看看很多参数是怎么起作用的。也就是怎么讲代码实践应用起来。

在本部分学习过程中,翻阅到了两部分文章,这里记录一下,后续再展开:
sklearn.svm包中的SVC(kernel=”linear“)和LinearSVC的区别
scikit-learn 支持向量机算法库使用小结
(未完待续。。。)

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值