Octave: คำนวณระยะห่างระหว่างเมทริกซ์สองตัวของเวกเตอร์


12

สมมติว่าฉันมีเมทริกซ์สองตัว Nx2, Mx2 แทน N, M 2d เวกเตอร์ตามลำดับ มีวิธีที่ง่ายและดีในการคำนวณระยะทางระหว่างเวกเตอร์แต่ละคู่ (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

1
ฉันพนันว่าคุณสามารถสร้างเมทริกซ์ 2xNxM ที่คุณเติมด้วยผลิตภัณฑ์ชั้นนอกจากนั้นให้แต่ละรายการและผลรวมตามแกน zeroth และรากที่สอง ใน Python สิ่งนี้จะมีลักษณะ: distance_matrix = (n [:,:, nexaxis] * m [:, newaxis ,:]); distance_matrix = distance_matrix ** 2; distance_matrix = sqrt (distance_matrix.sum (แกน = 1)); หากคุณต้องการทราบ n-vector ที่ใกล้เคียงที่สุดมีวิธีที่ดีกว่ามากในการทำเช่นนี้!
meawoppl

3
@ meawoppl (ใหม่ถึงคู่) ฉันค้นพบวิธีการใช้แพ็คเกจพีชคณิตเชิงเส้นใน 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) .. 3 ซึ่ง .. ทำงานเร็วขึ้นมาก!
Kelley van Evert

วิธีการเกี่ยวกับoctave.sourceforge.net/statistics/function/pdist.html
Nemo

คำตอบ:


6

Vectorizing ตรงไปตรงมาในสถานการณ์เหล่านี้โดยใช้กลยุทธ์เช่นนี้:

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

นี่คือตัวอย่างที่ vectorizes for loop ด้วยความเร็ว 15x สำหรับ M = 1,000 และ 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)) 

เดวิดยินดีที่ได้พบคุณใน scicomp! ฉันแก้ไขส่วนของโค้ดของคุณอย่างไร้ยางอายและขยายออกไปบางส่วนโปรดยกเลิกการแก้ไขหากการแก้ไขของฉันผิดไปจากที่คุณตั้งใจไว้
Aron Ahmadia

2

จาก Octave 3.4.3 และใหม่กว่าผู้ดำเนินการ - ทำการออกอากาศอัตโนมัติ (ใช้ bsxfun ภายใน) ดังนั้นคุณสามารถดำเนินการต่อด้วยวิธีนี้

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

คุณสามารถทำแบบเดียวกันได้โดยใช้เมทริกซ์ 3 มิติ แต่ฉันเดาว่านี่ชัดเจนกว่า D คือเมทริกซ์ NxM ของระยะทางเวกเตอร์ทุกตัวใน N ต่อเวกเตอร์ทุกตัวใน M

หวังว่านี่จะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.