如何在matlab中将数据非随机地分割成k折?

问题描述 投票:0回答:4

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

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

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

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

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


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

matlab statistics cross-validation
4个回答
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 矩阵上工作并输出实际的集合而不是索引。


3
投票

假设您有

k*n
样本,想要将其划分为
k
折叠,训练中的
n
样本和测试中的
(k-1)*n
样本(在您的问题中
k = 4
n = 250
)。
然后

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

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

对于折叠

f
,您可以使用

获取训练和测试样本的索引
 >> trainIdx = find( foldId == f );
 >> testIdx  = find( foldId ~= f );

(您可以使用逻辑索引代替

find
并加快速度)。


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
是一个结构数组,其中字段
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

0
投票

自 Matlab 2023 起,您现在可以使用自定义 cvpartition。例如,来自 Matlab 文档:

c = cvpartition("CustomPartition",[1 2 2 1 3 3 1 2 3 2]) 表示 3 倍交叉验证方案,第一个测试集中有第一个、第四个和第七个观察值。

c = cvpartition("CustomPartition",[true false true false false]) 表示保留验证方案,其中第一个和第三个观测值位于测试集中。

您可以使用

kron( 1:k, ones(1,n) )
生成数字向量,如 Shai 的答案所示,其中 k 是折叠数,n 是每个折叠中的样本数。

https://uk.mathworks.com/help/stats/cvpartition.html

© www.soinside.com 2019 - 2024. All rights reserved.