支持向量机 筛选特征基因 支持向量机特征重要性_核函数


支持向量机是强大并且用途广泛的机器学习工具,可以完成线性或者非线性的分类,回归,甚至离群点检测,尤其适合于那些复杂但是小型或者中型数据上的分类任务

线性SVM分类器


支持向量机 筛选特征基因 支持向量机特征重要性_支持向量机 筛选特征基因_02


这个图展示的是上一张的花朵分类,可以看出,这两个类是线性可分的,并且,存在着许多分类的方法,比如右图展示了三条决策边界都可以分开他们。简而言之,SVM追求的不只是分开他们,还希望决策边界到两个类的距离尽可能宽(中间实线那样),这叫最大分隔分类。

进一步,我们看哪些点决定了这个分类边界,那些离边界很远的内侧的点不会影响,而那些虚线上的点决定了哪一条边界是最好的,这些点被称为支持向量(上图红色的点)


支持向量机 筛选特征基因 支持向量机特征重要性_点积_03


从上图可以看出,SVM对尺度是敏感的,没有经过缩放可能会形成一条截然不同的边界(如上图左和右)

软间隔

如果分类边界把两类完美的区分开了,称为硬间隔,但是这样做有很大局限性:首先只能处理线性可分的数据,其次,对于一些离群点敏感,如下图


支持向量机 筛选特征基因 支持向量机特征重要性_核函数_04


因此我们需要用一个更灵活的模型,可以在比较大的边界和没有太多的点越界之间权衡,这就是软间隔

在Sklearn库中,我们用超参数C来控制这个程度,较大的C会造成很少的点越界但是间隔也会缩小,相反很大的C会导致会导致边界很宽但是越界的点比较多。

下图展示了一个SVM在Iris花朵分类的应用


import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

iris = datasets.load_iris()
X = iris["data"][:, (2, 3)] # petal length, petal width
y = (iris["target"] == 2).astype(np.float64) # Iris-Virginica

svm_clf = Pipeline((
        ("scaler", StandardScaler()),
        ("linear_svc", LinearSVC(C=1, loss="hinge")),
    ))

svm_clf.fit(X, y)

Then, as usual, you can use the model to make predictions:

>>> svm_clf.predict([[5.5, 1.7]])
array([ 1.])


不同于 Logistic 回归分类器,SVM 分类器不会输出每个类别的概率。

非线性SVM分类

在接近线性可分的问题上,线性SVM已经可以满足的很好,我们还是需要处理一些非线性可分的数据,一个想法是添加一些多项式的特征,比如上一节说过的PolynomialFeatures

但是低维的多项式可能不能组合出足够的特征,高维度的组合产生非常多的特征,让模型变得很慢。

在SVM上,我们可以使用一种“核技巧”,可以达到学习到高维特征的结果,又因为实际没有加上那么多的维度而不会让模型变慢。例如下面是一段Sklearn中多项式核的SVM


