Ricerca…


Operazioni elementali

MATLAB supporta (e incoraggia) operazioni vettorializzate su vettori e matrici.
Ad esempio, supponiamo di avere A e B , due n -by- m matrici e vogliamo C sia il prodotto elemento-saggio degli elementi corrispondenti (ad esempio, C(i,j) = A(i,j)*B(i,j) ).

Il modo non-vettorizzato, usando i cicli annidati è il seguente:

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

Tuttavia, il modo vettoriale per farlo è usando l'operatore element-wise .* :

C = A.*B;

  • Per ulteriori informazioni sulla moltiplicazione degli elementi in MATLAB consultare la documentazione dei times .
  • Per ulteriori informazioni sulla differenza tra le operazioni su matrice e matrice, consultare Array vs. Matrix Operations nella documentazione di MATLAB.

Somma, significa, prod & co

Dato un vettore casuale

v = rand(10,1);

se vuoi la somma dei suoi elementi, NON usare un ciclo

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

ma usa la capacità vettoriale della funzione sum()

s = sum(v);

Funzioni come sum() , mean() , prod() e altri, hanno la capacità di operare direttamente lungo righe, colonne o altre dimensioni.

Ad esempio, data una matrice casuale

A = rand(10,10);

la media per ogni colonna è

m = mean(A,1);

la media per ogni riga è

m = mean(A,2)

Tutte le funzioni sopra funzionano solo su una dimensione, ma cosa succede se vuoi sommare l'intera matrice? Potresti usare:

s = sum(sum(A))

Ma cosa succede se hai un ND-array? applicare la sum sulla sum sulla sum ... non sembra l'opzione migliore, invece usa l'operatore : per vettorizzare il tuo array:

s = sum(A(:))

e questo si tradurrà in un numero che è la somma di tutto il tuo array, non importa quante dimensioni ha.

Uso di bsxfun

Molto spesso, il motivo per cui il codice è stato scritto in un ciclo for consiste nel calcolare valori da quelli 'vicini'. La funzione bsxfun può essere usata spesso per farlo in un modo più succinto.

Ad esempio, si supponga di voler eseguire un'operazione a colonna sulla matrice B , sottraendo la media di ogni colonna da essa:

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 

Questo metodo è inefficiente se B è grande, spesso a causa del fatto che MATLAB deve spostare il contenuto delle variabili attorno alla memoria. Usando bsxfun , si può fare lo stesso lavoro ordinatamente e facilmente in una sola riga:

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

Qui, @minus è una funzione che gestisce l'operatore minus ( - ) e verrà applicata tra gli elementi delle due matrici B e mean(B) . Sono possibili anche altre maniglie di funzione, anche quelle definite dall'utente.


Successivamente, si supponga di voler aggiungere il vettore di riga v a ciascuna riga nella matrice A :

v = [1,  2,  3];

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

L'approccio ingenuo è usare un ciclo ( non farlo ):

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

Un'altra opzione sarebbe quella di replicare v con repmat ( non farlo neanche ):

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

>> B = A + v; 

Usa invece bsxfun per questa attività:

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

Sintassi

bsxfun(@fun, A, B)

dove @fun è una delle funzioni supportate e i due array A e B rispettano le due condizioni seguenti.

Il nome bsxfun aiuta a capire come funziona la funzione e si distingue per la B ction FUN fabbrica di alcune componenti con S Ingleton e X pansion. In altre parole, se:

  1. due array condividono le stesse dimensioni tranne uno
  2. e la dimensione discordante è un singleton (cioè ha una dimensione di 1 ) in uno dei due array

quindi l'array con la dimensione Singleton verrà espanso per corrispondere alla dimensione dell'altro array. Dopo l'espansione, una funzione binaria viene applicata elementwise sui due array.

Ad esempio, sia A un array M -by- N -by K e B sia un array M -by- N . In primo luogo, le loro prime due dimensioni hanno dimensioni corrispondenti. In secondo luogo, A ha livelli K mentre B ha implicitamente solo 1 , quindi è un singleton. Tutte le condizioni sono soddisfatte e B verrà replicato per corrispondere alla 3a dimensione di A

In altre lingue, questo è comunemente chiamato trasmissione e avviene automaticamente in Python (numpy) e Octave.

La funzione, @fun , deve essere una funzione binaria che significa che deve prendere esattamente due input.

Osservazioni

Internamente, bsxfun non replica la matrice ed esegue un ciclo efficiente.

Mascheramento logico

MATLAB supporta l'uso del mascheramento logico per eseguire la selezione su una matrice senza l'uso di cicli for o di istruzioni.

Una maschera logica è definita come una matrice composta solo da 1 e 0 .

Per esempio:

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

è una matrice logica che rappresenta la matrice di identità.

Possiamo generare una maschera logica usando un predicato per interrogare una matrice.

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

Per prima cosa creiamo una matrice 3x3, A , contenente i numeri da 1 a 9. Quindi interrogiamo A per valori maggiori di 4 e memorizziamo il risultato in una nuova matrice chiamata B

B è una matrice logica della forma:

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

O 1 quando il predicato A > 4 era vero. E 0 quando era falso.

Possiamo usare matrici logiche per accedere agli elementi di una matrice. Se si utilizza una matrice logica per selezionare gli elementi, gli indici in cui 1 appare nella matrice logica saranno selezionati nella matrice da cui si sta selezionando.

