MATLAB 支持向量机(SVM)详细解释(含代码)

  • 基础
    • 线性可分
    • 最大间隔超平面
  • SVM分类
    • 基本代码和工具
    • 二分类
      • 线性
      • 非线性
    • 多分类
      • 详细解释

基础

线性可分

简单来讲就是如何将两个数据用点、直线、平面分开。。。。。

二维空间中,要分开两个线性可分的点集合,我们需要找到一条分类直线即可,

最大间隔超平面

通俗来讲,在这个二维平面中,可以把两类点的分开的直线有很多条,那么这些直线中,哪一条才是最好的呢?也就是如何选择出一条最好的直线呢?

先看橙色的点,如果这些点到分类直线的距离越大,分类直线也就越远离橙色的点,那么再来一个新的点,如果这个点是依照橙色点集合的特性产生的(也就是它不是一个相对于橙色点集合很奇异的点),那么这个点也很可能和橙色的点集合一样,分布在直线的同一侧。分布在同一侧,表明它和橙色集合点属于同一个类别。用同样的思想,图4中,对于灰色的集合点,这条分类直线离它们的距离也要越远越好。所以找最优分类线,就是要找到这条一条直线,使它到两个类别点的距离越大越好。

因此便可得到某根距离离两边都累计最远的直线,即最大分隔超平面。


上述也叫硬间隔最最大化,能够用直线将两者分开。

SVM分类

基本代码和工具

工具:1、MATLAB 2020a;2、fitcsvm

二分类

fitcsvm:fitcsvm训练或交叉验证支持向量机(SVM)模型在低维或中维预测数据集上的一类和二类(binary)分类。fitcsvm支持使用核函数映射预测数据,并支持通过二次规划实现目标函数最小化的顺序最小优化(SMO,sequential minimal optimization)、迭代单数据算法(ISDA,iterative single data algorithm)或L1软边界最小化。
代码:

线性

clcclear all%设置两类不同数据A = [3,7;6,6;4,6;5,6.5];B = [1,2;3,5;7,3;3,4;6,2.7;4,3;2,7];C = [A;B];%两类数据合并%设置不同类别标签table = [true true true true false false false false false false false];D = nominal(table);%%数据集和标签sd=C;Y=D;%% 原始数据图像subplot(1,2,1)gscatter(sd(:,1),sd(:,2),Y,'rg','+*');%%SVMSVMModel=fitcsvm(sd,Y,'KernelFunction','linear');[lable,score]=predict(SVMModel,sd);%% 画图subplot(1,2,2)h = nan(3,1); h(1:2) = gscatter(sd(:,1),sd(:,2),Y,'rg','+*'); hold onh(3) =plot(sd(SVMModel.IsSupportVector,1),sd(SVMModel.IsSupportVector,2), 'ko');%画出支持向量%画出决策边界w=-SVMModel.Beta(1,1)/SVMModel.Beta(2,1);%斜率b=-SVMModel.Bias/SVMModel.Beta(2,1);%截距x_ = 0:0.01:10;y_ = w*x_+b;plot(x_,y_)hold onlegend(h,{'-1','+1','Support Vectors'},'Location','Southeast');axis equalhold off

实验结果:

上述实验得到一个硬间隔最大化的分隔超平面

非线性

clcclear all%设置两类不同数据A = [0.9,1;0.8,1.8;0.79,1.7;0.7,3;0.8,3.9;0.9,4.5;1.2,5.7;1.6,5.6;2.5,6.1;2.9,5.8; 2.9,1;3.1,1.4;3.6,1.2;5,2;5.5,3.9;4.9,4.5;4.2,5.9;3.6,5.6;2.5,5.1;2.9,5.3];B = [2.5,3.1;3.5,2.6;4.5,3.2;3.5,2;2.4,2;3.5,2.5;4.3,3.7;2.6,2.8;2.4,3;3.6,3.1;4.4,3.3; 2.5,4.0;3.5,4.1;4.5,4.2;1.5,4;2.4,4;3.5,4.5;4.3,3.7;3.6,3.8;2.4,3.5;3.6,3.7;4.4,3.3];C = [A;B];%两类数据合并%设置不同类别标签table = [true true true true true true true true true true true true true true true true true true true true false false false false false false false false false false false false false false false false false false false false false false];D = nominal(table);%%数据集和标签sd=C;Y=D;%% 原始数据图像subplot(1,2,1)gscatter(sd(:,1),sd(:,2),Y,'rg','+*');%% 原始数据图像subplot(1,2,1)gscatter(sd(:,1),sd(:,2),Y,'rg','+*');%% SVMSVMModel=fitcsvm(sd,Y,'BoxConstraint',10,'KernelFunction','rbf','KernelScale',2^0.5*2);%使用高斯核函数%%SVMModel=fitcsvm(sd,Y,'KernelFunction','rbf','OptimizeHyperparameters',{'BoxConstraint','KernelScale'},'HyperparameterOptimizationOptions',struct('ShowPlots',false));%使用超参数优化%% 画图subplot(1,2,2)h = nan(3,1); h(1:2) = gscatter(sd(:,1),sd(:,2),Y,'rg','+*'); hold onh(3) = plot(sd(SVMModel.IsSupportVector,1),sd(SVMModel.IsSupportVector, 2),'ko'); %画出支持向量%画出决策边界h = 0.2; [X1,X2] = meshgrid(min(sd(:,1)):h:max(sd(:,1)),min(sd(:,2)):h:max(sd(:,2)));%得到所有取点的矩阵[lable,score]=predict(SVMModel,[X1(:),X2(:)]);scoreGrid = reshape(score(:,2),size(X1,1),size(X2,2));contour(X1,X2,scoreGrid,[0 0]);%绘制等高线hold onlegend('-1','+1','Support Vectors','分界线');axis equalhold off

