支持向量机(SVM)原理推导以及matlab实现

支持向量机

学习支持向量机需要有一定的线性模型,最优化的的基础。

1.基础知识铺垫:

线性回归:线性回归试图找到一条线,让每个点在Y方向上离线越接近越好。就是说,每个数据点做一条垂直的线相较于回归直线,这些线段长度的平方和最小就是最优化的函数。

训练集:

目标函数:  

 

二次规划问题:  二次规划问题的一般形式为:

https://img-blog.csdn.net/20160128095350660

其中,https://img-blog.csdn.net/20160128095401290,d为纯量,G为n*n阶对称矩阵。易知二次规划的Hesse矩阵等于G。如果G为半正定矩阵,则称此规划为凸二次规划,否则为非凸规划。对于凸二次规划,目标函数q(x)是一个凸函数。如果有至少一个向量x满足约束而且q(x)在可行域有下界,二次规划问题就有一个全局最小值x。 如果G是正定矩阵,则称此规划为严格凸二次规划,此时全局最小值就是唯一的。如果G=0,二次规划问题就变成线性规划问题。根据优化理论,一个点x 成为全局最小值的必要条件是满足Karush-Kuhn-Tucker(KKT)条件。当q(x)是凸函数时,KKT条件也是充分条件。二次优化matlab有相应的函数进行求解。

 

2.公式的推导

训练集 

样本空间中划分超平面通过如下线性方程:

 

则任意点到超平面的距离

 

假设:  

间隔的定义:,距离超平面最近的这几个训练样本点使得不等式成立,他们被称为支持向量,两个异类支持向量到超平面的距离之和就是间隔。

找到满足不等式成立的,使得最大,成立

以上就是支持向量机(SVM)的基本型

 

 

3.对偶问题

我们希望得到最大间隔划分超平面所对应的模型 

s.t.  yiwTxi+b≥1,i=1,2,3….,m

以上两式是凸二次规划问题,matlab中专门的计算包,我们采用拉格朗日乘子法,使其转化为对偶问题,则该问题的拉格朗日函数可写为:

求偏导数可得:

 

 带入得到

解出求出即可得到模型:

上述过程需要满足KTT约束条件:一个点X成为全局最优最小值必要条件

有以上约束条件可知,这显示了支持向量的一大特性,训练完以后,大部分训练样本都不要保留,最终模型仅与支持向量有关。

是一个二次优化问题,采用常规算法较为复制,我们采用SMO算法进行求解。

SMO算法:先固定之外的所有参数,然后求上的极值,因为存在约束条件,若固定之外的所有参数,则可由其他导出,所以SMO每次选择两个参数,固定其他参数,更新步骤

当仅考虑参数时,约束条件可改写为:

是使得成立的常数

消去j中的变量

得到关于的单变量的二次规划问题,仅有的约束条件

这样就可以计算出更新后的

参数b对于任意的支持向量求出

现实中采用更加鲁棒的求b的方法:

 

code matlab:

function test_dual_svm()
    %主函数
    clear all;
    close all;
    %test_svm();
    %return;
    C = 10;
    %训练样本
    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,C);
    plot(svm.Xsv(1,:),svm.Xsv(2,:),'ro');

    %测试
    [x1,x2] = meshgrid(-2:0.05:7,-2:0.05:7);  %x1和x2都是181*181的矩阵基于向量 x 和 y 中包含的坐标返回二维网格坐标。
    [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);

    Yd = reshape(result.Y,rows,cols);
    contour(x1,x2,Yd,'m');%画等高线
end

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

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

    n = length(Y);
    H = (Y'*Y).*(X'*X);
    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;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function result = svmTest(svm, Xt, Yt)
    temp = (svm.a'.*svm.Ysv)*(svm.Xsv'*svm.Xsv);
    total_b = svm.Ysv-temp;
    b = mean(total_b);
    w = (svm.a'.*svm.Ysv)*(svm.Xsv'*Xt);
    result.score = w + b;
    Y = sign(w+b);
    result.Y = Y;
    result.accuracy = size(find(Y==Yt))/size(Yt);
end

参考文献:

【1】周志华.机器学习(第一版)[M].北京:清华大学出版社,2016

【2】lnsunqingshen, 464518439.什么是凸二次规划, 百度知道,2011-06-20.

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_41997920/article/details/84960051