Libliner中的-s参数选择:primal和dual

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Libliner中的-s参数选择:primal和dual
Libliner 中的-s 参数选择:primal 和dual
LIBLINEAR的优化算法主要分为两⼤类,即求解原问题(primal problem)和对偶问题(dual problem)。

求解原问题使⽤的是TRON的优化算法,对偶问题使⽤的是Coordinate Descent优化算法。

总的来说,两个算法的优化效率都较⾼,但还是有各⾃更加擅长的场景。

对于样本量不⼤,但是维度特别⾼的场景,如⽂本分类,更适合对偶问题求解,因为由于样本量⼩,计算出来的Kernel Matrix也不⼤,后⾯的优化也⽐较⽅便。

⽽如果求解原问题,则求导的过程中要频繁对⾼维的特征矩阵进⾏计算,如果特征⽐较稀疏的话,那么就会多做很多⽆意义的计算,影响优化的效率。

相反,当样本数⾮常多,⽽特征维度不⾼时,如果采⽤求解对偶问题,则由于Kernel Matrix过⼤,求解并不⽅便。

反倒是求解原问题更加容易。

下⾯是libliner 和libsvm的详细介绍:
LIBSVM与LIBLINEAR
模型与优化
LIBSVM和LIBLINEAR都提供了多种不同的模型供使⽤者选择,不同的模型有各⾃适⽤的场景。

下⾯分别介绍LIBSVM和LIBLINEAR所提供的各种模型。

LIBSVM
下⾯是LIBSVM帮助内容提供的介绍,给出了LIBSVM⽀持的5种模型。

其中模型0和1对应的都是SVM的分类模型,2对应的是one-class分类器,也就是只需要标注⼀个标签,模型3和4对应的是SVM的回归模型。

1 -s svm_type : set type of SVM (default 0)
2 0 -- C-SVC (multi-class classification)
3 1 -- nu-SVC (multi-class classification)
4 2 -- one-class SVM
5 3 -- epsilon-SVR (regression)
6 4 -- nu-SVR (regression)
⾸先来看最基础的C-SVC模型。

SVM可以写成如下的优化⽬标函数(这⾥不详细介绍推导算法了):
argminw,b,ξ subjectto 12wTw+C∑i=1lξiyi(wT?(xi)?b)≥1?ξi,ξi≤0,i=1,…,l
当模型使⽤linear kernel,也就是?(x)=x时,上⾯的问题⼀个标准的⼆次凸优化问题,可以⽐较⽅便的对每⼀个变量进⾏求导。

求解这样的问题是有很多快速的优化⽅法的,这些⽅法在LIBLINEAR中都有应⽤。

但是如果是引⼊kernel的SVM,情况就⼤不⼀样了。

因为很多时候我们既不能得到核函数的具体形式,⼜⽆法得到特征在核空间中新的表达。

这个时候,之前⽤在线性SVM上的的求解思路就完全不work了。

为了解决这个问题,就必须采⽤标准的SVM求解思路,⾸先把原问题转化为对偶问题,得到下⾯的⽬标函数(具体过程可以参考任何介绍SVM的资料):
argminα subjectto f(α)=12αTQα?eTα0≤αi≤C,i=1,…,l,yTα=0
通过对偶变化,上⾯的⽬标函数变成了⼀个关于变量α的⼆次型。

很显然,上⾯⽬标函数中最重要的常亮是矩阵Q,既训练样本的Kernel Matrix,满⾜Qi.j=?(xi)T?(xj)。

先看好的⼀⽅⾯,根据核函数的定义,能够保证Q是⼀个正定的矩阵。

也就是说,上⾯的⽬标函数还是⼀个凸函数,优化收敛后能保证得到的解是全局最优解,这也是SVM的重要优势之⼀。

但是问题也随之⽽来,使⽤常⽤的核函数,只要任意给出两个向量,总是能够计算出⼀个⾮0的距离。

