您的位置:首页 > 其它

Libsvm-Faruto Ultimate工具箱学习笔记

2016-03-30 10:55 253 查看
分类算法的大致流程:

利用参数寻优函数进行参数寻优,这里的参数是SVMtrain训练模型的参数,参数找的好,模型训练的就好,可以提高后面预测分类的准确率。不同的SVM类型需要寻优的参数不同。然后利用最优参数去训练模型model,得到模型后就可以利用svmpredict函数进行使用预测了。

下面我将学习farutu的笔记整理一下,希望能够帮助到后面学习svm的同学快速入门,因为我也是刚刚看完了farutu作者的视频教程,趁热打铁,记录一下学习的关键部分,为后面做项目进行一个参考,忘了可以来看看自己的博客



首先是MATLAB中svm工具箱的安装。libsvm-3.1-[FarutoUltimate3.1Mcode]工具箱是faruto在libsvm 的原始作者台湾大学的林智仁先生libsvm3.1版本的基础上进行改进得来的,在原始版本的基础上,Faruto又加了一些辅助函数,便于进行操作及可视化。下面我将结合自己在学习过程中需要用的一些必要的函数,来讲一下libsvm-3.1-[FarutoUltimate3.1Mcode]工具箱的使用情况。

下面是我要讲的函数列表,当然除了这些函数以外,工具箱里还有一些可视化的函数,但是可视化的函数并不是必要的,只是在讲解的时候便于别人去理解,我在学习的时候没怎么用过,所以就没有列出,一般情况下,这些函数就够用了:

核心函数:

svmtrain

svmpredict

预处理函数:

scaleForSVM

pcaForSVM

寻优函数:

SVMcgForClass

gaSVMcgForClass

psoSVMcgForClass

可视化及指标函数:

ClassResult

VF

整合函数:

SVC


这些函数只是对于分类来说的,libsvm不仅支持分类,而且支持回归问题,回归与分类问题的本质是一样的,就是有一个输入(属性矩阵或自变量)就有一个输出(分类输出的是分类标签,回归输出的是因变量),也就是相当于与个函数映射:y=f(x).在libsvm中,回归问题与分类问题相对应有其自己对应的函数,使用方法与分类问题相对应的函数相同,这里我们只针对分类问题讲解,对回归问题如果大家需要,可以自己找资料查看,我觉得最好的一本资料就是MATLAB神经网络43个案例分析这本书,因为这本书的libsvm工具箱部分就是libsvm-3.1-[FarutoUltimate3.1Mcode]工具箱的作者Faruto(李洋)编写的,我所介绍的内容,在这本书中上都有,不过我的更精简一些,可以让大家抓住最主要的部分,节省大家的时间。好了,下面进入正题。

首先是核心函数svmtrain和svmpredict

model = svmtrain(train_label, train_data, ‘options’);

[predict_label, accuracy/mse, dec_value] = svmpredict(test_label, test_data,model);

svmtrain的调用格式

model = svmtrain(train_label, train_data, ‘options’);

输入

– train_data训练集属性矩阵,大小n*m,n表示样本数,m表示属性数目(维数),数据类型double;

– train_label训练集标签,大小n*1,n表示样本数,数据类型double ;

– options参数选项, 主要有:

Options:

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

0 -- C-SVC

1 -- nu-SVC

2 -- one-class SVM

3 -- epsilon-SVR

4 -- nu-SVR

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

0 -- 线性核函数: u'*v

