【机器学习】算法 之 SVM

参考:

  1. https://blog.csdn.net/qq_31347869/article/details/88071930
  2. https://www.jianshu.com/p/501505437200
  • 机器学习的一般框架
    训练集 => 提取特征向量 => 结合一定的算法(分类器:比如决策树、KNN)=>得到结果

一、SVM原理

1. 概述:

  • 支持向量机(support vector machines,SVM)是一种二分类模型,它将实例的特征向量映射为空间中的一些点,SVM 的目的就是想要画出一条线,可以 “最好地” 区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。SVM 适合中小型数据样本、非线性、高维的分类问题
  • SVM 最早是由 Vladimir N. Vapnik 和 Alexey Ya. Chervonenkis 在1963年提出,目前的版本(soft margin)是由 Corinna Cortes 和 Vapnik 在1993年提出,并在1995年发表。深度学习(2012)出现之前,SVM 被认为机器学习中近十几年来最成功,表现最好的算法。

2. SVM基本概念:

  • 将实例的特征向量(以二维为例)映射为空间中的一些点,如下图的实心点和空心点,它们属于不同的两类。SVM 的目的就是想要画出一条线,可以“最好地”区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。
    在这里插入图片描述
    Q1:能够画出多少条线对样本点进行区分?
    答:线是有无数条可以画的,区别就在于效果好不好,每条线都可以叫做一个划分超平面。比如上面的绿线就不好,蓝线还凑合,红线看起来就比较好。我们所希望找到的这条效果最好的线就是具有 “最大间隔的划分超平面”。

    Q2:为什么要叫作“超平面”呢?
    答:因为样本的特征很可能是高维的,此时样本空间的划分就不是一条线了。

    Q3:画线的标准是什么?/ 什么才叫这条线的效果好?/ 哪里好?
    答:SVM 将会寻找可以区分两个类别并且能使间隔(margin)最大的划分超平面。比较好的划分超平面,样本局部扰动时对它的影响最小、产生的分类结果最鲁棒、对未见示例的泛化能力最强。

    Q4:间隔(margin)是什么?
    答:对于任意一个超平面,其两侧数据点都距离它有一个最小距离(垂直距离),这两个最小距离的和就是间隔。比如下图中两条虚线构成的带状区域就是 margin,虚线是由距离中央实线最近的两个点所确定出来的(也就是由支持向量决定)。但此时 margin 比较小,如果用第二种方式画,margin 明显变大也更接近我们的目标。
    在这里插入图片描述
    Q5:为什么要让 margin 尽量大?
    答:因为大 margin 犯错的几率比较小,也就是更鲁棒啦。

    Q6:支持向量是什么?
    答:从上图可以看出,虚线上的点到划分超平面的距离都是一样的,实际上只有这几个点共同确定了超平面的位置,因此被称作 “支持向量(support vectors)”,“支持向量机” 也是由此来的。

3. 分类:

  • 按照分割的情况将SVM分为三种:

    1.硬间隔支持向量机(线性可分支持向量机):当训练数据线性可分时,可通过硬间隔最大化学得一个线性可分支持向量机。用通用的话来说就是上图中的虚线间没有数据点。

  1. 软间隔支持向量机:当训练数据近似线性可分时,可通过软间隔最大化学得一个线性支持向量机。用通俗的话来讲就是上图中虚线间还存在部分数据点。
    在这里插入图片描述

  2. 非线性支持向量机:当训练数据线性不可分时,可通过核方法以及软间隔最大化学得一个非线性支持向量机。无法用线性来进行划分。比如上图的情况。

4. 算法:

  • 最终得到公式
    在这里插入图片描述

  • 首先我们要证明的就是线性可分支持向量机。
    首先我们假设中间的超平面方程为:
    在这里插入图片描述
    当然如上面所言,我们可以对这个超平面进行平移,直到达到不能移动的支持向量的点。
    在这里插入图片描述
    如上图公式所示,我们先证明的是二分类,让等式大于1的为正例,小于1为负例。为什么选1呢?其实你可以选任何数,同样正例与负例用(1,-1)表示也是为了计算方便。
    这样我们可以很容易得出:
    在这里插入图片描述
    这样两个公式就合并了,同时得出了条件。

  • 最大化边际

  • 我们都知道svm就是要寻找使边际最大的那个状态的超平面,用M来表示两个边界平面间的距离,即:max M = ?
    如下图所示:
    在这里插入图片描述
    两个平面间的距离公式直接可以得出:

