zoukankan      html  css  js  c++  java
  • SVM

    网址:https://www.cnblogs.com/further-further-further/p/9596898.html
    朗格朗日极大极小问题的证明:https://www.cnblogs.com/breezezz/p/11303722.html

    1. 解决什么问题?
      最基本的应用是数据分类,特别是对于非线性不可分数据集。支持向量机不仅能对非线性可分数据集进行分类,对于非线性不可分数据集的也可以分类
      (我认为这才是支持向量机的真正魅力所在,因为现实场景中,样本数据往往是线性不可分的)。
      现实场景一 :样本数据大部分是线性可分的,但是只是在样本中含有少量噪声或特异点,去掉这些噪声或特异点后线性可分 => 用支持向量机的软间隔方法进行分类;
      现实场景二:样本数据完全线性不可分 => 引入核函数,将低维不可分的非线性数据集转化为高维可分的数据集,用支持向量机的软间隔方法进行分类;

    一定要明白一点:对分类器准确性有影响只是样本中的支持向量,因此,其他样本在计算分类器的权重矩阵时可以直接过滤掉,大大节省运行时间。
    目标:获取离边界最近样本点到超平面最远距离

    1. SVM的思想演化?
      博客 https://www.cnblogs.com/zhizhan/p/4430253.html 关于SVM的演化说得很透彻,也很形象,这里借用一下。
      2.1 硬间隔支持向量机
      SVM中最关键的思想之一就是引入和定义了“间隔”这个概念。这个概念本身很简单,以二维空间为例,就是点到分类直线之间的距离。假设直线为y=wx+b,那么只要使所有正分类点到该直线的距离与所有负分类点到该直线的距离的总和达到最大,这条直线就是最优分类直线。这样,原问题就转化为一个约束优化问题,可以直接求解。这叫做硬间隔最大化,得到的SVM模型称作硬间隔支持向量机。
      2.2 软间隔支持向量机
      但是新问题出现了,在实际应用中,我们得到的数据并不总是完美的线性可分的,其中可能会有个别噪声点,他们错误的被分类到了其他类中。如果将这些特异的噪点去除后,可以很容易的线性可分。但是,我们对于数据集中哪些是噪声点却是不知道的,如果以之前的方法进行求解,会无法进行线性分开。是不是就没办法了呢?假设在y=x+1直线上下分为两类,若两类中各有对方的几个噪点,在人的眼中,仍然是可以将两类分开的。这是因为在人脑中是可以容忍一定的误差的,仍然使用y=x+1直线分类,可以在最小误差的情况下进行最优的分类。同样的道理,我们在SVM中引入误差的概念,将其称作“松弛变量”。通过加入松弛变量,在原距离函数中需要加入新的松弛变量带来的误差,这样,最终的优化目标函数变成了两个部分组成:距离函数和松弛变量误差。这两个部分的重要程度并不是相等的,而是需要依据具体问题而定的,因此,我们加入权重参数C,将其与目标函数中的松弛变量误差相乘,这样,就可以通过调整C来对二者的系数进行调和。如果我们能够容忍噪声,那就把C调小,让他的权重降下来,从而变得不重要;反之,我们需要很严格的噪声小的模型,则将C调大一点,权重提升上去,变得更加重要。通过对参数C的调整,可以对模型进行控制。这叫做软间隔最大化,得到的SVM称作软间隔支持向量机。
      2.3 非线性支持向量机
      之前的硬间隔支持向量机和软间隔支持向量机都是解决线性可分数据集或近似线性可分数据集的问题的。但是如果噪点很多,甚至会造成数据变成了线性不可分的,那该怎么办?最常见的例子是在二维平面笛卡尔坐标系下,以原点(0,0)为圆心,以1为半径画圆,则圆内的点和圆外的点在二维空间中是肯定无法线性分开的。但是,学过初中几何就知道,对于圆圈内(含圆圈)的点:x^2+y^2≤1,圆圈外的则x^2+y^2>1。我们假设第三个维度:z=x^2+y^2,那么在第三维空间中,可以通过z是否大于1来判断该点是否在圆内还是圆外。这样,在二维空间中线性不可分的数据在第三维空间很容易的线性可分了。这就是非线性支持向量机。
      实际中,对某个实际问题函数来寻找一个合适的空间进行映射是非常困难的,幸运的是,在计算中发现,我们需要的只是两个向量在新的映射空间中的内积结果,而映射函数到底是怎么样的其实并不需要知道。这一点不太好理解,有人会问,既然不知道映射函数,那怎么能知道映射后在新空间中的内积结果呢?答案其实是可以的。这就需要引入了核函数的概念。核函数是这样的一种函数:仍然以二维空间为例,假设对于变量x和y,将其映射到新空间的映射函数为φ,则在新空间中,二者分别对应φ(x)和φ(y),他们的内积则为<φ(x),φ(y)>。我们令函数Kernel(x,y)=<φ(x),φ(y)>=k(x,y),可以看出,函数Kernel(x,y)是一个关于x和y的函数!而与φ无关!这是一个多么好的性质!我们再也不用管φ具体是什么映射关系了,只需要最后计算Kernel(x,y)就可以得到他们在高维空间中的内积,这样就可以直接带入之前的支持向量机中计算!
      核函数不是很好找到,一般是由数学家反向推导出来或拼凑出来的。现在知道的线性核函数有多项式核函数、高斯核函数等。其中,高斯核函数对应的支持向量机是高斯径向基函数(RBF),是最常用的核函数。

    RBF核函数可以将维度扩展到无穷维的空间,因此,理论上讲可以满足一切映射的需求。为什么会是无穷维呢?我以前都不太明白这一点。后来老师讲到,RBF对应的是泰勒级数展开,在泰勒级数中,一个函数可以分解为无穷多个项的加和,其中,每一个项可以看做是对应的一个维度,这样,原函数就可以看做是映射到了无穷维的空间中。这样,在实际应用中,RBF是相对最好的一个选择。当然,如果有研究的话,还可以选用其他核函数,可能会在某些问题上表现更好。但是,RBF是在对问题不了解的情况下,对最广泛问题效果都很不错的核函数。因此,使用范围也最广。
    3. SVM原理
    3.1 目标函数
    求使几何间隔最大的分离超平面

    以及相应的分类决策函数

    也就是求出w,b
    3.2 几何间隔定义

    3.3 学习的对偶算法
    为了求解线性可分支持向量机的最优化问题,将它作为原始最优化问题,应用拉格朗日对偶性,通过求解对偶问题得到原始问题最优解。

    3.4 最大软间隔分类器(线性可分支持向量学习的最优化问题)
    这就是线性可分支持向量机的对偶算法,这样做的优点,一是对偶问题往往更容易求解;二是自然引入核函数,进而推广到非线性分类问题。

    的求解就转化为 的求解。上述公式就是对不同变量求偏导,具体推导过程见《统计学习方法》第7章 或者相关博客。
    3.5 KKT条件

    上图的总结有点小问题,分类不能合并,正确的分类描述应该是:

    在超平面上或误分的样本点是不能正确分类的。
    4. SMO算法(sequential minimal optimization 序列最小最优化)
    高效实现支持向量机的算法是SMO算法,其基本思路是:如果所有变量的解都满足此最优化的KKT条件,那么这个最优化问题的解就得到了。因为KKT条件是该优化问题的充分必要条件。否则,
    选择两个变量,固定其他变量,针对这两个变量构建一个二次规划问题,这个二次规划问题关于这两个变量的解应该更接近原始二次规划问题的解,因为这会使原始二次规划问题的目标函数值变得更小。
    重要的是,这时子问题可以通过解析方法求解,这样可以大大提高整个算法的计算速度。
    子问题有两个变量,一个是违反KKT条件最严重的那一个,另一个由约束条件自动确定。如此,SMO算法将原问题不断分解为子问题并对子问题求解,进而达到求解原问题的目的。

    并且 推出

    4.1 范围

    假定不固定,其他拉格朗日因子固定(也就是常量),得到
    常量 , 为变量, 为因变量,L,H的范围就是 的 范围

    4.2 计算拉格朗日乘子 ,
    第一个 公式如下,推导过程见《统计学习方法》第7章或者相关博客。

    选择一个违背KKT的数据项,根据下面结论得到优化后 ,

    s表示,从而可以得到另一个优化后的 ,同样也需要进行约束。
    4.3 计算b1,b2
    在每次完成两个变量的优化后,都要重新计算阈值b。具体推导见《统计学习方法》

    1. 代码实现
      5.1 输入数据
      这里使用两个原始数据文件 trainingData.txt,testData.txt。
      trainingData.txt
      原始训练数据

    testData.txt
    原始测试数据

    5.2 SMO算法实现
    定义数据结构体optStruct,用于缓存,提高运行速度。SMO算法具体实现如下(mySVMMLiA.py)
    每个方法的作用,以及每行代码的作用,我都做了详细的注解,希望对大家的理解有帮助。
    SMO算法实现

    5.3 测试代码(testMySVMMLiA.py)

    测试代码

    通过训练数据计算出 b, 权重矩阵,从而分类超平面和决策分类函数就明确了,然后测试数据以决策分类函数进行预测。
    这里采用高斯核RBF。
    5.4 运行结果

    “j not moving enough, abandon it” 表示数据项对应的 和 非常接近,不需要优化;
    “fullSet” 表示全量数据遍历;
    “non-bound” 表示非边界遍历,也就是只遍历属于支持向量的数据项。

    另外我将支持向量的数据项绘制出来了,这样更直观。

    可以看出,有77个支持向量,训练差错率是0,测试差错率6%。

  • 相关阅读:
    matplotlib 进阶之origin and extent in imshow
    Momentum and NAG
    matplotlib 进阶之Tight Layout guide
    matplotlib 进阶之Constrained Layout Guide
    matplotlib 进阶之Customizing Figure Layouts Using GridSpec and Other Functions
    matplotlb 进阶之Styling with cycler
    matplotlib 进阶之Legend guide
    Django Admin Cookbook-10如何启用对计算字段的过滤
    Django Admin Cookbook-9如何启用对计算字段的排序
    Django Admin Cookbook-8如何在Django admin中优化查询
  • 原文地址:https://www.cnblogs.com/131415-520/p/12356722.html
Copyright © 2011-2022 走看看