SVM详解(包含它的参数C为什么影响着分类器行为)-scikit-learn拟合线性和非线性的SVM

引言

这篇文章详细地介绍了SVM背后的原理,它为什么是大间距分类器?分类器的参数C为什么影响着分类器的行为?核函数背后采用了什么样的技术,看过这篇文章以后,相信你能很好地理解这些问题。最后,我用scikit-learn来分别来拟合线性和非线性的SVM,让大家对SVM分类器有更加深刻的理解。

找寻最优化目标

相信所有用过SVM的人都知道它是一个大间距分类器。但是,它的原理是什么?它为什么可以最大化决策边界与样本之间的距离?下面我将一步一步的揭开它神秘的面纱。

从上图中我们可以看到,SVM会最大化间距,也就是那个m。但是,你可能会疑惑,上面的直线都怎么得出来的,m等于什么?我现在给你一个关于原点到直线距离的公式:

对于wtx=k,我们有距离为:k||w||

这里我给你一个例子,应用一下这个公式,让你更好地理解它。我相信大家很早就知道y=?x+1这个函数图像了吧!如下:

我们可以把y=?x+1写成x+y=1,这里w=[11],k=1.应用上面的公式:k||w||=12√,现在你可以用勾股定理去验证一下这个结论,结果也是一样的。现在如果我们把这个公式应用到wtx+b=?1和wtx+b=1,我们就可以得到m=2||w||。

PS:你可以把这两个式子写成wtx=?1?b和wtx=1?b,最后b会约掉,得到我上面的结果。

如果你想要了解得到m的全部详细过程,我下面给你的3篇文章它会从最基本的线性代数知识讲起,到最后得到m。但是,如果你不了解也没关系,只要用我给你的那个公式就可以的。

http://www.svm-tutorial.com/2014/11/svm-understanding-math-part-1/

http://www.svm-tutorial.com/2014/11/svm-understanding-math-part-2/

http://www.svm-tutorial.com/2015/06/svm-understanding-math-part-3/

现在,我们已经得到了间距m=2||w||,我们的SVM是想要最大化这个间距,也就是最小化12||w||2。你可能会想这so easy啊,使w=0不就ok了吗!但是,大家别忘了,我们求这个最小值是有约束的,也就是要分开我们的训练样本。约束如下:

