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


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.