实验结果:

上述实验进行非线性的数据分类

多分类

详细解释

一对多法(one-versus-rest,简称OVR SVMs)

训练时依次把某个类别的样本归为一类,其他剩余的样本归为另一类,这样k个类别的样本就构造出了k个SVM。分类时将未知样本分类为具有最大分类函数值的那类。

假如我有四类要划分(也就是4个Label),他们是A、B、C、D。
于是我在抽取训练集的时候,分别抽取
  (1)A所对应的向量作为正集,B,C,D所对应的向量作为负集;
  (2)B所对应的向量作为正集,A,C,D所对应的向量作为负集;
  (3)C所对应的向量作为正集,A,B,D所对应的向量作为负集;
  (4)D所对应的向量作为正集,A,B,C所对应的向量作为负集;
  使用这四个训练集分别进行训练,然后的得到四个训练结果文件。在测试的时候,把对应的测试向量分别利用这四个训练结果文件进行测试。最后每个测试都有一个结果f1(x),f2(x),f3(x),f4(x)。于是最终的结果便是这四个值中最大的一个作为分类结果。
  数据链接: [https://pan.baidu.com/s/1QUNknb-AV-cPt0hM_jSs_Q ]提取码:http
  代码:

clc;clear;close all;%%导入数据:训练集、测试集、训练标签、测试标签train_data=xlsread('train_data.xls');group_train=xlsread('group_train.xls');test_data=xlsread('test_data.xls');test_labels=xlsread('test_labels.xls');%%绘数据分布图gscatter(train_data(:,1),train_data(:,2),group_train);title('数据分布');xlabel('Fea1');ylabel('Fea2');%%% 训练数据分为5% 类别i的 正样本 选择类别i的全部,负样本 从其余类别中随机选择(个数与正样本相同)%%% 类别1class1_p = train_data(1:12,:);% randperm(n,k)是从1到n的序号中随机返回k个index1 = randperm(48,12);train_data_c = train_data;train_data_c(1:12,:) = [];%正样本class1_n = train_data_c(index1,:);%负样本train_features1 = [class1_p;class1_n];% 正类表示为1,负类表示为-1train_labels1 = [ones(12,1);-1*ones(12,1)];%% 类别2class2_p = train_data(13:24,:);% randperm(n,k)是从1到n的序号中随机返回k个index1 = randperm(48,12);train_data_c = train_data;train_data_c(13:24,:) = [];%正样本class2_n = train_data_c(index1,:);%负样本train_features2 = [class2_p;class2_n];% 正类表示为1,负类表示为-1train_labels2 = [ones(12,1);-1*ones(12,1)];%% 类别3class3_p = train_data(25:36,:);% randperm(n,k)是从1到n的序号中随机返回k个index1 = randperm(48,12);train_data_c = train_data;train_data_c(25:36,:) = [];%正样本class3_n = train_data_c(index1,:);%负样本train_features3 = [class3_p;class3_n];% 正类表示为1,负类表示为-1train_labels3 = [ones(12,1);-1*ones(12,1)];%% 类别4class4_p = train_data(37:48,:);% randperm(n,k)是从1到n的序号中随机返回k个index1 = randperm(48,12);train_data_c = train_data;train_data_c(37:48,:) = [];%正样本class4_n = train_data_c(index1,:);%负样本train_features4 = [class4_p;class4_n];% 正类表示为1,负类表示为-1train_labels4 = [ones(12,1);-1*ones(12,1)];%% 类别5class5_p = train_data(49:60,:);% randperm(n,k)是从1到n的序号中随机返回k个index1 = randperm(48,12);train_data_c = train_data;train_data_c(49:60,:) = [];%正样本class5_n = train_data_c(index1,:);%负样本train_features5 = [class5_p;class5_n];% 正类表示为1,负类表示为-1train_labels5 = [ones(12,1);-1*ones(12,1)];%%% 分别训练5个类别的SVM模型model1 = fitcsvm(train_features1,train_labels1,'ClassNames',{'-1','1'});model2 = fitcsvm(train_features2,train_labels2,'ClassNames',{'-1','1'});model3 = fitcsvm(train_features3,train_labels3,'ClassNames',{'-1','1'});model4 = fitcsvm(train_features4,train_labels4,'ClassNames',{'-1','1'});model5 = fitcsvm(train_features5,train_labels5,'ClassNames',{'-1','1'});%%% label是n*1的矩阵,每一行是对应测试样本的预测标签;% score是n*2的矩阵,第一列为预测为“负”的得分,第二列为预测为“正”的得分。% 用训练好的5SVM模型分别对测试样本进行预测分类,得到5个预测标签[label1,score1] = predict(model1,test_data);[label2,score2] = predict(model2,test_data);[label3,score3] = predict(model3,test_data);[label4,score4] = predict(model4,test_data);[label5,score5] = predict(model5,test_data);% 求出测试样本在5个模型中预测为“正”得分的最大值,作为该测试样本的最终预测标签score = [score1(:,2),score2(:,2),score3(:,2),score4(:,2),score5(:,2)];% 最终预测标签为k*1矩阵,k为预测样本的个数final_labels = zeros(20,1);for i = 1:size(final_labels,1)% 返回每一行的最大值和其位置[m,p] = max(score(i,:));% 位置即为标签final_labels(i,:) = p;end% 分类评价指标