SVM应用
我在项目中应用的SVM库是国立台湾大学林智仁教授开发的一套开源软件,主要有LIBSVM与LIBLINEAR两个,LIBSVM是对非线性数据进行分类,大家也比较熟悉,LIBLINEAR是对线性数据进行分类,时间复杂度较之LIBSVM要低得多,而且运用于嵌入式领域的话产生的训练集占用芯片内存也要少得多,所以如果需要分类的数据有比较好的区分度的话,推荐使用LIBLINEAR。
LIBLINEAR主要解决大规模数据分类,先来看一下前几章提到的最优间隔分类器模型:
基于上面的模型,LIBLINEAR提供了8种分类方法和3中回归方法,而且能够任意的设置,优化参数。下面是源码中对LIBLINEAR的功能介绍:
void exit_with_help()
{
printf(
"Usage: train [options] training_set_file [model_file]\n"
"options:\n"
"-s type : set type of solver (default 1)\n"
" for multi-class classification\n"
" 0 -- L2-regularized logistic regression (primal)\n"
" 1 -- L2-regularized L2-loss support vector classification (dual)\n"
" 2 -- L2-regularized L2-loss support vector classification (primal)\n"
" 3 -- L2-regularized L1-loss support vector classification (dual)\n"
" 4 -- support vector classification by Crammer and Singer\n"
" 5 -- L1-regularized L2-loss support vector classification\n"
" 6 -- L1-regularized logistic regression\n"
" 7 -- L2-regularized logistic regression (dual)\n"
" for regression\n"
" 11 -- L2-regularized L2-loss support vector regression (primal)\n"
" 12 -- L2-regularized L2-loss support vector regression (dual)\n"
" 13 -- L2-regularized L1-loss support vector regression (dual)\n"
"-c cost : set the parameter C (default 1)\n"
"-p epsilon : set the epsilon in loss function of SVR (default 0.1)\n"
"-e epsilon : set tolerance of termination criterion\n"
" -s 0 and 2\n"
" |f'(w)|_2 <= eps*min(pos,neg)/l*|f'(w0)|_2,\n"
" where f is the primal function and pos/neg are # of\n"
" positive/negative data (default 0.01)\n"
" -s 11\n"
" |f'(w)|_2 <= eps*|f'(w0)|_2 (default 0.001)\n"
" -s 1, 3, 4, and 7\n"
" Dual maximal violation <= eps; similar to libsvm (default 0.1)\n"
" -s 5 and 6\n"
" |f'(w)|_1 <= eps*min(pos,neg)/l*|f'(w0)|_1,\n"
" where f is the primal function (default 0.01)\n"
" -s 12 and 13\n"
" |f'(alpha)|_1 <= eps |f'(alpha0)|,\n"
" where f is the dual function (default 0.1)\n"
"-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)\n"
"-wi weight: weights adjust the parameter C of different classes (see README for details)\n"
"-v n: n-fold cross validation mode\n"
"-q : quiet mode (no outputs)\n"
);
exit();
}
库的实现主要在linear.cpp这个文件中,其中train()函数负责训练数据得出相应的model,predict()函数负责预判未知的输入数据。具体的使用帮助请参考软件包中的README文件。我在项目中使用的训练方法主要是坐标下降法,下面就是坐标下降法 的主要原理和应用。
L2-regularized L1- and L2-loss Support Vector Classification(dual)
L2-regularized L1-loss support vector classification (dual)的最优化模型:
L2-regularized L2-loss support vector classification (dual)的最后化模型:
他们的对偶形式都是
下面讨论的求解过程以L1 SVC为准,L1与L2的泛化能力差不多,而训练时间一般L2要快些。
在求解这个方程之前我们先来了解一下坐标下降法(上述对偶形式的求解方法)。
J(θ)以线性回归的例子来定义:
这里的α是叫做学习速度(learning rate), 它决定了坐标下降的幅度大小,假设在只有一个训练样本的情况下对J(θ)求偏导并代入上式:
Θ的大小与误差偏移(y-h(x))成比例,也就是说如果遇上一个与实际值相近的预测值,则我们几乎不需要对θ做改变,相反,如遇到差距比较大的值,则要对θ做一定的调整。
现在再回到先前提到的对偶问题
为方便起见,我们把式子改写成:
对 关于 求导得
当d=0,即 时收敛,也就是说 达到最优值,在先前SVM原理简介中提到,带入到 中得到:。在更新α的同时我们也需要更新w:,其中 是更新后的值, 是更新前的值, ,两个值的差值d可以对上面的 关于d求导得到 :,可能写的比较乱,下面列出整个流程的伪代码来理清思路。
贴出LIBLINEAR源码中使用坐标下降法的核心代码
if(fabs(PG) > 1.0e-12)
{
double alpha_old = alpha[i];
alpha[i] = min(max(alpha[i] - G/QD[i], 0.0), C);
d = (alpha[i] - alpha_old)*yi;
xi = prob->x[i];
while (xi->index != -)
{
w[xi->index-] += d*xi->value;
xi++;
}
}
至于LIBLINEAR用到的其他方法(比如牛顿法)由于空余时间有限,也因为我在项目中用到的SVM对于训练时间没有太多要求,等有时间再来好好研究一下。一般来讲牛顿法比坐标下降法收敛的迭代次数要少得多,牛顿法要用到Hesse矩阵,所以每次迭代的运算量将会更大,但总的来说使用牛顿法所消耗的训练时间还是要比坐标下降法快得多,特别在特征量比较少的时候。
下面再来看predict,LIBLINEAR在训练时求出来的实际上就是个超平面,在预测时只要判断未知点在超平面的里面还是外面就可以完成判断,是常数级别的时间复杂度。因为我使用的SVM应用于嵌入式领域,使用核函数的SVM对于我来说太慢了,而LIBLINEAR刚好符合我的要求,在实际使用时我选取的是6个特征量,在cortex-m3中平均0.25ms就可以完成一次预测。下面是predict的源码。
double predict_values(const struct model *model_, const struct feature_node *x, double *dec_values)
{
int idx;
int n;
if(model_->bias>=)
n=model_->nr_feature+;
else
n=model_->nr_feature;
double *w=model_->w;
int nr_class=model_->nr_class;
int i;
int nr_w;
if(nr_class== && model_->param.solver_type != MCSVM_CS)
nr_w = ;
else
nr_w = nr_class; const feature_node *lx=x;
for(i=;i<nr_w;i++)
dec_values[i] = ;
for(; (idx=lx->index)!=-; lx++)
{
// the dimension of testing data may exceed that of training
if(idx<=n)
for(i=;i<nr_w;i++)
dec_values[i] += w[(idx-)*nr_w+i]*lx->value;
} if(nr_class==)
{
if(model_->param.solver_type == L2R_L2LOSS_SVR ||
model_->param.solver_type == L2R_L1LOSS_SVR_DUAL ||
model_->param.solver_type == L2R_L2LOSS_SVR_DUAL)
return dec_values[];
else
return (dec_values[]>)?model_->label[]:model_->label[];
}
else
{
int dec_max_idx = ;
for(i=;i<nr_class;i++)
{
if(dec_values[i] > dec_values[dec_max_idx])
dec_max_idx = i;
}
return model_->label[dec_max_idx];
}
}
对于惩罚因子C的优化问题,可以借助LIBSVM中grid.py这个工具,它使用交叉验证来选出预测精度最高的那个参数,如果同时优化两个参数(RBF kernel中的c和g),它可以借助gnuplot画出等高线来帮助我们直观的了解整个优化的过程,当然可以根据你自己的需要来修改grid.py来优化你想要的参数,非常有用的小工具。
Usage: grid.py [grid_options] [svm_options] dataset grid_options :
-log2c {begin,end,step | "null"} : set the range of c (default -,,)
begin,end,step -- c_range = ^{begin,...,begin+k*step,...,end}
"null" -- do not grid with c
-log2g {begin,end,step | "null"} : set the range of g (default ,-,-)
begin,end,step -- g_range = ^{begin,...,begin+k*step,...,end}
"null" -- do not grid with g
-v n : n-fold cross validation (default )
-svmtrain pathname : set svm executable path and name
-gnuplot {pathname | "null"} :
pathname -- set gnuplot executable path and name
"null" -- do not plot
-out {pathname | "null"} : (default dataset.out)
pathname -- set output file path and name
"null" -- do not output file
-png pathname : set graphic output file path and name (default dataset.png)
-resume [pathname] : resume the grid task using an existing output file (default pathname is dataset.out)
This is experimental. Try this option only if some parameters have been checked for the SAME data.
SVM应用的更多相关文章
- EasyPR--开发详解(6)SVM开发详解
在前面的几篇文章中,我们介绍了EasyPR中车牌定位模块的相关内容.本文开始分析车牌定位模块后续步骤的车牌判断模块.车牌判断模块是EasyPR中的基于机器学习模型的一个模块,这个模型就是作者前文中从机 ...
- 8.SVM用于多分类
从前面SVM学习中可以看出来,SVM是一种典型的两类分类器.而现实中要解决的问题,往往是多类的问题.如何由两类分类器得到多类分类器,就是一个值得研究的问题. 以文本分类为例,现成的方法有很多,其中一劳 ...
- 5.SVM核函数
核函数(Kernels) 定义 1.1 (核或正定核) 设是中的一个子集,称定义在上的函数是核函数,如果存在一个从到Hilbert空间的映射 使得对任意的,都成立.其中表示Hilbert空间中的内积. ...
- 4. SVM分类器求解(2)
最优间隔分类器(optimal margin classifier) 重新回到SVM的优化问题: 我们将约束条件改写为: 从KKT条件得知只有函数间隔是1(离超平面最近的点)的线性约束式前面的系数,也 ...
- 2. SVM线性分类器
在一个线性分类器中,可以看到SVM形成的思路,并接触很多SVM的核心概念.用一个二维空间里仅有两类样本的分类问题来举个小例子.如图所示 和是要区分的两个类别,在二维平面中它们的样本如上图所示.中间的直 ...
- 1. SVM简介
从这一部分开始,将陆续介绍SVM的相关知识,主要是整理以前学习的一些笔记内容,梳理思路,形成一套SVM的学习体系. 支持向量机(Support Vector Machine)是Cortes和Vapni ...
- SVM分类与回归
SVM(支撑向量机模型)是二(多)分类问题中经常使用的方法,思想比较简单,但是具体实现与求解细节对工程人员来说比较复杂,如需了解SVM的入门知识和中级进阶可点此下载.本文从应用的角度出发,使用Libs ...
- 【十大经典数据挖掘算法】SVM
[十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART SVM(Support Vector ...
- 卷积神经网络提取特征并用于SVM
模式识别课程的一次作业.其目标是对UCI的手写数字数据集进行识别,样本数量大约是1600个.图片大小为16x16.要求必须使用SVM作为二分类的分类器. 本文重点是如何使用卷积神经网络(CNN)来提取 ...
- 机器学习实战笔记(Python实现)-05-支持向量机(SVM)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
随机推荐
- 应用程序加载外部字体文件(使用AddFontResource API函数指定字体)
/* MSDN: Any application that adds or removes fonts from the system font table should notify other w ...
- java:继承
一.继承: java只支持单继承,一个子类只能继承一个父类,使用继承是为了减少类的重复代码,且父类的构造函数不能被子类继承. 当两个类里面有相同的属性或方法,就应该考虑使用继承解决重复代码了. 继承的 ...
- (转)Struts 拦截器
一.拦截器是怎么实现: 实际上它是用Java中的动态代理来实现的 二.拦截器在Struts2中的应用 对于Struts2框架而言,正是大量的内置拦截器完成了大部分操作.像params拦截器将http请 ...
- ios开发之 MPMoviePlayerController 视频播放器
MPMoviePlayerController 与AVAudioPlayer有点类似,前者播放视频,后者播放音频,不过也有很大不同,MPMoviePlayerController 可以直接通过远程UR ...
- 关于imx6核心板qt系统U盘挂载
在使用imx6核心板开发的时候,程序写到U盘,想通过U盘在板子上运行程序,U盘插到板子上后在minicom中有信息显示,但是无法找到挂载文件,/dev和/mnt下都没有找到相应的文件.后来百度后发现U ...
- Python 中的isinstance函数
解释: Python 中的isinstance函数,isinstance是Python中的一个内建函数 语法: isinstance(object, classinfo) 如果参数object是cla ...
- How to upgrade gcc using apt-get ?
在toolchain/test下已经有打包好的gcc,版本有4.x.5.0.6.0等,用这个PPA升级gcc就可以啦! 首先添加ppa到库: 1 sudo add-apt-repository ppa ...
- SPRING STS Virgo OSGI 开发一 : bundle 项目的创建
1. Spring STS 下载地址 (spring 最近改了站点 暂时不是太熟悉) http://spring.io/tools/sts/all 2. 下载 Virgo 插件 htt ...
- HDU 4869 Turn the pokers (2014 Multi-University Training Contest 1)
Turn the pokers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- 四种途径将HTML5 web应用变成android应用
作为下一代的网页语言,HTML5拥有很多让人期待已久的新特性.HTML5的优势之一在于能够实现跨平台游戏编码移植,现在已经有很多公司在移动 设备上使用HTML5技术.随着HTML5跨平台支持的不断增强 ...