如何在matlab中不随机地将数据拆分为k倍?

如何在matlab中不随机地将数据拆分为k倍?,matlab,statistics,cross-validation,Matlab,Statistics,Cross Validation,我有一个数据集,为了简单起见,假设它有1000个样本(每个样本是一个向量) 我想要分割数据进行交叉验证,用于训练和测试,不是随机的1,因此,例如,如果我想要4倍交叉验证,我应该得到: fold1:列车=1:250;测试=251:1000 fold2:列车=251:500,测试=[1:250;501:1000] fold3:列车=501:750,测试=[1:500;751:1000] 折叠4:列车=751:1000,测试=1:750 我知道,但是AFAIK-它随机分割数据-这不是我需要的 我想我可

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

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

fold1:列车=1:250;测试=251:1000
fold2:列车=251:500,测试=[1:250;501:1000]
fold3:列车=501:750,测试=[1:500;751:1000]
折叠4:列车=751:1000,测试=1:750

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

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



(1) 数据已经被洗牌了,我需要能够很容易地重现实验。

假设你有
k*n
s个样本,你想用
n
样本序列和
(k-1)*n
测试(在你的问题中
k=4
n=250
)将它们分成
k
倍。
然后

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

对于fold
f
,您可以使用

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

(您可以使用逻辑索引而不是
查找
,这样可以加快速度)。

这里有一个函数通常可以实现这一点:

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矩阵上工作,并输出实际集合而不是索引。

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

f=arrayfun(@(x)struct('train',x*n+(1:n),'test',setdiff(1:n*k,x*n+(1:n))), 0:k-1);
其中
f
是一个结构数组,其字段
train
test
包含对应折叠的索引。 例如,对于
n=5
k=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

似乎对我有用。我不是matlab专家,想解释一下为什么不在for循环中包含第一次迭代吗?不这样想只是因为
train
集合总是不相交的,除了第一次。嗯,虽然我猜也不是最后一次了:/如果你可以编辑它进入循环,那么请这样做:)我假设你知道这一点,但如果唯一的目标是完全可复制的工作,我建议在随机样本之前设置
rng
初始化随机生成器。
>> 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