0
votes

I know that MATLAB works better when most or everything is vectorized. I have two set of vectors X and T. For every vector x in X I want to compute:

enter image description here

this is because I want to compute:

enter image description here

which can be easily expressed as MATLAB linear algebra operations as I wrote above with a dot product. I am hoping that I can speed this up by having those vectors, instead of computing each f(x) with a for loop. Ideally I could have it all vectorized and compute:

enter image description here

I've been think about this for some time now, but it doesn't seem to be a a nice way were a function takes two vectors and computes the norm between each one of them, with out me having to explicitly write the for loop.

i.e. I've implemented the trivial code:

function [ f ] = f_start( x, c, t )
%   Computes f^*(x) = sum_i c_i exp( - || x_i - t_i ||^2)
%   Inputs:
%       x = data point (D x 1)
%       c = weights (K x 1)
%       t = centers (D x K)
%   Outputs:
%       f = f^*(x) = sum_k c_k exp( - || x - t_k ||^2)
[~, K] = size(t);
f = 0;
for k=1:K
    c_k = c(k);
    t_k = t(:, k);
    norm_squared = norm(x - t_k, 2)^2;
    f = f + c_k * exp( -1 * norm_squared );
end
end

but I was hoping there was a less naive way to do this!

2

2 Answers

4
votes

I think you want pdist2 (Statistics Toolbox):

X = [1 2 3;
     4 5 6];
T = [1 2 3;
     1 2 4;
     7 8 9];
result = pdist2(X,T);

gives

result =
         0    1.0000   10.3923
    5.1962    4.6904    5.1962

Equivalently, if you don't have that toolbox, use bsxfun as follows:

result = squeeze(sqrt(sum(bsxfun(@minus, X, permute(T, [3 2 1])).^2, 2)));
0
votes

Another method just for kicks

X = [1 2 3;
     4 5 6].';
T = [1 2 3;
     1 2 4;
     7 8 9].';

tT = repmat(T,[1,size(X,2)]);
tX = reshape(repmat(X,[size(T,2),1]),size(tT));
res=reshape(sqrt(sum((tT-tX).^2)).',[size(T,2),size(X,2)]).'