全文引自Free Mind博客,如果要引用请注明Free Mind的原文地址。
Maximum Margin Classifier
支持向量机即 Support Vector Machine,简称 SVM 。我最开始听说这头机器的名号的时候,一种神秘感就油然而生,似乎把 Support 这么一个具体的动作和 Vector 这么一个抽象的概念拼到一起,然后再做成一个 Machine ,一听就很玄了!
不过后来我才知道,原来 SVM 它并不是一头机器,而是一种算法,或者,确切地说,是一类算法,当然,这样抠字眼的话就没完没了了,比如,我说 SVM 实际上是一个分类器 (Classifier) ,但是其实也是有用 SVM 来做回归 (Regression) 的。所以,这种字眼就先不管了,还是从分类器说起吧。
SVM 一直被认为是效果最好的现成可用的分类算法之一(其实有很多人都相信,“之一”是可以去掉的)。这里“现成可用”其实是很重要的,因为一直以来学术界和工业界甚至只是学术界里做理论的和做应用的之间,都有一种“鸿沟”,有些很 fancy 或者很复杂的算法,在抽象出来的模型里很完美,然而在实际问题上却显得很脆弱,效果很差甚至完全 fail 。而 SVM 则正好是一个特例——在两边都混得开。
好了,由于 SVM 的故事本身就很长,所以废话就先只说这么多了,直接入题吧。当然,说是入贴,但是也不能一上来就是 SVM ,而是必须要从线性分类器开始讲。这里我们考虑的是一个两类的分类问题,数据点用
x
来表示,这是一个
一个超平面,在二维空间中的例子就是一条直线。我们希望的是,通过这个超平面可以把两类数据分隔开来,比如,在超平面一边的数据点所对应的
y
全是 -1 ,而在另一边全是 1 。具体来说,我们令
如上图所示,两种颜色的点分别代表两个类别,红颜色的线表示一个可行的超平面。在进行分类的时候,我们将数据点
x
代入
从几何直观上来说,由于超平面是用于分隔两类数据的,越接近超平面的点越“难”分隔,因为如果超平面稍微转动一下,它们就有可能跑到另一边去。反之,如果是距离超平面很远的点,例如图中的右上角或者左下角的点,则很容易分辩出其类别。
实际上这两个 Criteria 是互通的,我们定义 functional margin 为
γ^=y(wTx+b)=yf(x)
,注意前面乘上类别
y
之后可以保证这个 margin 的非负性(因为
到此为止,算是完成了 Maximum Margin Classifier 的介绍,通过最大化 margin ,我们使得该分类器对数据进行分类时具有了最大的 confidence (实际上,根据我们说给的一个数据集的 margin 的定义,准确的说,应该是“对最不 confidence 的数据具有了最大的 confidence”——虽然有点拗口)。不过,到现在似乎还没有一点点 Support Vector Machine 的影子。很遗憾的是,这个要等到下一次再说了,不过可以先小小地剧透一下,如上图所示,我们可以看到 hyper plane 两边的那个 gap 分别对应的两条平行的线(在高维空间中也应该是两个 hyper plane)上有一些点,显然两个 hyper plane 上都会有点存在,否则我们就可以进一步扩大 gap ,也就是增大 γ~ 的值了。这些点呢,就叫做 support vector ,嗯,先说这么多了。
Support Vector
上一次介绍支持向量机,结果说到 Maximum Margin Classifier ,到最后都没有说“支持向量”到底是什么东西。不妨回忆一下上次最后一张图:
可以看到两个支撑着中间的 gap 的超平面,它们到中间的 separating hyper plane 的距离相等(想想看:为什么一定是相等的?),即我们所能得到的最大的 geometrical margin γ~ 。而“支撑”这两个超平面的必定会有一些点,试想,如果某超平面没有碰到任意一个点的话,那么我就可以进一步地扩充中间的 gap ,于是这个就不是最大的 margin 了。由于在 n 维向量空间里一个点实际上是和以原点为起点,该点为终点的一个向量是等价的,所以这些“支撑”的点便叫做支持向量。
很显然,由于这些 supporting vector 刚好在边界上,所以它们是满足
当然,除了从几何直观上之外,支持向量的概念也会从其优化过程的推导中得到。其实上一次还偷偷卖了另一个关子就是虽然给出了目标函数,却没有讲怎么来求解。现在就让我们来处理这个问题。回忆一下之前得到的目标函数:
这个问题等价于(为了方便求解,我在这里加上了平方,还有一个系数,显然这两个问题是等价的,因为我们关心的并不是最优情况下目标函数的具体数值):
到这个形式以后,就可以很明显地看出来,它是一个凸优化问题,或者更具体地说,它是一个二次优化问题——目标函数是二次的,约束条件是线性的。这个问题可以用任何现成的 QP (Quadratic Programming) 的优化包进行求解。所以,我们的问题到此为止就算全部解决了,于是我睡午觉去了~ :)
啊?呃,有人说我偷懒不负责任了?好吧,嗯,其实呢,虽然这个问题确实是一个标准的 QP 问题,但是它也有它的特殊结构,通过 Lagrange Duality 变换到对偶变量 (dual variable) 的优化问题之后,可以找到一种更加有效的方法来进行求解——这也是 SVM 盛行的一大原因,通常情况下这种方法比直接使用通用的 QP 优化包进行优化要高效得多。此外,在推导过程中,许多有趣的特征也会被揭露出来,包括刚才提到的 supporting vector 的问题。
关于 Lagrange duality 我没有办法在这里细讲了,可以参考 Wikipedia 。简单地来说,通过给每一个约束条件加上一个 Lagrange multiplier,我们可以将它们融和到目标函数里去
然后我们令
容易验证,当某个约束条件不满足时,例如 yi(wTxi+b)<1 ,那么我们显然有 θ(w)=∞ (只要令 αi=∞ 即可)。而当所有约束条件都满足时,则有 θ(w)=12∥w∥2 ,亦即我们最初要最小化的量。因此,在要求约束条件得到满足的情况下最小化 12∥w∥2 实际上等价于直接最小化 θ(w) (当然,这里也有约束条件,就是 αi≥0,i=1,…,n ),因为如果约束条件没有得到满足, θ(w) 会等于无穷大,自然不会是我们所要求的最小值。具体写出来,我们现在的目标函数变成了:
首先要让
L
关于
w
和
带回 L 得到:
此时我们得到关于 dual variable α 的优化问题:
如前面所说,这个问题有更加高效的优化算法,不过具体方法在这里先不介绍,让我们先来看看推导过程中得到的一些有趣的形式。首先就是关于我们的 hyper plane ,对于一个数据点
x
进行分类,实际上是通过把
这里的形式的有趣之处在于,对于新点
x
的预测,只需要计算它与训练数据点的内积即可(这里
为什么非支持向量对应的 α 等于零呢?直观上来理解的话,就是这些“后方”的点——正如我们之前分析过的一样,对超平面是没有影响的,由于分类完全有超平面决定,所以这些无关的点并不会参与分类问题的计算,因而也就不会产生任何影响了。这个结论也可由刚才的推导中得出,回忆一下我们刚才通过 Lagrange multiplier 得到的目标函数:
注意到如果 xi 是支持向量的话,上式中红颜色的部分是等于 0 的(因为支持向量的 functional margin 等于 1 ),而对于非支持向量来说,functional margin 会大于 1 ,因此红颜色部分是大于零的,而 αi 又是非负的,为了满足最大化, αi 必须等于 0 。这也就是这些非 Supporting Vector 的点的悲惨命运了。 :p
嗯,于是呢,把所有的这些东西整合起来,得到的一个 maximum margin hyper plane classifier 就是支持向量机(Support Vector Machine),经过直观的感觉和数学上的推导,为什么叫“支持向量”,应该也就明了了吧?当然,到目前为止,我们的 SVM 还比较弱,只能处理线性的情况,不过,在得到了 dual 形式之后,通过 Kernel 推广到非线性的情况就变成了一件非常容易的事情了。不过,具体细节,还要留到下一次再细说了。 :)
Kernel
前面我们介绍了线性情况下的支持向量机,它通过寻找一个线性的超平面来达到对数据进行分类的目的。不过,由于是线性方法,所以对非线性的数据就没有办法处理了。例如图中的两类数据,分别分布为两个圆圈的形状,不论是任何高级的分类器,只要它是线性的,就没法处理,SVM 也不行。因为这样的数据本身就是线性不可分的。
对于这个数据集,我可以悄悄透露一下:我生成它的时候就是用两个半径不同的圆圈加上了少量的噪音得到的,所以,一个理想的分界应该是一个“圆圈”而不是一条线(超平面)。如果用 X1 和 X2 来表示这个二维平面的两个坐标的话,我们知道一条二次曲线(圆圈是二次曲线的一种特殊情况)的方程可以写作这样的形式:
注意上面的形式,如果我们构造另外一个五维的空间,其中五个坐标的值分别为 Z1=X1 , Z2=X21 , Z3=X2 , Z4=X22 , Z5=X1X2 ,那么显然,上面的方程在新的坐标系下可以写作:
关于新的坐标
Z
,这正是一个 hyper plane 的方程!也就是说,如果我们做一个映射
再进一步描述 Kernel 的细节之前,不妨再来看看这个例子映射过后的直观例子。当然,我没有办法把 5 维空间画出来,不过由于我这里生成数据的时候就是用了特殊的情形,具体来说,我这里的超平面实际的方程是这个样子(圆心在 X2 轴上的一个正圆):
因此我只需要把它映射到
Z1=X21
,
Z2=X22
,
Z3=X2
这样一个三维空间中即可,下图(这是一个 gif 动画)即是映射之后的结果,将坐标轴经过适当的旋转,就可以很明显地看出,数据是可以通过一个平面来分开的:
现在让我们再回到 SVM 的情形,假设原始的数据时非线性的,我们通过一个映射 ϕ(⋅) 将其映射到一个高维空间中,数据变得线性可分了,这个时候,我们就可以使用原来的推导来进行计算,只是所有的推导现在是在新的空间,而不是原始空间中进行。当然,推导过程也并不是可以简单地直接类比的,例如,原本我们要求超平面的法向量 w ,但是如果映射之后得到的新空间的维度是无穷维的(确实会出现这样的情况,比如后面会提到的 Gaussian Kernel ),要表示一个无穷维的向量描述起来就比较麻烦。于是我们不妨先忽略过这些细节,直接从最终的结论来分析,回忆一下,我们上一次得到的最终的分类函数是这样的:
现在则是在映射过后的空间,即:
而其中的 α 也是通过求解如下 dual 问题而得到的:
这样一来问题就解决了吗?似乎是的:拿到非线性数据,就找一个映射 ϕ(⋅) ,然后一股脑把原来的数据映射到新空间中,再做线性 SVM 即可。不过若真是这么简单,我这篇文章的标题也就白写了——说了这么多,其实还没到正题呐!其实刚才的方法稍想一下就会发现有问题:在最初的例子里,我们对一个二维空间做映射,选择的新空间是原始空间的所有一阶和二阶的组合,得到了五个维度;如果原始空间是三维,那么我们会得到 19 维的新空间(验算一下?),这个数目是呈爆炸性增长的,这给 ϕ(⋅) 的计算带来了非常大的困难,而且如果遇到无穷维的情况,就根本无从计算了。所以就需要 Kernel 出马了。
不妨还是从最开始的简单例子出发,设两个向量 x1=(η1,η2)T 和 x2=(ξ1,ξ2)T ,而 ϕ(⋅) 即是到前面说的五维空间的映射,因此映射过后的内积为:
另外,我们又注意到:
二者有很多相似的地方,实际上,我们只要把某几个维度线性缩放一下,然后再加上一个常数维度,具体来说,上面这个式子的计算结果实际上和映射
之后的内积 ⟨φ(x1),φ(x2)⟩ 的结果是相等的(自己验算一下)。区别在于什么地方呢?一个是映射到高维空间中,然后再根据内积的公式进行计算;而另一个则直接在原来的低维空间中进行计算,而不需要显式地写出映射后的结果。回忆刚才提到的映射的维度爆炸,在前一种方法已经无法计算的情况下,后一种方法却依旧能从容处理,甚至是无穷维度的情况也没有问题。
我们把这里的计算两个向量在映射过后的空间中的内积的函数叫做核函数 (Kernel Function) ,例如,在刚才的例子中,我们的核函数为:
核函数能简化映射空间中的内积运算——刚好“碰巧”的是,在我们的 SVM 里需要计算的地方数据向量总是以内积的形式出现的。对比刚才我们写出来的式子,现在我们的分类函数为:
其中 α 由如下 dual 问题计算而得:
这样一来计算的问题就算解决了,避开了直接在高维空间中进行计算,而结果却是等价的,实在是一件非常美妙的事情!当然,因为我们这里的例子非常简单,所以我可以手工构造出对应于 φ(⋅) 的核函数出来,如果对于任意一个映射,想要构造出对应的核函数就很困难了。
最理想的情况下,我们希望知道数据的具体形状和分布,从而得到一个刚好可以将数据映射成线性可分的 ϕ(⋅) ,然后通过这个 ϕ(⋅) 得出对应的 κ(⋅,⋅) 进行内积计算。然而,第二步通常是非常困难甚至完全没法做的。不过,由于第一步也是几乎无法做到,因为对于任意的数据分析其形状找到合适的映射本身就不是什么容易的事情,所以,人们通常都是“胡乱”选择映射的,所以,根本没有必要精确地找出对应于映射的那个核函数,而只需要“胡乱”选择一个核函数即可——我们知道它对应了某个映射,虽然我们不知道这个映射具体是什么。由于我们的计算只需要核函数即可,所以我们也并不关心也没有必要求出所对应的映射的具体形式。 :D
当然,说是“胡乱”选择,其实是夸张的说法,因为并不是任意的二元函数都可以作为核函数,所以除非某些特殊的应用中可能会构造一些特殊的核(例如用于文本分析的文本核,注意其实使用了 Kernel 进行计算之后,其实完全可以去掉原始空间是一个向量空间的假设了,只要核函数支持,原始数据可以是任意的“对象”——比如文本字符串),通常人们会从一些常用的核函数中选择(根据问题和数据的不同,选择不同的参数,实际上就是得到了不同的核函数),例如:
多项式核
κ(x1,x2)=(⟨x1,x2⟩+R)d
,显然刚才我们举的例子是这里多项式核的一个特例(
R=1,d=2
)。虽然比较麻烦,而且没有必要,不过这个核所对应的映射实际上是可以写出来的,该空间的维度是
(m+dd)
,其中
m
是原始空间的维度。
高斯核
线性核
κ(x1,x2)=⟨x1,x2⟩
,这实际上就是原始空间中的内积。这个核存在的主要目的是使得“映射后空间中的问题”和“映射前空间中的问题”两者在形式上统一起来了。
最后,总结一下:对于非线性的情况,SVM 的处理方法是选择一个核函数
κ(⋅,⋅)
,通过将数据映射到高维空间,来解决在原始空间中线性不可分的问题。由于核函数的优良品质,这样的非线性扩展在计算量上并没有比原来复杂多少,这一点是非常难得的。当然,这要归功于核方法——除了 SVM 之外,任何将计算表示为数据点的内积的方法,都可以使用核方法进行非线性扩展。
此外,略微提一下,也有不少工作试图自动构造专门针对特定数据的分布结构的核函数,感兴趣的同学可以参考,比如 NIPS 2003 的 Cluster Kernels for Semi-Supervised Learning 和 ICML 2005 的 Beyond the point cloud: from transductive to semi-supervised learning 等。
Outliers
在最开始讨论支持向量机的时候,我们就假定,数据是线性可分的,亦即我们可以找到一个可行的超平面将数据完全分开。后来为了处理非线性数据,使用 Kernel 方法对原来的线性 SVM 进行了推广,使得非线性的的情况也能处理。虽然通过映射
ϕ(⋅)
将原始数据映射到高维空间之后,能够线性分隔的概率大大增加,但是对于某些情况还是很难处理。例如可能并不是因为数据本身是非线性结构的,而只是因为数据有噪音。对于这种偏离正常位置很远的数据点,我们称之为 outlier ,在我们原来的 SVM 模型里,outlier 的存在有可能造成很大的影响,因为超平面本身就是只有少数几个 support vector 组成的,如果这些 support vector 里又存在 outlier 的话,其影响就很大了。例如下图:
用黑圈圈起来的那个蓝点是一个 outlier ,它偏离了自己原本所应该在的那个半空间,如果直接忽略掉它的话,原来的分隔超平面还是挺好的,但是由于这个 outlier 的出现,导致分隔超平面不得不被挤歪了,变成途中黑色虚线所示(这只是一个示意图,并没有严格计算精确坐标),同时 margin 也相应变小了。当然,更严重的情况是,如果这个 outlier 再往右上移动一些距离的话,我们将无法构造出能将数据分开的超平面来。
为了处理这种情况,SVM 允许数据点在一定程度上偏离一下超平面。例如上图中,黑色实线所对应的距离,就是该 outlier 偏离的距离,如果把它移动回来,就刚好落在原来的超平面上,而不会使得超平面发生变形了。具体来说,原来的约束条件
现在变成
其中 ξi≥0 称为松弛变量 (slack variable) ,对应数据点 xi 允许偏离的 functional margin 的量。当然,如果我们运行 ξi 任意大的话,那任意的超平面都是符合条件的了。所以,我们在原来的目标函数后面加上一项,使得这些 ξi 的总和也要最小:
其中
C
是一个参数,用于控制目标函数中两项(“寻找 margin 最大的超平面”和“保证数据点偏差量最小”)之间的权重。注意,其中
用之前的方法将限制加入到目标函数中,得到如下问题:
分析方法和前面一样,转换为另一个问题之后,我们先让
L
针对
w
、
将
w
带回
不过,由于我们得到 C−αi−ri=0 ,而又有 ri≥0 (作为 Lagrange multiplier 的条件),因此有 αi≤C ,所以整个 dual 问题现在写作:
和之前的结果对比一下,可以看到唯一的区别就是现在 dual variable
α
多了一个上限
C
。而 Kernel 化的非线性形式也是一样的,只要把
Numerical Optimization
作为支持向量机系列的基本篇的最后一篇文章,我在这里打算简单地介绍一下用于优化 dual 问题的 Sequential Minimal Optimization (SMO) 方法。确确实实只是简单介绍一下,原因主要有两个:第一这类优化算法,特别是牵涉到实现细节的时候,干巴巴地讲算法不太好玩,有时候讲出来每个人实现得结果还不一样,提一下方法,再结合实际的实现代码的话,应该会更加明了,而且也能看出理论和实践之间的差别;另外(其实这个是主要原因)我自己对这一块也确实不太懂。 :p
先回忆一下我们之前得出的要求解的 dual 问题:
对于变量 α 来说,这是一个 quadratic 函数。通常对于优化问题,我们没有办法的时候就会想到最笨的办法——Gradient Descent ,也就是梯度下降。注意我们这里的问题是要求最大值,只要在前面加上一个负号就可以转化为求最小值,所以 Gradient Descent 和 Gradient Ascend 并没有什么本质的区别,其基本思想直观上来说就是:梯度是函数值增幅最大的方向,因此只要沿着梯度的反方向走,就能使得函数值减小得越大,从而期望迅速达到最小值。当然普通的 Gradient Descent 并不能保证达到最小值,因为很有可能陷入一个局部极小值。不过对于 quadratic 问题,极值只有一个,所以是没有局部极值的问题。
另外还有一种叫做 Coordinate Descend 的变种,它每次只选择一个维度,例如 α=(α1,…,αn) ,它每次选取 αi 为变量,而将 α1,…,αi−1,αi+1,…,αn 都看成是常量,从而原始的问题在这一步变成一个一元函数,然后针对这个一元函数求最小值,如此反复轮换不同的维度进行迭代。Coordinate Descend 的主要用处在于那些原本很复杂,但是如果只限制在一维的情况下则变得很简单甚至可以直接求极值的情况,例如我们这里的问题,暂且不管约束条件,如果只看目标函数的话,当 α 只有一个分量是变量的时候,这就是一个普通的一元二次函数的极值问题,初中生也会做,带入公式即可。
然而这里还有一个问题就是约束条件的存在,其实如果没有约束条件的话,本身就是一个多元的 quadratic 问题,也是很好求解的。但是有了约束条件,结果让 Coordinate Descend 变得很尴尬了:比如我们假设 α1 是变量,而 α2,…,αn 是固定值的话,那么其实没有什么好优化的了,直接根据第二个约束条件 ∑ni=1αiyi=0 , α1 的值立即就可以定下来——事实上,迭代每个坐标维度,最后发现优化根本进行不下去,因为迭代了一轮之后会发现根本没有任何进展,一切都停留在初始值。
所以 Sequential Minimal Optimization (SMO) 一次选取了两个坐标维度来进行优化。例如(不失一般性),我们假设现在选取 α1 和 α2 为变量,其余为常量,则根据约束条件我们有:
其中那个从 3 到 n 的作和由于都是常量,我们统一记作
K
,然后由于
也可以得到
α1
的一个可行区间,同
[0,C]
交集即可得到最终的可行区间。这个问题可以从图中得到一个直观的感觉。原本关于
α1
和
α2
的区间限制构成途中绿色的的方块,而另一个约束条件
y1α1+y2α2=K
实际上表示一条直线,两个集合的交集即是途中红颜色的线段,投影到
α1
轴上所对应的区间即是
α1
的取值范围,在这个区间内求二次函数的最大值即可完成 SMO 的一步迭代。
同 Coordinate Descent 一样,SMO 也会选取不同的两个 coordinate 维度进行优化,可以看出由于每一个迭代步骤实际上是一个可以直接求解的一元二次函数极值问题,所以求解非常高效。此外,SMO 也并不是依次或者随机地选取两个坐标维度,而是有一些启发式的策略来选取最优的两个坐标维度,具体的选取方法(和其他的一些细节),可以参见 John C. Platt 的那篇论文 Fast Training of Support Vector Machines Using Sequential Minimal Optimization 。关于 SMO ,我就不再多说了。如果你对研究实际的代码比较感兴趣,可以去看 LibSVM 的实现,当然,它那个也许已经不是原来版本的 SMO 了,因为本来 SVM 的优化就是一个有许多研究工作的领域,在那些主要的优化方法之上,也有各种改进的办法或者全新的算法提出来。
除了 LibSVM 之外,另外一个流行的实现 SVMlight 似乎是用了另一种优化方法,具体可以参考一下它相关的论文 Making large-Scale SVM Learning Practical 。
此外,虽然我们从 dual 问题的推导中得出了许多 SVM 的优良性质,但是 SVM 的数值优化(即使是非线性的版本)其实并不一定需要转化为 dual 问题来完成的,具体做法我并不清楚,不过这方面的文章也不少,比如 2007 年 Neural Computation 的一篇 Training a support vector machine in the primal 。如果感兴趣可以参考一下。 :)
Duality
简单来说,对于任意一个带约束的优化都可以写成这样的形式:
形式统一能够简化推导过程中不必要的复杂性。其他的形式都可以归约到这样的标准形式,例如一个 maxf(x) 可以转化为 min−f(x) 等。假如 f0,f1,…,fm 全都是凸函数,并且 h1,…,hp 全都是仿射函数(就是形如 Ax+b 的形式),那么这个问题就叫做凸优化(Convex Optimization)问题。凸优化问题有许多优良的性质,例如它的极值是唯一的。不过,这里我们并没有假定需要处理的优化问题是一个凸优化问题。
虽然约束条件能够帮助我们减小搜索空间,但是如果约束条件本身就是比较复杂的形式的话,其实是一件很让人头痛的问题,为此我们希望把带约束的优化问题转化为无约束的优化问题。为此,我们定义 Lagrangian 如下:
它通过一些系数把约束条件和目标函数结合在了一起。当然 Lagrangian 本身并不好玩,现在让我们来让他针对 λ 和 ν 最大化,令:
这里
λ⪰0
理解为向量
λ
的每一个元素都非负即可。这个函数
z(x)
对于满足原始问题约束条件的那些
x
来说,其值等于
因为如果原始问题有最优值,那么肯定是在满足约束条件的某个
x∗
取得,而对于所有满足约束条件的
x
,
到这里,我们成功把带约束问题转化为了无约束问题,不过这其实只是一个形式上的重写,并没有什么本质上的改变。我们只是把原来的问题通过 Lagrangian 写作了如下形式:
这个问题(或者说原始的带约束的形式)称作 primal problem 。相对应的还有一个 dual problem ,其形式非常类似,只是把 min 和 max 交换了一下:
交换之后的 dual problem 和原来的 primal problem 并不相等,直观地,我们可以这样来理解:胖子中最瘦的那个都比瘦骨精中最胖的那个要胖。当然这是很不严格的说法,而且扣字眼的话可以纠缠不休,所以我们还是来看严格数学描述。和刚才的 z(x) 类似,我们也用一个记号来表示内层的这个函数,记:
并称
g(λ,ν)
为 Lagrange dual function (不要和
L
的 Lagrangian 混淆了)。
因为对于极值点(实际上包括所有满足约束条件的点) x∗ ,注意到 λ⪰0 ,我们总是有
因此
于是
这样一来就确定了 g 的下界性质,于是
实际上就是最大的下界。这是很自然的,因为得到下界之后,我们自然地就希望得到最好的下界,也就是最大的那一个——因为它离我们要逼近的值最近呀。记 dual problem 的最优值为 d∗ 的话,根据上面的推导,我们就得到了如下性质:
这个性质叫做 weak duality ,对于所有的优化问题都成立。其中
p∗−d∗
被称作 duality gap 。需要注意的是,无论 primal problem 是什么形式,dual problem 总是一个 convex optimization 的问题——它的极值是唯一的(如果存在的话),并且有现成的软件包可以对凸优化问题进行求解(虽然求解 general 的 convex optimization 实际上是很慢并且只能求解规模较小的问题的)。这样一来,对于那些难以求解的 primal problem (比如,甚至可以是 NP 问题),我们可以通过找出它的 dual problem ,通过优化这个 dual problem 来得到原始问题的一个下界估计。或者说我们甚至都不用去优化这个 dual problem ,而是(通过某些方法,例如随机)选取一些
λ⪰0
和
ν
,带到
g(λ,ν)
中,这样也会得到一些下界(只不过不一定是最大的那个下界而已)。当然要选
λ
和
ν
也并不是总是“随机选”那么容易,根据具体问题,有时候选出来的
λ
和
ν
带入
g
会得到
故事到这里还没有结束,既然有 weak duality ,显然就会有 strong duality 。所谓 strong duality ,就是
这是一个很好的性质,strong duality 成立的情况下,我们可以通过求解 dual problem 来优化 primal problem ,在 SVM 中我们就是这样做的。当然并不是所有的问题都能满足 strong duality ,在讲 SVM 的时候我们直接假定了 strong duality 的成立,这里我们就来提一下 strong duality 成立的条件。不过,这个问题如果要讲清楚,估计写一本书都不够,应该也有不少专门做优化方面的人在研究这相关的问题吧,我没有兴趣(当然也没有精力和能力)来做一个完整的介绍,相信大家也没有兴趣来看这样的东西——否则你肯定是专门研究优化方面的问题的了,此时你肯定比我懂得更多,也就不用看我写的介绍啦。 :p
所以,这里我们就简要地介绍一下 Slater 条件和 KKT 条件。Slater 条件是指存在严格满足约束条件的点
x
,这里的“严格”是指
让我们回到 duality 的话题。来看看 strong duality 成立的时候的一些性质。假设 x∗ 和 (λ∗,ν∗) 分别是 primal problem 和 dual problem 的极值点,相应的极值为 p∗ 和 d∗ ,首先 p∗=d∗ ,此时我们可以得到
由于两头是相等的,所以这一系列的式子里的不等号全部都可以换成等号。根据第一个不等号我们可以得到 x∗ 是 L(x,λ∗,ν∗) 的一个极值点,由此可以知道 L(x,λ∗,ν∗) 在 x∗ 处的梯度应该等于 0 ,亦即:
此外,由第二个不等式,又显然 λ∗ifi(x∗) 都是非正的,因此我们可以得到
这个条件叫做 complementary slackness 。显然,如果 λ∗i>0 ,那么必定有 fi(x∗)=0 ;反过来,如果 fi(x∗)<0 那么可以得到 λ∗i=0 。这个条件正是我们在介绍支持向量的文章末尾时用来证明那些非支持向量(对应于 fi(x∗)<0 )所对应的系数 αi (在本文里对应 λi )是为零的。 :) 再将其他一些显而易见的条件写到一起,就是传说中的KKT(Karush-Kuhn-Tucker) 条件:
任何满足 strong duality (不一定要求是通过 Slater 条件得到,也不一定要求是凸优化问题)的问题都满足 KKT 条件,换句话说,这是 strong duality 的一个必要条件。不过,当原始问题是凸优化问题的时候(当然还要求一应函数是可微的,否则 KKT 条件的最后一个式子就没有意义了),KKT 就可以升级为充要条件。换句话说,如果 primal problem 是一个凸优化问题,且存在 x~ 和 (λ~,ν~) 满足 KKT 条件,那么它们分别是 primal problem 和 dual problem 的极值点并且 strong duality 成立。 其证明也比较简单,首先 primal problem 是凸优化问题的话, g(λ,ν)=minxL(x,λ,ν) 的求解对每一组固定的 (λ,ν) 来说也是一个凸优化问题,由 KKT 条件的最后一个式子,知道 x~ 是 minxL(x,λ~,ν~) 的极值点(如果不是凸优化问题,则不一定能推出来),亦即:
Kernel II
在之前我们介绍了如何用 Kernel 方法来将线性 SVM 进行推广以使其能够处理非线性的情况,那里用到的方法就是通过一个非线性映射 ϕ(⋅) 将原始数据进行映射,使得原来的非线性问题在映射之后的空间中变成线性的问题。然后我们利用核函数来简化计算,使得这样的方法在实际中变得可行。不过,从线性到非线性的推广我们并没有把 SVM 的式子从头推导一遍,而只是直接把最终得到的分类函数
中的内积换成了映射后的空间中的内积,并进一步带入了核函数进行计算。如果映射过后的空间是有限维的,那么这样的做法是可行的,因为之前的推导过程会一模一样,只是特征空间的维度变化了而已,相当于做了一些预处理。但是如果映射后的空间是无限维的,还能不能这么做呢?答案当然是能,因为我们已经在这么做了嘛! :) 但是理由却并不是理所当然的,从有限到无限的推广许多地方都可以“直观地”类比,但是这样的直观性仍然需要严格的数学背景来支持,否则就会在一些微妙的地方出现一些奇怪的“悖论”(例如比较经典的芝诺的那些悖论)。当然这是一个很大的坑,没法填,所以这次我们只是来浮光掠影地看一看核方法背后的故事。
回忆一下原来我们做的非线性映射 ϕ ,它将原始特征空间中的数据点映射到另一个高维空间中,之前我们没有提过,其实这个高维空间在这里有一个华丽的名字——“再生核希尔伯特空间 (Reproducing Kernel Hilbert Space, RKHS)”。“再生核”就是指的我们用于计算内积的核函数,再说“再生”之前,我们先来简单地介绍一下 Hilbert Space ,它其实是欧氏空间的一个推广。首先从基本的向量空间开始,空间中的点具有加法和数乘的操作,在这个向量空间上定义一个内积操作,于是空间将升级为内积空间。根据内积可以定义一个范数:
从而成为一个赋范向量空间。范数可以用于定义一个度量
从而成为一个度量空间。如果这样的空间在这个度量下是完备的,那么这个空间叫做 Hilbert Space 。简单地来说,Hilbert Space 就是完备的内积空间。最简单的例子就是欧氏空间
Rm
,这是一个
m
维的 Hilbert Space ,无穷维的例子比如是区间
我们这里的 RKHS 就是一个函数空间。实际上,在这里我们有一个很有用的性质,就是维度相同的 Hilbert Space 是互相同构的——也就是说空间的各种结构(包括内积、范数、度量和向量运算等)都可以在不同的空间之间转换的时候得到保持。有了这样的性质,就可以让我们不用去关心 RKHS 中的点到底是什么。
将映射记为
ϕ:X→H
,这里
H
表示 RKHS,用
f
表示里面的元素 ;而
对于任意固定的
x0∈X
,
K(x,x0)
作为
x
的函数属于我们的函数空间
对于任意
x∈X
和
f(⋅)∈H
,我们有
f(x)=⟨f(⋅),K(⋅,x)⟩
。
其中第二条性质就叫做 reproducing property ,也是“再生核”名字的来源。至于字面上为什么这么叫,我也不清楚。也许是说元素
x
经过 kernel 映射之后,由内积一乘,又给冒出来了 -.-bb 。有了这个 kernel 之后,我们可以很自然地把映射
由核的再生性质,我们之前的用于计算 H 中内积的 kernel trick 也自然成立了:
再生核有很多很好的性质,比如正定性(在线性代数里这样的性质通常称为“半正定”),也就是说对任意 x1,…,xn∈X 和 ξ1,…,ξn∈R ,都有
这是很好证明的,按照核函数的再生性质写成刚才的内积形式,然后把系数拿到内积里面去,上面那个式子就等于 ∥∑ni=1ξiK(⋅,xi)∥2 ,根据范数的性质,也就非负了。
到这里,铺垫已经够多了,于是让我们回到 SVM ,这次我们不是直接偷工减料在最终得到的分类函数上做手脚,而是回到线性 SVM 的最初推导。当然,第一步我们要用刚才定义的映射 ϕ 将数据从原始空间 X 映射到 RKHS H 中,简单起见,我们用 fi(⋅) 来表示 K(⋅,xi) 。
和以前一样,我们使用一个线性超平面来分隔两类不同的点,并且我们假设经过非线性映射到 H 中之后数据已经是线性可分的了。这个线性超平面由一个线性函数来表示。这里需要再明确一下线性函数的概念,简单的说,如果 x1 、 x2 是向量, α1 、 α2 是标量,那么线性函数应该满足
在这里,由于我们讨论的空间 H 中的元素本身就是函数,因此我们把 H 上的函数改称“泛函 (functional)”。根据 Riesz Representation 定理,Hilbert Space 中的任意一个线性泛函 F ,都有一个 fF∈H ,使得
换句话说,线性函数可以由向量内积表示,这和我们熟知的有限维欧氏空间中是一样的。只是要表示超平面还得再加上一个截距 b
这个样子的函数(泛函)严格来说称作仿射函数(泛函)。同我们在第一篇中类似,我们可以定义 margin ,得到 geometrical margin 为
类似于原来的推导,我们最终会得到一个如下的目标函数
形式上和以前一样,只是把
xi
换成了
fi
,
w
换成了
这需要借助一个叫做 Representer Theorem 的定理,该定理说明,上面这个目标函数(还包括很大一类其他的目标函数)的最优解 g∗ 可以写成如下的形式:
换句话说,可以由这
n
个训练数据(有限集)张成。定理的证明是很简单的,记
由于 g∗⊥0 垂直于 f1,…,fn ,因此
因此, g∗⊥0 部分的取值对于目标函数中的约束条件并不产生影响,可以任意定。另一方面,考虑目标函数本身,我们有
最后一个等式是由于两者相互垂直而得到的(也就是勾股定理的推广啦),得到这个形式之后,再注意到我们是希望最小化 ∥g∗∥2 ,其中 g∗⊥0 是可以任意取值的,而范数 ∥g∗⊥0∥2 又是非负的,所以在最小值的时候我们必定有 \|g_0^{*\bot}\|^2=0 ∥g∗⊥0∥2=0 ,从而 g_0^{*\bot}=0 g∗⊥0=0 ,也就证明了 g^*\in\mathcal{H}_0 g∗∈H0 。
这样一来,问题就从在一个无穷维的 Hilbert Space 中找一个最优的 g^*
g∗
转化为了在一个 n
n
维的欧氏空间中找一个最优的系数 \mathbf{a}^*
这里矩阵 (K)ij=K(xi,xj) 就是 Kernel Gram Matrix 。而约束条件也可以相应地写成
这里
i=1,…,n
,而
Ki
表示矩阵
K
的第
最后稍微补充一下:在刚才的介绍中我们看起来好像是先确定了 RKHS 之后再找出对应的再生核的,但是在实际中,通常是先设计出一个核函数(或者说通常都是直接使用几个常见的核函数),然后对应的 RKHS 就自然地确定下来了。关于 RKHS 还有许多的内容,但是没有办法全部讲了。在传统的 Kernel 方法应用中,通常只要注意到是否可以全部表示为内积运算就可以尝试使用 kernel 方法了,许多常见的算法(例如 Least-Square Regression 、PCA 等)都是可以用核方法来扩展的,在这里 Representer Theorem 将会是重要的一环。
除此之外,进来还有不少在 RKHS 里衡量统计独立性的工作,又不是只是像传统的 kernel trick 那么简单了,说明 RKHS 还是包含了不少有趣的话题的。 :)