这也就意味着矩阵Q将会是⼀个⾮常稠密的矩阵,如果训练样本⾜够多,那么矩阵Q的存储和计算将成为很⼤的问题,这也是SVM的优化算法中的最⼤挑战。

由于矩阵Q过⼤,所以想⼀次性优化整个α是⽐较困难的。

所以常⽤的⽅法都是先把Q⼤卸⼋块,每次选择⼀部分的Q,然后update与这部分Q相关的α的值。

这其中最著名的算法就是1998由John C. Platt提出的,⽽LIBSVM的优化过程也是基于SMO算法进⾏的。

SMO算法的每⼀步迭代都选择最⼩的优化单元,也就是固定其他的α,只挑选两个α的值进⾏优化。

之所以不选择⼀个,是因为有yTα=0的约束,⾄少选择两个α的坐标才有可能进⾏更新。

本⽂主要⽬的是介绍LIBSVM,所以就不详细讨论SMO的细节了。

⾄于LIBSVM中的具体算法实现,在中介绍的很详细,这⾥总结部分关键问题:
Working Set,也就是需要优化的α部分的选取
迭代停⽌条件的设置
α的更新算法,也就是每⼀步⼦问题的求解⽅法
Shrinking,即移除⼀些已经满⾜条件的α,加快收敛速度
Cache,当Q矩阵过⼤时,需要对矩阵进⾏缓存。

上⾯的每个问题,处理起来都不简单。

作为使⽤者,或许也没有必要深谙⾥⾯的所有细节。

我觉得最需要认识的两个问题是:1) SVM的⽬标函数看起来好像是⼀个标准的优化问题,但实际求解却要复杂得多。

为了提⾼求解的速度,既要做算法上的优化,也需要做⼯程上的改进。

如果只是简简单单按照教科书的⽅法,甚⾄直接调⽤⼀些优化的⼯具包来实现的SVM算法,最多也就算个demo。

要能够真正写⼀个⾼效稳定、能处理⼤规模数据的SVM⼯具还是⾮常不容易的。

所以⽤LIBSVM还是⽐⾃⼰实现算法要简单靠谱不少。

2)SVM的求解之所以要优化,就是因为这个问题本⾝计算和存储⽐较⿇烦。

所以虽然做了这么多的优化,整个算法求解的效率仍然较低。

所以我们在使⽤时还要注意各种程序的细节,提⾼运⾏的效率。

另外,样本量过⼤时,有时候为了充分利⽤数据,也不得不忍痛割爱,放弃kernel的使⽤。

除了标准的C-SVM,LIBSVM也提供了对其他⼀些SVM⽅法的⽀持。

其中ν-SVM与C-SVM的算法与应⽤场景基本是相同的,唯⼀的区别是原本的参数C变成了参数ν。

C-SVM中参数C调整范围在[0,+∞),⽽ν-SVM中与之对应的参数ν的调整范围变成了 (0,1]。

这样的设置使得ν-SVM更具解释性,有时在参数设置上也能提供⼀定的⽅便。

但ν-SVM与C-SVM并不存在本质上的差别,通过参数的调节,两者可以达到完全相同的效果。

所以在使⽤LIBSVM处理分类问题是,选择上⾯任何⼀种⽅法都是OK的,只需要遵循⾃⼰的习惯就好了。

One-Class SVM也是LIBSVM所⽀持的⼀种分类⽅法。

顾名思义,使⽤One Class时,只需要提供⼀类样本,算法会学习⼀个尽量⼩的超球⾯包裹所有的训练样本。

One-Class SVM看起来很有诱惑⼒,因为我们经常会遇到有⼀类样本⽽需要学习分类器的情况。

但事实上,⼀⽅⾯很多时候我们得到的正样本在采样过程中存在很⼤的偏差,导致学习出的One Class分类器不⼀定考虑到了所有正样本的情形;另⼀⽅⾯,⼤部分问题还是存在很多构造⼈⼯负样本的办法。

