版权声明:本文为博主原创文章,未经博主允许不得转载。                    https://blog.csdn.net/lhanchao/article/details/53367532             </div><link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css"><div class="htmledit_views" id="content_views">

libSVM是一个非常有名的SVM开源库,最近我在做分类任务,最后需要用到SVM进行分类,可是网上对于libSVM的介绍大多是matlab的,还有就是使用DOS命令调用的,直接使用libSVM的函数进行编程的介绍非常少,我来大体介绍一下我使用的情况吧。

我对于libSVM的了解也不是很清楚,只是单纯的利用他做训练和识别而已。

一、环境搭建

我使用的VS2013 + C++作为开发的,首先下载libSVM最新的版本http://www.csie.ntu.edu.tw/~cjlin/libsvm/,解压后如下图所示:
使用VS2013创建一个新的空工程,把上图目录中的svm.cpp和svm.h复制到工程目录下,并通过在工程中右键——Add——Exsiting Item把这两个文件添加到工程中去,如下图所示。
好了,到目前为止环境就搭建好了,简单明了~
注意:VS2013中使用fopen会出现一个错误,原因是VS2013自身兼容性不好,认为fopen不安全,可以通过 工程右键——Properties——C++——Preprocesser——Preprocesser Definitions中添加_CRT_SECURE_NO_WARNINGS解决该问题。
同时VS2013中编译会出现strdup函数编译不过去,同样根据提示,把该函数改为_strdup即可。

二、特征文件读取

我感觉网上对于libsvm有一种误导,就是你的特征文件必须要按照一定的格式来,才能够被读取训练,其实这只是对于使用dos命令行调用libsvm时的规定,因为libsvm自定义的特征文件格式是与其读取相匹配的。
如果我们使用自己的读取文件函数,则完全不用拘束于这种格式,只要我们在读取函数之中与我们自己的特征文件格式相匹配即可。
在libsvm中,与读取特征文件相关的类型为svm_problem。这个类中有三个元素,如下所示:
  1. struct svm_problem
  2. {
  3. int n; //记录样本总数
  4. double *y; //记录样本所属类别
  5. struct svm_node **x; //存储所有样本的特征,二维数组,一行存一个样本的所有特征
  6. };

其中svm_node类型的定义如下:

  1. struct svm_node //用来存储输入空间中的单个特征
  2. {
  3. int index; //该特征在特征空间中的维度编号
  4. double value; //该特征的值
  5. };

借用网上的一张图进行表示:

好了,知道在libsvm中特征是如何存储以后,就可以编写读取文件的函数了。

以我使用svm举例,我的特征文件如下图所示:

我使用SVM的类的头文件如下所示:
  1. #include "svm.h"
  2. #include <vector>
  3. #include <list>
  4. #include <iostream>
  5. #include <Windows.h>
  6. class ClassificationSVM
  7. {
  8. public:
  9. ClassificationSVM();
  10. ~ClassificationSVM();
  11. void train(const std::string& modelFileName);
  12. void predict(const std::string& featureaFileName, const std::string& modelFileName);
  13. private:
  14. void setParam();
  15. void readTrainData(const std::string& featureFileName);
  16. private:
  17. svm_parameter param;
  18. svm_problem prob;//all the data for train
  19. std::list<svm_node*> dataList;//list of features of all the samples
  20. std::list<double> typeList;//list of type of all the samples
  21. int sampleNum;
  22. //bool* judgeRight;
  23. };

其中 setParam函数设置如下所示:

  1. void ClassificationSVM::setParam()
  2. {
  3. param.svm_type = C_SVC;
  4. param.kernel_type = RBF;
  5. param.degree = 3;
  6. param.gamma = 0.5;
  7. param.coef0 = 0;
  8. param.nu = 0.5;
  9. param.cache_size = 40;
  10. param.C = 500;
  11. param.eps = 1e-3;
  12. param.p = 0.1;
  13. param.shrinking = 1;
  14. param.nr_weight = 0;
  15. param.weight = NULL;
  16. param.weight_label = NULL;
  17. }

