天天看点

LIBSVM入门笔记(matlab2013a+VS2013)一、下载libsvm二、编译libsvm三、测试libsvm

一、下载libsvm

LIBSVM是台湾大学林智仁(Lin Chih-Jen)教授等开发设计的一个简单、易于使用和快速有效的SVM模式识别与回归的软件包,在http://www.csie.ntu.edu.tw/~cjlin/libsvm/可以下载,目前版本是libsvm-3.20,推荐把下载的libsvm-3.20.zip解压之后的libsvm-3.20文件夹放置在D:\MATLAB\R2013a\toolbox中(为方便区分我直接把libsvm-3.20文件夹放到D:\MATLAB下面),然后将其添加到matlab的搜索路径中:matlab里Set Path然后Add with Subfolders,选择libsvm-3.20文件夹,Save,Close。

二、编译libsvm

虽然libsvm-3.20\matlab中的README说libsvm-3.20\windows里有编译好的文件可以直接用,但是由于各人的matlab、VS版本不一样,有些文件在新版本中没有了,或者放在另一个文件夹下了,会导致有些文件找不到,总之,最好是自己编译一下吧。编译的目的呢,就是把libsvm-3.20\matlab中的svmtrain.c这样的C++源文件编译成svmtrain.mexw64这样的matlab文件,才能在matlab的命令行里直接调用。

编译步骤:

1、把matlab切换到libsvm-3.20\matlab目录下,以我的为例,在matlab命令行输入以下命令

CD D:\MATLAB\libsvm-3.20\matlab
           
2、如果你的编译器配置好了,直接输入以下命令
make
           
如果不能编译,那么你需要配置一下编译器,在matlab命令行输入以下命令
mex -setup
           

他会问你是否使用matlab自带的Lcc-win32C编译器,Would you like mex to locate installed compilers [y]/n?

由于libsvm原始版本是C++实现的,我们选择n使用C++编译器来编译这些源文件

然后会列出许多编译器:

Would you like mex to locate installed compilers [y]/n? n
 
Select a compiler: 
[1] Intel C++ 13.0 (with Microsoft Software Development Kit (SDK) linker) 
[2] Intel C++ 13.0 (with Microsoft Visual C++ 2010 linker) 
[3] Intel C++ 13.0 (with Microsoft Visual C++ 2012 linker) 
[4] Intel C++ 12.0 (with Microsoft Software Development Kit (SDK) linker) 
[5] Intel C++ 12.0 (with Microsoft Visual C++ 2008 SP1 linker) 
[6] Intel C++ 12.0 (with Microsoft Visual C++ 2010 linker) 
[7] Intel C++ 11.1 (with Microsoft Visual C++ 2008 SP1 linker) 
[8] Intel Visual Fortran 13 (with Microsoft Software Development Kit (SDK) linker) 
[9] Intel Visual Fortran 13.0 (with Microsoft Visual C++ 2010 linker) 
[10] Intel Visual Fortran 13.0 (with Microsoft Visual C++ 2012 linker) 
[11] Intel Visual Fortran 12 (with Microsoft Software Development Kit (SDK) linker) 
[12] Intel Visual Fortran 12.0 (with Microsoft Visual C++ 2008 SP1 linker) 
[13] Intel Visual Fortran 12.0 (with Microsoft Visual C++ 2008 Shell linker) 
[14] Intel Visual Fortran 12.0 (with Microsoft Visual C++ 2010 linker) 
[15] Intel Visual Fortran 11.1 (with Microsoft Visual C++ 2008 SP1 linker) 
[16] Intel Visual Fortran 11.1 (with Microsoft Visual C++ 2008 Shell linker) 
[17] Microsoft Software Development Kit (SDK) 7.1 
[18] Microsoft Visual C++ 2005 SP1 
[19] Microsoft Visual C++ 2008 SP1 
[20] Microsoft Visual C++ 2010 
[21] Microsoft Visual C++ 2012 
 
[0] None 
 
Compiler:
           

我装的是VS2013列表里没有显示,我先选择21