根据我的经验,采⽤普通的SVM效果通常还是会好过One-Class SVM,⽽One-Class SVM在真实场景中的使⽤也并算不上多。

因此在使⽤这个⽅法前也需要对问题进⾏更深⼊的研究。

最后,LIBSVM也⽀持基于SVM的回归模型,即SVR。

与分类模型类似,SVR也分为C-SVR和ν-SVR。

SVR的⽬标函数与SVM的分类模型稍有区别。

由于回归问题预测值与⽬标值的偏差可⼤可⼩,因此SVR使⽤了两个slack variable⽤来刻画预测的误差边界。

虽然存在这样的差别,但是两者的基本思路和优化算法与还是基本⼀致的。

在LIBSVM的实现中,上⾯五种模型,即C-SVM,ν-SVM,One-class SVM,C-SVR,ν-SVR,最终都可以转化为⼀个更通⽤的优化框架,然后⽤同样的策略进⾏求解,这也是LIBSVM所实现的主要功能。

在实际使⽤中,最常⽤到的⽅法还是C-SVM,这是最传统的SVM分类模型。

LIBLINEAR
LIBLINEAR是在LIBSVM流⾏多年后才开发的,要解决的问题本质上也⽐LIBSVM更简单,其优势主要在于效率与scalablility。

之所以存在这样的优势,是因为线性SVM的求解要⽐kernel SVM简单许多。

还从上⾯的对偶问题说起,之前SVM的求解很⼤程度上受到yTα=0的困扰,因此每次必须选择⼀组α进⾏优化。

如果对这⼀约束项追根述源,可以发现这⼀项是通过令模型的常数项b导数为0⽽得到的。

⽽在线性模型中,我们可以通过⼀个简单地trick,令x=[x,1]和w=[w,b],这样,在模型中的常数项就不存在了。

当然,这样的trick只能在线性模型中才适⽤。

没有了上⾯的约束,优化的⽬标函数变成了:
argminα subjecttof(α)=12αTQα?eTα0≤αi≤C,i=1,…,l
这个时候,就可以每次只选择⼀个αi进⾏优化,每⼀轮遍历α的所有维度,多轮迭代,直⾄最后收敛。

这样的优化算法叫做coordinate descent(坐标下降法)。

利⽤线性函数的特殊性,直接根据α就可以计算出w的向量表⽰,于是⼤⼤提⾼了算法的效率。

具体的优化算法可以参考⽂献。

换⼀个看问题的⾓度,线性SVM的⽬标函数可以写成下⾯的形式:
argminw12wTw+C∑i=1l(max(0,1?yiwTxi))
进⼀步对问题进⾏抽象,可以把⼀类分类问题写成下⾯的形式:
argminwΩ(w)+C∑i=1l?(yi,wTxi)
其中的?作为误差函数,⽤来度量预测值与⽬标值的损失。

在上⾯的线性SVM的情形中,有
(yi,wTxi)=max(0,1yiwTxi)
这⾥的?称为Hinge Loss。

⼜如在Logistic Regression中,loss function ?被定义为
(yi,wTxi)=log(1+eyiwTixi)
Ω⼀般被称为正则化项(Regularizer),最常使⽤的就是前⾯出现的?2-norm,写作wTw,也可以写作∥w∥22,即向量w中所有元素的平⽅和。

除?2-norm之外,?1-norm也是经常使
⽤regularizer,⽽且会带来⼀些特别的效果(后⾯会进⾏讨论)。

⼤量的监督学习模型都可以写成loss function + regularizer的形式,⽽参数C则控制了两者在最终损失函数中所
占的⽐重。

不同loss function与regularizer的选取以及两者之间的平衡,是机器学习的最重要主题之⼀。

对于上⾯的问题,有很多成熟的算法可以进⾏模型的求解,⽐如最速梯度法,⽜顿法等,对于样本量较⼤时,也可以采⽤随机梯度的⽅法进⾏训练。

⼀般来说,由于考虑了⼆阶
导数,⽜顿法本⾝的优化效率要⾼于只考虑⼀阶导数的最速梯度法。

