【问题标题】:Retraining after Cross Validation with libsvm使用 libsvm 进行交叉验证后重新训练
【发布时间】:2012-02-21 06:40:49
【问题描述】:

我知道交叉验证用于选择好的参数。找到它们后,我需要在没有 -v 选项的情况下重新训练整个数据。

但我面临的问题是,在我使用 -v 选项进行训练后,我得到了交叉验证的准确率(例如 85%)。没有模型,我看不到 C 和 gamma 的值。这种情况下我该如何重新训练?

顺便说一句,我应用了 10 折交叉验证。 例如

optimization finished, #iter = 138
nu = 0.612233
obj = -90.291046, rho = -0.367013
nSV = 165, nBSV = 128
Total nSV = 165
Cross Validation Accuracy = 98.1273%

需要一些帮助..

为了获得最好的 C 和 gamma,我使用了 LIBSVM 常见问题解答中提供的这段代码

bestcv = 0;
for log2c = -6:10,
  for log2g = -6:3,
    cmd = ['-v 5 -c ', num2str(2^log2c), ' -g ', num2str(2^log2g)];
    cv = svmtrain(TrainLabel,TrainVec, cmd);
    if (cv >= bestcv),
      bestcv = cv; bestc = 2^log2c; bestg = 2^log2g;
    end
    fprintf('(best c=%g, g=%g, rate=%g)\n',bestc, bestg, bestcv);
  end
end

另一个问题:使用 -v 选项后的交叉验证准确性是否类似于我们在没有 -v 选项的情况下进行训练并使用该模型进行预测时得到的准确性?两者的准确率相似吗?

另一个问题:交叉验证通过避免过度拟合,基本上提高了模型的准确性。因此,在改进之前,它需要有一个模型。我对吗?除此之外,如果我有不同的模型,那么交叉验证的准确性会有所不同吗?我说的对吗?

还有一个问题:在交叉验证准确率中,那么C和gamma的值是多少?

图表是这样的

那么 C 的值为 2 且 gamma = 0.0078125。但是当我用新参数重新训练模型时。该值与 99.63% 不同。有什么理由吗? 提前谢谢...

【问题讨论】:

    标签: matlab machine-learning classification svm libsvm


    【解决方案1】:

    如果您使用整个数据集来确定参数,然后在该数据集上进行训练,您将过度拟合数据。理想情况下,您将划分数据集,对一部分(使用 CV)进行参数搜索,然后使用另一部分使用 CV 进行训练和测试。如果你同时使用整个数据集,你会得到更好的结果吗?当然,但是您的模型可能无法很好地概括。如果要确定模型的真实性能,则需要单独进行参数选择。

    【讨论】:

    • 在最后一个语句中,参数选择是什么意思?你的意思是确定某个部分的参数。
    • 我很抱歉不清楚。参数选择是确定哪些参数最适合您的数据集的行为(实际上,哪些参数最适合数据集的整个域以及您希望能够分类的未来数据。)我最后的陈述只是为了总结我所说的上面 - 单独进行参数选择意味着使用数据集的单独部分来找出最佳参数,然后在训练未使用的部分时使用这些参数。
    • 第二部分:我认为您需要更深入地研究过拟合的概念。这个picture 是一个很好的插图。您的数据永远不会是数据世界的完美代表。构建模型时,您可以创建一个具有 100% 准确度的模型。你不想要那个 - 这就像图片中的绿线。它不能很好地概括,这意味着它会在未来的数据上犯更多的错误。这称为过拟合。这意味着您的模型对训练数据的训练过于严格。
    • 这就是我们将测试数据分开保存的原因 - 神圣。这是我们对数据世界的其他部分可能是什么样子的最佳猜测,我们不想用它来构建我们的模型,因为如果我们这样做,我们将不知道我们的模型是否真的对新数据有任何好处。如果您使用这些数据进行参数搜索,那么您不知道您的分类器是否会准确地处理未来的数据,或者您是否刚刚为这组特定数据找到了完美的参数。
    • 既然你有一个测试和训练集,我会将训练集减半——保持每个类的比例相同,使用前半部分进行参数网格搜索(最好使用 cv) .然后使用这些参数在第二部分训练模型并在测试集上进行测试。
    【解决方案2】:

    这里的-v 选项实际上是为了避免过度拟合问题(而不是使用整个数据进行训练,而是在N-1 折叠上执行 N 折交叉验证训练并在剩余的折叠,一次一个,然后报告平均准确度)。因此,它仅将交叉验证准确度(假设您有分类问题,否则回归的均方误差)作为标量数而不是实际的 SVM 模型返回。

    如果要执行模型选择,则必须使用交叉验证(类似于grid.py 辅助python 脚本)实现网格搜索,以找到C 的最佳值和gamma

    这应该不难实现:使用 MESHGRID 创建一个值网格,迭代所有对 (C,gamma) 使用 5 倍交叉验证训练 SVM 模型,并选择具有最佳 CV 精度的值...

    例子:

    %# read some training data
    [labels,data] = libsvmread('./heart_scale');
    
    %# grid of parameters
    folds = 5;
    [C,gamma] = meshgrid(-5:2:15, -15:2:3);
    
    %# grid search, and cross-validation
    cv_acc = zeros(numel(C),1);
    for i=1:numel(C)
        cv_acc(i) = svmtrain(labels, data, ...
                        sprintf('-c %f -g %f -v %d', 2^C(i), 2^gamma(i), folds));
    end
    
    %# pair (C,gamma) with best accuracy
    [~,idx] = max(cv_acc);
    
    %# contour plot of paramter selection
    contour(C, gamma, reshape(cv_acc,size(C))), colorbar
    hold on
    plot(C(idx), gamma(idx), 'rx')
    text(C(idx), gamma(idx), sprintf('Acc = %.2f %%',cv_acc(idx)), ...
        'HorizontalAlign','left', 'VerticalAlign','top')
    hold off
    xlabel('log_2(C)'), ylabel('log_2(\gamma)'), title('Cross-Validation Accuracy')
    
    %# now you can train you model using best_C and best_gamma
    best_C = 2^C(idx);
    best_gamma = 2^gamma(idx);
    %# ...
    

    【讨论】:

    • 很棒的代码,谢谢...还有一个 qn:准确度值是最佳 c 和 gamma 的位置的点。我说的对吗?
    • @lakesh:正确,请记住该图是使用 log2 比例绘制的(因此这里的最佳值是 C=2^9 和 gamma=2^-11
    • 太棒了...我在上面编辑了我的问题..基本上我添加了一些小问题...想知道你对这些问题的回答。
    • @lakesh:我建议你参考一本合适的机器学习书籍,并阅读更多关于过拟合、训练/测试/验证集、偏差/方差等的内容......(这些主题不是 SVM-具体)
    • @Amro [~,idx] = max(cv_acc);你说。是 -> [C,idx] = max(cv_acc); ?
    猜你喜欢
    • 2014-04-20
    • 2011-12-16
    • 2014-05-01
    • 2016-01-29
    • 2021-12-10
    • 2021-01-19
    • 2018-09-01
    • 2019-05-18
    • 2011-01-25
    相关资源
    最近更新 更多