接下来让你确认编译器位置:

Warning: The default location for Microsoft Visual C++ 2012 compiler is: 
         "C:\Program Files (x86)\Microsoft Visual Studio 11.0" 
         but either that directory does not exist or the configuration 
         is invalid. 
 
Use C:\Program Files (x86)\Microsoft Visual Studio 11.0 anyway [y]/n? 
           
由于matlab还不支持VS2013,我的编译器应该是Microsoft Visual Studio 12.0,而且我的VS2013不是默认安装到C盘的(我装在了D:\Microsoft Visual Studio 12.0),所以接下来我要手动输入编译器路径,我先选择n
Use C:\Program Files (x86)\Microsoft Visual Studio 11.0 anyway [y]/n? n
Please enter the location of your compiler: [C:\Program Files (x86)\Microsoft Visual Studio 11.0]
           
在这行后面输入VS安装时候的路径,我的是D:\Microsoft Visual Studio 12.0故输入如下
Use C:\Program Files (x86)\Microsoft Visual Studio 11.0 anyway [y]/n? n
Please enter the location of your compiler: [C:\Program Files (x86)\Microsoft Visual Studio 11.0] D:\Microsoft Visual Studio 12.0
           
然后再次让你确认路径
Please verify your choices: 
 
Compiler: Microsoft Visual C++ 2012  
Location: D:\Microsoft Visual Studio 12.0 
 
Are these correct [y]/n?
           
选择y
Are these correct [y]/n? y
 
*************************************************************************** 
  Warning: MEX-files generated using Microsoft Visual C++ 2012 require 
           that Microsoft Visual Studio 2012 run-time libraries be  
           available on the computer they are run on. 
           If you plan to redistribute your MEX-files to other MATLAB 
           users, be sure that they have the run-time libraries. 
*************************************************************************** 
 
 
Trying to update options file: C:\Users\张京林\AppData\Roaming\MathWorks\MATLAB\R2013a\mexopts.bat 
From template:              D:\MATLAB\R2013a\bin\win64\mexopts\msvc110opts.bat 
 
Done . . . 
 
************************************************************************** 
  Warning: The MATLAB C and Fortran API has changed to support MATLAB 
           variables with more than 2^32-1 elements.  In the near future 
           you will be required to update your code to utilize the new 
           API. You can find more information about this at: 
           http://www.mathworks.com/help/matlab/matlab_external/upgrading-mex-files-to-use-64-bit-api.html  
           Building with the -largeArrayDims option enables the new API. 
************************************************************************** 
 
>>
           

这样就设置好了编译器

由于前面说过的matlab2013a还不支持VS2013,在WIN8、VS2013下某些lib(比如gdi32.lib)不需要了,因此文件夹中没有这些文件,但是matlab还是会根据老版本VS的路径去找这些文件,所以会报错,说找不到某些lib文件,比如:

LINK : fatal error LNK1181: cannot open input file 'gdi32.lib'
           

网上找到的解决办法是mexopts.bat文件:

在C:\Users\张京林\AppData\Roaming\MathWorks\MATLAB\R2013a路径下找到mexopts.bat文件,右键编辑,找到如下行

set LINKFLAGS=/dll /export:%ENTRYPOINT% /LIBPATH:"%LIBLOC%" libmx.lib libmex.lib libmat.lib /MACHINE:X64 kernel32.lib user32.lib gdi32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /manifest /incremental:NO /implib:"%LIB_NAME%.x" /MAP:"%OUTDIR%%MEX_NAME%%MEX_EXT%.map"
           
把kernel32.lib user32.lib后面的gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib都删掉,如下
set LINKFLAGS=/dll /export:%ENTRYPOINT% /LIBPATH:"%LIBLOC%" libmx.lib libmex.lib libmat.lib /MACHINE:X64 kernel32.lib user32.lib /nologo /manifest /incremental:NO /implib:"%LIB_NAME%.x" /MAP:"%OUTDIR%%MEX_NAME%%MEX_EXT%.map"
           

