如果你已经看完并理解了我的上一篇SVM的博客,那么接下来你要面对的是怎么应用SVM这个实际的问题,现在SVM里面应用最广泛的就是LIBSVM这个函数库,OpenCV中也基于LIBSVM推出了CvSVM 的函数。因此下面的内容,我主要是介绍一下LIBSVM的应用方法,主要是参考文献[1,2]。
LIBSVM是国立*大学 Chih-Jen Lin开发的一个SVM的函数库,他不但提供了编译好的可在Windows系列系统的执行文件,还提供了源代码,方便改进、修改以及在其它操作系统上应用;该软件对SVM所涉及的参数调节相对比较少,提供了很多的默认参数,利用这些默认参数可以解决很多问题;并提供了交互检验(Cross Validation)的功能。该软件包可在http://www.csie.ntu.edu.tw/~cjlin/免费获得。该软件可以解决C-SVM、ν-SVM、ε-SVR和ν-SVR等问题,包括基于一对一算法的多类模式识别问题。
上一篇博客中谈的内容是从理论出发的东西,但是在实际应用中,我们常常无法找到一个完美无缺的判别超平面,那么为了能够在这样子的不可分的集合中学习支持向量机,需要引入软间隔(soft margin)来进行分类,即是允许一些训练模式停留在判别超平面的“错误”一侧,或者说允许其他类的模式停留在间隔内,则上一篇博客中的公式(3)修改为:
其中为松弛变量,对应数据点偏离对应的间隔面(非分类超平面)的距离(见图1)。因此,最终的结果是margin可以比1小,但是当某些点出现这种margin比1小的情况时(这些点也称离散点),意味着我们放弃啦对这些点的精确分类,而这对分类器来说是一种损失,但是放弃这些点也带来了好处,就是分类面不必向这些点的方向移动,因而可以得到更大的几何margin。显然,我们必须权衡这种损失和好处。好处是明显的,我们得到的分类间隔越大,好处就越多。
图1 松弛变量
下面还有几点需要注意:
- 并非所有的样本点都有一个松弛变量与其对应。实际上只有“离群点”才有,或者也可以这么看,所有没离群的点松弛变量都等于0(对负类来说,离群点就是在前面图中,跑到H2右侧的那些负样本点,对正类来说,就是跑到H1左侧的那些正样本点)。
- 松弛变量的值实际上标示出了对应的点到底离群有多远,值越大,点就越远。
- 惩罚因子C决定了你有多重视离群点带来的损失,显然当所有离群点的松弛变量的和一定时,你定的C越大,对目标函数的损失也越大,此时就暗示着你非常不愿意放弃这些离群点,最极端的情况是你把C定为无限大,这样只要稍有一个点离群,目标函数的值马上变成无限大,马上让问题变成无解,这就退化成了硬间隔问题。
- 惩罚因子C不是一个变量,整个优化问题在解的时候,C是一个你必须事先指定的值,指定这个值以后,解一下,得到一个分类器,然后用测试数据看看结果怎么样,如果不够好,换一个C的值,再解一次优化问题,得到另一个分类器,再看看效果,如此就是一个参数寻优的过程,但这和优化问题本身决不是一回事,优化问题在解的过程中,C一直是定值,要记住。
- 尽管加了松弛变量这么一说,但这个优化问题仍然是一个优化问题(汗,这不废话么),解它的过程比起原始的硬间隔问题来说,没有任何更加特殊的地方。
现在,我们来看看在实际应用中的C-SVM:
文献[1]中推荐的SVM使用步骤如下:
- 【将数据变换成SVM格式】Transform data to the format of an SVM package
- 【数据规范化(scale)】Conduct simple scaling on the data
- 【考虑使用RBF核】Consider the RBF Kernel
- 【使用交叉验证获取最优参数C和Gamma】Use Corss-validation to find the best parameter C and Gamma
- 【使用最优参数来训练整个训练集】Use the best parameter C and Gamma to train the whole training set
- 【新来数据的测试】Test
描述如下:
Data Preprocessing
Categorical Feature
SVM要求数据实例是实数向量,因此,我们必须先把它的类别特征转换成数值特征。这里推荐使用m个值去代表m类的特征。例如,一个三类特征{red,green,blue}可以表示成(0,0,1)(0,1,0)(1,0,0)。经验表明,当类别不是非常大时,这种特征类别编码方式更稳定
Scaling
Scaling在SVM中非常重要,这里推荐使用linearly scaling each attribute to the range [-1,+1] or [0,1]。
Model Selection
RBF Kernel
一般情况下,RBF Kernel 是一个合理的第一选择,可以首先尝试这个核函数。
Cross-validation and Grid-search
RBF核函数有两个参数:C和Gamma。针对一个给定的问题,需要通过参数搜索方法来获取他们的最优值。一个常用的方法是将训练数据分成2个部分,其中一部分为“未知的”,通过对未知数据的分类效果来反映系统分类性能。该方法的一个提升版本就是Cross-validation交叉验证。在v-fold交叉验证中,我们首先将数据分成v组,将每个子集分别做一次测试集,其余v-1组作为训练集,这样就会得到v个模型,用这v个模型最终的测试集的分类准确率作为v-fold cross-validation分类性能的指标。这里我们推荐使用“grid-search”,即尝试各个参数对(C,gamma),我们发现使用指数增长能更快找到最佳参数值。如
C = 2^(-5) 2^(-3) .... 2^15
gamma = 2^(-15) 2^(-13) ... 2^3
————————————————————————————————————————————————————————————
下面来看一下libsvm中的一个简单demo(\libsvm-3.17\windows\svm-toy.exe)
打开svm-toy.exe显示如下:
用鼠标点击上面生成数据点,然后用change生成新的点,最后用run进行分类;下面是我生成的数据点,总共三类数据点:
分类效果:
参考文献
[1] Hsu C W, Chang C C, Lin C J. A practical guide to support vector classification[J]. 2003.
[2] Chang C C, Lin C J. LIBSVM: a library for support vector machines[J]. ACM Transactions on Intelligent Systems and Technology (TIST), 2011, 2(3): 27.