SVM简单代码实现MATLAB

来源:互联网 发布:手机淘宝点购买没反应 编辑:程序博客网 时间:2024/05/22 13:01

一、前言

在推导出SVM公式的基础上,就可以考虑动手实现了。SVM解决分类问题,这里用MATLAB来实现,具体就不多说了,所以首先给出两种标记不同的点,然后分别标记为+1,-1。先训练,再测试,最后画图展示出来。代码也是主演参考的别人的,有加上自己的理解注释。

二、流程及实现

1.流程图



2.大家对二次规划可能有点陌生,可以查看帮助文档或者百度,讲解得都很详细,下面是我简单记录一下,其实就是一一对应起来:



3.得到大致流程之后,下面直接贴代码,复制之后就可直接运行。

主函数代码如下:

%------------主函数----------------clear all;close all;C = 10;  %成本约束参数kertype = 'linear';  %线性核%①------数据准备n = 30;%randn('state',6);   %指定状态,一般可以不用x1 = randn(2,n);    %2行N列矩阵,元素服从正态分布y1 = ones(1,n);       %1*N个1x2 = 4+randn(2,n);   %2*N矩阵,元素服从正态分布且均值为5,测试高斯核可x2 = 3+randn(2,n); y2 = -ones(1,n);      %1*N个-1 figure;  %创建一个用来显示图形输出的一个窗口对象plot(x1(1,:),x1(2,:),'bs',x2(1,:),x2(2,:),'k+');  %画图,两堆点axis([-3 8 -3 8]);  %设置坐标轴范围hold on;    %在同一个figure中画几幅图时,用此句%②-------------训练样本X = [x1,x2];        %训练样本2*n矩阵,n为样本个数,d为特征向量个数Y = [y1,y2];        %训练目标1*n矩阵,n为样本个数,值为+1或-1svm = 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)];%前半句reshape(x1,1,nt)是将x1转成1*(181*181)的矩阵,所以xt是2*(181*181)的矩阵%reshape函数重新调整矩阵的行、列、维数Yt = ones(1,nt);result = svmTest(svm, Xt, Yt, kertype);%④--------------画曲线的等高线图Yd = reshape(result.Y,rows,cols);contour(x1,x2,Yd,[0,0],'ShowText','on');%画等高线title('svm分类结果图');   x1=xlabel('X轴');  x2=ylabel('Y轴'); 

训练样本函数svmTrain:

%-----------训练样本的函数---------function svm = svmTrain(X,Y,kertype,C)% Options是用来控制算法的选项参数的向量,optimset无参时,创建一个选项结构所有字段为默认值的选项options = optimset;    options.LargeScale = 'off';%LargeScale指大规模搜索,off表示在规模搜索模式关闭options.Display = 'off';    %表示无输出%二次规划来求解问题,可输入命令help quadprog查看详情n = length(Y);  %返回Y最长维数H = (Y'*Y).*kernel(X,X,kertype);    f = -ones(n,1); %f为1*n个-1,f相当于Quadprog函数中的cA = [];b = [];Aeq = Y; %相当于Quadprog函数中的A1,b1beq = 0;lb = zeros(n,1); %相当于Quadprog函数中的LB,UBub = 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);%a是输出变量,问题的解%fval是目标函数在解a处的值%eXitflag>0,则程序收敛于解x;=0则函数的计算达到了最大次数;<0则问题无可行解,或程序运行失败%output输出程序运行的某些信息%lambda为在解a处的值Lagrange乘子epsilon = 1e-8;   %0<a<a(max)则认为x为支持向量,find返回一个包含数组X中每个非零元素的线性索引的向量。 sv_label = find(abs(a)>epsilon);     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

测试函数svmTest:

%---------------测试的函数-------------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(svm.Ysv-temp);  %b取均值w = (svm.a'.*svm.Ysv)*kernel(svm.Xsv,Xt,kertype);result.score = w + b;Y = sign(w+b);  %f(x)result.Y = Y;result.accuracy = size(find(Y==Yt))/size(Yt);end

核函数kernel:

%---------------核函数---------------function K = kernel(X,Y,type)%X 维数*个数switch typecase 'linear'   %此时代表线性核    K = X'*Y;case 'rbf'      %此时代表高斯核    delta = 5;    delta = delta*delta;    XX = sum(X'.*X',2);%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);endend

4.结果




原创粉丝点击