{wTxi+b≥1,wTxi+b≤?1,if yi=1if yi=?1

上面公式中的i表示第i个训练样本。我们可以把上面的分段函数写的更加紧凑一些,如下:

yi(wTxi+b)≥1?i

现在,我们可以总结一下SVM最优化目标了:

最小化:12||w||2约束:yi(wTxi+b)≥1?i

看到此情此景,我们是否想起了什么呢?Yeah,就是拉格朗日乘子(Lagrangemultiplier),它可以搞定这个有约束的最优化条件。

拉格朗日乘子法

为了让大家更好地理解拉格朗日乘子法,现在我用一个实例一步一步地来讲解这个知识点。

假设,我现在有个想要最大化的函数为:f(x,y)=2x+y,这是一个三维的函数,图像如下:

现在,我们有个约束为:x2+y2=1,这很明显是个圆形。因此,我们可以把这个最优化问题解释成:“单位圆上的哪个点(x,y)使得2x+y”最大?为了使这个问题简单化,我们用等高线(contour lines)来描述这个问题,如果你不熟悉它,请参考我的这篇文章:http://blog.csdn.net/xlinsist/article/details/50920479

从上图我们可以看出,当f(x,y)取得最大值或最小值时的等高线与约束图像相切。其它的函数也都是同样的道理。谈到切线,让我们不禁会想到梯度,下面让我们来看看梯度在我们求解问题的道路中扮演什么样的角色?

函数f在点(x0,y0)的梯度方向总是与通过这点的等高线相互垂直。上面我说过2个图形的等高线是相切的,因此2个函数的梯度方向是一致的。所以如果我们用一个常数乖上一个函数的梯度,我们一定可以得到另一个梯度,公式如下:

?f(x0,y0)=λ0?g(x0,y0)λ0是一个常数

因此,通过上面我们得出的结论,可以求解我们最初提出的带约束的最优化问题。解题过程如下:

我们上面的2个函数可写成如下形式:

f(x,y)=2x+yg(x,y)=x2+y2?1

现在,我们分别求出2个函数的梯度如下:

?f(x,y)=???????x(2x+y)??y(2x+y)?????=[21]

?g(x,y)=???????x(x2+y2?1)??y(x2+y2?1)?????=[2x2y]

[21]=λ0[2x02y0]

下面的过程我就不写了,3个方程,3个未知数你一定可以解出结果。

下面我要引入拉格朗日函数(Lagrangian function),它以一种更为紧凑的方式来描述我上面的过程,它的公式如下:

L(x,y,λ)=f(x,y)?λ(g(x,y)?c)

针对我上面提出的例子来说,其中的f(x,y)=2x+y、g(x,y)=x2+y2、c=1,代入拉格朗日函数可以得出如下结果:

L(x,y,λ)=2x+y?λ(x2+y2?1)

现在,我要对拉格朗日函数的三个变量分别求导,看看会有什么奇迹发生!!!

??λ(f(x,y)?λ(g(x,y)?c))=0?(g(x,y)?c)??x(f(x,y)?λ(g(x,y)?c))=fx(x,y)?λgx(x,y)??y(f(x,y)?λ(g(x,y)?c))=fy(x,y)?λgy(x,y)

现在,我们让上面的三个等式分别等于0,得到如下结果:

g(x,y)=cfx(x,y)=λgx(x,y)fy(x,y)=λgy(x,y)

如果我们把上面的第2个等式和第3个等式合在一起,就得到了?f(x,y)=λ?g(x,y)

现在,你已经体会到拉格朗日函数的伟大了吧。它以一种更为紧凑的方式诠释了我们那个例子中的条件。

现在,你已经了解了拉格朗日函数这个强大的数学工具了。现在我们就用这个强大的数学工具来解决SVM的最优化问题吧。

求解SVM背后的最优化问题

在解决这个问题之前,大家可能已经注意到了两个问题。1、因为我们有很多个训练样本,所以SVM的最优化问题有很多约束?2、我们那个例子中的约束条件是等式,而这个约束条件是不等式?

其实解决这2个问题很简单,只要稍微对拉格朗日函数做一些调整就行了。改动如下:

1、只要我们在每个约束前面都乖上一个λ,在把所有这些约束求和就OK了。

2、拉格朗日乘子(Lagrange multiplier),也就是λ必须为正的

我们的优化目标如下:

最小化:12||w||2约束:1?yi(wTxi+b)≤0i=1,2,?,m

拉格朗日函数如下:

L=12wTw+∑i=1mλi(1?yi(wTxi+b))

  • m:训练样本数
  • ||w||2=wTw

现在,我们要把拉格朗日函数对w和b的梯度设置为0,结果如下:

w=∑i=1mλiyixi∑i=1mλiyi=0

现在,我把上式中的w带回到拉格朗日函数中,我们得到了一个只关于λ的函数:

L=?12∑i=1m∑i=1mλiλjyiyjxTixj+∑i=1mλi

提示:对于原式中的wTw代入部分,你只要把求和符号里面的x转置就行了。

现在,我们涉及到了对偶问题(Dual Problem)。如果我们求得了w,我们就能解出所有的λi;如果我们求得了所有的λi,我们就解出了w,如果你想看关于对偶问题的详细说明,请参考维基百科:https://en.wikipedia.org/wiki/Duality_(optimization)

如果你不明白什么是对偶问题也是没什么关系的。你只要知道我们最初的优化问题称为primal problem,而上面我们代入w得到的结果称为dual problem。现在,我们要最大化这个dual problem。我们的最优化问题如下:

最大化:H(λ)=∑i=1mλi?12∑i=1m∑i=1mλiλjyiyjxTixj约束:λi≥0最初引入拉格朗日乘子的属性约束:∑i=1mλiyi=0把最初的拉格朗日函数对b求偏导得出的结果

这是一个二次规划(quadratic programming)问题,因此我们总能找到使全局最大化的λi。很多方法可以解决这个最优化问题。在SVM中,sequential minimal optimization(SMO)是一个最受欢迎的算法。在实际应用中,我们就把解决QP问题的方法当做黑盒方法使用就行,你不必知道它具体是怎么工作的。如果你对这个方法很感兴趣,建议你Google一下。

先让我们看看下面这幅图片,我对照这个图片给大家解释一些概念。

上图中的αi,就是我们QP问题中要求的λi。

上图中,非0αi所对应的训练样本(xi)称为支持向量(support vectors),因此上面的α1,α6,α8都是支持向量。决策边界只由支持向量决定。上面,我们已经计算出w=∑mi=1λiyixi,我们把求出的支持向量代入这个公式就可以求出权重w了。公式中的λi和yi都是标量,因此w和xi的维数是一样的,可见我们的确把权重求对了。

引入松弛变量(slack variables)

对于一些非线性可分的数据集,我们可以用松弛变量这个技巧来解决问题,你可以把它看成是放宽约束,允许一些并没有正确分类的样本存在。如下图:

上图中的ξi就是松弛变量,它允许样本存在误差。由于它放宽了约束,因此我们可以把约束改成yi(wTxi+b)≥1?ξi。注意:ξi≥0。现在,我们的优化目标变成了12||w||2+C∑mi=1ξi

明确了优化目标和约束条件,像上面的例子一样,用拉格朗日函数就能解决这个问题了,这我就不再重复这个过程了。

相信使用SVM分类器的朋友都知道优化目标中的C吧,它完全可以影响分类器的行为。既然已经学到了现在,我们就再多介绍一下这个C吧!!!

如果可以用一句话概括C的话,它就是权衡误差和间距的参数。如果你的C很小,它会给你一个大间距,但是作为牺牲,我们必须要忽视一些错误分类的样本;反之,如果你的C很大,你会尽量正确地分类样本,但是这样做的代价会导致你有很小的间距。如下图:

你现在可能会问,C大一点好,还是小一点好呢?实际上,这没有什么标准的答案,这完全取决于你的训练集是什么样的。看看下面的两个例子:

通过我们上面的最小化函数我们也可以看出:如果C值很大,我们的松弛变量ξi就会很小,我们允许的误差也就很小,因此分类器会尽量正确分类样本,结果我们就会得到一个小间距的超平面,这样的结果可能会导致在新样本的分类性能很差,而在训练集上的分类性能很好,也就是出现过拟合(overfitting)现象;如果C值很小,我们所允许的误差也就很大,分类器即使要错误地分类样本,它也会找寻大间距的超平面,在这种情况下,如果你的训练集是线性可分的,也有可能出现错误分类的样本。

因此,在SVM算法的训练上,我们可以通过减小C值来避免overfitting的发生。

引入核函数(kernel function)

对于一些非线性可分的训练集,上面我引入了slack变量来解决这个问题。但是,对于一些训练集来说,用slack变量并不是一个好的选择。看看下图:

无论我们怎么调节参数C都不可能拟合出这样一个决策边界,因此slack变量不能很好地解决这个问题。Oh Yeah,核函数闪亮登场!!!下面,让我给大家一下核函数的本质。

现在,如果我把训练集的数据映射到高维空间看看会发生什么的结果呢?如下图:

Oh Yeah,现在线性可分了。但是,这样的方法也伴随着一个问题的出现,为了使我们的训练集线性可分,我们需要引入更多的特征,计算更多的权重系数,甚至这样的特征空间有可能是无限维的,这样的结果会导致我们无法计算。但是一个kernel技巧可以解决这样的问题,下面,让我们看看它是怎么办到的吧!

现在,你回去看看我们那个dual problem的最大化目标函数,训练集中的数据样本仅仅是计算两点之间的内积(xTixj)。因此,只要我们能计算特征空间上的内积,我们就不需要显示地映射数据。下面,用我上面那幅图中的映射举个例子。

我们最初样本的输入空间为:

[x1x2]

用映射函数?映射以后的结果为:

?([x1x2])=????x1x2x21+x22???????√????

现在,我们随机挑选出2个映射以后的样本做内积:

??([a1a2]),?([b1b2])?=?????a1a2a21+a22??????√????,????b1b2b21+b22??????√?????=a1b1+a2b2+(a21+a22)????????√(b21+b22)???????√

最后,如果我们定义一个核函数K(如下),我们就不需要显示地映射样本数据:

K(x,y)=x?y+ ∥x∥ ∥y∥

当然了,核函数有很多种,相信用过SVM的人都知道有什么样的核函数,这里我就不去介绍不同的核函数了。

假定你现在选择了一个合适的核函数K,现在我们要修改一下dual problem中的优化目标,如下:

H(λ)=∑i=1mλi?12∑i=1m∑i=1mλiλjyiyjK(xi,xj)

现在,我挑选出一个测试集中的样本z来做一下分类:

f(z)=∑xi∈support vectorsλiyiK(z,xi)+b

在实际应用中,我建议大家先试试低阶多项式核或者RBF核,这两个核都 是很好的选择。

把文章读到现在的朋友,我相信你已经对SVM有个很深入的了解。接下来,让我们拿起手中理论的武器征战实际中的问题吧。

scikit-learn实现线性SVM

如果你对scikit-learn和Iris数据集不算很了解,先看看这篇文章吧:http://blog.csdn.net/xlinsist/article/details/51289825

下面,我就直接上代码了!!!

from sklearn import datasets
import numpy as np
from sklearn.cross_validation import train_test_split

iris = datasets.load_iris() # 由于Iris是很有名的数据集,scikit-learn已经原生自带了。
X = iris.data[:, [2, 3]]
y = iris.target # 标签已经转换成0,1,2了
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0) # 为了看模型在没有见过数据集上的表现,随机拿出数据集中30%的部分做测试

