2016-10-28 3 views
0

Ich möchte um eine schnelle Möglichkeit bitten, die folgenden Operationen durchzuführen, entweder in nativem Matlab, C++ oder mit Toolboxen/Bibliotheken, je nachdem, welches die schnellsten Lösungen bietet .Produkt eines mehrdimensionalen Arrays (oder Tensors) und Vektoren

M Lassen Sie einen Tensor D Dimensionen sein: n1 x n2 x... x nD und lassen v1, v2, ..., vDD Vektoren, deren Abmessungen jeweils n1, n2, ..., nD sein.

  1. Compute das Produkt M*vi (1 < = i < = D). Das Ergebnis ist ein mehrdimensionales Array von (D-1) Dimensionen.
  2. Das Produkt von M mit allen Vektoren außer vi berechnen.

Zum Beispiel mit D = 3:

  • Das Produkt von M und v1 ein Tensor N von 2 Dimensionen (dh einer Matrix), wo

N[i2][i3] = Sum_over_i1 of M[i1][i2][i3]*v1[i1]

  • Das Produkt von M und ist eine Matrix, wo

N[i1][i3] = Sum_over_i2 of M[i1][i2][i3]*v2[i2]

  • Das Produkt von M und v2 und v3 ein Vektor ist v wo

v[i1] = Sum_over_i2 of (Sum_over_i3 of M[i1][i2][i3]*v2[i2]*v3[i3])

Eine weitere Frage: die oben aber für spärliche Tensoren.

Ein Beispiel für Matlab-Code ist unten angegeben.

Vielen Dank im Voraus für Ihre Hilfe !!

n1 = 3; 
n2 = 5; 
n3 = 4; 

M = randn(n1,n2,n3); 
v1 = randn(n1,1); 
v2 = randn(n2,1); 
v3 = randn(n3,1); 

%% N = M*v2 
N = zeros(n1,n3); 
for i1=1:n1 
    for i3=1:n3 
     for i2=1:n2 
      N(i1,i3) = N(i1,i3) + M(i1,i2,i3)*v2(i2); 
     end 
    end 
end 

%% v = M*v2*v3 
v = zeros(n1,1); 
for i1=1:n1 
    for i2=1:n2 
     for i3=1:n3 
      v(i1) = v(i1) + M(i1,i2,i3)*v2(i2)*v3(i3); 
     end 
    end 
end 
+0

Zumindest die innere for-Schleife können Sie vereinfachen, indem Sie nur 'N (i1, i3) = M (i1,:, i3) * v2;' – rst

+0

@RobertSetttler: Danke, aber ich wollte ein Beispiel schreiben, das ist das Offensichtlichste. (Es könnte eine Möglichkeit geben, das Produkt des zweiten Typs zu berechnen, ohne das erste zu schleifen und anzuwenden. Sonst würde ich nicht nach ZWEI Operationen fragen, sondern nur nach dem ersten.) – Khue

Antwort

2

ich bemerkt habe, dass der Betrieb Sie beschreiben nimmt (D - 1) dimensionale Scheiben M und skaliert sie durch den entsprechenden Eintrag von vi anschließend das Ergebnis über die Indizes der vi Summieren.Dieser Code scheint für immer N in Ihrem Beispiel zu arbeiten:

N2 = squeeze(sum(M.*(v2)', 2)); 

Um v in Ihrem Code zu bekommen, alles, was Sie tun müssen, ist mehrfach N von v3:

v2 = N2*v3; 

EDIT

Bei älteren Versionen von MatLab funktioniert der elementweise Operator .* nicht so, wie ich ihn oben benutzt habe. Eine Alternative ist bsxfun:

N2 = squeeze(sum(bsxfun(@times, M, v2'), 2)); 

habe gerade überprüft: In Bezug auf die Leistung, die bsxfun Weg scheint so schnell wie der .* Weg für große Arrays, zumindest auf R2016b.

+0

Danke, aber ich habe diesen Fehler beim Kompilieren bekommen Code: "Fehler bei der Verwendung. * Matrix-Dimensionen müssen übereinstimmen." Könnten Sie bitte nachsehen? – Khue

+0

Es könnte sein, dass wir verschiedene Versionen von MatLab verwenden. In der Version verwende ich Code wie folgt: 'Einsen (2,3). * [1; 2] 'oder' one (2, 3). * [1, 2, 3] 'funktioniert gut, aber ich erinnere mich, dass dies in R2015 nicht der Fall war. Um es zum Laufen zu bringen, müssen Sie 'bsxfun' verwenden, das möglicherweise langsamer ist (siehe Bearbeiten). –

+0

Vielen Dank, Yuri! – Khue

Verwandte Themen