LIBSVM是台湾大学林智仁(Lin Chih-Jen)教授于2001年开发设计,可在 http://www.csie.ntu.edu.tw/~cjlin/libsvm/ 或 https://github.com/cjlin1/libsvm/releases 免费获得。
下载后解压,主要有6个文件夹和一些源码文件:
libsvm-3.23.zip
(2018年8月时最新版本)解压,把解压出的文件夹libsvm-3.23
复制到Matlab的安装路径下...\MATLAB\R2016b\toolbox
...\MATLAB\R2016b\toolbox\libsvm-3.23
添加到Matlab的搜索路径(添加并包含子文件夹)注:
因为使用的是64位的操作系统和matlab,而...\MATLAB\R2016b\toolbox\libsvm-3.23\windows
下包含了matlab可执行的64位二进制文件libsvmread.mexw64/libsvmwrite.mexw64/svmpredict.mexw64/svmtrain.mexw64,故无需自己编译。
假设你使用的是32位操作系统和matlab,则需要自己编译相应的二进制文件:在matlab命令窗口输入mex –setup,这时matlab会提示你选择编译mex文件的c/c++编译器。选择一个你电脑上安装的c/c++编译器,例如Microsoft Visual C++ 2010,将matlab当前目录设置为:‘…\MATLAB\R2016b\toolbox\libsvm-3.23\matlab’,输入命令make,这时你会看到当前目录生成了二进制文件libsvmread.mexw32/libsvmwrite.mexw32/svmpredict.mexw32/svmtrain.mexw32。将当前目录添加到matlab路径中即可。
...\MATLAB\R2016b\toolbox\libsvm-3.23
,输入如下测试代码:[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 traindata
得到如下结果,说明安装成功:
*
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)
参考:SVM学习笔记(1)LIBSVM在matlab下的使用安装
libsvmread
主要用于读取数据这里的数据是非matlab下的.mat数据,比如说是.txt,.data等等,这个时候需要使用libsvmread函数进行转化为matlab可识别数据,比如自带的数据是heart_scale数据,那么导入到matlab有两种方式,
一种使用libsvmread函数,在matlab下直接libsvmread(heart_scale);
第二种方式为点击matlab的‘导入数据’按钮,然后导向heart_scale所在位置,直接选择就可以了。因为有的数据libsvmread读取不管用,但是‘导入数据’后就可以变成matlab下数据。
libsvmwrite
写函数,就是把已知数据存起来使用方式为:libsvmwrite(‘filename’,label_vector, instance_matrix);
label_vector是标签,instance_matrix为数据矩阵(注意这个数据必须是稀疏矩阵,就是里面的数据不包含没用的数据(比如很多0),有这样的数据应该去掉再存)。
svmtrain
训练函数,训练数据产生模型的Options:可用的选项即表示的涵义如下
-s
svm类型:SVM设置类型(默认0)
0 – C-SVC
1 --v-SVC
2 – 一类SVM
3 – e-SVR
4 – v-SVR
(分类问题主要使用0 – C-SVC,回归问题主要使用3 – e-SVR)
-t
核函数类型:核函数设置类型(默认2)
0 – 线性:u’v
1 – 多项式:(ru’v + coef0)^degree(关联参数:-g -r -d)
2 – RBF函数:exp(-gamma|u-v|^2)(关联参数:-g)
3 –sigmoid:tanh(ru’v + coef0)(关联参数:-g -r)
(一般使用RBF核函数)
-d
degree:核函数中的degree设置(针对多项式核函数)(默认3)
-g
r(gamma):核函数中的gamma函数设置(针对多项式/rbf/sigmoid核函数)(默认1/ num_features,即属性数目的倒数)
-r
coef0:核函数中的coef0设置(针对多项式/sigmoid核函数)((默认0)
-c
cost:设置C-SVC,e -SVR和v-SVR的参数(损失函数)(范围(0,+∞),默认1)
-n
nu:设置v-SVC,一类SVM和v- SVR的参数(范围(0,1],默认0.5)
-p
p:设置e -SVR 中损失函数p的值(范围(0,+∞),默认0.1)
-m cachesize:设置cache内存大小,以MB为单位(默认40)
-e eps:设置允许的终止判据(默认0.001)
-h shrinking:是否使用启发式,0或1(默认1)
-wi
weight:设置第几类的参数C为weight*C(C-SVC中的C)(默认1)
-v
n: n-fold交互检验模式,n为fold的个数,必须大于等于2
其中
以上这些参数设置可以按照SVM的类型和核函数所支持的参数进行任意组合。如果设置的参数在函数或SVM类型中没有也不会产生影响,程序不会接受该参数;如果应有的参数设置不正确,参数将采用默认值。
附:利用libsvm-mat建立分类模型model参数解密
function write4libsvm
% 为了使得数据满足libsvm的格式要求而进行的数据格式转换 注意原始格式是mat的数据格式,转化成txt或者dat都可以。
% 原始数据保存格式为:
% [标签 第一个属性值 第二个属性值...]
% 转换后文件格式为满足libsvm的格式要求,即:
% [标签 1:第一个属性值 2:第二个属性值 3:第三个属性值 ...]
% Genial@ustc
% 2004.6.16
[filename, pathname] = uigetfile( {'*.mat', ...
'数据文件(*.mat)'; ...
'*.*', '所有文件 (*.*)'}, ...
'选择数据文件');
try
S=load([pathname filename]);
fieldName = fieldnames(S);
str = cell2mat(fieldName);
B = getfield(S,str);
[m,n] = size(B);
[filename, pathname] = uiputfile({'*.txt;*.dat' ,'数据文件(*.txt;*.dat)';'*.*','所有文件 (*.*)'},'保存数据文件');
fid = fopen([pathname filename],'w');
if(fid~=-1)
for k=1:m
fprintf(fid,'%3d',B(k,1));
for kk = 2:n
fprintf(fid,'\t%d',(kk-1));
fprintf(fid,':');
fprintf(fid,'%d',B(k,kk));
end
k;
fprintf(fid,'\n');
end
fclose(fid);
else
msgbox('无法保存文件!');
end
catch
end
参考:
如何转成libsvm支持的数据格式并做回归分析
先归一化再划分训练集、测试集
% 数据集归一化
dataset_c21_label = dataset_c21(:,1);dataset_c21_inst = dataset_c21(:,2:136);
[dataset_c21_scale_T,PS] = mapminmax(dataset_c21_inst'); dataset_c21_scale = dataset_c21_scale_T';
% Matlab中的mapminmax用法
% [inputtrain,setting] = mapminmax(input_train');
% inputtest = mapminmax('apply',input_test',setting);
% 随机划分训练集、测试集,训练集:测试集=6:4,使用函数split_train_test.m,ratio=0.6
[X_train, y_train, X_test, y_test] = split_train_test(dataset_c21_scale(:,1:5*i), dataset_c21_label, 2, 0.6);
function [X_train, y_train, X_test, y_test] = split_train_test(X, y, k, ratio)
%SPLIT_TRAIN_TEST 分割训练集和测试集
% 参数X是数据矩阵 y是对应类标签 k是类别个数 ratio是训练集的比例
% 返回训练集X_train和对应的类标签y_train 测试集X_test和对应的类标签y_test
m = size(X, 1);
y_labels = unique(y); % 去重,k应该等于length(y_labels)
d = [1:m]';
X_train_0 = [];y_train_0= [];
for i = 1:k
comm_i = find(y == y_labels(i));
if isempty(comm_i) % 如果该类别在数据集中不存在
continue;
end
size_comm_i = length(comm_i);
rp = randperm(size_comm_i); % random permutation
rp_ratio = rp(1:floor(size_comm_i * ratio));
ind = comm_i(rp_ratio);
X_train_0 = [X_train_0; X(ind, :)];
y_train_0 = [y_train_0; y(ind, :)];
d = setdiff(d, ind);
end
X_test = X(d, :);y_test = y(d, :);
% famirtse增加:打乱训练集的顺序,日期:20180901
Xy_train_0 = [y_train_0,X_train_0];
rowrank = randperm(size(Xy_train_0, 1));Xy_train = Xy_train_0(rowrank, :); % 随机打乱矩阵的行数
X_train = Xy_train(:,2:end);y_train = Xy_train(:,1);
end
参考:再议归一化问题
归一化函数mapminmax的讨论
归一化问题
Matlab实现 把数据集X分割成训练集和测试集
Matlab划分测试集和训练集
c,g
% 参数(c,g)寻优,使用函数SVMcg.m
[bestacc,bestc,bestg] = SVMcg(y_train,X_train,-8,8,-8,8,10,0.5,0.5,0.9);
cmd = ['-c',num2str(bestc),'-g',num2str(bestg),'-w1 2 -w0 0.5'];
function [bestacc,bestc,bestg] = SVMcg(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,accstep)
%SVMcg cross validation by faruto
%Email:[email protected] QQ:516667408 http://blog.sina.com.cn/faruto BNU
%last modified 2009.8.23
%Super Moderator @ www.ilovematlab.cn
%% 参数说明:
% train_label:训练集标签.要求与libsvm工具箱中要求一致.
% train:训练集.要求与libsvm工具箱中要求一致.
% cmin:惩罚参数c的变化范围的最小值(取以2为底的对数后),即 c_min = 2^(cmin).默认为 -5
% cmax:惩罚参数c的变化范围的最大值(取以2为底的对数后),即 c_max = 2^(cmax).默认为 5
% gmin:参数g的变化范围的最小值(取以2为底的对数后),即 g_min = 2^(gmin).默认为 -5
% gmax:参数g的变化范围的最小值(取以2为底的对数后),即 g_min = 2^(gmax).默认为 5
% v:cross validation的参数,即给测试集分为几部分进行cross validation.默认为 3
% cstep:参数c步进的大小.默认为 1
% gstep:参数g步进的大小.默认为 1
% accstep:最后显示准确率图时的步进大小. 默认为 1.5
%% about the parameters of SVMcg
if nargin < 10
accstep = 1.5;
end
if nargin < 8
accstep = 1.5;
cstep = 1;
gstep = 1;
end
if nargin < 7
accstep = 1.5;
v = 3;
cstep = 1;
gstep = 1;
end
if nargin < 6
accstep = 1.5;
v = 3;
cstep = 1;
gstep = 1;
gmax = 5;
end
if nargin < 5
accstep = 1.5;
v = 3;
cstep = 1;
gstep = 1;
gmax = 5;
gmin = -5;
end
if nargin < 4
accstep = 1.5;
v = 3;
cstep = 1;
gstep = 1;
gmax = 5;
gmin = -5;
cmax = 5;
end
if nargin < 3
accstep = 1.5;
v = 3;
cstep = 1;
gstep = 1;
gmax = 5;
gmin = -5;
cmax = 5;
cmin = -5;
end
%% X:c Y:g cg:acc
[X,Y] = meshgrid(cmin:cstep:cmax,gmin:gstep:gmax);
[m,n] = size(X);
cg = zeros(m,n);
%% record acc with different c & g,and find the bestacc with the smallest c
bestc = 0;
bestg = 0;
bestacc = 0;
basenum = 2;
for i = 1:m
for j = 1:n
cmd = ['-v ',num2str(v),' -c ',num2str( basenum^X(i,j) ),' -g ',num2str( basenum^Y(i,j) )];
cg(i,j) = svmtrain(train_label, train, cmd);
if cg(i,j) > bestacc
bestacc = cg(i,j);
bestc = basenum^X(i,j);
bestg = basenum^Y(i,j);
end
if ( cg(i,j) == bestacc && bestc > basenum^X(i,j) )
bestacc = cg(i,j);
bestc = basenum^X(i,j);
bestg = basenum^Y(i,j);
end
end
end
%% to draw the acc with different c & g
[C,h] = contour(X,Y,cg,60:accstep:100);
clabel(C,h,'FontSize',10,'Color','r');
xlabel('log2c','FontSize',10);
ylabel('log2g','FontSize',10);
grid on;
参考:
关于SVM参数c&g选取的总结帖[matlab-libsvm]
% 训练
model = svmtrain(y_train, X_train, cmd);
% 测试/预测
[predict_label, accuracy, dec_values] = svmpredict(y_test, X_test, model);
acc = accuracy(1);
% 计算敏感性和特异性
sens = sum(predict_label==1&y_test==1)/sum(y_test==1)*100;
spec = sum(predict_label==0&y_test==0)/sum(y_test==0)*100;
首先用svm(libsvm,lssvm、hssvm)等等进行分类预测,要进行三个步骤1、训练 2、测试 3、预测
1、训练——大家都知道,就是用训练数据集,不管你采用那种寻优方式,得到相对的最优参数,训练模型。
2、测试——就是用刚刚得到的模型,对测试数据进行测试,此时测试数据集的label是已知的,这主要是用来对刚刚的模型的检测,或者是对参数的检测、或者是对模型的泛化能力的检测。此时会得到一个准确率,这时的准确率是有用的,是有实际意义的,因为原来的label是已知的。
3、预测——预测就是对未知类别的样本在测试确定了模型有好的泛化能力的情况下的预测分类,这步才是真的预测能力功能的实现。此时数据的label随便给了,这样是为了满足libsvm对数据格式的要求。此时也会得到一个准确率,但是这个是没有实际意义的,因为原始的label是随便给的,没有意义,我们只是关心的是最后得到的类别号——达到分类的目的。
以下简称交叉验证(Cross Validation)为CV.CV是用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set),首先用训练集对分类器进行训练,在利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标.常见CV的方法如下:
1).Hold-Out Method
将原始数据随机分为两组,一组做为训练集,一组做为验证集,利用训练集训练分类器,然后利用验证集验证模型,记录最后的分类准确率为此Hold-OutMethod下分类器的性能指标.此种方法的好处的处理简单,只需随机把原始数据分为两组即可,其实严格意义来说Hold-Out Method并不能算是CV,因为这种方法没有达到交叉的思想,由于是随机的将原始数据分组,所以最后验证集分类准确率的高低与原始数据的分组有很大的关系,所以这种方法得到的结果其实并不具有说服性.
2).K-fold Cross Validation(记为K-CV)
将原始数据分成K组(一般是均分),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证集的分类准确率的平均数作为此K-CV下分类器的性能指标.K一般大于等于2,实际操作时一般从3开始取,只有在原始数据集合数据量小的时候才会尝试取2.K-CV可以有效的避免过学习以及欠学习状态的发生,最后得到的结果也比较具有说服性.
3).Leave-One-Out Cross Validation(记为LOO-CV)
如果设原始数据有N个样本,那么LOO-CV就是N-CV,即每个样本单独作为验证集,其余的N-1个样本作为训练集,所以LOO-CV会得到N个模型,用这N个模型最终的验证集的分类准确率的平均数作为此下LOO-CV分类器的性能指标.相比于前面的K-CV,LOO-CV有两个明显的优点:
①a.每一回合中几乎所有的样本皆用于训练模型,因此最接近原始样本的分布,这样评估所得的结果比较可靠。
②b.实验过程中没有随机因素会影响实验数据,确保实验过程是可以被复制的。
但LOO-CV的缺点则是计算成本高,因为需要建立的模型数量与原始数据样本数量相同,当原始数据样本数量相当多时,LOO-CV在实作上便有困难几乎就是不显示,除非每次训练分类器得到模型的速度很快,或是可以用并行化计算减少计算所需的时间.
参考:交叉验证(CrossValidation)方法思想简介
选取SVM中参数 c和g的最佳值
寻找最佳c和g的思想仍然是让c和g在一定的范围里跑(比如 c = 2(-5),2(-4),…,2^(5),g = 2(-5),2(-4),…,2^(5)),然后用cross validation的想法找到是的准确率最高的c和g,在这里做了一点修改是: 因为会有不同的c和g都对应最高的的准确率,我把具有最小c的那组c和g认为是最佳的c和g,因为惩罚参数不能设置 太高,很高的惩罚参数能使得validation数据的准确率提高,但过高的惩罚参数c会造成过学习状态,往往都是惩罚参数c过高会导致最终测试集合的准确率并不是很理想 。
先大范围粗糙的找 比较理想的c和g,然后再细范围找更加理想的c和g.
比如首先让 c = 2(-5),2(-4),…,2^(5),g = 2(-5),2(-4),…,2^(5)在这个范围找比较理想的c和g。
此时bestc = 0.5,bestg=1,bestacc = 98.8764[cross validation 的准确率]
最终测试集合的准确率 Accuracy = 96.6292% (86/89) (classification)
下载:
libsvm-3.1-FarutoUltimate3.1Mcode,faruto最新加强工具箱
参考:
Libsvm-Faruto Ultimate工具箱学习笔记
libsvm-3.1-[FarutoUltimate3.1Mcode]——辅助函数简介(修改
参考:
学习SVM
SVM学习笔记(1)LIBSVM在matlab下的使用安装
【svm】使用libsvm分类的一般操作步骤