1、支持向量机理论学习汇编(一)SVM 的八股简介支持向量机(Support Vector Machine)是 Cortes 和 Vapnik 于 1995 年首先提出的,它在解决小样本、非线性及高维模式 识别中表现出许多特有的优势 ,并能 够推广应用到函数拟合等其他机器学习问题中10。支持向量机方法是建立在统计学习理论的 VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期 获 得最好的推广能力14(或称泛化能力)。以上是经常被有关 SVM 的学术文献引用的介绍,有
2、点八股,我来逐一分解并解释一下。Vapnik 是统计机器学习的大牛,这想必都不用说,他出版的Statistical Learning Theory是一本完整阐述统计机器学习思想的名著。在 该书中详细 的论证了统计机器学习之所以区别于传统机器学习的本质,就在于 统计机器学习能够精确的 给出学习效果,能 够解答需要的样本数等等一系列问题。与统计 机器学习的精密思维相比,传统的机器学习基本上属于摸着石头过河,用传统的机器学习 方法构造分类系统完全成了一种技巧,一个人做的结果可能很好,另一个人差不多的方法做出来却很差,缺乏指导和原则。所谓 VC 维是对函数类的一种度量,可以 简单的理解为问题 的复杂程
3、度, VC 维越高,一个问题就越复杂。正是因为 SVM 关注的是 VC 维,后面我们可以看到, SVM 解决问题的时候,和样本的维数是无关的(甚至 样本是上万维的都可以,这使得 SVM 很适合用来解决文本分类的问题,当然,有这样的能力也因为引入了核函数)。结构风险最小听上去文绉绉,其 实说的也无非是下面这回事。机器学习本质上就是一种对问题真实模型的逼近(我们选择一个我们认为比较好的近似模型,这个近似模型就叫做一个假 设),但毫无疑 问,真实模型一定是不知道的(如果知道了,我们干吗还要机器学习?直接用真实模型解决问题不就可以了?对吧,哈哈)既然真实模型不知道,那么我们选择的假设 与问题真实解之间
4、究竟有多大差距,我们就没法得知。比如说我们认为宇宙诞生于 150 亿年前的一场大爆炸, 这个假设 能够描述很多我们观察到的现象,但它与真实的宇宙模型之间还相差多少?谁也说不清,因为我们压根就不知道真实的宇宙模型到底是什么。这个与问题真实解之间的误差,就叫做 风险(更严格的说,误差的累积叫做风险)。我们选择了一个假设之后(更直观点说,我 们得到了一个分类器以后),真实误差无从得知,但我们可以用某些可以掌握的量来逼近它。最直观的想法就是使用分 类器在样本数据上的分类的结果与真实结果(因为样本是已经标注过的数据,是准确的数据)之间的差值来表示。 这个差值叫做经验风险 Remp(w)。以前的机器学习方
5、法都把经验风险最小化作为努力的目标,但后来发现很多分类函数能够在样本集上轻易达到 100%的正确率,在真实分类时却一塌糊涂(即所谓的推广能力差,或泛化能力差)。此时的情况便是选择了一个足够复杂的分类函数(它的 VC 维很高),能够精确的 记住每一个样本,但 对样本之外的数据一律分 类错误。回头看看经验风险最小化原则我们就会发现,此原 则适用的大前提是 经验风险要确实能够逼近真实风险才行(行话叫一致),但 实际上能逼近么?答案是不能,因为样本数相对于现实世界要分类的文本数来说简直九牛一毛, 经验风险最小化原则 只在这占很小比例的样本上做到没有误差,当然不能保证在更大比例的真 实文本上也没有 误差
6、。统计学习因此而引入了泛化误差界的概念,就是指真 实风险应该 由两部分内容刻画,一是经验风险,代表了分类器在 给定样本上的误差;二是置信 风险,代表了我 们在多大程度上可以信任分类器在未知文本上分类的结果。很 显然,第二部分是没有办法精确计算的,因此只能给出一个估计的区间,也使得整个 误差只能计算上界,而无法计算准确的值(所以叫做泛化误差界,而不叫泛化误差)。置信风险与两个量有关,一是 样本数量, 显然给定的样本数量越大,我们的学习结果越有可能正确,此时置信风险越小;二是分 类函数的 VC 维,显然 VC 维越大,推广能力越差,置信风险会变大。泛化误差界的公式为:R(w)Remp(w)+(n/
7、h)公式中 R(w)就是真 实风险,R emp(w)就是经验风险,(n/h)就是置信风险。统计学习的目标从经验风险最小化变为了寻求经验风险与置信风险的和最小,即结构风险最小。SVM 正是 这样一种努力最小化结构风险的算法。SVM 其他的特点就比较容易理解了。小样本,并不是说样本的绝对 数量少(实际上, 对任何算法来 说,更多的样本几乎总是能带来更好的效果),而是说与问题 的复杂度比起来, SVM 算法要求的 样本数是相对比较少的。非线性,是指 SVM 擅长应付样本数据线性不可分的情况,主要通过松弛变量(也有人叫惩罚变量)和核函数技术来实现, 这一部分是 SVM 的精髓,以后会详细讨论。多 说一
8、句,关于文本分类这个问题究竟是不是线性可分的,尚没有定 论 ,因此不能 简单的认为它是线性可分的而作简化处理,在水落石出之前,只好先当它是线性不可分的(反正线性可分也不过是线性不可分的一种特例而已,我们向来不怕方法过于通用)。高维模式识别是指样本维数很高,例如文本的向量表示,如果没有经过另一系列文章(文本分类入门)中提到过的降维处理,出 现几万维的情况很正常,其他算法基本就没有能力应付了,SVM 却可以,主要是因为 SVM 产生的分类器很简洁,用到的样本信息很少(仅仅用到那些称之为“支持向量”的样本,此为后话),使得即使样本维数很高,也不会 给存储和计算带来大麻烦(相对照而言, kNN 算法在
9、分类时就要用到所有样本,样本数巨大,每个样本维数再一高,这日子就没法 过了)。下一节开始正式讨论 SVM。别嫌我说得太详细哦。SVM 入 门(二)线性分类器 Part 12009-08-28 00:22线性分类器(一定意义上,也可以叫做感知机 ) 是最简单也很有效的分类器形式.在一个线性分类器中,可以看到 SVM 形成的思路,并接触很多 SVM 的核心概念.用一个二维空间里仅有两类样本的分类问题来举个小例子。如图所示C1 和 C2 是要区分的两个类别,在二维平面中它们的样本如上图所示。中间的直线就是一个分类函数,它可以将两类样 本完全分开。一般的,如果一个 线性函数能够将样本完全正确的分开,就
10、称这些数据是线 性可分的,否 则称为非线性可分的。什么叫线性函数呢?在一维空间里就是一个点,在二 维空 间里就是一条直线,三 维空间里就是一个平面,可以如此想象下去,如果不关注空间的维数,这种线性函数还有一个统一的名称超平面(Hyper Plane)!实际上,一个线性函数是一个 实值函数(即函数的值是连续 的实数),而我 们的分类问题(例如这里的二元分类问题回答一个样本属于还是不属于一个类别的问题)需要离散的输出值,例如用 1 表示某个样 本属于类别 C1,而用 0 表示不属于(不属于 C1 也就意味着属于 C2),这时候只需要简单的在实值函数的基础上附加一个 阈值即可,通过分类函数执行时得到
11、的值大于还是小于这个阈值来确定类别归属。 例如我 们有一个线性函数g(x)=wx+b我们可以取阈值为 0,这样当有一个 样本 xi 需要判别的时候,我们就看 g(xi)的值。若g(xi)0,就判别为类别 C1,若 g(xi)0(记得么?这是因为我们所选的 g(x)=wx+b 就通过大于 0 还是小于 0 来判断分类),而 yi 也大于 0;若不属于该类别的话,那么 wxi+b表示向量x1,x2 的内积(也叫点积,注意与向量叉 积的区别)。因此 g(x)的表达式严格的形式应该是:g(x)=+b但是上面的式子还不够好,你回 头看看图中正样本和 负样本的位置,想像一下,我不动所有点的位置,而只是把其
12、中一个正样本点定为负样 本点(也就是把一个点的形状从圆形变为方形),结果怎么样?三条直 线都必须移动(因为对这 三条直线的要求是必须把方形和圆形的点正确分开)!这说明 w 不仅跟样本点的位置有关,还跟样本的类别有关(也就是和样本的“标签 ”有关)。因此用下面这个式子表示才算完整:w=1y1x1+2y2x2+ nynxn (式 1)其中的 yi 就是第 i 个样本的标签,它等于 1 或者-1。其实以上式子的那一堆拉格朗日乘子中,只有很少的一部分不等于 0(不等于 0 才对 w 起决定作用),这部分不等于 0 的拉格朗日乘子后面所乘的样本点,其 实都落在 H1 和 H2 上,也正是这部分样本(而不
13、需要全部样本)唯一的确定了分类函数,当然,更严格的说, 这些样本的一部分就可以确定,因为例如确定一条直线,只需要两个点就可以,即便有三五个都落在上面,我们也不是全都需要。这部分我们真正需要的样本点,就叫做 支持(撑)向量!(名字 还挺形象吧,他 们“ 撑”起了分界线)式子也可以用求和符号简写一下:因此原来的 g(x)表达式可以写为:注意式子中 x 才是变量,也就是你要分 类哪篇文档,就把该文档的向量表示代入到 x 的位置,而所有的 xi统统都是已知的样本。 还注意到式子中只有 xi 和 x 是向量,因此一部分可以从内积符号中拿出来,得到 g(x)的式子为:发现了什么?w 不见啦!从求 w 变成
14、了求 。但肯定有人会说,这并没有把原 问题简化呀。嘿嘿,其实简化了,只不过在你看不见的地方,以这样的形式描述 问题以后,我 们的优化问题少了很大一部分不等式 约束(记得这是我们解不了极值问题的万恶之源)。但是接下来先跳 过线 性分类器求解的部分,来看看 SVM 在 线性分 类器上所做的重大改进核函数。转】SVM (七) 为什么需要核函数2009-07-06 10:43生存?还是毁灭?哈姆雷特可分?还是不可分?支持向量机之前一直在讨论的线性分类器,器如其名(汗, 这是什么说 法啊),只能 对线性可分的样本做处理。如果提供的样本线 性不可分, 结果很简单,线性分类器的求解程序会无限循环,永远也解不
15、出来。这必然使得它的适用范 围大大缩小,而它的很多优点我们实在不原意放弃,怎么办呢?是否有某种方法, 让线性不可分的数据变得线 性可分呢?有!其思想说来也简单,来用一个二 维平面中的分类问题 作例子,你一看就会明白。事先声明,下面这个例子是网络 早就有的,我一 时找不到原作者的正确信息,在此借用,并加进了我自己的解说而已。例子是下面这张图:我们把横轴上端点 a 和 b 之间红色部分里的所有点定为正类,两边的黑色部分里的点定为负类。试问能找到一个线 性函数把两类正确分开么?不能,因为二维空间里的线性函数就是指直线,显然找不到符合条件的直 线。但我们可以找到一条曲线,例如下面 这一条:显然通过点在
16、这条曲线的上方还是下方就可以判断点所属的类别(你在横轴上随便找一点,算算这一点的函数值,会发现负类的点函数值一定比 0 大,而正类的一定比 0 小)。这条曲线就是我们熟知的二次曲线,它的函数表达式可以写 为 :问题只是它不是一个线性函数,但是,下面要注意看了,新建一个向量 y 和 a:这样 g(x)就可以转化为 f(y)=,你 可以把 y 和 a 分别回 带一下,看看等不等于原来的 g(x)。用内积的形式写你可能看不太清楚, 实际上 f(y)的形式就是:g(x)=f(y)=ay在任意维度的空间中,这种形式的函数都是一个 线性函数(只不 过其中的 a 和 y 都是多维向量罢了),因为自变量 y
17、的次数不大于 1。看出妙在哪了么?原来在二维空间中一个线性不可分的问题,映射到四维空间后, 变成了线性可分的!因此这也形成了我们最初想解决线性不可分问题的基本思路向高维空间转化,使其变得线性可分。而转化最关键的部分就在于找到 x 到 y 的映射方法。 遗憾的是,如何找到这个映射,没有系统性的方法(也就是说,纯 靠猜和凑)。具体到我 们的文本分 类问题,文本被表示为上千维的向量,即使维数已经如此之高,也常常是线性不可分的,还要向更高的空间转化。其中的难度可想而知。小 Tips:为什么说 f(y)=ay 是四 维空间里的函数?大家可能一时没看明白。回想一下我 们二维空间里的函数定 义g(x)=ax
18、+b变量 x 是一维的,为什么说它是二 维空间里的函数呢?因 为还有一个变量我们没写出来,它的完整形式其实是y=g(x)=ax+b即y=ax+b看看,有几个变量?两个。那是几维空间的函数?(作者五 岁的弟弟答:五维的。作者:)再看看f(y)=ay里面的 y 是三维的变量,那 f(y)是几维空间里的函数?(作者五岁的弟弟答:还是五维的。作者:)用一个具体文本分类的例子来看看这种向高维空间映射从而分类的方法如何运作,想象一下,我们文本分类问题的原始空 间是 1000 维的(即每个要被分 类的文档被表示为一个1000 维的向量),在这个维度上 问题是线性不可分的。 现在我 们有一个 2000 维空间
19、里的线性函数f(x)=+b注意向量的右上角有个 哦。它能够将原问题变得可分。式中的 w和 x都是 2000 维的向量,只不过 w是定值,而 x是变量(好吧,严格说来这个函数是 2001 维的,哈哈),现在我们的输入呢,是一个 1000 维的向量 x,分 类的过程是先把 x 变换为 2000 维的向量 x,然后求这个变换后的向量 x与向量 w的内积,再把 这个内积的值 和 b 相加,就得到了 结果,看结果大于阈值还是小于阈值就得到了分类结果。你发现了什么?我们其实只关心那个高维空间里内积的值,那个值算出来了,分 类结果就算出来了。而从理论上说, x是经由 x 变换来的,因此广义上可以把它叫做 x
20、 的函数(有一个 x,就确定了一个 x,对吧,确定不出第二个),而 w是常量,它是一个低维空间里的常量 w 经过变换得到的,所以给了一个 w 和 x 的值,就有一个确定的 f(x)值与其对应。这让我们幻想,是否能有这样一种函数 K(w,x),他接受低维空间 的输入值,却能算出高 维空间的内积值?如果有这样的函数,那么当给 了一个低维空间的输入 x 以后,g(x)=K(w,x)+bf(x)=+b这两个函数的计算结果就完全一样,我 们也就用不着费力找那个映射关系,直接拿低维的输入往 g(x)里面代就可以了(再次提醒,这回的 g(x)就不是 线性函数啦,因为你不能保证K(w,x)这个表达式里的 x
21、次数不高于 1 哦)。万幸的是,这样的 K(w,x)确实存在(发现凡是我们人类能解决的 问题,大都是巧得不能再巧,特殊得不能再特殊的问题 ,总是恰好有些能投机取巧的地方才能解决,由此感到人类的渺小),它被称作核函数(核,kernel),而且 还不止一个,事实上,只要是满足了 Mercer 条件的函数,都可以作为核函数。核函数的基本作用就是接受两个低维空间里的向量,能够计算出经过某个变换后在高维空间里的向量内积值。几个比较常用的核函数,俄,教课书里都列过,我就不敲了(懒!)。回想我们上节说的求一个线性分类器,它的形式 应该是:现在这个就是高维空间里的线性函数(为了区别低维和高维空间里的函数和向量
22、,我改了函数的名字,并且给 w 和 x 都加上了 ),我们就可以用一个低维空间里的函数(再一次的,这个低维空间里的函数就不再是线性的啦)来代替,又发现什么了?f(x) 和 g(x)里的 ,y,b 全都是一样一样的!这就是说,尽管给的问题是线性不可分的,但是我们就硬当它是 线性问题来求解,只不过求解过程中,凡是要求内积的时候就用你选定的核函数来算。 这样求出来的 再和你选定的核函数一组合,就得到分类器啦!明白了以上这些,会自然的问 接下来两个问题:1 既然有很多的核函数,针对具体问题该怎么选择?2 如果使用核函数向高维空 间映射后, 问题仍然是线性不可分的,那怎么办?第一个问题现在就可以回答你:
23、对核函数的选择,现在还缺乏指 导原则!各种实验的观察结果(不光是文本分类)的确表明,某些 问题用某些核函数效果很好,用另一些就很差,但是一般来讲,径向基核函数是不会出太大偏差的一种,首选。(我做文本分类系统的时候,使用径向基核函数,没有参数调优 的情况下, 绝大部分类别的准确和召回都在 85%以上,可见。虽然 libSVM 的作者林智仁认为文本分类用线性核函数效果更佳,待考证)对第二个问题的解决则引出了我们下一节的主题:松弛变量。【转】SVM 入门(八)松弛变量2009-07-06 10:45现在我们已经把一个本来线性不可分的文本分类问题,通过映射到高维空间而变成了线性可分的。就像下图这样:
24、圆形和方形的点各有成千上万个(毕竟, 这就是我们训练集中文档的数量嘛,当然很大了)。现在想象我们有另一个训练 集,只比原先 这个训练集多了一篇文章,映射到高维空间以后(当然,也使用了相同的核函数),也就多了一个样本点,但是这个样本的位置是这样的:就是图中黄色那个点,它是方形的,因而它是负类的一个样本,这单独的一个样本,使得原本线性可分的问题变成了线性不可分的。 这样类似的 问题(仅有少数点线性不可分)叫做“近似线性可分 ”的问题。 以我们人类的常识来判断,说 有一万个点都符合某种规律(因而 线性可分),有一个点不符合,那这一个点是否就代表了分 类规则中我们没有考虑 到的方面呢(因而规则应该为它
25、而做出修改)? 其实我们会觉得,更有可能的是,这个样本点压根就是错误,是噪声,是提供训练集的同学人工分类时一打瞌睡错放进去的。所以我 们会简单的忽略 这个样本点,仍然使用原来的分类器,其效果丝毫不受影响。 但这种对噪声的容错性是人的思维带来的,我 们的程序可没有。由于我们原本的优化问题的表达式中,确实要考虑所有的 样本点(不能忽略某一个,因为程序它怎么知道该忽略哪一个呢?),在此基础上寻找正 负类之间的最大几何间隔,而几何间隔本身代表的是距离,是非负的,像上面这种有噪声的情况会使得整个 问题无解。 这 种解法其实也叫做“ 硬间隔”分类法,因为他硬性的要求所有样 本点都满足和分类平面间的距离必
26、须大于某个值。 因此由上面的例子中也可以看出,硬间隔的分类法其结果容易受少数点的控制,这是很危险的(尽管有句话说真理总是掌握在少数人手中,但那不 过是那一小撮人聊以自慰的词句罢了,咱还是得民主)。 但解决方法也很明显,就是仿照人的思路,允许一些点到分类平面的距离不满足原先的要求。由于不同的训练集各点的 间距尺度不太一样,因此用间隔(而不是几何间隔)来衡量有利于我们表达形式的简洁。我 们原先对样本点的要求是: 意思是说离分类面最近的样本点函数间隔也要比 1 大。如果要引入容错性,就 给 1 这个硬性的阈值加一个松弛变量,即允 许因为松弛变量是非负的,因此最 终的结果是要求间隔可以比 1 小。但是
27、当某些点出 现这种间隔比 1 小的情况时(这些点也叫离群点),意味着我 们 放弃了对这些点的精确分类,而 这对我们的分类器来说是种损失。但是放弃 这些点也带来了好 处,那就是使分 类面不必向这些点的方向移动,因而可以得到更大的几何 间隔(在低维空间 看来,分 类边界也更平滑)。显然我们必须权衡这种损失和好处。好 处很明显,我 们得到的分 类间隔越大,好处就越多。回顾我们原始的硬间隔分类对应的优化问题:|w|2 就是我 们的目标函数(当然系数可有可无),希望它越小越好,因而损失就必然是一个能使之变大的量(能使它变小就不叫损失了,我 们本来就希望目 标函数值越小越好)。那如何来衡量损失,有两种常用
28、的方式,有人喜欢用而有人喜欢用其中 l 都是样本的数目。两种方法没有大的区 别。如果选择了第一种,得到的方法的就叫做二阶软间隔分类器,第二种就叫做一 阶软间隔分类器。把损失加入到目标函数里的时候,就需要一个惩罚因子(cost,也就是 libSVM 的诸多参数中的 C),原来的优化问题就变成了下面这样:这个式子有这么几点要注意: 一是并非所有的样本点都有一个松弛变量与其对应。实际 上只有“离群点”才有,或者也可以这么看,所有没离群的点松弛 变量都等于 0(对负类来 说,离群点就是在前面 图中,跑到H2 右侧的那些负样本点,对正类来说,就是跑到 H1 左侧的那些正样本点)。 二是松弛变量的值实际上
29、标示出了对应的点到底离群有多远,值越大,点就越 远。 三是惩罚因子 C 决定了你有多重 视离群点带来的损失, 显然当所有离群点的松弛变量的和一定时,你定的 C 越大, 对目标函数的损失也越大,此时就暗示着你非常不愿意放弃这些离群点,最极端的情况是你把 C 定为无限大,这样只要稍有一个点离群,目标函数的值马上变成无限大,马上让问题变 成无解, 这就退化成了硬间隔 问题。 四是惩罚因子 C 不是一个变量,整个优化问题在解的时候,C 是一个你必须事先指定的值,指定这个值以后,解一下,得到一个分类器,然后用 测试 数据看看结果怎么样,如果不 够好,换一个 C 的 值,再解一次 优化问题,得到另一个分类
30、器,再看看效果,如此就是一个参数寻优的过程,但这和优化问题 本身决不是一回事, 优化问题 在解的过程中,C 一直是定值,要记住。 五是尽管加了松弛变量这么一说,但 这个优化问题仍然是一个 优化问题(汗, 这不废话么),解它的过程比起原始的硬 间隔问题来说,没有任何更加特殊的地方。 从大的方面说优化问题解的过程,就是先 试着确定一下 w,也就是确定了前面图中的三条直线,这时看看间隔有多大,又有多少点离群,把目标函数的值算一算,再换一组三条直线(你可以看到,分类的直线位置如果移 动了,有些原来离群的点会变得不再离群,而有的本来不离群的点会变成离群点),再把目 标函数的值算一算,如此往复(迭代),直
31、到最 终找到目标函数最小时的 w。 啰嗦了这么多,读者一定可以 马上自己总结出来,松弛 变量也就是个解决 线性不可分问题的方法罢了,但是回想一下,核函数的引入不也是为了解决线性不可分的问题么?为什么要为了一个问题使用两种方法呢? 其实两者还有微妙的不同。一般的 过程应该是这样, 还以文本分 类为例。在原始的低维空间中,样本相当的不可分,无论你怎么找分类平面,总会有大量的离群点,此时用核函数向高维空间映射一下,虽然结 果仍然是不可分的,但比原始空间里的要更加接近线性可分的状态(就是达到了近似线性可分的状态),此 时再用松弛变 量处理那些少数“冥顽不化”的离群点,就简单有效得多啦。 本节中的(式
32、1)也确实是支持向量机最最常用的形式。至此一个比 较完整的支持向量机框架就有了,简单说来,支持向量机就是使用了核函数的 软间 隔线性分类法。 下一节会说说松弛变量剩下的一点点东西, 顺便搞个读者 调查,看看大家 还想侃侃SVM 的哪些方面【转】SVM 入 门(九)松弛变量(续)2009-07-06 10:48接下来要说的东西其实不是松弛变量本身,但由于是 为了使用松弛 变量才引入的,因此放在这里也算合适,那就是惩罚 因子 C。回头看一眼引入了松弛变量以后的优化问题:注意其中 C 的位置,也可以回想一下 C 所起的作用(表征你有多么重视离群点,C 越大越重视,越不想丢掉它们)。这个式子是以前做
33、SVM 的人写的,大家也就这么用,但没有任何规定说必须对所有的松弛变量都使用同一个惩罚因子,我们完全可以给每一个离群点都使用不同的 C,这时就意味着你对每个样本的重视程度都不一样,有些样本丢了也就丢了,错了也就错了,这些就给一个比 较小的 C;而有些样本很重要,决不能分类错误(比如中央下达的文件啥的,笑),就给一个很大的 C。 当然实际使用的时候并没有这么极端,但一种很常用的 变 形可以用来解决分类问题中样本的“偏斜”问题。 先来说说样本的偏斜问题,也叫数据集偏斜( unbalanced),它指的是参与分类的两个类别(也可以指多个类别)样本数量差异很大。比如 说正类有 10,000 个样本,而
34、负类只给了100 个,这会引起的问题显而易 见,可以看看下面的 图:方形的点是负类。H,H 1,H2 是根据给的样本算出来的分类面,由于负类的样本很少很少,所以有一些本来是负类的 样本点没有提供,比如 图中两个灰色的方形点,如果这两个点有提供的话,那算出来的分类 面应该是 H,H2和 H1,他 们显 然和之前的结果有出入,实际上负类给的样本点越多,就越容易出 现在灰色点附近的点,我们算出的结果也就越接近于真实的分类面。但现在由于偏斜的 现象存在,使得数量多的正类可以把分类面向负类的方向“推”,因而影响了结果的准确性。 对付数据集偏斜问题的方法之一就是在惩罚因子上作文章,想必大家也猜到了,那就是
35、给样本数量少的负类更大的惩罚因子,表示我 们重视这部分 样本(本来数量就少,再抛弃一些,那人家负类还活不活了),因此我们的目标函数中因松弛 变量而损失的部分就变成了: 其中 i=1p 都是正 样本,j=p+1p+q 都是负样本。 libSVM 这个算法包在解决偏斜问题的时候用的就是这种方法。 那 C+和 C-怎么确定呢?它们的大小是试出来的(参数调优),但是他们的比例可以有些方法来确定。咱们先假定说 C+是 5 这么大,那确定 C-的一个很直 观的方法就是使用两类样本数的比来算,对应到刚才举 的例子, C-就可以定为 500 这么大(因为 10,000:100=100:1 嘛)。 但是这样并不
36、够好,回看刚才的 图,你会 发现正类之所以可以 “欺负”负类,其 实并不是因为负类样本少,真实的原因是 负类的样本分布的不够广(没 扩充到负类本应该有的区域)。说一个具体点的例子,现在想 给政治类和体育类的文章做分 类,政治 类文章很多,而体育类只提供了几篇关于篮球的文章, 这时分类会明显偏向于政治 类,如果要 给体育类文章增加样本,但增加的样本仍然全都是关于 篮球的(也就是说,没有足球,排球,赛车,游泳等等),那结果会怎样呢?虽然体育类文章在数量上可以达到与政治类一样多,但过于集中了, 结果仍会偏向于政治类!所以给 C+和 C-确定比例更好的方法应该是衡量他们分布的程度。比如可以算算他们在空
37、间中占据了多大的体积,例如 给负类找一个超球 就是高维空间里的球啦它可以包含所有负类的样本,再 给正类找一个,比比两个球的半径,就可以大致确定分布的情况。显然半径大的分布就比 较广,就 给小一点的惩罚 因子。 但是这样还不够好,因为有的 类别样本确实很集中, 这不是提供的 样本数量多少的问题,这是类别本身的特征(就是某些话题涉及的面很窄,例如 计 算机类的文章就明显不如文化类的文章那么“天 马行空” ),这个时候即便超球的半径差异很大,也不应该赋予两个类别不同的惩罚因子。 看到这里读者一定疯了,因为说 来说去, 这岂不成了一个解决不了的 问题?然而事实如此,完全的方法是没有的,根据需要,选择实
38、现简单又合用的就好(例如 libSVM 就直接使用样本数量的比)。SVM 入 门(十)将 SVM 用于多类分类2009-07-06 10:49从 SVM 的那几张图可以看出来,SVM 是一种典型的两类分类器,即它只回答属于正类还是负类的问题。而现实中要解决的 问题,往往是多 类的 问题(少部分例外,例如垃圾邮件过滤,就只需要确定“ 是”还是“不是”垃圾邮件),比如文本分类,比如数字识别。如何由两 类分类器得到多类分类器,就是一个 值得研究的问题。 还以文本分类为例,现成的方法有很多,其中一种一 劳永逸的方法,就是真的一次性考虑所有样本,并求解一个多目 标函数的优化问题,一次性得到多个分类面,就
39、像下图这样: 多个超平面把空间划分为多个区域,每个区域 对应一个类别 ,给一篇文章,看它落在哪个区域就知道了它的分类。 看起来很美对不对?只可惜这种算法还基本停留在纸面上,因为一次性求解的方法计算量实在太大,大到无法实用的地步。 稍稍退一步,我们就会想到所 谓“ 一类对其余”的方法,就是每次仍然解一个两类分类的问题。比如我们有 5 个类别,第一次就把类别 1 的样本定为 正样本,其余 2,3,4,5 的样本合起来定为负样本,这样得到一个两 类分类器,它能 够指出一篇文章是 还是不是第 1 类的;第二次我们把类别 2 的样本定为正样本,把 1,3,4,5 的样本合起来定为负样本,得到一个分类器,
40、如此下去,我们可以得到 5 个这样的两类分类器(总是和类别的数目一致)。到了有文章需要分类的时候,我们就拿着 这篇文章挨个分类器的问 :是属于你的么?是属于你的么?哪个分类器点头说是了,文章的 类别就确定了。 这种方法的好 处是每个优化问题的规模比较小,而且分类的时候速度很快(只需要 调用 5 个分类器就知道了 结果)。但有 时也会出现两种很尴尬的情况,例如拿一篇文章 问了一圈,每一个分 类器都 说它是属于它那一类的,或者每一个分类器都说它不是它那一类的,前者叫分 类重叠现象,后者叫不可分类现象。分类重叠倒还好办,随便选一个结果都不至于太离 谱,或者看看 这篇文章到各个超平面的距离,哪个远就判
41、给哪个。不可分类现象就着 实难办了,只能把它分 给 第 6 个类别了更要命的是,本来各个类别的样本数目是差不多的,但 “其余”的那一类样本数总是要数倍于正类(因为它是除正类以外其他类别的样本之和嘛), 这就人为的造成了上一 节所说的“数据集偏斜”问题。因此我们还得再退一步,还是解两 类分类问题, 还是每次选 一个类的样本作正类样本,而负类样本则变成只选一个类(称为“一对一单挑”的方法,哦,不对,没有单挑,就是“一对一”的方法,呵呵),这就避免了偏斜。因此过程就是算出这样一些分类器,第一个只回答“是第1 类还是第 2 类” ,第二个只回答 “是第 1 类还是第 3 类”,第三个只回答“是第 1
42、类还是第 4类”,如此下去,你也可以 马上得出,这样的分类器应该有 5 X 4/2=10 个(通式是,如果有 k个类别,则总的两类分类器数目 为 k(k-1)/2)。虽然分类器的数目多了,但是在训练阶段(也就是算出这些分类器的分类平面时)所用的总时间却比“一类对其余”方法少很多,在真正用来分类的时候,把一篇文章扔给 所有分类器,第一个分 类器会投票 说它是“1” 或者“2”,第二个会说它是“1”或者“3”,让每一个都投上自己的一票,最后 统计票数,如果类别“1” 得票最多,就判这篇文章属于第 1 类。这 种方法显然也会有分类重叠的 现象,但不会有不可分 类现象,因为总不可能所有类别的票数都是
43、0。看起来 够好么?其 实不然,想想分 类一篇文章,我们调用了多少个分类器?10 个, 这还是类别数为 5 的时候,类别数如果是 1000,要调用的分类器数目会上升至约 500,000 个(类别数的平方量级)。 这如何是好? 看来我们必须再退一步,在分 类的时候下功夫,我 们还是像一 对一方法那样来训练,只是在对一篇文章进行分类之前,我 们先按照下面图的样子来 组织分类器(如你所见, 这是一个有向无环图,因此这种方法也叫做 DAG SVM) 这样在分类时,我们就可以先问分类器“1 对 5”(意思是它能够回答“是第 1 类还是第 5类”),如果它回答 5,我们就往左走,再 问“2 对 5”这个分
44、类 器,如果它 还说是“5” ,我们就继续往左走,这样一直问下去,就可以得到分类结果。好处在哪?我们其实只调用了 4 个分类器(如果类别数是 k,则只调用 k-1 个),分类速度飞快,且没有分类重叠和不可分类现象!缺点在哪?假如最一开始的分类器回答错误(明明是类别 1 的文章,它说成了 5),那么后面的分类器是无论如何也无法纠正它的错误的(因为后面的分类器压根没有出现“1”这个类别标签),其实对下面每一层的分 类器都存在这种错误向下累 积的现象。 不过不要被 DAG 方法的错误累积吓倒, 错误累积在一对其余和一对一方法中也都存在,DAG 方法好于它们的地方就在于,累 积的上限,不管是大是小,总
45、是有定论的,有理 论证明。而一对其余和一对一方法中,尽管每一个两 类分类器的泛化 误差限是知道的,但是合起来做多类分类的时候,误差上界是多少,没人知道,这意味着准确率低到 0 也是有可能的,这多让人郁闷。 而且现在 DAG 方法根节点的选取(也就是如何选第一个参与分类的分类器),也有一些方法可以改善整体效果,我们总 希望根节点少犯错误为好,因此参与第一次分类的两个类别,最好是差别特别特别大,大到以至于不太可能把他们分错 ;或者我们就总取在两类分类中正确率最高的那个分类器作根节点,或者我 们让两类分类器在分 类的时候,不光 输出类别的标签, 还输出一个类似“ 置信度”的东东,当它 对自己的结果不
46、太自信的时候,我 们就不光按照它的输出走,把它旁边的那条路也走一走,等等。 大 Tips:SVM 的计算复杂度 使用 SVM 进行分类的时候,实际上是训练和分类两个完全不同的过程,因而讨论复杂度就不能一概而论,我们这里所 说的主要是训练阶段的复 杂度,即解那个二次 规划问题的复杂度。对这个问题的解,基本上要划分为两大块,解析解和数值解。 解析解就是理论上的解,它的形式是表达式,因此它是精确的,一个问题只要有解(无解的问题还跟着掺和什么呀,哈哈),那它的解析解是一定存在的。当然存在是一回事,能够解出来,或者可以在可以承受的时间范围内解出来,就是另一回事了。 对 SVM 来说,求得解析解的时间复杂
47、度最坏可以达到 O(Nsv3),其中 Nsv 是支持向量的个数,而虽然没有固定的比例,但支持向量的个数多少也和训练集的大小有关。 数值解就是可以使用的解,是一个一个的数,往往都是近似解。求数值解的过程非常像穷举法,从一个数开始,试一 试它当解效果怎样,不满足一定条件(叫做停机条件,就是满足这个以后就认为解足够精确了,不需要 继续算下去了)就试 下一个,当然下一个数不是乱 选的,也有一定章法可循。有的算法,每次只尝试一个数,有的就尝试多个,而且找下一个数字(或下一组数)的方法也各不相同,停机条件也各不相同,最终得到的解精度也各不相同,可见对求数值解的复杂度的讨论不能脱开具体的算法。 一个具体的算
48、法,Bunch-Kaufman 训练算法,典型的 时间复杂度在 O(Nsv3+LNsv2+dLNsv)和 O(dL2)之间,其中 Nsv 是支持向量的个数,L 是训练集样 本的个数,d 是每个样本的维数(原始的维数,没有经过向高维 空间映射之前的维数)。复 杂 度会有变化,是因为它不光跟输入问题的规模有关(不光和样本的数量, 维数有关),也和 问题 最终的解有关(即支持向量有关),如果支持向量比较少,过程会快很多,如果支持向量很多,接近于样本的数量,就会 产生 O(dL2)这个十分糟糕的 结果( 给 10,000 个样本,每个样本 1000 维,基本就不用算了,算不出来,呵呵,而这种输入规 模
49、对文本分类来说太正常了)。 这样再回头看就会明白为什么一对一方法尽管要训练的两类分类器数量多,但总时间实际上比一对其余方法要少了,因 为一对其余方法每次训练 都考虑了所有样本(只是每次把不同的部分划分为正类或者负类而已),自然慢上很多SVM 入 门(十)将 SVM 用于多类分类2009-07-06 10:49从 SVM 的那几张图可以看出来,SVM 是一种典型的两类分类器,即它只回答属于正类还是负类的问题。而现实中要解决的 问题,往往是多 类的 问题(少部分例外,例如垃圾邮件过滤,就只需要确定“ 是”还是“不是”垃圾邮件),比如文本分类,比如数字识别。如何由两 类分类器得到多类分类器,就是一个 值得研究的问题。 还以文本分类为例,现成的方法有很多,其中一种一 劳永逸的方法,就是真的一次性考虑所有样本,并求解一个多目 标函数的优化问题,一次性得到多个分类面,就像下图这样: 多个超平面把空间划分为多个区域,每个区域 对应一个类别 ,给一篇文章,看它落在哪个区域就知道了它的分类。 看起来很美对不对?只可惜这种算法还基本停留在纸面上,因为一次性求解的方法计算量实在太大,大到无法实用的地步。 稍稍退一步,我们就会想到所 谓“ 一类对其余”的方法,就是每次仍