from sklearn.svm import SVC
poly_kernel_svm_clf = Pipeline((
        ("scaler", StandardScaler()),
        ("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))
    ))
poly_kernel_svm_clf.fit(X, y)


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_05


很明显,如果你的模型过拟合,你可以减小多项式核的阶数。相反的,如果是欠拟合,你可以尝试增大它。超参数coef0控制了高阶多项式与低阶多项式对模型的影响(图中的


)。可以用网格搜索来寻找最好的超参数。


另一种解决非线性问题的方法是使用相似函数计算每个样本与特定地标的相似度,高斯径向基函数(Gaussian Radial Basis Function,RBF)就是一种这样的函数


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_06

RBF函数

如图,假设有-2和1两个地标,通过计算到这两个点的相似函数,如右图,可以把一个一维空间的线性不可分的点(左)映射到右面空间的二维空间并且线性可分了。


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_07


这样的问题是,假设m个样本n维的空间,如果每个样本当一个地标来算,就变成了m个样本m维空间的,由于m常常远大于n,会增加额外的复杂度,核技巧还是可以来解决这个问题。


rbf_kernel_svm_clf = Pipeline((
        ("scaler", StandardScaler()),
        ("svm_clf", SVC(kernel="rbf", gamma=5, C=0.001))
    ))
rbf_kernel_svm_clf.fit(X, y)


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_08


用不同的超参数gamma (γ)C训练的模型。增大γ使钟型曲线更窄(左图),导致每个样本的影响范围变得更小:即判定边界最终变得更不规则,在单个样本周围环绕。相反的,较小的γ值使钟型曲线更宽,样本有更大的影响范围,判定边界最终则更加平滑。所以γ是可调整的超参数:如果你的模型过拟合,你应该减小γ值,若欠拟合,则增大γ(与超参数C相似)。

下图展示了SVM的复杂度(m是样本数,n是特征数)


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_09


一般来说,应该先尝试线性核函数 LinearSVC类基于 liblinear库,它实现了线性 SVM 的优化算法。它并不支持核技巧
因此 LinearSVCSVC(kernel="linear")要快得多。
如果训练集不太大,你也可以尝试高斯径向基核(Gaussian RBF Kernel),它在大多数情况下都很有效。如果你有空闲的时间和计算能力,你还可以使用交叉验证和网格搜索来试验其他的核函数,特别是有专门用于你的训练集数据结构的核函数。

SVM回归

SVM的用处确实很多,还可以处理回归的问题。不过目标不同,回归SVM希望把尽可能多的点放到宽的边界带之中,边界带的宽度由超参数


控制。这是外面的点是支持向量(红色圆圈)


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_10


from sklearn.svm import LinearSVR
svm_reg = LinearSVR(epsilon=1.5)
svm_reg.fit(X, y)

from sklearn.svm import SVR #SVR和SVC等价 LinearSVR和LinearSVC等价
svm_poly_reg = SVR(kernel="poly", degree=2, C=100, epsilon=0.1)
svm_poly_reg.fit(X, y)


支持向量机 筛选特征基因 支持向量机特征重要性_点积_11


SVM机制

如果你刚接触机器学习,可以暂时跳过这一部分。等到需要深入了解SVM再去研究


支持向量机 筛选特征基因 支持向量机特征重要性_支持向量机 筛选特征基因_12


预测用简单的函数Wx+b来进行,如果结果大于0的话,判断是正例。

如图,展示了两个特征下的决策边界,绿色部分wx+B>0,判断是正例,和平面的交线是边界


支持向量机 筛选特征基因 支持向量机特征重要性_多项式_13


我们可以直观的看出,对应同样的差值,如果平面w平缓,那么两点之间在x轴的距离大


支持向量机 筛选特征基因 支持向量机特征重要性_多项式_14


我们希望在都区分正确的前提下,让w尽可能平缓,就是||w||尽可能小。对于正的训练样本,我们需要决策函数大于 1,对于负训练样本,小于 -1。

可以得出


支持向量机 筛选特征基因 支持向量机特征重要性_点积_15


因为需要容忍一些分错的情况,要采取软间隔,因此加入了松弛变量(slack variable)



,它代表着出错的程度。另外,我们希望出错的程度加起来尽量的小,因此把它也加入损失函数,这样我们的损失函数就由两部分构成,w希望间隔尽量的大,


希望出错尽可能地少,用超参数C来调节平衡


支持向量机 筛选特征基因 支持向量机特征重要性_多项式_16


这个问题转化成了一个二次规划问题,可以用一些求解二次规划的方法来求解

但是,这个问题还可以转化为一个更好解的形式,同时,可以方便引入核函数。就是原函数的对偶问题。对偶问题的解通常是对原始问题的解给出一个下界约束,但在某些条件下,它们可以获得相同解。幸运的是,SVM 问题恰好满足这些条件,所以你可以选择解决原始问题或者对偶问题,两者将会有相同解。


支持向量机 筛选特征基因 支持向量机特征重要性_核函数_17


支持向量机 筛选特征基因 支持向量机特征重要性_支持向量机 筛选特征基因_18


最后求解了向量


,就可以求出W和b


支持向量机 筛选特征基因 支持向量机特征重要性_核函数_19


核函数

下面到了讨论核函数的时候

假设你有个多项式函数



支持向量机 筛选特征基因 支持向量机特征重要性_多项式_20


可以发现,对于两个向量的点积等于原始向量点积的平方


支持向量机 筛选特征基因 支持向量机特征重要性_网格向量必须包含特征点。_21


和这个过程一样,可以将SVM转换后的向量点积替换成


。所以实际上你根本不需要对训练样本进行转换:仅仅需要在公式中,将点积替换成它点积的平方。结果将会和你经过麻烦的训练集转换并拟合出线性 SVM 算法得出的结果一样,但是这个技巧使得整个过程在计算上面更有效率。这就是核技巧的精髓。


注意到支持向量才满足α(i)≠0,做出预测只涉及计算为支持向量部分的输入样本

的点积,而不是全部的训练样本。


支持向量机 筛选特征基因 支持向量机特征重要性_多项式_22


支持向量机 筛选特征基因 支持向量机特征重要性_点积_23


支持向量机 筛选特征基因 支持向量机特征重要性_核函数_24

一些常见的核函数

如果你开始感到头痛,这很正常:因为这是核技巧一个不幸的副作用

对于SVM理论的细节,可以参考林轩田老师的《机器学习技法》视频或其他资料

在线支持向量机

最后,快速地了解一下在线 SVM 分类器,一种方式是使用梯度下降(例如使SGDClassifiers)最小化代价函数(Hinge损失),如从原始问题推导出的公式 5-13。不幸的是,它比基于 QP 方式收敛慢得多。


支持向量机 筛选特征基因 支持向量机特征重要性_多项式_25


代价函数第一个和会使模型有一个小的权重向量w,从而获得一个更大的间隔。第二个和计算所有间隔违规的总数。如果样本位于“街道”上和正确的一边,或它与“街道”正确一边的距离成比例,则间隔违规等于 0。最小化保证了模型的间隔违规尽可能小并且少。

我们也可以实现在线核化的 SVM。例如使用“增量和递减 SVM 学习”或者“在线和主动的快速核分类器”。但是,这些都是用 Matlab 和 C++ 实现的。