文章目录

  • 一、介绍
  • 二、支持向量机分类基本原理
  • 2.1 线性可分SVM
  • 2.2 线性不可分SVM
  • 2.3 多分类问题
  • 2.3.1一对一(ovo)
  • 2.3.2一对多(ovr)
  • 2.3.2ovo 和ovr 区别
  • 三、MATLAB实现
  • libsvm包实现
  • 1.产生训练集/测试集
  • 2. 数据归一化
  • 3. SVM创建/训练(RBF核函数)
  • 4. SVM仿真测试
  • 5. 结果展示


一、介绍

  支持向量机是数据挖掘中的一项新技术,是借助最优化方法来解决机器学习问题的新工具,最初由V.Vapnik等人提出,近几年来在其理论研究和算法实现等方面都取得了很大的进展,开始成为克服“维数灾难”和“过学习”等困难的强有力手段,其理论基础和实现途径的基本框架都已形成。

  支持向量机(Support Vector Machine ,以下简称SVM)在模式识别等领域获得了广泛的应用。其主要思想是找到一个超平面,使得它能够尽可能多地将两类数据点正确分开,同时使分开的两类数据点距离分类面最远,如下图(b)所示。(与图(a)做对比)

  在进行线性分类时,将分类面取在离两类样本距离较大的地方;进行非线性分类时通过高维空间变换,将非线性分类变成高维空间的线性分类问题。

java如何表示一个向量 java支持向量机_matlab

二、支持向量机分类基本原理

java如何表示一个向量 java支持向量机_线性分类_02 = {java如何表示一个向量 java支持向量机_线性分类_03} java如何表示一个向量 java支持向量机_matlab_04 (java如何表示一个向量 java支持向量机_线性分类_05, 式中java如何表示一个向量 java支持向量机_支持向量机_06java如何表示一个向量 java支持向量机_支持向量机_07称为输入空间,输入空间中的每个点java如何表示一个向量 java支持向量机_线性分类_08,由java如何表示一个向量 java支持向量机_java如何表示一个向量_09个属性特征组成;java如何表示一个向量 java支持向量机_支持向量机_10{-1,1},java如何表示一个向量 java支持向量机_matlab_11。寻找java如何表示一个向量 java支持向量机_matlab_12上的一个实值函数java如何表示一个向量 java支持向量机_支持向量机_13,以便用分类函数
java如何表示一个向量 java支持向量机_matlab_14,
推断任意一个模式java如何表示一个向量 java支持向量机_java如何表示一个向量_15相对应的java如何表示一个向量 java支持向量机_java如何表示一个向量_16值的问题为分类问题。

2.1 线性可分SVM

  支持向量机最初是研究线性可分问题而提出的,因此,这里先详细介绍线性SVM的基本
思想及原理。
  为不失一般性,假设大小为java如何表示一个向量 java支持向量机_matlab_17的训练样本集{(java如何表示一个向量 java支持向量机_支持向量机_18),java如何表示一个向量 java支持向量机_线性分类_19}由两个类别组成。若java如何表示一个向量 java支持向量机_线性分类_20属于第一类,则记java如何表示一个向量 java支持向量机_机器学习_21=1;若java如何表示一个向量 java支持向量机_线性分类_20属于第二类,则记java如何表示一个向量 java支持向量机_机器学习_21= -1。
  若存在分类超平面
java如何表示一个向量 java支持向量机_支持向量机_24
能够将样本正确地划分成两类,即相同类别的样本都落在分类超平面的同一侧,则称该样本集是线性可分的,即满足
java如何表示一个向量 java支持向量机_线性分类_25
  定义样本点java如何表示一个向量 java支持向量机_线性分类_20;到式(2.1.1)所指的分类超平面的间隔为
java如何表示一个向量 java支持向量机_支持向量机_27
将式(2.1.3)中的java如何表示一个向量 java支持向量机_matlab_28进行归一化,即用java如何表示一个向量 java支持向量机_机器学习_29分别代替原来的java如何表示一个向量 java支持向量机_支持向量机_30,并将归一化后的间隔定义为集合间隔
java如何表示一个向量 java支持向量机_java如何表示一个向量_31
  同时定义一个样本集到超平面的距离为此集合与分类超平面最近的样本点的几何间隔,即
java如何表示一个向量 java支持向量机_线性分类_32
  样本误分次数java如何表示一个向量 java支持向量机_线性分类_33与样本集到分类超平面的距离java如何表示一个向量 java支持向量机_机器学习_34之间的关系为
java如何表示一个向量 java支持向量机_支持向量机_35
其中,java如何表示一个向量 java支持向量机_线性分类_36,为样本集中间向量长度最长的值。
  由式(2.1.6)可知,误分次数java如何表示一个向量 java支持向量机_线性分类_33的上界由样本集到分类超平面的距离java如何表示一个向量 java支持向量机_机器学习_34决定,即java如何表示一个向量 java支持向量机_机器学习_34越大,java如何表示一个向量 java支持向量机_线性分类_33越小。因此,需要在满足式(2.1.2)的无数个分类超平面中选择一个最优分类面,使得样本集到分类超平面的距离java如何表示一个向量 java支持向量机_机器学习_34最大。
  若间隔java如何表示一个向量 java支持向量机_线性分类_42,则两类样本点间的距离为 java如何表示一个向量 java支持向量机_线性分类_43。因此,如下图所示,目标即为在满足式(2.1.2)的约束下寻求最优分类超平面,使得java如何表示一个向量 java支持向量机_线性分类_44最大,即最小化java如何表示一个向量 java支持向量机_线性分类_45


java如何表示一个向量 java支持向量机_matlab_46

用数学语言描述,即,

java如何表示一个向量 java支持向量机_机器学习_47

  该问题目标函数java如何表示一个向量 java支持向量机_线性分类_45java如何表示一个向量 java支持向量机_支持向量机_49的凸函数,并且约束条件都是线性的。引入拉格朗日函数

java如何表示一个向量 java支持向量机_matlab_50

其中,java如何表示一个向量 java支持向量机_机器学习_51为拉格朗日乘子。

  由于计算的复杂性,一般不直接求解,而是根据对偶理论,将(2.1.8)转化成对偶问题,即

java如何表示一个向量 java支持向量机_线性分类_52

  这个问题可以用二次规划方程求解。设最优解为java如何表示一个向量 java支持向量机_机器学习_53,则可以得到最优解java如何表示一个向量 java支持向量机_支持向量机_54

java如何表示一个向量 java支持向量机_matlab_55

其中,java如何表示一个向量 java支持向量机_机器学习_56为两个类别中的任意一对支持向量。

  最终得到的分类模型为

java如何表示一个向量 java支持向量机_java如何表示一个向量_57

  值得一提的是,若数据集中的绝大多数样本是线性可分的,仅有少数几个样本(可能是异常点)导致寻找不到最优分类超平面(入下图所示)

java如何表示一个向量 java支持向量机_java如何表示一个向量_58

针对此类情况,通用的做法是引入松弛变量,并对式(2.1.7)中的优化目标即约束项进行修正,即
java如何表示一个向量 java支持向量机_支持向量机_59
其中,java如何表示一个向量 java支持向量机_机器学习_60为惩罚因子,起着控制错分样本惩罚程度的作用,从而实现在错分样本的比例与算法复杂度间的折中。求解方法与式(2.1.8)相同,即转化为其对偶问题
java如何表示一个向量 java支持向量机_支持向量机_61
只是约束条件变为
java如何表示一个向量 java支持向量机_java如何表示一个向量_62
最终求得到的分类函数形式与(2.1.11)一样。

2.2 线性不可分SVM

java如何表示一个向量 java支持向量机_机器学习_63,将原输人空间的样本映射到高维的特征空间java如何表示一个向量 java支持向量机_支持向量机_64中,再在高维特征空间java如何表示一个向量 java支持向量机_支持向量机_64中构造最优分类超平面,如下图所示。另外,与线性可分SVM相同,考虑到通过非线性映射到高维特征空间后仍有因少量样本造成的线性不可分情况,亦考虑引入松弛变量。


java如何表示一个向量 java支持向量机_线性分类_66

  在高维特征空间中寻求最优分类超平面的过程及方法与线性可分SVM情况类似,只是
以核函数取代了高维特征空间中的点积,从而大大减少了计算量与复杂度。
  映射到高维特征空间后对应的对偶问题变为
java如何表示一个向量 java支持向量机_java如何表示一个向量_67
设最优解为java如何表示一个向量 java支持向量机_机器学习_53,则
java如何表示一个向量 java支持向量机_线性分类_69
从而得到最优的分类模型为
java如何表示一个向量 java支持向量机_支持向量机_70
  容易证明,解中将只有一部分(通常是少部分)不为零,非零部分对应的样本java如何表示一个向量 java支持向量机_线性分类_20就是支持向量,决策边界仅由支持向量确定。由式(2.1.15)也可以看出,支持向量机的结构与神经网络的结构较为类似,如下图所示。输出是中间节点的线性组合,每个中间节点对应一个支持向量。


java如何表示一个向量 java支持向量机_matlab_72

  常用的核函数

函数

公式

线性核函数

java如何表示一个向量 java支持向量机_机器学习_73

多项式核函数

java如何表示一个向量 java支持向量机_java如何表示一个向量_74

径向基核函数

java如何表示一个向量 java支持向量机_机器学习_75

Sigmoid核函数

java如何表示一个向量 java支持向量机_java如何表示一个向量_76

傅里叶核函数

java如何表示一个向量 java支持向量机_matlab_77

2.3 多分类问题

  由线性可分SVM和线性不可分SVM的原理可知,支持向量机仅限于处理二分类问题,对于多分类问题,须做进一步的改进。目前,构造多分类SVM的方法主要有两个:直接法和间接法。直接法通过修改待求解的优化问题,直接计算出用于多分类的分类函数,该方法计算量较大、求解过程复杂、花费时间较长,实现起来比较困难。间接法主要是通过组合多个二分类SVM来实现多分类SVM的构建,常见的方法有一对一(one-against-one)和一对多(one-against- all)两种。

2.3.1一对一(ovo)

java如何表示一个向量 java支持向量机_机器学习_78类训练样本中构造所有可能的二分类SVM,即将每类样本与其他类别的样本分别构成二分类问题,共构造java如何表示一个向量 java支持向量机_支持向量机_79个二分类SVM。测试样本经过所有的二分类SVM进行分类,然后对所有类别进行投票,得票最多的类别(最占优势的类别)即为测试样本所属的类别。


java如何表示一个向量 java支持向量机_线性分类_80

2.3.2一对多(ovr)

java如何表示一个向量 java支持向量机_机器学习_78个二分类SVM组成,第java如何表示一个向量 java支持向量机_java如何表示一个向量_82个二分类SVM将第java如何表示一个向量 java支持向量机_matlab_83类训练样本的类别标记为+1,而将其余所有训练样本的类别标记为-1。测试样本经过所有二分类SVM进行分类,然后根据预测得到的类别标号判断是否属于第java如何表示一个向量 java支持向量机_java如何表示一个向量_82个类别。


java如何表示一个向量 java支持向量机_支持向量机_85

2.3.2ovo 和ovr 区别

  区别如下图所示:

java如何表示一个向量 java支持向量机_java如何表示一个向量_86

三、MATLAB实现

libsvm包实现

  本例将用乳腺癌诊断来对算法进行实现

1.产生训练集/测试集

%% 清空环境变量
clear all
clc
%% 导入数据
load BreastTissue_data.mat
% 随机产生训练集和测试集
n = randperm(size(matrix,1));
% 训练集——80个样本
train_matrix = matrix(n(1:80),:);
train_label = label(n(1:80),:);
% 测试集——26个样本
test_matrix = matrix(n(81:end),:);
test_label = label(n(81:end),:);

2. 数据归一化

%% 数据归一化
[Train_matrix,PS] = mapminmax(train_matrix');
Train_matrix = Train_matrix';
Test_matrix = mapminmax('apply',test_matrix',PS);
Test_matrix = Test_matrix';

3. SVM创建/训练(RBF核函数)

java如何表示一个向量 java支持向量机_java如何表示一个向量_87(惩罚因子)和参数java如何表示一个向量 java支持向量机_支持向量机_88(RBF核函数中的方差),然后利用最佳的参数训练模型。值得一提的是,当模型的性能相同时,为了减少计算时间,优先选择惩罚因子java如何表示一个向量 java支持向量机_java如何表示一个向量_87比较小的参数组合,这是因为惩罚因子java如何表示一个向量 java支持向量机_java如何表示一个向量_87越大,最终得到的支持向量数将越多,计算量越大。具体程序如下:

% 寻找最佳c/g参数——交叉验证方法
[c,g] = meshgrid(-10:0.2:10,-10:0.2:10);
[m,n] = size(c);
cg = zeros(m,n);
eps = 10^(-4);
v = 5;
bestc = 1;
bestg = 0.1;
bestacc = 0;
for i = 1:m
    for j = 1:n
        cmd = ['-v ',num2str(v),' -t 2',' -c ',num2str(2^c(i,j)),' -g ',num2str(2^g(i,j))];
        cg(i,j) = svmtrain(train_label,Train_matrix,cmd);     
        if cg(i,j) > bestacc
            bestacc = cg(i,j);
            bestc = 2^c(i,j);
            bestg = 2^g(i,j);
        end        
        if abs( cg(i,j)-bestacc )<=eps && bestc > 2^c(i,j) 
            bestacc = cg(i,j);
            bestc = 2^c(i,j);
            bestg = 2^g(i,j);
        end               
    end
end
cmd = [' -t 2',' -c ',num2str(bestc),' -g ',num2str(bestg)];
% 创建/训练SVM模型
model = svmtrain(train_label,Train_matrix,cmd);

4. SVM仿真测试

%% SVM仿真测试
[predict_label_1,accuracy_1] = svmpredict(train_label,Train_matrix,model);
[predict_label_2,accuracy_2] = svmpredict(test_label,Test_matrix,model);
result_1 = [train_label predict_label_1];
result_2 = [test_label predict_label_2];

5. 结果展示

%% 绘图
figure
plot(1:length(test_label),test_label,'r-*')
hold on
plot(1:length(test_label),predict_label_2,'b:o')
grid on
legend('真实类别','预测类别')
xlabel('测试集样本编号')
ylabel('测试集样本类别')
string = {'测试集SVM预测结果对比(RBF核函数)';
          ['accuracy = ' num2str(accuracy_2(1)) '%']};
title(string)

结果如下:


java如何表示一个向量 java支持向量机_线性分类_91

  由于训练集和测试集是随机产生的,所以程序每次运行的结果都会不同。某次运行的测试集预测结果如下表所列。从表中可以清晰地看到,只有样本5和7和13预测错误,测试集的预测正确率达到88.46%(23/26)。且如前文所述,乳腺癌、纤维腺瘤和乳腺病(标签分别为1、2和3)为病变组织,乳腺组织、结缔组织和脂肪组织(标签分别为4、5、6)为正常组织,若仅判断为病变组织或正常组织(即二分类),则样本5和7判断正确(将乳腺癌诊断为纤维腺瘤,同为病变组织),预测正确率将达到96.15%(25/26),这也从另外一个角度体现了SVM用于二分类的优越性。

样本编号

1

2

3

4

5

6

7

8

9

10

11

12

13

真实类别

2

2

2

5

3

1

4

6

1

1

1

6

4

预测类别

2

2

2

5

1

1

6

6

1

1

1

6

1

样本编号

14

15

16

17

18

19

20

21

22

23

24

25

26

真实类别

1

3

3

1

4

6

5

6

3

1

3

6

6

预测类别

1

3

3

1

4

6

5

6

3

1

3

6

6