LibSVM笔记系列(3)——初学移植libsvm的C/C++版本
在LibSVM笔记系列(1)中已经提到在g++环境中编译LibSVM只需要一个make命令那样简单。
本文将介绍
(1)LibSVM的编译文件结构
(2)svm.h中重要数据结构及函数分析
(3)svm_train.c 和 svm_predict.c源代码分析
(4)如何将LibSVM移植到eclipse IDE环境中
1. LibSVM编译文件结构
要了解一个工程是如何编译链接的,最好的办法是参考Makefile。
CXX ?= g++
CFLAGS = -Wall -Wconversion -O3 -fPIC
SHVER = 2
OS = $(shell uname)
all: svm-train svm-predict svm-scale
lib: svm.o
if [ "$(OS)" = "Darwin" ]; then \
SHARED_LIB_FLAG="-dynamiclib -Wl,-install_name,libsvm.so.$(SHVER)"; \
else \
SHARED_LIB_FLAG="-shared -Wl,-soname,libsvm.so.$(SHVER)"; \
fi; \
$(CXX) $${SHARED_LIB_FLAG} svm.o -o libsvm.so.$(SHVER)
svm-predict: svm-predict.c svm.o
$(CXX) $(CFLAGS) svm-predict.c svm.o -o svm-predict -lm
svm-train: svm-train.c svm.o
$(CXX) $(CFLAGS) svm-train.c svm.o -o svm-train -lm
svm-scale: svm-scale.c
$(CXX) $(CFLAGS) svm-scale.c -o svm-scale
svm.o: svm.cpp svm.h
$(CXX) $(CFLAGS) -c svm.cpp
clean:
rm -f *~ svm.o svm-train svm-predict svm-scale libsvm.so.$(SHVER)
tags:
ctags --c++-kinds=+p --fields=+iaS --extra=+q -R
下图描述了生成svm-predict和svm-train目标的过程,支持向量机的所有相关的核心代码在svm.cpp中实现,svm_train.c和svm_predict.c中只是提供了训练和预测的主函数接口而已。我们将svm修改移植时只需要仿照svm_train.c或svm_predict.c进行修改就可以了。
2. svm.h中重要数据结构及函数分析(参考README)
大部分函数在头文件“svm.h”,因此在自己的C/C++文件中必须#include "svm.h",而且
要将svm.cpp一同编译到自己的程序当中。可以参考svm-train.c和svm-predict.c。在
svm.h中定义了LIBSVM_VERSION以及声明了'extern int libsvm_version'。
在对测试数据分类前,需要使用训练数据构建一个'svm_model',这个模型可以存到文件
中或立即被使用。
- Function: struct svm_model *svm_train(const struct svm_problem *prob,
const struct svm_parameter *param);
This function constructs and returns an SVM model according to
the given training data and parameters.
struct svm_problem
{
int l; // 训练数据的数量
double *y; // 包含标签值的数组
struct svm_node **x; // 指针数组,每一个指针指向一个训练的特征向量
};
比如,数据如下:
LABELATTR1ATTR2ATTR3ATTR4ATTR5
------------------------------
1 0 0.1 0.2 0 0
2 0 0.1 0.3 -1.2 0
1 0.4 0 0 0 0
2 0 0.1 0 1.4 0.5
3-0.1 -0.2 0.1 1.1 0.1
则svm_problem结构体成员的值如下:
l = 5
y -> 1 2 1 2 3
x -> [ ] -> (2,0.1) (3,0.2) (-1,?)
[ ] -> (2,0.1) (3,0.3) (4,-1.2) (-1,?)
[ ] -> (1,0.4) (-1,?)
[ ] -> (2,0.1) (4,1.4) (5,0.5) (-1,?)
[ ] -> (1,-0.1) (2,-0.2) (3,0.1) (4,1.1) (5,0.1) (-1,?)
注意x,其中的(index,value)存储在'svm_node'结构体中:
struct svm_node
{
int index; // 特征向量中非0元素的索引
double value; // 索引值位置对应的特征值
};
index = -1 表示向量的结束。注意,index的值是递增的。
struct svm_parameter 描述了SVM model的参数:
struct svm_parameter
{
int svm_type;
int kernel_type;
int degree; /* for poly */
double gamma; /* for poly/rbf/sigmoid */
double coef0; /* for poly/sigmoid */
/* these are for training only */
double cache_size; /* in MB */
double eps; /* stopping criteria */
double C; /* for C_SVC, EPSILON_SVR, and NU_SVR */
int nr_weight;/* for C_SVC */
int *weight_label;/* for C_SVC */
double* weight;/* for C_SVC */
double nu; /* for NU_SVC, ONE_CLASS, and NU_SVR */
double p; /* for EPSILON_SVR */
int shrinking;/* use the shrinking heuristics */
int probability; /* do probability estimates */
};
svm_type 可以为C_SVC, NU_SVC, ONE_CLASS, EPSILON, NU_SVR.
C_SVC:C-SVM classification
NU_SVC:nu-SVM classification
ONE_CLASS:one-class-SVM
EPSILON_SVR:epsilon-SVM regression
NU_SVR:nu-SVM regression
kernel_type可以为LINEAR, POLY, RBF, SIGMOID.
LINEAR:u'*v
POLY:(gamma*u'*v + coef0)^degree
RBF:exp(-gamma*|u-v|^2)
SIGMOID:tanh(gamma*u'*v + coef0)
PRECOMPUTED: kernel values in training_set_file
注意:在还要使用svm_train返回的svm_model的情况下,不能将svm_problem的内存空间释放,
因为svm_model中含有指向svm_problem结构的指针。
注意:为了避免传入错误的参数,应该在使用svm_train之前使用svm_check_parameter()检验。
svm_model存储了训练过程获得的模型,不建议直接访问该结构体中的实体,而应该使用接口
函数获得结构体中成员的值。
struct svm_model
{
struct svm_parameter param;/* parameter */
int nr_class; /* number of classes, = 2 in regression/one class svm */
int l; /* total #SV */
struct svm_node **SV; /* SVs (SV[l]) */
double **sv_coef;/* coefficients for SVs in decision functions (sv_coef[k-1][l]) */
double *rho; /* constants in decision functions (rho[k*(k-1)/2]) */
double *probA;/* pairwise probability information */
double *probB;
int *sv_indices; /* sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to indicate SVs in the training set */
/* for classification only */
int *label; /* label of each class (label[k]) */
int *nSV; /* number of SVs for each class (nSV[k]) */
/* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
/* XXX */
int free_sv; /* 1 if svm_model is created by svm_load_model*/
/* 0 if svm_model is created by svm_train */
};
SV和sv_coef是支持向量和对应的系数。假设有k类,对于第j类中的数据,对应的sv_coef包括
支持向量的系数是一个 (k-1)y*alpha 的向量,比如有4类,则sv_coef和SV如下:
+-+-+-+--------------------+
|1|1|1| |
|v|v|v| SVs from class 1 |
|2|3|4| |
+-+-+-+--------------------+
|1|2|2| |
|v|v|v| SVs from class 2 |
|2|3|4| |
+-+-+-+--------------------+
|1|2|3| |
|v|v|v| SVs from class 3 |
|3|3|4| |
+-+-+-+--------------------+
|1|2|3| |
|v|v|v| SVs from class 4 |
|4|4|4| |
+-+-+-+--------------------+
参考svm_train(),其中给sv_coef赋了值。
rho是平衡项(-b)。probA和probB是用于概率输出的参数。如果有k类,则有k*(k-1)/2
个二元分类问题,按照如下的方式对齐:
1 vs 2, 1 vs 3, ..., 1 vs k, 2 vs 3, ..., 2 vs k, ..., k-1 vs k.
sv_indices[0,...,nSV-1]值在[1,...,num_training_data]范围内,标识训练数据集中的支持向量。
label 包含了训练数据集中的标签。
nSV包含了训练数据集中每类的支持向量数。
free_sv是一个标志,决定是否在free_model_content(struct svm_model*)中
和free_and_destroy_model(struct svm_model**)中将SV的空间释放。如果SV是由svm_train()得到
的,则设置为0,不能释放,如果是通过svm_load_model加载的,则设置为1。
- Function: double svm_predict(const struct svm_model *model,
const struct svm_node *x);
For a classification model, the predicted class for x is returned.
For a regression model, the function value of x calculated using
the model is returned. For an one-class model, +1 or -1 is
returned.
3. svm_train.c的源代码分析
注意,虽然看到的是.c的文件,但里面实际使用了不少C++特有的东西,因此,在后面eclipse移植过程中最好“新建C++”工程。
svm_predict.c的代码分析类似,svm_predict的过程比svm_train更简单。
4. 将LibSVM移植到eclipse IDE的过程
前提要求:配置好的eclipse C/C++环境,或者使用VC环境也一样
移植文件:svm.cpp svm.h svm-train.c
拷贝数据文件:heart_scale
(1)新建C++工程
(2)将“移植文件”拷贝到工程目录并添加到工程
(3)添加命令行参数,eclipse中,在“Run Configurations”的Arguments选项卡中添加heart_scale heart_scale.model。
(4)编译运行结果,与make结果相同
*
optimization finished, #iter = 162
nu = 0.431029
obj = -100.877288, rho = 0.424462
nSV = 132, nBSV = 107
Total nSV = 132
LibSVM笔记系列(3)——初学移植libsvm的C/C++版本的更多相关文章
- 《Mastering Opencv ...读书笔记系列》车牌识别(II)
http://blog.csdn.net/jinshengtao/article/details/17954427 <Mastering Opencv ...读书笔记系列>车牌识别(I ...
- 【论文笔记系列】AutoML:A Survey of State-of-the-art (下)
[论文笔记系列]AutoML:A Survey of State-of-the-art (上) 上一篇文章介绍了Data preparation,Feature Engineering,Model S ...
- Hadoop学习笔记系列文章导航
一.为何要学习Hadoop? 这是一个信息爆炸的时代.经过数十年的积累,很多企业都聚集了大量的数据.这些数据也是企业的核心财富之一,怎样从累积的数据里寻找价值,变废为宝炼数成金成为当务之急.但数据增长 ...
- MongoDB学习笔记系列
回到占占推荐博客索引 该来的总会来的,Ef,Redis,MVC甚至Sqlserver都有了自己的系列,MongoDB没有理由不去整理一下,这个系列都是平时在项目开发时总结出来的,希望可以为各位一些帮助 ...
- C#温故知新:《C#图解教程》读书笔记系列
一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...
- C#刨根究底:《你必须知道的.NET》读书笔记系列
一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...
- Dynamic CRM 2013学习笔记 系列汇总
这里列出所有 Dynamic CRM 2013学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址: Dynamic CRM 2013学习笔记 系列汇总 ...
- SQLServer学习笔记系列3
一.写在前面的话 今天又是双休啦!生活依然再继续,当你停下来的时候,或许会突然显得不自在.有时候,看到一种东西,你会发现原来在这个社会上,优秀的人很多,默默 吃苦努力奋斗的人也多!星期五早上按时上班, ...
- SQLServer学习笔记系列2
一.写在前面的话 继上一次SQLServer学习笔记系列1http://www.cnblogs.com/liupeng61624/p/4354983.html以后,继续学习Sqlserver,一步一步 ...
随机推荐
- .net 微信APP支付接口的开发流程以及坑
流程 申请APP的微信支付 申请成功之后得到APPID 商户号 以及自己设置商户号的支付密码 这时就可以开发接口了 微信APP支付API:https://pay.weixin.qq.com/wiki/ ...
- iOS 技能集结号
1. 获取磁盘总空间大小 2. 获取磁盘可用空间大小 3. 获取指定路径下某个文件的大小 4. 获取文件夹下所有文件的大小 5. 获取字符串(或汉字)首字母 6. 将字符串数组按照元素首字母顺序进行排 ...
- visual studio 2013 使用IIS Express附加调试MVC5
1.如何找到调试的站点的进程[由于图片无法上传,就不上传图片了] 2.vs运行的时候,在状态栏会存在一个IIS Express 进程,点击显示所有的应用程序,找到想要调试的程序的PID; 3.附加调试 ...
- Android应用开发提高篇(1)-----获取本地IP
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/21/2361802.html 一.概述 习惯了Linux下的网络编程,在还没用智能机之前就一直想 ...
- JZOI
orz..kpm大神做的JZOI卡.很好看 目前是全球限量十张哈哈哈 (正面) (背面) 原图:
- WCF服务
一.新建windows服务 二.新建wcf服务 三.添加安装程序 四.设置安装程序 五.设置启动代码 6 7 8. 注:当使用管理员身份 安装不成功时,可以使用vs自带的命令工具 ...
- pure学习笔记
最近研究Pure,发现这个对于写css来说确实是个好的框架,特此总结了一番,如有错误或不足的地方,欢迎交流指点,轻拍. 此文运用的是优雅的Markdown而书 Pure学习笔记 #写在最前 1# Pu ...
- iphone抓取移动网络报文的方法
iphone抓取移动网络报文的方法 对iPhone进行越狱,网上有很多教程,这里不做说明.越狱后会有cydia这个app,首先对用户身份进行设置,选用开发者身份.打开这个应用,搜索openssh,找到 ...
- Best practice for Invoke other scripts or exe in PowerShell
Recently, I find I used many different type method to invoke other scripts or exe in PowerShell. May ...
- xfire发布的Webservice中Spring注入为空的解决方案
Spring框架使用中注入为空是一个比较头疼的问题,遇到Webservice和Spring框架配合时,这个问题更容易出现并很难发现问题的原因. 在做SSO系统中就遇到这样的问题,在Service的实现 ...