支持向量机-SVM+源码

声明:个人学习之作,受时间和个人能力约束,仅供大家学习参考。欢迎讨论。

支持向量机(SVM),用于分类和回归的强大判别模型。
首先我们将重新考虑把特征映射到更高维度的空间。
接着我们将讨论支持向量机如何去缓和从映射到高维空间的数据中学习时遇到的计算问题和泛化问题。

1.1 核与核的技巧

感知机使用一个超平面作为决策边界来区分正向实例和负向实例。
决策边界公式:
f(x)=<w,x>+bf(x)=<w,x>+b
预测公式:
h(x)=sign(f(x))h(x)=sign(f(x))
这种方式,我们称之为原始形式
而在支持向量机中,我们需要把它转化为对偶形式。
f(x)=<w,x>+b=aiyi<xi,x>+bf(x)=<w,x>+b=\sum a_{i}y_{i}<x_{i},x>+b
原始形式和对偶形式最大的不同在于,原始形式计算了模型参数和测试实例特征向量的内积,而对偶形式计算了训练实例和测试实例特征向量的内积
而正是这个特性,被用来处理线性不可分类。
首先,我们把特征映射到更高维度空间的定义进行形式化
将特征映射到一个更高维度的空间中,在该空间中特征与响应变量线性相关。映射通过创建原有特征的二次项增加了特征的数量。而这些合成特征允许我们使用一个线性模型来表示一个非线性模型。
总的来说,一个映射从公式上来讲,如下:
xϕ(x)x\rightarrow \phi (x)
ϕ:RdRD\phi :R^{d}\rightarrow R^{D}
效果如下图[1]


在第二张图中,绿色的平面可以完美的划分紫色和红色,数据变得可分。
回到决策边界的对偶形式,可以看到特征向量智慧出现在点积中。我们可以通过在特征向量上执行映射来把数据映射到一个更高维度的空间中。
f(x)=aiyi<xi,x>+bf(x)=\sum a_{i}y_{i}<x_{i},x>+b
f(x)=aiyi<ϕ(xi),ϕ(x)>+bf(x)=\sum a_{i}y_{i}<\phi (x_{i}),\phi (x)>+b
就像我们前面说的那样,映射操作可以让我们表示更复杂的模型,但是也引入了计算问题和泛化问题。
这意味着,对特征向量进行映射和计算特征向量的点积需要大量的处理能力。
而且,虽然说我们把特征向量映射到了一个更高维度的空间中,特征向量仍然只出现在点积计算中。点积的计算结果是一个标量,一个这个标量被计算出来,我们不在需要映射后的特征向量。
如果能用依众不同的方法求出和映射后向量点积相同的标量,那就很省事了。

核技巧

一个核实这样的一种函数,只要给定了原始特征向量,就能返回和其相关的映射特征向量相同的点积值。核并不会直接把特征向量映射到一个更高维度空间,或者计算映射向量的点积。
核通过一系列不同的操作来产出相同的值,这些操作可以得到有效的计算。
核的定义公式如下:
K(x,z)=<ϕ(x),ϕ(z)>K(x,z)=<\phi (x),\phi (z)>
下面来证明核实如何运行的。
假设我们有两个特征向量x和z,
x=(x1,x2)x=(x_{1},x_{2})
z=(z1,z2)z=(z_{1},z_{2})
在实际当中,我们希望能够将特征向量映射到更高维度空间。
ϕ(x)=(x12,x22,2x1x2)\phi (x)=(x{_{1}}^{2},x{_{2}}^{2},\sqrt{2}x_{1}x_{2})
按照之前介绍的,映射标准化后的特征向量的点积如下:
<ϕ(x),ϕ(z)>=(x12,x22,2x1x2),(z12,z22,2z1z2)<\phi (x),\phi (z)>=(x{_{1}}^{2},x{_{2}}^{2},\sqrt{2}x_{1}x_{2}),(z{_{1}}^{2},z{_{2}}^{2},\sqrt{2}z_{1}z_{2})
核函数能产出和映射特征项链点积相等的值:
K(x,z)=<x,z>2=(x1z1+x2z2)2=x12z12+2x1z1x2z2+x22z22K(x,z)=<x,z>^{2}=(x_{1}z_{1}+x_{2}z_{2})^{2}=x{_{1}}^{2}z{_{1}}^{2}+2x{_{1}}z{_{1}}x{_{2}}z{_{2}}+x{_{2}}^{2}z{_{2}}^{2}
K(x,z)=<ϕ(x),ϕ(z)>K(x,z)=<\phi (x),\phi (z)>
公式是这个意思,我这块写一个个人理解的实例。一是方便理解,二是增加说服力,这里为了方便,我就不用公式编辑器了。
x=(4,9)
z=(3,3)
K(x,z)=4X4 X3x3 +2X4X3X9X3+9X9X3X3=1521
<ϕ(x),ϕ(z)>=<(42,92,2X4X9),(32,32,2X3X3)>=1521<\phi (x),\phi (z)>=<(4^{2},9^{2},\sqrt{2}X4X9),(3^{2},3^{2},\sqrt{2}X3X3)>=1521
核函数K(x,z)生成了和映射向量点积<ϕ(x),ϕ(z)><\phi (x),\phi (z)>计算结果相等的值,但是它并没有显性的把特征向量映射到高维空间,并只需要相对较少的数学运算。
在举得这个例子中,其实只使用了二维向量。
然而即使是只有少量特征的数据集也会产生巨大维度的映射特征空间。
scikit-learn类库则有一些常用的核函数:
多项式核函数:K(x,z)=(γ<xz>+δ)kK(x,z)=(\gamma <x-z>+\delta )^{k}
平方核或者k等于2的多项式核,经常被用于自然语言处理。
S型核:K(x,z)=tanh(γ<xz>+δ)kK(x,z)=tanh(\gamma <x-z>+\delta )^{k},其中 y和r这两个参数都是可以在交叉验证中进行微调的超参数。
对于需要用非线性模型处理的问题来说,高斯核是第一优先选择。高斯核是一个径向基函数。映射特征向量空间中作为决策边界的超平面和源空间中走位决策边界的超平面类似。
由高斯核产出的特征空间可以拥有无限维度,这是其他特征空间不可能具有的特性。
高斯核函数的定义如下:
K(x,z)=exp(γxz2)K(x,z)=exp(-\gamma |x-z|^{2})
使用SVM时,对特征进行缩放是很重要的,但是在使用高斯核时,特征缩放特别重要。
选择核函数非常难。
理想情况下,一个核函数能通过某种对任务有效的方式衡量实例之间的相似性。
虽然核函数经常和SVM一起使用,但是它也能和任何能够被表示为两个特征向量点积的模型一起使用
包括但不限于逻辑回归,感知机,主成分分析法PCA。(之后我会后续介绍)

1.2 最大间隔分类和支持向量

还是用实际例子来描述:

这三条线,也就是我们所谓的三个分类器,都可以划分样本分类。
直观的来讲,红色的线最优
但是对于技术人员来讲,我们要求的是严谨和论证。

假定图中的线是一个逻辑回归分类器的决策便捷。标记为A的实例远离决策边界,它有很高的概率被预测为正向类。标记为B的实例仍然被预测为属于正向类,但是实例越靠近决策边界被预测为正向类的概率机会越低。
最后,标记为C的实例有很低的概率被预测为正向类,即使是训练书记的一个微笑变化也会导致预测类发生变化。
如何解决?
最可信的预测是远离决策边界的训练实例,因此我们可以使用其函数间隔来评估预测的可信度。
训练集的函数间隔如下:
funct=minyif(xi)funct=min y_{i}f(x_{i})
f(x)=<w,x>+bf(x)=<w,x>+b
实例A的函数间隔很大,实例C的函数间隔很小。如果C分类错误,函数间隔将为负值。
函数间隔等于1的实例称为支持向量。(?为啥)
和函数间隔相关联的有几何间隔,或者支持向量的最大宽度。几何间隔等于标准化函数间隔,由于函数间隔能通过w进行缩放,
所以对函数间隔进行标准化非常有必要。
当w是一个单位向量时,几何间隔等于函数间隔。
最大化几何间隔的参数模型可以通过约束优化条件得出。
min12<w,w>min\frac{1}{2}<w,w>
yi(<wixi>+b)1y_{i}(<w_{i}x_{i}>+b)\geq 1

(待解决问题:)
SVM的一个特性:约束优化问题是一个凸优化问题,它的局部最小值也是全局最小值(如何证明?)
找出使得几何间隔最大化的参数是一个二次规划问题,该问题 通常使用序列最小优化算法SMO解决。(未研究)

使用实例来进行测试:手写数字分类

import matplotlib.pyplot as plt
from sklearn.datasets import fetch_mldata
import matplotlib.cm as cm
from sklearn import datasets

#引入数据集
mnist = datasets.fetch_mldata("mnist-original", data_home='/home/tianchi/myspace/datapanbo/mnist')
#mnist = fetch_mldata("MINIST original", data_home='/home/tianchi/myspace/datapanbo/mnist')
counter = 1
for i in range(1,4):
    for j in range(1,6):
        plt.subplot(3,5,counter)
        plt.imshow(mnist.data[(i-1) * 8000+j].reshape((28,28)),cm.Greys_r)
        plt.axis('off')
        counter+=1
plt.show

在这里插入图片描述

from sklearn.pipeline import   Pipeline

from sklearn.model_selection import  train_test_split
from sklearn.svm import SVC
from  sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
X,y =mnist.data, mnist.target 
X = X/255.0*2-1
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=11)
pipeline =Pipeline([
        ('clf',SVC(kernel='rbf', gamma=0.01, C=100))
    ])
parameters ={
        'clf__gamma':(0.01, 0.03, 0.1, 0.3, 1),
        'clf__C' : (0.1, 0.3, 1, 3, 10 , 30),
    }
grid_search =GridSearchCV(pipeline,parameters,n_jobs=2, verbose=1, scoring='accuracy')
grid_search.fit(X_train[:100],y_train[:100])

在这里插入图片描述
这里我要说一下,因为是为了测试代码跑通,所以我选择了100个数据。

print('最好的分数: %0.3f' %grid_search.best_score_)
print('最好的参数集:')
best_parameters= grid_search.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
    print('\t%s: % r '%(param_name,best_parameters[param_name]))

predictions=grid_search.predict(X_test)
print(classification_report(y_test,predictions))

在这里插入图片描述
这个是用电脑跑一万个数据,大约花了一个小时:63min
在这里插入图片描述
后续的代码和数据集我会上传到git
GIT代码地址

参考文献

1.核函数 https://blog.csdn.net/zb1165048017/article/details/49280979

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章