Octave: tính khoảng cách giữa hai ma trận của vectơ


12

Giả sử tôi có hai ma trận Nx2, Mx2 tương ứng là các vectơ N, M 2d. Có cách nào đơn giản và tốt để tính khoảng cách giữa mỗi cặp vectơ (n, m) không?

Tất nhiên, cách dễ dàng nhưng không hiệu quả là:

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

Câu trả lời gần nhất mà tôi tìm thấy là bsxfun, được sử dụng như vậy:

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

Tôi đã xem xét điều này và tôi không thể làm tốt hơn nhiều so với việc tính toán tính toán. Tôi nghĩ rằng tính toán này là một ứng cử viên khá tốt để viết một hàm C / Fortran bên ngoài.
Aron Ahmadia

1
Tôi cá là bạn có thể tạo một ma trận 2xNxM mà bạn tạo ra với một sản phẩm bên ngoài, sau đó bình phương mỗi mục và tính tổng theo trục zeroth và căn bậc hai. Trong Python, nó sẽ trông giống như: distance_matrix = (n [:,:, nexaxis] * m [:, newaxis ,:]); distance_matrix = distance_matrix ** 2; distance_matrix = sqrt (distance_matrix.sum (trục = 1)); Nếu bạn chỉ cần biết các vectơ n gần nhất thì có nhiều cách tốt hơn để làm điều này!
meawoppl

3
@meawoppl (Mới đối với Octave) Tôi đã tìm ra cách sử dụng gói đại số tuyến tính trong Octave, cung cấp cartprod, vì vậy bây giờ tôi có thể viết: (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) .. trong đó chạy nhanh hơn nhiều!
Kelley van Evert

Câu trả lời:


6

Vectorizing là đơn giản trong những tình huống này bằng cách sử dụng một chiến lược như thế này:

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

Đây là một ví dụ giúp vector hóa vòng lặp for với tốc độ tăng gấp 15 lần cho M = 1000 và N = 2000.

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, rất vui được gặp bạn trên scicomp! Tôi xấu hổ chỉnh sửa đoạn mã của bạn và mở rộng nó một số, vui lòng hoàn nguyên nếu các chỉnh sửa của tôi đi sai hướng từ việc làm rõ những gì bạn dự định.
Aron Ahmadia

2

Từ Octave 3.4.3 trở lên, nhà điều hành - thực hiện phát sóng tự động (sử dụng bsxfun trong nội bộ). Vì vậy, bạn có thể tiến hành theo cách này.

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

Bạn có thể làm tương tự bằng cách sử dụng ma trận 3d nhưng tôi đoán như thế này rõ ràng hơn. D là ma trận NxM khoảng cách, mọi vectơ trong N so với mọi vectơ trong M.

Hi vọng điêu nay co ich

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.