Recherche…


Opérations élémentaires

MATLAB supporte (et encourage) les opérations vectorisées sur les vecteurs et les matrices.
Par exemple, supposons que nous ayons A et B , deux matrices n - m et que nous voulons que C soit le produit élémentaire des éléments correspondants (c.-à-d. C(i,j) = A(i,j)*B(i,j) ).

La manière non vectorisée d'utiliser des boucles imbriquées est la suivante:

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

Cependant, la manière vectorisée de le faire est d’utiliser l’opérateur par élément .* :

C = A.*B;

  • Pour plus d'informations sur la multiplication d'éléments dans MATLAB, consultez la documentation des times .
  • Pour plus d'informations sur la différence entre les opérations matricielles et matricielles, voir Opérations Matrice ou Matrice dans la documentation MATLAB.

Somme, méchant, prod & co

Étant donné un vecteur aléatoire

v = rand(10,1);

si vous voulez la somme de ses éléments, n'utilisez PAS de boucle

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

mais utilisez la capacité vectorisée de la fonction sum()

s = sum(v);

Les fonctions comme sum() , mean() , prod() et autres ont la possibilité de fonctionner directement le long des lignes, des colonnes ou d'autres dimensions.

Par exemple, donner une matrice aléatoire

A = rand(10,10);

la moyenne pour chaque colonne est

m = mean(A,1);

la moyenne pour chaque ligne est

m = mean(A,2)

Toutes les fonctions ci-dessus ne fonctionnent que sur une seule dimension, mais que se passe-t-il si vous souhaitez additionner toute la matrice? Vous pouvez utiliser:

s = sum(sum(A))

Mais que faire si un tableau ND? appliquer la sum sur la sum sur la sum ... ne semble pas être la meilleure option, utilisez plutôt l'opérateur : pour vectoriser votre tableau:

s = sum(A(:))

et cela se traduira par un nombre qui est la somme de tout votre tableau, peu importe combien de dimensions il a.

Utilisation de bsxfun

Très souvent, la raison pour laquelle le code a été écrit dans une boucle for est de calculer des valeurs à partir de celles situées à proximité. La fonction bsxfun peut souvent être utilisée pour le faire de manière plus succincte.

Par exemple, supposons que vous souhaitiez effectuer une opération par colonnes sur la matrice B , en soustrayant la moyenne de chaque colonne:

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 

Cette méthode est inefficace si B est grand, souvent dû au fait que MATLAB doit déplacer le contenu des variables en mémoire. En utilisant bsxfun , on peut faire le même travail facilement et facilement en une seule ligne:

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

Ici, @minus est un handle de fonction pour l'opérateur minus ( - ) et sera appliqué entre les éléments des deux matrices B et mean(B) . D'autres poignées de fonction, même celles définies par l'utilisateur, sont également possibles.


Supposons ensuite que vous souhaitiez ajouter un vecteur de ligne v à chaque ligne de la matrice A :

v = [1,  2,  3];

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

L'approche naïve consiste à utiliser une boucle ( ne le faites pas ):

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

Une autre option serait de répliquer v avec repmat ( ne le faites pas non plus ):

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

>> B = A + v; 

Utilisez plutôt bsxfun pour cette tâche:

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

Syntaxe

bsxfun(@fun, A, B)

@fun est l'une des fonctions prises en charge et que les deux tableaux A et B respectent les deux conditions ci-dessous.

Le nom bsxfun aide à comprendre comment fonctionne la fonction et il est synonyme de FUN B inaire ction avec S Ingleton e X pansion. En d'autres termes, si:

  1. deux tableaux partagent les mêmes dimensions sauf un
  2. et la dimension discordante est un singleton (c'est-à-dire a une taille de 1 ) dans l'un ou l'autre des deux tableaux

alors le tableau avec la dimension singleton sera développé pour correspondre à la dimension de l'autre tableau. Après l'extension, une fonction binaire est appliquée par élément sur les deux tableaux.

Par exemple, soit A un tableau M -by- N -by K et B un tableau M -by- N . Premièrement, leurs deux premières dimensions ont des tailles correspondantes. Deuxièmement, A a K couches alors que B a implicitement seulement 1 , donc c'est un singleton. Toutes les conditions sont remplies et B sera répliqué pour correspondre à la 3ème dimension de A

Dans d'autres langues, il s'agit généralement de diffusion et se produit automatiquement en Python (numpy) et Octave.

La fonction, @fun , doit être une fonction binaire, ce qui signifie qu’elle doit prendre exactement deux entrées.

Remarques

En interne, bsxfun ne réplique pas le tableau et exécute une boucle efficace.

Masquage logique

MATLAB prend en charge l'utilisation du masquage logique afin d'effectuer une sélection sur une matrice sans utiliser des boucles for ou des instructions if.

Un masque logique est défini comme une matrice composée de 1 et 0 .

Par exemple:

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

est une matrice logique représentant la matrice d'identité.

Nous pouvons générer un masque logique en utilisant un prédicat pour interroger une matrice.

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

Nous créons d'abord une matrice 3x3, A , contenant les nombres de 1 à 9. Nous interrogeons ensuite A pour les valeurs supérieures à 4 et stockons le résultat dans une nouvelle matrice appelée B

B est une matrice logique de la forme:

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

Ou 1 lorsque le prédicat A > 4 était vrai. Et 0 quand c'était faux.

Nous pouvons utiliser des matrices logiques pour accéder aux éléments d’une matrice. Si une matrice logique est utilisée pour sélectionner des éléments, les indices où un 1 apparaît dans la matrice logique seront sélectionnés dans la matrice que vous sélectionnez.

En utilisant le même B ci-dessus, nous pourrions faire ce qui suit:

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

Cela sélectionnerait tous les éléments de CB a un 1 dans cet index. Ces indices dans C sont alors mis à 5 .

Notre C ressemble maintenant à:

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

Nous pouvons réduire les blocs de code complexes contenant if et for en utilisant des masques logiques.

Prenez le code non vectoriel:

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

Cela peut être raccourci en utilisant le masquage logique au code suivant:

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

Ou même plus court:

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

Extension implicite de la matrice (diffusion) [R2016b]

MATLAB R2016b comportait une généralisation de son mécanisme d’expansion scalaire 1 , 2 , pour prendre en charge également certaines opérations entre éléments de tableaux de tailles différentes, à condition que leur dimension soit compatible. Les opérateurs qui prennent en charge l'expansion implicite sont 1 :

  • Opérateurs arithmétiques élémentaires: + , - ./ .* ./ .^ , ./ .\ .
  • Opérateurs relationnels: < , <= , > , >= , == , ~= .
  • Opérateurs logiques: & , | , ou xor .
  • Fonctions bitand : bitand , bitor , bitxor .
  • Fonctions mathématiques élémentaires: max , min , mod , rem , hypot , atan2 , atan2d .

Les opérations binaires susmentionnées sont autorisées entre les baies, à condition qu'elles aient des "tailles compatibles". Les tailles sont considérées comme "compatibles" lorsque chaque dimension d'un tableau est soit exactement égale à la même dimension dans l'autre tableau, soit égale à 1 . Notez que les dimensions de singleton final (c'est-à-dire de taille 1 ) sont omises par MATLAB, même s'il en existe théoriquement une quantité infinie. En d'autres termes, les dimensions qui apparaissent dans un tableau et n'apparaissent pas dans l'autre sont implicitement adaptées à une expansion automatique.

