옥타브 : 두 벡터 행렬 사이의 거리 계산


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 함수를 작성하는 데 매우 적합한 후보라고 생각합니다.
Aron Ahmadia 2019

1
외부 제품으로 채운 2xNxM 행렬을 만든 다음 각 항목을 제곱하고 0 번째 축과 제곱근을 따라 합산 할 수 있습니다. 파이썬에서 이것은 다음과 같습니다 : distance_matrix = (n [:, :, nexaxis] * m [:, newaxis ,:]); distance_matrix = 거리 _ 매트릭스 ** 2; distance_matrix = sqrt (거리 _matrix.sum (축 = 1)); 가장 가까운 n- 벡터 만 알아야하는 경우 훨씬 더 좋은 방법이 있습니다!
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) 요식 훨씬 빠르게 실행됩니다!
Kelley van Evert

답변:


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)) 

데이빗, 공상 과학에서 만나서 반가워! 코드 조각을 부끄럽게 편집하고 일부를 확장했습니다. 편집 한 내용이 의도 한 내용을 명확하게 설명하지 못하는 경우 되돌려 놓으십시오.
Aron Ahmadia

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의 모든 벡터와 비교됩니다.

도움이 되었기를 바랍니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.