SVM 回归的交叉验证

Posted

技术标签:

【中文标题】SVM 回归的交叉验证【英文标题】:Cross validation for SVM-regression 【发布时间】:2016-09-30 19:31:41 【问题描述】:

我想执行交叉验证来为 SVR(支持向量回归)的 RBF 内核选择最佳参数 Gamma 和 C。我正在使用 LIBSVM。我有一个包含 4 组 3D 网格的数据库。 我的问题是: 我使用的这种方法可以用于 4 折交叉验证吗?我认为,为了选择 RBF Kernal 的参数 C 和 Gamma,我必须尽量减少预测值和 groud_truth_values 之间的误差。

我还有另一个问题,我得到了一个 NAN 值,而交叉验证(平方相关系数 = nan(回归))

这是我写的代码:

[C,gamma] = meshgrid(-5:2:15, -15:2:3); %range of values for C and 
                                        %gamma

%# grid search, and cross-validation

for m=1:numel(C)

    for k=1:4 
        fid1 = fopen(sprintf('list_learning_%d.txt',k), 'rt'); 
        i=1;

        while feof(fid1) == 0 
            tline = fgetl(fid1); 
            v= load(tline);
            v=normalize(v);
            matrix_feature_tmp(i,:)=v;
            i=i+1;
        end  

        fclose(fid1);

        % I fill matrix_feature_train of size m by n via matrix_feature_tmp

        %%construction of the test matrix
       fid2 = fopen(sprintf('liste_features_test%d.txt',k), 'rt'); 
       i=1;

       while feof(fid2) == 0 
           tline = fgetl(fid2); 
           v= load(tline);
           v=normalize(v);
           matrice_feature_test_tmp(i,:)=v;
           i=i+1;
       end  

       fclose(fid2);

       %I fill matrix_feature_test of size m by k via matrix_feature_test_tmp

       mos_learning=load(sprintf('mos_learning_%d.txt',k));
       mos_wanted=load(sprintf('mos_test%d.txt',k));

       model = svmtrain(mos_learning, matrix_feature_train',sprintf('- 
       s %f -t %f -c %f -g %f -p %f  ',3,2 ,2^C(m),2^gamma(m),1 ));

       [y_hat, Acc, projection] = svmpredict(mos_wanted,
                                  matrix_feature_test', model);
       MSE_Test = mean((y_hat-mos_wanted).^2);
       vecc_error(k)=MSE_Test;

       end
       mean_vec_error_fold(m)=mean(vecc_error);
end

%select the best gamma and C 
[~,idx]=min(mean_vec_error_fold);

best_C = 2^C(idx);
best_gamma = 2^gamma(idx);

%training with best parameters
%for example
 model = svmtrain(mos_learning1, matrice_feature_train1',sprintf('-s   
          %f -t %f -c %f -g %f -p %f  ',3,2 ,best_C, best_gamma,1 ));

[y_hat_final, Acc, projection] = svmpredict(mos_test1,matrice_feature_test1', 
                           model);

【问题讨论】:

【参考方案1】:

根据您的描述,没有阅读您的代码,听起来您没有进行交叉验证。交叉验证要求您选择一个参数集(即Cgamma 的值)并保持这些参数不变,使用k-1 折叠训练,1 折叠测试并执行此操作k 次这样您就可以将每个折叠用作测试集一次。然后汇总这些k 测试的错误/准确度度量,这就是您用于对这些参数进行排名的度量对于在所有数据上训练的模型。将此称为您使用的参数集的交叉验证错误。然后,您对一系列不同的参数重复此过程,并选择具有最佳精度/最低 CV 误差的参数集。您的最终模型是根据您的所有数据进行训练的。

你的代码对我来说真的没有意义。看着这个sn-p

folds = 4; 
for i=1:numel(C)
    cv_acc(i) = svmtrain(ground_truth, matrice_feature_train', ...
                sprintf(' -s %d -t %d -c %f -g %f -p %d -v %d',3,2, 
                2^C(i), 2^gamma(i), 1, 4)); %Kernel RBF
end

cv_acc 包含什么?对我来说,它包含实际的 SVM 模型(如果您使用 MATLAB 工具箱,则为 SVMStruct,如果您使用 LIBSVM,则为其他内容)。如果您使用循环来更改将哪些折叠用作训练集,这将是可以的。但是,您使用它们来更改 gammaC 参数的值,这是不正确的。但是你后来打电话给min(cv_acc); 所以我现在猜测你认为对smvtrain 的调用实际上返回了训练错误?我看不出你怎么能在这样的结构数组上有意义地调用min,但我可能是错的。但即便如此,您实际上对最小化您的训练错误并不感兴趣,您希望最小化您的交叉验证错误,这是您的 k 运行中 test 错误的总和,没有什么可做的处理您的培训错误。

现在实际上不可能知道你是否做错了,因为你没有向我们展示gammaC 的向量,但是只有一个循环而不是一个嵌套循环来迭代很奇怪这些(除非您像真值表一样安排它们,但我对此表示怀疑)。您需要测试C 的每个潜在值与gamma 的每个值配对。目前,您似乎只为 C 中的每个值尝试了 1 个不同的 gamma 值。

查看this answer 以查看与 SVM 一起使用的交叉验证示例。

【讨论】:

嗨,1)我在我的帖子中指定 SVMTRAIN 的调用返回均方误差而不是结构模型(请注意,我使用选项 -V 调用 SVTMTRAIN)。所以,我认为 min(cv_acc) 的使用是正确的,因为向量 cv_acc 包含与每对(C,gamma)相关的错误。 2)我必须使用嵌套循环来更改折叠。我会编辑。 3)我猜我必须尽量减少交叉验证的错误,以便以后选择最佳参数? @Anass 如果是训练错误它仍然是错误的,你不在乎哪个参数集给你最好的训练错误,你关心的是交叉验证错误。因此,您训练 3 次,返回 SVM 模型,使用该模型在第 4 次进行预测,计算 MSE,执行 4 次,聚合错误,该聚合是您的 交叉验证 错误对于该参数集。然后,您对要测试的所有参数组合重复此操作,并且只有 然后您才关心每个参数组合的交叉验证误差的最小值。 好的,谢谢。我会试试这个并编辑我的帖子以显示结果

以上是关于SVM 回归的交叉验证的主要内容,如果未能解决你的问题,请参考以下文章

在 R 中使用插入符号进行交叉验证的 SVM

如何进行交叉验证 SVM 分类器

使用 Joaquim 的 SVM 光进行 3 折交叉验证

带有交叉验证的 SVM 分类

MATLAB 支持向量机 (SVM) 交叉验证实现以提高代码速度

字符串python列表上的Kfold交叉验证和SVM