Suche…


Elementweise Operationen

MATLAB unterstützt (und ermutigt) vektorisierte Operationen an Vektoren und Matrizen.
Angenommen, wir haben A und B , zwei n um- m Matrizen, und wir wollen, dass C das elementare Produkt der entsprechenden Elemente ist (dh C(i,j) = A(i,j)*B(i,j) ).

Die nicht vektorisierte Methode, verschachtelte Schleifen zu verwenden, lautet wie folgt:

C = zeros(n,m);
for ii=1:n
    for jj=1:m
        C(ii,jj) = A(ii,jj)*B(ii,jj);
    end
end

Die vektorisierte Methode hierfür ist jedoch der elementweise Operator .* :

C = A.*B;

  • Weitere Informationen zur elementweisen Multiplikation in MATLAB finden Sie in der Dokumentation der times .
  • Weitere Informationen über den Unterschied zwischen Arrays und Matrixoperationen siehe Array vs. Matrix - Operationen in der MATLAB - Dokumentation.

Summe, Mittelwert, Prod & Co

Gegeben ein zufälliger Vektor

v = rand(10,1);

Wenn Sie die Summe seiner Elemente wünschen, verwenden Sie KEINE Schleife

s = 0;
for ii = 1:10
    s = s + v(ii);
end 

Verwenden Sie jedoch die vektorisierte Funktion der Funktion sum()

s = sum(v);

Funktionen wie sum() , mean() , prod() und andere können direkt entlang von Zeilen, Spalten oder anderen Dimensionen arbeiten.

Zum Beispiel eine zufällige Matrix gegeben

A = rand(10,10);

Der Durchschnitt für jede Spalte ist

m = mean(A,1);

Der Durchschnitt für jede Zeile ist

m = mean(A,2)

Alle oben genannten Funktionen funktionieren nur in einer Dimension, aber was ist, wenn Sie die gesamte Matrix summieren möchten? Du könntest benutzen:

s = sum(sum(A))

Aber was wäre, wenn ich ein ND-Array habe? Anwendung sum auf sum auf sum ... scheint nicht wie die beste Option, verwenden Sie stattdessen den : Betreiber Array vektorisieren:

s = sum(A(:))

und dies ergibt eine Zahl, die die Summe Ihres Arrays ist, egal wie viele Dimensionen es hat.

Verwendung von bsxfun

Der Grund, warum Code in eine for Schleife geschrieben wurde, ist häufig das Berechnen von Werten aus 'nahen' Werten. Die Funktion bsxfun kann häufig dazu verwendet werden.

Nehmen Sie beispielsweise an, Sie möchten eine spaltenweise Operation an der Matrix B ausführen und den Mittelwert jeder Spalte davon abziehen:

B = round(randn(5)*10);                  % Generate random data 
A = zeros(size(B));                      % Preallocate array
for col = 1:size(B,2);                    % Loop over columns
    A(:,col) = B(:,col) - mean(B(:,col));   % Subtract means 
end 

Diese Methode ist ineffizient, wenn B groß ist. Dies liegt häufig daran, dass MATLAB den Inhalt von Variablen im Speicher verschieben muss. Durch die Verwendung von bsxfun können Sie dieselbe Aufgabe in nur einer Zeile ordentlich und problemlos erledigen:

A = bsxfun(@minus, B, mean(B));

Hier @minus ist ein Funktionsgriff zum minus Operator ( - ) und zwischen den Elementen der beiden Matrizen angewendet werden B und mean(B) , mean(B) . Andere Funktionshandles, auch benutzerdefinierte, sind ebenfalls möglich.


Angenommen, Sie möchten der Zeile A in Matrix A Zeilenvektor v hinzufügen:

v = [1,  2,  3];

A = [8,  1,  6
     3,  5,  7
     4,  9,  2];

Der naive Ansatz ist eine Schleife ( mach das nicht ):

B = zeros(3);
for row = 1:3
    B(row,:) = A(row,:) + v;
end

Eine weitere Option wäre zu replizieren v mit repmat (nicht tut dies entweder):

>> v = repmat(v,3,1)
v =
     1     2     3
     1     2     3
     1     2     3

>> B = A + v; 

Verwenden bsxfun stattdessen bsxfun für diese Aufgabe:

>> B = bsxfun(@plus, A, v);
B =
     9     3     9
     4     7    10
     5    11     5

Syntax

bsxfun(@fun, A, B)

Dabei ist @fun eine der unterstützten Funktionen und die beiden Arrays A und B @fun die beiden folgenden Bedingungen.

