线性情况下的支持向量机对非线性的数据没有办法处理。例如图中的两类数据(线性不可分),分别分布为两个圆圈的形状,线性SVM没法处理。
但是我们可以想到,对于上面的数据集,一个理想的分界应该是一个“圆圈”而不是一条线(超平面)。圆的方程可以写作以下形式:
原来我们的特征只有两个,即是二维的,X1和X2
如果我们构造五个新特征代替原来的两个特征,即用 Z1=X1 , Z2=X21 , Z3=X2 , Z4=X22 , Z5=X1X2 ,那么我们的特征维度就从二维升级到五维(也可以叫做构造一个五维空间代替原来的二维空间)。这时候奇妙的事情发生了:圆的方程变成线性的了,再也没有什么X的平方出现了。
这意味着什么呢?这意味着,我们只要从X1和X2中构造出Z1……Z5这五个特征,就可以用这个五个新特征,训练一个线性SVM超平面来划分前面的双圆圈数据集了。
至此,我们直觉上知道了一个事实:低维特征映射到高维特征,为解决线性不可分问题提供了一种方法。
既然如此,那我们就简单的把特征映射完,然后还是用之前的SVM老方法重做一遍,不就解决线性不可分问题了吗,为什么又要引入核函数这个概念呢?
这是因为简单的映射有缺点!
首先,给出我们原始的SVM分类函数是这样的:
那么在映射过后,则变成这样:
为什么会变成这样?
因为不管映射前,映射后,利用这个分类函数时,都需要进行两个输入向量之间的内积计算。
原来是二维特征,所以每个xi是二维向量,xi=(t
1, t2)。特征映射后,变成新的五维特征x'i = ϕ(xi)=(t'1, t'2, t'3, t'4, t'5)
所以内积计算<xi,x>才可以用<ϕ(xi),ϕ(x)>来代替,这可以想象成特征从xi变成了ϕ(xi)。
注:其中的 α 也是通过求解如下 dual 问题而得到的:
原来的特征是1阶2维的(即2个特征,每个特征最高1次幂);上升一次变成2阶5维(5个特征,每个特征最高2次幂);再上升一次,变成3阶19维。维数是爆炸性增长的,这给 ϕ(xi)的计算带来了非常大的困难(为什么带来困难?你自己想想最开头的时候计算Z1……Z5是不是很麻烦,如果要计算到Z19是不是得疯掉),所以就需要 核函数Kernel 出马了。
核函数就是用来解决如何高效计算<ϕ(x1),ϕ(x2)>的问题。
不妨还是从最开始的简单例子出发,设两个向量 x1=(η1,η2)T 和 x2=(ξ1,ξ2)T ,而 ϕ(⋅) 即是到前面说的五维空间的映射,因此映射过后的内积为:
上面这个计算看起来就很麻烦,对吧。另外,我们又注意到这么一个令人心动的等式:
可以看到左边是“(低维向量内积+1)的平方”,而右边很像<ϕ(x1),ϕ(x2)>。同时我们知道左边的计算是简单的,右边的计算是复杂的,所以我们惊奇地发现:简单计算通过一个函数变换就可以得到复杂计算的结果。因此我们知道了,用低维的向量内积就可以高效地算出高维向量内积。
但要注意到,右边只是很相似,而并非完全是<ϕ(x1),ϕ(x2)>。所以我们需要再做一些改变,改变的是什么东西呢?答案就是映射。
回到双圆圈的例子,我们原来的映射是:
φ(X1,X2)=(X1
,X21,X2,X22,X1X2)T
现在我们把映射改为:
φ(X1,X2)=(2√X1,X21,2√X2,X22,2√X1X2,1)T
改变体现在2个地方:某几个维度线性缩放,加上一个常数维度。
我们把这里的计算两个向量在映射过后的内积的函数叫做核函数 (Kernel Function) ,例如,在刚才的例子中,我们的核函数为:
核函数能简化映射空间中的内积运算——刚好“碰巧”的是,在我们的 SVM 里需要计算的地方数据向量总是以内积的形式出现的。对比刚才我们写出来的式子,现在我们的分类函数为:
其中 α 由如下 dual 问题计算而得:
以下直接摘抄自pluskid,没有进行修改
这样一来计算的问题就算解决了,避开了直接在高维空间中进行计算,而结果却是等价的,实在是一件非常美妙的事情!当然,因为我们这里的例子非常简单,所以我可以手工构造出对应于 φ(⋅) 的核函数出来,如果对于任意一个映射,想要构造出对应的核函数就很困难了。
最理想的情况下,我们希望知道数据的具体形状和分布,从而得到一个刚好可以将数据映射成线性可分的 ϕ(⋅) ,然后通过这个 ϕ(⋅) 得出对应的 κ(⋅,⋅) 进行内积计算。然而,第二步通常是非常困难甚至完全没法做的。不过,由于第一步也是几乎无法做到,因为对于任意的数据分析其形状找到合适的映射本身就不是什么容易的事情,所以,人们通常都是“胡乱”选择映射的,所以,根本没有必要精确地找出对应于映射的那个核函数,而只需要“胡乱”选择一个核函数即可——我们知道它对应了某个映射,虽然我们不知道这个映射具体是什么。由于我们的计算只需要核函数即可,所以我们也并不关心也没有必要求出所对应的映射的具体形式。
当然,说是“胡乱”选择,其实是夸张的说法,因为并不是任意的二元函数都可以作为核函数,所以除非某些特殊的应用中可能会构造一些特殊的核(例如用于文本分析的文本核,注意其实使用了 Kernel 进行计算之后,其实完全可以去掉原始空间是一个向量空间的假设了,只要核函数支持,原始数据可以是任意的“对象”——比如文本字符串),通常人们会从一些常用的核函数中选择(根据问题和数据的不同,选择不同的参数,实际上就是得到了不同的核函数),例如:
- 多项式核 κ(x1,x2)=(⟨x1,x2⟩+R)d ,显然刚才我们举的例子是这里多项式核的一个特例( R=1,d=2 )。虽然比较麻烦,而且没有必要,不过这个核所对应的映射实际上是可以写出来的,该空间的维度是 (m+dd) ,其中 m 是原始空间的维度。
- 高斯核 κ(x1,x2)=exp(−∥x1−x2∥22σ2) ,这个核就是最开始提到过的会将原始空间映射为无穷维空间的那个家伙。不过,如果 σ 选得很大的话,高次特征上的权重实际上衰减得非常快,所以实际上(数值上近似一下)相当于一个低维的子空间;反过来,如果 σ 选得很小,则可以将任意的数据映射为线性可分——当然,这并不一定是好事,因为随之而来的可能是非常严重的过拟合问题。不过,总的来说,通过调控参数 σ ,高斯核实际上具有相当高的灵活性,也是使用最广泛的核函数之一。
- 线性核 κ(x1,x2)=⟨x1,x2⟩ ,这实际上就是原始空间中的内积。这个核存在的主要目的是使得“映射后空间中的问题”和“映射前空间中的问题”两者在形式上统一起来了。
最后,总结一下:对于非线性的情况,SVM 的处理方法是选择一个核函数 κ(⋅,⋅) ,通过将数据映射到高维空间,来解决在原始空间中线性不可分的问题。由于核函数的优良品质,这样的非线性扩展在计算量上并没有比原来复杂多少,这一点是非常难得的。当然,这要归功于核方法——除了 SVM 之外,任何将计算表示为数据点的内积的方法,都可以使用核方法进行非线性扩展。