• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

matlab 基于 libsvm工具箱的svm分类遇到的问题与解决

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

最近在做基于无线感知的身份识别这个工作,在后期数据处理阶段,需要使用二分类的方法进行训练模型。本身使用matlab做,所以看了一下网上很多都是使用libsvm这个工具箱,就去下载了,既然用到了想着就把这个东西梳理一下,顺便记录一下过程中的遇到的问题。

1、  Libsvm下载与安装

Libsvm这个工具箱是 台@@湾 大学林智仁(Lin Chih-Jen)教授等开发的一套基于SVM的模式识别的软件包,网上也有详细的介绍,还有源代码,很方便学习。

下载:https://www.csie.ntu.edu.tw/~cjlin/libsvm/

我用的是现在比较新的一个版本:libsvm-3.23

安装:安装过程比较简单,下载好工具包之后傻瓜操作就可以了

A、解压到matlab安装根目录toolbox下(其他目录也行,最好放这儿,比较好找,其他地方哪天说不定删掉) D:\Program Files\MATLAB\R2015b\toolbox\

B、 打开matlab之后设置好当前路径:D:\Program Files\MATLAB\R2015b\toolbox\libsvm-3.23\matlab,在命令行输入mex –setup,选择编译环境。(编译环境比较重要,需要将这个工具箱中的源码使用C编译器编译,不然无法使用)

 

 

C、 在命令行输入 make 进行编译,在D:\Program Files\MATLAB\R2015b\toolbox\libsvm-3.23\matlab 生成svmtrain.mexw64、svmpredict.mexw64、libsvmread.mexw64,

libsvmwrite.mexw64这四个文件,仔细查看,如果没有编译成功也无法使用。

D、到这一步其实应该是没啥问题了,可以在命令行输入 which svm,会输出你之前工具箱所在的那个路径。如果都没啥问题,就可以使用了,不放心还可以使用它自带的数据进行测试。

2、  svm 的使用

svm的使用也比较简单,不过也根据需求而定,可以做one-class、two-class,当然也可以实现多分类。这都取决于svm模型的参数设定,关于参数详细可以doc svmtrain在matlab帮助文档中查看。

1 训练:model = svmtrain(trainlabel,traindata,PARAMETERS);
2 
3 预测:[predictlabel,predictacc] =svmpredict(testlabel,testdata,model);

PARAMETERS一般是用键值对的方式,如‘-s 0 -c 100 -g 0.8 -t 2 -b 1’ 可以没有,没有就是默认参数。一般来说为了达到好的结果都会进行调参

简单列一下主要参数:(红色的是我实验中用到的参数)

-s svm类型:SVM设置类型(默认0)

0 -- C-SVC:C-支持向量分类机; C代表惩罚系数,C越大表示对错误分类的惩罚越大,通过自己实验发现这个C确实对准确率影响很大,C的选择很关键。

1 --v-SVC:v-支持向量分类机;

2 – 一类SVM:​单类别-支持向量机,不需要类标号,用于支持向量的密度估计和聚类。这种思路可能更适合对于那种异常检测的应用,这个单类模型需要有很高的区分度。

3 -- e -SVR:ε-支持向量回归机。

4 -- v-SVR:n-支持向量回归机。

3、4对应回归问题,用到可以试一下。

 

-t 核函数类型:核函数设置类型(默认2)

0 – 线性核:u\'v