1 -- 多项式核函数: (gamma*u'*v + coef0)^degree

2 -- RBF核函数: exp(-gamma*|u-v|^2)

3 -- sigmoid核函数: tanh(gamma*u'*v + coef0)

4 -- 预定义核函数(指定核矩阵)

-d degree:核函数中的degree设置(针对多项式核函数)(默认3)

-g gama:核函数中的gamma函数设置(针对多项式/rbf/sigmoid核函数)(默认1/num_features,即属性数目的倒数)

-r coef0:核函数中的coef0设置(针对多项式/sigmoid核函数)(默认0)

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

-n nu:设置nu-SVC,one-class SVM和nu-SVR的参数(默认0.5)

-p epsilon:设置epsilon-SVR中损失函数epsilon的值(默认0.1)

-m cachesize:设置cache内存大小,以MB为单位(默认100)

-e eps:设置允许的终止判据(默认0.001)

-h shrinking:是否使用启发式,0或1(默认1)

-wi weight:设置第几类的参数C为weight*C(C-SVC中的C)(默认1)

以上这些参数设置可以按照SVM的类型和核函数所支持的参数进行任意组合,如果设置的参数在函数或SVM类型中没有也不会产生影响,程序不会接受该参数;如果应有的参数设置不正确,参数将采用默认值。

输出

– model 训练得到的模型,是一个结构体。关于他的详细解释,请参考http://blog.sina.com.cn/s/blog_6646924501018fqc.html

注意:当svmtrain使用-v参数时,返回的model不再是一个结构体,分类问题返回的是交叉验证下的平均分类准确率;回归问题返回的是交叉检验下的平均mse(均方根误差)。使用-v是在参数寻优时寻找最优参数所用的,在正常模型训练时不用-v参数。关于参数寻优后面还有会介绍。

svmpredict函数的使用更加简单,输入就是待测数据的特征矩阵和标签,输出有三个一个是predict_label,预测的测试集的标签,数据类型double;accuracy/mse是一个3*1的列向量,第一个数代表分类准确率(分类问题使用),第二个代表mse(回归问题使用),第三个数表示平方相关系数(回归问题使用)。注意,如果测试集的真实标签事先无法得知,则这个返回值没有意义。实际上我们真实做预测的时候,标签本来就是应该没有的,如果我们事先都知道的话,预测标签就没有意义了。之所以要用标签,就是为了测试我们训练得到的模型去做预测时效果好不好,这个返回值就是为了验证用的。一旦我们知道了我们的模型是可靠地,我们就可以真正用它来做预测了,那么这个返回值就没有任何意义了。另外需要说明的是,标签只是我们用来表示某个类别的一个符号而已,不具有真实的数据意义,只是我们要知道,这个数据代表的是哪一类。

dec_value是决策值,只是在多分类的时候才会返回这个值,二分类的时候没有,他的矩阵大小是预测数据样本个数*类别数,但是具体代表什么意义我没有搞懂,网上也没有找到相应的解释,不过好在这个数不怎么用。

归一化预处理函数scaleforsvm的用法:

train_scale,test_scale,ps] = scale For SVM(train_data,test_data,ymin,ymax)

输入:

– train_data:训练集

– test_data:测试集

– ymin:归一化范围下限(可不输入,默认为0)

– ymax:归一化范围上限(可不输入,默认为1)

输出:

– train_scale:归一化后的训练集

– test_scale:归一化后的测试集

– ps:归一化映射

归一化化就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。首先归一化是为了后面数据处理的方便,其次是保正程序运行时收敛加快。为什么要用归一化呢?首先先说一个概念,叫做奇异样本数据,所谓奇异样本数据数据指的是相对于其他输入样本特别大或特别小的样本矢量。下面举例:

m=[0.11 0.15 0.32 0.45 30;

0.13 0.24 0.27 0.25 45];

其中的第五列数据相对于其他4列数据就可以成为奇异样本数据(下面所说的网络均值bp)。奇异样本数据存在所引起的网络训练时间增加,并可能引起网络无法收敛,所以对于训练样本存在奇异样本数据的数据集在训练之前,最好先进形归一化,若不存在奇异样本数据,则不需要事先归一化。归一化的算法实现过程可以参考:http://www.ilovematlab.cn/thread-27021-1-1.html。是否一定要做归一化这个预处理才能提高最后的分类准确率呢?答案是否定的。并不是任何问题都必须要进行归一化预处理,要具体问题具体分析,进行试验测试表明,有时归一化后的预测准确率要比没有归一化的低好多,而且不同的归一化方式对最后的准确率也会有一定的影响。还要强调一点就是训练集是如何归一化的测试集也要如何归一化。

降维预处理函数pcaForSVM的用法:

[train_pca,test_pca] = pcaForSVM(train,test,threshold)

输入:

– train_data:训练集,格式要求与svmtrain相同

– test_data:测试集,格式要求与svmtrain相同。

– threshold:对原始变量的解释程度([0,100]之间的一个数),通过该阈值可以选取出主成分,该参数可以不输入,默认为90,即选取的主成分默认可以达到对原始变量达到90%的解释程度。

输出:

– train_pca:进行pca降维预处理后的训练集。

– test_pca:进行pca降维预处理后的测试集。

再用SVM做分类预测时,需要调节相关的参数(主要是惩罚参数c和核函数参数g)才能得到比较理想的分类预测准确率。那么SVM的参数该怎么选择呢,有没有最佳的参数呢?采用CV的思想可以在某种意义下得到最优的参数,可以有效地避免欠学习和过学习状态的发生,最终对于测试集合的预测得到较理想的准确率。

然后普及一下欠拟合与过拟合是什么意思(其实我也是刚搞懂



过拟合:1)简单理解就是训练样本的得到的输出和期望输出基本一致,但是测试样本输出和测试样本的期望输出相差却很大 。2)为了得到一致假设而使假设变得过度复杂称为过拟合。想像某种学习算法产生了一个过拟合的分类器,这个分类器能够百分之百的正确分类样本数据(即再拿样本中的文档来给它,它绝对不会分错),但也就为了能够对样本完全正确的分类,使得它的构造如此精细复杂,规则如此严格,以至于任何与样本数据稍有不同的文档它全都认为不属于这个类别!

