Эффективная по скорости классификация сложных векторов в 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

person ousama kanawati    schedule 25.04.2015    source источник
comment
Каковы размеры InitialPoints и newPoints? Минимальное расстояние между любыми двумя точками в каждом наборе?   -  person krisdestruction    schedule 25.04.2015
comment
Вы можете избавиться от одного цикла с векторизацией: 47487   -  person brodoll    schedule 25.04.2015
comment
У меня подход лучше, но это зависит от размеров точек.   -  person krisdestruction    schedule 25.04.2015
comment
Точки сложные   -  person ousama kanawati    schedule 25.04.2015
comment
Размер InitialPoints равен единице -- 4 , 8 , 16 , 64 размер новых точек достаточно велик   -  person ousama kanawati    schedule 25.04.2015
comment
Мы говорим здесь о точках 1D, 2D, 3D, 4D? Сохраняются ли очки из каждого набора в InitialPoints и newPoints? Было бы лучше, если бы вы уточнили свой вопрос на примере того, как выглядели переменные.   -  person krisdestruction    schedule 25.04.2015
comment
1+j//-1+j//-1+j//-1-j являются начальными точками, и я пытаюсь определить 0,5+0,7j, чтобы точка, к которой она принадлежит, приближалась к минимальному расстоянию.   -  person ousama kanawati    schedule 25.04.2015
comment
Всегда ли они воображаемые? Re и Im, представляющие каждую ось?   -  person krisdestruction    schedule 25.04.2015
comment
Да они всегда.   -  person ousama kanawati    schedule 25.04.2015
comment
@ousamakanawati Дайте мне знать, если это сработает для вас. Если нет, прокомментируйте мой ответ и дайте мне знать, если есть какие-либо проблемы :)   -  person krisdestruction    schedule 25.04.2015


Ответы (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.
person Divakar    schedule 25.04.2015
comment
Появляется правильно и пылает быстро! +1 Возможно, вы можете включить немного того, что делает каждая операция? - person krisdestruction; 25.04.2015
comment
Кроме того, есть ли причина, по которой вы делаете [real(newPoints).' ; imag(newPoints).']; вместо [real(newPoints) imag(newPoints)]';? - person krisdestruction; 25.04.2015
comment
@krisdestruction Думаю, будет то же самое. Добавлено несколько комментариев, но для получения дополнительной информации я думаю, что ссылка должна быть фактической ссылкой, так как в ней много деталей, необходимых для действительного объяснения работы, стоящей за ней. - person Divakar; 25.04.2015
comment
Я просто подумал об этом быстро, и это имело смысл. Сначала мне было интересно, почему вам не нужно sqrt, но потом я вспомнил, что min( sqrt ) => min! Объяснение для ОП, но это тоже работает. - person krisdestruction; 25.04.2015
comment
@krisdestruction Точно, в основном это квадраты расстояний. - person Divakar; 25.04.2015
comment
@ousamakanawati Если это было лучшее решение, которое сработало для вас, не забудьте принять его. Спасибо! - person Divakar; 25.04.2015

Решение очень простое. Однако вам нужна моя 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 );
person krisdestruction    schedule 25.04.2015

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

    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
person Tom Gijselinck    schedule 25.04.2015
comment
Это решение по сути является ссылкой @brodroll. В моей ссылке используется цикл 1 cellfun для генерации декартова произведения и не используется какой-либо явный цикл. Кроме того, если я не ошибаюсь, abs уже вычисляет величину, а это означает, что ^, sqrt и sum на самом деле не нужны в вашем решении. - person krisdestruction; 25.04.2015
comment
Это напомнило мне, что мне нужно изменить форму моего кода: 3 - person krisdestruction; 25.04.2015
comment
@krisdestruction Спасибо, я не знал, что abs возвращает модуль комплексного числа. Вероятно, не самое быстрое решение, но я думаю, что эта реализация проста и лаконична. - person Tom Gijselinck; 25.04.2015
comment
Кратким будет ответ Дивакара - person krisdestruction; 25.04.2015