Usando la stessa B dall'alto, potremmo fare quanto segue:

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

Questo selezionerebbe tutti gli elementi di C cui B ha un 1 in quell'indice. Questi indici in C sono quindi impostati su 5 .

La nostra C ora sembra:

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

Possiamo ridurre complicati blocchi di codice contenenti if e for utilizzando maschere logiche.

Prendi il codice non-vettorizzato:

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

Questo può essere abbreviato usando il mascheramento logico al seguente codice:

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

O ancora più corto:

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

Espansione di array implicita (broadcasting) [R2016b]

MATLAB R2016b presentava una generalizzazione del suo meccanismo di espansione scalare 1 , 2 , per supportare anche certe operazioni element-grade tra array di diverse dimensioni, purché le loro dimensioni fossero compatibili. Gli operatori che supportano l'espansione implicita sono 1 :

  • Operatori aritmetici element-wise: + , - ./ .* ./ .^ , ./ .\ .
  • Operatori relazionali: < , <= , > , >= , == , ~= .
  • Operatori logici: & , | , xor .
  • Funzioni bit-bit: bitand , bitor , bitxor .
  • Funzioni matematiche elementari: max , min , mod , rem , hypot , atan2 , atan2d .

Le suddette operazioni binarie sono consentite tra gli array, purché abbiano "dimensioni compatibili". Le dimensioni sono considerate "compatibili" quando ogni dimensione in un array è esattamente uguale alla stessa dimensione nell'altro array o è uguale a 1 . Nota che le dimensioni finali di singleton (ovvero di dimensione 1 ) sono omesse da MATLAB, anche se teoricamente c'è una quantità infinita di esse. In altre parole - le dimensioni che compaiono in una matrice e non compaiono nell'altra, sono implicitamente idonee per l'espansione automatica.

Ad esempio, nelle versioni MATLAB precedenti a R2016b ciò accadrebbe:

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

Mentre a partire da R2016b l'operazione precedente avrà esito positivo:

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

     9     3     9
     4     7    10
     5    11     5

Esempi di dimensioni compatibili:

Descrizione dimensione di matrice 2 ° dimensione array Dimensione del risultato
Vettore e scalare [3x1] [1x1] [3x1]
Vettori di righe e colonne [1x3] [2x1] [2x3]
Matrice vettoriale e 2D [1x3] [5x3] [5x3]
Array ND e KD [1x3x3] [5x3x1x4x2] [5x3x3x4x2]

Esempi di dimensioni incompatibili:

Descrizione dimensione di matrice 2 ° dimensione array Possibile soluzione
Vettori in cui una dimensione è un multiplo della stessa dimensione nell'altra matrice. [1x2] [1x8] transpose
Array con dimensioni che sono multipli l'uno dell'altro. [2x2] [8x8] repmat , reshape
Matrici ND che hanno la giusta quantità di dimensioni singleton ma sono nell'ordine sbagliato (n. 1). [2x3x4] [2x4x3] permute
Matrici ND che hanno la giusta quantità di dimensioni singleton ma sono nell'ordine sbagliato (n. 2). [2x3x4x5] [5x2] permute

IMPORTANTE:
Il codice basato su questa convenzione NON è retrocompatibile con le versioni precedenti di MATLAB. Pertanto, l'invocazione esplicita di bsxfun 1 , 2 (che ottiene lo stesso effetto) dovrebbe essere utilizzata se il codice deve essere eseguito su versioni MATLAB precedenti. Se tale preoccupazione non esiste, le note sulla versione MATLAB R2016 incoraggiano gli utenti a passare da bsxfun :

Rispetto all'utilizzo di bsxfun , l'espansione implicita offre una maggiore velocità di esecuzione, un migliore utilizzo della memoria e una migliore leggibilità del codice.


Lettura correlata:

Ottieni il valore di una funzione di due o più argomenti

In molte applicazioni è necessario calcolare la funzione di due o più argomenti.

Tradizionalmente, usiamo for -loops. Ad esempio, se abbiamo bisogno di calcolare il valore f = exp(-x^2-y^2) (non usare questo se hai bisogno di simulazioni veloci ):

% 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

Ma la versione vettoriale è più elegante e veloce:

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

di quanto possiamo visualizzare:

surf(x,y,f)

Nota 1 - Griglie: in genere, la memoria della matrice è organizzata riga per riga . Ma nel MATLAB, è l'archiviazione colonna per colonna come in FORTRAN. Quindi, ci sono due funzioni ndgrid e meshgrid in MATLAB per implementare i due modelli sopra menzionati. Per visualizzare la funzione nel caso di meshgrid , possiamo usare:

surf(y,x,f)

Nota 2 - Il consumo di memoria: Let dimensioni di x o y è 1000. In questo modo, abbiamo bisogno di memorizzare 1000*1000+2*1000 ~ 1e6 elementi per code1 non vectorized. Ma abbiamo bisogno di 3*(1000*1000) = 3e6 elementi nel caso di code2 vettorializzare. Nel caso 3D (lasciare che z abbia le stesse dimensioni di x o y ), il consumo di memoria aumenta drammaticamente: 4*(1000*1000*1000) (~ 32 GB per i doppi) nel caso del codice 2 vettorizzato vs ~1000*1000*1000 (solo ~ 8 GB) nel caso di code1 . Quindi, dobbiamo scegliere la memoria o la velocità.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow