精华内容
下载资源
问答
  • svm算法原理
    2019-07-13 16:39:00

    SVM算法原理

    转载于:https://www.cnblogs.com/liuys635/p/11181166.html

    更多相关内容
  • SVM算法原理详解及python实现

    千次阅读 2020-05-26 22:13:25
    SVM算法算法原理对数据的要求算法的优缺点算法需要注意的点算法实现(python)(待更.........) 算法原理 {wTx+b>0yi=1⟺y(xi)>0wTx+b<0yi=−1⟺y(xi)<0\begin{cases} w^Tx+b>0 \quad y_i=1 \...

    算法原理

    { w T x + b > 0 y i = 1 ⟺ y ( x i ) > 0 w T x + b < 0 y i = − 1 ⟺ y ( x i ) < 0 \begin{cases} w^Tx+b>0 \quad y_i=1 \Longleftrightarrow y(x_i)>0\\ w^Tx+b<0 \quad y_i=-1 \Longleftrightarrow y(x_i)<0\\ \end{cases} {wTx+b>0yi=1y(xi)>0wTx+b<0yi=1y(xi)<0
    将点到直线的距离转化为: ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ ( 几 何 间 距 ) ⟺ y i ∣ w T x + b ∣ ⩾ 0 ∣ ∣ w ∣ ∣ ( 函 数 间 隔 ) \frac{|w^Tx+b|}{||w||}(几何间距)\Longleftrightarrow\frac{y_i|w^Tx+b|\geqslant0}{||w||}(函数间隔) wwTx+b()wyiwTx+b0()

    进行缩放变换:使 ∣ Y ∣ ⩾ 1 ⇒ y i ∣ w T x + b ∣ ⩾ 1 |Y|\geqslant1\Rightarrow y_i|w^Tx+b|\geqslant1 Y1yiwTx+b1(之前我们认为恒大于0,现在严格了些)

    优化目标: a r g m a x ( w , b ) { 1 ∣ ∣ w ∣ ∣ m i n ( i ) [ y i ( w T x + b ) ] } argmax(w,b)\{\frac{1}{||w||}min(i)[y_i(w^Tx+b)]\} argmax(w,b){w1min(i)[yi(wTx+b)]}

    优化目标: a r g m a x ( w , b ) { 1 ∣ ∣ w ∣ ∣ } s t . y i ∣ w T x + b ∣ ⩾ 1 argmax(w,b)\{\frac{1}{||w||}\} \quad st. y_i|w^Tx+b|\geqslant1 argmax(w,b){w1}st.yiwTx+b1

    优化目标: m i n ( w , b ) { 1 2 ∣ ∣ w ∣ ∣ 2 } s t . y i ∣ w T x + b ∣ ⩾ 1 min(w,b)\{\frac{1}{2}{||w||^2}\} \quad st. y_i|w^Tx+b|\geqslant1 min(w,b){21w2}st.yiwTx+b1

    拉格朗日乘子法求解: L ( ω , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ i = 1 n α i ( y i ( w T x i + b ) − 1 ) s t . y i ∣ w T x + b ∣ ⩾ 1 L(\omega,b,\alpha)=\frac{1}{2}{||w||^2}-\sum_{i=1}^n\alpha_i(y_i(w^Tx_i+b)-1) \quad st. y_i|w^Tx+b|\geqslant1 L(ω,b,α)=21w2i=1nαi(yi(wTxi+b)1)st.yiwTx+b1

    求导可得:
    { ∂ L ∂ ω = ω − ∑ i = 1 n α i y i x i = 0 ∂ L ∂ b = ∑ i = 1 n α i y i = 0 \begin{cases} \frac{\partial L}{\partial \omega}=\omega-\sum_{i=1}^n\alpha_iy_ix_i=0\\ \frac{\partial L}{\partial b}=\sum_{i=1}^n\alpha_iy_i=0\\ \end{cases} {ωL=ωi=1nαiyixi=0bL=i=1nαiyi=0

    将求导后的式子带入L可得: L ( ω , b , α ) = ∑ i = 1 n α i − 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j x i x j s t . ∑ i = 1 n α i y i ⩾ 0 且 α i ⩾ 0 L(\omega,b,\alpha)=\sum_{i=1}^n\alpha_i-\frac{1}{2}\sum_{i=1}^n\sum_{j=1}^n\alpha_i\alpha_jy_iy_jx_ix_j \quad st. \sum_{i=1}^n\alpha_iy_i\geqslant0且\alpha_i\geqslant0 L(ω,b,α)=i=1nαi21i=1nj=1nαiαjyiyjxixjst.i=1nαiyi0αi0

    求解得:
    { α i = 0 不 是 支 持 向 量 α i ≠ 0 是 支 持 向 量 \begin{cases} \alpha_i=0\quad不是支持向量\\ \alpha_i\ne0\quad是支持向量 \end{cases} {αi=0αi=0

    对数据的要求

    1. 对于 缺失值需要处理(填充或者删除)
    2. 分类变量需要编码(涉及距离计算)
    3. 数据需要标准化或者归一化处理(消除量纲的影响。涉及距离计算的算法都需要考虑)

    算法的优缺点

    一、优点
    1.SVM只由支持向量决定,计算的复杂度取决于支持向量的数量,在某种意义上避免‘维度灾难’
    2. 具有一定的鲁棒性(增删非支持向量对模型无影响)
    3. 理论完善

    一、缺点
    1.大规模训练样本难以实施,存储与计算将耗费大量内存与时间
    2.对缺失数据敏感
    3. 可解释能力弱
    4. 解决多分类问题困难
    5. 核函数选择不易

    算法需要注意的点

    1. SVM几种原理
    1、线性可分: 硬间隔最大化
    2、线性近似可分(有个别点偏移): 引入松弛变量(软间隔最大化)
    3、非线性支持向量机(引入线性核函数(实际求解时不在高维上,因为可能无穷维,求解不易),线性不可分): 高斯核 K ( x , x i ) = e x p ( − ∣ ∣ x − x i ∣ ∣ 2 σ 2 ) ( σ 小 会 带 来 过 拟 合 ) K(x,x_i)=exp(-\frac{||x-x_i||^2}{\sigma^2})(\sigma小会带来过拟合) K(x,xi)=exp(σ2xxi2)(σ)

    2. SVM为什么采用间隔最大化?
    获得最优解,泛化能力最强(因为解有无穷多个)

    3. SVM处理多分类问题?
    1、一对多: 将某一类归一类,其余类归一类共训练K个类K个分类器,用K个分类器来测试新样本,哪个分类器概率(p)高就预测为哪一类(bias较高)
    2、一对一: 任意两个类训练一个分类器,一共训练 C k 2 C_k^2 Ck2个分类器,最后投票判别

    算法实现(python)(待更…)

    展开全文
  • SVM算法原理及实现

    千次阅读 2019-03-06 18:39:01
    SVM算法原理及实现 转自:https://blog.csdn.net/d__760/article/details/80387432 Svm(support Vector Mac)又称为支持向量机,是一种二分类的模型。当然如果进行修改之后也是可以用于多类别问题的分类。支持...

    SVM算法原理及实现

    转自:https://blog.csdn.net/d__760/article/details/80387432

          Svm(support Vector Mac)又称为支持向量机,是一种二分类的模型。当然如果进行修改之后也是可以用于多类别问题的分类。支持向量机可以分为线性核非线性两大类。其主要思想为找到空间中的一个更够将所有数据样本划开的超平面,并且使得本本集中所有数据到这个超平面的距离最短。

    一、基于最大间隔分隔数据

    1.1支持向量与超平面

        在了解svm算法之前,我们首先需要了解一下线性分类器这个概念。比如给定一系列的数据样本,每个样本都有对应的一个标签。为了使得描述更加直观,我们采用二维平面进行解释,高维空间原理也是一样。举个简单子:如下图所示是一个二维平面,平面上有两类不同的数据,分别用圆圈和方块表示。我们可以很简单地找到一条直线使得两类数据正好能够完全分开。但是能将据点完全划开直线不止一条,那么在如此众多的直线中我们应该选择哪一条呢?从直观感觉上看图中的几条直线,是不是要更好一些呢?是的我们就是希望寻找到这样的直线,使得距离这条直线最近的点到这条直线的距离最短。这读起来有些拗口,我们从图三中直观来解释这一句话就是要求的两条外面的线之间的间隔最大。这是可以理解的,因为假如数据样本是随机出现的,那么这样分割之后数据点落入到其类别一侧的概率越高那么最终预测的准确率也会越高。在高维空间中这样的直线称之为超平面,因为当维数大于三的时候我们已经无法想象出这个平面的具体样子。那些距离这个超平面最近的点就是所谓支持向量,实际上如果确定了支持向量也就确定了这个超平面,找到这些支持向量之后其他样本就不会起作用了。

                                      图 1                                                 图2

     

    1.2寻找最大间隔

    1.2.1点到超平面的距离公式

          既然这样的直线是存在的,那么我们怎样寻找出这样的直线呢?与二维空间类似,超平面的方程也可以写成一下形式:

                                                                                                 (1.1)

    有了超平面的表达式之后之后,我们就可以计算样本点到平面的距离了。假设为样本的中的一个点,其中表示为第个特征变量。那么该点到超平面的距离就可以用如下公式进行计算:

                                                                             (1.2)

     

    其中||W||为超平面的范数,常数b类似于直线方程中的截距。

    上面的公式可以利用解析几何或高中平面几何知识进行推导,这里不做进一步解释。

    1.2.2最大间隔的优化模型

        现在我们已经知道了如何去求数据点到超平面的距离,在超平面确定的情况下,我们就能够找出所有支持向量,然后计算出间隔margin。每一个超平面都对应着一个margin,我们的目标就是找出所有margin中最大的那个值对应的超平面。因此用数学语言描述就是确定w、b使得margin最大。这是一个优化问题其目标函数可以写成:

                                             (1.3)

    其中表示数据点的标签,且其为-1或1。距离用计算,这是就能体会出-1和1的好处了。如果数据点在平面的正方向(即+1类)那么是一个正数,而当数据点在平面的负方向时(即-1类),依然是一个正数,这样就能够保证始终大于零了。注意到当w和b等比例放大时,d的结果是不会改变的。因此我们可以令所有支持向量的u为1,而其他点的u大1这是可以办通过调节w和b求到的。因此上面的问题可以简化为:                     (1.4)

    为了后面计算的方便,我们将目标函数等价替换为:

                                                                   (1.5)

    这是一个有约束条件的优化问题,通常我们可以用拉格朗日乘子法来求解。拉格朗日乘子法的介绍可以参考这篇博客。应用拉格朗日乘子法如下:

    令                                (1.6)

    求L关于求偏导数得:                          (1.7)

    将(1.7)代入到(1.6)中化简得:

                                          (1.8)

    原问题的对偶问题为:

                                                  (1.9)

    该对偶问题的KKT条件为

                                    (1.10)

        到此,似乎问题就能够完美地解决了。但是这里有个假设:数据必须是百分之百可分的。但是实际中的数据几乎都不那么“干净”,或多或少都会存在一些噪点。为此下面我们将引入了松弛变量来解决这种问题。

    1.2.3松弛变量

        由上一节的分析我们知道实际中很多样本数据都不能够用一个超平面把数据完全分开。如果数据集中存在噪点的话,那么在求超平的时候就会出现很大问题。从图三中课看出其中一个蓝点偏差太大,如果把它作为支持向量的话所求出来的margin就会比不算入它时要小得多。更糟糕的情况是如果这个蓝点落在了红点之间那么就找不出超平面了。

                                       

                                                             图 3

    因此引入一个松弛变量ξ来允许一些数据可以处于分隔面错误的一侧。这时新的约束条件变为:

      (1.11)

    式中ξi的含义为允许第i个数据点允许偏离的间隔。如果让ξ任意大的话,那么任意的超平面都是符合条件的了。所以在原有目标的基础之上,我们也尽可能的让ξ的总量也尽可能地小。所以新的目标函数变为:

    (1.12)

    (1.13)

    其中的C是用于控制“最大化间隔”和“保证大部分的点的函数间隔都小于1”这两个目标的权重。将上述模型完整的写下来就是:

    (1.14)

    新的拉格朗日函数变为:

    (1.15)

    接下来将拉格朗日函数转化为其对偶函数,首先对分别求ξ的偏导,并令其为0,结果如下:

    (1.16)

    代入原式化简之后得到和原来一样的目标函数:

    (1.17)

    但是由于我们得到,因此有所以对偶问题写成:

    (1.18)

    经过添加松弛变量的方法,我们现在能够解决数据更加混乱的问题。通过修改参数C,我们可以得到不同的结果而C的大小到底取多少比较合适,需要根据实际问题进行调节。

    1.2.4核函数

        以上讨论的都是在线性可分情况进行讨论的,但是实际问题中给出的数据并不是都是线性可分的,比如有些数据可能是如图4样子。      

                                                              图4

    那么这种非线性可分的数据是否就不能用svm算法来求解呢?答案是否定的。事实上,对于低维平面内不可分的数据,放在一个高维空间中去就有可能变得可分。以二维平面的数据为例,我们可以通过找到一个映射将二维平面的点放到三维平面之中。理论上任意的数据样本都能够找到一个合适的映射使得这些在低维空间不能划分的样本到高维空间中之后能够线性可分。我们再来看一下之前的目标函数:

    (1.19)

    定义一个映射使得将所有映射到更高维空间之后等价于求解上述问题的对偶问题:

    (1.20)

    这样对于线性不可分的问题就解决了,现在只需要找出一个合适的映射即可。当特征变量非常多的时候在,高维空间中计算内积的运算量是非常庞大的。考虑到我们的目的并不是为找到这样一个映射而是为了计算其在高维空间的内积,因此如果我们能够找到计算高维空间下内积的公式,那么就能够避免这样庞大的计算量,我们的问题也就解决了。实际上这就是我们要找的核函数,即两个向量在隐式映射后的空间中的内积。下面的一个简单例子可以帮助我们更好地理解核函数。

    通过以上例子,我们可以很明显地看到核函数是怎样运作的。上述问题的对偶问题可以写成如下形式:

    (1.21)

    那么怎样的函数才可以作为核函数呢?下面的一个定理可以帮助我们判断。

    Mercer定理:任何半正定的函数都可以作为核函数。其中所谓半正定函数是指拥有训练集数据集合,我们定义一个矩阵的元素,这个矩阵是的矩阵,如果这个矩阵是半正定的,那么就称为半正定函数。

    值得注意的是,上述定理中所给出的条件是充分条件而非充要条件。因为有些非正定函数也可以作为核函数。

    下面是一些常用的核函数:

                                                 表1 常用核函数表

    核函数名称

    核函数表达式

    核函数名称

    核函数表达式

    线性核

    指数核

    多项式核

    拉普拉斯核

    高斯核

    Sigmoid核


        现在我们已经了解了一些支持向量机的理论基础,我们通过对偶问题的的转化将最开始求的问题转化为求的对偶问题。只要找到所有的(即找出所有支持向量),我们就能够确定。然后就可以通过计算数据点到这个超平面的距离从而判断出该数据点的类别。

    二、Smo算法原理

    2.1 约束条件

         根据以上问题的分析,我们已经将原始问题转化为了求的值,即求下面优化模型的解:

    (2.1)

    求解的值的方法有很多,Smo算法就是其中一种比较常用的方法。该算法是由John Platt在1996年发布,他的思路是将大的优化问题转化为小的优化问题。而这些小的优化问题往往更容易求解,并且对它们进行顺序求解的结果和将它们作为整体求解的结果完全一致但是Smo算法的时间要小得多。

         Smo算法的原理为:每次任意抽取两个乘子和,然后固定以外的其它乘子,使得目标函数只是关于的函数。然后增大其中一个乘子同时减少另外一个。这样,不断的从一堆乘子中任意抽取两个求解,不断的迭代求解子问题,最终达到求解原问题的目的。

         而原对偶问题的子问题的目标函数可以表达成:

    (2.2)

    其中:

    (2.3)

    这里之所以算两个是因为的限制,如果只改变其中的一个量,那么这个约束条件可能就不成立了。要解决这个问题,我们必须得选取这样的两个乘子。那么怎样确定这样的呢?这是我们首先要考虑的问题,在《机器学习实战》这本书中,作者首先给出了一种简化版的方法,遍历每一个然后在剩余的中随机选取一个进行优化。虽然样也能够解决问题,但是运算量太大,因此考虑找一种更好的方法来寻找对。

    为了表述方便,定义一个特征到输出结果的输出函数:

    (2.4)

    该对偶问题中KKT条件为:

    (2.5)

    根据上述问题的KKT条件可以得出目标函数中的的含义如下:

    1、 ,表明是正常分类,在边界外;

    2、,表明是支持向量,在边界上;

    3、,表明在两边界之间。

    最优解需要满足KKT条件,因此需要满足以上的三个条件都满足。而不满足这三个条件的情况也有三种:

    1、<=1但是<C则是不满足的,而原本=C;

    2、>=1但是>0则是不满足的,而原本=0;

    3、=1但是=0或者=C则表明不满足的,而原本应该是0<<C.

    也就是说如果存在不满足这些KKT条件的,我们就要更新它,这就是约束条件之一。其次,还受到约束条件的限制,因此假设选择的两个因子为,他们在更新前分别为在更新后为,为了保证上述约束条件成立必须要保证下列等式的成立:

    (2.6)

    其中为常数。

     

    2.2参数优化

        因为两个因子不好同时求解,所以可先求第二个乘子的解,然后再用的解表示的解。为了求解,得先确定的取值范围。假设它的上下边界分别为H和L,那么有:(2.6)

    接下来,综合这两个约束条件,求取的取值范围。

    时,根据可得,所以有

    时,同样根据可得:,所以有

    回顾第二个约束条件 :(2.7)

    令其两边同时乘y1,可得:

                              . (2.8)

    其中:.

    因此可以用表示,即:               (2.9)

    令                    (2.10)

    经过转化之后可得:

                       ,.        (2.11)

    那么如何来选择乘子呢?对于第一个乘子,我们可以按照3种不满足KTT的条件来寻找。对于第二个乘子,我们可以寻找满足条件的乘子。

    而b在满足以下条件时需要更新:

                           (2.12)

    且更新后的和如下:

                          (2.13)

    每次更新完两个乘子之后,都需要重新计算b以及对应的E。最后更新完所有的,y和b,这样模型也就出来了,从而可以计算出开始所说的分类函数:

    (2.14)

    三、Svm的python实现与应用

         第二节已经对Smo算法进行了充分的说明并进行了推导,现在一切都准备好了。接下来需要做的就是实现这些算法了,这里我参考了《机器学习实战》这本书中的代码,并利用该程序对一个问题进行了求解。由于代码数量过大,因此这里就不再列出,而是放在附录中。有兴趣的朋友可以直接下载,也可以去官网下载源代码。笔者在读这些代码的过程中,也遇到了许多困难,大部分都根据自己的情况进行了注释。

    3.1问题描述

        这里我选取的一个数据集为声呐数据集,该问题为需要根据声呐从不同角度返回的声音强度来预测被测物体是岩石还是矿井。数据集中共有208个数据,60个输入变量和1个输出变量。每个数据的前60个元素为不同方向返回的声音强度,最后一个元素为本次用于声呐测试的物体类型。其中标签M表示矿井,标签R为岩石。

    3.2数据预处理

        所给数据中没有缺失值和异常值,因此不需要对数据集进行清洗。注意到所给数据集的标签为字母类型,而svm算法的标准标签为“-1”和“1”的形式,所以需要对标签进行转化,用“-1”、“1”分别代替M和R。由于该数据集中所给标签相同的数据都放在了一起,因此先对数据顺序进行了打乱。代码如下:

    def loadDataSet(fileName):    

    dataMat=[];labelMat=[];data=[]    

    fr=open(fileName)

        for line in fr.readlines():

            line=line.replace(',','\t')#去除逗号 

           line=line.replace('M','-1')#对标签进行替换 

           line=line.replace('R','1'

           lineArr=line.strip('\n').split('\t')#分割数据 

           data.append([float(lineArr[i]) 

    for in range(len(lineArr))])

        random.shuffle(data)  #随机打乱列表 

      for in range(len(data)): 

           dataMat.append(data[i][0:len(data)-1]) 

           labelMat.append(data[i][-1]) 

       return dataMat,labelMat

    3.3模型训练及测试

        首先测试了一下将所有数据即作为训练集又作为测试集,然后用Smo模型进行训练找到所有的支持向量。最后根据训练好的模型进行求解,最终测试的准确率平均为54%。如果把数据集分成测试集和训练集,发现测试的准确率也在这附近。而根据网上数据统计该数据集测试的准确率最高为84%,一般情况下为百分之六十几。数据集本身是造成测试准确率低的一个原因,但是另外一个更加重要的原因大概是参数的选择问题。如何选取合适的参数是一个值得思考的问题,在接下来的学习过程中我也会注意一下参数选取这个问题。到这里,关于svm的算法就告一段落了。

     ​​​​​

    #svm算法的实现
    
    from numpy import*
    
    import random
    
    from time import*
    
    def loadDataSet(fileName):#输出dataArr(m*n),labelArr(1*m)其中m为数据集的个数
    
    dataMat=[];labelMat=[]
    
    fr=open(fileName)
    
    for line in fr.readlines():
    
    lineArr=line.strip().split('\t')#去除制表符,将数据分开
    
    dataMat.append([float(lineArr[0]),float(lineArr[1])])#数组矩阵
    
    labelMat.append(float(lineArr[2]))#标签
    
    return dataMat,labelMat
    
    
    def selectJrand(i,m):#随机找一个和i不同的j
    
    j=i
    
    while(j==i):
    
    j=int(random.uniform(0,m))
    
    return j
    
    
    def clipAlpha(aj,H,L):#调整大于H或小于L的alpha的值
    
    if aj>H:
    
    aj=H
    
    if aj<L:
    
    aj=L
    
    return aj
    
    
    def smoSimple(dataMatIn,classLabels,C,toler,maxIter):
    
    dataMatrix=mat(dataMatIn);labelMat=mat(classLabels).transpose()#转置
    
    b=0;m,n=shape(dataMatrix)#m为输入数据的个数,n为输入向量的维数
    
    alpha=mat(zeros((m,1)))#初始化参数,确定m个alpha
    
    iter=0#用于计算迭代次数
    
    while (iter<maxIter):#当迭代次数小于最大迭代次数时(外循环)
    
    alphaPairsChanged=0#初始化alpha的改变量为0
    
    for i in range(m):#内循环
    
    fXi=float(multiply(alpha,labelMat).T*\
    
    (dataMatrix*dataMatrix[i,:].T))+b#计算f(xi)
    
    Ei=fXi-float(labelMat[i])#计算f(xi)与标签之间的误差
    
    if ((labelMat[i]*Ei<-toler)and(alpha[i]<C))or\
    
    ((labelMat[i]*Ei>toler)and(alpha[i]>0)):#如果可以进行优化
    
    j=selectJrand(i,m)#随机选择一个j与i配对
    
    fXj=float(multiply(alpha,labelMat).T*\
    
    (dataMatrix*dataMatrix[j,:].T))+b#计算f(xj)
    
    Ej=fXj-float(labelMat[j])#计算j的误差
    
    alphaIold=alpha[i].copy()#保存原来的alpha(i)
    
    alphaJold=alpha[j].copy()
    
    if(labelMat[i]!=labelMat[j]):#保证alpha在0到c之间
    
    L=max(0,alpha[j]-alpha[i])
    
    H=min(C,C+alpha[j]-alpha[i])
    
    else:
    
    L=max(0,alpha[j]+alpha[i]-C)
    
    H=min(C,alpha[j]+alpha[i])
    
    if L==H:print('L=H');continue
    
    eta=2*dataMatrix[i,:]*dataMatrix[j,:].T-\
    
    dataMatrix[i,:]*dataMatrix[i,:].T-\
    
    dataMatrix[j,:]*dataMatrix[j,:].T
    
    if eta>=0:print('eta=0');continue
    
    alpha[j]-=labelMat[j]*(Ei-Ej)/eta
    
    alpha[j]=clipAlpha(alpha[j],H,L)#调整大于H或小于L的alpha
    
    if (abs(alpha[j]-alphaJold)<0.0001):
    
    print('j not move enough');continue
    
    alpha[i]+=labelMat[j]*labelMat[i]*(alphaJold-alpha[j])
    
    b1=b-Ei-labelMat[i]*(alpha[i]-alphaIold)*\
    
    dataMatrix[i,:]*dataMatrix[i,:].T-\
    
    labelMat[j]*(alpha[j]-alphaJold)*\
    
    dataMatrix[i,:]*dataMatrix[j,:].T#设置b
    
    b2=b-Ej-labelMat[i]*(alpha[i]-alphaIold)*\
    
    dataMatrix[i,:]*dataMatrix[i,:].T-\
    
    labelMat[j]*(alpha[j]-alphaJold)*\
    
    dataMatrix[j,:]*dataMatrix[j,:].T
    
    if (0<alpha[i])and(C>alpha[j]):b=b1
    
    elif(0<alpha[j])and(C>alpha[j]):b=b2
    
    else:b=(b1+b2)/2
    
    alphaPairsChanged+=1
    
    print('iter:%d i:%d,pairs changed%d'%(iter,i,alphaPairsChanged))
    
    if (alphaPairsChanged==0):iter+=1
    
    else:iter=0
    
    print('iteraction number:%d'%iter)
    
    return b,alpha
    
    #定义径向基函数
    
    def kernelTrans(X, A, kTup):#定义核转换函数(径向基函数)
    
    m,n = shape(X)
    
    K = mat(zeros((m,1)))
    
    if kTup[0]=='lin': K = X * A.T #线性核K为m*1的矩阵
    
    elif kTup[0]=='rbf':
    
    for j in range(m):
    
    deltaRow = X[j,:] - A
    
    K[j] = deltaRow*deltaRow.T
    
    K = exp(K/(-1*kTup[1]**2)) #divide in NumPy is element-wise not matrix like Matlab
    
    else: raise NameError('Houston We Have a Problem -- \
    
    That Kernel is not recognized')
    
    return K
    
    
    class optStruct:
    
    def __init__(self,dataMatIn, classLabels, C, toler, kTup): # Initialize the structure with the parameters
    
    self.X = dataMatIn
    
    self.labelMat = classLabels
    
    self.C = C
    
    self.tol = toler
    
    self.m = shape(dataMatIn)[0]
    
    self.alphas = mat(zeros((self.m,1)))
    
    self.b = 0
    
    self.eCache = mat(zeros((self.m,2))) #first column is valid flag
    
    self.K = mat(zeros((self.m,self.m)))
    
    for i in range(self.m):
    
    self.K[:,i] = kernelTrans(self.X, self.X[i,:], kTup)
    
    
    def calcEk(oS, k):
    
    fXk = float(multiply(oS.alphas,oS.labelMat).T*oS.K[:,k] + oS.b)
    
    Ek = fXk - float(oS.labelMat[k])
    
    return Ek
    
    
    def selectJ(i, oS, Ei):
    
    maxK = -1; maxDeltaE = 0; Ej = 0
    
    oS.eCache[i] = [1,Ei]
    
    validEcacheList = nonzero(oS.eCache[:,0].A)[0]
    
    if (len(validEcacheList)) > 1:
    
    for k in validEcacheList: #loop through valid Ecache values and find the one that maximizes delta E
    
    if k == i: continue #don't calc for i, waste of time
    
    Ek = calcEk(oS, k)
    
    deltaE = abs(Ei - Ek)
    
    if (deltaE > maxDeltaE):
    
    maxK = k; maxDeltaE = deltaE; Ej = Ek
    
    return maxK, Ej
    
    else: #in this case (first time around) we don't have any valid eCache values
    
    j = selectJrand(i, oS.m)
    
    Ej = calcEk(oS, j)
    
    return j, Ej
    
    
    def updateEk(oS, k):#after any alpha has changed update the new value in the cache
    
    Ek = calcEk(oS, k)
    
    oS.eCache[k] = [1,Ek]
    
    
    def innerL(i, oS):
    
    Ei = calcEk(oS, i)
    
    if ((oS.labelMat[i]*Ei < -oS.tol) and (oS.alphas[i] < oS.C)) or ((oS.labelMat[i]*Ei > oS.tol) and (oS.alphas[i] > 0)):
    
    j,Ej = selectJ(i, oS, Ei) #this has been changed from selectJrand
    
    alphaIold = oS.alphas[i].copy(); alphaJold = oS.alphas[j].copy()
    
    if (oS.labelMat[i] != oS.labelMat[j]):
    
    L = max(0, oS.alphas[j] - oS.alphas[i])
    
    H = min(oS.C, oS.C + oS.alphas[j] - oS.alphas[i])
    
    else:
    
    L = max(0, oS.alphas[j] + oS.alphas[i] - oS.C)
    
    H = min(oS.C, oS.alphas[j] + oS.alphas[i])
    
    if L==H: print("L==H"); return 0
    
    eta = 2.0 * oS.K[i,j] - oS.K[i,i] - oS.K[j,j] #changed for kernel
    
    if eta >= 0: print("eta>=0"); return 0
    
    oS.alphas[j] -= oS.labelMat[j]*(Ei - Ej)/eta
    
    oS.alphas[j] = clipAlpha(oS.alphas[j],H,L)
    
    updateEk(oS, j) #added this for the Ecache
    
    if (abs(oS.alphas[j] - alphaJold) < 0.00001): print("j not moving enough"); return 0
    
    oS.alphas[i] += oS.labelMat[j]*oS.labelMat[i]*(alphaJold - oS.alphas[j])#update i by the same amount as j
    
    updateEk(oS, i) #added this for the Ecache #the update is in the oppostie direction
    
    b1 = oS.b - Ei- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.K[i,i] - oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.K[i,j]
    
    b2 = oS.b - Ej- oS.labelMat[i]*(oS.alphas[i]-alphaIold)*oS.K[i,j]- oS.labelMat[j]*(oS.alphas[j]-alphaJold)*oS.K[j,j]
    
    if (0 < oS.alphas[i]) and (oS.C > oS.alphas[i]): oS.b = b1
    
    elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2
    
    else: oS.b = (b1 + b2)/2.0
    
    return 1
    
    else: return 0
    
    #smoP函数用于计算超平的alpha,b
    
    def smoP(dataMatIn, classLabels, C, toler, maxIter,kTup=('lin', 0)): #完整的Platter SMO
    
    oS = optStruct(mat(dataMatIn),mat(classLabels).transpose(),C,toler, kTup)
    
    iter = 0#计算循环的次数
    
    entireSet = True; alphaPairsChanged = 0
    
    while (iter < maxIter) and ((alphaPairsChanged > 0) or (entireSet)):
    
    alphaPairsChanged = 0
    
    if entireSet: #go over all
    
    for i in range(oS.m):
    
    alphaPairsChanged += innerL(i,oS)
    
    print("fullSet, iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))
    
    iter += 1
    
    else:#go over non-bound (railed) alphas
    
    nonBoundIs = nonzero((oS.alphas.A > 0) * (oS.alphas.A < C))[0]
    
    for i in nonBoundIs:
    
    alphaPairsChanged += innerL(i,oS)
    
    print("non-bound, iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))
    
    iter += 1
    
    if entireSet: entireSet = False #toggle entire set loop
    
    elif (alphaPairsChanged == 0): entireSet = True
    
    print("iteration number: %d" % iter)
    
    return oS.b,oS.alphas
    
    #calcWs用于计算权重值w
    
    def calcWs(alphas,dataArr,classLabels):#计算权重W
    
    X = mat(dataArr); labelMat = mat(classLabels).transpose()
    
    m,n = shape(X)
    
    w = zeros((n,1))
    
    for i in range(m):
    
    w += multiply(alphas[i]*labelMat[i],X[i,:].T)
    
    return w
    
    
    #值得注意的是测试准确与k1和C的取值有关。
    
    def testRbf(k1=1.3):#给定输入参数K1
    
    #测试训练集上的准确率
    
    dataArr,labelArr = loadDataSet('testSetRBF.txt')#导入数据作为训练集
    
    b,alphas = smoP(dataArr, labelArr, 200, 0.0001, 10000, ('rbf', k1)) #C=200 important
    
    datMat=mat(dataArr); labelMat = mat(labelArr).transpose()
    
    svInd=nonzero(alphas.A>0)[0]#找出alphas中大于0的元素的位置
    
    #此处需要说明一下alphas.A的含义
    
    sVs=datMat[svInd] #获取支持向量的矩阵,因为只要alpha中不等于0的元素都是支持向量
    
    labelSV = labelMat[svInd]#支持向量的标签
    
    print("there are %d Support Vectors" % shape(sVs)[0])#输出有多少个支持向量
    
    m,n = shape(datMat)#数据组的矩阵形状表示为有m个数据,数据维数为n
    
    errorCount = 0#计算错误的个数
    
    for i in range(m):#开始分类,是函数的核心
    
    kernelEval = kernelTrans(sVs,datMat[i,:],('rbf', k1))#计算原数据集中各元素的核值
    
    predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + b#计算预测结果y的值
    
    if sign(predict)!=sign(labelArr[i]): errorCount += 1#利用符号判断类别
    
    ### sign(a)为符号函数:若a>0则输出1,若a<0则输出-1.###
    
    print("the training error rate is: %f" % (float(errorCount)/m))
    
    #2、测试测试集上的准确率
    
    dataArr,labelArr = loadDataSet('testSetRBF2.txt')
    
    errorCount = 0
    
    datMat=mat(dataArr)#labelMat = mat(labelArr).transpose()此处可以不用
    
    m,n = shape(datMat)
    
    for i in range(m):
    
    kernelEval = kernelTrans(sVs,datMat[i,:],('rbf', k1))
    
    predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + b
    
    if sign(predict)!=sign(labelArr[i]): errorCount += 1
    
    print("the test error rate is: %f" % (float(errorCount)/m))
    
    def main():
    
    t1=time()
    
    dataArr,labelArr=loadDataSet('testSet.txt')
    
    b,alphas=smoP(dataArr,labelArr,0.6,0.01,40)
    
    ws=calcWs(alphas,dataArr,labelArr)
    
    testRbf()
    
    t2=time()
    
    print("程序所用时间为%ss"%(t2-t1))
    
    
    if __name__=='__main__':
    
    main()

                                                       后记

        这是第一次写博客,其中难免会出错,因此希望大家能够批评指正。首先非常感谢网上的一些朋友,在理解svm这算法他们给了我很多启发,在公式推导中给了我很多参考的地方。本文主要参考的资料是《机器学习实战》和《惊呼!理解svm的三种境界》这篇博客。对于svm虽然学的时间不长,但是对它一直有种特别的感觉。第一次听说svm是在做一个验证码识别问题的时候,但那时候我使用的是KNN算法,尽管效果还不错,但是我一直希望能够用svm算法来完成这个题目。本来这次是打算把这个问题一起解决的,但是由于时间关系,没有来得及做。只能等下次有空闲的时候再来做这个问题了。

     

     

    展开全文
  • SVM算法原理及其实现

    2018-12-23 13:43:39
    SVM的学习算法是求解凸二次规划的最优化算法。 支持向量机学习方法包含构建由简至繁的模型:线性可分支持向量机、线性支持向量机及非线性支持向量机。简单模型是复杂模型的基础,也是复杂模型的基础情...

    1.支持向量机

    支持向量机是一种二分类模型,SVM能构建出数据之间的非线性关系。svm的学习策略就是间隔最大化,学习一个线性分类器,可形式化为一个求凸二次规划的问题,也等价于正则化的合页损失函数最小化问题。SVM的学习算法是求解凸二次规划的最优化算法。

    支持向量机学习方法包含构建由简至繁的模型:线性可分支持向量机、线性支持向量机及非线性支持向量机。简单模型是复杂模型的基础,也是复杂模型的基础情况

    2.线性可分支持向量机

    给定线性可分训练数据集,通过间隔最大化或等价地求解相应的涂二次规划问题学习得到分离超平面为

    w^{*}*x+b^{*}=0

    以及相应的分类决策函数

    f(x)=sign(w^{*}*x+b^{*})

    称为线性可分支持向量机。

    函数间隔:分类预测的准确性及确信度

    间隔最大化:对数据集找到几何间隔最大的超平面意味着以充分大的确信度对训练数据进行分类

    剩余参考https://www.cnblogs.com/pinard/p/6097604.html

    展开全文
  • SVM算法原理及其Matlab应用.docx
  • SVM算法原理及Python实现

    万次阅读 多人点赞 2018-09-18 19:53:18
    Svm(support Vector Mac)又称为支持向量机,是一种二分类的模型。当然如果进行修改之后也是可以用于多类别问题的分类。支持向量机可以分为线性核非线性两... 在了解svm算法之前,我们首先需要了解一下线性分类器这...
  • SVM算法原理分析

    千次阅读 2017-07-23 08:15:16
    SVM算法: 算法背景:支持向量机方法是建立在统计学习理论的VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本...
  • Svm算法原理及实现

    万次阅读 多人点赞 2018-05-21 05:09:33
    Svm(support Vector Mac)又称为支持向量机,是一种二分类的模型。当然如果进行修改之后也是可以用于多类别...一、基于最大间隔分隔数据1.1支持向量与超平面 在了解svm算法之前,我们首先需要了解一下线性分类器这...
  • 本套代码是本人根据svm原理纯写的代码,并没有调用已经封装好的包,非常适用于初学者从原理上了解svm,包括线性svm
  • SVM算法原理讲解

    千次阅读 2021-02-13 23:20:23
    原文地址:svm算法 最通俗易懂讲解 最近在学习svm算法,借此文章记录自己的学习过程,在学习时很多处借鉴了z老师的讲义和李航的统计,若有不足的地方,请海涵;svm算法通俗的理解在二维上,就是找一分割线把两类...
  • svm基本原理,python代码实现,拉格朗日与KKT算法描述
  • SVM算法原理以及实现

    千次阅读 2019-04-10 10:27:25
    https://blog.csdn.net/d__760/article/details/80387432
  • 机器学习 SVM算法原理

    2012-09-17 09:11:57
    该资料非常详细的论述了SVM的理论基础,真的是非常详细,对需要学习SVM算法的人来说是非常好的资料
  • 小白学习机器学习---第六章:SVM算法原理(1)

    万次阅读 多人点赞 2018-03-30 20:24:46
    支持向量机是我们用于分类的一种算法。让我们以一个小故事的形式,开启我们的SVM之旅吧。在很久以前的情人节,一位大侠要去救他的爱人,但天空中的魔鬼和他玩了一个游戏。魔鬼在桌子上似乎有规律放了两种颜色的球,...
  • 支持向量机的原理这里也就不阐述了,我也不太会。我大概的理解就是和KNN一样是个分类器,可以想象以下,两类样本点可以用很多条线分开,但是那一条是最优呢?支持向量机中利用支持向量(可能是样本中的几个点,具体...
  • SVM算法-Python实现

    2014-09-01 19:28:38
    支持向量机算法的目的在于寻找一个超平面H(d),该超平面可以将训练集中的数据分开,且与类域边界的沿垂直于该超平面方向的距离最大,故SVM法亦被称为最大边缘(maximum margin)算法。待分样本集中的大部分样本不是...
  • SVM算法详细推导.pptx

    2020-04-09 09:33:09
    本文档包含SVM的详细推导过程和一些别的资料没有记载的理解。非常适合入门和想具体理解一些细微处的同学。
  • python机器学习 | SVM算法介绍及实现

    千次阅读 2020-12-09 12:07:38
    本篇博客具体学习参考: 1 【机器学习】支持向量机SVM及实例应用 2 【ML】支持向量机(SVM)从入门到放弃再到掌握 ...SVM算法介绍及实现1 SVM算法介绍-线性可分思路1.1 线性可分样本集与非线性可分样本集1.1.1 线性
  • (1)SVM可以表示为凸优化问题,因此可以利用已知的有效算法发现目标函数的全局最小值。而其他分类方法都采用一种基于贪心学习的策略来搜索假设空间,这种方法一般只能获得局部最优解。 (2) SVM通过最大化决策边界...
  • 支持向量机SVM算法原理笔记1

    千次阅读 2016-07-12 18:08:01
    最近在学习李航编写的《统计学习方法》一书,看到SVM这一章时遇到了一些困难,在翻阅很多资料之后对其有了一定的理解,所以打算写篇博客来记录一下,后面如果有时间也会把前面几章中的算法加以整理。在看这本书的...
  • svm算法原理

    2014-05-28 13:48:56
    这一系列文章对svm的介绍很详细,包括最小距离,songchi
  • 大白话SVM算法课程

    2021-06-15 16:20:47
    01_SVM之回顾梯度下降原理02_SVM之回顾有约束的最优化问题03_SVM之回顾有约束的最优化问题-KKT几何解释04_SVM之回顾有约束的最优化问题-KKT数学解释05_SVM之回顾距离公式和感知器模型06_SVM之感知器到SVM的引入07_...
  • 1. SVM算法特性:   1.1 训练好的模型的算法复杂度是由支持向量的个数决定的,而不是由数据的维度决定的。所以SVM不太容易产生overfitting  1.2 SVM训练出来的模型完全依赖于支持向量(Support Vectors), 即使...
  • 上一篇:基于OpenCV的 SVM算法实现数字识别(一)---理论基础 下一篇:基于OpenCV的 SVM算法实现数字识别(三)---SMO求解
  • 支持向量机SVM算法原理

    千次阅读 2019-05-08 17:26:09
    SVM 的英文叫 Support Vector Machine,中文名为支持向量机。它是常见的一种分类方法,在机器学习中,SVM 是有监督的学习模型。 什么是有监督的学习模型呢?它指的是我们需要事先对数据打上分类标签,这样机器就...
  • SVM 算法最初是用来解决二分类问题的,而在这个基础上进行扩展,也能够处理多分类问题以及回归问题。
  • 融合PCA、LDA和SVM算法的人脸识别.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,265
精华内容 11,706
关键字:

svm算法原理