SVM(支持向量机)
引言
支持向量机(Support Vector Machine,SVM),可以用来解答二分类问题。支持向量(Support Vector):把划分数据的决策边界叫做超平面,点到超平面的距离叫做间隔。在SVM中,距离超平面最近的且满足一定条件的几个训练样本点被称为支持向量。
图中,被圈出来的就是支持向量。支持向量机是要使超平面和支持向量之间的间隔尽可能的大,这样才能使两类样本尽可能地分开。
间隔又分为硬间隔和软间隔。
- 硬间隔
在使用超平面进行分割数据时,严格地让所有实例都不在最大间隔之间,并且位于正确的一遍,就是硬间隔。
硬间隔存在的问题:1.只在数据线性可分时有效 2.对异常值非常敏感。
- 软间隔
要避免硬间隔存在的问题,目标是尽可能在保持最大间隔宽阔和限制间隔违例之间找到良好平衡。
SVM存在以下优点:
SVM通过优化一个凸二次规划问题来求解最佳的超平面,其中包括最小化模型的复杂度,同时限制训练样本的误分类情况。
我们将支持向量机的判别面、支持面表示为:
w
x
+
b
=
±
1
w
x
+
b
=
0
wx+b= \pm 1\\ wx+b = 0
wx+b=±1wx+b=0
从而可以算得,支持面和判别面的距离为
d
=
1
∣
∣
w
∣
∣
d = \frac{1}{||w||}
d=∣∣w∣∣1
在使用SVM模型时,由于SVM的支持面与判别面的距离为
d
=
1
∣
∣
w
∣
∣
d = \frac{1}{||w||}
d=∣∣w∣∣1,所以两个支持面的距离为
2
d
=
2
∣
∣
w
∣
∣
2d=\frac{2}{||w||}
2d=∣∣w∣∣2最大化两支持面之间的距离
2
∣
∣
w
∣
∣
\frac{2}{||w||}
∣∣w∣∣2,等价于最小化
∣
∣
w
∣
∣
2
2
(
给
∣
∣
w
∣
∣
加平方是为了去除根号
)
\frac{||w||^2}{2}(给{||w||}加平方是为了去除根号)
2∣∣w∣∣2(给∣∣w∣∣加平方是为了去除根号)
-
硬间隔SVM的损失函数
硬间隔SVM最大化支持面之间的距离,并要求所有样本在支持面之外。因此,硬间隔的损失函数如下:
目标函数:
L ( w , b ) = 1 2 ∣ ∣ w ∣ ∣ 2 L(w,b)=\frac{1}{2}||w||^2 L(w,b)=21∣∣w∣∣2
约束条件:
y i ( w x i + b ) − 1 ≥ 0 , i = 1 , 2 , . . . . . , N y_i(wx_i+b)−1 \geq 0 , i=1,2,.....,N yi(wxi+b)−1≥0,i=1,2,.....,N正样本要在正支持面一侧,即 w x i + b ≥ 1 wx_i+b \geq 1 wxi+b≥1,此时 y i = 1 y_i = 1 yi=1,可得 y i ( w x i + b ) − 1 ≥ 0 y_i(wx_i + b)-1 \geq 0 yi(wxi+b)−1≥0
负样本要在负支持面一侧,即 w x i + b ≤ − 1 wx_i+b \leq -1 wxi+b≤−1,此时 y i = − 1 y_i = -1 yi=−1 ,可得 y i ( w x i + b ) − 1 ≥ 0 y_i(wx_i+b)-1 \geq 0 yi(wxi+b)−1≥0 -
软间隔SVM的损失函数
软间隔SVM最小化支持面之间的距离,并最小化错误样本,因此软间隔的损失函数如下:
目标函数:
L ( w , b , ξ ) = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i L(w,b,\xi) = \frac {1}{2}||w||^2 + C \sum_{i=1}^{N} \xi _i L(w,b,ξ)=21∣∣w∣∣2+Ci=1∑Nξi
约束条件:
(1) y i ( w x i + b ) − ( 1 − ξ i ) ≥ 0 , i = 1 , 2 , . . . . . . . , N y_i(wx_i+b)-(1-\xi_i) \geq 0,i=1,2,.......,N yi(wxi+b)−(1−ξi)≥0,i=1,2,.......,N
(2) ξ i ≥ 0 , i = 1 , 2 , . . . . . . , N \xi_i \geq 0 ,i=1,2,......,N ξi≥0,i=1,2,......,N
其中 ξ i \xi_i ξi是对i个样本的松弛量,而C是惩罚因子。随着支持面的不同取值,有的样本能在支持面正确一侧,有的则在错误一侧,不妨记 ξ i \xi_i ξi为第i个样本的误错量,则第i个样本满足 y i ( w x i + b ) − ( 1 − ξ i ) ≥ 0 y_i(wx_i+b)-(1-\xi_i)\geq0 yi(wxi+b)−(1−ξi)≥0
然后目标函数是最小化所有样本的误错量 C ∑ i = 1 N ξ i C\sum_{i=1}^N\xi_i C∑i=1Nξi,其中C是错误量在损失函数中的权重。
SVM的损失函数中带有各种约束条件,难以用一般的方法进行求解,因此可以考虑使用下面的方法:
- 先将损失函数转化为拉格朗日形式
- 通过拉格朗日形式获得损失函数的对偶问题
- 使用SOM算法求得对偶问题的解
- 将对偶问题的解转换回原问题的解
下面是对软间隔问题的求解
将SVM软间隔模型的损失函数化为拉格朗日函数形式为:
L
(
w
,
b
,
ξ
,
α
,
μ
)
=
1
2
∣
∣
w
∣
∣
2
−
∑
i
=
1
N
α
i
y
i
(
w
x
i
+
b
)
+
∑
i
=
1
N
α
i
−
∑
i
=
1
N
(
C
−
α
i
−
μ
i
)
ξ
i
L(w,b,\xi,\alpha,\mu) = \frac{1}{2}||w||^2 - \sum_{i=1}^N \alpha_i y_i(wx_i+b)+\sum_{i=1}^N \alpha_i - \sum _{i=1}^N(C - \alpha_i -\mu_i)\xi_i
L(w,b,ξ,α,μ)=21∣∣w∣∣2−i=1∑Nαiyi(wxi+b)+i=1∑Nαi−i=1∑N(C−αi−μi)ξi
其中
α
i
≥
0
,
μ
i
≥
0
\alpha_i \geq 0,\mu_i \geq 0
αi≥0,μi≥0
SVM损失函数的对偶问题:
目标函数:
m
i
n
1
2
∑
i
=
1
N
∑
j
=
1
N
α
i
α
j
y
i
y
j
(
x
i
T
⋅
x
j
)
−
∑
i
=
1
N
α
i
min\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_j y_i y_j(x_i^T \cdot x_j) - \sum_{i=1}^N \alpha_i
min21i=1∑Nj=1∑Nαiαjyiyj(xiT⋅xj)−i=1∑Nαi
约束条件:
(1) ∑ i = 1 N α i y i = 0 \sum_{i=1}^N \alpha_i y_i = 0 ∑i=1Nαiyi=0
(2) C ≥ α i ≥ 0 , ( i = 1 , 2....... N ) C\geq\alpha_i\geq0,(i=1,2.......N) C≥αi≥0,(i=1,2.......N)
解得损失函数对偶问题
α
i
\alpha_i
αi之后,按下式可以转回原问题的解w、b
w
=
∑
i
=
1
N
α
i
y
i
x
i
b
=
A
v
g
(
y
i
−
∑
j
=
1
N
α
j
y
j
(
x
j
T
⋅
x
i
)
)
w = \sum_{i=1}^N\alpha_i y_i x_i \\ b = Avg(y_i - \sum_{j=1}^N\alpha_j y_j (x_j^T \cdot x_i))
w=i=1∑Nαiyixib=Avg(yi−j=1∑Nαjyj(xjT⋅xi))
最终,SVM的模型解由对偶问题的解所给出,可以写为:
g
=
w
x
+
b
,其中
w
=
∑
i
=
1
N
α
i
y
i
x
i
b
=
A
v
g
(
y
i
−
∑
j
=
1
N
α
j
y
j
(
x
j
T
⋅
x
i
)
)
g = wx+b,其中\\ w = \sum_{i=1}^N \alpha_i y_i x_i \\ b = Avg(y_i - \sum_{j=1}^N\alpha_j y_j(x_j^T \cdot x_i))
g=wx+b,其中w=i=1∑Nαiyixib=Avg(yi−j=1∑Nαjyj(xjT⋅xi))
忽略掉
α
i
=
0
\alpha_i = 0
αi=0的项,可以看到模型是由所有
α
i
>
0
\alpha_i > 0
αi>0 样本来共同表示,也就是
α
i
>
0
\alpha_i >0
αi>0的样本构成了最终的判别函数,因此称
α
i
>
0
\alpha_i > 0
αi>0的样本为支持向量。
几何意义:支持向量是落在支持面上及支持面错误一侧的样本
支持向量是我们所需要关注的样本,它们都是模型决策较为模糊、错误的样本。
由于模型的w,b实际只由支持向量构成,这就是为什么把模型称为"支持向量机SVM"的原因
代码
from sklearn import svm
import numpy as np
# ----生成样本数据与构建SVM模型-----------
X = np.array( [[0.708333,1],[0.291667,1],[0.217,1.5],[0.2367,0.3],[0.454,1]
,[0.583333,-4],[0.875,-1],[0.333,-0.6],[0.111,-1]] )
y = np.array([1,1,1,1,1,-1,-1,-1,-1])
clf = svm.SVC(kernel ='linear',C=1000) # 初始SVM模型,这里C设为很大,也就成为了硬间隔
clf.fit(X,y) # 用X,y训练模型
# -----------------打印模型系数------------
print('\n---------支持向量与alpha--------') # 打印模型求解结果
print('support_vectors:\n',clf.support_vectors_) # 打印支持向量
print('alpha:\n' ,clf.dual_coef_[0]) # 打印支持向量系数
print("\n----------模型系数---------")
w = clf.coef_ # 提取模型系数w,它等于clf.dual_coef_[0]@clf.support_vectors_
b = -clf._intercept_ # 提取模型系数b
print('w:',w) # 打印模型系数w
print('b:',b) # 打印模型阈值b
# ---画出分割面与支持面-----------------
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (9, 5) # 设置figure_size尺寸
plt.scatter(X[:, 0], X[:, 1],c=y,marker='o') # 画出样本点
line_x = np.array([X[:,0].min(),X[:,0].max()]) # 判别面的x坐标
line_y = (-b-w[0,0]*line_x)/w[0,1] # 判别面的y坐标
plt.plot(line_x,line_y) # 画出判别面
line_u = (-b+1-w[0,0]*line_x)/w[0,1] # 上支持面的y坐标
line_b = (-b-1-w[0,0]*line_x)/w[0,1] # 下支持面的y坐标
plt.plot(line_x,line_u,color='grey') # 画出上支持面
plt.plot(line_x,line_b,color='grey') # 画出下支持面
#在代码中,我们将松驰惩罚系数C设得非常大(C=1000),相当于使用了硬间隔模型
---------支持向量与alpha--------
support_vectors:
[[ 0.333 -0.6 ]
[ 0.2367 0.3 ]]
alpha:
[-2.44118665 2.44118665]
----------模型系数---------
w: [[-0.23508627 2.19706799]]
b: [0.39652452]
参考
老饼讲解
CSDN博客
代码