前言

在做毕设的时候用到了支持向量机(SVM)做分类,当特征为3维的时候,想画一个分类面出来。因为在matlab中使用的Libsvm包,没有画三维分类面的功能,所以参考了stackoverflow上的一个问题,写了一下画三维分类曲面的程序。

所用软件

  1. Matlab R2017b
  2. Libsvm-3.22 (安装在matlab的toolbox中)

所用数据

变量名 说明
model 用Libsvm建模输出的模型
train_data 标准化后的训练数据,每一行是一个样本,每一列是一个特征
train_target 样本标记,0-1向量

数据示例

说明

  1. negative样本在前,positive样本在后
  2. negative样本标记0positive样本标记1
  3. train_data已经标准化到-11之间(标准化后方便svm的训练和曲面的展示)
  4. 训练svm的核函数为RBF,若训练时使用了其他的核函数,则需要修改funRBF

train_data

train_target

训练模型

model = svmtrain(train_target,train_data, ['-t 2 -c 100 -g', num2str(1/3),' -b 1 -q']); 

代码

Main Code | 主代码

close all
clear
clc

tic % 开始计时

%% load data 加载数据
load('model','train_data','train_target') 

Xdata_scaled = train_data;
group = train_target;


%% code 
GN3Dplot(Xdata_scaled,sum(group==0),sum(group==1),0,0,0,0); %plot samples 画三维图
xlabel('F1');ylabel('F3'); zlabel('F6');
ylim([-1 0]);
yticks([-1 -0.75 -0.5 -0.25 0])
yticklabels({'-1','-0.5','0','0.5','1'})
set(gca,'fontsize',14)
box on

k = 30; %grid density 网格密度,越大越慢
cubeXMin = min(Xdata_scaled(:,1));
cubeYMin = min(Xdata_scaled(:,2));
cubeZMin = min(Xdata_scaled(:,3));

cubeXMax = max(Xdata_scaled(:,1));
cubeYMax = max(Xdata_scaled(:,2));
cubeZMax = max(Xdata_scaled(:,3));
stepx = (cubeXMax-cubeXMin)/(k-1);
stepy = (cubeYMax-cubeYMin)/(k-1);
stepz = (cubeZMax-cubeZMin)/(k-1);
[x, y, z] = meshgrid(cubeXMin:stepx:cubeXMax,cubeYMin:stepy:cubeYMax,cubeZMin:stepz:cubeZMax);
mm = size(x);
x = x(:);
y = y(:);
z = z(:);
f = funRBF([x y z],model); %kernel function 核函数,此处为RBF

x0 = reshape(x, mm);
y0 = reshape(y, mm);
z0 = reshape(z, mm);
v0 = reshape(f, mm);

[faces,verts,colors] = isosurface(x0, y0, z0, v0, 0, x0);

grid on
box on

%% plot 画图
% colorful grid 彩色网格
p = patch('Faces',faces,'Vertices',verts,'facecolor','w','edgecolor','flat','CData',verts(:,3), 'FaceAlpha', 0.5)

% black grid 黑色网格
% p = patch('Faces',faces,'Vertices',verts,'facecolor','w','CData',verts(:,3),'FaceAlpha', 0.5)

% black plane with alpha 黑色曲面,可通过alpha调节透明度
% p = patch('Vertices', verts, 'Faces', faces, 'FaceColor','k','Edgecolor', 'none', 'FaceAlpha', 0.5);

set(gca,'fontsize',14) %设置图像中的字体大小
hold off

toc %结束计时

对isosurface的一些说明:

patch

重要的命令:

'FaceVertexCData',colors
  • ‘edgecolor’网格线:若要画出彩色的网格线(’interp’),需要加入’FaceVertexCData’项,否则’edgecolor’选项只能使用’none’

  • ‘FaceColor’曲面颜色:若要画出彩色的网格线(’interp’),需要加入’FaceVertexCData’项,否则’FaceColor’选项只能使用’none’

‘FaceAlpha’ — Face transparency 曲面透明度

  • [0, 1]间的常数:固定的透明度,1为不透明,0为全透明
  • ‘flat’: 根据FaceVertexAlphaData确定不同的透明度
  • ‘interp’ : 根据FaceVertexAlphaData,用差值法确定不同的透明度

相关命令: view(a, b)

  • 作用:设置图像观察方向
  • 一般b设置为30就可以,a可以根据需要调整。

RBF kernel function | 径向基核函数

function y = funRBF(x,model)
% x: the vector
% SVs: support vectors

gamma = model.Parameters(4);
SVs = model.SVs;
sv_coef = model.sv_coef;
b = -model.rho;

RBF = @(u,v)( exp(-gamma.*sum( (u-v).^2) ) );

for i = 1:size(x,1)
    y(i) = 0;
    for j = 1:size(SVs,1)
        u = SVs(j,:);
        y(i) = y(i) + sv_coef(j)*RBF(u,x(i,:));
    end
    y(i) = y(i) + b;
end

GN3Dplot | 三维散点图的绘制

function GN3Dplot(x,nNeg,nPos,xp,yp,zp,textFlag)
% BZ: if standardized
% function 
if size(x,2) < 3
	error('dim(x) < 3!!!');
end

n = nPos+nNeg;
target = [zeros(nNeg,1);ones(nPos,1)];

% plot
figure; %三维作图
for i = 1:n
    if target(i) == 1
        h1 = stem3(x(i,1),x(i,2),x(i,3),'filled','-r');
        hold on;
    else
%         h2 = stem3(x(i,1),x(i,2),x(i,3),'filled','-b');
        h2 = stem3(x(i,1),x(i,2),x(i,3),'-.b');
        hold on;
    end
    if textFlag == 1
        text(x(i,1)+xp,x(i,2)+yp,x(i,3)+zp,num2str(i));
    end
end
legend([h1 h2],'Positive','Negative');

xpp = (max(x(:,1))-min(x(:,1)))/10;
ypp = (max(x(:,2))-min(x(:,2)))/10;
zpp = (max(x(:,3))-min(x(:,3)))/10;
xlim([min(x(:,1)) - xpp,max(x(:,1)) + xpp]);
ylim([min(x(:,2)) - ypp,max(x(:,2)) + ypp]);
zlim([min(x(:,3)) - zpp,max(x(:,3)) + zpp]);
grid on; grid minor;
hold off;

end

图像展示

colorful grid | 彩色网格

black grid 黑色网格

black plane with alpha 黑色曲面,可通过alpha调节透明度

参考