Оптимизировать код MATLAB (вложенный в цикл для вычисления матрицы сходства) - PullRequest
2 голосов
/ 24 апреля 2011

Я вычисляю матрицу подобия на основе евклидова расстояния в MATLAB. Мой код выглядит следующим образом:

for i=1:N % M,N is the size of the matrix x for whose elements I am computing similarity matrix
 for j=1:N
  D(i,j) = sqrt(sum(x(:,i)-x(:,j)).^2)); % D is the similarity matrix
 end
end

Может ли помочь в оптимизации это = уменьшение циклов for, поскольку моя матрица x имеет размер 256x30000.

Большое спасибо!

- Адитья

Ответы [ 4 ]

5 голосов
/ 24 апреля 2011

Функция для этого в matlab называется pdist.К сожалению, он мучительно медленный и не учитывает возможности векторизации Matlabs.

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

   Qx=repmat(dot(x,x,2),1,size(x,1));
   D=sqrt(Qx+Qx'-2*x*x');

Обратите внимание, что это будет работать, только если ваши точки данных находятся в строках, а ваши измерения - в столбцах.Например, допустим, у меня 256 точек данных и 100000 измерений, а затем на моем компьютере Mac используется x = rand (256,100000), а приведенный выше код создает матрицу 256x256 примерно за полсекунды.

1 голос
/ 24 апреля 2011

Я думаю, это то, что вы ищете.

D=zeros(N);    
jIndx=repmat(1:N,N,1);iIndx=jIndx'; %'# fix SO's syntax highlighting
D(:)=sqrt(sum((x(iIndx(:),:)-x(jIndx(:),:)).^2,2));

Здесь я предположил, что вектор расстояния x инициализируется в виде массива NxM, где M - это число измерений системы, а N - это число точек. Так что, если ваш заказ отличается, вам придется внести соответствующие изменения.

1 голос
/ 24 апреля 2011

Возможно, есть лучший способ сделать это, но первое, что я заметил, это то, что вы можете сократить время выполнения пополам, используя симметрию D(i,j)==D(i,j)

Вы также можете использовать функцию norm(x(:,i)-x(:,j),2)

0 голосов
/ 24 апреля 2011

Начнем с того, что вы вычисляете здесь вдвое больше, чем нужно, потому что D будет симметричным. Вам не нужно рассчитывать (i, j) запись и (j, i) запись отдельно. Измените свой внутренний цикл на for j=1:i и добавьте в тело этого цикла D(j,i)=D(i,j);

После этого в коде остается не так уж много избыточности, поэтому вам остается только улучшить параллелизм: если у вас есть Parallel Computing Toolbox, преобразуйте внешний цикл в parfor и перед запустите его, скажем, matlabpool(n), где n - количество используемых потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...