Октава: обчисліть відстань між двома матрицями векторів


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.
Арон Ахмадія

1
Б'юсь об заклад, ви можете зробити матрицю 2xNxM, яку ви заповнюєте зовнішнім добутком, а потім помажте кожну із записів і підсумовуйте уздовж нульової осі та квадратного кореня. У Python це виглядатиме так: distance_matrix = (n [:,:, nexaxis] * m [:, newaxis ,:]); відстань_матриця = відстань_матриця ** 2; distance_matrix = sqrt (distance_matrix.sum (вісь = 1)); Якщо вам потрібно лише знати найближчі n-вектори, є набагато кращі способи зробити це!
meawoppl

3
@meawoppl (New to Octave) Я дізнався, як використовувати пакет лінійної алгебри в 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) ..що працює набагато швидше!
Келлі ван Еверт

Відповіді:


6

Векторизація в таких ситуаціях проста, використовуючи таку стратегію:

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

Ось приклад, який векторизує цикл for з 15-кратним прискоренням для M = 1000 і 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! Я безсоромно відредагував ваш фрагмент коду та розширив його, будь ласка, скасуйте, якщо мої правки пішли не в тому напрямку, щоб пояснити, що ви планували.
Арон Ахмадія

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 проти кожного вектора в М.

Сподіваюсь, це допомагає

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.