SVM支持向量机分类模型SVC理论+python sklean.svm实践

支持向量机是啥

有一次公司项目上的同事一起吃饭(面前是一锅炒土鸡),提到了支持向量机,学文的同事就问支持向量机是什么,另一个数学物理大牛想了一下,然后说,一种鸡。。。

确实很难一句话解释清楚这只鸡。。。support vector machine从字面意思来说应该是依靠support vector来划分数据(其实也能回归啦。。)的机器学习模型。它是一个凸优化问题。

SVM的核心将数据的特征投射到高维,然后找到超平面,分割不同类别的数据点,而且要使分离的程度越大越好,至于为什么叫支持向量机,是因为每个类别都会有一些数据点作为支撑向量,这些支撑向量决定了最后分割的超平面。
![@线性可分示意图|300x200]
(https://img-blog.youkuaiyun.com/20171116151440572?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3VtbWVyU3RvbmVT/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

这个图里的圈圈就是两边的支撑向量。

线性可分支持向量机

我们先讲最简单的情况,也就是线性可分的平面二分类问题。
支持向量机的目标是,找到一条分界线,把两类数据分开。但是这样的线可能有很多。
@多条线分割 | 200x100

像上图。并不是每条线都是一个很好的分割线,如果紧贴着红点,那么线的另一头会立马被判为蓝色,这样对红点就很不合适了。所以SVM的目标不光是要找到这样一条分割线,而是要找到一条能最公平合理的分割线,让两类数据中最边缘的数据点距离分割线越远越好,这样这个分类器的泛化能力才会更强。于是乎支撑向量就被引入了。

分割线,分类表达式

这里写图片描述

直线的一般表达式:ax+by+c=0
对于多维,可以直接表达成: w T x + b = 0 w^{T}x+b=0 wTx+b=0,在多维情况下,它是个超平面。
对于直线上方的类别有 w T x + b > 0 w^{T}x+b>0 wTx+b>0
对于直线下方的类别有 w T x + b < 0 w^{T}x+b<0 wTx+b<0

距离表达式

有了直线,我们需要定义数据点到分割平面的距离,这里用的是点到直线的距离公式。

$ distance = \frac{|Ax_{0}+By_{0}+C|}{\sqrt{A^2+B^2}} $
- 如果我们去掉绝对值,就可以根据大于零还是小于零来判断数据点在直线上方还是下方。 - 更进一步,我们可以把它表示成如下形式:
$ distance=\frac{w^{T}x_{0}+b}{||w||} $
最大分割距离max margin

然后我们再来看一开始的那张图:
这里写图片描述

回顾一下支持向量机是要干啥来着,是要找到一条把两类数据分得很开的割平面对不对,这需要我们找到两类数据最边缘的数据点(支撑向量),然后画出来两条平行的切面,两边支撑向量距离的垂直平分线就是最终的切割平面。

支持向量机的目标是让最边缘的点之间的距离越大越好。即 ρ \rho ρ最大

这是我们的终极目标,敲黑板!

目标函数表达式推导

接下来,我们来分析怎么把这个目标写成数学表达式~
很简单,只需要表示support vector到分割线的距离,并且让该距离最大不就行了。

$ \rho = 2r = 2\frac{|w^{T}x_{support}+b|}{||w||}=2\frac{y_{support}(w^{T}x_{support}+b)}{||w||}$
最右边的等式成立是因为,y的sign和(直线上方的点记为1,直线下方的点记为-1)括号里的一直,保证了分子大于零。

直线上方的点 y i = 1 w T x i + b ≥ ρ 2 \quad y_{i}=1 \quad w^{T}x_{i}+b \ge \frac{\rho}{2} yi=1wTxi+b2ρ

直线下方的点 y i = − 1 w T x i + b ≤ − ρ 2 \quad y_{i}=-1 \quad w^{T}x_{i}+b \le -\frac{\rho}{2} yi=1wTxi+b2ρ

等价于:$ y_{i}(w^{T}x_{i}+b)\ge \frac{\rho}{2}$

那么新的问题来了,我们如何知道哪个点是support vector?
答案就是离分割线最近的点对不对。
所以,目标函数是一个极小极大问题。。。
\begin{equation}
\mathop{\arg\max}{w,b} \left{\frac{2}{||w||} \mathop{\min}{i} y_{i}(w^{T}x_{i}+b)\right}.
\end{equation}

之前我们有 $ y_{i}(w^{T}x_{i}+b)\ge \frac{\rho}{2}$,我们总可以通过缩放w和b,使该不等式右边划归到1。如此,就可以简化目标函数。

\begin{equation}
\mathop{\arg\max}{w,b}\frac{2}{||w||}
\ {s.t. \quad y
{i}(w^{T}x_{i}+b)\ge 1 for i=1,2,3…n}
\end{equation}

优化问题求解

我们把问题改为求它的对偶问题
\begin{equation}
\mathop{\arg\min}{w,b}\frac{||w||^2}{2}
\ {s.t. \quad y
{i}(w^{T}x_{i}+b)\ge 1 for i=1,2,3…n}
\end{equation}

因为目标函数是二次的,而约束在参数w和b上是线性的,因此这个问题是一个凸优化问题,可以通过标准的拉格朗日乘子来求解。

用拉格朗日乘子法:
L ( w , b , α ) = ∣ ∣ w ∣ ∣ 2 2 − ∑ i = 0 n α i ( y i ( w T x i + b ) − 1 ) ( 1 ) L(w,b,\alpha)=\frac{||w||^2}{2}-\sum_{i=0}^{n} \alpha_{i}(y_{i}(w^{T}x_{i}+b)-1)\quad(1) L(w,b,α)=2∣∣w2i=0nαi(yi(wTxi+b)1)(1) 其中, α i ≥ 0 \alpha_{i} \ge 0 αi0

解这个优化问题的方法是先求关于 α \alpha α的极大,再求关于w和b的极小。
m i n w , b m a x α L ( w , b , α ) \mathop{min}_{w,b}\mathop{max}_{\alpha}L(w,b,\alpha) minw,bmaxαL(w,b,α)
(因为 α i ≥ 0 \alpha_{i} \ge 0 αi0, − ( y i ( w T x i + b ) − 1 ) ≤ 0 -(y_{i}(w^{T}x_{i}+b)-1)\le 0 (yi(wTxi+b)1)0, 求这个式子关于 α \alpha α的极大,就是0,于是等价于原来的对 ∣ ∣ w ∣ ∣ 2 \frac{||w||}{2} 2∣∣w∣∣求极小)

我们转而求它的对偶问题:
m a x α m i n w , b L ( w , b , α ) \mathop{max}_{\alpha}\mathop{min}_{w,b}L(w,b,\alpha) maxαminw,bL(w,b,α)

(1)先求极小问题
另L对w,b求偏导并等于0, 有
∂ L ∂ w = w − ∑ i = 1 n α i y i x i = 0 \frac{\partial L}{\partial w}=w-\sum_{i=1}^{n} \alpha_{i}y_{i}x_{i}=0 wL=wi=1nαiyixi=0
∂ L ∂ b = ∑ i = 1 n α i y i = 0 \frac{\partial L}{\partial b} = \sum_{i=1}^{n} \alpha_{i}y_{i}=0 bL=i=1nαiyi=0

然后我们把这两个式子带入到拉格朗日函数(1)中,最终化简可以得到:
∑ i = 1 n α i − 1 2 ∑ i , j = 1 n α i α j y i y j x i T x j \sum_{i=1}^{n}\alpha_{i}-\frac{1}{2}\sum_{i,j=1}^{n}\alpha_{i}\alpha_{j}y_{i}y_{j}x_{i}^{T}x_{j} i=1nαi21i,j=1nαiαjyiyjxiTxj

(2)现在求极大问题
m a x α { ∑ i = 1 n α i − 1 2 ∑ i , j = 1 n α i α j y i y j x i T x j } s . t . ∑ i = 1 n α i y i = 0 α i ≥ 0 \mathop{max}_{\alpha}\left\{\sum_{i=1}^{n}\alpha_{i}-\frac{1}{2}\sum_{i,j=1}^{n}\alpha_{i}\alpha_{j}y_{i}y_{j}x_{i}^{T}x_{j}\right\}\\s.t. \sum_{i=1}^{n} \alpha_{i}y_{i}=0\\ \alpha_{i} \ge 0 maxα{i=1nαi21i,j=1nαiαjyiyjxiTxj}s.t.i=1nαiyi=0αi0

还是将问题转成对偶问题,求解这个问题用到了SMO,sequential minimal optimization,即每次只挑两个拉格朗日乘子,其他乘子认为是常数,然后每次都化为两变量凸优化问题。

最终通过求得 α \alpha α的值,找到最优的w和b。注意,最后的结果里,只有支撑向量的 α > 0 \alpha \gt 0 α>0, 对于非支撑向量,其 α = 0 \alpha = 0 α=0

松弛变量

有时候数据点不会分隔的这么好,会有一些点,总是站在对方阵营。或者及时我们能找到一条线,把两个类别的数据点刚好完美分开,我们可能也不希望是这根线。。。因为我们希望模型能有较好的泛化能力,希望中间的过渡带 ρ \rho ρ越大越好,所以我们会对某些不好的点选择性忽略。

一般用 ξ \xi ξ来表示松弛变量。加入松弛变量后的模型优化目标和约束变成啥样了呢。

m i n w , b , ξ ∣ ∣ w ∣ ∣ 2 2 + C ∑ i = 1 n ξ i s . t . y i ( w T x i + b ) ≥ 1 − ξ i ξ ≥ 0 \mathop{min}_{w,b,\xi}\frac{||w||^2}{2}+C\sum_{i=1}^{n}\xi_{i}\\s.t. y_{i}(w^{T}x_{i}+b) \ge 1-\xi_{i}\\ \xi \ge 0 minw,b,ξ2∣∣w2+Ci=1nξis.t.yi(wTxi+b)1ξiξ0

然后跟刚才的过程差不多,先对w,b, ξ \xi ξ求极小,在对 α \alpha α求极大。

这里需要强调的是,C越大,我们越倾向于没有松弛变量,即模型会尽可能分对每一个点,反之,C越小,模型的泛化能力越强

核函数

终于讲到核函数了。。。我最喜欢的部分。。。
之前的问题中我们都是用的x本尊,现实是,这堆数据点可能一条线不可分,比如说圆环图,斑马图。。。于是我们可以对x做高维变换,以期望在高维空间中,数据点能分开。此处盗用一张非常著名的图。
这里写图片描述

之前所有 x i x_{i} xi出现的地方,都可以改成 Φ ( x i ) \Phi(x_{i}) Φ(xi)
比如最终的分割超平面: w ∗ T Φ ( x i ) + b w ∗ = ∑ i = 1 n α i ∗ y i Φ ( x i ) b ∗ = y i − ∑ i = 1 n α i ∗ y i ( Φ ( x i ) T Φ ( x j ) ) w^{*T}\Phi(x_{i})+b\\ w^*=\sum_{i=1}^{n} \alpha_{i}^*y_{i}\Phi(x_{i})\\b^*=y_{i}-\sum_{i=1}^{n} \alpha_{i}^*y_{i}(\Phi(x_{i})^{T}\Phi(x_{j})) wTΦ(xi)+bw=i=1nαiyiΦ(xi)b=yii=1nαiyi(Φ(xi)TΦ(xj))
再比如求解中的目标函数: ∑ i = 1 n α i − 1 2 ∑ i , j = 1 n α i α j y i y j Φ ( x i ) T Φ ( x j ) \sum_{i=1}^{n}\alpha_{i}-\frac{1}{2}\sum_{i,j=1}^{n}\alpha_{i}\alpha_{j}y_{i}y_{j}\Phi(x_{i})^{T}\Phi(x_{j}) i=1nαi21i,j=1nαiαjyiyjΦ(xi)TΦ(xj)

因为从始至终,我们都只用到了内积,所以我们并不需要定义核函数的具体形式,而只需给出核函数的内积形式。

三种常见核函数
多项式核函数: κ ( x i , x j ) = ( α ∣ ∣ x i − x j ∣ ∣ a + r ) b \kappa(x_{i},x_{j})=(\alpha||x_{i}-x_{j}||^a+r)^b κ(xi,xj)=(α∣∣xixja+r)b α , a , b , r 是常数 \alpha,a,b,r是常数 α,a,b,r是常数
RBF径向基核函数: κ ( x i , x j ) = e x p ( − ∣ ∣ x i − x j ∣ ∣ 2 2 σ 2 ) \kappa(x_{i},x_{j})=exp(-\frac{||x_{i}-x_{j}||^2}{2\sigma^2}) κ(xi,xj)=exp(2σ2∣∣xixj2) 也叫高斯核函数,因为长得像
sigmoid核函数: κ ( x i , x j ) = t a n h ( γ ∣ ∣ x i − x j ∣ ∣ a + r ) \kappa(x_{i},x_{j})=tanh(\gamma||x_{i}-x_{j}||^a+r) κ(xi,xj)=tanh(γ∣∣xixja+r)

一般来讲RBF核已经很好用了,它可以投射到无穷维(回顾一下 e x e^x ex的tylor展开式。。。)
你可能还会有疑问,都什么函数能当核函数。答案是,所有半正定矩阵。
这里写图片描述

好了,现在我们终于可以来两行代码了。。。

from sklearn.datasets import load_iris
data = load_iris()

用sklearn自带的鸢尾花数据集,好嘛,我知道老掉牙了。。。复习一下

dir(data)返回的结果是[‘DESCR’, ‘data’, ‘feature_names’, ‘target’, ‘target_names’],比较直观,我就不解释了。

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(data.data, data.target,test_size=0.3,random_state=30,stratify=data.target)

这一步是划分训练集和测试集,永远不要忘了这一步。

from sklearn import svm
model=svm.SVC(C=0.5, kernel='rbf',gamma=5 )

sklearn.svm.SVC(C=1.0, kernel=‘rbf’, degree=3, gamma=‘auto’, coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape= ovr’, random_state=None)

C是松弛变量的系数
kernel是要定义核函数的名字,跟后面的系数也息息相关
gamma是这三个核函数的乘系数
degree是对多项式核函数来的。。。
coef0是另外两个核函数里的r
probability是可以允许多分类的情况
class_weight是可以实现给不同类别设不同的权重

from sklearn.metrics import accuracy
model.fit(X_train,y_train)
model.score(X_test,y_test)

输出是91%
虽然如此,我们还是象征性调个参

import numpy as np
from sklearn.model_selection import GridSearchCV
parameters={'kernel':['linear','rbf','sigmoid','poly'],'C':np.linspace(0.1,20,50),'gamma':np.linspace(0.1,20,20)}
svc = svm.SVC()
model = GridSearchCV(svc,parameters,cv=5,scoring='accuracy')
model.fit(X_train,y_train)
model.best_params_
model.score(X_test,y_test)

{‘C’: 1.7244897959183674, ‘gamma’: 0.10000000000000001, ‘kernel’: ‘rbf’}
accuracy=95%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值