在相关推荐项目的改版中,对liblinear/fm/xgboost等主流成熟算法模型的训练效果进行了尝试和对比,并在一期改造中选择了liblinear实际上线使用。本文主要从工程应用的角度对liblinear涉及的各模式进行初步介绍,并给出liblinear/fm/xgboost的实际评测结果供参考。
1. Liblinear说明
考虑到训练效率,本次选用的为多线程并行版liblinear,实际为liblinear-multicore-2.1-4,首先直接给出其train命令所支持的各模式说明,各模式选择不仅与我们使用liblinear工具直接相关,也对我们理解liblinear很有帮助,下面即主要围绕这些模式展开。
Parallel LIBLINEAR is only available for -s0, 1, 2, 3, 11 now
Usage: train [options] training_set_file[model_file]
options:
-s type : set type of solver (default 1)
formulti-class classification
0 -- L2-regularized logistic regression (primal)
1 -- L2-regularized L2-loss support vector classification (dual)
2 -- L2-regularized L2-loss support vector classification (primal)
3 -- L2-regularized L1-loss support vector classification (dual)
4 -- support vector classification by Crammer and Singer
5 -- L1-regularized L2-loss support vector classification
6 -- L1-regularized logisticregression
7 -- L2-regularized logistic regression (dual)
forregression
11 -- L2-regularized L2-loss support vector regression (primal)
12 -- L2-regularized L2-loss support vector regression (dual)
13 -- L2-regularized L1-loss support vector regression (dual)
1.1 liblinear还是libsvm
既然是liblinear相关,不可免俗地会涉及到这个问题,当然其实这是个很大的命题,在此我们截取重点简单介绍。
首先,liblinear和libsvm都是国立台湾大学林智仁(Chih-Jen Lin)老师团队开发的,libsvm早在2000年就已经发布,liblinear则在2007年才发布首个版本。
在原理和实现上存在差别,libsvm是一套完整的svm实现,既包含基础的线性svm,也包含核函数方式的非线性svm;liblinear则是针对线性场景而专门实现和优化的工具包,同时支持线性svm和线性Logistic Regression模型。由于libsvm支持核函数方式实现非线性分类器,理论上,libsvm具有更强的分类能力,应该能够处理更复杂的问题。
但是,libsvm的训练速度是个很大的瓶颈,按一般经验,在样本量过万后,libsvm就比较慢了,样本量再大一个数量级,通常的机器就无法处理了;而liblinear设计初衷就是为了解决大数据量的问题,正因为只需要支持线性分类,liblinear可以采用与libsvm完全不一样的优化算法,在保持线性svm分类时类似效果的同时,大大降低了训练计算复杂度和时间消耗。
同时,在大数据背景下,线性分类和非线性分类效果差别不大,尤其是在特征维度很高而样本有限的情况下,核函数方式有可能会错误地划分类别空间,导致效果反而变差。林智仁老师也给出过很多实际例子证明,人工构造特征+线性模型的方式可以达到甚至超过kernel SVM的表现,同时大大降低训练的时间和消耗的资源。
关于实际时间对比,liblinear作者官方给出了以下数据:对于LIBSVM数据集中某实例"20242个样本/47236个特征",在保持交叉验证的精度接近的情况下,liblinear仅耗时约3秒,远远小于libsvm的346秒。
% time libsvm-2.85/svm-train -c 4 -t 0 -e 0.1 -m 800 -v 5rcv1_train.binary
Cross Validation Accuracy = 96.8136%
345.569s
% time liblinear-1.21/train -c 4 -e 0.1 -v 5rcv1_train.binary
Cross Validation Accuracy = 97.0161%
2.944s
1.2 具体solver的选择?线性svm还是logistic regression/L1正则化项还是L2正则化项
liblinear支持多种solver模式,以下直接列举liblinear支持的几种典型solver模式对应的结构风险函数(结构风险函数由损失函数和正则化项/罚项组合而成,实际即为求解结构风险函数最小值的最优化问题),以方便说明和理解。
L2-regularized L1-loss Support VectorClassification
L2-regularized L2-loss Support Vector Classification
L1-regularized L2-loss Support Vector Classification
L2-regularized Logistic Regression
L1-regularized Logistic Regression
Liblinear中同时支持线性svm和logisticregression,两者最大区别即在于损失函数(loss function)不同,损失函数是用来描述预测值f(X)与实际值Y之间差别的非负实值函数,记作L(Y, f(X)),即上述公式中的项。
另一个重要选择是正则化项。正则化项是为了降低模型复杂度,提高泛化能力,避免过拟合而引入的项。当数据维度很高/样本不多的情况下,模型参数很多,模型容易变得很复杂,表面上看虽然极好地通过了所有样本点,但实际却出现了很多过拟合,此时则通过引入L1/L2正则化项来解决。
一般情况下,L1即为1范数,为绝对值之和;L2即为2范数,就是通常意义上的模。L1会趋向于产生少量的特征,而其他的特征都是0,即实现所谓的稀疏,而L2会选择更多的特征,这些特征都会接近于0。
对于solver的选择,作者的建议是:一般情况下推荐使用线性svm,其训练速度快且效果与lr接近;一般情况下推荐使用L2正则化项,L1精度相对低且训练速度也会慢一些,除非想得到一个稀疏的模型(个人注:当特征数量非常大,稀疏模型对于减少在线预测计算量比较有帮助)。
1.3 primal还是dual
primal和dual分别对应于原问题和对偶问题的求解,对结果是没有影响的,但是对偶问题可能比较慢。作者有如下建议:对于L2正则-SVM,可以先尝试用dual求解,如果非常慢,则换用primal求解。
网上另一个可参考的建议是:对于样本量不大,但是维度特别高的场景,如文本分类,更适合对偶问题求解;相反,当样本数非常多,而特征维度不高时,如果采用求解对偶问题,则由于Kernel Matrix过大,求解并不方便。反倒是求解原问题更加容易。
1.4 训练数据是否要归一化
对于这点,作者是这样建议的:在他们文档分类的应用中,归一化不但能大大减少训练时间,也能使得训练效果更好,因此我们选择对训练数据进行归一化。同时在实践中,归一化使得我们能直接对比各特征的公式权重,直观地看出哪些特征比较重要。
2. liblinear及fm/xgboost实际效果对比记录
本轮改造中,主要实际尝试了liblinear各模式的效果,也同时对业界常用的fm/xgboost进行了对比测试,以下一并列出供参考。
注:由于liblinear尚为单机训练,受内存限制,不能加载全量数据训练,因此后续针对训练数据量多少(1/120->1/4->1/2)也有专门实验;
2.1 liblinear效果总结
liblinear中'L14' 解决回归问题(for regression) 的s11效果相对最好0.8361,其次是解决分类问题(formulti-class classification)的s1/s2/s5(support vector classification) 的0.8356;
尝试过的各种模式的AUC完整排序如下:s11>s1/s2/s5/>s0/s7>s6
2.1.1 -e epsilon
set tolerance of termination criterion,此参数用于设置迭代终止条件的容忍度tolerance;
从L6->L10(提升0.16%)可以看出,s2模式下调小e会使AUC小幅上升;但对于不同 模式,调小e对AUC的影响幅度似乎不同,如s0模式下基本没有变化,L1->L3(仅提升0.04%);
因为e的影响不大,因此后续模式的尝试中直接采用各模式的默认e值;
2.1.2 -c cost
set the parameter C (default 1),此参数即为惩罚系数C,仅有solver-0/2支持-C参数自动判断最佳C;
从L6/L7/L8/L9可以看出,L8是系统自动计算出的c,确实AUC最高;
因为c对AUC影响很小(非单调、仅波动0.06%),因此后续模式的尝试也直接采用各模式的默认c值;
2.1.3 训练数据量的影响
从L5->L6(提升0.3%)可以看出,数据从1/120(约200万样本)提高到1/4(约6000万样本),AUC有小幅提升;而当数据量已足够大时,再增大数据量如L1->L2,AUC反而有下降,可以认为此时对AUC已无影响;
2.2 fm效果总结
fm模型主要尝试了libfm和libffm两种,其中libfm是fm算法作者的实现,libffm则是liblinear同作者国立台湾大学林智仁(Chih-JenLin)老师团队的实现;
测试中,fm算法作者的实现libfm效果确实最好,AUC达 0.8243;
而台湾大学的实现libffm对训练数据有附加field需求(此处实验了3种field,分别为无field/4种特征大类别/50种特征小类别),合理增加field类别的数量确实能明显提高AUC,但最高AUC仍只达到0.8109,不如libfm;
将训练数据从1/120(约200万样本)增加到1/4(约6000万样本),对libfm(FM1->FM2提升0.8%)和libffm(FFM9->FFM10提升0.3%)的AUC确实均有提升,说明在数据量还不足够时,提高训练数据量还是有帮助的;
2.3 xgboost效果总结
xgboost的全称是eXtreme Gradient Boosting,它是GradientBoosting Machine的一个c++实现,作者为华盛顿大学研究机器学习的大牛陈天奇。传统GBDT以CART作为基分类器,xgboost还支持线性分类器,它能够自动利用CPU的多线程进行并行,同时在算法上加以改进提高了精度,在Kaggle等数据竞赛平台社区知名度很高。
在测试中,xgboost确实表现出了实力,仅用默认参数配置和1/120小数据量(约200万样本),就达到了0.8406的超出所有liblinear效果的AUC;受时间限制,当前并未直接采用xgboost,后续有同事进一步跟进。
3. 参考文献
1 liblinear官方主页http://www.csie.ntu.edu.tw/~cjlin/liblinear/
2 统计学习方法(中文版)李航
3 [转载]LIBSVM与LIBLINEAR(一)https://segmentfault.com/a/1190000004867622
4 关于liblinearhttp://zhangliliang.com/2014/09/06/about-liblinear/
5 机器学习中的范数规则化之(一)L0、L1与L2范数http://blog.csdn.net/zouxy09/article/details/24971995
6 LR与SVM的异同http://www.cnblogs.com/zhizhan/p/5038747.html
7 Libsvm和Liblinear的使用经验谈http://m.blog.csdn.net/article/details?id=7607112
8 SVM和logistic回归分别在什么情况下使用?https://www.zhihu.com/question/21704547
9 Linear SVM 和 LR 有什么异同? https://www.zhihu.com/question/26768865