但由于⽜顿法本⾝在计算量和收敛性上存在很多局限性,所以很少直接使⽤,⽽是在⽜顿法思想基础上进⾏
⼀定的改进。

其中普遍使⽤的算法有BFGS和L-BFGS等。

具体到liblinear软件包,作者采⽤的是Trust Region Newton (TRON) method对模型对传统⽜顿法进⾏了改进,该⽅法
被证明⽐L-BFGS训练更加⾼效。

LIBLINEAR中实现了基于TRON⽅法的L-2 SVM和Logistical Regression模型训练。

其中的L2-loss SVM是标准SVM的变种,loss function变成了:
(yi,wTxi)=(max(0,1yiwTxi))2
从实际效果来说,L2-loss SVM与标准的L1-loss SVM并没有太⼤的区别。

但是在计算上,前者的求导形式更加简单,便于梯度的计算与优化。

LIBLINEAR并没有实现Trust
Region Newton法的标准L1-loss SVM实现,⼀⽅⾯是因为直接对hinge loss求导需要分段讨论⽐较复杂,另⼀⽅⾯L2-loss SVM基本可以直接替代L1-loss SVM。

不过在其他的
⼀些软件包中,如中,则实现了L1-loss SVM的原问题求解,但使⽤的优化算法是L-BGFS⽽不是TRON。

总结
前⾯介绍了LIBSVM和LIBLINEAR的优化算法,下⾯简单总结⼀下不同算法的应⽤场景吧:
所有线性问题都是⽤LIBLINEAR,⽽不要使⽤LIBSVM。

LIBSVM中的不同算法,如C-SVM和nu-SVM在模型和求解上并没有本质的区别,只是做了⼀个参数的变换,所以选择⾃⼰习惯的就好。

LIBLINEAR的优化算法主要分为两⼤类,即求解原问题(primal problem)和对偶问题(dual problem)。

求解原问题使⽤的是TRON的优化算法,对偶问题使⽤的是Coordinate
Descent优化算法。

总的来说,两个算法的优化效率都较⾼,但还是有各⾃更加擅长的场景。

对于样本量不⼤,但是维度特别⾼的场景,如⽂本分类,更适合对偶问题求
解,因为由于样本量⼩,计算出来的Kernel Matrix也不⼤,后⾯的优化也⽐较⽅便。

⽽如果求解原问题,则求导的过程中要频繁对⾼维的特征矩阵进⾏计算,如果特征⽐较
稀疏的话,那么就会多做很多⽆意义的计算,影响优化的效率。

相反,当样本数⾮常多,⽽特征维度不⾼时,如果采⽤求解对偶问题,则由于Kernel Matrix过⼤,求解并不
⽅便。

反倒是求解原问题更加容易。

多分类问题
LIBSVM和LIBLINEAR都⽀持多分类(Multi-class classification)问题。

所谓多分类问题,就是说每⼀个样本的类别标签可以超过2个,但是最终预测的结果只能是⼀个类别。


如经典的⼿写数字识别问题,输⼊是⼀幅图像,最后输出的是0-9这⼗个数字中的某⼀个。

LIBSVM与LIBLINEAR但实现⽅式却完全不同。

LIBSVM采取的one vs one的策略,也就是所有的分类两两之间都要训练⼀个分类器。

这样⼀来,如果存在k个class,理论上就需
要训练 k(k?1)/2个分类器。

实际上,libsvm在这⼀步也进⾏了⼀定的优化,利⽤已有分类的关系,减少分类器的个数。

尽管如此,LIBSVM在多分类问题上还是要多次训练分类
器。

但是,考虑到前⾯说的LIBSVM的优化⽅法,随着样本数量的增加,训练的复杂度会⾮线性的增加。

⽽通过1VS1的策略,可以保证每⼀个⼦分类问题的样本量不⾄于太多,
其实反倒是⽅便了整个模型的训练。

⽽LIBLINEAR则采取了另⼀种训练策略,即one vs all。

每⼀个class对应⼀个分类器,副样本就是其他类别的所有样本。

由于LIBLINEAR能够和需要处理的训练规模⽐LIBSVM
⼤得多,因此这种⽅式要⽐one vs one更加⾼效。

此外,LIBLINEAR还实现了基于Crammer and Singer⽅法的SVM多分类算法,在⼀个统⼀的⽬标函数中学习每⼀个class对应
的分类器。

输出⽂件
⼀般来说,我们使⽤LIBLINEAR或者LIBSVM,可以直接调⽤系统的训练与预测函数,不需要直接去接触训练得到的模型⽂件。

但有时候我们也可能需要在⾃⼰的平台实现预测
的算法,这时候就不可避免的要对模型⽂件进⾏解析。

由于LIBLINEAR与LIBSVM的训练模型不同,因此他们对应的模型⽂件格式也不同。

LIBLINEAR训练结果的格式相对简单,例如:
1 solver_type L2R_L2LOSS_SVC_DUAL
2 nr_class
3 3 label 0 1 2
4 nr_feature
5 5 bias -1
6 w
7 -0.402109729385541
8 0.1002472498884907 -0.1619908595357437 8 0.008699468444669581 0.2310109611908343 -0.2295723940247394
上⾯的solver_type表⽰求解算法,w以下表⽰求解得到的模型权重。

其中每⼀列对应⼀个class的分类器,⽽每⼀⾏对应特征的⼀个维度。

其中nr_class表⽰求解的个
数,nr_feature表⽰特征的维度,bias表⽰模型的bias,可以⼈⼯设置权重。

这⾥容易产⽣误解的是label这个字段,表⽰的是每⼀个⽤户训练⽂件中label对应w的列数。

⽐如在上
⾯的模型中,⽤户指定编号为0的分类器对应w的第⼀列。

但是上⾯的对应关系并不是⼀定存在的,⽐如在⼆分类场景中,⽤将整样本标为1,负样本标为0,但在模型训练
中,LIBLINEAR会按照⾃⼰的编号系统进⾏训练,因⽽有可能出现负样本在前,正样本在后的情形。

这时候,就必须要根据label 1 0将LIBLIENAR内部的编号体系与真实的⽤户
标签进⾏对应。

当然,后来LIBLINEAR和LIBSVM做了⼀些优化,在⼆分类时,如果正负样本标签分别是-1和+1,那么可以始终保证正样本出现在w的第⼀列。

但是这个机制也
不是完全靠谱,⽐如说在LIBLINEAR的spark实现代码中,就没有实现这个特性,曾经把我整的很惨。

因此在这⾥还是需要⼗分注意。

LIBSVM的训练结果格式就更复杂⼀些,例如:
1 kernel_type rbf
2 gamma 0.0769231
3 nr_class 3
4 total_sv 140
5 rho -1.0449
6 0.315784 1.0303
7 6 label 1 0 -1 7 nr_sv 2 2 1
8 SV
9 0 1 1:0.583333 2:-1 3:0.333333 4:-0.603774 5:1 6:-1 7:1 8:0.358779 9:-1 10:-0.483871 12:-1 13:1
上⾯参数的意义都⽐较直接,需要注意的是SV后⾯就是训练出的模型参数,以⽀持向量的⽅式进⾏存储。

nr_sv给出了每⼀个⽀持向量所对应的模型,⽐如“2 2 1”就表⽰前两⾏
是标签为1类的⽀持向量,其后⾯两⾏是标签为0类的⽀持向量,最后⼀⾏是标签为-1类的⽀持向量。

⽽具体每⼀⾏⽀持向量,在上⾯的模型中,由于存在三类,所以每⼀个⽀持
向量有可能都会存在于两个分类器中,所以前两列的数分别对应了对剩下两个分类作为⽀持向量时候的α值,后⾯才是真正的⽀持向量。

相关文档
最新文档