保存,关闭mexopts.bat文件

这个时候回到matlab,注意matlab的当前目录还是切换到D:\MATLAB\libsvm-3.20\matlab下,在matlab命令行输入编译命令:

make
           

这个时候编译就能成功了,在D:\MATLAB\libsvm-3.20\matlab目录下就会生成libsvmread.mexw64、libsvmwrite.mexw64、svmpredict.mexw64、svmtrain.mexw64等matlab文件

参考:matlab与vs2013 mex无法找到编译器问题

三、测试libsvm

在README里面有示例代码,可以用来验证libsvm是否正常工作。 假设matlab当前目录仍为D:\MATLAB\libsvm-3.20\matlab,运行如下代码即可得到SVM的测试结果,用来训练的数据在上一层目录的heart_scale文件里
>> [heart_scale_label, heart_scale_inst] = libsvmread('../heart_scale');
>> model = svmtrain(heart_scale_label, heart_scale_inst, '-c 1 -g 0.07');
>> [predict_label, accuracy, dec_values] = svmpredict(heart_scale_label, heart_scale_inst, model); % test the training data
           
[label_vector, instance_matrix] = libsvmread('data.txt');  Libsvmread函数可以 读入训练数据data.txt,注意data.txt里的数据必须按照libsvm约定的格式来组织 。两个输出分别是标签labels 和样本集 instances,它们可以作为svmtrain 或者 svmpredict的输入。

model = svmtrain(training_label_vector, training_instance_matrix [, 'libsvm_options']);

输入参数如下:

-training_label_vector:训练样本的标签,m*1向量。注意必须是double类型。

-training_instance_matrix:训练样本,m*n矩阵。每个样本为n维。它必须是稀疏的,而且必须是double类型。

-libsvm_options:字符串格式的训练选项,格式和LIBSVM 一样。

[predicted_label, accuracy, decision_values/prob_estimates] = svmpredict(testing_label_vector, testing_instance_matrix, model [, 'libsvm_options']);

输入参数如下:

-testing_label_vector:测试样本的标签,mx1向量。如果未知,那么就简单使用随机值。注意必须是double类型。

-testing_instance_matrix:训练样本,mxn矩阵。每个样本为n维。它必须是稀疏的,而且必须是double类型。

-model:前面训练得到的模型。

-libsvm_options:字符串格式的测试选项,格式和LIBSVM 一样。

输出参数如下:

-predicted_label:预测样本的标签向量。

-accuracy:一个向量,包含分类精度、均方误差、相关系数的平方(线性回归)

-decision_values/prob_estimates:用来评判分类置信度的值

libsvmwrite('data.txt', label_vector, instance_matrix)

libsvmwrite可以将参数以LIBSVM的格式写到文件中。instance_matrix必须是个稀疏矩阵。类型必须是double型。

以上示例代码运行结果如下:

optimization finished, #iter = 134
nu = 0.433785
obj = -101.855060, rho = 0.426412
nSV = 130, nBSV = 107
Total nSV = 130
Accuracy = 86.6667% (234/270) (classification)
>> 
           
实际应用中我们往往会有测试集和样本集,假设我有一个样本集TrainA.txt和一个测试集TestA.txt,数据格式都符合LIBSVM格式,我要进行测试得到精度的示例如下:
clc;
clear all;

%训练过程
[heart_scale_label, heart_scale_inst] = libsvmread('F:\work\SVMdata\TrainA.txt');
model = svmtrain(heart_scale_label, heart_scale_inst, '-c 1 -g 0.07');
%测试过程
[p_heart_scale_label, p_heart_scale_inst] = libsvmread('F:\work\SVMdata\TestA.txt');
[predict_label, accuracy, dec_values] = svmpredict(p_heart_scale_label, p_heart_scale_inst, model); 
           
结果如下:
*
optimization finished, #iter = 595
nu = 0.442940
obj = -533.171471, rho = -0.772225
nSV = 561, nBSV = 540
Total nSV = 561
Accuracy = 50% (2/4) (classification)
>> 
           

继续阅读