如何在Matlab中将数据非随机地分成k个部分?

3
我有一个数据集,为了简单起见,假设它有1000个样本(每个样本是一个向量)。
我想要将我的数据进行交叉验证划分,用于训练和测试,不是随机的1,因此例如,如果我想要4倍交叉验证,则应该得到: 第一折:训练集=1:250;测试集=251:1000
第二折:训练集=251:500,测试集=[1:250; 501:1000]
第三折:训练集=501:750,测试集=[1:500; 751:1000]
第四折:训练集=751:1000,测试集=1:750
我知道 CVPARTITION ,但我认为它是随机划分数据 - 这不是我所需要的。
我想我可以编写代码来完成它,但我想可能有一个我可以使用的函数。
(1)数据已经被洗牌过了,我需要能够轻松地重现实验。

我假设你已经意识到了这一点,但如果唯一的目标是完全可重现的工作,我建议在随机化样本之前设置rng来初始化你的随机生成器。 - Dennis Jaheruddin
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矩阵上工作,并输出实际的集合而不是索引。


似乎对我有用。我不是Matlab专家,能否详细说明为什么您没有在for循环中包括第一次迭代? - amit
这只是考虑较少,因为“train”集除了第一次之外总是不相交的。嗯,尽管我猜最后一次也不相交 :/ 如果您可以将其编辑为在循环中,则请执行:) - Dan

2

假设您有k*n个样本,希望将其分成k折,其中训练集中有n个样本,测试集中有(k-1)*n个样本(在您的问题中,k = 4n = 250)。


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

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

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

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

你可以使用逻辑索引而不是find来提高速度。

1

要将数据集分成长度为nk折,您可以使用:

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

其中f是一个结构体数组,包含字段traintest,分别包含对应折叠的索引。例如对于n=5k=3以及第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].';

对于折叠2,E包含:

>> 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

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