# 为了追求机器学习和最优化算法的最佳性能,我们将特征缩放
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(X_train) # 估算每个特征的平均值和标准差
sc.mean_ # 查看特征的平均值,由于Iris我们只用了两个特征,所以结果是array([ 3.82857143,  1.22666667])
sc.scale_ # 查看特征的标准差,这个结果是array([ 1.79595918,  0.77769705])
X_train_std = sc.transform(X_train)
# 注意:这里我们要用同样的参数来标准化测试集,使得测试集和训练集之间有可比性
X_test_std = sc.transform(X_test)
X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))

# 导入SVC
from sklearn.svm import SVC
svm = SVC(kernel=‘linear‘, C=1.0, random_state=0) # 用线性核,你也可以通过kernel参数指定其它的核。
svm.fit(X_train_std, y_train)
# 打印决策边界,这个函数是我自己写的,如果你想要的话,我发给你
plot_decision_regions(X_combined_std, y_combined, classifier=svm, test_idx=range(105,150))
plt.xlabel(‘petal length [standardized]‘)
plt.ylabel(‘petal width [standardized]‘)
plt.legend(loc=‘upper left‘)
plt.show()

从上图中我们看到我们的线性SVM分类器干的还算不错。下图是不同的核分类的效果,链接中有详细的代码我就不在这重复了。

