简体   繁体   中英

Multiply columns of a matrix with 2d matrix slices of a 3d matrix in MatLab

Basically, I want to perform the following computation:

    G is m x n x k
    S is n x k

    Answer=zeros(m,d)
    for Index=1:k
        Answer(:,Index)=G(:,:,Index)*S(:,Index)
    end

So, answer is a matrix, whose columns are the result of multiplying each layer of a 3d matrix with a column of another matrix.

This really seems like a straightforward type of operation, and I was hoping to find out if there is a native or vectorized (or at least >> faster) way of performing this type of computation in Matlab. Thanks.

Try using mtimesx from the Matlab File Exchange . It's the best (fast/efficient) tool I've found so far to do this sort of n-dimensional array multiplication, since it uses mex . I think you could also use bsxfun , but my Matlab-fu is not enough for this sort of thing.

You have mxnxk and mxk and want to produce a nxk .

mtimesx multiplies inputs like ixjxk and jxrxk to produce ixrxk .

To put your problem in mtimesx form, let G be mxnxk , and expand S to be nx 1 xk . Then mtimesx(G,S) would be mx 1 xk , which could then be flattened down to mxk .

m=3; 
n=4; 
k=2;
G=rand(m,n,k);
S=rand(n,k);

% reshape S
S2=reshape(S,n,1,k);

% do multiplication and flatten mx1xk to mxk
Ans_mtimesx = reshape(mtimesx(G,S2),m,k)

% try loop method to compare
Answer=zeros(m,k);
for Index=1:k
    Answer(:,Index)=G(:,:,Index)*S(:,Index);
end

% compare
norm(Ans_mtimesx-Answer)
% returns 0.

So if you wanted a one-liner, you could do:

Ans = reshape(mtimesx(G,reshape(S,n,1,k)),m,k)

By the way, if you post your question on the Matlab Newsreader forums there'll be plenty of gurus who compete to give you answers more elegant or efficient than mine!

Here is the bsxfun() version. If A is an m-by-n matrix and x is an n-by-1 vector then A*x can be computed as

sum(bsxfun(@times, A, x'), 2)

The operation permute(S, [3 1 2]) will take the columns of S and distribute them along the 3rd dimension as rows. The [3 1 2] is a permutation of the dimensions of S.

Thus sum(bsxfun(@times, G, permute(S, [3 1 2])), 2) achieves the answer but leaves the result in the 3rd dimension. In order to get it in the form you want another permute is required.

permute(sum(bsxfun(@times, G, permute(S, [3 1 2])), 2), [1 3 2])

One thing you can do is to represent your 3d matrix as a 2d block diagonal matrix, with each layer being a diagonal block. The 2d matrix in this case should be represented as a vector containing the stacked columns. if the matrix is large, declare it as a sparse matrix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM