2014-09-16 8 views
5

Angenommen, ich habe eine Matrix von Elementen wie so:Effizientes eine 3D-Matrix von äußeren Produkten berechnen - MATLAB

A = reshape(1:25, 5, 5) 

A = 

1  6 11 16 21 
2  7 12 17 22 
3  8 13 18 23 
4  9 14 19 24 
5 10 15 20 25 

ich effizient eine 3D berechnen Matrix von äußeren Produkten, so dass die i th möchte Schicht dieser Ausgangsmatrix ist das äußere Produkt der Spalte A mit sich selbst. Das äußere Produkt zwischen zwei Vektoren u und v ist einfach u*v.', wenn u und v beide Spaltenvektoren sind.

Daher wird jede Scheibe von dieser Ausgangsmatrix B sollte so aufgebaut sein, dass:

B(:,:,1) = A(:,1) * A(:,1).'; 
B(:,:,2) = A(:,2) * A(:,2).'; 
     ... 
     ... 
B(:,:,5) = A(:,5) * A(:,5).'; 

My aktuellen Methode ist die folgende. Ich habe es auf diese Weise zu tun unter Verwendung arrayfun und cell2mat:

cellmatr = arrayfun(@(x) A(:,x) * A(:,x).', 1:size(A,2), 'uni', 0); 
out = reshape(cell2mat(cellmatr), size(A,1), size(A,1), size(A,2)); 

I einfach Schleife über eine lineare Indexanordnung zwischen 1 und so vielen Spalten wir in A haben, und für jedes Element in diesem Array zugreifen I die entsprechende Spalte und berechne das äußere Produkt. Die Ausgabe ergibt somit ein 1D-Gitter aus Zellen, das ich dann zurück in eine 2D-Matrix umwandle, um dann in eine 3D-Matrix umzuformen, um die 3D-Matrix der äußeren Produkte zu finden.

Für große Matrizen ist dies jedoch ziemlich langsam. Ich habe auch versucht, das Matrixprodukt durch kron (d. H. kron(A(:,x), A(:,x))) innerhalb meiner arrayfun Aufforderung zu ersetzen, aber das ist immer noch ziemlich langsam für meine Zwecke.


Kennt jemand eine effiziente Möglichkeit, diese 3D-Matrix von äußeren Produkten auf diese Weise zu berechnen? Diese

+0

haben Sie in diesen sehen: http://www.mathworks.com/matlabcentral/fileexchange/25977-mtimesx- Fast-Matrix-Multiply-mit-multi-dimensionale Unterstützung – bla

+0

@natan - Ich habe nicht, aber danke für den Link zu FEX! – rayryeng

+0

Ich frage mich, wie effizient wäre das vs Divakar Antwort ... – bla

Antwort

8

Dies ist nur eine kleine Verbesserung gegenüber Divakar's answer. Es ist ein wenig schneller, weil es einen 3D-Array permute mit einer permute 2D-Array ersetzt:

B = bsxfun(@times, permute(A, [1 3 2]), permute(A, [3 1 2])); 
+1

Nur ein Kommentar zum Timing - wenn ich dies in meinen Gesamtalgorithmus eingebe, dauerte die Zeit bis zur Fertigstellung des Algorithmus mit einer "3125 x 3125" -Matrix wie folgt: Divakar: 0,403 Sekunden, Amro: 0,304 Sekunden, Luis Mendo: 0,284 Sekunden. Ich habe 100 Versuche mit zufälligen Daten durchgeführt und die Zeiten gemittelt. – rayryeng

+0

Nur überprüft, um sicherzustellen. Dies wird auch die komplexe "diagonale" (nur übereinstimmende Indizes) Menge von äußeren Produkten zwischen Vektoren in zwei getrennten Matrizen berechnen. Das Ersetzen des zweiten "A" durch "conj (B)" berechnet 'für k = 1: n; C (:,:, k) = A (:, k) * B (:, k) '; Ende; '. –

3

-

B = permute(bsxfun(@times,A,permute(A,[3 2 1])),[1 3 2]) 
+0

Ich habe immer Probleme mit "Permutieren", also musste ich jede Aussage einzeln zerlegen und sehen, was bei jedem Schritt passiert. Ich verstehe, was jetzt passiert, und ich wünschte, ich hätte das selbst herausfinden können!Wie auch immer, ich denke, es war eine gute Frage zu stellen :) – rayryeng

+2

Dies scheint ein wenig schneller zu sein, da es eine 3D-Array-Permutation durch 2D-Array-Permutation ersetzt: 'B = bsxfun (@ mal, Permutation (A, [ 1 3 2]), permutieren (A, [3 1 2])); ' –

+0

@LuisMendo - Ihr Tweak in der Lösung schlägt tatsächlich die For-Schleife. – rayryeng

7

das Offensichtliche zu erklären, haben Sie versucht, eine einfache for-Schleife:

[m,n] = size(A); 
B = zeros(m,m,n); 
for i=1:n 
    B(:,:,i) = A(:,i) * A(:,i).'; 
end 

Sie werden überrascht sein, wie kompetitiv schnell es ist.

+0

Ich dachte nicht an eine 'for'-Schleife, weil ich nicht gedacht hätte, dass es funktionieren würde. Ich habe nur ein paar Tests gemacht und das ist eigentlich etwas schneller als 'permute/bsxfun'. Schön gemacht Amro. – rayryeng

+3

+1 amro, manchmal die offensichtlichen Bedürfnisse auch erwähnen. Ich bevorzuge dies auch über bsxfun, viel besser lesbar ... – bla

+0

Das ist auch eine großartige Lösung! +1 BTW-Vorbelegung mit "B (m, m, n) = 0;" könnte ebenfalls berücksichtigt werden. – Divakar

Verwandte Themen