http://scikit-learn.org/stable/auto_examples/svm/plot_iris.html

SVM分类器中还有很多有用的参数,具体请参考官方文档:http://scikit-learn.org/stable/modules/svm.html#svm

scikit-learn实现非线性SVM

上面我已经介绍了核的概念,它的基本思想就是:通过映射函数?把训练集数据映射到高维的特征空间(是线性可分的),然后训练线性的SVM分类这个高维的特征空间,最后,我们用同样的映射函数转换测试集中的样本,用高维的特征空间所训练出的线性分类器对其分类。

在用scikit-learn实现算法之前,我先介绍一下高斯核的定义,它的公式如下:

K(x(i),x(j))=exp(?γ∥x(i)?x(j)∥)2γ=12σ2

上面的γ被称为核系数,它在控制overfitting现象上有很大的作用,在下面的2个例子中你会看到它的作用。现在,我就用RBF核(高斯核)来对Irsi数据集进行分类。代码如下:

svm = SVC(kernel=‘rbf‘, random_state=0, gamma=x, C=1.0) # 令gamma参数中的x分别等于0.2和100.0
svm.fit(X_train_std, y_train) # 这两个参数和上面代码中的训练集一样
plot_decision_regions(X_combined_std, y_combined, classifier=svm, test_idx=range(105,150))
plt.xlabel(‘petal length [standardized]‘)
plt.ylabel(‘petal width [standardized]‘)
plt.legend(loc=‘upper left‘)
plt.show()

用上面的两个γ值,得到了下面两幅图像:

我们看到当gamma = 100.0时,它非常好地拟合了训练数据,但是它在测试集上的表现会非常糟糕,因此产生了过拟合现象。

γ的值越大,我们的决策边界越柔和

SVM之在线学习(online learning)

有时候,我们的数据集太大而不能全部放到计算机内存中,因此scikit-learn提供了一个解决方案,SGDClassifier中的partial_fit方法允许你在线学习(或minibatch learning),这个就是在随机梯度下降中的意思。

svm = SGDClassifier(loss=‘hinge‘) # 指定为线性SVM

这个类中有很多方法和参数,具体参考官方文档:http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html

结语

这篇文章大约花费了我3天时间写的,为了让大家能更好地且准确地理解文章,其中有不确定的概念我参考了很多的资料才写在文章中,但谁能无错,希望有不好的地方大家能给指出来,小编在此谢过了。

参考资料

