Matlab product of vectors in the third dimension

Hope my problem has a very simple solution. I just can't find it:

Suppose you have two vectors (one column vector, one row vector) A, B:

A = [1,2,3] B = [4;5;6] 

if we multiply them as follows, we get the matrix:

 >> B*A ans = 4 8 12 5 10 15 6 12 18 

Now my problem: I have two 3D matrices of sizes m × n × p and m × n × q

Imagine the sizes m and n , we have pixels, and for each pixel we have a vector (length p or q). Now I want to multiply by each corresponding pixel by the vectors of two images, so for each pixel I get a matrix and, therefore, a whole 4D Matrix at the end.

How do I do this efficiently?

+4
source share
3 answers

The loops in Matlaba no longer need to be feared or avoided on their own.

Of course, you should be very careful when using them, but, nevertheless, JIT can take care of many kinds of loops, improving performance even beyond built-in functions.

Consider the following test cases:

 clc m = 512; n = 384; p = 5; q = 3; A = rand(m,n,p); % some sample data B = rand(m,n,q); % some sample data %% non-loop approach tic A2 = reshape(A,[],p); B2 = reshape(B,[],q); C2 = arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false); C0 = permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]); toc %% looped approach, simplest tic C = zeros(m,n,p,q); for mm = 1:m for nn = 1:n C(mm,nn,:,:) = ... squeeze(A(mm,nn,:))*squeeze(B(mm,nn,:)).'; end end toc % check for equality all(C0(:) == C(:)) %% looped approach, slightly optimized tic C = zeros(m,n,p,q); pp = zeros(p,1); qq = zeros(1,q); for mm = 1:m for nn = 1:n pp(:) = A(mm,nn,:); qq(:) = B(mm,nn,:); C(mm,nn,:,:) = pp*qq; end end toc % check for equality all(C0(:) == C(:)) %% looped approach, optimized tic C = zeros(p,q,m*n); A2 = reshape(A,[],p); B2 = reshape(B,[],q); for mn = 1:m*n C(:,:,mn) = A2(mn,:).'*B2(mn,:); end C = permute(reshape(C, p,q,m,n), [3,4,1,2]); toc % check for equality all(C0(:) == C(:)) 

Results:

 Elapsed time is 3.955728 seconds. Elapsed time is 21.013715 seconds. ans = 1 Elapsed time is 1.334897 seconds. ans = 1 Elapsed time is 0.573624 seconds. ans = 1 

Regardless of performance, I also find that the latter case is much more intuitive and readable than the case without a loop.

+4
source

Using reshaping , arrayfun and permute :

 m=5; n=4; p=3; q=2; A=randi(10,m,n,p); %some sample data B=randi(10,m,n,q); %some sample data A2=reshape(A,[],p); B2=reshape(B,[],q); C2=arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false); C=permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]); 

breakdown:

  • the first two changes convert the matrices A and B mxnx(p or q) to the format (m*n)x(p or q)
  • so that arrayfun can easily scroll through them to compute the vector product of strings
  • then cell2mat, reshape and permute will change the result to mxnxpxq format
+3
source

I use the rody_o solution and modified it to get rid of the change and permutation:

 C = zeros(m*n, p, q); A2 = reshape(A,[],p); B2 = reshape(B,[],q); for mn = 1:m*n C(mn,:,:) = A2(mn,:).' * B2(mn,:); end 
0
source

All Articles