您可以通过计算与累积概率相关的百分位数来设法确定每个类别的数量,然后将每个区间与相关区间相关联。让我们使用这个策略首先创建一个随机数据集,其中正好包含 50% 的 1 类、30% 的 2 类和 20% 的 3 类(并不是说你不必这样做,因为你已经有了这个类矩阵classmat和数据矩阵datamat):
clc; clear all; close all;
% Parameters
c = 3; % number of classes
d = 500; % number of data
o = 30; % number of data for each observation
propd = [0.4, 0.2, 0.4]; % proportions of each class in the original data (size 1xc)
% Generation of fake data
datamat = randi([0,15],o,d); % test data matrix
propd_os = cumsum([0, propd]); propd_os(end) = 1;
randmat = rand(d,1);
classmat = zeros(c,d); % test class matrix
for i=1:c
prctld = prctile(randmat, 100*propd_os); prctld(1) = 0; prctld(end) = 1;
classmat(i,randmat>=prctld(i) & randmat<prctld(i+1)) = 1;
end
% Proportions of the original data
disp(['original data proportions:' sprintf(' %.3f',sum(classmat,2)/d)])
执行时,此代码创建classmat 矩阵并显示该矩阵中每个类的比例:
>>>
original data proportions: 0.400 0.200 0.400
我为您创建了一个脚本,用于将此数据集拆分为与原始数据集相同比例的部分:
%% Splitting parameters
s = 3; % number of parts
props = [0.8, 0.1, 0.1]; % proportions of each splitted datasets (size 1xs)
props_os = cumsum([0, props]); props_os(end) = 1;
randmat = rand(1,d);
splitmat = zeros(s,d); % split matrix (one hot)
for i=1:c
indc = classmat(i,:)==1;
prctls = prctile(randmat(indc), 100*props_os); prctls(1) = 0; prctls(end) = 1;
for j=1:s
inds = randmat>=prctls(j) & randmat<prctls(j+1);
splitmat(j,indc&inds) = 1;
end
end
% Proportions of classes in each split parts
disp(['original split proportions:' sprintf(' %.3f',sum(splitmat,2)/d)])
for j=1:s
inds = splitmat(j,:)==1;
disp([sprintf('part %d proportions:', j) sprintf(' %.3f',sum(classmat(:,inds),2)/sum(inds))])
end
您获得这 3 个部分,其中包含 80%、10% 和 10%。这些中的每一个与原始数据集的每个类的比例相同:
>>>
original split proportions: 0.800 0.100 0.100
part 1 proportions: 0.400 0.200 0.400
part 2 proportions: 0.400 0.200 0.400
part 3 proportions: 0.400 0.200 0.400
请注意,您不能总是获得确切的比例,因为它取决于数据集的大小以及它们被比例倒数的可分性......但我认为它应该做你想要的。如果您对代码有任何疑问,请随时提出问题。最后,您会获得一个热门的splitmat 矩阵。如果数据点d 属于部件s,则splitmat(s,d) 等于1。