Der Name bsxfun hilft zu verstehen , wie die Funktion arbeitet und es steht für B inary FUN ction mit S ingleton e X pansion. Mit anderen Worten, wenn:

  1. Zwei Arrays haben die gleichen Abmessungen außer einem
  2. und die diskordante Dimension ist in jedem der beiden Arrays ein Singleton (dh hat eine Größe von 1 )

Dann wird das Array mit der Singleton-Dimension erweitert, um der Dimension des anderen Arrays zu entsprechen. Nach der Erweiterung wird eine binäre Funktion elementweise auf die beiden Arrays angewendet.

Zum Beispiel sei A ein M by- N by K Array und B ist ein M by- N Array. Erstens haben ihre ersten beiden Dimensionen entsprechende Größen. Zweitens hat A K Schichten, während B implizit nur 1 , daher ist es ein Singleton. Alle Bedingungen sind erfüllt und B wird entsprechend der 3. Dimension von A repliziert.

In anderen Sprachen wird dies häufig als Rundfunk bezeichnet und geschieht automatisch in Python (Numpy) und Octave.

Die Funktion @fun muss eine binäre Funktion sein, dh sie muss genau zwei Eingaben annehmen.

Bemerkungen

Intern repliziert bsxfun das Array nicht und führt eine effiziente Schleife aus.

Logische Maskierung

MATLAB unterstützt die Verwendung der logischen Maskierung, um die Auswahl in einer Matrix ohne for-Schleifen oder if-Anweisungen auszuführen.

Eine logische Maske ist als eine Matrix definiert, die nur aus 1 und 0 .

Zum Beispiel:

mask = [1 0 0; 0 1 0; 0 0 1];

ist eine logische Matrix, die die Identitätsmatrix darstellt.

Wir können eine logische Maske mit einem Prädikat zum Abfragen einer Matrix generieren.

A = [1 2 3; 4 5 6; 7 8 9];
B = A > 4;

Zuerst erstellen wir eine 3x3-Matrix A , die die Zahlen 1 bis 9 enthält. Wir fragen dann A nach Werten ab, die größer als 4 sind, und speichern das Ergebnis in einer neuen Matrix mit dem Namen B

B ist eine logische Matrix der Form:

B = [0 0 0
     0 1 1
     1 1 1]

Oder 1 wenn das Prädikat A > 4 wahr ist. Und 0 wenn es falsch war.

Wir können logische Matrizen verwenden, um auf Elemente einer Matrix zuzugreifen. Wenn eine logische Matrix zum Auswählen von Elementen verwendet wird, werden in der Matrix, aus der Sie auswählen, Indizes ausgewählt, bei denen eine 1 in der logischen Matrix angezeigt wird.

Mit demselben B von oben könnten wir Folgendes tun:

C = [0 0 0; 0 0 0; 0 0 0];
C(B) = 5;

Dies würde alle Elemente von C auswählen, bei denen B eine 1 in diesem Index hat. Diese Indizes in C werden dann auf 5 .

Unser C sieht jetzt so aus:

C = [0 0 0
     0 5 5
     5 5 5]

Wir können komplizierte Codeblöcke reduzieren, die if und for indem Sie logische Masken verwenden.

Nehmen Sie den nicht vektorisierten Code:

A = [1 3 5; 7 9 11; 11 9 7];
for j = 1:length(A)
  if A(j) > 5
    A(j) = A(j) - 2;
  end
end

Dies kann durch logisches Maskieren zu folgendem Code verkürzt werden:

A = [1 3 5; 7 9 11; 11 9 7];
B = A > 5;
A(B) = A(B) - 2;

Oder noch kürzer:

A = [1 3 5; 7 9 11; 11 9 7];
A(A > 5) = A(A > 5) - 2;

Implizite Array-Erweiterung (Broadcasting) [R2016b]

In MATLAB R2016b wurde der Mechanismus der skalaren Erweiterung 1 , 2 verallgemeinert, um auch bestimmte elementweise Operationen zwischen Arrays unterschiedlicher Größe zu unterstützen, sofern ihre Abmessungen kompatibel sind. Die Operatoren, die die implizite Erweiterung unterstützen, sind 1 :

  • Elementweise arithmetische Operatoren: + , - ./ .* ./ .^ , ./ .\ .
  • Vergleichsoperatoren: < , <= , > , >= , == , ~= .
  • Logische Operatoren: & , | xor .
  • Bitweise Funktionen: bitand , bitor , bitxor .
  • Mathematische Grundfunktionen: max , min , mod , rem , hypot , atan2 , atan2d .

