comment la multiplication diffèrent pour NumPy Matrice vs Tableau des classes?
le numpy docs recommande l'utilisation de tableau au lieu de matrice pour travailler avec des matrices. Cependant, contrairement à octave (que j'utilisais jusqu'à récemment), * n'effectue pas de multiplication matricielle, vous devez utiliser la fonction matrixmultipy (). Je pense que cela rend le code très illisible.
quelqu'un partage mon point de vue, et a trouvé une solution?
7 réponses
la principale raison pour éviter d'utiliser la classe matrix
est que a) il est intrinsèquement bidimensionnel, et b) Il ya des frais généraux supplémentaires par rapport à un Tableau" normal". Si tout ce que vous faites est l'algèbre linéaire, alors par tous les moyens, n'hésitez pas à utiliser la classe matrix... Personnellement, je trouve que c'est plus difficile que ce que ça vaut.
pour les tableaux (avant Python 3.5), utilisez dot
au lieu de matrixmultiply
.
Par exemple:
import numpy as np
x = np.arange(9).reshape((3,3))
y = np.arange(3)
print np.dot(x,y)
ou dans les versions plus récentes de numpy, il suffit d'utiliser x.dot(y)
personnellement, je le trouve beaucoup plus lisible que l'opérateur *
impliquant une multiplication matricielle...
pour les tableaux en Python 3.5, utilisez x @ y
.
les points clés à connaître pour les opérations sur NumPy "1519140920 des" tableaux par rapport à des opérations sur NumPy "1519140920 des" matrices sont:
-
num Py matrix is a subclass of num Py array
-
NumPy array opérations élément-sage (une fois que la radiodiffusion est comptabilisé)
-
NumPy matrice les opérations de suivre les règles ordinaires de l'algèbre linéaire
quelques extraits de code pour illustrer:
>>> from numpy import linalg as LA
>>> import numpy as NP
>>> a1 = NP.matrix("4 3 5; 6 7 8; 1 3 13; 7 21 9")
>>> a1
matrix([[ 4, 3, 5],
[ 6, 7, 8],
[ 1, 3, 13],
[ 7, 21, 9]])
>>> a2 = NP.matrix("7 8 15; 5 3 11; 7 4 9; 6 15 4")
>>> a2
matrix([[ 7, 8, 15],
[ 5, 3, 11],
[ 7, 4, 9],
[ 6, 15, 4]])
>>> a1.shape
(4, 3)
>>> a2.shape
(4, 3)
>>> a2t = a2.T
>>> a2t.shape
(3, 4)
>>> a1 * a2t # same as NP.dot(a1, a2t)
matrix([[127, 84, 85, 89],
[218, 139, 142, 173],
[226, 157, 136, 103],
[352, 197, 214, 393]])
mais cette opération échoue si ces deux matrices NumPy sont converties en tableaux:
>>> a1 = NP.array(a1)
>>> a2t = NP.array(a2t)
>>> a1 * a2t
Traceback (most recent call last):
File "<pyshell#277>", line 1, in <module>
a1 * a2t
ValueError: operands could not be broadcast together with shapes (4,3) (3,4)
bien que utilisant le NP.point 1519150920" la syntaxe fonctionne avec les tableaux ; cette opération fonctionne comme la multiplication matricielle:
>> NP.dot(a1, a2t)
array([[127, 84, 85, 89],
[218, 139, 142, 173],
[226, 157, 136, 103],
[352, 197, 214, 393]])
avez-vous besoin d'une matrice? ie, un tableau NumPy suffira-t-il pour le calcul de l'algèbre linéaire (à condition que vous connaissiez la syntaxe correcte, ie, NP.dot)?
la règle semble être que si les arguments (tableaux) ont des formes (m x n) compatibles avec l'opération d'algèbre linéaire donnée, alors vous êtes ok, sinon, Numpy lance.
la seule exception que j'ai rencontrée (il y en a probablement d'autres) est calculating matrix inverse .
ci-dessous sont des extraits dans lesquels j'ai appelé une opération d'algèbre linéaire pure (en fait, à partir de module D'algèbre linéaire de Numpy) et passé dans un NumPy array
déterminant d'un réseau:
>>> m = NP.random.randint(0, 10, 16).reshape(4, 4)
>>> m
array([[6, 2, 5, 2],
[8, 5, 1, 6],
[5, 9, 7, 5],
[0, 5, 6, 7]])
>>> type(m)
<type 'numpy.ndarray'>
>>> md = LA.det(m)
>>> md
1772.9999999999995
vecteurs propres/valeur propre paires:
>>> LA.eig(m)
(array([ 19.703+0.j , 0.097+4.198j, 0.097-4.198j, 5.103+0.j ]),
array([[-0.374+0.j , -0.091+0.278j, -0.091-0.278j, -0.574+0.j ],
[-0.446+0.j , 0.671+0.j , 0.671+0.j , -0.084+0.j ],
[-0.654+0.j , -0.239-0.476j, -0.239+0.476j, -0.181+0.j ],
[-0.484+0.j , -0.387+0.178j, -0.387-0.178j, 0.794+0.j ]]))
matrice norme :
>>>> LA.norm(m)
22.0227
QR factorisation :
>>> LA.qr(a1)
(array([[ 0.5, 0.5, 0.5],
[ 0.5, 0.5, -0.5],
[ 0.5, -0.5, 0.5],
[ 0.5, -0.5, -0.5]]),
array([[ 6., 6., 6.],
[ 0., 0., 0.],
[ 0., 0., 0.]]))
matrice rang :
>>> m = NP.random.rand(40).reshape(8, 5)
>>> m
array([[ 0.545, 0.459, 0.601, 0.34 , 0.778],
[ 0.799, 0.047, 0.699, 0.907, 0.381],
[ 0.004, 0.136, 0.819, 0.647, 0.892],
[ 0.062, 0.389, 0.183, 0.289, 0.809],
[ 0.539, 0.213, 0.805, 0.61 , 0.677],
[ 0.269, 0.071, 0.377, 0.25 , 0.692],
[ 0.274, 0.206, 0.655, 0.062, 0.229],
[ 0.397, 0.115, 0.083, 0.19 , 0.701]])
>>> LA.matrix_rank(m)
5
matrice condition :
>>> a1 = NP.random.randint(1, 10, 12).reshape(4, 3)
>>> LA.cond(a1)
5.7093446189400954
inversion nécessite un NumPy matrix bien que:
>>> a1 = NP.matrix(a1)
>>> type(a1)
<class 'numpy.matrixlib.defmatrix.matrix'>
>>> a1.I
matrix([[ 0.028, 0.028, 0.028, 0.028],
[ 0.028, 0.028, 0.028, 0.028],
[ 0.028, 0.028, 0.028, 0.028]])
>>> a1 = NP.array(a1)
>>> a1.I
Traceback (most recent call last):
File "<pyshell#230>", line 1, in <module>
a1.I
AttributeError: 'numpy.ndarray' object has no attribute 'I'
mais le Moore-Penrose pseudoinverse semble fonctionner très bien
>>> LA.pinv(m)
matrix([[ 0.314, 0.407, -1.008, -0.553, 0.131, 0.373, 0.217, 0.785],
[ 1.393, 0.084, -0.605, 1.777, -0.054, -1.658, 0.069, -1.203],
[-0.042, -0.355, 0.494, -0.729, 0.292, 0.252, 1.079, -0.432],
[-0.18 , 1.068, 0.396, 0.895, -0.003, -0.896, -1.115, -0.666],
[-0.224, -0.479, 0.303, -0.079, -0.066, 0.872, -0.175, 0.901]])
>>> m = NP.array(m)
>>> LA.pinv(m)
array([[ 0.314, 0.407, -1.008, -0.553, 0.131, 0.373, 0.217, 0.785],
[ 1.393, 0.084, -0.605, 1.777, -0.054, -1.658, 0.069, -1.203],
[-0.042, -0.355, 0.494, -0.729, 0.292, 0.252, 1.079, -0.432],
[-0.18 , 1.068, 0.396, 0.895, -0.003, -0.896, -1.115, -0.666],
[-0.224, -0.479, 0.303, -0.079, -0.066, 0.872, -0.175, 0.901]])
en 3.5, Python finalement a obtenu un opérateur de multiplication de matrice . La syntaxe est a @ b
.
il y a une situation où l'opérateur dot donnera des réponses différentes lorsqu'il s'agit de tableaux comme lorsqu'il s'agit de matrices. Par exemple, supposons ce qui suit:
>>> a=numpy.array([1, 2, 3])
>>> b=numpy.array([1, 2, 3])
permet de les convertir en matrices:
>>> am=numpy.mat(a)
>>> bm=numpy.mat(b)
Maintenant, nous pouvons voir une sortie différente pour les deux cas:
>>> print numpy.dot(a.T, b)
14
>>> print am.T*bm
[[1. 2. 3.]
[2. 4. 6.]
[3. 6. 9.]]
référence de http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html
... l'utilisation de la numpy.matrice classe est découragé , car il n'ajoute rien qui ne peut être accompli avec 2D numpy.ndarray et peut conduire à une confusion dont la classe est utilisée. Par exemple,
>>> import numpy as np
>>> from scipy import linalg
>>> A = np.array([[1,2],[3,4]])
>>> A
array([[1, 2],
[3, 4]])
>>> linalg.inv(A)
array([[-2. , 1. ],
[ 1.5, -0.5]])
>>> b = np.array([[5,6]]) #2D array
>>> b
array([[5, 6]])
>>> b.T
array([[5],
[6]])
>>> A*b #not matrix multiplication!
array([[ 5, 12],
[15, 24]])
>>> A.dot(b.T) #matrix multiplication
array([[17],
[39]])
>>> b = np.array([5,6]) #1D array
>>> b
array([5, 6])
>>> b.T #not matrix transpose!
array([5, 6])
>>> A.dot(b) #does not matter for multiplication
array([17, 39])
scipy.les opérations linalg peuvent être appliquées également à numpy.la matrice ou "2D 151960920" numpy.ndarray des objets.
Ce truc pourrait être ce que vous cherchez. C'est une sorte de simple opérateur de surcharge.
vous pouvez alors utiliser quelque chose comme la classe Infix suggérée comme ceci:
a = np.random.rand(3,4)
b = np.random.rand(4,3)
x = Infix(lambda x,y: np.dot(x,y))
c = a |x| b
une citation pertinente de PEP 465-un opérateur infix dédié pour la multiplication matricielle , comme mentionné par @petr-viktorin, clarifie le problème que l'OP obtenait à:
[...] numpy fournit deux types différents avec des méthodes
__mul__
différentes. Pour les objetsnumpy.ndarray
,*
effectue la multiplication élémentaire, et la multiplication matricielle doit utiliser un appel de fonction (numpy.dot
). Au lieu denumpy.matrix
objets,*
effectue la multiplication matricielle, et la multiplication élémentaire nécessite la syntaxe de la fonction. Ecrire le code en utilisantnumpy.ndarray
fonctionne très bien. Ecrire le code en utilisantnumpy.matrix
fonctionne aussi très bien. mais les problèmes commencent dès que nous essayons d'intégrer ces deux morceaux de code ensemble. Le Code qui s'attend à unndarray
et obtient unmatrix
, ou vice-versa, peut s'écraser ou retourner des résultats incorrects
l'introduction de l'opérateur infix @
devrait aider à unifier et simplifier le code matriciel python.