LIBSVM使用实验兼数据转换--UCI-SPECTF

目录

1. 概要

2. 数据格式转换

2.1 LIBSVM的数据格式

2.2 数据格式转换

3. Step-by-step

4. Grid Search

5. Auto full-flow

6. 基于sklearn SVC的实验


1. 概要

        本文介绍以UCI-SPECTF数据实验对象,基于LIBSVM的分类实验,以及相应的数据转换。最后还给出了直接使用SKLEARN的的实验代码及结果对比。

2. 数据格式转换

        Reference: https://blog.csdn.net/cclaree/article/details/103392803

2.1 LIBSVM的数据格式

        libSVM的数据格式为:

Label index1:value1 index2:value2 index3:value3 ….
Label index1:value1 index2:value2 index3:value3 ….

        Label:是类别的标识,可以自己随意定,比如1,-1,再比如-10,0,15。当然,如果是回归,这是目标值,就要实事求是了。

        index :是有顺序的索引,通常是连续的整数。就是指特征编号,必须按照升序排列。

        Value:就是要训练的数据,从分类的角度来说就是特征值,数据之间用空格隔开。比如:

        

-15 1:0.708 2:1056 3:-0.3333

        需要注意的是,如果特征值为0,该项特征可以跳过,因此index看上去就不连续(数据处理程序看到有index被跳过就知道这是特征值为0的项)。如:

-15 1:0.708 3:-0.3333

        中间跳过了index=2的项,表明第2个特征值为0。

2.2 数据格式转换

        查阅了一下网上资源,八仙过海各显神通,有多种办法。最终觉得[2]看上去比较对眼,其中提供了一个将matlab数组转换为LIBSVM所接受的格式的matlab函数,为了方便各位读者,转录如下(亲测OK各位放心使用):

% https://blog.csdn.net/cclaree/article/details/103392803
% Matlab function.
function libsvmtransform(A,filename)
[m,n]=size(A);
txt='.txt';
file=[filename,txt];
fid = fopen(file,'w');%写入文件路径

for i=1:m
    temp1 = A(i,2:n);%存储A中每一行从第2位开始的值
    temp2 = [];
    for j = 1:length(temp1)
       if temp1(j) ~= 0
            temp2 = [temp2 ' ' num2str(j) ':' num2str(temp1(j))];
       else
            temp2 = [temp2];
       end
    end  % temp2存放A一行添加序号的结果
temp3 = [num2str(A(i,1)) temp2];%temp3存放最终一行的结果
[m1,n1] = size(temp3);
 for k = 1:n1
     if k == n1
         fprintf(fid,'%c\n',temp3(k));
     else
         fprintf(fid,'%c',temp3(k));
     end
 end
end
fclose(fid);

        基于以上转换函数,我写了matlab脚本进行数据转换。先读入数据(原始数据相当于是csv格式) ,得到matlab数组,然后再调用以上函数生成LIBSVM所需要的格式文件。

% Matlab/Octave scipt
% chenxy 2021-10-24
close all; clear; clc

SPECTF = csvread('SPECTF.train'); % read a csv file
libsvmtransform(SPECTF,'SPECTF_train');
open('SPECTF_train.txt')

SPECTF = csvread('SPECTF.test'); % read a csv file
libsvmtransform(SPECTF,'SPECTF_test');
open('SPECTF_test.txt')

        这样得到了LIBSVM数据文件SPECTF_train.txt和SPECTF_test.txt。可以开始干活了。

3. Step-by-step

        首先还是step-by-step地做(毕竟现在还不是很熟练),多麻烦一点儿没有坏处。

        第一步,scaling后训练

>> svm-scale -l -1 -u 1 -s SPECTF_range SPECTF_train.txt > SPECTF_train.scale
>> svm-scale -r SPECTF_range SPECTF_test.txt > SPECTF_test.scale
>> svm-train SPECTF_train.scale

LIBSVM使用实验兼数据转换--UCI-SPECTF_第1张图片

        第2步, 对训练集和测试集做预测

>> svm-predict SPECTF_train.scale SPECTF_train.scale.model SPECTF_train.predict
>> svm-predict SPECTF_test.scale SPECTF_train.scale.model SPECTF_test.predict

         训练集和测试集的分类准确度都不是很高。

4. Grid Search

>>python ..\libsvm-master\tools\grid.py SPECTF_train.scale

        输出:0.5, 0.125, 78.75 

LIBSVM使用实验兼数据转换--UCI-SPECTF_第2张图片

         基于以上搜索的参数(C=0.5, gamma=0.125)重新进行训练和分类评估:

>>svm-train -c 0.5 -g 0.125 SPECTF_train.scale
>>svm-predict SPECTF_train.scale SPECTF_train.scale.model SPECTF_train.predict
>>svm-predict SPECTF_test.scale SPECTF_train.scale.model SPECTF_test.predict

LIBSVM使用实验兼数据转换--UCI-SPECTF_第3张图片

LIBSVM使用实验兼数据转换--UCI-SPECTF_第4张图片

        比上一节的结果略有提高。

        这是这个数据集用SVM所能取得的性能极限呢?还是因为以上做法有问题呢?

5. Auto full-flow

        作为一个既定的实验流程,也重新做一次全自动的流程:

>>python easy.py SPECTF.train SPECTF.test

LIBSVM使用实验兼数据转换--UCI-SPECTF_第5张图片

         结果与上面的半手动流程相同,毫不意外。

6. 基于sklearn SVC的实验

        

        为了做个对比,直接调用sklearn SVC进行分类实验并于以上分类结果进行对比。并且都直接使用缺省参数。

        注意,UCI-SPECTF的原始数据格式是符合SKLEARN要求的,不需要进行变换。因此在这个实验中直接用UCI-SPECTF的原始数据。代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Sep 29 12:50:49 2021

@author: chenxy

Experiment on UCI-SPECTF using sklearn SVC
"""

print(__doc__)

import numpy as np
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
# X = np.array([[-1, -1], [-2, -1], [1, 1], [2, 1]])
# y = np.array([1, 1, 2, 2])

train_data = np.loadtxt('SPECTF.train', delimiter=',')
X = train_data[:,1:]
y = train_data[:,0]
clf = make_pipeline(StandardScaler(), SVC(gamma='auto'))
clf.fit(X, y)
print('SPECTF train data accuracy = ',clf.score(X, y))

test_data = np.loadtxt('SPECTF.test', delimiter=',')
X_test = test_data[:,1:]
y_test = test_data[:,0]
print('SPECTF test data accuracy = ',clf.score(X_test, y_test))

        输出结果:

        SPECTF train data accuracy =  0.95
        SPECTF test data accuracy =  0.7433155080213903

        这是个典型的欠拟合的症状。

        另外,作为参考:

An accuracy comparison between scikit-learn’s SVM and LightTwinSVM program – The Blog of Amir Mir (mirblog.net)        报告的基于Scikit-learn's SVM 的UCI-SPECTF的结果为79.78%。

        这说明以上不管是直接基于libSVM的训练还是基于sklearn-SVC的训练都还有不足之处,有待进一步研究(终于要进入炼丹的领域了。。。^-^)。

        关于LIBSVM的安装(Windows)以及初始实验参见:

LIBSVM安装和使用实验(Windows 10)https://blog.csdn.net/chenxy_bwave/article/details/120923321icon-default.png?t=L9C2https://blog.csdn.net/chenxy_bwave/article/details/120923321

  

你可能感兴趣的:(机器学习,机器学习,支持向量机,LIBSVM,scikit-learn,1024程序员节)