MATLAB环境使用LIBSVM-回归问题详解(四)

简介

回归分析(regression analysis)是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。LIBSVM可以用于解决分类和回归问题,上一篇博文中介绍了分类问题。在这里将对回归问题结合实例运用LIBSVM。回归分析按照涉及的变量的多少,分为一元回归和多元回归分析。这篇博文对于一元回归和多元回归,基于LIBSVM分别用两个例子进行讲解。

回归问题

回归问题与分类问题不同,但问题本质是一样的,就是有 一个输入又有输出(分类输出是分类标签 ,回归输出是因变量),也就是相当于一个函数映射。根据训练样本得到一个拟合函数,然后根据这个拟合函数预测给定的一个样本的输出值。分类问题是预测样本所述类别,回归问题是预测样本的值。
利用训练集合已知的 x,y来建立回归模型 model,然后用这个 model去预测。

核心函数svmtrain和svmpredict

调用格式

model = svmtrain(train_label, train_data, ‘options’);
[predict_label, accuracy/mse, dec_value] = svmpredict(test_label, test_data,model);

输入
train_data训练集属性矩阵,大小n*m,n表示样本数,m表示属性数目(维数),数据类型double;

train_label训练集标签,大小n*1,n表示样本数,数据类型double ;
这里输入变量顺序与Matlab自带的SVM正好相反。

LIBSVM options 训练参数设置

-s 选择SVM类型,回归分析只能选3或者4(默认值为0)
    0:C - SVC
    1:nu - SVC
    2:one - class SVM
    3:epsilon - SVR
    4:nu - SVR
