SVM约束因子测试----Matlab版本

1.约束因子

1.1 约束因子C

对于不可分的数据集,需要容忍一定错误率的存在。因此引入了约束因子C来权衡这个容忍度。

得到的优化问题为:

权重matlab三维图 matlab 权重_二分类

通过式子我们可以看到,但C足够大时,误差受到的关注度就会增大,这时SVM就会通过缩减间隔的方式来使这个误差减小。但支持向量机的"带宽"越小,容错率也就对于下降,因此我们需要限制C的大小,不能一味放大误差的影响。

对偶化后的问题:

权重matlab三维图 matlab 权重_数据_02

对比没有任何约束的SVM模型,加入约束后的模型目标函数没有变化,但约束域被C所限制。在LIBSVM工具包中我们也可以通过调节参数-c来调节约束因子的大小。

1.2 惩罚因子k

如果某个类别格外重要,那么我们也可以通过增加这个类出错时的惩罚倍数来降低对此类别分类时的错误率。

如下我们假设任务是一个二分类问题,如果对label=1的样本,分类错误的惩罚因子设置为k,label=-1的样本仍为1。

得到优化问题如下:

权重matlab三维图 matlab 权重_数据_03

对偶化后的问题:

权重matlab三维图 matlab 权重_二分类_04


可以看见不同的类别的约束条件是与自身的惩罚因子k有关的。

2. 测试惩罚因子的效果

2.1 解读惩罚因子k

因为上一篇文章已经对参数C进行了测试,所以我们这里调试一下因子k。

首先看一下参数说明:

-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
-wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)

按照提示,我们暂时是不需要设置参数C,因为我们能够调节第i类的weight来调节k的大小。

2.2 导入数据 && 转化二分类问题

我们将类别分为Class 6 和其他。其他类别用label=1标记。做法如下:

clear
clc
%% 导入数据
%根据网站,总训练数据拆分成了train和val两部分
[LabelOfAll,FeatureOfAll] = libsvmread('satimage.scale.txt'); %总数据(4435):testing:2000/ tr:3104 / val:1331
[LabelOfVal,FeatureOfVal] = libsvmread('satimage.scale.val.txt'); % val数据
[LabelOfTrain,FeatureOfTrain] = libsvmread('satimage.scale.train.txt');% train数据
[LabelOfTest,FeatureOfTest] = libsvmread('satimage.scale.testing.txt');% test数据

%% 稀疏阵转满阵
FeatureOfAllMatrix = full(FeatureOfAll);
FeatureOfTrainMatrix = full(FeatureOfTrain);
FeatureOfValMatrix = full(FeatureOfVal);
FeatureOfTestMatrix=full(FeatureOfTest);

%% 合并测试集与训练集(任务要求)  && 归一化处理
FeatureOfTestAndTrainMatrix_Minmax = normalize([FeatureOfTestMatrix',FeatureOfTrainMatrix']);
FeatureOfTestAndTrainMatrix_Minmax = FeatureOfTestAndTrainMatrix_Minmax';
LabelOfTestAndTrain=[LabelOfTest;LabelOfTrain];

FeatureOfTestMatrix_Minmax=FeatureOfTestAndTrainMatrix_Minmax(1:2000,:);

%% 将问题转化为二分类问题: class 6 && else
for i=1:size(LabelOfTestAndTrain,1)
    if LabelOfTestAndTrain(i)~=6
        LabelOfTestAndTrain(i)=1;
    end
end

2.3 使用-wi参数

2.3.1 解读README

网上暂时没有找到对-wi参数的使用说明,但我们可以在工具包内部的README.md内找到需要的使用说明:

Examples
========
> svm-scale -l -1 -u 1 -s range train > train.scale
> svm-scale -r range test > test.scale

Scale each feature of the training data to be in [-1,1]. Scaling
factors are stored in the file range and then used for scaling the
test data.

> svm-train -s 0 -c 5 -t 2 -g 0.5 -e 0.1 data_file

Train a classifier with RBF kernel exp(-0.5|u-v|^2), C=10, and
stopping tolerance 0.1.

> svm-train -s 3 -p 0.1 -t 0 data_file

Solve SVM regression with linear kernel u'v and epsilon=0.1
in the loss function.

> svm-train -c 10 -w1 1 -w-2 5 -w4 2 data_file

Train a classifier with penalty 10 = 1 * 10 for class 1, penalty 50 =
5 * 10 for class -2, and penalty 20 = 2 * 10 for class 4.

> svm-train -s 0 -c 100 -g 0.1 -v 5 data_file

Do five-fold cross validation for the classifier using
the parameters C = 100 and gamma = 0.1

> svm-train -s 0 -b 1 data_file
> svm-predict -b 1 test_file data_file.model output_file

Obtain a model with probability information and predict test data with
probability estimates

Precomputed Kernels
===================

感兴趣的朋友也可以打开svmtrain.c,查看SVM的具体实现过程。这里我们把svmtrain.c内参数options的结构及初始化给出来了:

param.svm_type = C_SVC;
param.kernel_type = RBF;
param.degree = 3;
param.gamma = 0;
param.coef0 = 0;
param.nu = 0.5;
param.cache_size = 100;
param.C = 1;
param.eps = 1e-3;
param.p = 0.1;
param.shrinking = 1;
param.probability = 0;
param.nr_weight = 0;
param.weight_label = NULL;
param.weight = NULL;
cross_validation = 0;

2.3.2 加权训练模型 && 结果反馈

有了这些帮助后便可以正确调参了:

%% 训练模型
% Class6 权重10 & Else 权重 1
d=2;
c=1;
Options=['-t 1',' -d ',num2str(d),' -c ',num2str(c),'-v 10 -w6 10 -q'];
svmtrain(LabelOfTestAndTrain,FeatureOfTestAndTrainMatrix_Minmax,Options);
% Class6 权重1 & Else 权重 1
d=2;
c=1;
Options=['-t 1',' -d ',num2str(d),' -c ',num2str(c),'-v 10 -w6 1 -q'];
svmtrain(LabelOfTestAndTrain,FeatureOfTestAndTrainMatrix_Minmax,Options);

得到结果:

Cross Validation Accuracy = 83.0329%
Cross Validation Accuracy = 90.2038%