MATLAB小技巧(12)SVM简单实例
前言
MATLAB进行图像处理相关的学习是非常友好的,可以从零开始,对基础的图像处理都已经有了封装好的许多可直接调用的函数,这个系列文章的话主要就是介绍一些大家在MATLAB中常用一些概念函数进行例程演示!
普遍意义上的SVM是一个二分类线性分类器,它的学习策略是:“在分类超平面的正负两边各找到一个离分类超平面最近的点(也就是支持向量),使得这两个点距离分类超平面的距离和最大”。
所以SVM一般应用的时候存在两种情况,线性可分和线性不可分;线性可分比较好理解,线性不可分就是需要将样本进行维度提升或者变换,在更高的维度中实现样本的线性可分,下面针对SVM在线性可分与线性不可分分别进行简单例程示例,仿真示例MATLAB版本均为MATLAB2015b。
一. MATLAB仿真一:线性可分
%% SVM线性分类简单示例
% date:2022-4-27 23:43:02
% author:C.S
clear all;
close all;
clc;
%% 生成随机数据
shift = 3;
n = 100;%样本矩阵的行数
d = 2;%样本矩阵的列值
%% data1 是负类的
data1 = randn(n,d)-shift;%建立一个100x2的矩阵,randn表示产生均值为0,方差为1的随机样本矩阵
len_1=size(data1);
%% data2 is 正类的
data2 = randn(n,d)+shift;
len_2=size(data2);
%% Combine to Training set(结合训练集)
trnSet=[data1;data2];% trnSet: 训练集样本,是N*D的矩阵,N代表样本个数(200),D代表样本的维度(2)
trnClass = ones(200,1);
trnClass(1:100) = -1;%训练集类别,是200*1的矩阵,其中的每个元素都是1或-1,代表两种不同的类别
%生成测试集数据,标定类别
data3 = randn(n,d)-shift;
data4 = randn(n,d)+shift;
len_3=size(data3);
len_4=size(data4);
tstSet=[data3;data4];% tstSet: 测试集样本,是N*D的矩阵,N代表样本个数(200),D代表样本的维度(2)
tstClass = ones(200,1);
tstClass(1:100) = -1;
%% show the data(显示数据)
%训练集数据分类及显示
figure(1);
subplot(1,2,1)
plot(data1(1:len_1,1),data1(1:len_1,2),'r+');%取data1的第一列作为横坐标;第二列作为纵坐标
hold on;
plot(data2(1:len_2,1),data2(1:len_2,2),'g*');
legend('负样本','正样本');
subplot(1,2,2)
svmStruct=svmtrain(trnSet,trnClass,'showplot',true);%svmStruct为训练得到的线性分类器
%(使用训练集的数据生成svm分类器)
%(分类数据的控制图的显示,包括分类器的分类线,当使用二维数据。选择是对还是错(默认))
trnClass1=svmclassify(svmStruct,trnSet);
train_acc = sum(trnClass==trnClass1)/200 %计算训练结果
%测试集数据分类及显示
figure(2);
subplot(1,2,1)
plot(data3(1:len_3,1),data3(1:len_3,2),'r+');%取data3的第一列作为横坐标;第二列作为纵坐标
hold on;
plot(data4(1:len_4,1),data4(1:len_4,2),'g*');
legend('负样本','正样本');
subplot(1,2,2)
svmStruct1=svmtrain(tstSet,trnClass,'showplot',true);%svmStruct1为测试得到的线性分类器,以训练集模板trnClass为模板,给测试集样本分类
%(使用测试集的数据生成svm分类器)
%(分类数据的控制图的显示,包括分类器的分类线,当使用二维数据。选择是对还是错(默认))
tstClass1=svmclassify(svmStruct1,tstSet);
test_acc = sum(tstClass==tstClass1)/200 %计算测试结果
二. MATLAB仿真二:非线性可分
%% SVM非线性分类简单示例
% date:2022-4-27 23:43:02
% author:C.S
clear all;
close all;
clc;
%% 生成随机数据
%% data1 是负类的
r = sqrt(rand(200,1)); % radius(半径)(rand:生成均匀分布的伪随机数,分布在(0~1)之间主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数)
t = 2*pi*rand(200,1); % angle(角度)
data1 = [r.*cos(t), r.*sin(t)]; % points(样本点矩阵)
%% data2 是正类的
r2 = sqrt(3*rand(200,1)+1);
t2 = 2*pi*rand(200,1);
data2 = [r2.*cos(t2), r2.*sin(t2)];
%% Combine to Training set and Testing set(结合训练集和测试集)
trnSet = [data1(1:100, :); data2(1:100, :)];%分别取data1和data2的前100个数据作为样本集
trnClass = ones(200,1);
trnClass(1:100) = -1;
tstSet = [data1(101:end, :); data2(101:end, :)];%分别取data1和data2的后100个数据作为测试集
tstClass = ones(200,1);
tstClass(1:100) = -1;
%% Train SVM
figure(1)
% trnSet: 训练集样本,是N*D的矩阵,N代表样本个数,D代表样本的维度
% trnClass: 训练集类别,是N*1的矩阵,其中的每个元素都是1或-1,代表两种不同的类别
% 这里演示用RBF核,这是实践中最常用的做法。
% 'boxconstraint'参数是SVM的惩罚系数。一般是按[..., 0.1, 1, 10, ...] 这样的规律调节尝试;默认为1
%‘showplot’其参数指定是否显示一个框图,当该值为true,svmtrain创建关于分类器的一个分组数据和分离线的图,当使用数据有2个特征(列)时,默认是错误的。
% 得到的svmStruct就是分类器,不要动它。
svmStruct = svmtrain(trnSet,trnClass,'Kernel_Function','rbf', ...
'boxconstraint',10,'showplot',true);
tstClass1 = svmclassify(svmStruct, trnSet);
train_acc = sum(trnClass==tstClass1)/200
%svmStruct = svmtrain(trnSet,trnClass,'Kernel_Function','rbf','showplot',true);指定在径向基函数核中的缩放因子、标准差,即rbf的σ默认值是1
%% Test SVM
figure(2)
% svmStruct就是前面训练得到的分类器
% tstSet: 测试集样本,是M*D的矩阵,M代表样本个数,D代表样本的维度
% tstClass1:分类器对测试集类别的预测,是N*1的矩阵,其中的每个元素都是1或-1,代表两种不同的类别
svmStruct1 = svmtrain(tstSet,trnClass,'Kernel_Function','rbf', ...
'boxconstraint',10,'showplot',true);
tstClass2 = svmclassify(svmStruct1, tstSet);
% tstClass: 测试集类别的真实值,与tstClass1相比较就可以得到准确率
% 真正实用的时候可能没有tstClass。因此就没有这一步。但作为研究,还是要加这步验证的。
test_acc = sum(tstClass==tstClass1)/200
三. 小结
支持向量机虽然是个二分类的工具,但通过不同方式也可以进行多分类问题的应用,传统分类方法中,SVM的理论数学逻辑是非常严谨的,应用效果也非常不错,在深度学习未兴起之前,SVM在工业工程上的应用还是非常广泛的,时至今日还在不断发光发热,本文仅为抛砖引玉。每天学一个MATLAB小知识,大家一起来学习进步阿!