欠拟合:1)如果数据本身呈现二次型,故用一条二次曲线拟合会更好。但普通的PLS程序只提供线性方程供拟合之用。这就产生拟合不足即“欠拟合”现象,从而在预报时要造成偏差。2)如果模型未考虑足够的信息,从而无法对现实世界精确建模,将产生欠拟合(underfitting) 现象。例如,如果仅观察指数曲线上的两点,我们可能会断言这里存在一个线性关系(如图1-1 所示)。但也有可能并不存在任何模式,因为只有两个点可供参考。

简单地说,过拟合就是本来一个简单的模型就可以搞定,但是为了追求在训练集上的高准确率,我们把一些误差或者噪声也考虑进去,把模型变得很复杂,但是一旦我们用不属于这个训练集中的数据进行测试时,由于过拟合的存在,结果就会变的很差。欠拟合则正好相反,是因为数据集不够造成的,本来应该是一个相对复杂的模型,但是由于数据集不够,我们只能得到一个简单的模型,所以导致分类的结果不好。

在讲寻优函数之前,我们先对CV思想做一下简介。交叉验证(Cross Validation)方法思想简介:http://www.matlabsky.com/forum-v
... -fromuid-18677.html

关于SVM参数的优化选取,国际上并没有公认统一的最好的方法,现在目前常用的方法就是让c和g在一定的范围内取值,对于取定的c和g对于把训练集作为原始数据集利用K-CV方法得到在此组c和g下训练集验证分类准确率,最终取使得训练集验证分类准确率最高的那组c和g做为最佳的参数,但有一个问题就是可能会有多组的c和g对应于最高的验证分类准确率,这种情况怎么处理?这里采用的手段是选取能够达到最高验证分类准确率中参数c最小的那组c和g做为最佳的参数,如果对应最小的c有多组g,就选取搜索到的第一组c和g做为最佳的参数。这样做的理由是:过高的c会导致过学习状态发生,即训练集分类准确率很高而测试集分类准确率很低(分类器的泛化能力降低),因为过高的惩罚因子说明我们非常重视,所以在能够达到最高验证分类准确率中的所有的成对的c和g中认为较小的惩罚参数c是更佳的选择对象。当然,你也可以同时记录下多组c和g,在后面对测试集进行预测时可以分别使用这些参数,看最后的结果如何,再进行选择。

寻优函数:

1、SVMcgForClass:网格划分来寻找最佳参数c和g

2、gaSVMForClass:遗传算法参数寻优

3、psoSVMForClass:粒子群优化算法参数寻优

对于分类问题网格参数优化(c,g),C-SVC+RBF核函数(’-s
0 –t 2’)

[bestCVaccuracy,bestc,bestg]=SVMcgForClass(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,accstep)

输入:

train_label:训练集的标签,格式要求与svmtrain相同。

train:训练集,格式要求与svmtrain相同。

cmin,cmax:惩罚参数c的变化范围,即在[2^cmin,2^cmax]范围内寻找最佳的参数c,默认值为cmin=-8,cmax=8,即默认惩罚参数c的范围是[2^(-8),2^8]。

gmin,gmax:RBF核参数g的变化范围,即在[2^gmin,2^gmax]范围内寻找最佳的RBF核参数g,默认值为gmin=-8,gmax=8,即默认RBF核参数g的范围是[2^(-8),2^8]。

v:进行Cross Validation过程中的参数,即对训练集进行v-fold Cross Validation,默认为3,即默认进行3折CV过程。(但是我看的是默认值5)

cstep,gstep:进行参数寻优是c和g的步进大小,即c的取值为2^cmin,2^(cmin+cstep),…,2^cmax,,g的取值为2^gmin,2^(gmin+gstep),…,2^gmax,默认取值为cstep=1,gstep=1。

accstep:最后参数选择结果图中准确率离散化显示的步进间隔大小([0,100]之间的一个数),默认为4.5。

