机器学习入门(二十二)——SVM(3)

        SVM的本质上是一个线性分类器,并且引入了Margin区间的概念,保证Margin最大进而提高模型的准确性。Soft Margin对于SVM改善了模型泛化能力不足的问题,允许噪音、异常点的存在,但本质上仍是处理线性分割的问题。

1.0 使用多项式处理非线性数据

        处理非线性数据最典型的思路就是使用多项式的方式:扩充原本数据,制造新的多项式特征。

        使用sklearn.datasets中的make_moon数据集,创建经典的月牙形数据:


import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

X, y = datasets.make_moons(noise=0.20,random_state=123)

plt.scatter(X[y==0,0], X[y==0,1])

plt.scatter(X[y==1,0], X[y==1,1])

plt.show()


        使用多项式特征,建立SVM模型:


from sklearn.preprocessing import PolynomialFeatures, StandardScaler

from sklearn.svm import LinearSVC

from sklearn.pipeline import Pipeline

def PolynomialSVC(degree, C=1.0):

    return Pipeline([

        ("poly", PolynomialFeatures(degree=degree)),

        ("std_scaler", StandardScaler()),

        ("linearSVC", LinearSVC(C=C))

        ])

poly_svc = PolynomialSVC(degree=3)

poly_svc.fit(X, y)


        poly_svc的决策边界如下图所示。可以看出,通过多项式的方式使得决策边界不再是一条直线了,而是一条曲线。

        对于SVM算法来说,可以不使用多项式PolynomialFeatures的方式,而是使用另一种巧妙的方法实现非线性划分。

2.0 SVM解决非线性问题

2.1 示例1

        上图中有两种情况:第一种情况是线性可分的一维数据,可以在红蓝之间找到一个阈值将二者分开,黑色竖线(非0点刻度)就是决策边界,左右距离决策竖线最近的点是支持向量(外面套着圆圈的点)。

       第二种情况中,存在 红-蓝-红 三组数据分布,不存在单一的阈值将三组数据分开。

        对于第二种情况,SVM使用了一种非常巧妙的思路:一维空间不能解决,投影到二维空间,是数据的空间分布变成了如下的样子:

        横坐标是,纵坐标是,相当于引入了一个新的维度。此时,就可以用一条线将其分开。

        SVM将在原始空间中无法使用线性分类的数据映射到另一空间(Feature Space)当中,使其变得容易划分。

2.2 示例2

        在下面的样本数据集中,红色点在中心,蓝色点在四周,所以一条直线是肯定无法分划开的。如果一定要在当前空间将其分开的话,可以找到一个圆圈作为决策边界,将其分离。

        同样,通过坐标变化将其映射到新的空间中,也能够得到线性可分的形式。将横坐标变为,纵坐标变为,这样数据在空间分布中如下图所示:

        可以想象,有一个内功深厚的武林高手,面对桌子上的一堆混在一起的绿豆和红豆(数据点),一掌拍在桌子上,用内力将其逼到空中(从低维空间映射到高维空间),再它们在空中分散的时候(在高维空间上线性可分),然后再一刀将其分开(决策平面)。如下图:

3.0 核函数

        核函数指得是一类将数据从原始空间映射到Feature Space中的方法,就可以解决原本的线性不可分问题。一般求解最优化问题中也常用到核函数。

3.1 多项式核函数

        一种核函数映射方法:

        映射方法实际上是将数据维度升上去,映射到一个非常高的维度(大约有维)。

        一般情况下,高维数据的运算是十分复杂的,但SVM算法的精妙之处在于:两个向量做内积运算。这样在原始空间中,两个向量做内积映射到高维空间中则变成。展开后相乘得到:

        

        数学家们神奇地发现(具体怎么发现的不用知道...),存在这样一个表达式:

        这就是SVM中最重要的一个特性,是SVM算法的精妙之处:数学家设计出一种巧妙的数学变换,使高维空间的操作等价于低维空间的操作,解决了高维空间中的计算量问题,大大减少了运算量,这被称为Kernel Trick。

        上面的就是所谓的多项式核函数。可以拓展为一般形式:

        其中为多项式的阶数,在sklearn中,阶数degree的默认值为3。

