用于Matlab的LibSVM - 结果不稳定

时间:2017-10-05 11:43:48

标签: matlab svm libsvm

我在x64 PC上使用LINBS R2016a上的LIBSvm 3.22(但我已经用R2017a进行了测试),并且在我的代码中找到了奇怪的行为。

我使用的是预计算机内核(68x68,对称,在对角线上全零)。

这是我的代码:

    %
    clear all

    % 
    % 
    E1=load('..\sani_bi.mat');
    addpath('..\libsvm-3.22\windows\');
D=E1.Error_fro_sym
D=D+D'
labels=[zeros(34,1);ones(size(D,1)-34,1)]';
results = [];
GACC=[];
dec_values_p = [];
models=[];
rbfKernel = @(Gamma) exp(-Gamma .* D);
for C = 25:27%21:30 
    for Gamma = -1.75:.01:1%-50:.01:25
        eC= 2^C;
        eG=2^Gamma;
        K =  [rbfKernel(eG)];
        szK=size(K,1);
        u_param = ['-c ' num2str(eC) ' -t 4 -q'];
        for i = 1: szK
            %
            ind=[1:i-1, i+1:szK];
            model = svmtrain(labels(ind)',[(1:szK-1)', K(ind,ind)],u_param);
            [predict_label, accuracy, dec_values] = svmpredict(labels(i),K(i,ind), model);
            dec_values_p=[dec_values_p; dec_values];
            results = [results; accuracy(1)/100];
            %disp([i accuracy(1)/100]);
        end
        value=sum(results)/szK;
        disp(value);
        GACC=[GACC; value, C, Gamma,sum(dec_values_p)/szK];
        results = [];
        dec_values_p = [];
    end
end
E=sortrows(GACC,[1]);
save('GACC')
%%
clear all

E1=load('..\sani_bi.mat');
E2=load('.\GACC.mat');
GACC=E2.GACC;
addpath('..\libsvm-3.22\windows\');
D=E1.Error_fro_sym
D=D+D'
labels=[zeros(34,1);ones(size(D,1)-34,1)]';
results = [];
GACC1=[];
dec_values_p = [];
models=[];
rbfKernel = @(Gamma) exp(-Gamma .* D);
for C = 25:27%21:30
    for Gamma = -1.75:.01:1%-50:.01:25
        eC= 2^C;
        eG=2^Gamma;
        K =  [rbfKernel(eG)];
        szK=size(K,1);
        u_param = ['-c ' num2str(eC) ' -t 4 -q'];
        for i = 1: szK
            %
            ind=[1:i-1, i+1:szK];
            model = svmtrain(labels(ind)',[(1:szK-1)', K(ind,ind)],u_param);
            [predict_label, accuracy, dec_values] = svmpredict(labels(i),K(i,ind), model);
            dec_values_p=[dec_values_p; dec_values];
            results = [results; accuracy(1)/100];
            %disp([i accuracy(1)/100]);
        end
        value=sum(results)/szK;
        disp(value);
        GACC1=[GACC1; value, C, Gamma,sum(dec_values_p)/szK];
        results = [];
        dec_values_p = [];
    end
end


GACC(GACC(:,4) ~= GACC1(:,4),:)

正如你所看到的,我做了两次同样的事情。但是,并不总是最后一个命令返回相同的东西。 有时候还可以:GACC == GACC1 ad,它已退回

ans =

Empty matrix: 0-by-4

但有时会返回一些内容,并观察我能看到的两个矩阵(例如):

GACC=
0,500000000000000   27  0,970000000000000   -0,418026223801469
0,500000000000000   27  0,980000000000000   -0,418081551411518
0,500000000000000   27  0,990000000000000   -0,418132655182850
0,500000000000000   27  1   -0,418184269051726

 GACC1=
 0,500000000000000  27  0,970000000000000   -0,233717714208454
 0,500000000000000  27  0,980000000000000   -0,233752196783965
 0,500000000000000  27  0,990000000000000   -0,233784292330333
 0,500000000000000  27  1   -0,233816355641198

刚刚再次跑步,我获得了:

GACC=
0,500000000000000   27  0,970000000000000   159857,292875661  
0,500000000000000   27  0,980000000000000   159875,372503753
0,500000000000000   27  0,990000000000000   159891,859001955
0,500000000000000   27  1   159908,815885524    

GACC1=
0,220588235294118   27  0,970000000000000   -0,0149253624535754
0,220588235294118   27  0,980000000000000   -0,0149350999202524
0,205882352941176   27  0,990000000000000   -0,0149446308316416
0,205882352941176   27  1   -0,0149534857047891

经过一段时间后,它会回到第一个结果(没有发现差异)

我无法弄清楚为什么会这样。在我的调试过程中,我发现问题可能在"预测"方法,看起来有时dec_value可以发散并且有时收敛,但是在LIBSvm源中我找不到任何种子\随机初始化,并且代码看起来是确定性的(即没有随机启动或其他的优化)。 / p>

可能是内核矩阵的问题(可能是精度问题?)? K看起来像这样(对角线显然都是1因为已被取幂):

1                           2,54073447948936e-11    4,23480527542159e-12
2,54073447948936e-11        1                       8,81718110217103e-12
4,23480527542159e-12        8,81718110217103e-12    1

感谢您的支持!

1 个答案:

答案 0 :(得分:0)

libSVM使用'C'随机数生成器(rand()函数)在svm_binary_svc_probability和svm_cross_validation函数中进行数据混洗。

见svm.cpp:

Line 1906:      int j = i+rand()%(prob->l-i);
Line 2371:              int j = i+rand()%(count[c]-i);
Line 2408:          int j = i+rand()%(l-i); 

因此,您需要修改源代码并重新编译libSVM以获得稳定的结果。

您还可以使用-rnd选项(https://github.com/agdavydov81/antennaarray/tree/master/voice-noise-music/matlab/thirdpart/libsvm/src)尝试我的libSVM 3.2.1 fork。在这种情况下,请对任何libSVM函数使用lib前缀:例如libsvmtrain代替svmtrain