Скоростная классификация сложных векторов в MATLAB

Я пытаюсь оптимизировать этот кусок кода и избавиться от реализованного вложенного цикла. Я испытываю трудности в применении матрицы к функции pdist

Например, 1+j // -1+j // -1+j // -1-j являются начальными точками, и я пытаюсь обнаружить 0,5+0,7j с той точкой, к которой он относится при приближении на минимальное расстояние.
любая помощь приветствуется

function result = minDisDetector( newPoints, InitialPoints)
result = [];
for i=1:length(newPoints)
    minDistance = Inf;
    for j=1:length(InitialPoints)

        X = [real(newPoints(i)) imag(newPoints(i));real(InitialPoints(j)) imag(InitialPoints(j))];
        d = pdist(X,'euclidean');

        if d < minDistance
            minDistance = d;
            index = j;
        end
    end
    result = [result; InitialPoints(index)]; 
end     
end

3 ответа

Решение

Вы можете использовать эффективный расчет евклидова расстояния, как указано в Speed-efficient classification in Matlab для vectorized solution -

%// Setup the input vectors of real and imaginary into Mx2 & Nx2 arrays
A = [real(InitialPoints) imag(InitialPoints)];
Bt = [real(newPoints).' ; imag(newPoints).'];

%// Calculate squared euclidean distances. This is one of the vectorized
%// variations of performing efficient euclidean distance calculation using 
%// matrix multiplication linked earlier in this post.
dists = [A.^2 ones(size(A)) -2*A ]*[ones(size(Bt)) ; Bt.^2 ; Bt];

%// Find min index for each Bt & extract corresponding elements from InitialPoints
[~,min_idx] = min(dists,[],1);
result_vectorized = InitialPoints(min_idx);

Быстрые тесты во время выполнения с newPoints как 400 x 1 & InitialPoints как 1000 x 1 :

-------------------- With Original Approach
Elapsed time is 1.299187 seconds.
-------------------- With Proposed Approach
Elapsed time is 0.000263 seconds.

Решение очень простое. Однако вам нужна моя функция cartprod.m, чтобы генерировать декартово произведение.

Сначала сгенерируйте случайные комплексные данные для каждой переменной.

newPoints = exp(i * pi * rand(4,1));
InitialPoints = exp(i * pi * rand(100,1));

Генерируем декартово произведение newPoints а также InitialPoints с помощью cartprod,

C = cartprod(newPoints,InitialPoints);

Разница в столбце 1 и столбце 2 - это расстояние в комплексных числах. затем abs найдет величину расстояния.

A = abs( C(:,1) - C(:,2) );

Поскольку декартово произведение генерируется так, что оно переставляет newPoints переменные сначала так:

 1     1
 2     1
 3     1
 4     1
 1     2
 2     2
 ...

Мы должны reshape это и получить минимум, используя min найти минимальное расстояние. Нам нужно транспонировать, чтобы найти мин для каждого newPoints, В противном случае без транспонирования мы получим мин для каждого InitialPoints,

[m,i] = min( reshape( D, length(newPoints) , [] )' );

m дает мин, а i дает вам индексы. Если вам нужно получить минимум initialPoints, просто используйте:

result = initialPoints( mod(b-1,length(initialPoints) + 1 );

Можно исключить вложенный цикл, введя поэлементные операции с использованием евклидовой нормы для вычисления расстояния, как показано ниже.

    result = zeros(1,length(newPoints)); % initialize result vector
    for i=1:length(newPoints)
        dist = abs(newPoints(i)-InitialPoints); %calculate distances
        [value, index] =  min(dist);
        result(i) = InitialPoints(index);
    end
Другие вопросы по тегам