3

我有一个数据集,为简单起见,假设它有 1000 个样本(每个都是一个向量)。

我想分割我的数据进行交叉验证,训练和测试,而不是随机1,所以例如,如果我想要 4 倍交叉验证,我应该得到:

fold1 : 火车 = 1:250; 测试= 251:1000
fold2:火车= 251:500,测试= [1:250;501:1000]
折叠 3:火车 = 501:750,测试 = [1:500; 751:1000]
fold4:训练 = 751:1000,测试 = 1:750

我知道CVPARTITION,但是 AFAIK - 它随机拆分数据 - 这不是我需要的。

我想我可以为它编写代码,但我想可能有一个我可以使用的函数。


(1) 数据已经洗牌,我需要能够轻松地重现实验。

4

3 回答 3

3

这是一个通常执行此操作的函数:

function [test, train] = kfolds(data, k)

  n = size(data,1);

  test{k,1} = [];
  train{k,1} = [];

  chunk = floor(n/k);

  test{1} = data(1:chunk,:);
  train{1} = data(chunk+1:end,:);

  for f = 2:k
      test{f} = data((f-1)*chunk+1:(f)*chunk,:);
      train{f} = [data(1:(f-1)*chunk,:); data(f*chunk+1:end, :)];
  end
end

它不是一个优雅的 1 衬里,但它相当健壮,不需要k成为样本数量的一个因素,适用于 2D 矩阵并输出实际集合而不是索引。

于 2013-11-05T11:25:54.600 回答
2

假设您有k*n要在训练和测试中使用样本(在您的问题中)划分为k折叠的样本。 然后n(k-1)*nk = 4n = 250

 >> foldId = kron( 1:k, ones(1,n) );

foldId为您提供每个样本所属的训练折叠的索引。

对于折叠f,您可以使用获取训练和测试样本的索引

 >> trainIdx = find( foldId == f );
 >> testIdx  = find( foldId ~= f );

(您可以使用逻辑索引而不是find加快速度)。

于 2013-11-05T11:11:25.087 回答
1

要将数据集划分k为长度的折叠,n您可以使用:

f=arrayfun(@(x)struct('train',x*n+(1:n),'test',setdiff(1:n*k,x*n+(1:n))), 0:k-1);

其中f是一个结构数组,其中包含字段traintest包含相应折叠的索引。例如对于n=5andk=3和 fold 2

>> f(2).train
ans =
     6     7     8     9    10
>> f(2).test
ans =
     1     2     3     4     5    11    12    13    14    15

您甚至可以直接提取数据。假设您的数据是n*k行的二维矩阵

E=arrayfun(...
@(x) struct('train', D(x*n+(1:n),:), ...
            'test',  D(setdiff(1:n*k, x*n+(1:n)),:)), 0:k-1)

说你的数据是

D = [(1:15).^2; (1:15).^3].';

对于 fold 2E包含:

>> E(2).train
ans =
          36         216
          49         343
          64         512
          81         729
         100        1000
>> E(2).test
ans =
           1           1
           4           8
           9          27
          16          64
          25         125
         121        1331
         144        1728
         169        2197
         196        2744
         225        3375
于 2013-11-05T12:04:58.957 回答