我的读取文件的函数如下所示:

  1. void ClassificationSVM::readTrainData(const string& featureFileName)
  2. {
  3. FILE *fp = fopen(featureFileName.c_str(), "r");
  4. if (fp == NULL)
  5. {
  6. cout << "open feature file error!" << endl;
  7. return;
  8. }
  9. fseek(fp, 0L, SEEK_END);
  10. long end = ftell(fp);
  11. fseek(fp, 0L, SEEK_SET);
  12. long start = ftell(fp);
  13. //读取文件,直到文件末尾
  14. while (start != end)
  15. {
  16. //FEATUREDIM是自定义变量,表示特征的维度
  17. svm_node* features = new svm_node[FEATUREDIM + 1];//因为需要结束标记,因此申请空间时特征维度+1
  18. for (int k = 0; k < FEATUREDIM; k++)
  19. {
  20. double value = 0;
  21. fscanf(fp, "%lf", &value);
  22. features[k].index = k + 1;//特征标号,从1开始
  23. features[k].value = value;//特征值
  24. }
  25. features[FEATUREDIM].index = -1;//结束标记
  26. char c;
  27. fscanf(fp, "\n", &c);
  28. char name[100];
  29. fgets(name, 100, fp);
  30. name[strlen(name) - 1] = '\0';
  31. //negative sample type is 0
  32. int type = 0;
  33. //positive sample type is 1
  34. if (featureFileName == "PositiveFeatures.txt")
  35. type = 1;
  36. dataList.push_back(features);
  37. typeList.push_back(type);
  38. sampleNum++;
  39. start = ftell(fp);
  40. }
  41. fclose(fp);
  42. }

其中dataList和typeList分别存放特征值和该特征样本对应的标号(正或负)。

**修改**
dataList和typeList的声明如下:
std::list<svm_node*> dataList;//list of features of all the samples 
std::list<double>  typeList;//list of type of all the samples

三、svm训练和识别

训练时的代码如下图所示:

  1. void ClassificationSVM::train(const string& modelFileName)
  2. {
  3. cout << "reading positivie features..." << endl;
  4. readTrainData("PositiveFeatures.txt");
  5. cout << "reading negative features..." << endl;
  6. readTrainData("NegativeFeatures.txt");
  7. cout << sampleNum << endl;
  8. prob.l = sampleNum;//number of training samples
  9. prob.x = new svm_node *[prob.l];//features of all the training samples
  10. prob.y = new double[prob.l];//type of all the training samples
  11. int index = 0;
  12. while (!dataList.empty())
  13. {
  14. prob.x[index] = dataList.front();
  15. prob.y[index] = typeList.front();
  16. dataList.pop_front();
  17. typeList.pop_front();
  18. index++;
  19. }
  20. cout << "start training" << endl;
  21. svm_model *svmModel = svm_train(&prob, ¶m);
  22. cout << "save model" << endl;
  23. svm_save_model(modelFileName.c_str(), svmModel);
  24. cout << "done!" << endl;
  25. }

prob是svm_problem类型的对象,就是把之前读取的特征全部放入svm_problem的对象中。

svm_train和svm_save_model函数都是libsvm中自带的,在svm.h中定义。
分类时的代码如下所示:
  1. void ClassificationSVM::predict(const string& featureFileName, const string& modelFileName)
  2. {
  3. std::vector<bool> judgeRight;
  4. svm_model *svmModel = svm_load_model(modelFileName.c_str());
  5. FILE *fp;
  6. if ((fp = fopen(featureFileName.c_str(), "rt")) == NULL)
  7. return;
  8. fseek(fp, 0L, SEEK_END);
  9. long end = ftell(fp);
  10. fseek(fp, 0L, SEEK_SET);
  11. long start = ftell(fp);
  12. while (start != end)
  13. {
  14. svm_node* input = new svm_node[FEATUREDIM + 1];
  15. for (int k = 0; k<FEATUREDIM; k++)
  16. {
  17. double value = 0;
  18. fscanf(fp, "%lf", &value);
  19. input[k].index = k + 1;
  20. input[k].value = value;
  21. }
  22. char c;
  23. fscanf(fp, "\n", &c);
  24. char name[100];
  25. fgets(name, 100, fp);
  26. name[strlen(name) - 1] = '\0';
  27. input[FEATUREDIM].index = -1;
  28. int predictValue = svm_predict(svmModel, input);
  29. if (featureFileName == "positive_test.txt")
  30. {
  31. if (predictValue == 0)
  32. judgeRight.push_back(false);
  33. else
  34. judgeRight.push_back(true);
  35. }
  36. else if (featureFileName == "negative_test.txt")
  37. {
  38. if (predictValue == 1)
  39. judgeRight.push_back(false);
  40. else
  41. judgeRight.push_back(true);
  42. }
  43. start = ftell(fp);
  44. }
  45. fclose(fp);
  46. int correctNum = 0;
  47. int totalNum = judgeRight.size();
  48. for (int i = 0; i < totalNum; i++)
  49. {
  50. if (judgeRight[i] == true)
  51. correctNum++;
  52. }
  53. double precent = 1.0 * correctNum / totalNum;
  54. cout << precent << endl;
  55. }

分类时的代码与之前的代码非常类似,不多做赘述。

