SVM简单代码实现MATLAB

xiaoxiao2021-02-28  47

一、前言

在推导出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个1 x2 = 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或-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)]; %前半句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函数中的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); %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 type case '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); end end 4. 结果

转载请注明原文地址: https://www.6miu.com/read-1100212.html

最新回复(0)