Par exemple, dans les versions MATLAB antérieures à R2016b, cela se produirait:

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

Considérant que à partir de R2016b l'opération précédente réussira:

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

     9     3     9
     4     7    10
     5    11     5

Exemples de tailles compatibles:

La description 1ère taille de tableau 2 ème taille de tableau Taille du résultat
Vecteur et scalaire [3x1] [1x1] [3x1]
Vecteurs de lignes et de colonnes [1x3] [2x1] [2x3]
Matrice vectorielle et 2D [1x3] [5x3] [5x3]
Tableaux ND et KD [1x3x3] [5x3x1x4x2] [5x3x3x4x2]

Exemples de tailles incompatibles:

La description 1ère taille de tableau 2 ème taille de tableau Solution de rechange possible
Vecteurs où une dimension est un multiple de la même dimension dans l'autre tableau. [1x2] [1x8] transpose
Tableaux avec des dimensions qui sont des multiples les uns des autres. [2x2] [8x8] repmat , reshape
Les tableaux ND qui ont la bonne quantité de singleton mais dans le mauvais ordre (# 1). [2x3x4] [2x4x3] permute
Les tableaux ND qui ont la bonne quantité de singleton mais qui sont dans le mauvais ordre (# 2). [2x3x4x5] [5x2] permute

IMPORTANT:
Le code reposant sur cette convention n'est PAS compatible avec les anciennes versions de MATLAB. Par conséquent, l'appel explicite de bsxfun 1 , 2 (qui produit le même effet) doit être utilisé si le code doit être exécuté sur d'anciennes versions de MATLAB. Si un tel problème n'existe pas, les notes de publication de MATLAB R2016 encouragent les utilisateurs à passer de bsxfun :

Par rapport à l'utilisation de bsxfun , l'expansion implicite offre une vitesse d'exécution plus rapide, une meilleure utilisation de la mémoire et une meilleure lisibilité du code.


Lecture connexe:

Obtenir la valeur d'une fonction de deux arguments ou plus

Dans de nombreuses applications, il est nécessaire de calculer la fonction de deux arguments ou plus.

Traditionnellement, nous utilisons for boucles. Par exemple, si nous devons calculer le f = exp(-x^2-y^2) (ne l'utilisez pas si vous avez besoin de simulations rapides ):

% 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

Mais la version vectorisée est plus élégante et plus rapide:

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

que nous pouvons le visualiser:

surf(x,y,f)

Remarque 1 - Grilles: généralement, le stockage matriciel est organisé ligne par ligne . Mais dans le MATLAB, il s'agit du stockage colonne par colonne , comme dans FORTRAN. Ainsi, il existe deux fonctions simulaires ndgrid et meshgrid dans MATLAB pour implémenter les deux modèles susmentionnés. Pour visualiser la fonction dans le cas de meshgrid , on peut utiliser:

surf(y,x,f)

Note2 - La consommation de mémoire: Soit la taille de x ou y est 1000. Ainsi, nous avons besoin de stocker 1000*1000+2*1000 ~ 1e6 éléments pour code1 non vectorisé. Mais il faut 3*(1000*1000) = 3e6 éléments dans le cas du code vectorisé2. Dans le cas 3D (laissez z avoir la même taille que x ou y ), la consommation de mémoire augmente considérablement: 4*(1000*1000*1000) (~ 32 Go pour les doubles) dans le cas du code vectoriel2 vs ~1000*1000*1000 (seulement ~ 8 Go) dans le cas du code1 . Il faut donc choisir entre la mémoire ou la vitesse.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow