2016-01-13 2 views
4

j'utilise bsxfun à vectoriser une opération d'extension singleton entre les matrices de dimensions:Utilisation d'bsxfun avec l'expansion singleton avec des matrices de trois dimensions

MS: (nms, nls) 
KS: (nks, nls) 

L'opération est la somme des différences absolues entre chaque valeur MS(m,l) avec m en 1:nms et l en 1:nls, et tous KS(k,l) avec k en 1:nks.

Je y arrive en code:

[~, nls] = size(MS); 
MS = reshape(MS',1,nls,[]); 
R = sum(abs(bsxfun(@minus,MS,KS))); 

R est de taille (nls, nms).

Je veux généraliser cette opération à une liste d'échantillons, de sorte que les nouveaux formats seront:

MS: (nxs, nls, nms) 
KS: (nxs, nls, nks) 

Ceci peut être réalisé facilement avec une boucle qui exécute le premier morceau de code pour chaque 2 dimensions matrices, mais je soupçonne que la performance peut être beaucoup mieux en généralisant le code précédent en ajoutant une nouvelle dimension.

R a serait de taille: (nxs, nls, nms)

J'ai essayé de remodeler MS à 4 dimensions sans succès. Cela pourrait-il être fait avec remodelage et bsxfun?

+0

Cela peut être fait, mais votre description des dimensions est un peu floue pour moi. Pouvez-vous donner un petit exemple? Ou expliquer comment les nouvelles tailles sont liées aux anciennes tailles? –

+2

J'ai ajouté une réponse basée sur 'bsxfun' et' permute'. Si vos dimensions sont énormes et que les performances sont importantes, il peut être plus rapide de «permuter» l'index de sommation pour qu'il soit en premier lieu, de sorte que la fonction sum_mation agit sur des blocs de mémoire contigus. –

+0

Voulez-vous dire permuter sur MS? – jruizaranguren

Répondre

6

Vous pouvez en avoir besoin:

% generate small dummy data 
nxs = 2; 
nls = 3; 
nms = 4; 
nks = 5; 
MS = rand(nxs, nls, nms); 
KS = rand(nxs, nls, nks); 

R = sum(abs(bsxfun(@minus,MS,permute(KS,[1,2,4,3]))),4) 

Cela produira une matrice de taille [2,3,4], à savoir [nxs,nls,nms]. Chaque élément [k1,k2,k3] correspondra à

R(k1,k2,k3) == sum_k abs(MS(k1,k2,k3) - KS(k1,k2,k)) 

Par exemple, dans ma course aléatoire

R(2,1,3) 

ans = 

    1.255765020150647 

>> sum(abs(MS(2,1,3)-KS(2,1,:))) 

ans = 

    1.255765020150647 

L'astuce consiste à introduire une dimension singleton avec permute: permute(KS,[1,2,4,3]) est de taille [nxs,nls,1,nks], tandis que MS de taille [nxs,nls,nms] est implicitement aussi de taille [nxs,nls,nms,1]: chaque tableau de MATLAB est supposé posséder un nombre infini et dénombrable de dimensions singleton. De là, il est facile de voir comment vous pouvez bsxfun ensemble des tableaux de taille [nxs,nls,nms,1] et [nxs,nls,1,nks], respectivement, pour obtenir un avec la taille [nxs,nls,nms,nks]. Résumer le long de la cote 4 scelle l'affaire.


Je note dans un commentaire, qu'il pourrait être plus rapide à permute l'indice de sommation pour être en premier lieu. Il s'avère que cela fait en soi le code plus lent. Cependant, en remodelant les tableaux pour avoir des tailles de dimension décroissantes, les performances globales augmentent (en raison de l'accès mémoire optimal).Comparez ceci:

% generate larger dummy data 
nxs = 20; 
nls = 30; 
nms = 40; 
nks = 500; 
MS = rand(nxs, nls, nms); 
KS = rand(nxs, nls, nks); 

MS2 = permute(MS,[4 3 2 1]); 
KS2 = permute(KS,[3 4 2 1]); 
R3 = permute(squeeze(sum(abs(bsxfun(@minus,MS2,KS2)),1)),[3 2 1]); 

Ce que je n'ai mis la sommation nks dimension en premier lieu, et commander le reste des dimensions dans l'ordre décroissant. Cela pourrait être fait automatiquement, je ne voulais pas trop compliquer l'exemple. Dans votre cas d'utilisation, vous connaissez probablement l'ampleur des dimensions.

Runtimes avec les deux codes ci-dessus: 0.07028 s pour l'original, 0.051162 s pour le réordonné (le meilleur sur 5). Des exemples plus grands ne me conviennent pas pour le moment, malheureusement.

+2

Permute '4D'! Agréable!! – Divakar

+1

@Divakar merci! :) J'espère atteindre votre niveau 6D un jour;) –

+0

@AndrasDeak, j'ai été capable de reproduire le même comportement. Dans mon cas, les dimensions tiennent nxs >> nks> nms ~ nls, donc je peux l'organiser au préalable. Néanmoins, je ne reçois pas une amélioration notable une fois que nxs est en premier lieu. – jruizaranguren