一、SVM算法简介
1 SVM算法导入
在很久以前的情人节,大侠要去救他的爱人,但魔鬼和他玩了一个游戏。
魔鬼在桌子上似乎有规律放了两种颜色的球,说:
“你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。”
于是大侠这样放,干的不错?
然后魔鬼,又在桌上放了更多的球,似乎有一个球站错了阵营。
怎么办??
把分解的小棍儿变粗。
SVM就是试图把棍放在最佳位置,好让在棍的两边有尽可能大的间隙。
现在即使魔鬼放了更多的球,棍仍然是一个好的分界线。
然后,在SVM 工具箱中有另一个更加重要的技巧( trick)。 魔鬼看到大侠已经学会了一个trick,于是魔鬼给了大侠一个新的挑战。
现在,大侠没有棍可以很好帮他分开两种球了,现在怎么办呢?
当然像所有武侠片中一样大侠桌子一拍,球飞到空中。然后,凭借大侠的轻功,大侠抓起一张纸,插到了两种球的中间。
现在,从魔鬼的角度看这些球,这些球看起来像是被一条曲线分开了。
再之后,无聊的大人们,把上面的物体起了别名:
球—— 「data」数据
棍子—— 「classifier」分类
最大间隙——「optimization」最优化
拍桌子——「kernelling」核方法
纸——「hyperplane」超平面
案例来源:http://bytesizebio.net/2014/02/05/support-vector-machines-explained-well/
2 SVM算法定义
2.1 定义
SVM:SVM全称是supported vector machine(支持向量机),即寻找到一个超平面使样本分成两类,并且间隔最大。
SVM能够执行线性或非线性分类、回归,甚至是异常值检测任务。 它是机器学习领域最受欢迎的模型之一。SVM特别适用于中小型复杂数据集的分类。
2.2 超平面最大间隔介绍
上左图显示了三种可能的线性分类器的决策边界:
虚线所代表的模型表现非常糟糕,甚至都无法正确实现分类。其余两个模型在这个训练集上表现堪称完美,但是它们的决策边界与实例过于接近,导致在面对新实例时,表现可能不会太好。
右图中的实线代表SVM分类器的决策边界,不仅分离了两个类别,且尽可能远离最近的训练实例。
2.3 硬间隔和软间隔
2.3.1 硬间隔分类
在上面我们使用超平面进行分割数据的过程中,如果我们严格地让所有实例都不在最大间隔之间,并且位于正确的一边,这就是硬间隔分类。
硬间隔分类有两个问题,首先,它只在数据是线性可分离的时候才有效;其次,它对异常值非常敏感。
当有一个额外异常值的鸢尾花数据:下面左图的数据根本找不出硬间隔,而右图最终显示的决策边界与我们之前所看到的无异常值时的决策边界也大不相同,可能无法很好地泛化。
2.3.2 软间隔分类
要避免这些问题,最好使用更灵活的模型。目标是尽可能在保持最大间隔宽阔和限制间隔违例(即位于最大间隔之中,甚至在错误的一边的实例)之间找到良好的平衡,这就是软间隔分类。
在Scikit-Learn的SVM类中,可以通过超参数C来控制这个平衡:C值越小,则间隔越宽,但是间隔违例也会越多。 上图显示了在一个非线性可分离数据集上,两个软间隔SVM分类器各自的决策边界和间隔。
-
左边使用了高C值,分类器的错误样本(间隔违例)较少,但是间隔也较小。
-
右边使用了低C值,间隔大了很多,但是位于间隔上的实例也更多。
看起来第二个分类器的泛化效果更好,因为大多数间隔违例实际上都位于决策边界正确的一边,所以即便是在该训练集上,它做出的错误预测也会更少。
二、SVM算法api初步使用
from sklearn import svm
X = [[0, 0], [1, 1]]
y = [0, 1]
clf = svm.SVC()
clf.fit(X, y)
在拟合后, 这个模型可以用来预测新的值:
clf.predict([[2., 2.]])
# array([1])
三、SVM算法原理
1 定义输入数据
假设给定一个特征空间上的训练集为:
其中,
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi)称为样本点。
- x i x_i xi为第 i i i个实例(样本),
-
y
i
y_i
yi 为
x
i
x_i
xi 的标记:
- 当 y i = 1 y_i=1 yi=1时, x i x_i xi为正例
- 当 y i = − 1 y_i=-1 yi=−1时, x i x_i xi为负例
至于为什么正负用(-1,1)表示呢?
其实这里没有太多原理,就是一个标记,你也可以用(2,-3)来标记。只是为了方便, y i / y j = y i ∗ y j y_i/y_j=y_i*y_j yi/yj=yi∗yj 的过程中刚好可以相等,便于之后的计算。
2 线性可分支持向量机
给定了上面提出的线性可分训练数据集,通过间隔最大化得到分离超平面为 : y ( x ) = w T Φ ( x ) + b y(x)=w^T\Phi(x)+b y(x)=wTΦ(x)+b
相应的分类决策函数为: f ( x ) = s i g n ( w T Φ ( x ) + b ) f(x)=sign(w^T\Phi(x)+b) f(x)=sign(wTΦ(x)+b)
以上决策函数就称为线性可分支持向量机。
这里解释一下 Φ ( x ) \Phi(x) Φ(x)这个东东。
这是某个确定的特征空间转换函数,它的作用是将x映射到更高的维度,它有一个以后我们经常会见到的专有称号"核函数"。
比如我们看到的特征有2个:
x 1 , x 2 x1,x2 x1,x2组成最先见到的线性函数可以是 w 1 x 1 + w 2 x 2 w_1x_1+w_2x_2 w1x1+w2x2
但也许这两个特征并不能很好地描述数据,于是我们进行维度的转化,变成了
w 1 x 1 + w 2 x 2 + w 3 x 1 x 2 + w 4 x 1 2 + w 5 x 2 2 w_1x_1+w_2x_2+w_3x_1x_2+w_4x_1^2+w_5x_2^2 w1x1+w2x2+w3x1x2+w4x12+w5x22
于是我们多了三个特征。而这个就是笼统地描述 x x x的映射的。
最简单直接的就是: Φ ( x ) = x \Phi(x)=x Φ(x)=x
以上就是线性可分支持向量机的模型表达式。我们要去求出这样一个模型,或者说这样一个超平面 y ( x ) y(x) y(x),它能够最优地分离两个集合。
其实也就是我们要去求一组参数 ( w , b ) (w,b) (w,b),使其构建的超平面函数能够最优地分离两个集合。
如下就是一个最优超平面:
又比如说这样:
阴影部分是一个“过渡带”,“过渡带”的边界是集合中离超平面最近的样本点落在的地方。
3 SVM的计算过程与算法步骤
3.1 推导目标函数
我们知道了支持向量机是个什么东西了。现在我们要去寻找这个支持向量机,也就是寻找一个最优的超平面。
于是我们要建立一个目标函数。那么如何建立呢?
再来看一下我们的超平面表达式: y ( x ) = w T Φ ( x ) + b y(x)=w^T\Phi(x)+b y(x)=wTΦ(x)+b
为了方便我们让: Φ ( x ) = x \Phi(x)=x Φ(x)=x
则在样本空间中,划分超平面可通过如下线性方程来描述: w T x + b = 0 w^Tx+b =0 wTx+b=0
- 我们知道 w = ( w 1 , w 2 , . . . . , w d ) w = (w_1,w_2,....,w_d) w=(w1,w2,....,wd) 为法向量,决定了超平面的方向;
- b b b为位移项,决定了超平面和原点之间的距离。
- 显然,划分超平面可被法向量 w w w和位移b确定,我们把其记为 ( w , b ) (w,b) (w,b)
样本空间中任意点
x
x
x到超平面
(
w
,
b
)
(w,b)
(w,b),的距离可写成
r
=
∣
w
T
x
+
b
∣
∣
∣
w
∣
∣
r = \frac{|w^Tx + b|}{||w||}
r=∣∣w∣∣∣wTx+b∣
假设超平面
(
w
,
b
)
(w,b)
(w,b) 能将训练样本正确分类,即对于
(
x
i
,
y
i
)
∈
D
(x_i, y_i)\in D
(xi,yi)∈D
- 若 y i = + 1 y_i=+1 yi=+1,则有 w T x i + b > 0 w^Tx_i+b>0 wTxi+b>0;
- 若 y i = − 1 y_i=-1 yi=−1,则有 w T x i + b < 0 w^Tx_i+b<0 wTxi+b<0;
令
如图所示,距离超平面最近的几个训练样本点使上式等号成立,他们被称为“支持向量",两个异类支持向量到超平面的距离之和为:
γ
=
2
∣
∣
w
∣
∣
\gamma = \frac{2}{||w||}
γ=∣∣w∣∣2,它被称为“间隔”。
欲找到具有最大间隔的划分超平面,也就是要找到能满足下式中约束的参数
w
w
w 和
b
b
b,使得
γ
\gamma
γ 最大。
即:
显然,为了最大化间隔,仅需要最大化
∣
∣
w
∣
∣
−
1
||w||^{-1}
∣∣w∣∣−1,这等价于最小化
∣
∣
w
∣
∣
2
||w||^{2}
∣∣w∣∣2。于是上式可以重写为:
这就是支持向量机的基本型。
3.2 目标函数的求解
到这一步,终于把目标函数给建立起来了。
那么下一步自然是去求目标函数的最优值.
因为目标函数带有一个约束条件,所以我们可以用拉格朗日乘子法求解。
3.2.1 朗格朗日乘子法
啥是拉格朗日乘子法呢?
拉格朗日乘子法 (Lagrange multipliers)是一种寻找多元函数在一组约束下的极值的方法
通过引入拉格朗日乘子,可将有 d 个变量与 k 个约束条件的最优化问题转化为具有 d + k 个变量的无约束优化问题求解。
经过朗格朗日乘子法,我们可以把目标函数转换为:
其中,上式后半部分:
走到这一步,这个目标函数还是不能开始求解,现在我们的问题是极小极大值问题
3.2.2 对偶问题
我们要将其转换为对偶问题,变成极大极小值问题:
从 min max L ( w , b , α ) \min\max L(w,b,\alpha) minmaxL(w,b,α) 变为: max α min w , b L ( w , b , α ) \max\limits_{\alpha}\min\limits_{w,b} L(w,b,\alpha) αmaxw,bminL(w,b,α)
如何获取对偶函数?
首先我们对原目标函数的w和b分别求导:
- 原目标函数:
- 对w求偏导:
- 对b求偏导:
然后将以上w和b的求导函数重新代入原目标函数的w和b中,得到的就是原函数的对偶函数:
这个对偶函数其实求的是:
max
α
min
w
,
b
L
(
w
,
b
,
α
)
\max\limits_{\alpha}\min\limits_{w,b} L(w,b,\alpha)
αmaxw,bminL(w,b,α)中的
min
L
(
w
,
b
)
\min L(w,b)
minL(w,b)部分(因为对w,b求了偏导)。
于是现在要求的是这个函数的极大值
max
(
a
)
\max(a)
max(a),写成公式就是:
好了,现在我们只需要对上式求出极大值
α
\alpha
α,然后将
α
\alpha
α代入
w
w
w求偏导的那个公式:
从而求出
w
w
w
将 w w w 代入超平面的表达式,计算 b b b 值;
现在的 w , b w,b w,b 就是我们要寻找的最优超平面的参数。
3.2.3 整体流程确定
4 举例
四、SVM的损失函数
在SVM中,我们主要讨论三种损失函数:
五、SVM的核方法
【SVM + 核函数】 具有极大威力。
核函数并不是SVM特有的,核函数可以和其他算法也进行结合,只是核函数与SVM结合的优势非常大。
1 什么是核函数
1.1 核函数概念
核函数,是将原始输入空间映射到新的特征空间,从而,使得原本线性不可分的样本可能在核空间可分。
下图所示的两类数据,分别分布为两个圆圈的形状,这样的数据本身就是线性不可分的,此时该如何把这两类数据分开呢?
- 假设X是输入空间,
- H是特征空间,
- 存在一个映射 ϕ ϕ ϕ使得X中的点x能够计算得到H空间中的点h,
- 对于所有的X中的点都成立:
h = ϕ ( x ) h=\phi(x) h=ϕ(x)
若x,z是X空间中的点,函数k(x,z)满足下述条件,那么都成立,则称k为核函数,而
ϕ
ϕ
ϕ为映射函数:
k
(
x
,
z
)
=
ϕ
(
x
)
ϕ
(
z
)
k(x,z)=\phi(x)\phi(z)
k(x,z)=ϕ(x)ϕ(z)
1.2 核函数举例
1.2.1 核方法举例1
1.2.2 核方法举例2
- 下面这张图位于第一、二象限内。我们关注红色的门,以及“北京四合院”这几个字和下面的紫色的字母。
- 我们把红色的门上的点看成是“+”数据,字母上的点看成是“-”数据,它们的横、纵坐标是两个特征。
- 显然,在这个二维空间内,“+”“-”两类数据不是线性可分的。
2 常见核函数
1.多项核中,d=1时,退化为线性核;
2.高斯核亦称为RBF核。
六、SVM回归
SVM回归是让尽可能多的实例位于预测线上,同时限制间隔违例(也就是不在预测线距上的实例)。
线距的宽度由超参数
ϵ
\epsilon
ϵ控制。
七、SVM算法api再介绍
1 SVM算法api综述
- SVM方法既可以用于分类(二/多分类),也可用于回归和异常值检测。
- SVM具有良好的鲁棒性,对未知数据拥有很强的泛化能力,特别是在数据量较少的情况下,相较其他传统机器学习算法具有更优的性能。
使用SVM作为模型时,通常采用如下流程:
- 对样本数据进行归一化
- 应用核函数对样本进行映射 (最常采用和核函数是RBF和Linear,在样本线性可分时,Linear效果要比RBF好)
- 用cross-validation和grid-search对超参数进行优选
- 用最优参数训练得到模型
- 测试
sklearn中支持向量分类主要有三种方法:SVC、NuSVC、LinearSVC,扩展为三个支持向量回归方法:SVR、NuSVR、LinearSVR。
- SVC和NuSVC方法基本一致,唯一区别就是损失函数的度量方式不同
- NuSVC中的nu参数和SVC中的C参数;
- LinearSVC是实现线性核函数的支持向量分类,没有kernel参数。
2 SVC
3 NuSVC
4 LinearSVC
八、案例:数字识别器
1 案例背景介绍
MNIST(“修改后的国家标准与技术研究所”)是计算机视觉事实上的“hello world”数据集。自1999年发布以来,这一经典的手写图像数据集已成为分类算法基准测试的基础。随着新的机器学习技术的出现,MNIST仍然是研究人员和学习者的可靠资源。
本次案例中,我们的目标是从数万个手写图像的数据集中正确识别数字。
2 数据介绍
数据文件train.csv和test.csv包含从0到9的手绘数字的灰度图像。
每个图像的高度为28个像素,宽度为28个像素,总共为784个像素。
每个像素具有与其相关联的单个像素值,指示该像素的亮度或暗度,较高的数字意味着较暗。该像素值是0到255之间的整数,包括0和255。
训练数据集(train.csv)有785列。第一列称为“标签”,是用户绘制的数字。其余列包含关联图像的像素值。
训练集中的每个像素列都具有像pixelx这样的名称,其中x是0到783之间的整数,包括0和783。为了在图像上定位该像素,假设我们已经将x分解为x = i * 28 + j,其中i和j是0到27之间的整数,包括0和27。然后,pixelx位于28 x 28矩阵的第i行和第j列上(索引为零)。
例如,pixel31表示从左边开始的第四列中的像素,以及从顶部开始的第二行,如下面的ascii图中所示。
在视觉上,如果我们省略“像素”前缀,像素组成图像如下:
000 001 002 003 ... 026 027
028 029 030 031 ... 054 055
056 057 058 059 ... 082 083
| | | | ...... | |
728 729 730 731 ... 754 755
756 757 758 759 ... 782 783
测试数据集(test.csv)与训练集相同,只是它不包含“标签(label)”列。
3 案例实现
MNIST手写数据集
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.model_selection import train_test_split
获取数据
train = pd.read_csv("./data/train.csv")
确定特征值\目标值
train_image = train.iloc[:, 1:]
train_label = train.iloc[:, 0]
查看具体图像
num = train_image.iloc[0].values.reshape(28, 28)
plt.imshow(num)
plt.axis("off")
plt.show()
封装成函数
def to_plot(n):
num = train_image.iloc[n].values.reshape(28, 28)
plt.imshow(num)
plt.axis("off")
plt.show()
to_plot(n=40)
数据归一化处理
# 对数据特征值归一化处理
train_image = train_image.values / 255
train_label = train_label.values
数据集分割
x_train, x_val, y_train, y_val = train_test_split(train_image, train_label, train_size = 0.8, random_state=0)
特征降维和模型训练
import time
from sklearn.decomposition import PCA
# 多次使用pca,确定最后的最优模型
def n_components_analysis(n, x_train, y_train, x_val, y_val):
# 记录开始时间
start = time.time()
# pca降维实现
pca = PCA(n_components=n)
print("特征降维,传递的参数为:{}".format(n))
pca.fit(x_train)
# 在训练集和测试集进行降维
x_train_pca = pca.transform(x_train)
x_val_pca = pca.transform(x_val)
# 利用svc进行训练
print("开始使用svc进行训练")
ss = svm.SVC()
ss.fit(x_train_pca, y_train)
# 获取accuracy结果
accuracy = ss.score(x_val_pca, y_val)
# 记录结束时间
end = time.time()
print("准确率是:{}, 消耗时间是:{}s".format(accuracy, int(end-start)))
return accuracy
# 传递多个n_components,寻找合理的n_components:
n_s = np.linspace(0.70, 0.85, num=5)
accuracy = []
for n in n_s:
tmp = n_components_analysis(n, x_train, y_train, x_val, y_val)
accuracy.append(tmp)
运行结果:
# 准确率可视化展示
plt.plot(n_s, np.array(accuracy), "r")
plt.show()
经过图形展示,选择合理的n_components, 最后综合考虑确定结果为:0.80
确定最优模型
pca = PCA(n_components=0.80)
pca.fit(x_train)
pca.n_components_
# 43
x_train_pca = pca.transform(x_train)
x_val_pca = pca.transform(x_val)
# 训练比较优的模型,计算accuracy
ss1 = svm.SVC()
ss1.fit(x_train_pca, y_train)
ss1.score(x_val_pca, y_val)
# 0.979047619047619
练习:用MNIST手写数据集的测试集测试模型的精度
九、SVM总结
1 SVM基本综述
-
SVM是一种二类分类模型。
-
它的基本模型是在特征空间中寻找间隔最大化的分离超平面的线性分类器。
1)当训练样本线性可分时,通过硬间隔最大化,学习一个线性分类器,即线性可分支持向量机;
2)当训练数据近似线性可分时,引入松弛变量,通过软间隔最大化,学习一个线性分类器,即线性支持向量机;
3)当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习非线性支持向量机。
2 SVM优缺点:
-
SVM的优点:
- 在高维空间中非常高效;
- 即使在数据维度比样本数量大的情况下仍然有效;
- 在决策函数(称为支持向量)中使用训练集的子集,因此它也是高效利用内存的;
- 通用性:不同的核函数与特定的决策函数一一对应;
-
SVM的缺点:
- 如果特征数量比样本数量大得多,在选择核函数时要避免过拟合;
- 对缺失数据敏感;
- 对于核函数的高维映射解释力不强
上一篇:机器学习:朴素贝叶斯
下一篇:机器学习:EM算法