入门机器学习(西瓜书+南瓜书)支持向量机总结(python代码实现)
一、支持向量机
1.1 通俗理解
通俗来说,支持向量机这玩意就是用一条直线把不同的样本的分开,具体可以看下图。可以看到就目前的数据分布,我们可以找到非常多的直线都可以很容易把样本分开。那么这么多的直线那一条最好呢?更直白点,那一条我预测数据出错率最低呢?答案就是下图中间的那一条(正式说法这条直线也叫超平面),可以看到这条直线距离两侧的“边界”样本的距离都是最大且相等的(正式说法把两侧的距离之和叫做间隔,也就是图片上的
2
∣
∣
w
∣
∣
\frac{2}{||w||}
∣∣w∣∣2)。个人理解就是这样给与两侧样本合理公平划分“38线”,因此理论上泛化性能最好。这也就是支持向量机的雏形。
那么啥叫支持向量呢?实际上,支持向量也就是距离超平面最近的点的直线,也就是图中虚线所示的两条直线。他们决定了这条直线的位置,换句话说直线的位置仅与支持向量有关。因此这个模型也叫做支持向量机。
这里面还有一个说法是软间隔和硬间隔。什么意思呢?我们通俗理解硬间隔就是标准强硬,不容有丝毫错误,这条直线必须把我给的样本完美分开。而软间隔就是反过来容许直线出错。把一些样本划分错误,这样会提升模型的泛化性能。如下图所示。
还有提到支持向量机不可回避的问题,也是支持向量机的核心方法——核函数,我们回顾上节课说到的单层感知机基于线性模型存在的“线性不可分问题”。支持向量机基于线性方法当然也存在这个问题,其中最为著名的“线性不可分问题”就是异或问题,由1969年,马文明斯基提出,可以看到直线划分可以轻而易举地划分“与”,“或”,“非”,但是对于“异或”问题束手无策。这也导致基于感知机的神经网络陷入冷静期。但是同样基于感知机的支持向量机先于神经网络提出了核函数方法,成功地解决了线性不可分,因此再一次成为了AI界的宠儿。但是这对于神经网络来说遭到了进一步的冷落,甚至国际会议在这个时期,一律不接受有关神经网络的论文。从中足见支持向量机的地位。
那么说的这么玄乎,导致这个使得支持向量机封神的“核函数”是何方神圣呢?其实很简单,就是增加数据维度,你不是二维不可分吗?我构建一个三维的,大家看上面的(d)图想象把两侧的值为0的(0,0)点和(1,1)点从屏幕中揪出来,浮在空中的一个平面内,这样我是不是就可以在屏幕和浮在空中的平面内找到一个平面把它们划分好了吗?,而且我同样可以让这个平面距离两侧的平面具体最大且相等。下面附上下图便于读者理解。注意到了吧,这里的是一个平面哦。这样也就更能理解,为什么把一条划分的直线叫做超平面了。当然揪出来只是便于读者理解的一个描述罢了,核函数的具体构造具有具体的函数形式。
1.2 理论分析
1.2.1 间隔方程
如下图所示,红线代表间隔方程,若超平面(w,b)可以将样本正确分类,则
{
w
T
x
i
+
b
>
=
1
,
y
i
=
1
w
T
x
i
+
b
<
=
−
1
,
y
i
=
−
1
\left\{ \begin{aligned} w^Tx_{i} + b & >= 1 ,y_{i}=1 \\ w^Tx_{i} + b & <= -1 ,y_{i}=-1 \\ \end{aligned} \right.
{wTxi+bwTxi+b>=1,yi=1<=−1,yi=−1
其中两个式子化作等式即为支持向量,上述式子等价于
y
i
(
w
T
x
i
+
b
)
>
=
1
y_{i}(w^Tx_{i}+b)>=1
yi(wTxi+b)>=1,两个支持向量的间隔就是
γ
=
2
∣
∣
w
∣
∣
\gamma=\frac{2}{||w||}
γ=∣∣w∣∣2.
其中的SVM算法:
m
a
x
w
,
b
2
∣
∣
w
∣
∣
,
s
.
t
(
y
i
(
w
T
x
i
+
b
)
>
=
1
)
max_{w,b}\frac{2}{||w||},s.t (y_{i}(w^Tx_{i}+b)>=1)
maxw,b∣∣w∣∣2,s.t(yi(wTxi+b)>=1)
举个栗子,给大家补补(doge),比如现在,我手里有三个正样本和三个负样本,正样本的坐标为
(
0
,
0
)
,
(
1
,
0
)
,
(
0
,
1
)
(0,0),(1,0),(0,1)
(0,0),(1,0),(0,1),负样本的坐标为
(
1
,
1
)
,
(
2
,
1
)
,
(
1
,
2
)
(1,1),(2,1),(1,2)
(1,1),(2,1),(1,2).那么把样本放在二维坐标图,如图所示。经过优化获得的支持向量假如是
y
=
x
,
y
=
1
,
x
=
1
y=x,y=1,x=1
y=x,y=1,x=1。
我们假设最优的分类界限为
w
1
x
1
+
w
2
x
2
+
b
=
0
w1x1+w2x2+b=0
w1x1+w2x2+b=0,带入获得支持向量可得。
{
w
1
+
w
2
+
b
=
−
1
w
1
+
b
=
1
w
2
+
b
=
1
\left\{ \begin{aligned} w_{1}+w_{2}+b&=-1 \\ w_{1}+b&=1 \\ w_{2}+b&=1 \\ \end{aligned} \right.
⎩
⎨
⎧w1+w2+bw1+bw2+b=−1=1=1
最终的最优分类曲线为
−
2
x
1
−
2
x
2
+
3
=
0
-2x_{1}-2x_{2}+3=0
−2x1−2x2+3=0
分隔为:
γ
=
2
∣
∣
w
∣
∣
=
2
2
\gamma=\frac{2}{||w||}=\frac{\sqrt{2}}{2}
γ=∣∣w∣∣2=22
那么最优化的间隔就是最大化分隔.
由于梯度下降法更适合解决求最小值问题.因此把最优化目标转化为如下所示
{
m
a
x
w
,
b
2
∣
∣
w
∣
∣
,
s
.
t
(
y
i
(
w
T
x
i
+
b
)
>
=
1
)
,
i
=
1
,
2
,
.
.
.
,
m
m
i
n
w
,
b
1
2
∣
∣
w
∣
∣
2
,
s
.
t
(
y
i
(
w
T
x
i
+
b
)
>
=
1
)
,
i
=
1
,
2
,
.
.
.
,
m
\left\{ \begin{aligned} max_{w,b}\frac{2}{||w||},s.t (y_{i}(w^Tx_{i}+b)&>=1),i=1,2,...,m\\ min_{w,b}\frac{1}{2}||w||^2,s.t (y_{i}(w^Tx_{i}+b)&>=1),i=1,2,...,m\\ \end{aligned} \right.
⎩
⎨
⎧maxw,b∣∣w∣∣2,s.t(yi(wTxi+b)minw,b21∣∣w∣∣2,s.t(yi(wTxi+b)>=1),i=1,2,...,m>=1),i=1,2,...,m
这就是支持向量机的基本型。后期的工作就是加入等式约束和不等式约束,利用拉格朗日子乘法。构造函数,求出偏导数,将偏导数等于零,然后会带出结果,其中还包括SMO算法等方法,这里笔者水平有限,不敢乱讲。也怕大家听不懂打我。
就说下最后的结论吧,最后的式子是
f
(
x
)
=
w
T
x
+
b
=
∑
i
=
1
m
α
i
y
i
x
i
T
x
+
b
f(x)=w^Tx+b=\sum_{i=1}^{m}\alpha_{i}y_{i}x^T_{i}{x}+b
f(x)=wTx+b=∑i=1mαiyixiTx+b
训练完成后,最终模型仅与支持向量有关。
1.2.2 硬间隔和软间隔
那么软间隔和硬间隔如何在优化函数上体现呢?
也就是最大化间隔的同时,
m
i
n
w
,
b
1
2
∣
∣
w
∣
∣
2
+
C
∑
i
=
1
m
l
0
/
1
(
y
i
(
w
T
x
i
+
b
)
>
=
1
)
min_{w,b}\frac{1}{2}||w||^2+C\sum_{i=1}^{m}l_{0/1}(y_{i}(w^Tx_{i}+b)>=1)
minw,b21∣∣w∣∣2+C∑i=1ml0/1(yi(wTxi+b)>=1)
其中,
l
0
/
1
l_{0/1}
l0/1是0/1损失函数
(
0
/
1
l
o
s
s
f
u
n
c
t
i
o
n
)
(0/1 loss function)
(0/1lossfunction)
l
0
/
1
(
z
)
=
{
1
,
i
f
(
z
<
0
)
0
,
e
l
s
e
l_{0/1}(z)=\left\{ \begin{aligned} 1&,if (z<0)\\ 0&,else\\ \end{aligned} \right.
l0/1(z)={10,if(z<0),else
当C越大时,一旦模型分类错误会获得一个较大的惩罚项,也就是硬间隔。而C越小时,也就是默认模型可以分类一些错误。这也就是软间隔。
1.2.3 核函数
核函数就是把样本
x
x
x映射为
ϕ
(
x
)
\phi(x)
ϕ(x)
对
f
(
x
)
=
w
T
x
+
b
=
∑
i
=
1
m
α
i
y
i
x
i
T
x
+
b
f(x)=w^Tx+b=\sum_{i=1}^{m}\alpha_{i}y_{i}x^T_{i}{x}+b
f(x)=wTx+b=∑i=1mαiyixiTx+b来说就变为
f
(
x
)
=
w
T
x
+
b
=
∑
i
=
1
m
α
i
y
i
ϕ
(
x
i
)
T
ϕ
(
x
)
+
b
f(x)=w^Tx+b=\sum_{i=1}^{m}\alpha_{i}y_{i}\phi(x_{i})^T\phi(x)+b
f(x)=wTx+b=∑i=1mαiyiϕ(xi)Tϕ(x)+b
其中这个
ϕ
(
x
i
)
T
ϕ
(
x
)
\phi(x_{i})^T\phi(x)
ϕ(xi)Tϕ(x)就是所谓的核函数。
定义为
k
(
x
i
,
x
j
)
=
ϕ
(
x
i
)
T
ϕ
(
x
)
k(x_{i},x_{j})=\phi(x_{i})^T\phi(x)
k(xi,xj)=ϕ(xi)Tϕ(x),那么核函数的选择称为支持向量机性能的关键。
下面附上常用的几种核函数
使用核函数的基本经验就是:文本数据采用线性核,情况不明先尝试高斯核。
以上就是支持向量机的全部基本内容,具体的公式推导请详见西瓜书第122页,南瓜书第30页,以及南瓜书支持向量机对应配套视频和软间隔和支持向量回归
二、代码实现
这里附上一个简单的代码,后续的代码小程序员放在百度网盘里,大家自行下载。
链接:https://pan.baidu.com/s/1Ce14ZQYEYWJxhpNEP1ERhg?pwd=7mvf
提取码:7mvf
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
data = load_iris()
x = data.data
y = data.target
x = x[y<2,:2]
y = y[y<2]
plt.scatter(x[y==0,0],x[y==0,1],color='red',marker='x')
plt.scatter(x[y==1,0],x[y==1,1],color='blue')
plt.legend(labels=['c1','c2'],loc='upper left')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()#将原始数据映射到均值为0、标准差为1的分布上
scaler.fit(x)
x = scaler.transform(x)
from sklearn.svm import LinearSVC
svc = LinearSVC(C=1)
svc.fit(x,y)
print(svc.coef_)
print(svc.intercept_)
#[[ 1.69023462 -1.23470856]] 斜率
#[0.27241557] 截距
plt.scatter(x[y==0,0],x[y==0,1],color='red',marker='x')
plt.scatter(x[y==1,0],x[y==1,1],color='blue')
plt.legend(labels=['c1','c2'],loc='upper left')
x_min=x[:,0].min()
x_max=x[:,0].max()
y_min=-(x_min*svc.coef_[0][0]+svc.intercept_)/svc.coef_[0][1]
y_max=-(x_max*svc.coef_[0][0]+svc.intercept_)/svc.coef_[0][1]
y_min_up=(1-x_min*svc.coef_[0][0]-svc.intercept_)/svc.coef_[0][1]
y_max_up=(1-x_max*svc.coef_[0][0]-svc.intercept_)/svc.coef_[0][1]
y_min_down=(-1-x_min*svc.coef_[0][0]-svc.intercept_)/svc.coef_[0][1]
y_max_down=(-1-x_max*svc.coef_[0][0]-svc.intercept_)/svc.coef_[0][1]
plt.plot([x_min,x_max],[y_min,y_max])
plt.plot([x_min,x_max],[y_min_up,y_max_up])
plt.plot([x_min,x_max],[y_min_down,y_max_down])
plt.xlabel('x')
plt.ylabel('y')
plt.show()
运行结果为
三、代码文件
小程序员将代码文件和相关素材整理到了百度网盘里,因为文件大小基本不大,大家也不用担心限速问题。后期小程序员有能力的话,将在gitee或者github上上传相关素材。
链接:https://pan.baidu.com/s/1Ce14ZQYEYWJxhpNEP1ERhg?pwd=7mvf
提取码:7mvf