机器学习(3)支持向量机SVM

前言

SVM(support vector machine)算法属于机器学习算法里面(不包括深度学习算法)理论比较复杂同时十分有效的分类算法,因此在学习过程中也花了不少心思,尤其是一些证明过程。网上也已经有许多整理好的博文,动笔过程中在学习这些前辈的博文的基础上加上自己对这些算法的理解以及一些实际的利用。另外,因为是站在自己理解的基础上写这篇文章,所以可能很多部分的具体过程不是特别详细,需要更加详细的可以去文末链接,欢迎大家不吝赐教。

话不多说,开撸。

1 初识SVM

1.1 回顾logical回归



1.2 SVM的思想

      不同于logical分类器,SVM关心的是距离平面最近的样本距离平面的距离,总是希望这个距离尽可能的大。这样做的原因是因为在进行logical分类的时候,较远的样本点的存在使得分类平面距离某些样本点特别近。从概率上来讲,在进行样本分类预测的时候,这些预测结果并不可靠(概率分布略大于0.5)。另外,SVM采用这样的方式(关心局部样本点)可以在较少的样本点的情况下就可以拟合出分类器,但并不意味着不需要大数据集,自然训练数据集合越大训练效果越好。

1.3函数间隔和几何间隔

      因为网上关于两种不同间隔的定义已经和详细,因此我只做简单定义(详细过程可以看文末链接),主要进行两者不同点说明和适用情况。

                            

                      函数间隔                                                                      几何间隔

函数间隔的值小于任意样本到分类平面的函数距离;几何间隔将进行归一化处理,这样当缩放w和b的时候的值不会改变。通常情况下提到的间隔指的都是几何间隔。

1.4 最优化分类

