zoukankan      html  css  js  c++  java
  • 如何在Visual Studio(VS)2012里使用libsvm工具箱

    原文:http://blog.csdn.net/u014691453/article/details/40393137

    软件版本:

    Visual Studio版本:VS2012 

    (注:使用方法在 VS2010 上面亲测同样可用,只是可能会出现的问题是: VS2010 和 VS2012 之间有些函数写法不同,需在编译前做改动,譬如 VS2010 的 scanf 对比 VS2012 的 scanf_s )

    libsvm版本:libsvm-3.18

    声明:

    如果你找到了我这篇标题的文章,那很大程度上意味着你一定是在 VS 里或者 MFC 里使用 libsvm 工具箱出现了问题。那你也一定知道了,libsvm 在VS工程里的使用与它在 matlab 或者是 python 里面的使用,是多么的不同。

    致谢:

    如果没有 gg 百分之百的帮助,就凭我在 VS 里编程的菜鸟能力,是绝对不可能1天就搞好的,我绝对会弄半年不止委屈所以非常感谢非常感谢,今后我一定认真学习编程。

    正文:

    分三部分:第一部分:先把 VS 工程的框架建好

                      第二部分:工程里包含主函数的 cpp 文件要怎么写

                      第三部分:把 libsvm 工具箱移植到 MFC 中进行使用

                      第四部分:在本文代码中能够正确运行的数据格式

    资源地址:如何在Visual Studio(VS)里使用libsvm工具箱(与博文相关的代码包)

    第一部分:先把 VS 工程的框架建好

    之前一直都是在 matlab 里面使用这个 libsvm 工具箱,也曾经有一段时间在 python 里面使用过,刚接触的时候还在 cmd 控制台上面使用过,libsvm 的编写者真的很赞,打开此工具箱我们看到的情景是这样的:
     

    对于java、matlab、python、windows 都有相对应的文件夹,文件夹里面的内容和上图中的这个 readme 就可以帮助你在以上四种情况下使用了。

    那在 VS 里该怎么使用呢?

    首先,我们先建立一个Win32控制台项目,起名为 MM ,如下步骤:

    然后,把 libsvm 文件夹里的这几个文件(如下图),都拷贝到 MM 项目的文件夹(如下下图)里去,以备后续使用。

    然后,在 MM 项目里,我们把 svm.h 和 svm.cpp 分别添加到头文件和源文件里面去,如下图:

    然后,在源文件里,右键——新建项:MM.cpp

    接下来是第二部分

     第二部分:工程里包含主函数的 cpp 文件要怎么写

    MM.cpp也就是上面说的包含主函数的 cpp 文件,我们最终要执行的就是它。
    首先,我们先给 MM.cpp 里写好需要用到的头文件,如下:
    [cpp] view plaincopy
     
    1. #include <stdio.h>  
    2. #include <string.h>  
    3. #include <ctype.h>  
    4. #include <list>  
    5. #include <fstream>  
    6. #include <iostream>  
    7. #include "svm.h"  
    8. using namespace std;  

    接下来的内容大致分五部分:
    第一:读入训练数据和测试数据
    第二:构建参数 param 的结构体(主要目的就是让VS知道你要用的参数都是什么)
    第三:构建分类问题 prob 的结构体(主要就是把第一步读入的数据传递给 svm_train 和 svm_predict)
    第四:主函数如下
    第五:结果展示
     

    第一:读入训练数据和测试数据

    首先,在读数据之前,先定义一些变量(整个程序还是主要参考的 libsvm/svm_toy/qt/svm_toy.cpp 这个代码,由于目前我编程能力实在是差,所以一些冗余的代码我都没有删改,仅仅只实现了能够使用libsvm的目的。)
    [cpp] view plaincopy
     
    1. #define XLEN 10  //生产测试数据,这个感觉就是无用的地方  
    2. #define YLEN 10  
    3.   
    4.   
    5. ofstream outdata;  //需要准备的所有数据的标签label和特征feature都是分开的,而且特征feature前面不需要加序号冒号这种东西,只需用空格隔开就好  
    6. ifstream indata;   //所以这里indata只包含特征,indata_label只包含label,每一行是一个样本的。  
    7. ofstream outdata_lable;  
    8. ifstream indata_lable;  
    9.   
    10. int NUM = 1440;   //由于我的样本特征是 1440 维,所以读数据的时候,我定义了个数,你可以根据自己特征的维度对 NUM 进行更改。  
    11.   
    12. //char default_param[] = "-t 2 -c 100";  // 这个是 svm_toy.cpp 里对参数的选择  
    13. char default_param[] = "-t 2 -c 4 -g 32";  // 这个是匹配我数据的参数  
    14. struct point {                           //这个是后面 svm_train 拿来数据做训练时候的数据传入方式  
    15.     double *feature;  
    16.     //signed char value;  
    17.     int value;  
    18. };  
    19.   
    20. list<point> point_list;        // 通过 indata 读进来的数据就放在 point_list 里面  
    21. int current_value = 1;          // 路人甲变量  
    22.   
    23. void clear_all()         // 清空链表  
    24. {  
    25.     point_list.clear();  
    26. }  

    然后,我们先读入训练数据,用来训练模型
    [cpp] view plaincopy
     
    1. void readFile1(char *file,char *file_lable)  //定义读入训练数据的函数叫做 readFile1  
    2. {  
    3.   
    4.     indata.open(file,ios::in);               //读入特征  
    5.     indata_lable.open(file_lable,ios::in);    // 读入标签  
    6.     cout <<"read data begin"<<endl;          // 屏显  
    7.       
    8.     clear_all();  
    9.     while(!indata.eof())              // 如果没有读到文件结束,就继续读,知道读完整个 traindata 文件  
    10.     {  
    11.           
    12.         double *line = new double[NUM];  
    13.         for(int i =0;i<NUM;i++)  
    14.         {  
    15.             indata >> line[i];       //把特征存起来  
    16.         }  
    17.         point p;  
    18.         indata_lable >>p.value;          //把label存起来  
    19.   
    20.         p.feature = line;  
    21.         point_list.push_back(p);  
    22.     }  
    23.       
    24.     point_list.pop_back();        //如果你的 traindata.txt 文件数据的最后有一个空格的话,需要加上这句话,否则预测会有错如果没有空格,这句话就不需要了  
    25.     indata.close();  
    26.     indata_lable.close();  
    27.     cout <<"read data end"<<endl;  
    28. }  
     

    接下来,读入测试数据:
    [cpp] view plaincopy
     
    1. void readFile2(char *file,char *file_lable)  // 读入测试文件的函数叫做 readFile2  
    2. {  
    3.   
    4.     indata.open(file,ios::in);      //接下来代码和上面读训练数据是一个样子的  
    5.     indata_lable.open(file_lable,ios::in); // <span style="font-family: Arial, Helvetica, sans-serif;">由于读训练数据之后就会建立model,然后才会读测试数据,所以不用担心会有数据覆盖的问题</span>  
    6.     cout <<"read test data begin"<<endl;  
    7.     clear_all();  
    8.     while(!indata.eof())  
    9.     {  
    10.           
    11.         double *line = new double[NUM];  
    12.         for(int i =0;i<NUM;i++)  
    13.         {  
    14.             indata >> line[i];  
    15.         }  
    16.         point p;  
    17.         indata_lable >>p.value;  
    18.   
    19.         p.feature = line;  
    20.         point_list.push_back(p);  
    21.     }  
    22.     point_list.pop_back();  
    23.     cout <<"read test data end size = "<<point_list.size()<<endl;  
    24.     indata.close();  
    25.     indata_lable.close();  
    26. }  
     

    第二:构建参数 param 的结构体


    然后,训练模型!:包括了构建参数param结构和构建 prob结构。
    由于太长了,我上传到 CSDN 下载页面吧,免积分下载。这段代码主要就是参考的 svm_toy.cpp 文件,同学们好好研读。
     

    第三:构建分类问题 prob 的结构体

     
    同第二,代码是一起的,我会把整体代码,包括以上写的读入feature和label的代码,发到下载页面
     

    第四:主函数如下

    [cpp] view plaincopy
     
    1. int main()  
    2. {  
    3.     int choice;  
    4.     cout<<"1 train model 2 test1 3 test2 "<<endl;   
    5.     cin >>choice;  
    6.     switch(choice)  
    7.     {  
    8.     case 1:  
    9.         {  
    10.             readFile1("traindata.txt","trainlabel.txt"); //选择1 是训练模型,模型会保存为“model.txt”  
    11.             run();  
    12.             break;  
    13.         }  
    14.     case 2:  
    15.         {  
    16.             readFile2("1.txt","1_label.txt");   // 选择2 是用第一份测试数据进行测试  
    17.             testData();  
    18.             break;  
    19.         }  
    20.     case 3:  
    21.         {  
    22.             readFile2("11.txt","11_label.txt");  // 选择3 是用第二份测试数据进行测试  
    23.             testData();  
    24.             break;  
    25.         }  
    26.   
    27.     }  
    28.     system("pause");  
    29.     return 0;  
    30. }  
     

    第五:结果展示

    等啊等~ 训练结束啦~
    接下来就是测试了:
     

    第三部分:把 libsvm 工具箱移植到 MFC 中进行使用

     
    其实在 MFC 中的使用,和libsvm在普通VS 项目中的使用是一样的。
    如果你不想在MFC 里训练 model,那么完全可以把在第二部分中训练出来的 model 拷贝到 MFC 的这个项目里面,然后在 测试数据之前,把 model load进去就好了,具体load方式参照我的代码里test()函数里写的内容。
    那么在 MFC 的代码里,你就可以把第二部分代码中的 void run() ,即训练模型部分去掉了
     
    注:我就是在 MFC 里使用 libsvm 的时候,发现了 VS2010 和 VS2012 的不同,svm.cpp 和 svm.h 这两个文件里的一些函数,可以在 VS2010 的 MFC 工程里跑的很好,可是到了 VS2012 里就会提示说 “你把 XX 换成 XX_s 会更安全”,是错误而不是警告,所以如果在 VS2012 里面用libsvm的话,需要在svm.cpp 和 svm.h 这两个文件里修改部分函数的表达形式,这个在网上都有解答,可以自行查询。
     

    第四部分:在本文代码中能够正确运行的数据格式

    在第二部分给出的资源链接里,我上传的资料里包括我的测试数据,1.txt和1_label.txt 就是test1测试的内容,11.txt 和 11_label.txt 就是test2 测试的内容,如果你要测试你自己的数据,记得在test()代码里更改成你自己数据的名称。
     
    可以使用的数据格式: 大家可以参照我上传的 1.txt,大致如以下:
     
    0.564 0.436 0.675 0.453 0.000 0.345 
    0.354 0.345 0.456 0.000 0.346 0.645 
    0.678 0.678 0.866 0.757 0.575 0.867 
    0.866 0.865 0.856 0.867 0.557 0.754 
     
    我的1_label.txt,大致如以下:
     
    1
    1
    2
    2
     
    如以上格式,因为我的数据是之前通过 matlab 处理过的,所以空格位置用的是 ‘ ’ 。
     
    如果你的数据格式和我不一样,只有两条路: 1:改成我这样的数据格式  2:更改代码里读数据这部分的程序,保证读进去的数据是对的就好 
    或者还有一条路,就是自己按照你的需要重新写代码。
     
    利用了宝贵的一个下午来整理这些东西,希望能够真的帮到像之前的我一样有需要的人。
     
    感觉该说的应该都说完了,如果有解释不正确或者漏掉的地方,也请大家告知我,我会再修改
  • 相关阅读:
    洛谷 P1200.[USACO1.1]你的飞碟在这儿Your Ride Is Here
    洛谷 P1055.ISBN号码
    洛谷 P1567.统计天数
    洛谷 P2141.珠心算测验
    洛谷 P1428.小鱼比可爱
    洛谷 P1427.小鱼的数字游戏
    洛谷 P1047.校门外的树
    洛谷 P1046.陶陶摘苹果
    洛谷 P1980.计数问题
    洛谷 P1424.小鱼的航程(改进版)
  • 原文地址:https://www.cnblogs.com/zhizhan/p/4342799.html
Copyright © 2011-2022 走看看