输出:

bestCVaccuracy:最终CV意义下的最佳分类准确率。

bestc:最佳的参数c。

bestg:最佳的参数g。

网格参数寻优函数(回归问题):SVMcgForRegress

[bestCVmse,bestc,bestg]=SVMcgForRegress(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,msestep)其输入输出与SVMcgForClass类似。

虽然采用网格搜索能够找到在CV意义下的最高分类准确率,即全局最优解,但有时候要想在更大范围内找最佳参数时会很费力,采用启发式算法就可以不必遍历所有的参数点,也能找到全局最优解。下面就介绍两种启发式算法ga遗传和pso粒子群优化算法。

对于分类问题利用GA来进行参数优化(c,g),C-SVC+RBF核函数(’-s
0 –t 2’)

[best CVaccuracy,bestc,bestg,ga_option]=gaSVMcgFor
Class(train_label,train,ga_option)

输入:

– train_label:训练集的标签,格式要求与svmtrain相同。

– train:训练集,格式要求与svmtrain相同。

– ga_option:GA中的一些参数设置,可不输入,有默认值,详细请看代码的帮助说明。

输出:

– best CVaccuracy:最终CV意义下的最佳分类准确率。

– bestc:最佳的参数c。

– bestg:最佳的参数g。

– ga_option:记录GA中的一些参数。

注意:作者farutu用的是谢菲尔德的遗传算法工具箱,直接将遗传算法的工具箱放在了他的工具箱里面,可以直接用,并不是用的MATLAB本身自带的遗传算法的函数。

一般情况下,ga_options 采用默认值就可以,不用输入这部分。

对于分类问题利用PSO

来进行参数优化(c,g), C-SVC+RBF核函数(’-s 0
–t 2’)

[best CVaccuracy,bestc,bestg,pso_option]= pso
SVMcg For Class(train_label,train,pso_option)

输入:

– train_label:训练集的标签,格式要求与svmtrain相同。

– train:训练集,格式要求与svmtrain相同。

– pso_option:PSO中的一些参数设置,可不输入,有默认值,详细请看代码的帮助说明。

输出:

– best CVaccuracy:最终CV意义下的最佳分类准确率。

– bestc:最佳的参数c。

– bestg:最佳的参数g。

– pso_option:记录PSO中的一些参数。

一般,pso_options采用默认值就可以,不用输入这部分。

注意:一般情况下采用默认值就可以了,经过试验,默认值往往能够达到最好的效果。

可视化及指标函数:

1、ClassResult

2、VF

classresult函数的用法:CR = ClassResult(label, data, model, type)

type 1:输入的data为训练集

2:输入的data为测试集

如果是二分类的时候才会给出下面所有这些参数,多分类只会返回CR.accuracy

CR.accuracy,整体的分类准确率,及每一类的分类准确率

CR.SVlovation,model中支持向量在原始数据集中的位置

CR.b,决策函数中的常数项

CR.w,每个支持向量的系数

CR.alpha ,w=alpha*y,y代表标签

如果type=1,输入是训练集的时候,算出来的分类准确率是不具有参考意义的,因为其实就是用训练集训练出来的模型又对训练集进行了一次精确度的验证,所以精确度会比较高,当然也不见得就会达到100,因此只有type=2的分类精度才有意义,多分类时type=1,可以看一下支持向量所占训练集样本数目的比例。

VF函数的用法,评价分类结果的好坏不一定非得用分类准确率,还可以用一些其他的指标,VF函数就是返回一些分类问题的评价指标,但是这个函数是只用于二分类的C-SVM,并且类别标签是1或-1(我看了源码,其实只要求二分类时正样本的标签是1就可以了,负样本的标签随意即可),多分类,回归以及概率估计问题不属于考虑范围。关于评价分类效果的指标,可以看http://blog.csdn.net/wangran51/article/details/7579100

[score,str] = VF(true_labels,predict_labels,type)

输入:

-true_labels:是实际的正确的标签

-predict_labels:是预测得到的标签

-type : 1,2,3,4,5

type=1:输出的score就是Accuracy = #true / #total

依次:2:Precision = true_positive / (true_positive + false_positive)

3:Recall = true_positive / (true_positive + false_negative)

4:F-score = 2 * Precision * Recall / (Precision + Recall)

5: BAC (Ballanced ACcuracy) = (Sensitivity + Specificity) / 2, where Sensitivity = true_positive / (true_positive
+ false_negative) and
Specificity = true_negative / (true_negative + false_positive)

