zoukankan      html  css  js  c++  java
  • SVM原理与实践

    SVM迅速发展和完善,在解决小样本、非线性及高维模式识别问题中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中.从此迅速的发展起来,已经在许多领域(生物信息学,文本和手写识别等)都取得了成功的应用.在地球物理反演当中解决非线性反演也有显著成效,例如(SVM在预测地下水涌水量问题等).

     SVM中的一大亮点是在传统的最优化问题中提出了对偶理论,主要有最大最小对偶及拉格朗日对偶.

     SVM的关键在于核函数.低维空间向量集通常难于划分,解决的方法是将它们映射到高维空间.但这个办法带来的困难就是计算复杂度的增加,而核函数正好巧妙地解决了这个问题.也就是说,只要选用适当的核函数,就可以得到高维空间的分类函数.

     在确定了核函数之后,由于确定核函数的已知数据也存在一定的误差,考虑到推广性问题,因此引入了松弛系数以及惩罚系数两个参变量(注:引入松弛变量之后w依然是唯一的,但是b不是唯一的)来加以校正.在确定了核函数基础上,再经过大量对比实验等将这两个系数取定,该项研究就基本完成,适合相关学科或业务内应用,且有一定能力的推广性.

    原理

     

    SVM的优缺点:

    SVM优点:
    (1)内积核函数:非线性映射是SVM方法的理论基础,SVM利用内积核函数代替向高维空间的非线性映射;
    (2)最大化分类边际:对特征空间划分的最优超平面是SVM的目标,最大化分类边际的思想是SVM方法的核心;
    (3)支持向量:支持向量是SVM的训练结果,在SVM分类决策中起决定作用的是支持向量. SVM 的最终决策函数只由少数的支持向量所确定,计算的复杂性取决于支持向量的数目,而不是样本空间的维数,这在某种意义上避免了“维度灾难”;
    (4)坚实理论基础的新颖的小样本学习方法:SVM 是一种有坚实理论基础的新颖的小样本学习方法.它基本上不涉及概率测度及大数定律等,因此不同于现有的统计方法.从本质上看,它避开了从归纳到演绎的传统过程,实现了高效的从训练样本到预报样本的“转导推理”,大大简化了通常的分类和回归等问题;
    (5)鲁棒性:少数支持向量决定了最终结果,这不但可以帮助我们抓住关键样本、“剔除”大量冗余样本,而且注定了该方法不但算法简单,而且具有较好的“鲁棒”性.这种“鲁棒”性主要体现在:①增、删非支持向量样本对模型没有影响;②支持向量样本集具有一定的鲁棒性;③有些成功的应用中,SVM 方法对核的选取不敏感.

    不足:
    (1) SVM
    算法对大规模训练样本难以实施:
    由于SVM是借助二次规划来求解支持向量,而求解二次规划将涉及m阶矩阵的计算(m为样本的个数),当m数目很大时该矩阵的存储和计算将耗费大量的机器内存和运算时间.针对以上问题的主要改进有J.Platt的SMO算法、T.Joachims的SVM、C.J.C.Burges等的PCGC、张学工的CSVM以及O.L.Mangasarian等的SOR算法
    (2) 用SVM解决多分类问题存在困难:
    经典的SVM算法只给出了二类分类的算法,而在数据挖掘的实际应用中,一般要解决多类的分类问题.可以通过多个二类SVM的组合来解决.主要有一对多组合模式、一对一组合模式和SVM决策树;再就是通过构造多个分类器的组合来解决.主要原理是克服SVM固有的缺点,结合其他算法的优势,解决多类问题的分类精度.如:与粗集理论结合,形成一种优势互补的多类问题的组合分类器.

    代码

    ####################################R包###################################

    R的函数包e1071提供了libsvm的接口。使用e1071包中svm函数可以得到与libsvm相同的结果。write.svm()更是可以把R训练得到的结果写为标准的Libsvm格式,以供其他环境下libsvm的使用。下面我们来看看svm()函数的用法。有两种格式都可以。 

    svm(formula,data=NULL,…,subset,na.action=na.omit,sacle=TRUE)

    或者  svm(x, y = NULL, scale = TRUE, type = NULL, kernel =  "radial", degree = 3, gamma = if (is.vector(x)) 1 else 1 / ncol(x), coef0 = 0, cost = 1, nu = 0.5,  class.weights = NULL, cachesize = 40, tolerance = 0.001, epsilon = 0.1, shrinking = TRUE, cross = 0, probability = FALSE, fitted = TRUE, ..., subset, na.action = na.omit)  

    主要参数说明如下: 

    formula:分类模型形式,在第二个表达式中可以理解为y~x,即y相当于标签,x相当于特征(变量) data:数据框。  subset:可以指定数据集的一部分作为训练数据。

    na.cation:缺失值处理,默认为删除缺失数据。 

    scale:将数据标准化,中心化,使其均值为0,方差为1,将自动执行。

    type:svm的形式。

    为:C-classification ,nu-classification, one-classification (for novelty detection) ,eps-regression,  nu-regression 五种形式。后面两者为做回归时用到。默认为C分类器。

    kernel:在非线性可分时,我们引入核函数来做。

    R中提供的核函数如下

    线性核:   u'*v  多项式核:  

    (gamma*u'*v + coef0)^degree  

    高斯核:   exp(-gamma*|u-v|^2) 

    sigmoid核:   tanh(gamma*u'*v + coef0)  默认为高斯核。顺带说一下,在kernel包中可以自定义核函数。

    degree:多项式核的次数,默认为3 

    gamma:除去线性核外,其他核的参数,默认为1/数据维数

    coef0:多项式核与sigmoid核的参数,默认为0.

    cost:C分类中惩罚项c的取值

    nu:Nu分类,单一分类中nu的值

    cross:做k折交叉验证,计算分类正确性。

     

    我们依然使用iris数据集来做svm分类。

    如下

    > data(iris)

    >  ir<-iris

    > set.seed(124) 

    > count.test<-round(runif(50,1,150))

    > test<-ir[count.test,]

    > library(e1071) 

    >sv<-svm(Species~.,data=ir,cross=5,type='C-classification',kernel='sigmoid') 

    > summary(sv)  #查看支持向量机sv的具体信息,发现做5倍交叉验证的正确率为92%   

    > pre<-predict(sv,test) #对测试样本作预测。pre是一个类别向量。

    > dim(test[test$Species!=pre,])[1]/dim(test)[1] #计算错误率 [1] 0.06我们发现错误率为6%

    ##################################MATLAB####################################

    %主函数

    clear all;

    close all;

    C = 10;

    kertype = 'linear';

    %训练样本

    n = 50;

    randn('state',6);

    x1 = randn(2,n);    %2行N列矩阵

    y1 = ones(1,n);       %1*N个1

    x2 = 5+randn(2,n);   %2*N矩阵

    y2 = -ones(1,n);      %1*N个-1

     

    figure;

    plot(x1(1,:),x1(2,:),'bx',x2(1,:),x2(2,:),'k.'); 

    axis([-3 8 -3 8]);

    hold on;

     

    X = [x1,x2];        %训练样本d*n矩阵,n为样本个数,d为特征向量个数

    Y = [y1,y2];        %训练目标1*n矩阵,n为样本个数,值为+1或-1

    svm = svmTrain(X,Y,kertype,C);

    plot(svm.Xsv(1,:),svm.Xsv(2,:),'ro');

     

    %测试

    [x1,x2] = meshgrid(-2:0.05:7,-2:0.05:7);  %x1和x2都是181*181的矩阵

    [rows,cols] = size(x1);  

    nt = rows*cols;                  

    Xt = [reshape(x1,1,nt);reshape(x2,1,nt)];

    Yt = ones(1,nt);

    result = svmTest(svm, Xt, Yt, kertype);

     

    Yd = reshape(result.Y,rows,cols);

    contour(x1,x2,Yd,'m');

     

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    function svm = svmTrain(X,Y,kertype,C)

     

    options = optimset;    % Options是用来控制算法的选项参数的向量

    options.LargeScale = 'off';

    options.Display = 'off';

     

    n = length(Y);

    H = (Y'*Y).*kernel(X,X,kertype);

    f = -ones(n,1); %f为1*n个-1,f相当于Quadprog函数中的c

    A = [];

    b = [];

    Aeq = Y; %相当于Quadprog函数中的A1,b1

    beq = 0;

    lb = zeros(n,1); %相当于Quadprog函数中的LB,UB

    ub = C*ones(n,1);

    a0 = zeros(n,1);  % a0是解的初始近似值

    [a,fval,eXitflag,output,lambda]  = quadprog(H,f,A,b,Aeq,beq,lb,ub,a0,options);

     

    epsilon = 1e-8;                     

    sv_label = find(abs(a)>epsilon);  %0<a<a(max)则认为x为支持向量     

    svm.a = a(sv_label);

    svm.Xsv = X(:,sv_label);

    svm.Ysv = Y(sv_label);

    svm.svnum = length(sv_label);

    %svm.label = sv_label;

     

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    function result = svmTest(svm, Xt, Yt, kertype)

    temp = (svm.a'.*svm.Ysv)*kernel(svm.Xsv,svm.Xsv,kertype);

    total_b = svm.Ysv-temp;

    b = mean(total_b);

    w = (svm.a'.*svm.Ysv)*kernel(svm.Xsv,Xt,kertype);

    result.score = w + b;

    Y = sign(w+b);

    result.Y = Y;

    result.accuracy = size(find(Y==Yt))/size(Yt);

     

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    function K = kernel(X,Y,type)

    %X 维数*个数

    switch type

    case 'linear'

        K = X'*Y;

    case 'rbf'

        delta = 5;

        delta = delta*delta;

        XX = sum(X'.*X',2);

        YY = sum(Y'.*Y',2);

        XY = X'*Y;

        K = abs(repmat(XX,[1 size(YY,1)]) + repmat(YY',[size(XX,1) 1]) - 2*XY);

        K = exp(-K./delta);

    end

     

  • 相关阅读:
    进程与线程的介绍
    内存结构篇:直接内存
    内存结构篇:方法区
    内存结构篇:堆
    内存结构篇:本地方法栈
    内存结构篇:虚拟机栈
    内存结构篇:程序计数器
    Error: Rule can only have one resource source (provided resource and test + include + exclude) in {
    iview-admin(cli3 + webpack4 )解决兼容ie9+ 方案
    日期插件 js
  • 原文地址:https://www.cnblogs.com/dudumiaomiao/p/6220524.html
Copyright © 2011-2022 走看看