倍频程:计算两个向量矩阵之间的距离


12

假设我有两个分别代表N,M个2d向量的矩阵Nx2,Mx2。有没有一种简单而又好的方法来计算每个向量对(n,m)之间的距离?

简单但低效的方法当然是:

d = zeros(N, M);
for i = 1:N,
  for j = 1:M,
    d(i,j) = norm(n(i,:) - m(j,:));
  endfor;
endfor;

我找到的最接近的答案是bsxfun,用法如下:

bsxfun(inline("x-y"),[1,2,3,4],[3;4;5;6])

ans =
  -2 -1  0  1
  -3 -2 -1  0
  -4 -3 -2 -1
  -5 -4 -3 -2

我看了一下,没有比向量化计算更好的了。我认为此计算非常适合编写外部C / Fortran函数。
阿隆·艾玛迪亚

1
我敢打赌,您可以制作一个2xNxM的矩阵,并在其中填充一个外部乘积,然后对每个条目求平方并沿零轴和平方根求和。在Python中,它看起来像是:distance_matrix =(n [:,:,nexaxis] * m [:,newaxis ,:]); distance_matrix = distance_matrix ** 2; distance_matrix = sqrt(distance_matrix.sum(axis = 1)); 如果您只需要知道最接近的n个向量,则可以使用更好的方法!
meawoppl 2012年

3
@meawoppl(Octave的新手)我发现了如何在Octave中使用线性代数包,该包提供cartprod,所以现在我可以编写:(1) x = cartprod(n(:,1), m(:,1)); (2) y = cartprod(n(:,2), m(:,2)); (3) d = sqrt((x(:,1)-x(:,2)).^2+(y(:,1)-y(:,2)).^2) ..它运行得更快!
凯利·范·埃弗特

Answers:


6

在这种情况下,矢量化非常简单,可以使用以下策略:

eN = ones(N,1);
eM = ones(M,1);
d  = sqrt(eM*n.^2' - 2*m*n' + m.^2*eN');

这是一个示例,它以15倍的加速比(对于M = 1000和N = 2000)对for循环进行矢量化处理。

n = rand(N,2);
m = rand(M,2);
eN = ones(N,2);
eM = ones(2,M);

tic;
d_vect  = sqrt(eN*m.^2' - 2*n*m' + n.^2*eM);
vect_time = toc;

tic;
for i=1:N
  for j=1:M
     d_for(i,j) = norm(n(i,:)-m(j,:));
  end
end
for_time = toc; 

assert(norm(d_vect-d_for) < 1e-10*norm(d_for)) 

大卫,很高兴在scicomp上见到您!我无耻地编辑了您的代码片段,并将其扩展了一些,如果澄清了您的意图后,如果我的编辑走错了方向,请恢复。
阿隆·艾玛迪亚

2

从Octave 3.4.3及更高版本开始,操作员-进行自动广播(内部使用bsxfun)。因此您可以以这种方式进行。

Dx = N(:,1) - M(:,1)';
Dy = N(:,2) - M(:,2)';
D = sqrt (Dx.^2 + Dy.^2);

您可以使用3D矩阵执行相同操作,但我想这样会更清晰。D是距离的NxM矩阵,N中的每个矢量与M中的每个矢量。

希望这可以帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.