3D阵列A的尺寸为M×N×P。2d矩阵B的大小为M×N。对于B的每一行,最多有一个元素大于零。例:
B = [0 3 0; 2 0 0];
A = zeros(2,3,4);
我想随机填充A,以便在第一行和第二列中恰好有三个,在第二行和第一列中恰好有两个。例如:
A(:,:,1) = [0 1 0; 0 0 0]
A(:,:,2) = [0 1 0; 1 0 0]
A(:,:,3) = [0 0 0; 1 0 0]
A(:,:,4) = [0 1 0; 0 0 0]
换句话说,B元素指示在A的第三维中应具有相同行和列索引的元素。我目前可以通过循环执行此操作,但我希望以一种更有效的方式执行此操作,因此由于M和N实际上很大,因此没有循环。这是我的代码:
B = [0 3 0; 2 0 0];
A = zeros(2,3,4);
for i = 1:size(B,1)
[r,c] = max(B(i,:));
idx = randperm(size(A,3),r);
A(i,c,idx) = 1;
end
请参阅此答案底部的基准以解决计算时间方面的“效率”。
您可以使索引循环更快
通过使用find
,您可以获得B
非零的实际索引,这使循环更“有针对性”,然后您可以跳过该调用,max
因为我们不在乎B
其中任何一行。
可以说这也更加灵活,因为它不对的每一行中的非零值的数量假设任何约束B
。
[M, N] = size(B);
% Set up the output
A = zeros(M,N,P);
% Get row and column indices of non-zero B
[r,c] = find(B);
for ii = 1:numel(r)
% Index into A, given row and column, random columns according to B
A( r(ii), c(ii), randperm( P, B(r(ii), c(ii)) ) ) = 1;
end
全矩阵运算不一定很快。下面的操作不使用循环,但是实际上内存效率低下,这对于大输入来说很慢!
创建一个随机矩阵
r = rand( M, N, P );
在第3维上对随机随机矩阵进行排序,我们不在乎排序的矩阵,而只在乎索引。即订购。这是一种用于获取整个矩阵的方法,在该矩阵中,第3维的每个矢量都经过1:P
混洗(类似于randperm
在循环中使用)。
[~,shuff] = sort(r, 3);
使用B
作为阈值来洗牌后的指数转换成1
/ 0
。请注意,这使用隐式扩展,这需要MATLAB 2016b或更高版本。
A = (shuff <= B)
您可以将1.和2.合并为一个步骤,因此完整的代码将变为
% Inputs
B = [0 3 0; 2 0 0];
P = 4;
% Get shuffled matrix
[M, N] = size(B);
[~,shuff] = sort( rand( M, N, P ), 3 );
% Get ouput
A = (shuff <= B);
基准测试
我们可以运行一个快速基准测试来比较这些方法。在很小的一端,矩阵运算速度更快。对于large来说B
,此答案顶部建议的有效循环要快得多。
N = 7, P = 10, M = variable
因为您实际上说过您M
很大,所以使用此基准。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句