支持向量机SVM
间隔与支持向量
对于分类学习的想法就是基于训练集在样本空间
D
D
D中找到一个划分超平面,将不同类别得样本分开。但超平面有很多,如何找个一个合适的超平面呢?划分超平面应该对训练样本局部扰动的容忍性最好, 在样本空间中,划分超平面可由如下线性方程描述:
w
T
x
+
b
=
0
w^Tx+b=0
wTx+b=0
其中w和b决定了划分超平面。样本空间中任意点到超平面的距离有(点到直线的距离公式):
r
=
∣
w
T
x
+
b
∣
∣
∣
w
∣
∣
r=\frac{|w^Tx+b|}{||w||}
r=∣∣w∣∣∣wTx+b∣
其中 ∣ ∣ w ∣ ∣ = ∑ j = 1 w j 2 ||w||=\sqrt{\sum_{j=1}{w_j^2}} ∣∣w∣∣=j=1∑wj2
若超平面能将训练样本正确划分,即对 ( x i , y i ) (x_i,y_i) (xi,yi)属于 D D D,若 w T + b > 0 w^T+b>0 wT+b>0, 则 y i = + 1 y_i=+1 yi=+1,若 w T + b < = − 1 w^T+b<=-1 wT+b<=−1,则 y i = − 1 y_i=-1 yi=−1。令(缩放变化):
w T + b > = + 1 , y i = + 1 w^T+b>=+1, y_i=+1 wT+b>=+1,yi=+1
w T + b < = − 1 , y i = − 1 w^T+b<=-1,y_i=-1 wT+b<=−1,yi=−1
距离超平面最近的几个训练样本点使式的等号成立,它们被称为“支持向量”,两个异类支持向量到超平面的和称为间隔:
2
∣
∣
w
∣
∣
=
γ
\frac{2}{||w||} = \gamma
∣∣w∣∣2=γ
欲找到具有“最大间隔”的划分超平面,也就是找满足上诉不等式中的约束参数w和b。通过二次规划,拉格朗日乘子法得其对偶问题求解。这里不深入推导了。
训练支持向量机有一个重要的特性,就是训练完后大部分训练样本不必保存,最终的模型仅与支持向量有关。
核函数
现实世界中,原始样本空间可能不存在一个能够正确划分样本的超平面,如“异或”问题。 对此我们将原始空间映射到一个更高维度的特征空间中,使得样本在这个特征空间内线性可分。通过映射函数将样本映射到高维的特征空间,并在新的特征空间中训练SVM。特征映射到新的特征空间内往往维度很高,无法直接计算。因此我们通过核函数来避免高维度的运算。有多种核函数可选择。
- 线性核 (linear)
- 高斯核(RBF)
- 多项式核 (poly)
- sigmoid核
软间隔与正则化
前面的叙述我们一直假定样本空间式线性可分得,即存在一个超平面能将不同的类完全划分,然后现实很难找到这样的划分超平面,所有引入软间隔概念。(数学理解不在此讨论) 总而概知,为解决非线性问题,我们放松线性约束条件,以保证在适当的惩项成本下,对错误分类的情况进行优化时能够收敛。引入松弛变量ξ
w
T
x
(
i
)
>
=
1
,
y
(
i
)
=
1
−
ξ
(
i
)
w^Tx^{(i)}>=1, y^{(i)}=1-\xi^{(i)}
wTx(i)>=1,y(i)=1−ξ(i)
w T x ( i ) < = 1 , y ( i ) = 1 + ξ ( i ) w^Tx^{(i)}<=1, y^{(i)}=1+\xi^{(i)} wTx(i)<=1,y(i)=1+ξ(i)
每个样本对于一个松弛变量ξ,在新的约束条件下,新的优化目标为最小值化下式:
1 2 ∣ ∣ w ∣ ∣ 2 + C ( ∑ i ξ ( i ) ) \frac{1}{2}||w||^2+C(\sum_{i}{\xi^{(i)}}) 21∣∣w∣∣2+C(i∑ξ(i))
通过变量C,我们可以控制对错误分类的惩罚程度,C值较大时,对应大的错误惩罚,C值较小时,则对错误分类的惩罚较低。
下面使用svm实现对异或问题的分类:
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(0)
X_xor = np.random.randn(200, 2)
y_xor = np.logical_xor(X_xor[:, 0] > 0, X_xor[:, 1] > 0)#异或
y_xor = np.where(y_xor, 1, -1)
plt.scatter(X_xor[y_xor == 1, 0], X_xor[y_xor == 1, 1], c='b', marker='x', label='1')
plt.scatter(X_xor[y_xor == -1, 0], X_xor[y_xor == -1, 1], c='r', marker='o', label='-1')
plt.legend()
plt.show()
'''
gamma : float,optional(默认='auto')
当前默认值为'auto',它使用1 / n_features,如果gamma='scale'传递,则使用1 /(n_features * X.std())作为gamma的值。
当前默认的gamma''auto'将在版本0.22中更改为'scale'。'auto_deprecated','auto'的弃用版本用作默认值,表示没有传递明确的gamma值。
coef0 : float,optional(默认值= 0.0)
核函数中的独立项。它只在'poly'和'sigmoid'中很重要。
degree :多项式poly核函数的维度
'''
svm = SVC(kernel='rbf', random_state=0, gamma=0.1, C=10.0)#使用rbf核函数,映射到高维度寻找划分超平面,gamma过大会决策边界紧凑,可能会产生过拟合。
svm.fit(X_xor, y_xor)
#画图
h = 0.01
x_min, x_max = X_xor[:, 0].min() - 1, X_xor[:, 0].max() + 1
y_min, y_max = X_xor[:, 1].min() - 1, X_xor[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))#一维数组变为矩阵将第一个变为行向量,第二个为列向量
Z = svm.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X_xor[y_xor == 1, 0], X_xor[y_xor == 1, 1], c='b', marker='x', label='1')
plt.scatter(X_xor[y_xor == -1, 0], X_xor[y_xor == -1, 1], c='r', marker='o', label='-1')
plt.show()