最后注意:标准的svm只支持二分类问题,对于多分类问题,需要进行其他的处理操作。

libSVM + VS2013 + C++使用介绍相关推荐

  1. MATLAB libsvm 安装和使用

    最近在学习SVM,在matlab上安装和使用Libsvm的过程中遇到了好多问题,在网上查看了许多资料,踩了许多坑. 整理一下供大家分享,希望能节省大家在安装过程中的时间. 一.安装 1.libsvm  ...

  2. LIBSVM在Matlab下的使用和LIBSVM的matlab软件下README全文翻译

    1.简介 我们每次用matlab编写SVM模型做预测和分类时,就会需要用到这个工具包,当然现在新版本有matlab自带的工具APP,可以完成支持向量机(SVM),不需要写代码,因此就不需要安装工具包. ...

  3. libsvm的安装和使用【转载】

    最近在学习SVM,在matlab上安装和使用Libsvm的过程中遇到了好多问题,在网上查看了许多资料,踩了许多坑. 整理一下供大家分享,希望能节省大家在安装过程中的时间. 一.安装 1.libsvm  ...

  4. LIBSVM使用说明、简介及感悟

    使用LIBSVM需要用到的其他工具:Python(相信搞SVM的或多或少都知道Python吧,安装时注意一点就是记得要添加环境变量!).以下内容是指windows平台的. 配套论文:LIBSVM: A ...

  5. SVM讲的成体系的,自圆其说较好的一篇,上午没读完,KKT第二部分不等式有疑问没弄懂,复制后继续读完

    https://www.jiqizhixin.com/articles/2018-10-17-20 贪心科技原创 2018/10/17 16:26 我i智能来源 学习SVM,这篇文章就够了!(附详细代 ...

  6. 一文读懂支持向量机SVM(附实现代码、公式)

    来源:机器学习算法与Python学习 本文约11000字,建议阅读10+分钟. 本文以简单实例化形式记录学习SVM的过程,力图帮助新手级学习者少走弯路. 支持向量机(SVM),一个神秘而众知的名字,在 ...

  7. 2014年7月份第2周51Aspx源码发布详情

      体育馆综合会员管理系统源码  2014-7-11 [VS2010]功能介绍:本系统适用于羽毛球馆,台球馆,乒乓球馆,棋牌室,篮球馆等综合体育馆,可同时使用.本系统功能非常强大,包含体育馆内餐厅,超 ...

  8. 2014年6月份第4周51Aspx源码发布详情

    通用医院会员管理系统源码  2014-6-23 [VS2010]功能介绍:本系统共包括以下模块:会员开卡管理.会员充值管理.会员消费管理.会员病例管理.客户预约管理.系统信息管理(门诊管理.卡类型管理 ...

  9. 关于福昕软件公司的控件使用-Foxit PDF SDK ActiveX

    这是一款由福昕软件公司开发的控件,控件名字FoxitPDFSDKActiveX520_Std_x64.ocx. 我的开发环境: WIN7  64BIT    VS2013 官网介绍: https:// ...

最新文章

  1. Asterisk安装
  2. Java基础知识——异常Throwable和Exception
  3. 在网页中给Flash加上超级链接
  4. 通才和专家:如何选择
  5. Python标准库之csv(1)
  6. 有关于mysql自增型需要返回id_关于mysql自增id,你需要知道的
  7. 判断上三角矩阵_线性代数15——矩阵空间\对角矩阵\和秩1矩阵
  8. tmemo 选择消除行_无线耳机新选择
  9. python2.7.12源码编译
  10. jQuery、Ajax,DataTable数据如何转换成Json格式
  11. Js获取移动设备分辨率
  12. 陈希孺《概率论与数理统计》读书笔记
  13. NiFi 学习 —自己实现处理器
  14. 鸟哥的linux私房菜 第五章
  15. 无人机三维建模(1) 调研
  16. 这应该是史上最强的物理学科普(雄文)
  17. 安庆集团-冲刺日志(第六天)
  18. linux nginx配置81端口用于访问web81
  19. mac系统升级后git使用不了
  20. UINO优诺:数字孪生可视化管理GIV,打造统览全局大视野

热门文章

  1. c++类的嵌套(1)
  2. sv_labs学习笔记——sv_lab5_上(System Verilog)
  3. 如何将win10的资源管理器指向“这台电脑”?
  4. 三维点云学习(3)7- 实现GMM
  5. 【前端 · 面试 】HTTP 总结(七)—— HTTP 缓存概述
  6. javascript继承的原理
  7. 共同努力做好NBear!
  8. 2021-08-31 转载 Scala Akka 系列文章
  9. JavaWeb——拦截器HandlerInterceptor
  10. addEventListener事件监听传递参数