2

I have two matrices X and Y, both of order mxn. I want to create a new matrix O of order mxm such that each i,j th entry in this new matrix is computed by applying a function to ith and jth row of X and Y respectively. In my case m = 10000 and n = 500. I tried using a loop but it takes forever. Is there an efficient way to do it?

I am targeting two functions dot product -- dot(row_i, row_j) and exp(-1*norm(row_i-row_j)). But I was wondering if there is a general way so that I can plugin any function.

Divakar
  • 218,885
  • 19
  • 262
  • 358
Bob
  • 561
  • 1
  • 6
  • 18
  • I have feeling that I can use bsxfun but I do not understand what the arguments will be. I found this http://stackoverflow.com/questions/9813554/apply-function-to-every-pair-of-columns-in-two-matrices-in-matlab which is close but did not work. – Bob Oct 04 '14 at 12:48

2 Answers2

4

Solution #1

For the first case, it looks like you can simply use matrix multiplication after transposing Y -

X*Y'

If you are dealing with complex numbers -

conj(X*ctranspose(Y))

Solution #2

For the second case, you need to do a little more work. You need to use bsxfun with permute to re-arrange dimensions and employ the raw form of norm calculations and finally squeeze to get a 2D array output -

squeeze(exp(-1*sqrt(sum(bsxfun(@minus,X,permute(Y,[3 2 1])).^2,2)))

If you would like to avoid squeeze, you can use two permute's -

exp(-1*sqrt(sum(bsxfun(@minus,permute(X,[1 3 2]),permute(Y,[3 1 2])).^2,3)))

I would also advise you to look into this problem - Efficiently compute pairwise squared Euclidean distance in Matlab.


In conclusion, there isn't a common most efficient way that could be employed for every function to ith and jth row of X. If you are still hell bent on that, you can use anonymous function handles with bsxfun, but I am afraid it won't be the most efficient technique.

Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Can you please explain the anonymous function handles part.. sorry I am a newbie to MATLAB. I actually tried defining funcs like dotFun = @(x,y) dot(x,y); and used that in K = bsxfun(@(i,j) (dotFun(X(i,:), X(j,:))), 1:m, (1:m)'); but got error unequal dimension A,B – Bob Oct 04 '14 at 13:21
  • Would be interesting to see the speedups you might be getting with these! – Divakar Oct 04 '14 at 13:21
  • 1
    @Divakar I meant `'` was right! Dot product has a conjugate – Luis Mendo Oct 04 '14 at 13:22
  • @Bob I think this could help you on the anonymous function with bsxfun part - http://stackoverflow.com/questions/23310433/using-bsxfun-with-an-anonymous-function . Also, would you be dealing with complex numbers by any chance? – Divakar Oct 04 '14 at 13:32
  • Real numbers- not yet. But I guess some one will need that in future someday :) – Bob Oct 04 '14 at 14:02
  • @Bob Added for those too! :) – Divakar Oct 04 '14 at 14:03
  • @LuisMendo Took me sometime to figure that out, but finally it's here! Thank you for the heads up there :) +1 for you too BTW for a good alternative solution! – Divakar Oct 04 '14 at 14:04
4

For the second part, you could also use pdist2:

result = exp(-pdist2(X,Y));
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147