Векторизация вызова функции двух векторов (обрабатывать матрицу как массив векторов) - PullRequest
4 голосов
/ 03 февраля 2011

Я хочу вычислить совокупное косинусное расстояние между наборами векторов.
Естественным представлением набора векторов является матрица ... но как мне векторизовать следующее?

function d = cosdist(P1,P2)
    ds = zeros(size(P1,2),1);
    for k=1:size(P1,2)
      %#used transpose() to avoid SO formatting on '
        ds(k)=transpose(P1(:,k))*P2(:,k)/(norm(P1(:,k))*norm(P2(:,k)));
    end
    d = prod(ds);
end

Конечно, я могу написать

fz = @(v1,v2) transpose(v1)*v2/(norm(v1)*norm(v2));
ds = cellfun(fz,P1,P2);

... до тех пор, пока я переписываю свои матрицы в виде массивов векторов.Есть ли лучший / полностью числовой способ?
Кроме того, будет ли cellfun, arrayfun и т. Д. Использовать преимущества векторных инструкций и / или многопоточности?

Примечание , вероятно, избыточно в нынешней компании, нодля векторов столбцов v1'*v2 == dot(v1,v2) и значительно быстрее в Matlab.

Ответы [ 2 ]

5 голосов
/ 03 февраля 2011

Поскольку P1 и P2 имеют одинаковый размер, вы можете выполнять поэлементные операции здесь.v1'*v равно sum(v1.*v2), кстати.

d = prod(sum(P1.*P2,1)./sqrt(sum(P1.^2,1) .* sum(P2.^2,1)));
3 голосов
/ 03 февраля 2011

@ Jonas имел правильную идею, но нормализующий знаменатель может быть неверным. Попробуйте вместо этого:

%# matrix of column vectors
P1 = rand(5,8);
P2 = rand(5,8);

d = prod( sum(P1.*P2,1) ./ sqrt(sum(P1.^2,1).*sum(P2.^2,1)) );

Вы можете сравнить это с результатами, возвращаемыми функцией PDIST2 :

%# PDIST2 returns one minus cosine distance between all pairs of vectors
d2 = prod( 1-diag(pdist2(P1',P2','cosine')) );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...