- t 是选择核函数(默认值为2)
    0:线性核函数 u'v
    1:多项式核函数(r *u'v + coef0)^degree
    2:RBF 核函数 exp( -r|u - v|^2)
    3:sigmiod核函数 tanh(r * u'v + coef0)
- d degree:核函数中的 degree 参数设置(针对多项式核函数,默认值为3)
- g r(gama):核函数中的gama参数设置(针对多项式/sigmoid 核函数/RBF/,默认值为属性数目的倒数。即,k为属性的数目,则-g参数默认为 1/k)
- r coef0:核函数中的coef0参数设置(针对多项式/sigmoid核函数,默认值为0)
- c cost:设置 C - SVC,epsilon - SVR 和 nu - SVR的参数(默认值为1)
- n nu:设置 nu-SVC ,one - class SVM 和 nu - SVR的参数(默认值为 0.5)
- p epsilon:设置 epsilon - SVR 中损失函数的值(默认值为0.1)
- m cachesize:设置 cache 内存大小,以 MB 为单位(默认值为100)
- e eps:设置允许的终止阈值(默认值为0.001)
- h shrinking:是否使用启发式,0或1(默认值为1)
- wi weight:设置第几类的参数 C 为 weight * C(对于 C - SVC 中的 C,默认值为1)
- v n将训练数据分成n份做交叉验证。默认为5

其中-s控制的就是训练类型,而当-s等于3或4的时候,就是回归模型SVR。-s 3 就是常用的带惩罚项的 SVR模型。

注意:当svmtrain使用-v参数时,返回的model不再是一个结构体,分类问题返回的是交叉验证下的平均分类准确率;回归问题返回的是交叉检验下的平均mse(均方根误差)。使用-v是在参数寻优时寻找最优参数所用的,在正常模型训练时不用-v参数。

以上这些参数设置可以按照SVM的类型和核函数所支持的参数进行任意组合,如果设置的参数在函数或SVM类型中没有也不会产生影响,程序不会接受该参数;如果应有的参数设置不正确,参数将采用默认值。

输出model

训练得到的模型,是一个结构体。假设一个model结构如下:

model =
Parameters: [5x1 double]
nr_class: 2
totalSV: 259
rho: 0.0514
Label: [2x1 double]
ProbA: []
ProbB: []
nSV: [2x1 double]
sv_coef: [259x1 double]
SVs: [259x13 double]

首先先来看一下model.Parameters里面承装的都是什么:

model.Parameters
ans =
0
2.0000
3.0000
2.8000
0

重要知识点:

model.Parameters参数意义从上到下依次为:
-s svm类型:SVM设置类型(默认0)
-t 核函数类型:核函数设置类型(默认2)
-d degree:核函数中的degree设置(针对多项式核函数)(默认3)
-g r(gama):核函数中的gamma函数设置(针对多项式/rbf/sigmoid核函数) (默认类别数目的倒数)
-r coef0:核函数中的coef0设置(针对多项式/sigmoid核函数)((默认0)
即在本例中通过model.Parameters我们可以得知 –s 参数为0;-t 参数为 2;-d 参数为3;-g 参数为2.8(这也是我们自己的输入);-r 参数为0。

model.Label model.nr_class

model.Label
ans =
1
-1
>> model.nr_class
ans =
2

model.Label表示数据集中类别的标签都有什么,这里是 1,-1;
model.nr_class表示数据集中有多少类别,这里是二分类。

model.totalSV model.nSV

model.totalSV
ans =
259
>> model.nSV
ans =
118
141

model.totalSV代表总共的支持向量的数目,这里共有259个支持向量;
model.nSV表示每类样本的支持向量的数目,这里表示标签为1的样本的支持向量有118个,标签为-1的样本的支持向量为141。
注意:这里model.nSV所代表的顺序是和model.Label相对应的。

model.ProbA model.ProbB
使用-b参数时才能用到,用于概率估计。

model.sv_coef model.SVs model.rho

sv_coef: [259x1 double]
SVs: [259x13 double]
model.rho = 0.0514

重要知识点:

model.sv_coef是一个2591的矩阵,承装的是259个支持向量在决策函数中的系数;
model.SVs是一个259
13的稀疏矩阵,承装的是259个支持向量。
model.rho是决策函数中的常数项的相反数(-b)
最后我们来看一下,svmpredict得到的返回参数的意义都是什么?

% 利用建立的模型看其在训练集合上的分类效果
[PredictLabel,accuracy] = svmpredict(label,data,model);
accuracy

假设运行可以看到:

model =
Parameters: [5x1 double]
nr_class: 2
totalSV: 259
rho: 0.0514
Label: [2x1 double]
ProbA: []
ProbB: []
nSV: [2x1 double]
sv_coef: [259x1 double]
SVs: [259x13 double]
Accuracy = 99.6296% (269/270) (classification)
accuracy =
99.6296
0.0148
0.9851

这里面要说一下返回参数accuracy的三个参数的意义。返回参数accuracy从上到下依次的意义分别是:
分类准率(分类问题中用到的参数指标)
平均平方误差(MSE (mean squared error)) [回归问题中用到的参数指标]
平方相关系数(r2 (squared correlation coefficient))[回归问题中用到的参数指标]

svmpredict

svmpredict函数的使用更加简单,输入就是待测数据的特征矩阵和标签,输出有三个一个是predict_label,预测的测试集的标签,数据类型double;accuracy/mse是一个3*1的列向量,第一个数代表分类准确率(分类问题使用),第二个代表mse(回归问题使用),第三个数表示平方相关系数(回归问题使用)。注意,如果测试集的真实标签事先无法得知,则这个返回值没有意义。实际上我们真实做预测的时候,标签本来就是应该没有的,如果我们事先都知道的话,预测标签就没有意义了。之所以要用标签,就是为了测试我们训练得到的模型去做预测时效果好不好,这个返回值就是为了验证用的。一旦我们知道了我们的模型是可靠地,我们就可以真正用它来做预测了,那么这个返回值就没有任何意义了。另外需要说明的是,标签只是我们用来表示某个类别的一个符号而已,不具有真实的数据意义,只是我们要知道,这个数据代表的是哪一类。

数据归一化

归一化化就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。首先归一化是为了后面数据处理的方便,其次是保正程序运行时收敛加快。为什么要用归一化呢?首先先说一个概念,叫做奇异样本数据,所谓奇异样本数据数据指的是相对于其他输入样本特别大或特别小的样本矢量。下面举例:

m=[0.11 0.15 0.32 0.45 30;
      0.13 0.24 0.27 0.25 45];

其中的第五列数据相对于其他4列数据就可以成为奇异样本数据(下面所说的网络均值bp)。奇异样本数据存在所引起的网络训练时间增加,并可能引起网络无法收敛,所以对于训练样本存在奇异样本数据的数据集在训练之前,最好先进形归一化,若不存在奇异样本数据,则不需要事先归一化。是否一定要做归一化这个预处理才能提高最后的分类准确率呢?答案是否定的。并不是任何问题都必须要进行归一化预处理,要具体问题具体分析,进行试验测试表明,有时归一化后的预测准确率要比没有归一化的低好多,而且不同的归一化方式对最后的准确率也会有一定的影响。还要强调一点就是训练集是如何归一化的测试集也要如何归一化。

不同的归一化方式对最后的准确 率也会有一定的影响。但是否一定 要做归一化这个预处理才能提高最后的准确率呢?答案是否定的。并不是任何问题都必须事 先把原始数据进行归一化,要具体问题具体看待,测试表明有时候归一化后的预测准确率比没有归一化的预测准确率会低很多。

参数寻优

这里的参数是SVMtrain训练模型的参数,参数找的好,模型训练的就好,可以提高后面预测分类的准确率。不同的SVM类型需要寻优的参数不同。然后利用最优参数去训练模型model,得到模型后就可以利用svmpredict函数进行使用预测了。

关于SVM参数的优化选取,国际上并没有公认统一的最好的方法,现在目前常用的方法就是让c和g在一定的范围内取值,对于取定的c和g对于把训练集作为原始数据集利用K-CV方法得到在此组c和g下训练集验证分类准确率,最终取使得训练集验证分类准确率最高的那组c和g做为最佳的参数,但有一个问题就是可能会有多组的c和g对应于最高的验证分类准确率,这种情况怎么处理?这里采用的手段是选取能够达到最高验证分类准确率中参数c最小的那组c和g做为最佳的参数,如果对应最小的c有多组g,就选取搜索到的第一组c和g做为最佳的参数。这样做的理由是:过高的c会导致过学习状态发生,即训练集分类准确率很高而测试集分类准确率很低(分类器的泛化能力降低),因为过高的惩罚因子说明我们非常重视,所以在能够达到最高验证分类准确率中的所有的成对的c和g中认为较小的惩罚参数c是更佳的选择对象。当然,你也可以同时记录下多组c和g,在后面对测试集进行预测时可以分别使用这些参数,看最后的结果如何,再进行选择。
具体的寻优思路请看:https://blog.csdn.net/hellocsz/article/details/81206703

采用 CV 的方法,在没有测试集标签的情况下可以找到一定意义下的最佳的参数 c 和 g.这里说的“一定意义下”指的是此时的最佳参数 c和 g是使得训练集在 CV思想下能够达到最 高分类准确率的参 数,但其不能保证会使得测试集也达到最高的分类准确率 。

实例1

这个例子里,测试数据为一元函数,y=f(x)形式。

clc
clear all
close all
%%
% 生成待回归的数据
x = (-1:0.1:1)';
y = -100*x.^3 + x.^2 - x + 1;
% 增加噪声
y = y+ 20*rand(length(y),1);
figure;
plot(x,y,'o');

%% 最优参数选择
mse = 10^7;
for log2c = -10:0.5:3
    for log2g = -10:0.5:3
        % -v 交叉验证参数:在训练的时候需要,测试的时候不需要,否则出错
        options = ['-v 3 -c ', num2str(2^log2c), ' -g ', num2str(2^log2g) , ' -s 3 -p 0.4 -t 3'];
        cv = svmtrain(y,x,options);
        if (cv < mse)
            mse = cv; bestc = 2^log2c; bestg = 2^log2g;
        end
    end
end
%%  训练
options = ['-c ', num2str(2^bestc), ' -g ', num2str(2^bestg) , ' -s 3 -p 0.4 -n 0.1'];
model = svmtrain(y,x,options)
% model
% 利用建立的模型看其在训练集合上的回归效果
[py,accuracy,dv] = svmpredict(y,x,model);

hold on;
plot(x,py,'g+');
%% 
% 进行预测新的x值
%-- 产生[-1 1]的随机数
testx = -2+(2-(-2))*rand(10,1);
testy = zeros(10,1);% 理论y值无所谓
[ptesty,~,~] = svmpredict(testy,testx,model);
hold on;
plot(testx,ptesty,'r*');
legend('原始数据','回归数据','新数据');
grid on;
% title('t=0:线性核')
% title('t=1:多项式核')
% title('t=2:径向基函数(高斯)')
title('t=3:sigmod核函数')

这里的回归实验采用了一维数据,下面将进行多元数据回归分析。

实例2 多元函数回归

这个例子里,测试数据为多元函数,g=f(x,y,z,l)形式。假设我们有一组数据,x,y,z,l和相应的g数据,但是其函数形式未知,如何使用LIBSVM根据x,y,z,l反演g的数据呢?
假设二手奥迪A8价格price(万)与其使用年限years、里程miles(km)、有无事故(0 无 1有)有关,下面的例子就根据这些属性反演A8的价格。由于样本较少,反演效果一般。

clc
clear all
close all
%% 假设二手奥迪A8价格price(万)与其使用年限years、里程miles(km)、有无事故(0 无 1有)
price = [120; 110; 105; 80; 75; 71; 60; 56; 55; 50; 42; 40; 38; 35; 25];
proper = [0 0 0; 1 1 0; 1 5 0; 1 5 1;...
          2 10 0; 2 10 1; 2 20 0; 2 20 1;...
          3 30 0; 3 30 1; 3 40 0; 3 40 1;...
          4 54 0; 4 60 0; 5 70 1]

%% 最优参数选择
mse = 10^7;
for log2c = -10:0.5:3
    for log2g = -10:0.5:3
        % -v 交叉验证参数:在训练的时候需要,测试的时候不需要,否则出错
        options = ['-v 3 -c ', num2str(2^log2c), ' -g ', num2str(2^log2g) , ' -s 3 -p 0.4 -t 3'];
        cv = svmtrain(price,proper,options);
        if (cv < mse)
            mse = cv; bestc = 2^log2c; bestg = 2^log2g;
        end
    end
end
%%  训练
options = ['-c ', num2str(2^bestc), ' -g ', num2str(2^bestg) , ' -s 3 -p 0.4 -n 0.1'];
model = svmtrain(price,proper,options)
% model
% 利用建立的模型看其在训练集合上的回归效果
[predict_p,accuracy,dv] = svmpredict(price,proper,model);
figure
plot(price,'o')
hold on
plot(predict_p,'.')
test_proper = [4 60 0]
test_price = 0; %这个随便给不影响预测的价格,但是会基于这个值计算预测准确率。
[predict_t,accuracy_t,dv_t] = svmpredict(test_price,test_proper,model);
hold on
plot(predict_t,'*')
legend('原始价格','回归价格','新数据预测价格');

警告类型

WARNING: using -h 0 may be faster
*
optimization finished, #iter = 4078
obj = -10295.123752, rho = 65.395952
nSV = 3917, nBSV = 3915

解释:h参数的描述如下:
-h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)

这是一个limsvm缩小启发式的警告,缩小的启发式是为了加速优化。

迭代次数达到了上限,却没有达到收敛条件,所以训练结果可能会很差。

输出信息含义

// obj为SVM文件转换为的二次规划求解得到的最小值,rho为判决函数的偏置项

optimization finished, #iter = 7327    //iter为迭代次数
nu = 0.940297                    	   //nu是你选择的核函数类型的参数
obj = -2153154.192497, rho = 63.164656 //obj为SVM文件转换为的二次规划求解得到的最小值,rho为判决函数的偏置项
nSV = 883, nBSV = 780                  // nSV为标准支持向量个数,nBSV为边界上的支持向量个数(a[i]=c)

引用
https://blog.csdn.net/on2way/article/details/47733861
http://blog.sina.com.cn/s/blog_6646924501018fqc.html

  • 30
    点赞
  • 148
    收藏
  • 打赏
    打赏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 20

打赏作者

大作家佚名

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值