因为python的教程没有找到详细的所以就改用matlab了
使用的是matlab r2016a,libsvm3-24,具体的安装配置教程就直接参考谦恭大大的了:
https://blog.csdn.net/github_35807147/article/details/80725642
libsvm的使用需要按照它需要的格式排列数据,格式即:
标记值 属性序号:属性值 属性序号:属性值......
这次的数据格式使用libsvmwrite函数生成,它的使用格式如下:
libsvmwrite(‘libsvm_data.mat’,label,instance);
label为样本的标记值矩阵,n*1大小,
instance是一个稀疏矩阵,我们通过sparse()函数来生成。
数据准备的过程如下:
label=[1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0];
instance=[2,1,2,3,3,1,0.697,0.406;...
3,1,1,3,3,1,0.774,0.376;...
3,1,2,3,3,1,0.634,0.264;...
2,1,1,3,3,1,0.608,0.318;...
1,1,2,3,3,1,0.556,0.215;...
2,2,2,3,2,0,0.403,0.237;...
3,2,2,2,2,0,0.481,0.149;...
3,2,2,3,2,1,0.437,0.211;...
3,2,1,2,2,1,0.666,0.091;...
2,3,3,3,1,0,0.243,0.267;...
1,3,3,1,1,1,0.245,0.057;...
1,1,2,1,1,0,0.343,0.099;...
2,2,2,2,3,1,0.639,0.161;...
1,2,1,2,3,1,0.657,0.198;...
3,2,2,3,2,0,0.360,0.370;...
1,1,2,1,1,1,0.593,0.042;...
2,1,1,2,2,1,0.719,0.103];
instance=sparse(instance);
libsvmwrite('libsvm_data.mat',label,instance);
然后再将生成的libsvm_data.mat用libsvmread读入,
libsvmread的作用是把如下格式的文本文件egin{align*} 1 & *:* *:* \ -1 & *:* *:* end{align*}读取进MATLAB,将第一列的$1,-1$串存成一个类标记向量,之后的特征存成矩阵。
粗暴理解就是一个预处理的作用。
[data_label,data_instance]=libsvmread('libsvm_data.mat');
找到的参考博客上是这么写的,但我一琢磨,好家伙,data_label和label有什么区别么?同理instance和data_instance有什么区别么?
于是我就换了换,原本应当是
model=svmtrain(data_label,data_instance)
我直接
model=svmtrain(label,instance)
输出结果都是
optimization finished, #iter = 7
nu = 0.764822
obj = -10.174209, rho = 0.319850
nSV = 14, nBSV = 12
Total nSV = 14
model =
Parameters: [5x1 double]
nr_class: 2
totalSV: 14
rho: 0.3199
Label: [2x1 double]
sv_indices: [14x1 double]
ProbA: []
ProbB: []
nSV: [2x1 double]
sv_coef: [14x1 double]
SVs: [14x8 double]
没有任何区别,大约是这次提供的数据集是完整并且严格按照格式写出来的,所以没法体现出区别。
建模函数svmtrain进行分类建模时的完整格式应当类似下面这个:
model = svmtrain(trainlabel, traindata, ‘-s 0 -t 2 -c 1.2 -g 2.8’);
具体每个参数的作用这个大大的博客里写得很详尽了:https://www.omegaxyz.com/2018/01/23/matlab_svm/
完成题目所需要修改的核函数类型是-t,0是线性核,2是RBF核即高斯核,那么就修改代码如下:
model=svmtrain(label,instance,'-t 0')
得到线性核的结果
optimization finished, #iter = 25
nu = 0.457287
obj = -6.675040, rho = 3.775986
nSV = 10, nBSV = 6
Total nSV = 10
model =
Parameters: [5x1 double]
nr_class: 2
totalSV: 10
rho: 3.7760
Label: [2x1 double]
sv_indices: [10x1 double]
ProbA: []
ProbB: []
nSV: [2x1 double]
sv_coef: [10x1 double]
SVs: [10x8 double]
而高斯核的结果就是参数缺省时的结果,也就是最上面那个。
然后就是结果分析。
#iter是迭代次数,nu与前面的操作参数-n v相同,obj为SVM文件转换为的二次规划求解得到的最小值,rho是判决函数的常数项b,nSV是支持向量个数,nBSV是边界上的支持向量个数。Total nSV是支持向量总个数。
而在训练好的模型中,parameters内装的是训练模型的参数,totalSV是支持向量的数目,Labe装的是类别标记,nSV装的是每类支持向量的个数,sv_coef装的是支持向量对应的Wi,SVs里则是每个支持向量。我们要看的就是SVs的内容。输出时应当是稀疏矩阵,为了可观性可以用full()函数转化为全矩阵后输出。
线性核的SVs结果如下:
2.0000 1.0000 1.0000 3.0000 3.0000 1.0000 0.6080 0.3180
1.0000 1.0000 2.0000 3.0000 3.0000 1.0000 0.5560 0.2150
2.0000 2.0000 2.0000 3.0000 2.0000 0 0.4030 0.2370
3.0000 2.0000 2.0000 2.0000 2.0000 0 0.4810 0.1490
3.0000 2.0000 2.0000 3.0000 2.0000 1.0000 0.4370 0.2110
2.0000 3.0000 3.0000 3.0000 1.0000 0 0.2430 0.2670
2.0000 2.0000 2.0000 2.0000 3.0000 1.0000 0.6390 0.1610
1.0000 2.0000 1.0000 2.0000 3.0000 1.0000 0.6570 0.1980
3.0000 2.0000 2.0000 3.0000 2.0000 0 0.3600 0.3700
2.0000 1.0000 1.0000 2.0000 2.0000 1.0000 0.7190 0.1030
高斯核的SVs结果如下:
2.0000 1.0000 2.0000 3.0000 3.0000 1.0000 0.6970 0.4060
3.0000 1.0000 1.0000 3.0000 3.0000 1.0000 0.7740 0.3760
2.0000 1.0000 1.0000 3.0000 3.0000 1.0000 0.6080 0.3180
1.0000 1.0000 2.0000 3.0000 3.0000 1.0000 0.5560 0.2150
2.0000 2.0000 2.0000 3.0000 2.0000 0 0.4030 0.2370
3.0000 2.0000 2.0000 2.0000 2.0000 0 0.4810 0.1490
3.0000 2.0000 2.0000 3.0000 2.0000 1.0000 0.4370 0.2110
3.0000 2.0000 1.0000 2.0000 2.0000 1.0000 0.6660 0.0910
2.0000 3.0000 3.0000 3.0000 1.0000 0 0.2430 0.2670
1.0000 1.0000 2.0000 1.0000 1.0000 0 0.3430 0.0990
2.0000 2.0000 2.0000 2.0000 3.0000 1.0000 0.6390 0.1610
1.0000 2.0000 1.0000 2.0000 3.0000 1.0000 0.6570 0.1980
3.0000 2.0000 2.0000 3.0000 2.0000 0 0.3600 0.3700
2.0000 1.0000 1.0000 2.0000 2.0000 1.0000 0.7190 0.1030
可以看到的是线性核的支持向量个数比高斯核要少,但两者的向量长度是相同的,而且部分向量是一致的,两者相差不多的原因、依据网上博主们的核函数选择原则来看,或许是因为这个样本集的样本数和属性数相差不大。而在其他情况下的表现还有待讨论。