如何使用libsvm进行回归预测
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用libsvm进行回归预测相关的知识,希望对你有一定的参考价值。
参考技术A <1> 下载Libsvm、Python和Gnuplot。我用的版本分别是:Libsvm(2.8.1),Python(2.4),Gnuplot(3.7.3)。注意:Gnuplot一定要用3.7.3版,3.7.1版的有bug.<2> 修改训练和测试数据的格式(可以自己用perl编个小程序):
目标值 第一维特征编号:第一维特征值 第二维特征编号:第二维特征值 ...
...
例如:
2.3 1:5.6 2:3.2
表示训练用的特征有两维,第一维是5.6,第二维是3.2,目标值是2.3
注意:训练和测试数据的格式必须相同,都如上所示。测试数据中的目标值是为了计算误差用
<3> 分别使用Libsvm中的Windows版本的工具svmscale.exe进行训练和测试数据的归一化,svmtrain.exe进行模型训练,svmpredict.exe进行预测
(1)svmscale.exe的用法:svmscale.exe feature.txt feature.scaled
默认的归一化范围是[-1,1],可以用参数-l和-u分别调整上界和下届,feature.txt是输入特征文件名
输出的归一化特征名为feature.scaled
(2)svmtrtrain.exe训练模型
我习惯写个批处理小程序,处理起来比较方便。例如svm_train.bat中训练语句为:
svmtrain.exe -s 3 -p 0.0001 -t 2 -g 32 -c 0.53125 -n 0.99 feature.scaled
训练得到的模型为feature.scaled.model
具 体的参数含义可以参考帮助文档。这里-s是选择SVM的类型。对于回归来说,只能选3或者4,3表示epsilon-support vector regression, 4表示nu-support vector regression。-t是选择核函数,通常选用RBF核函数,原因在“A Practical Guide support vector classification”中已经简单介绍过了。-p尽量选个比较小的数字。需要仔细调整的重要参数是-c和-g。除非用 gridregression.py来搜索最优参数,否则只能自己慢慢试了。
用gridregression.py搜索最优参数的方法如下:
python.exe gridregression.py -svmtrain H:/SVM/libsvm-2.81/windows/svmtrain.exe -gnuplot C:/gp373w32/pgnuplot.exe -log2c -10,10,1 -log2g -10,10,1 -log2p -10,10,1 -v 10 -s 3 -t 2 H:/SVM/libsvm-2.81/windows/feature.scaled > gridregression_feature.parameter
注意:-svmtrain是给出svmtrain.exe所在路径,一定要是完整的全路径
-gnuplot是给出pgnuplot.exe所在路径。这里要用pgnuplot.exe这种命令行形式的,不要用wgnupl32.exe,这个是图形界面的。
-log2c是给出参数c的范围和步长
-log2g是给出参数g的范围和步长
-log2p是给出参数p的范围和步长
上面三个参数可以用默认范围和步长
-s选择SVM类型,也是只能选3或者4
-t是选择核函数
-v 10 将训练数据分成10份做交叉验证。默认为5
最后给出归一化后训练数据的全路径
搜索最优参数的过程写入文件gridregression_feature.parameter(注意别少了这个>符号啊)
根据搜索到的最优参数修改feature.scaled.model中的参数
(3)用svmpredict.exe进行预测
svmpredict.exe feature_test.scaled feature.scaled.model feature_test.predicted
其中feature_test.scaled是归一化后的测试特征文件名,feature.scaled.model是训练好的模型,SVM预测的值在feature_test.predicted中。
如何转成libsvm支持的数据格式并做回归分析
本次实验的数据是来自老师给的2006-2008年的日期,24小时的温度、电力负荷数据,以及2009年的日期,24小时的温度数据,目的是预测2009年每天24小时的电力负荷,实验数据本文不予给出。
用libsvm进行预测的步骤大体是:将数据进行归一化处理,并转换成livsvm需要的格式,然后进行参数择优,用选的最佳参数使用2006-2008 3年的数据建立模型,再用该模型预测2009年的电力负荷。实际过程中,我先用2006-2007年的数据建模,预测2008年的数据,以得到测试误差。事实证明,用2006-2007 两年的数据建模来预测2008年的电力负荷,效果要比单用2007年的数据建模预测2008年的电力负荷的效果好。所以最终我是用2006-2008 三年的数据进行建模,来预测。
libsvm训练模型时,设置的参数有:
-s SVM类型,取值有 0,1,2,3,4 回归的话选3或4.
-t 核函数类型,取值有0,1,2,3 0是线性核函数,1是多项式核函数,2是RBF径向基核函数,3是sigmoid 核函数。
-g gamma,这是针对多项式、RBF、sigmoid 核函数才有的参数选项。默认是1/k,k是属性数/类别数。
-c 为 c-SVC、e-SVR 和 nu-SVR 设置的损失函数,默认为1.
详细的参数描述见 LIBSVM使用方法及参数设置(转)。
下面是进行回归预测的步骤:
1.将数据转换成libsvm需要的格式
数据格式需要:
target属性 | 第1个属性:值 | 第2个属性:值 | … |
---|---|---|---|
2 | 1:7 | 2:5 | … |
1 | 1:4 | 2:2 | … |
即如果是分类问题的话,第一列是类别属性。
在网上下载一个 write4libsvm.m 格式转换程序,在matlab中直接运行,然后选择需要转换的数据文件即可,非常简便易用。
write4libsvm.m
function write4libsvm % 为了使得数据满足libsvm的格式要求而进行的数据格式转换 注意原始格式是mat的数据格式,转化成txt或者dat都可以。 % 原始数据保存格式为: % [标签 第一个属性值 第二个属性值...] % 转换后文件格式为满足libsvm的格式要求,即: % [标签 1:第一个属性值 2:第二个属性值 3:第三个属性值 ...] % [email protected] % 2004.6.16 [filename, pathname] = uigetfile( {‘*.mat‘, ... ‘数据文件(*.mat)‘; ... ‘*.*‘, ‘所有文件 (*.*)‘}, ... ‘选择数据文件‘); try S=load([pathname filename]); fieldName = fieldnames(S); str = cell2mat(fieldName); B = getfield(S,str); [m,n] = size(B); [filename, pathname] = uiputfile({‘*.txt;*.dat‘ ,‘数据文件(*.txt;*.dat)‘;‘*.*‘,‘所有文件 (*.*)‘},‘保存数据文件‘); fid = fopen([pathname filename],‘w‘); if(fid~=-1) for k=1:m fprintf(fid,‘%3d‘,B(k,1)); for kk = 2:n fprintf(fid,‘\t%d‘,(kk-1)); fprintf(fid,‘:‘); fprintf(fid,‘%d‘,B(k,kk)); end k fprintf(fid,‘\n‘); end fclose(fid); else msgbox(‘无法保存文件!‘); end catch end
2. 选择核函数类型
我选择的是RBF核函数。
2.将数据做归一化处理
不做归一化处理的话,最后预测误差会很大。
通过程序对属性进行归一化处理。一开始我并没有做归一化处理,结果测试误差MAPE达14%,做属性归一化处理后,测试数据的MAPE是3.9556% 。
clear; load(‘X1.mat‘);% X1.mat 是训练集。 load(‘X2.mat‘);% X2.mat 是测试集。 X1_1 =normalization(X1); X2_1 =normalization(X2); %另存为X1_1.mat X2_1.mat 然后运行 **write4libsvm.m** 转成符合需要的格式的文件 X1_1.csv 和 X2_1.csv。 %进入D:\softwares_diy\MATLAB\R2014a\toolbox\libsvm-3.21目录,将D:\softwares_diy\MATLAB\R2014a\toolbox\libsvm-3.21\matlab添加到路径 [Y1, X1] = libsvmread(‘X1_1.csv‘);% Y1 X1 是2006-2008年的数据。 [Y2, X2] = libsvmread(‘X2_1.csv‘);%Y2 X2 是2009年的数据。 Y1_train = Y1(1:17520,:); %06-07年的数据做训练 X1_train = X1(1:17520,:); Y1_test = Y1(17521:end,:);%08年的数据做测试 X1_test = X1(17521:end,:);
3.参数寻优
需调整的重要参数是 -c 和 -g。 -c指定损失函数,-g是针对多项式、RBF、sigmoid核函数的γ值设置。
我用程序 SVM.cg.m 通过指定c的变化范围和g的变化范围来寻找最优的参数c和g。
这是 预测代码:
%寻找最优的 c 和 g result1 = []; % 06-07年的数据训练,08年的数据做测试。 %SVMcg(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,accstep) %参数 c的变化范围是 [2^cmin,2^cmax] %参数g的变化范围是[2^gmin,2^gmax] %cstep是c的变化步长,gstep是g的变化步长。 [bestacc,bestc,bestg] = SVMcg(Y1_train,X1_train,0,8,-1,4,2,1,1,0.9); %跑了很久才出来 cmd = [‘-s 3 -t 2‘,‘ -c ‘,num2str(bestc),‘ -g ‘,num2str(bestg)]; model = libsvmtrain(Y1_train, X1_train, cmd); [y_08_pre,mse,decision_values] = libsvmpredict(Y1_test,X1_test,model); MAPE = mean(abs(y_test_pre-Y1_test)./Y1_test);%计算08年的MAPE RMSE = sqrt(mean((y_test_pre-Y1_test).^2)); MAE = mean(abs(y_test_pre-Y1_test)); MSE = mean((y_test_pre-Y1_test).^2); clear model cmd y_test_pre mse decision_values MAPE RMSE MAE MSE bestacc bestc bestg; %06-08年的数据做训练,09年测试。 [bestacc,bestc,bestg] = SVMcg(Y1,X1,0,8,-1,4,2,1,1,0.9); cmd = [‘-s 3 -t 2‘,‘ -c ‘,num2str(bestc),‘ -g ‘,num2str(bestg)]; model = libsvmtrain(Y1, X1, cmd); [y_09_pre,mse,decision_values] = libsvmpredict(Y2,X2,model);
其中 y_09_pre 是预测的 2009年每天24小时的电力负荷,由于并没有2009年电力负荷的真实值,所以忽略libsvmpredict的返回值mse。
SVM.cg.m
function [bestacc,bestc,bestg] = SVMcg(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,accstep) %SVMcg cross validation by faruto %Email:[email protected] QQ:516667408 http://blog.sina.com.cn/faruto BNU %last modified 2009.8.23 %Super Moderator @ www.ilovematlab.cn %% about the parameters of SVMcg if nargin < 10 accstep = 1.5; end if nargin < 8 accstep = 1.5; cstep = 1; gstep = 1; end if nargin < 7 accstep = 1.5; v = 3; cstep = 1; gstep = 1; end if nargin < 6 accstep = 1.5; v = 3; cstep = 1; gstep = 1; gmax = 5; end if nargin < 5 accstep = 1.5; v = 3; cstep = 1; gstep = 1; gmax = 5; gmin = -5; end if nargin < 4 accstep = 1.5; v = 3; cstep = 1; gstep = 1; gmax = 5; gmin = -5; cmax = 5; end if nargin < 3 accstep = 1.5; v = 3; cstep = 1; gstep = 1; gmax = 5; gmin = -5; cmax = 5; cmin = -5; end %% X:c Y:g cg:acc [X,Y] = meshgrid(cmin:cstep:cmax,gmin:gstep:gmax); [m,n] = size(X); cg = zeros(m,n); %% record acc with different c & g,and find the bestacc with the smallest c bestc = 0; bestg = 0; bestacc = 0; basenum = 2; for i = 1:m for j = 1:n cmd = [‘-v ‘,num2str(v),‘ -c ‘,num2str( basenum^X(i,j) ),‘ -g ‘,num2str( basenum^Y(i,j) )]; cg(i,j) = libsvmtrain(train_label, train, cmd); if cg(i,j) > bestacc bestacc = cg(i,j); bestc = basenum^X(i,j); bestg = basenum^Y(i,j); end if ( cg(i,j) == bestacc && bestc > basenum^X(i,j) ) bestacc = cg(i,j); bestc = basenum^X(i,j); bestg = basenum^Y(i,j); end end end %% to draw the acc with different c & g [C,h] = contour(X,Y,cg,60:accstep:100); clabel(C,h,‘FontSize‘,10,‘Color‘,‘r‘); xlabel(‘log2c‘,‘FontSize‘,10); ylabel(‘log2g‘,‘FontSize‘,10); grid on;
以上是关于如何使用libsvm进行回归预测的主要内容,如果未能解决你的问题,请参考以下文章
转自网络用LIBSVM进行回归预测的粗浅认识————————作者师梦
Matlab 中的 Libsvm 回归预测测试集实例的相同值