1 – 多项式核:(r*u\'v + coef0)^degree

2 – RBF核:exp(-gamma|u-v|^2)

3 – sigmoid:tanh(r*u\'v + coef0)

 

-d degree : 用于多项式核函数,默认值是3

-g gamma :多项式核函数、RBF核函数、sigmoid核函数。默认是1/k(num_features)

-r coef0 :多项式核函数、sigmoid核函数。默认是0

-c cost : C-SVC使用的惩罚因子C,epsilon-SVR, and nu-SVR中也使用 ,默认值为1

-n nu : nu-SVC, one-class SVM, and nu-SVR使用的参数nu。默认值为0.5

-p epsilon : epsilon-SVR的损失函数所用参数,默认0.1

-m cachesize :设置缓存大小,默认100M

-e epsilon :终止标准公差,默认0.001

-h shrinking :是否使用缩减的启发式

-b probability_estimates :是否训练SVC或SVR模型进行概率估计,0或1(默认为0)

-wi weight : C-SVC

-v n: n-折交叉验证,必须大于等于2

-q : quiet mode (no outputs)

 

 
%关于网格搜索调参:网格搜索其实就是穷举给定范围内c和g的值来选择模型,c和g给定的范围不要太大,不然穷举次数太多导致程序跑起来太慢。

%寻找最优c和g

% c 的变化范围是 2^(-2),2^(-1.5),...,2^(10), g 的变化范围是 2^(-4),2^(-3.5),...,2^(4)

[bestacc,bestc,bestg] = SVMcgForClass(trainlabelk,traindatak,-2,10,-4,4,3,0.5,0.5,0.9);

%将得到的最高的参数bestc和bestg用来训练模型

cmd = [\'-c \',num2str(bestc),\' -g \',num2str(bestg),\' -t \',num2str(2),\' -b \',num2str(1)];

model = svmtrain(trainlabel,traindatak,cmd);

3、  遇到的问题

A 分类模型

多分类(单个模型):

  我要做的是不同人的身份识别,比如我现在有20个人的数据,我需要识别出这20个人,这样一看好像就是个多分类问题,一个多分类模型就可以搞定,我也用了一些matlab中自带的一个应用于多分类的svm(这个在2014版以后的matlab中有):

Mdl = fitcecoc(traindata,trainlabel);

[preb] = predict(Mdl,testdata);

  但是后来一想,这个模型根本没法扩展,人多了就没法用了,实际根本不可行。这样根本没法扩展,更多的人来怎么办?

基于异常检测的多分类(one class SVM):这个实现方法比较多(有一对一,一对多等),可以根据不同的数据集以及应用场景确定

   直接用每个人的数据给自己训练一个模型,这样得到N个不同的模型,用不同的测试数据测试,显然结果不是很好,这个对训练数据的要求很高,如果做人脸识别或者指纹识别这种,可能更适合这种方式。

 

前面两种都试了,效果不理想,所以只能用基于二分类的多分类,给每个人建立模型的时候,将其他所有不是这个人的数据作为负样本进行训练,这样虽然说扩展性也不是很好,但还是有进行扩展的空间。

B、可能性评估出现Line search fails in two-class probability estimates

  因为每个人只有50条左右的数据,所以在给每个人训练样本时,正负样本的比例接近几十倍。当然这个问题确实会有,但是为了模型的准确性也不可避免这样做。

  开始训练模型和测试,使用70%训练集,30测试集的原则进行数据集划分,在人数少时识别效果非常好,在人数多时出现了很奇怪的问题:结果接近两个极端,一个很好,一个很差,而且重复很多次实验,仍然是这样,没有别的结果出现,差的结果占百分之七八十。反复检查之后发现坏结果发生时,命令行会输出这样一句话:Line search fails in two-class probability estimates

 百度之后发现这个问题也确实有人遇到过但不是很多,本人也是菜鸟,所以还真不知道哪里出了问题,参考网上的说法(https://stackoverflow.com/questions/16709053/libsvm-outputs-line-search-fails-in-two-class-probability-estimates),我也试了,还是没有找到端倪:

 

 

 

有回答说这个是单纯效果不好的原因,我有点怀疑,但是为什么只有两个极端呢,这个结果不好应该是个随机的,至少结果分布应该正常的,这完全就不是我想看到的结果。所以我打开了svm的源码,找到输出那条语句的地方:

 

果然,在可能性计算的时候,就没有进去这个循环,而是直接跳出了,突然想到可能模型并没有训练,去看了一下训练好的模型,结果是这样:

 

里面全是空的,支持向量都没有,ok那就是说,一开始由于样本的不均衡导致svm觉得这两类训练数据完全分不开就直接罢工不干了…好吧,就是数据集惹的祸。

后面改了训练样本中正负样本的比例,就不会出现这个问题了。

 

参考链接:

https://www.cnblogs.com/LuffySir/p/5961219.html

https://blog.csdn.net/s9434/article/details/75386112

https://stackoverflow.com/questions/16709053/libsvm-outputs-line-search-fails-in-two-class-probability-estimates

https://stackoverflow.com/questions/36686672/why-do-i-get-the-message-line-search-fails-in-two-class-probability-estimates

https://blog.csdn.net/ture_dream/article/details/52788745


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Rust 与 Golang - 何时使用它们?发布时间:2022-07-18
下一篇:
【Rust】路径发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap