Vectoriser l'appel à la fonction de deux vecteurs (traiter la matrice comme un tableau de vecteur)
-
28-10-2019 - |
Question
Je souhaite calculer la distance cumulée en cosinus entre les ensembles de vecteurs.
La représentation naturelle d'un ensemble de vecteurs est une matrice ... mais comment puis-je vectaliser ce qui suit?
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
Je peux bien sûr écrire
fz = @(v1,v2) transpose(v1)*v2/(norm(v1)*norm(v2));
ds = cellfun(fz,P1,P2);
... Tant que je refonte mes matrices comme tableaux cellulaires de vecteurs. Y a-t-il une manière meilleure / entièrement numérique?
De plus, CellFun, ArrayFun, etc. profiteront-ils des instructions vectorielles et / ou du multithreading?
Noter Probablement superflu dans la société actuelle mais pour les vecteurs de colonnes v1'*v2 == dot(v1,v2)
et est considérablement plus rapide dans Matlab.
La solution
Depuis P1
et P2
sont de la même taille, vous pouvez effectuer des opérations d'élément ici. v1'*v
équivaut à sum(v1.*v2)
, d'ailleurs.
d = prod(sum(P1.*P2,1)./sqrt(sum(P1.^2,1) .* sum(P2.^2,1)));
Autres conseils
@Jonas avait la bonne idée, mais le dénominateur de normalisation pourrait être incorrect. Essayez ceci à la place:
%# 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)) );
Vous pouvez comparer cela avec les résultats renvoyés par PDIST2 fonction:
%# PDIST2 returns one minus cosine distance between all pairs of vectors
d2 = prod( 1-diag(pdist2(P1',P2','cosine')) );