3.2 高斯核函数

        高斯核函数是SVM算法中使用最多的核函数,也被称作是RBF核(Radial Basis Function Kernel),形式为:

        高斯核函数的与高斯函数(统计学中的正态分布函数)的(标准差)成反比,即越大,高斯分布越窄;越小,高斯分布越宽。表示向量的范数,可以理解为向量的模。

        通过一个例子看高斯核函数的作用:

        将原本的中的替换成两个固定点和,这两个特殊的点为地标landmark。高斯核函数升维的过程就是对于原本的每个x值,如果有两个landmark的话,就将其升维为二维样本点,每个样本升维后的值是高斯核函数的值:。通过这样的映射,就可以将线性不可分数据变得线性可分。

        对于地标点的选择,若认为地标点,那么对于每一个数据点都是landmark,有多少样本,就有多少地标点,这样就将m*n的数据映射成m*m的数据

4.0 SVM最终优化函数

        SVM本身的优化函数:

      ,

        为求解有条件的最优化问题,使用拉格朗日乘数法构造对偶函数:

     ,

        引入核函数变换后的函数形式:

      ,

        其中可以使用不同的核函数代入:或者

5.0 sklearn中的核函数实现

        使用本篇开头时的示例数据(make_moons),建立核函数的SVM模型。

5.1 多项式核函数建立SVM


from sklearn.svm import SVC

def PolynomialKernelSVC(degree, C=1.0):

    return Pipeline([

        ("std_scaler", StandardScaler()),

        ("kernelSVC", SVC(kernel='poly', degree=degree, C=C))

        ])

poly_kernel_svc = PolynomialKernelSVC(degree=3)

poly_kernel_svc.fit(X, y)


        poly_kernel_svc的决策边界为:

5.1.1 调整参数C


poly_kernel_svc2 = PolynomialKernelSVC(degree=3,C=200)

poly_kernel_svc2.fit(X, y)


        poly_kernel_svc2的决策边界如下图。可见参数C越大,中间的“凸起”越尖锐。而参数C是正则化项的系数,C越大,越接近于Hard Margin;C越小,容错性越大。

5.1.2 调整参数degree


poly_kernel_svc3 = PolynomialKernelSVC(degree=4)

poly_kernel_svc3.fit(X, y)


        poly_kernel_svc3的决策边界如下图。通过一些尝试发现,degree参数为偶数时,决策边界类似于双曲线的形式,而为奇数时则是以直线为基础。需要注意多项式阶数degree参数越大,则越容易出现过拟合。

5.2 RBF核函数建立SVM


def RBFKernelSVC(gamma=1.0):

    return Pipeline([

        ('std_scaler', StandardScaler()),

        ('svc', SVC(kernel='rbf', gamma=gamma))

    ])

rbf_svc = RBFKernelSVC(gamma=1.0)

rbf_svc.fit(X,y)


        rbf_svc的决策边界如下,此时KBF中的参数默认为1.0。

5.2.1 调整参数


rbf_svc2 = RBFKernelSVC(gamma=100)

rbf_svc2.fit(X,y)


        rbf_svc2的决策边界如下,可见分类效果非常不好,严重的过拟合。但可以直观看出的作用:已知参数取值越大,意味着高斯函数的“山峰”越窄。对于每个样本点来说,相当于在其周围都形成了一个“山峰”(想象成一个俯视图,蓝色点是“山顶”),以“山峰”比较窄,所以看起来就在每个蓝色点的周围圆环区域就比较小。

        由此可见,RBF核函数以该类中的每个点为“山尖”,用gamma参数表示“山峰的粗细”,所有的数据点连成“山脉”,这一区域是一类范围,其他范围都属于另一类。

        适当缩小的取值,查看分类效果:


rbf_svc3 = RBFKernelSVC(gamma=10)

rbf_svc3.fit(X,y)


        rbf_svc3的决策边界如下,可以看出缩小后,分类效果要平滑很多。

你可能感兴趣的:(机器学习入门(二十二)——SVM(3))