Die zuvor genannten binären Operationen sind zwischen Arrays zulässig, sofern sie "kompatible Größen" haben. Größen werden als "kompatibel" betrachtet, wenn jede Dimension in einem Array entweder genau gleich ist wie das andere Array oder gleich 1 . Beachten Sie, dass nachgestellte Singleton-Dimensionen (d. H. Von Größe 1 ) von MATLAB weggelassen werden, obwohl theoretisch unendlich viele vorhanden sind. Mit anderen Worten: Dimensionen, die in einem Array erscheinen und nicht im anderen Array erscheinen, sind implizit für die automatische Erweiterung geeignet.

In MATLAB-Versionen vor R2016b wäre dies beispielsweise der Fall:

>> magic(3) + (1:3)
Error using  + 
Matrix dimensions must agree.

Ab R2016b wird die vorherige Operation erfolgreich sein:

>> magic(3) + (1:3)
ans =

     9     3     9
     4     7    10
     5    11     5

Beispiele für kompatible Größen:

Beschreibung 1. Array - Größe 2. Array - Größe Ergebnisgröße
Vektor und Skalar [3x1] [1x1] [3x1]
Zeilen- und Spaltenvektoren [1x3] [2x1] [2x3]
Vektor- und 2D-Matrix [1x3] [5x3] [5x3]
ND- und KD-Arrays [1x3x3] [5x3x1x4x2] [5x3x3x4x2]

Beispiele für inkompatible Größen:

Beschreibung 1. Array - Größe 2. Array - Größe Mögliche Problemumgehung
Vektoren, bei denen eine Dimension ein Vielfaches derselben Dimension im anderen Array ist. [1x2] [1x8] transpose
Arrays mit Dimensionen, die ein Vielfaches voneinander sind. [2x2] [8x8] repmat , reshape
ND-Arrays mit der richtigen Menge an Singleton-Abmessungen, aber in der falschen Reihenfolge (# 1). [2x3x4] [2x4x3] permute
ND-Arrays mit der richtigen Menge an Singleton-Abmessungen, aber in der falschen Reihenfolge (# 2). [2x3x4x5] [5x2] permute

WICHTIG:
Code auf dieser Konvention unter Berufung ist nicht rückwärtskompatibel mit allen älteren Versionen von MATLAB. Daher sollte der explizite Aufruf von bsxfun 1 , 2 (mit dem gleichen Effekt) verwendet werden, wenn Code unter älteren MATLAB-Versionen ausgeführt werden muss. Wenn ein solches bsxfun nicht besteht, bsxfun MATLAB R2016- bsxfun den Benutzer, von bsxfun zu wechseln:

Im Vergleich zur Verwendung von bsxfun bietet die implizite Erweiterung eine schnellere Ausführung, eine bessere Speichernutzung und eine verbesserte Lesbarkeit des Codes.


Verwandte Lesung:

Rufen Sie den Wert einer Funktion von zwei oder mehr Argumenten ab

In vielen Anwendungen ist es notwendig, die Funktion von zwei oder mehr Argumenten zu berechnen.

Traditionell verwenden wir for -loops. Wenn Sie beispielsweise f = exp(-x^2-y^2) berechnen müssen (verwenden Sie dies nicht, wenn Sie schnelle Simulationen benötigen):

% code1
x = -1.2:0.2:1.4;
y = -2:0.25:3;
for nx=1:lenght(x)
   for ny=1:lenght(y)
      f(nx,ny) = exp(-x(nx)^2-y(ny)^2);
   end
end

Die vektorisierte Version ist jedoch eleganter und schneller:

% code2
[x,y] = ndgrid(-1.2:0.2:1.4, -2:0.25:3);
f = exp(-x.^2-y.^2);

als wir es uns vorstellen können:

surf(x,y,f)

Hinweis 1 - Raster : Normalerweise ist der Matrixspeicher Zeile für Zeile organisiert . In MATLAB ist dies jedoch die spaltenweise Speicherung wie in FORTRAN. Daher gibt es in MATLAB zwei Simelfunktionen, nämlich ndgrid und meshgrid , um die beiden zuvor genannten Modelle zu implementieren. Um die Funktion im Fall von meshgrid zu visualisieren, können wir meshgrid verwenden:

surf(y,x,f)

Hinweis2 - Speicherverbrauch: Die Größe von x oder y 1000 sein. Daher müssen wir 1000*1000+2*1000 ~ 1e6 Elemente für nicht vektorisierten Code1 speichern . Bei vektorisiertem Code2 benötigen wir jedoch 3*(1000*1000) = 3e6 Elemente. Im 3D-Fall ( z B. hat dieselbe Größe wie x oder y ) steigt der Speicherverbrauch dramatisch: 4*(1000*1000*1000) (~ 32 GB für Doubles) im Fall des vektorisierten Codes2 im Vergleich zu ~1000*1000*1000 (nur ~ 8 GB) im Fall von Code1 . Daher müssen wir entweder den Speicher oder die Geschwindigkeit wählen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow