libsvm学习记录(二)libsvm的使用以及参数意义

来源:互联网 发布:windows自带录音机 编辑:程序博客网 时间:2024/05/22 09:51

传送门:

[教程] 如何使用libsvm进行分类

http://www.matlabsky.com/forum-viewthread-tid-12379-fromuid-18677.html

[教程] 利用libsvm-mat建立分类模型model参数解密【by faruto】

http://www.matlabsky.com/thread-12649-1-1.html


以下为转载内容:(稍作删减修改)

使用libsvm进行分类很简单,只需要有属性矩阵和标签,然后就可以建立分类模型(model),然后利用得到的这个model进行分类预测。

举个简单栗子:

一个班级里面有两个男生(男生1、男生2),两个女生(女生1、女生2),其中

男生1 身高:176cm 体重:70kg;
男生2 身高:180cm 体重:80kg;

女生1 身高:161cm 体重:45kg;
女生2 身高:163cm 体重:47kg;

如果我们将男生定义为1,女生定义为-1,并将上面的数据放入矩阵data中,即

  1. data = [176 70;
  2. 180 80;
  3. 161 45;
  4. 163 47];
复制代码
在label中存入男女生类别标签(1、-1),即

  1. label = [1;1;-1;-1];
复制代码
这样上面的data矩阵就是一个属性矩阵,行数4代表有4个样本,列数2表示属性有两个,label就是标签(1、-1表示有两个类别:男生、女生)。

有了上面的属性矩阵data,和标签label就可以利用libsvm建立分类模型了,简要代码如下:


  1. model = svmtrain(label,data);
复制代码
有了model我们就可以做分类预测,比如此时该班级又转来一个新学生,其
身高190cm,体重85kg
我们想通过上面这些信息就给出其标签(想知道其是男【1】还是女【-1】)
比如 令 testdata = [190 85]; 由于其标签我们不知道,我们假设其标签为-1(也可以假设为1) ,testdatalabel = -1;


然后利用libsvm来预测这个新来的学生是男生还是女生,代码如下:


  1. [predictlabel,accuracy] = svmpredict(testdatalabel,testdata,model)
复制代码
下面我们整体运行一下上面这段代码:

  1. data = [176 70;
  2. 180 80;
  3. 161 45;
  4. 163 47];
  5. label = [1;1;-1;-1];

  6. model = svmtrain(label,data);

  7. testdata = [190 85];
  8. testdatalabel = -1;

  9. [predictlabel,accuracy] = svmpredict(testdatalabel,testdata,model);
  10. predictlabel
复制代码
运行结果如下:

  1. Accuracy = 0% (0/1) (classification)
  2. predictlabel =
  3.      1
复制代码
哎,我们看到,通过预测我们得知这个新来的学生的标签是1(男生),由于原本我们假设其标签为-1,假设错误,所以分类准确率为0%。


下面使用libsvm工具箱本身带的测试数据heart_scale来实际进行一下测试:

  1. %% HowToClassifyUsingLibsvm
  2. % by faruto @ faruto's Studio~
  3. % http://blog.sina.com.cn/faruto
  4. % Email:faruto@163.com
  5. % http://www.MATLABsky.com
  6. % http://www.mfun.la
  7. % http://video.ourmatlab.com
  8. % last modified by 2010.12.27
  9. %% a litte clean work
  10. tic;
  11. close all;
  12. clear;
  13. clc;
  14. format compact;
  15. %% 

  16. % 首先载入数据
  17. load heart_scale;
  18. data = heart_scale_inst;
  19. label = heart_scale_label;

  20. % 选取前200个数据作为训练集合,后70个数据作为测试集合
  21. ind = 200;
  22. traindata = data(1:ind,:);
  23. trainlabel = label(1:ind,:);
  24. testdata = data(ind+1:end,:);
  25. testlabel = label(ind+1:end,:);

  26. % 利用训练集合建立分类模型
  27. model = svmtrain(trainlabel,traindata,'-s 0 -t 2 -c 1.2 -g 2.8');

  28. % 分类模型model解密
  29. model
  30. Parameters = model.Parameters
  31. Label = model.Label
  32. nr_class = model.nr_class
  33. totalSV = model.totalSV
  34. nSV = model.nSV 

  35. % 利用建立的模型看其在训练集合上的分类效果
  36. [ptrain,acctrain] = svmpredict(trainlabel,traindata,model);

  37. % 预测测试集合标签
  38. [ptest,acctest] = svmpredict(testlabel,testdata,model);

  39. %%
  40. toc;
复制代码
运行结果:

  1. model = 
  2.     Parameters: [5x1 double]
  3.       nr_class: 2
  4.        totalSV: 197
  5.            rho: 0.0583
  6.          Label: [2x1 double]
  7.          ProbA: []
  8.          ProbB: []
  9.            nSV: [2x1 double]
  10.        sv_coef: [197x1 double]
  11.            SVs: [197x13 double]
  12. Parameters =
  13.          0
  14.     2.0000
  15.     3.0000
  16.     2.8000
  17.          0
  18. Label =
  19.      1
  20.     -1
  21. nr_class =
  22.      2
  23. totalSV =
  24.    197
  25. nSV =
  26.     89
  27.    108
  28. Accuracy = 99.5% (199/200) (classification)
  29. Accuracy = 68.5714% (48/70) (classification)
  30. Elapsed time is 0.040873 seconds.
  31. >> 
复制代码
上面的代码基本我不想多说什么。

只是说一下参数输入的意义:

1.svmtrain函数第三个参数意义

  1. % 利用训练集合建立分类模型
  2. model = svmtrain(trainlabel,traindata,'-s 0 -t 2 -c 1.2 -g 2.8');

svmtrain第三个参数意义:  
-s svm类型:SVM设置类型(默认0)
  0 -- C-SVC
  1 --v-SVC
  2 – 一类SVM
  3 -- e -SVR
  4 -- v-SVR
-t 核函数类型:核函数设置类型(默认2)
  0 – 线性:u'v
  1 – 多项式:(r*u'v + coef0)^degree
  2 – RBF函数:exp(-r|u-v|^2)
  3 –sigmoid:tanh(r*u'v + coef0)

-g r(gama):核函数中的gamma函数设置(针对多项式/rbf/sigmoid核函数)

-c cost:设置C-SVC,e -SVR和v-SVR的参数(损失函数)(默认1)

2.model结构体中各种参数意义

2.1 Parameters: [5x1 double]

  1. >> model.Parameters
  2. ans =
  3.          0
  4.     2.0000
  5.     3.0000
  6.     2.8000
  7.          0
model.Parameters参数意义从上到下依次为:
-s svm类型:SVM设置类型(默认0)
-t 核函数类型:核函数设置类型(默认2)
-d degree:核函数中的degree设置(针对多项式核函数)(默认3)
-g r(gama):核函数中的gamma函数设置(针对多项式/rbf/sigmoid核函数) (默认类别数目的倒数)
-r coef0:核函数中的coef0设置(针对多项式/sigmoid核函数)((默认0)


2.2 nr_class: 2

  1. >> model.nr_class
  2. ans =
  3.      2
model.nr_class表示数据集中有多少类别,这里是二分类。


2.3totalSV: 197

model.totalSV代表总共的支持向量的数目,这里共有197个支持向量;


2.4rho: 0.0583

model.rho是决策函数中的常数项的相反数(-b)


2.5Label: [2x1 double]

  1. Label =
  2.      1
  3.     -1
model.Label表示数据集中类别的标签都有什么,这里是 1,-1;


2.6

  1. ProbA: []
  2. ProbB: []
关于这两个参数这里不做介绍,使用-b参数时才能用到,用于概率估计。
-b probability_estimates: whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)

2.7nSV: [2x1 double]

  1. nSV =
  2.     89
  3.    108
model.nSV表示每类样本的支持向量的数目,这里表示标签为1的样本的支持向量有89个,标签为-1的样本的支持向量为108。

注意:这里model.nSV所代表的顺序是和model.Label相对应的。


2.8sv_coef: [197x1 double]

model.sv_coef是一个259*1的矩阵,承装的是259个支持向量在决策函数中的系数;


2.9SVs: [197x13 double]

model.SVs是一个259*13的稀疏矩阵,承装的是259个支持向量。


最终的决策函数为:

 

在由于我们使用的是RBF核函数(前面参数设置 –t 2),故这里的决策函数即为:

 

其中|| x-y ||是二范数距离 ;

这里面的

b就是-model.rho(一个标量数字);
b = -model.rho;
n代表支持向量的个数即 n = model.totalSV(一个标量数字); 

对于每一个i:
wi =model.sv_coef(i); 支持向量的系数(一个标量数字)
xi = model.SVs(i,:) 支持向量(1*13的行向量)

x 是待预测标签的样本 (1*13的行向量)
gamma 就是 -g 参数


好的下面我们通过model提供的信息自己建立上面的决策函数如下:

  1. %% DecisionFunction
  2. function plabel = DecisionFunction(x,model)

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

  5. len = length(model.sv_coef);
  6. y = 0;

  7. for i = 1:len
  8.     u = model.SVs(i,:);
  9.     y = y + model.sv_coef(i)*RBF(u,x);
  10. end
  11. b = -model.rho;
  12. y = y + b;

  13. if y >= 0
  14.     plabel = 1;
  15. else
  16.     plabel = -1;
  17. end
复制代码
有了这个决策函数,我们就可以自己预测相应样本的标签了:

  1. %%
  2. plable = zeros(270,1);
  3. for i = 1:270
  4.     x = data(i,:);
  5.     plabel(i,1) = DecisionFunction(x,model);
  6. end

  7. %% 验证自己通过决策函数预测的标签和svmpredict给出的标签相同
  8. flag = sum(plabel == PredictLabel)
  9. over = 1;
复制代码
最终可以看到 flag = 270 ,即自己建立的决策函数是正确的,可以得到和svmpredict得到的一样的样本的预测标签,事实上svmpredict底层大体也就是这样实现的。


3.svmpredict得到的返回参数意义

  1. Accuracy = 99.6296% (269/270) (classification)
  2. accuracy =
  3.    99.6296
  4.     0.0148
  5.     0.9851
返回参数accuracy从上到下依次的意义分别是:
分类准率(分类问题中用到的参数指标)
平均平方误差(MSE (mean squared error)) [回归问题中用到的参数指标]

平方相关系数(r2 (squared correlation coefficient))[回归问题中用到的参数指标]


4.运行后的返回值

#iter:迭代次数,

nu:设置nu - SVC、one-class-SVM 与nu - SVR 中参数nu ,默认值0.5,

obj:SVM文件转换为的二次规划求解得到的最小值,

rho:判决函数的常数项b,

nSV:支持向量个数,

nBSV:边界上的支持向量个数,

Total nSV:支持向量总个数。


上述例子中有些数据可能对不上,因为是两篇文章整合在一起的,不用细抠具体数字正确与否,意思到了就行