在 MATLAB 中通过 类 交错数据集的高效技术

Efficient technique to interleave data sets by classes in MATLAB

数据集格式如下:输入样本矩阵X,输出class向量Y,X中每一行都是一个样本,每一列对应一个特征。 Y 中的每个索引对应于 X 中相应样本的相应输出 class。X 可以包含实数,而 Y 包含正整数。

我的目标是根据 class 对数据集进行排序。例如

X =      Y =
 1 8 3     2
 4 2 6     1
 7 8 9     2
 2 3 4     3
 1 4 6     1

应订购和交错为

X =      Y =
 4 2 6     1
 1 8 3     2
 2 3 4     3
 1 4 6     1
 7 8 9     2

我尝试的代码似乎需要很长时间才能 运行 因为它是基于串行执行的。就是下面的

X = csvread('X.csv');
Y = csvread('Y.csv');

n = size(unique(Y),1);
m = size(X,1);

for i = 1:n
   Dataset(i).X = X(Y==i,:);
   Dataset(i).Y = Y(Y==i);
end

[num, ~] = hist(Y,n);
maxfreq = max(num);

NewX = [];
NewY = [];

for j = 1:maxfreq
   for i = 1:n
      if(j <= size(Dataset(i).X,1))
         NewX = [NewX; Dataset(i).X(j,:)];
         NewY = [NewY; i];
      end
   end
end

X = NewX;
Y = NewY;
clear NewX;
clear NewY;

csvwrite('OrderedX.csv', X);
csvwrite('OrderedY.csv', Y);

是否可以并行化上述代码?

方法 #1 使用 cumsumdiff 遵循与 this solution -

中列出的相同的哲学
function [outX,outY] = interleave_cumsum_diff(X,Y)

Y = Y(:);
[R,C] = find(bsxfun(@eq,Y,unique(Y).'));

lens = accumarray(C,1);
out = ones(1,numel(R));
shifts = cumsum(lens(1:end-1));
out(shifts+1) =  1- diff([0 ; shifts]);
[~,idx] = sort(cumsum(out));
sort_idx = R(idx)';

outX = X(sort_idx,:);
outY = Y(sort_idx,:);

方法 #1 使用 bsxfun -

function [outX,outY] = interleave_bsxfuns(X,Y)

Y = Y(:);
[R,C] = find(bsxfun(@eq,Y,unique(Y).'));
lens = accumarray(C,1);

mask = bsxfun(@le,[1:max(lens)]',lens.');
V = zeros(size(mask));
V(mask) = R;
Vt = V.';
sort_idx = Vt(mask.');
outX = X(sort_idx,:);
outY = Y(sort_idx,:);

样本运行-

1) 输入:

>> X
X =
     1     8     3
     4     2     6
     7     8     9
     2     3     4
     1     4     6
>> Y
Y =
     2
     1
     2
     3
     1

2) 两种方法的输出:

>> [NewX,NewY] = interleave_cumsum_diff(X,Y)
NewX =
     4     2     6
     1     8     3
     2     3     4
     1     4     6
     7     8     9
NewY =
     1
     2
     3
     1
     2
>> [NewX,NewY] = interleave_bsxfuns(X,Y)
NewX =
     4     2     6
     1     8     3
     2     3     4
     1     4     6
     7     8     9
NewY =
     1
     2
     3
     1
     2

您一直在调整矩阵的大小,这很昂贵。为您的算法快速加速的方法是将 NewX 和 NewY 设置为适当的大小,然后将数据复制到:

NewX = zeros(size(X));
NewY = zeros(size(Y));
k = 1;
for j = 1:maxfreq
  for i = 1:n
     if(j <= size(Dataset(i).X,1))
       NewX(k,:) = Dataset(i).X(j,:);
       NewY(k) = i;
       k=k+1;
     end
   end
end