输出的str是与score相对应的打印语句。

整合函数SVC:

上面所说的这些函数都可以被一个整合函数SVC包含(除了VF),SVC是一个分类问题中各种函数插件的一个整合函数,类似的回归问题的整合函数是SVR。下面是SVC的用法。

[predict_label,accuracy] = SVC(train_label,train_data,test_label,test_data,Method_option)

输入:

前四个和SVMtrain是一样的,后面的Method_option代表的意思如下:其中1代表是,0代表不是

Method_option.plot Original = 0 or 1 表示是否画出原始数据

Method_option.scale = 0 or 1 表示是否进行归一化

Method_option.plot Scale = 0 or 1 表示是否画出归一化后的图像

Method_option.pca = 0 or 1 表示是否进行pca降维预处理

Method_option.type = 1[grid] or 2[ga] or 3[pso] 表示采用何种寻参方法

输出:predict_label,预测得到的标签,accuracy,整体的分类准确率及各个类别的分类准确率,当然你如果想看训练得到的模型的话,也可以在返回参数中加一个model。

大家可以验证一下,得到的结果与上面 自己用SVMtrain,SVMpredict,及一些预处理和寻优函数的组合结果是一样的。

注意下面这两行语句:

cmd = ['-v ',num2str(v),' -c ',num2str(cg(nind,1)),' -g ',num2str(cg(nind,2))];

ObjV(nind,1) = svmtrain(train_label,train_data,cmd);

tip1:在cmd中使用-t等参数的时候,一定要注意’-t‘等字母的前后空格,因为如果后面不留空格,会将前后的两个参数连在一起,以为是一个数,就会影响后面的结果。我在验证SVC与自己的组合函数得到的结果时总是得不到一样的结果,后来知道就是因为这个原因。

tip2:在专门强调一下,用在寻优中的SVMtrain和我们训练时用的SVMtrain是不一样的,’-s‘的位置换成了’-v‘,而且没有核函数的选择,是一个固化好了的训练函数,只是用来训练一个模型然后去进行测试,看结果是怎样的,来评价一下,c,g参数的效果好坏,因为评价c和g好坏的指标就是分类准确率。

GUI版本

SVM_GUI工具箱是在Libsvm-Faruto Ultimate的基础上改进出来的一个图像可视化使用界面,使用前需要安装工具箱,它整合了SVC和SVR也就是分类和回归的两个整合函数,使用起来很方便,只需要手动去进行一些参数设置就可以了,基本上就是一个SVC参数的选择过程,这里就不详细说明了,使用起来很简单。

如何提高分类器的性能:

下面这些是我自己的总结,提高分类器的性能首先要提取比较好的特征,这是前提条件。

1、试一下,是不是归一化的结果更好

2、尝试一下不同类型的SVM类型

3、选择适当的核函数,一般情况下径向基RBF核函数效果不会太差

4、参数寻优,找到合适的c和g

5、如果更加重视某一类的精确度,可以调整惩罚因子的大小,就是在c的基础上乘以一个权重,增大惩罚力度,尤其是对样本数据偏斜问题。先来说说样本的偏斜问题,也叫数据集偏斜(unbalanced),它指的是参与分类的两个类别(也可以指多个类别)样本数量差异很大。比如说正类有10,000个样本,而负类只给了100个,这会引起的问题显而易见由于偏斜的现象存在,使得数量多的正类可以把分类面向负类的方向“推”,因而影响了结果的准确性。对付数据集偏斜问题的方法之一就是在惩罚因子上作文章,就是给样本数量少的负类更大的惩罚因子,表示我们重视这部分样本。

上面所说的每一步都有很多细节值得改进推敲,有很多的算法去进行试验,去得到更好的分类准确率。

总结:进行分类预测的整个过程就是:1、数据准备:将数据特征按照每行代表一个样本的数据,其列数就是每个样本的特征数,排好矩阵,每个样本对应的标签标好,一定要注意,样本与其标签相对应。2、预处理:是否进行归一化,是否进行降维。3、参数寻优:采用哪种寻优方式进行c和g的寻优。4:训练SVMtrain:利用求得的最优参数进行模型训练。5、预测SVMpredict:利用训练得到的model进行预测。6、根据预测的结果,进行相应的参数的调整。

以上就是我在学习Libsvm-Faruto Ultimate工具箱的所有收获,分享给大家,当然可能会有一些不足之处,希望大家批评指正,写了好长时间呀



。后面在我的博客中有相应的各个函数的测试样例函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: