非线性矩阵 matlab程序,SVM代码实现非线性分类 Matlab版

一、前言

在已经实现线性分类的基础上,进一步实现非线性分类的情况。其流程与代码与上一篇博客中的线性分类实现很相似。下面先谈一下sv与bsv,这些概念在西瓜书上可以找到的。关于这里出现的公式的推倒,请参考上上一篇博客:

135055876_1_20180605093032160

二、流程及实现

流程图与线性分类一样

135055876_2_20180605093032378

而关于二次规划查看帮助文档即可。

还是直接上代码,注释都比较详细:

%------------主函数----------------

clear all;

close all;

C = 10;  %成本约束参数

kertype = 'rbf';  %rbf高斯核

%①------数据准备5*10方格,每个方格20个点,共1000个点

x1=[];

x3=[];

for i=0:1:9

for j=0:1:4

b=j+rand(20,1);%随机生成20个点

c=i+rand(20,1);

x0=[x1;b];

x2=[x3;c];

x1=x0;  %这里的x1放所有点的横坐标

x3=x2;  %x3放所有点的纵坐标,(x1,x3)

end

end

y0=[];%这个矩阵放所有点的标记

y1 = ones(20,1); %20个+1标记

y2 = -ones(20,1);%20个-1标记

for k=0:1:24    %循环赋值,使得5*10方格内相邻的格子标记都不一样

y0=[y0;y1];

y0=[y0;y2];

end

x1=x1.'

x3=x3.'  %记得转置一下哦

figure;  %创建一个用来显示图形输出的一个窗口对象

for m=1:1:25

plot(x1(1,(1+20*(2*m-2)):(20*(2*m-1))),x3(1,(1+20*(2*m-2)):(20*(2*m-1))),'k.');  %画图

hold on;

plot(x1(1,(1+20*(2*m-1)):(20*(2*m))),x3(1,(1+20*(2*m-1)):(20*(2*m))),'b+');  %画图

hold on;    %在同一个figure中画几幅图时,用此句

end

%axis([0 5 0 10]);  %设置坐标轴范围

%②-------------训练样本

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

Y = y0.';        %训练目标1*n矩阵,n为样本个数,值为+1或-1

svm = svmTrain(X,Y,kertype,C);  %训练样本

%%%把支持向量标出来,若支持向量画的不对,此时可通过在kernel函数调参来修改

for i=1:1:svm.svnum

if svm.Ysv(1,i)==1

plot(svm.Xsv(1,i),svm.Xsv(2,i),'mo');%一类支持向量用粉色圈住

else

plot(svm.Xsv(1,i),svm.Xsv(2,i),'ko');%另一类支持向量黑色圈

end

end

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

%③-------------测试

[x1,x2] = meshgrid(0:0.05:5,0:0.05:10);  %最大值控制着等高线在几乘几范围画出来

[rows,cols] = size(x1);

nt = rows*cols;

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

%前半句reshape(x1,1,nt)是将x1转成1*(rows*cols)的矩阵,所以Xt是2*(rows*cols)的矩阵

%reshape函数重新调整矩阵的行、列、维数

y3 = ones(1,floor(nt/2));

y4 = -ones(1,floor(nt/2)+1);

Yt = [y3,y4];

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

%④--------------画曲线的等高线图

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

contour(x1,x2,Yd,3); %产生三个水平的等高线

title('5*10数据分类');

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

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

%---------------核函数kernel---------------

function K = kernel(X,Y,type)

%X 维数*个数

switch type

case 'linear'   %此时代表线性核

K = X'*Y;

case 'rbf'      %此时代表高斯核

delta = 0.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

%---------------测试的函数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

运行结果:

135055876_3_20180605093032910

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值