M = |b+1-(b-1)|/sqrt(w^2+0) = 2/||w||
  • M要最大,|w|就需要最小。所以我们得到的目标函数就是使 |w| 最小,即|w|^2最小。为求导方便,我们设为求:1/2|w|^2 最小。
  • 构造函数
  • 通过以上两次分析,我们已经把问题转化为了大学的数学问题:
    在已知:
    在这里插入图片描述
    的条件下,要使得 1/2|w|^2 最小。
  • 这就明显变成了一个目标函数和一个约束条件组合成的拉格朗日求最小值的问题。但是由于条件是一个不等式,同时这个条件包含所有的数据点, 利用一些数学推导,以上公式可变为有限制的凸优化问题(convex quadratic optimization)。利用 Karush-Kuhn-Tucker(KKT)条件和拉格朗日公式,可以推出MMH可以被表示为以下“决定边界”:
    在这里插入图片描述
    在这里插入图片描述

5. 示例:

在这里插入图片描述

二、SVM算法实现

  • 由于 SVM 算法本身的实现非常复杂,所以不研究如何实现 SVM,而是采用 sklearn 库来学习 SVM 的应用问题。
# sklearn 库中导入 svm 模块
from sklearn import svm

# 定义三个点和标签
X = [[2, 0], [1, 1], [2,3]]
y = [0, 0, 1]
# 定义分类器,clf 意为 classifier,是分类器的传统命名
clf = svm.SVC(kernel = 'linear')  # .SVC()就是 SVM 的方程,参数 kernel 为线性核函数
# 训练分类器
clf.fit(X, y)  # 调用分类器的 fit 函数建立模型(即计算出划分超平面,且所有相关属性都保存在了分类器 cls 里)
# 打印分类器 clf 的一系列参数
print(clf)
# 支持向量
print(clf.support_vectors_)
# 属于支持向量的点的 index 
print(clf.support_)
# 在每一个类中有多少个点属于支持向量
print(clf.n_support_) 
# 预测一个新的点
print(clf.predict([[2,0]]))

输出结果:

# 打印分类器 clf 的一系列参数
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
  kernel='linear', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)
# 支持向量
[[1. 1.]
 [2. 3.]]
# 属于支持向量的点的 index
[1 2]
# 在每一个类中有多少个点属于支持向量
[1 1]
# 预测一个新的点
[0]
print(__doc__)
# 导入相关的包
import numpy as np
import pylab as pl  # 绘图功能
from sklearn import svm

# 创建 40 个点
np.random.seed(0) # 让每次运行程序生成的随机样本点不变
# 生成训练实例并保证是线性可分的
# np._r表示将矩阵在行方向上进行相连
# random.randn(a,b)表示生成 a 行 b 列的矩阵,且随机数服从标准正态分布
# array(20,2) - [2,2] 相当于给每一行的两个数都减去 2
X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]]
# 两个类别 每类有 20 个点,Y 为 40 行 1 列的列向量
Y = [0] * 20 + [1] * 20

# 建立 svm 模型
clf = svm.SVC(kernel='linear')
clf.fit(X, Y)

# 获得划分超平面
# 划分超平面原方程:w0x0 + w1x1 + b = 0
# 将其转化为点斜式方程,并把 x0 看作 x,x1 看作 y,b 看作 w2
# 点斜式:y = -(w0/w1)x - (w2/w1)
w = clf.coef_[0]  # w 是一个二维数据,coef 就是 w = [w0,w1]
a = -w[0] / w[1]  # 斜率
xx = np.linspace(-5, 5)  # 从 -5 到 5 产生一些连续的值(随机的)
# .intercept[0] 获得 bias,即 b 的值,b / w[1] 是截距
yy = a * xx - (clf.intercept_[0]) / w[1]  # 带入 x 的值,获得直线方程

# 画出和划分超平面平行且经过支持向量的两条线(斜率相同,截距不同)
b = clf.support_vectors_[0] # 取出第一个支持向量点
yy_down = a * xx + (b[1] - a * b[0]) 
b = clf.support_vectors_[-1] # 取出最后一个支持向量点
yy_up = a * xx + (b[1] - a * b[0])

# 查看相关的参数值
print("w: ", w)
print("a: ", a)
print("support_vectors_: ", clf.support_vectors_)
print("clf.coef_: ", clf.coef_)

