オクターブ:ベクトルの2つの行列間の距離を計算します


12

N、M 2dベクトルをそれぞれ表す2つの行列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のマトリックスを作成して外積を入力し、各エントリを2乗して、0番目の軸と平方根に沿って合計することができます。Pythonでは、これは次のようになります。distance_matrix =(n [:、:、nexaxis] * m [:、newaxis ,:]); distance_matrix = distance_matrix ** 2; distance_matrix = sqrt(distance_matrix.sum(axis = 1)); 最も近いn-vectorのみを知る必要がある場合、これを行うためのより良い方法があります!
meawoppl

3
@meawoppl(オクターブに新)私が使用する方法を見つけた線形代数提供する、オクターブでパッケージを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)はるかに高速に実行..which!
ケリーヴァンエバート

回答:


6

これらの状況では、ベクトル化は次のような戦略を使用して簡単です。

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

M = 1000およびN = 2000の15倍の高速化で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)) 

David、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は、NのすべてのベクトルとMのすべてのベクトルに対する距離のNxM行列です。

お役に立てれば

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.