来源:
BreastTissue_classify_matlab: 使用libsvm进行分类 (github.com)
使用的一般步骤
1 )按照 LIBSVM 软件包所要求的格式准备数据集;
2 )对数据进行简单的缩放操作;
3 )首要考虑选用 RBF 核函数;
4 )采用交叉验证选择最佳参数 C 与 g ;
5 )采用最佳参数 C 与 g 对整个训练集进行训练获取支持向量机模型;
6 )利用获取的模型进行测试与预测。
一、数据
BreastTissue_data.mat
这里给出了106个数据, 每一个数据都有9个特征和一个分类标签;用这些数据来生成测试集和训练集, 得到模型并且测试、分类。
label:1、2、3、4、5、6
二、代码流程
%% I. 清空环境变量
clear all
clc
%% II. 导入数据
load BreastTissue_data.mat
%%
% 1. 随机产生训练集和测试集
n = randperm(size(matrix,1));
%%
% 2. 训练集——80个样本
train_matrix = matrix(n(1:80),:);
train_label = label(n(1:80),:);
%%
% 3. 测试集——26个样本
test_matrix = matrix(n(81:end),:);
test_label = label(n(81:end),:);
%% III. 数据归一化
[Train_matrix,PS] = mapminmax(train_matrix');
Train_matrix = Train_matrix';
Test_matrix = mapminmax('apply',test_matrix',PS);
Test_matrix = Test_matrix';
%% IV. SVM创建/训练(RBF核函数)
%%参数
% 1. 寻找最佳c/g参数——交叉验证方法
[c,g] = meshgrid(-10:0.2:10,-10:0.2:10);
[m,n] = size(c);
cg = zeros(m,n);
eps = 10^(-4);
v = 5;
bestc = 1;
bestg = 0.1;
bestacc = 0;
for i = 1:m
for j = 1:n
cmd = ['-v ',num2str(v),' -t 2',' -c ',num2str(2^c(i,j)),' -g ',num2str(2^g(i,j))];
cg(i,j) = svmtrain(train_label,Train_matrix,cmd);
if cg(i,j) > bestacc
bestacc = cg(i,j);
bestc = 2^c(i,j);
bestg = 2^g(i,j);
end
if abs( cg(i,j)-bestacc )<=eps && bestc > 2^c(i,j)
bestacc = cg(i,j);
bestc = 2^c(i,j);
bestg = 2^g(i,j);
end
end
end
cmd = [' -t 2',' -c ',num2str(bestc),' -g ',num2str(bestg)];
%%
% 2. 创建/训练SVM模型
model = svmtrain(train_label,Train_matrix,cmd);
%% V. SVM仿真测试
[predict_label_1,accuracy_1,prob_estimates] = svmpredict(train_label,Train_matrix,model);
[predict_label_2,accuracy_2,prob_estimates2] = svmpredict(test_label,Test_matrix,model);
result_1 = [train_label predict_label_1];
result_2 = [test_label predict_label_2];
%% VI. 绘图
figure
plot(1:length(test_label),test_label,'r-*')
hold on
plot(1:length(test_label),predict_label_2,'b:o')
grid on
legend('真实类别','预测类别')
xlabel('测试集样本编号')
ylabel('测试集样本类别')
string = {'测试集SVM预测结果对比(RBF核函数)';
['accuracy = ' num2str(accuracy_2(1)) '%']};
title(string)
结果:
参数
输入:
cmin,cmax: 惩罚参数c的变化范围,在[2^cmin,2^cmax]范围内寻找最佳的参数c,默认值为cmin=-8,cmax=8。
gmin,gmax: RBF核参数g的变化范围,在[2^gmin,2^gmax]范围内寻找最佳的RBF核参数g,默认值为gmin=-8,gmax=8。
v:对训练集进行v-fold Cross Validation,默认为3。
cstep,gstep:进行参数寻优是c和g的步进大小,默认取值为cstep=1,gstep=1。
accstep:最后参数选择结果图中准确率离散化显示的步进间隔大小([0,100]之间的一个数),默认为4.5。
输出:
bestCVaccuracy:最终CV意义下的最佳分类准确率。
bestc:最佳的参数c。
bestg:最佳的参数g。
三、常用的几个概念:
1.归一化函数(mapminmax)
(1)[Y,PS] = mapminmax(X,YMIN,YMAX)
其中,YMIN是我们期望归一化后矩阵Y每行的最小值,YMAX是我们期望归一化后矩阵Y每行的最大值。
(2)[Y,PS] = mapminmax(X,FP)
FP是一个结构体成员,主要是FP.ymin(相当于YMIN), FP.ymax(相当于YMAX)。1和2处理效果一样,只不过参数的带入形式不同。
(3)Y = mapminmax('apply',X,PS)
PS是训练样本的映射,测试样本的预处理方式应与训练样本相同。只需将映射PS apply到测试样本。
(4)X = mapminmax('reverse',Y,PS)
将归一化后的Y反转为归一化之前
(5)dx_dy = mapminmax('dx_dy',X,Y,PS)
2.交叉验证(Cross-validation)
交叉验证将原始数据集分为两组,分别作为训练集和验证集。训练集用于训练模型,验证集用于评价训练模型的性能指标。
参数寻优的意义:参数的数值决定着模型的性能。
采用交叉验证方法保障验证数据集没有参与过模型的训练,可以给出较为准确的参数寻优结果。
几种常用交叉验证(cross validation)方式的比较【python】
优化算法有很多,如网格搜索算法、遗传算法、粒子群算法、蚁群算法、模拟退火算法等。
交叉验证来说,我们采取的是网格搜索算法,即在参数的一定的范围内,按照指定的步长对不同的参数进行排列组合,将每一组参数组合进行测试,取性能指标最优的那一组参数作为最终参数的值。如本例中(C,gamma)组成了一个二维网格,再与性能指标识别率组成三维模型,实现参数的最优选择。
1、Double cross-validation
Double cross-validation也称2-fold cross-validation(2-CV)
将数据集分成两个相等大小的子集,进行两回合的分类器训练。在第一回合,一个子集作为训练集,另一个作为测试集;在第二回合,则将训练集与测试集对换后,再次训练分类器,而其中我们比较关心的是两次测试集的识别率。
优点:容易实现,处理简单。
缺点:没有用到交叉的方法,验证数据集对于模型的训练没有任何贡献。
2、K-flod CV(k折交叉验证)
样本数据被分为k组,每次将一组作为验证数据集,其余的k−1组作为训练数据集。这样就会有k 个训练模型,这k个模型的验证准确率的平均值作为模型的性能指标。
优点:所有的样本都会被用于模型训练,评价结果可信。
缺点:相较于Hold one method,处理较为复杂。
3、Leave-One-Out CV(LOO-CV留一验证法)
设原始数据集中有K个样本,每次选择一个样本作为验证数据集,其余的K−1个样本作为训练数据集,这样就会有K个训练模型,这K个训练模型的验证准确率平均值为模型的性能指标。
优点:每次模型训练,几乎所有的样本都会应用到,结果最可信。
缺点:需要训练的模型较多,且训练数据集样本大,计算成本高。
3.rbf核函数最佳参数cg的选取w问题
C被称为惩罚因子,C越大说明对错误的容忍度越小,会导致过拟合(overfitting);C太小可能会导致容错率过高,会导致欠拟合。
一般是通过交叉验证的方法来确定C和gamma。
思路:将C和gamma参数在一定取值范围内按照一定的步长(默认为1)进行取值组合;在不同(C,gamma)的组合下,将训练集样本均分成k组,一组作为验证的数据样本,其余k-1组则用来作为训练的数据,每一组数据都轮流着作为验证数据样本,这样在一组(C,gamma)组合下,就需要进行K次计算,把这K次计算的模型测试准确率score的均值作为这组(C,gamma)下模型的得分。这样的话就能够得到不同(C,gamma)组合下模型的得分,取得分最高的那组(C,gamma)即可,如果碰到有相同分的,一般考虑参数C,取C小的,因为在保证模型的准确率的情况下,C越小模型容错率大,可以避免过拟合,若C也相同,则取先出现的那一组gamma。简单的说,网格法原理就是在一定的范围里面大步伐的,挨着试cg的参数,然后把该参数结果的精确度 绘制成等高线;再缩小cg的范围,用小步伐去试,所以运算量很大。
网格法的缺点就是慢,数据量稍微大一点根本就跑不了。详细的理论代码可以在《[MATAB神经网络30个案例分析].史峰》这本书的的十二十三章有讲解,数据量太大的真的跑不动。