【问题标题】:How to split a data into k-folds NOT randomly in matlab?如何在matlab中将数据拆分为k-folds而不是随机的?
【发布时间】:2013-11-05 10:48:00
【问题描述】:

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

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

fold1:火车 = 1:250;测试= 251:1000
fold2:train = 251:500, test = [1:250 ; 501:1000]
fold3:训练 = 501:750,测试 = [1:500; 751:1000]
fold4:训练 = 751:1000,测试 = 1:750

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

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


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

【问题讨论】:

  • 我假设你知道这一点,但如果唯一的目标是完全可重复的工作,我建议在随机化样本之前设置 rng 来初始化你的随机生成器。

标签: matlab statistics cross-validation


【解决方案1】:

这是一个通用的函数:

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 循环中包含第一次迭代?
  • 只是少考虑不这样做,因为train 集合除了第一次之外总是不相交的。嗯,虽然我猜也不是最后一次 :/ 如果你可以将它编辑到循环中,那么请这样做:)
【解决方案2】:

假设您有k*n smaples,您想将其划分为k 折叠,其中n 训练中的样本和(k-1)*n 在测试中(在您的问题中k = 4n = 250)。
那么

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

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

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

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

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

【讨论】:

    【解决方案3】:

    要将数据集划分为长度为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].';
    

    对于折叠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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-21
      相关资源
      最近更新 更多