Quelles sont les différences entre les tableaux numpy et les matrices? Lequel devrais-je utiliser?

346

Quels sont les avantages et les inconvénients de chacun?

D'après ce que j'ai vu, l'un ou l'autre peut fonctionner en remplacement de l'autre si nécessaire, alors devrais-je prendre la peine d'utiliser les deux ou devrais-je m'en tenir à l'un d'entre eux?

Le style du programme influencera-t-il mon choix? Je fais un peu d'apprentissage automatique en utilisant numpy, donc il y a en effet beaucoup de matrices, mais aussi beaucoup de vecteurs (tableaux).

levesque
la source
3
Je n'ai pas suffisamment d'informations pour justifier une réponse, mais d'après ce que je peux dire, la principale différence est la mise en œuvre de la multiplication. Une matrice effectue une multiplication matrice / tenseur, tandis qu'un tableau effectuera une multiplication élément par élément.
Mike Axiak
5
Python 3.5 a ajouté l'opérateur infix @ pour la multiplication matricielle (PEP 465), et NumPy 1.10 a ajouté la prise en charge. Donc, si vous utilisez Python 3.5+ et NumPy 1.10+, vous pouvez simplement écrire à la A @ Bplace de A.dot(B), où Aet Bsont des 2D ndarray. Cela supprime le principal avantage de l'utilisation matrixau lieu de ndarrays simples , à mon humble avis.
MiniQuark

Réponses:

396

Les matrices numpy sont strictement bidimensionnelles, tandis que les tableaux numpy numpy (ndarrays) sont N-dimensionnels. Les objets matriciels sont une sous-classe de ndarray, ils héritent donc de tous les attributs et méthodes des ndarrays.

Le principal avantage des matrices numpy est qu'elles fournissent une notation pratique pour la multiplication matricielle: si a et b sont des matrices, alors a*best leur produit matriciel.

import numpy as np

a = np.mat('4 3; 2 1')
b = np.mat('1 2; 3 4')
print(a)
# [[4 3]
#  [2 1]]
print(b)
# [[1 2]
#  [3 4]]
print(a*b)
# [[13 20]
#  [ 5  8]]

D'un autre côté, à partir de Python 3.5, NumPy prend en charge la multiplication de matrice infixe à l'aide de l' @opérateur, de sorte que vous pouvez obtenir la même commodité de multiplication matricielle avec ndarrays en Python> = 3.5.

import numpy as np

a = np.array([[4, 3], [2, 1]])
b = np.array([[1, 2], [3, 4]])
print(a@b)
# [[13 20]
#  [ 5  8]]

Les objets matriciels et les ndarrays doivent tous .Tles deux renvoyer la transposition, mais les objets matriciels doivent également être utilisés .Hpour la transposition conjuguée et .Ipour l'inverse.

En revanche, les tableaux numpy respectent systématiquement la règle selon laquelle les opérations sont appliquées par élément (sauf pour le nouvel @opérateur). Ainsi, si aet bsont des tableaux numpy, alors a*ble tableau est formé en multipliant les composants par élément:

c = np.array([[4, 3], [2, 1]])
d = np.array([[1, 2], [3, 4]])
print(c*d)
# [[4 6]
#  [6 4]]

Pour obtenir le résultat de la multiplication matricielle, vous utilisez np.dot(ou @en Python> = 3,5, comme indiqué ci-dessus):

print(np.dot(c,d))
# [[13 20]
#  [ 5  8]]

L' **opérateur se comporte également différemment:

print(a**2)
# [[22 15]
#  [10  7]]
print(c**2)
# [[16  9]
#  [ 4  1]]

Puisque aest une matrice, a**2renvoie le produit matriciel a*a. Puisque cest un ndarray, c**2retourne un ndarray avec chaque composant au carré élément par élément.

Il existe d'autres différences techniques entre les objets matriciels et les ndarrays (concernant la np.ravelsélection des éléments et le comportement des séquences).

Le principal avantage des tableaux numpy est qu'ils sont plus généraux que les matrices bidimensionnelles . Que se passe-t-il lorsque vous voulez un tableau en 3 dimensions? Ensuite, vous devez utiliser un ndarray, pas un objet matrice. Ainsi, apprendre à utiliser des objets matriciels est plus de travail - vous devez apprendre les opérations des objets matriciels et les opérations ndarray.

Écrire un programme qui mélange à la fois des matrices et des tableaux vous rend la vie difficile car vous devez garder une trace du type d'objet de vos variables, de peur que la multiplication ne renvoie quelque chose que vous n'attendez pas.

En revanche, si vous vous en tenez uniquement aux ndarrays, vous pouvez faire tout ce que les objets matriciels peuvent faire, et plus, sauf avec des fonctions / notation légèrement différentes.

Si vous êtes prêt à renoncer à l'attrait visuel de la notation des produits matriciels NumPy (qui peut être atteint presque aussi élégamment avec des ndarrays en Python> = 3,5), alors je pense que les tableaux NumPy sont certainement la voie à suivre.

PS. Bien sûr, vous n'avez vraiment pas à en choisir un au détriment de l'autre, np.asmatrixet np.asarrayvous permettant de convertir l'un à l'autre (tant que le tableau est en 2 dimensions).


Il y a un résumé des différences entre NumPy arrayset NumPy matrixes ici .

unutbu
la source
7
Pour ceux qui se demandent, mat**npour une matrice peut être appliquée de manière non reduce(np.dot, [arr]*n)
élégante
6
Ou tout simplementnp.linalg.matrix_power(mat, n)
Eric
Je me demande si les matrices seraient plus rapides ... on pourrait penser qu'elles doivent effectuer moins de contrôles que ndarray.
PascalVKooten
1
En fait, les tests timeit montrent des opérations ndarray telles que np.dot(array2, array2)sont plus rapides que matrix1*matrix2. Cela a du sens car matrixc'est une sous-classe de ndarray qui remplace les méthodes spéciales comme __mul__. matrix.__mul__les appelsnp.dot . Il y a donc une réutilisation du code ici. Au lieu d'effectuer moins de vérifications, l'utilisation matrix*matrixnécessite un appel de fonction supplémentaire. L'avantage de l'utilisation matrixest donc purement syntaxique, pas de meilleures performances.
unutbu
4 * 1 + 3 * 3 vous donnant 13 lorsque vous avez fait np.dot (c, d) n'est-ce pas vraiment un produit croisé en mathématiques
PirateApp
92

Scipy.org vous recommande d'utiliser des tableaux:

* 'tableau' ou 'matrice'? Que dois-je utiliser? - Réponse courte

Utilisez des tableaux.

  • Ce sont les numpy de type vecteur / matrice / tensor standard. Beaucoup de fonctions numpy retournent des tableaux, pas des matrices.

  • Il existe une distinction claire entre les opérations élément par élément et les opérations d'algèbre linéaire.

  • Vous pouvez avoir des vecteurs standard ou des vecteurs ligne / colonne si vous le souhaitez.

Le seul inconvénient de l'utilisation du type tableau est que vous devrez utiliser dotau lieu de *multiplier (réduire) deux tenseurs (produit scalaire, multiplication vectorielle matricielle, etc.).

atomh33ls
la source
11
Même si la réponse acceptée fournit plus d'informations, la vraie réponse est en effet de rester avec ndarray. L'argument principal pour l'utilisation matrixserait si votre code est lourd en algèbre linéaire et semble moins clair avec tous les appels à la dotfonction. Mais cet argument disparaîtra à l'avenir, maintenant que @ -operator est accepté pour une utilisation avec la multiplication matricielle, voir PEP 465 . Cela nécessitera Python 3.5 et la dernière version de Numpy. La classe matricielle pourrait être déconseillée dans un avenir lointain, il vaut donc mieux utiliser ndarray pour le nouveau code ...
Bas Swinckels
6
Cette page oublie gracieusement les scipy.sparsematrices. Si vous utilisez à la fois des matrices denses et clairsemées dans votre code, il est beaucoup plus facile de s'y tenir matrix.
David Nemeskey
3
À mon avis, le principal inconvénient des tableaux est que le découpage en colonnes renvoie des tableaux plats qui peuvent être déroutants et mathématiquement pas vraiment sains. Cela conduit également à l'inconvénient important que les tableaux numpy ne peuvent pas être traités de la même manière que les matrices scipy.sparse tandis que les matrices numpy peuvent être échangées librement avec des matrices clairsemées. Sorte d'absurde dans ce contexte que scipy recommande d'utiliser des tableaux et ne fournit alors pas de tableaux clairsemés compatibles.
Contrôlé par radio
29

Juste pour ajouter un cas à la liste d'unutbu.

L'une des plus grandes différences pratiques pour moi des ndarrays numpy par rapport aux matrices numpy ou aux langages matriciels comme matlab, est que la dimension n'est pas préservée dans les opérations de réduction. Les matrices sont toujours 2D, tandis que la moyenne d'un tableau, par exemple, a une dimension de moins.

Par exemple, rabaisser les lignes d'une matrice ou d'un tableau:

avec matrice

>>> m = np.mat([[1,2],[2,3]])
>>> m
matrix([[1, 2],
        [2, 3]])
>>> mm = m.mean(1)
>>> mm
matrix([[ 1.5],
        [ 2.5]])
>>> mm.shape
(2, 1)
>>> m - mm
matrix([[-0.5,  0.5],
        [-0.5,  0.5]])

avec tableau

>>> a = np.array([[1,2],[2,3]])
>>> a
array([[1, 2],
       [2, 3]])
>>> am = a.mean(1)
>>> am.shape
(2,)
>>> am
array([ 1.5,  2.5])
>>> a - am #wrong
array([[-0.5, -0.5],
       [ 0.5,  0.5]])
>>> a - am[:, np.newaxis]  #right
array([[-0.5,  0.5],
       [-0.5,  0.5]])

Je pense également que le mélange de tableaux et de matrices donne lieu à de nombreuses heures de débogage "heureuses". Cependant, les matrices scipy.sparse sont toujours des matrices en termes d'opérateurs comme la multiplication.

Josef
la source
20

Comme d'autres l'ont mentionné, le principal avantage de matrixcette méthode est peut-être qu'elle fournit une notation pratique pour la multiplication matricielle.

Cependant, dans Python 3.5, il existe enfin un opérateur d'infixe dédié pour la multiplication matricielle :@ .

Avec les versions récentes de NumPy, il peut être utilisé avec ndarrays:

A = numpy.ones((1, 3))
B = numpy.ones((3, 3))
A @ B

De nos jours, encore plus, en cas de doute, vous devez vous en tenir ndarray.

Peque
la source