# 在 scikit-learin 中,coef_ 保存了线性模型中划分超平面的参数向量。形式为(n_classes, n_features)。若 n_classes > 1,则为多分类问题,(1,n_features) 为二分类问题。

# 绘制划分超平面,边际平面和样本点
pl.plot(xx, yy, 'k-')
pl.plot(xx, yy_down, 'k--')
pl.plot(xx, yy_up, 'k--')
# 圈出支持向量
pl.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
           s=80, facecolors='none')
pl.scatter(X[:, 0], X[:, 1], c=Y, cmap=pl.cm.Paired)

pl.axis('tight')
pl.show()

输出结果:

Automatically created module for IPython interactive environment
w:  [0.90230696 0.64821811]
a:  -1.391980476255765
support_vectors_:  [[-1.02126202  0.2408932 ]
 [-0.46722079 -0.53064123]
 [ 0.95144703  0.57998206]]
clf.coef_:  [[0.90230696 0.64821811]]

在这里插入图片描述

三、核方法

1. 使用核方法的动机

在这里插入图片描述

2. 常用的核函数(kernel functions)

在这里插入图片描述

3. 如何选择kernel function?

  • 根据先验知识,比如图像分类,通常使用 RBF(高斯径向基核函数),文字不使用 RBF。
  • 尝试不同的 kernel,根据结果准确度而定。

4. 核函数举例

在这里插入图片描述
不用核函数,直接求内积
在这里插入图片描述
使用核函数
在这里插入图片描述
同样的结果,使用 kernel 方法计算容易很多。而这只是 9 维的情况,如果维度更高,那么直接求内积的方法运算复杂度会非常大。

所以使用 核函数 的意义在于:

  • 将向量的维度从低维映射到高维;
  • 降低运算复杂度。

补充

1. 凸优化:

  • 凸优化或叫做凸最优化,凸最小化,是数学最优化的一个子领域,研究定义于凸集中的凸函数最小化的问题。凸优化在某种意义上说较一般情形的数学最优化问题要简单,譬如在凸优化中局部最优值必定是全局最优值。凸函数的凸性使得凸分析中的有力工具在最优化问题中得以应用,如次导数等。许多最优化问题都可以转化成凸优化(凸最小化)问题,例如求凹函数f最大值的问题就等同于求凸函数 -f最小值的问题。

2. 凸函数:

  • 凸函数是一个定义在某个向量空间的凸子集C(区间)上的实值函数f,如果在其定义域C上的任意两点x、y,以及
    在这里插入图片描述
    ,有
    在这里插入图片描述
    也就是说,一个函数是凸的当且仅当其上境图(在函数图像上方的点集)为一个凸集。
  • 如果对于任意的在这里插入图片描述
    在这里插入图片描述
    函数f是严格凸的。
  • 若对于任意的x、y、z,其中在这里插入图片描述
    ,都有在这里插入图片描述
    则称函数f是几乎凸的。

3. 线性可分与线性不可分

  • 线性不可区分,即无法用一条直线将两类样本点区分开。
  • 在线性不可分的情况下,数据集在空间中对应的向量无法被一个超平面区分开,该如何处理
    分两个步骤来解决:
  1. 利用一个非线性的映射把原数据集中的向量点转化到一个更高维度的空间中(比如下图将二维空间中的点映射到三维空间)
  2. 在这个高维度的空间中找一个线性的超平面来根据线性可分的情况处理。
    在这里插入图片描述
    如何利用非线性映射将原始数据转化到高维空间中去
    在这里插入图片描述
    思考问题:
  • 如何选择合理的非线性转化把数据转到高维空间中?
  • 如何解决计算内积时算法复杂度非常高的问题?
    使用核方法(kernel trick)

4. SVM 可扩展到多分类问题

  • SVM 扩展可解决多个类别分类问题:
    对于每个类,有一个当前类和其他类的二类分类器(one-vs-rest)
    将多分类问题转化为 n 个二分类问题,n 就是类别个数。

5. SVM 算法特性

  • 训练好的模型的算法复杂度由支持向量的个数决定的,而不是由数据的维度决定的。所以 SVM 不太容易产生 overfitting。
  • SVM 训练出来的模型完全依赖于支持向量,即使训练集里面所有非支持向量的点都被去除,重复训练过程,结果仍然会得到完全一样的模型。
    一个 SVM 如果训练得出的支持向量个数比较少,那么SVM 训练出的模型比较容易被泛化。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值