使用libsvm进行交叉验证后的重新训练

18

我知道交叉验证用于选择好的参数。在找到它们之后,我需要重新训练整个数据但不使用-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 FAQ中提供的代码。

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的值是多少?

图表如下 enter image description here

然后C的值为2,gamma=0.0078125。但是当我用新参数重新训练模型时,这个值与99.63%不同。可能有什么原因吗? 提前感谢...

2个回答

32
这里的-v选项的真正用途是为了避免过拟合问题(而不是使用整个数据进行训练),它通过对N-1个折叠进行N次交叉验证训练并在剩余的一个折叠上测试,然后逐个报告平均精度来返回交叉验证精度(假设您有一个分类问题,否则是回归问题的均方误差)作为标量数值,而不是实际的SVM模型。
如果要执行模型选择,则必须使用交叉验证实现网格搜索(类似于helper python脚本grid.py),以找到最佳的Cgamma值。
这应该很容易实现:使用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);
%# ...

等高线图


2
@lakesh:没错,只要记住图表是用log2比例尺绘制的(因此最佳值为C=2^9和gamma=2^-11)。 - Amro
太棒了...我编辑了我的问题,基本上我添加了几个小问题...想知道你对这些问题的答案。 - lakshmen
@Amro,你说的是[C,idx] = max(cv_acc)吗? - kamaci
@kamaci:不,我只是获取对应于最高准确度的索引。要获取实际值,请使用:C(idx)gamma(idx) - Amro
@Amro 我是Matlab的新手,我使用的版本是7.7.0,它显示无效语法。你的意思是我应该写其他内容,因为我不会使用那个变量吗? - kamaci
显示剩余5条评论

2

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


在最后一句话中,您所说的参数选择是什么意思?您是指在某个部分确定参数吗? - lakshmen
1
我为表述不清而道歉。参数选择是确定哪些参数最适合您的数据集(实际上是最适合数据集整个领域和未来要分类的数据)。我的最后一句话只是总结了我上面说的 - 单独进行参数选择意味着使用数据集的一个单独部分来确定最佳参数,然后在未使用的部分进行训练时使用这些参数。 - karenu
1
第二部分:我认为你需要更深入地了解过拟合的概念。这张图片是一个很好的说明。你的数据永远不会完美地代表数据宇宙。当你建立模型时,你可以创建一个具有100%准确性的模型。但你不想要那个 - 那就像图片中的绿线。它不会很好地推广,意味着它将在未来的数据上犯更多的错误。这就是所谓的过拟合。这意味着你的模型对训练数据过于紧密训练。 - karenu
1
这就是为什么我们将测试数据保持独立和神圣的原因。这是我们对于其余数据宇宙可能看起来像的最佳猜测,我们不想使用它来构建我们的模型,因为如果我们这样做,我们将不知道我们的模型在新数据上是否真正有效。如果您使用此数据进行参数搜索,则无法确定分类器在未来数据上是否准确,或者您是否只是找到了适用于此特定数据集的完美参数。 - karenu
1
由于您有测试集和训练集,我建议将训练集减半 - 在保持每个类的比例相同的情况下,使用前一半进行参数网格搜索(最好使用交叉验证)。然后使用这些参数在第二半上训练模型,并在测试集上进行测试。 - karenu
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接