http://www.cise.ufl.edu/class/cis4930sp11dtm/notes/intro_svm_new.pdf

http://pages.cs.wisc.edu/~jerryzhu/cs540/handouts/svm.pdf

时间: 2024-08-11 05:36:28

SVM详解(包含它的参数C为什么影响着分类器行为)-scikit-learn拟合线性和非线性的SVM的相关文章

Mysql常用show命令,show variables like xxx 详解,mysql运行时参数

MySQL中有很多的基本命令,show命令也是其中之一,在很多使用者中对show命令的使用还容易产生混淆,本文汇集了show命令的众多用法. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 a. show tables或show tables from database_name; -- 显示当前数据库中所有表的名称. b. show databases; -- 显示mysql中所有数据库的名称. c. show columns from table_n

伯努利分布详解(包含该分布数字特征的详细推导步骤)

Bernouli Distribution(中文翻译称伯努利分布) 该分布研究的是一种特殊的实验,这种实验只有两个结果要么成功要么失败,且每次实验是独立的并每次实验都有固定的成功概率p. 概率公式可以表示为  , x只能为0或者1,即要么成功要么失败 根据数学期望的性质 由于这里x只有两个取值所以该分布的数学期望为 方差则可以由方差公式来计算 方差公式:  该分布显然, 因此可以得到, 所以方差  最后我们来推导该分布的最大似然估计 是这样定义的,假设我们做了N次实验,得到的结果集合为 ,我们想

flowplayer网页视频播放器事例详解--包含各种参数说明(自译)

flowplayer网页视频播放器事例详解--包含各种参数说明(自译) <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">     <title></title>     <meta http-equiv="content-type" content="text/html; charset=UTF-8&

Android动画最新最全详解包含Material Design动画

以前写动画也是零零种种,需要的时候就查API或找现成的,不够系统.现在通过学习将Android整个动画体系勾勒出来,做到有的放矢. 安卓框架提供了2个动画系统:属性动画(Android 3.0)和View动画.这两种动画系统都是可行的,但是,在一般情况下,属性动画是首选的方法,因为它是更灵活,提供更多的功能.除了这两个系统,你可以利用Drawable动画,它允许你一帧一个的加载显示Drawable资源.所以总体来说Android API提供了三类的动画: - Tween动画或View动画(API

机器学习经典算法详解及Python实现---Logistic回归(LR)分类器

(一)认识Logistic回归(LR)分类器 首先,Logistic回归虽然名字里带"回归",但是它实际上是一种分类方法,主要用于两分类问题,利用Logistic函数(或称为Sigmoid函数),自变量取值范围为(-INF, INF),自变量的取值范围为(0,1),函数形式为: 由于sigmoid函数的定义域是(-INF, +INF),而值域为(0, 1).因此最基本的LR分类器适合于对两分类(类0,类1)目标进行分类.Sigmoid 函数是个很漂亮的"S"形,如下

JVM参数配置详解-包含JDK1.8

堆大小设置    JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作系统对内存无限制.我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m.    典型设置:        java -Xmx3550m -Xms3550m -Xmn2g -Xss128k        -Xmx3550m:设置JVM最

SVM详解

SVM入门(一)至(三)Refresh 按:之前的文章重新汇编一下,修改了一些错误和不当的说法,一起复习,然后继续SVM之旅. (一)SVM的简介 支持向量机(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,它在解决小样本.非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中[10]. 支持向量机方法是建立在统计学习理论的VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本

Android OTA升级包制作脚本详解(一,参数解析)

写在前面: "build/tools/releasetools/ota_from_target_files  -u lk.bin  -n target.zip update.zip"这是制作整包的命令,很显然这里支持lk升级.本系列博文主要对该命令的执行流程及原理进行一个系统的分析,涉及到/build/tools/releasetools/目录下多个模块如ota_from_target_files.common等.由于本人对python了解粗浅,文中所涉及到的python语法大都做了注

SpringMVC详解(五)------参数绑定

参数绑定,简单来说就是客户端发送请求,而请求中包含一些数据,那么这些数据怎么到达 Controller ?这在实际项目开发中也是用到的最多的,那么 SpringMVC 的参数绑定是怎么实现的呢?下面我们来详细的讲解. 1.SpringMVC 参数绑定 在 SpringMVC 中,提交请求的数据是通过方法形参来接收的.从客户端请求的 key/value 数据,经过参数绑定,将 key/value 数据绑定到 Controller 的形参上,然后在 Controller 就可以直接使用该形参. 这里