简介
使用LIBSVM需要遵循其指定的数据格式组织输入数据。这里就介绍一下如何组织输入数据,将制作好的数据输出和读取。
LIBSVM数据格式
LIBSVM训练数据和检验数据文件格式如下(训练和测试数据的格式必须相同):
[label] [index1] [value1] [index2] [value2] …
[label] [index1] [value1] [index2] [value2] …
label 目标值,就是说class(属于哪一类),就是你要分类的种类,通常是一些整数。
index 就是索引值,是整数升序排列。
value 就是特征值(属性数据),用来train的数据,通常是一堆实数组成。
类别标签 索引1 属性1 索引2 属性2 …
类别标签 索引1 属性1 索引2 属性2 …
……
类别标签 索引1 属性1 索引2 属性2 …
以自带数据heart_scale为例:
1 1:0.708333 2:1 3:1 4:-0.320755 5:-0.105023 6:-1 7:1 8:-0.419847 9:-1 10:-0.225806 12:1 13:-1
-1 1:0.583333 2:-1 3:0.333333 4:-0.603774 5:1 6:-1 7:1 8:0.358779 9:-1 10:-0.483871 12:-1 13:1
.....
.....
第一行数据,表示训练用的特征有13维,第一维是0.708333,第二维是1,第三维是1,第四维是-0.320755,类别是1
生成LIBSVM数据
因为是在MATLAB环境安装的LIBSVM,我们基于MATLAB使用libsvmwrite函数生成LIBSVM格式的数据。libsvmwrite函数使用方法如下:
libsvmwrite('libsvm_data.mat',label, instance);
label为目标值,即样本的类别,是一个n*1的矩阵。
instance是一个稀疏矩阵,这里有必要讲解一下稀疏矩阵。
什么是稀疏矩阵,以及稀疏矩阵的表示方式。
在MATLAB中矩阵有两种存储方式:(1)完全存储方式;(2)稀疏存储方式。
完全存储方式,是将矩阵的全部元素按行列存储,也就传统意义中的矩阵存储。
稀疏存储方式,只存储矩阵的非零元素的值及其位置,即行号和列号。
如下所示,A矩阵是完全存储方式,B矩阵是稀疏存储方式。
>> A = magic(3)
A =
8 1 6
3 5 7
4 9 2
>> B = sparse(A)
B =
(1,1) 8
(2,1) 3
(3,1) 4
(1,2) 1
(2,2) 5
(3,2) 9
(1,3) 6
(2,3) 7
(3,3) 2
因为LIBSVM要求的instance为稀疏矩阵,我们可以在MATLAB中先制作出完全存储方式的矩阵,然后用命令sparse转成稀疏矩阵即可。
使用一个简单直白的例子,计划使用身高、体重、头发长度、胸围等特征对样本进行训练并用训练后的模型进行分类。例子:
男生1 身高:176cm 体重:70kg 发长:6cm 胸围:86cm;
男生2 身高:180cm 体重:80kg 发长:5cm 胸围:80cm;
男生3 身高:175cm 体重:69kg 发长:8cm 胸围:90cm;
女生1 身高:161cm 体重:45kg 发长:15cm 胸围:96cm;
女生2 身高:163cm 体重:47kg 发长:35cm 胸围:97cm;
女生3 身高:170cm 体重:43kg 发长:20cm 胸围:93cm;
如果我们将男生标签label设置为1,女生标签为2,即
label = [1; 1; 1; 2; 2; 2];
instance矩阵为
instance = [176 70 6 86; 180 80 5 80; 175 69 8 90; 161 45 15 96; 163 47 35 97; 170 43 20 93];
使用libsvmwrite函数输出LIBSVM格式数据时,需要将instance转成稀疏矩阵,转换方法如下:
instance = sparse(instance);
libsvmwrite('libsvm_data.mat',label, instance);
完整代码如下:
clc
clear
label = [1; 1; 1; 2; 2; 2];
instance = [176 70 6 86; 180 80 5 80; 175 69 8 90; 161 45 15 96; 163 47 35 97; 170 43 20 93];
instance = sparse(instance);
libsvmwrite('libsvm_data.mat',label, instance);
[data_label,data_instance]=libsvmread('libsvm_data.mat');
model = svmtrain(data_label,data_instance)
[predict_label,accuracy,dec_values] = svmpredict(data_label,data_instance,model)
运行结果:
*.*
optimization finished, #iter = 7
nu = 0.998470
obj = -2.995923, rho = 0.001631
nSV = 6, nBSV = 1
Total nSV = 6
model =
包含以下字段的 struct:
Parameters: [5×1 double]
nr_class: 2
totalSV: 6
rho: 0.0016
Label: [2×1 double]
sv_indices: [6×1 double]
ProbA: []
ProbB: []
nSV: [2×1 double]
sv_coef: [6×1 double]
SVs: [6×4 double]
Accuracy = 100% (6/6) (classification)
如果班级中新来了一个同学,我们知道这位新同学的身体特征,如何用训练好的model判断这位同学的性别呢?
这位新同学的身体特征为,男生1 身高:165cm 体重:65kg 发长:3cm 胸围:80cm;
new_label = [1];
new_instance = [165 65 3 80];
[predict_label,accuracy,dec_values] = svmpredict(new_label,new_instance,model)
预测结果,从结果看很不幸这个小男孩被预测判断为女生了(predict_label = 2)
>> new_label = [1];
new_instance = [165 65 3 80];
[predict_label,accuracy,dec_values] = svmpredict(new_label,new_instance,model)
Accuracy = 0% (0/1) (classification)
predict_label =
2
accuracy =
0
1
NaN
dec_values =
-0.0016