于是最大间隔分类器(maximum margin classifier的目标函数可以定义为:

回顾下几何间隔的定义令函数间隔等于1则有 = 1 / ||w||且,从而上述目标函数转化成了

    相当于在相应的约束条件下,最大化这个1/||w||,而1/||w||便是几何间隔。   

    如下图所示,中间的实线便是寻找到的最优超平面(Optimal Hyper Plane),其到两条虚线边界的距离相等,这个距离便是几何间隔,两条虚线间隔边界之间的距离等于2,而虚线间隔边界上的点则是支持向量。由于这些支持向量刚好在虚线间隔边界上,所以它们满足,而对于所有不是支持向量的点,则显然有


2 深入SVM

2.1 求解最优化

目标函数:

   等价于 

  

(1)对偶问题

       由于这个问题的特殊结构,还可以通过拉格朗日对偶性(Lagrange Duality)变换到对偶变量 (dual variable) 的优化问题,即通过求解与原问题等价的对偶问题(dual problem得到原始问题的最优解,这就是线性可分条件下支持向量机的对偶算法,这样做的优点在于:一者对偶问题往往更容易求解;二者可以自然的引入核函数,进而推广到非线性分类问题。

     那什么是拉格朗日对偶性呢?简单来讲,通过给每一个约束条件加上一个拉格朗日乘子(Lagrange multiplier),定义拉格朗日函数(通过拉格朗日函数将约束条件融合到目标函数里去,从而只用一个函数表达式便能清楚的表达出我们的问题 

    容易验证,当某个约束条件不满足时,例如,那么显然有只要令即可)。而当所有约束条件都满足时,则最优值为亦即最初要最小化的量。

    因此,在要求约束条件得到满足的情况下最小化实际上等价于直接最小化(当然,这里也有约束条件,就是)   ,因为如果约束条件没有得到满足,会等于无穷大,自然不会是我们所要求的最小值。

    具体写出来,目标函数变成了:

    这里用表示这个问题的最优值,且和最初的问题是等价的。如果直接求解,那么一上来便得面对w和b两个参数,而又是不等式约束,这个求解过程不好做。不妨把最小和最大的位置交换一下,变成:

    交换以后的新问题是原始问题的对偶问题,这个新问题的最优值用来表示。而且有,在满足某些条件的情况下,这两者相等,这个时候就可以通过求解对偶问题来间接地求解原始问题。

    换言之,之所以从minmax的原始问题,转化为maxmin的对偶问题,一者因为的近似解,二者,转化为对偶问题后,更容易求解。

    下面可以先求wb的极小,再求的极大

具体计算过程如图:


求对a的极大即是关于对偶问题的最优化问题。经过上面第一个步骤的求w和b,得到的拉格朗日函数式子已经没有了变量w,b,只有a。从上面的式子得到:

    这样,求出了a即可求出w,然后通过即可求出b,最终得出分离超平面和分类决策函数。

(2)KKT条件

                       

KKT条件是用来求取最优化时候的理论,用来判断和确定最优化点的位置。

不等式约束条件:

       设目标函数f(x),不等式约束为g(x),有的教程还会添加上等式约束条件h(x)。此时的约束优化问题描述如下:


      则我们定义不等式约束下的拉格朗日函数L,则L表达式为:


      其中f(x)是原目标函数,hj(x)是第j个等式约束条件,λj是对应的约束系数,gk(X)是不等式约束,uk是对应的约束系数。

      此时若要求解上述优化问题,必须满足下述条件(也是我们的求解条件):


      这些求解条件就是KKT条件。(1)是对拉格朗日函数取极值时候带来的一个必要条件,(2)是拉格朗日系数约束(同等式情况),(3)是不等式约束情况,(4)是互补松弛条件,(5)、(6)是原约束条件。

Note:

       从KKT条件中我们其实可以看到,对于非支持向量上的数据点,他们的系数必定为0.一方面说明在整个超平面的求解过程非支持向量上的点没有起到对平面参数的约束作用;同时,说明我们在进行新的样本点的分类预测的时候,只需要和支持向量上的点进行內积即可。

2.2 非线性数据集的线性分类

SVM进行分类时其实产生的是一个超平面,所以只能进行线性数据的分类,对于非线性数据可能并不能进行很好的分类,例如:

2.2.1实现非线性特征到线性特征的变换

怎么进行这些数据集合的分类?我们引入升维的概念,先看一张图。当我们将一个三维图像投影到一个二维平面的时候,必然会丢失一个维度的信息。反之,对数据进行升维的话,会让我们看到更多在低纬度看不到的数据特征。

怎样进行升维?设两个向量,增加新的维度 

          

则原空间映射为五维空间,理论上可以映射到无线维。

因此映射过后的内积为:

另外,我们又注意到:

到这里我们先停一下,回想一下我们进行SVM的样本预测的时候是不是其实就是预测样本和支持向量进行內积运算。同样,如果将空间映射到高维空间之后,进行內积运算的时候是不是增大了内存量。这时候这个公式派上用场了,可以发现先进性內积运算然后带入特定的函数可以发现,內积结果不改变。


这个特定的函数我们称之为核函数,可以很好的解决映射后计算內积工作量太大的问题。

2.2.1 核函数

通常人们会根据问题和数据的不同,选择不同的参数,实际上就是得到了不同的核函数,例如:

(1)多项式核,显然刚才我们举的例子是这里多项式核的一个特例(R = 1,d = 2。虽然比较麻烦,而且没有必要,不过这个核所对应的映射实际上是可以写出来的,该空间的维度是,其中 是原始空间的维度。

(2)高斯核,这个核就是最开始提到过的会将原始空间映射为无穷维空间的那个家伙。不过,如果选得很大的话,高次特征上的权重实际上衰减得非常快,所以实际上(数值上近似一下)相当于一个低维的子空间;反过来,如果选得很小,则可以将任意的数据映射为线性可分——当然,这并不一定是好事,因为随之而来的可能是非常严重的过拟合问题。不过,总的来说,通过调控参数,高斯核实际上具有相当高的灵活性,也是使用最广泛的核函数之一。下图所示的例子便是把低维线性不可分的数据通过高斯核函数映射到了高维空间。

      其实到现在思路已经很清晰了,为了解决此维度县非线性分类的问题,引入映射,将数据特征映射到更高维度去提取线性特征,但是映射后的高纬度下必然造成计算量的增大,而利用构造特殊结构的核函数可以使得在低纬度进行內积运算之后再进行函数求解,很好的解决这一问题。


2.3 松弛变量处理outliers

      数据有噪音。对于这种偏离正常位置很远的数据点,我们称之为 outlier ,在我们原来的 SVM 模型里,outlier 的存在有可能造成很大的影响,因为超平面本身就是只有少数几个 support vector 组成的,如果这些 support vector 里又存在 outlier 的话,其影响就很大了。例如下图:

      用黑圈圈起来的那个蓝点是一个 outlier ,它偏离了自己原本所应该在的那个半空间,如果直接忽略掉它的话,原来的分隔超平面还是挺好的,但是由于这个 outlier 的出现,导致分隔超平面不得不被挤歪了,变成途中黑色虚线所示(这只是一个示意图,并没有严格计算精确坐标),同时 margin 也相应变小了。当然,更严重的情况是,如果这个 outlier 再往右上移动一些距离的话,我们将无法构造出能将数据分开的超平面来。

      为了处理这种情况,SVM 允许数据点在一定程度上偏离一下超平面。也就是说再进行超平面的最优化参数求取的时候,这些噪声点也是支持向量,只是他们的拉格朗日参数是通过我们手动设定的。

    我们,原来的约束条件为:

    现在考虑到outlier问题,约束条件变成了:

    其中称为松弛变量 (slack variable) ,对应数据点允许偏离的 functional margin 的量。当然,如果我们运行任意大的话,那任意的超平面都是符合条件的了。所以,我们在原来的目标函数后面加上一项,使得这些的总和也要最小:

    其中 是一个参数,用于控制目标函数中两项(“寻找 margin 最大的超平面”和“保证数据点偏差量最小”)之间的权重。注意,其中 是需要优化的变量(之一),而 是一个事先确定好的常量。完整地写出来是这个样子:

    用之前的方法将限制或约束条件加入到目标函数中,得到新的拉格朗日函数,如下所示:

     分析方法和前面一样,转换为另一个问题之后,我们先让针对最小化:

     将  带回 并化简,得到和原来一样的目标函数:

     不过,由于我们得到而又有(作为 Lagrange multiplier 的条件),因此有,所以整个 dual 问题现在写作:

3 代码实现

 人脸识别:https://github.com/coneypo/ML_handwritten_number

 

# -*- coding: utf-8 -*-
"""
Created on Fri Apr 27 15:54:58 2018

@author: 王乾
"""
import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC # "Support vector classifier"
from sklearn.datasets import make_classification,make_blobs
model = SVC(kernel='linear')
X = np.array([[0,0], [1,1]])
y = np.array([0,1])
model.fit(X,y)
'''
from sklearn.svm import LinearSVC
from sklearn.datasets import make_classification
X, y = make_classification(n_features=4, random_state=0)
clf = LinearSVC(random_state=0)
clf.fit(X, y)
#print(clf.coef_)
'''
def plot_svc_decision_function(model, ax=None, plot_support=True):

 if ax is None:
    ax = plt.gca()#Get Current Axes获取当前轴线
 xlim = ax.get_xlim()
 ylim = ax.get_ylim()

 # create grid to evaluate model
 x = np.linspace(xlim[0], xlim[1], 30)
 y = np.linspace(ylim[0], ylim[1], 30)
 Y, X = np.meshgrid(y, x)
 xy = np.vstack([X.ravel(), Y.ravel()]).T
 P = model.decision_function(xy).reshape(X.shape)

 # plot decision boundary and margins
 ax.contour(X, Y, P, colors='k',
           levels=[-1, 0, 1], alpha=0.5,
           linestyles=['--', '-', '--'])

 # plot support vectors
 if plot_support:
     ax.scatter(model.support_vectors_[:, 0],
               model.support_vectors_[:, 1],
               s=300, linewidth=1, facecolors='none');
 ax.set_xlim(xlim)
 ax.set_ylim(ylim)


plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
plot_svc_decision_function(model);


model.support_vectors_


#加入径向基函数, 核设为 rbf
clf = SVC(kernel='rbf', C=1E6)
clf.fit(X, y)




X, y = make_blobs(n_samples=100, centers=2,
                  random_state=0, cluster_std=0.8)

fig, ax = plt.subplots(1, 2, figsize=(16, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)

for axi, C in zip(ax, [10.0, 0.1]):
    model = SVC(kernel='linear', C=C).fit(X, y)
    axi.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    plot_svc_decision_function(model, axi)
    axi.scatter(model.support_vectors_[:, 0],
                model.support_vectors_[:, 1],
                s=300, lw=1, facecolors='none');
    axi.set_title('C = {0:.1f}'.format(C), size=14)
    
    
    

X, y = make_blobs(n_samples=100, centers=2,
                  random_state=0, cluster_std=1.1)

fig, ax = plt.subplots(1, 2, figsize=(16, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
# wspace调整图像边框,使得各个图之间的间距为0

for axi, gamma in zip(ax, [10.0, 0.1]):
    model = SVC(kernel='rbf', gamma=gamma).fit(X, y)
    axi.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    plot_svc_decision_function(model, axi)
    axi.scatter(model.support_vectors_[:, 0],
                model.support_vectors_[:, 1],
                s=300, lw=1, facecolors='none');
    axi.set_title('gamma = {0:.1f}'.format(gamma), size=14)


参考文献及推荐阅读

  1. 斯坦福大学机器学习课程原始讲义:http://www.cnblogs.com/jerrylead/archive/2012/05/08/2489725.html
  2. 斯坦福机器学习课程笔记:http://www.cnblogs.com/jerrylead/tag/Machine%20Learning/
  3. 支持向量机通俗导论:https://blog.csdn.net/v_july_v/article/details/7624837#commentBox
  4. KKT条件介绍:https://blog.csdn.net/johnnyconstantine/article/details/46335763
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值