3d矩阵到2d矩阵matlab

时间:2014-12-07 02:11:52

标签: matlab matrix indexing vectorization

我正在使用Matlab R2014a。

我有一个三维M x N x M矩阵A.我想用一种矢量化方法从中提取二维矩阵B,这样对于每个i,我都有

B(I,J)= A(I,J,G(I,J))

其中g是大小为M×N的二维索引矩阵,即在{1,2,...,M}中具有整数值。

上下文是我将函数A(k,z,k')表示为三维矩阵,函数g(k,z)表示为二维矩阵,我想计算功能

H(K,Z)= F(K,Z,G(K,Z))

这似乎是一个简单而常见的尝试,但我真的无法在网上找到任何东西。非常感谢能有所帮助的人!

我的第一个想法是尝试像B = A(:,:,g)或B = A(g)这样的东西,但这些都不起作用,这并不令人惊讶。有类似的东西吗?

2 个答案:

答案 0 :(得分:2)

您可以使用最佳的矢量化工具,bsxfun此处 -

B = A(bsxfun(@plus,[1:M]',M*(0:N-1)) + M*N*(g-1))

说明:将其分解为两步

步骤1:计算与A的前两个维度(行和列)对应的索引 -

bsxfun(@plus,[1:M]',M*(0:N-1))

步骤2:添加包含由g提供的dim-3索引所需的偏移量,并使用这些索引将索引编入A以获得所需的输出 -

A(bsxfun(@plus,[1:M]',M*(0:N-1)) + M*N*(g-1))

基准

这是一个快速基准测试,用于将基于bsxfun的方法与基于ndgrid + sub2ind的解决方案进行比较,如Luis's solutionMN 100所示1}}。

使用tic-toc的基准代码看起来像这样 -

M = 100;
N = 100;
A = rand(M,N,M);
g = randi(M,M,N);

num_runs = 5000; %// Number of iterations to run each approach

%// Warm up tic/toc.
for k = 1:50000
    tic(); elapsed = toc();
end

disp('-------------------- With BSXFUN')
tic
for iter = 1:num_runs
    B1 = A(bsxfun(@plus,[1:M]',M*(0:N-1)) + M*N*(g-1));  %//'
end
toc, clear B1

disp('-------------------- With NDGRID + SUB2IND')
tic
for iter = 1:num_runs
    [ii, jj] = ndgrid(1:M, 1:N);
    B2 = A(sub2ind([M N M], ii, jj, g));
end
toc

这是运行时结果 -

-------------------- With BSXFUN
Elapsed time is 2.090230 seconds.
-------------------- With NDGRID + SUB2IND
Elapsed time is 4.133219 seconds.

结论

正如您所看到的那样,基于bsxfun的方法非常有效,既可以作为矢量化方法,也可以作为性能良好的方法。

为什么bsxfun在这里更好 -

  • bsxfun复制偏移元素并添加它们,即时

  • 在另一个解决方案中,ndgrid在内部对repmat进行两次函数调用,从而导致函数调用开销。在下一步,sub2ind花费时间添加偏移量来获取线性索引,从而带来另一个函数调用开销。

答案 1 :(得分:0)

尝试使用sub2ind。这假设g被定义为M x N矩阵,可能值1,...,M

[ii, jj] = ndgrid(1:M, 1:N);
B = A(sub2ind([M N M], ii, jj, g));