Python NumPy Matrix 与 Array 类的乘法有何不同?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3890621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how does multiplication differ for NumPy Matrix vs Array classes?
提问by elexhobby
The numpy docs recommend using array instead of matrix for working with matrices. However, unlike octave (which I was using till recently), * doesn't perform matrix multiplication, you need to use the function matrixmultipy(). I feel this makes the code very unreadable.
numpy 文档建议使用数组而不是矩阵来处理矩阵。但是,与八度(我直到最近才使用)不同,* 不执行矩阵乘法,您需要使用函数 matrixmultipy()。我觉得这使得代码非常不可读。
Does anybody share my views, and has found a solution?
有没有人分享我的观点,并找到了解决方案?
回答by Joe Kington
The main reason to avoid using the matrixclass is that a) it's inherently 2-dimensional, and b) there's additional overhead compared to a "normal" numpy array. If all you're doing is linear algebra, then by all means, feel free to use the matrix class... Personally I find it more trouble than it's worth, though.
避免使用matrix该类的主要原因是 a) 它本质上是二维的,并且 b) 与“普通”numpy 数组相比有额外的开销。如果你所做的只是线性代数,那么无论如何,请随意使用矩阵类......但我个人觉得它比它的价值更麻烦。
For arrays (prior to Python 3.5), use dotinstead of matrixmultiply.
对于数组(Python 3.5 之前的版本),使用dot代替matrixmultiply。
E.g.
例如
import numpy as np
x = np.arange(9).reshape((3,3))
y = np.arange(3)
print np.dot(x,y)
Or in newer versions of numpy, simply use x.dot(y)
或者在较新版本的 numpy 中,只需使用 x.dot(y)
Personally, I find it much more readable than the *operator implying matrix multiplication...
就个人而言,我发现它比*暗示矩阵乘法的运算符更具可读性......
For arrays in Python 3.5, use x @ y.
对于 Python 3.5 中的数组,请使用x @ y.
回答by doug
the key things to know for operations on NumPyarraysversus operations on NumPy matricesare:
对NumPy数组的操作与对 NumPy矩阵的操作需要了解的关键是:
NumPy matrix is a subclassof NumPy array
NumPy arrayoperations are element-wise(once broadcasting is accounted for)
NumPy matrixoperations follow the ordinary rules of linear algebra
NumPy 矩阵是NumPy 数组的子类
NumPy数组操作是按元素进行的(一旦考虑到广播)
NumPy矩阵运算遵循线性代数的普通规则
some code snippets to illustrate:
一些代码片段来说明:
>>> 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]])
but this operations fails if these two NumPy matrices are converted to arrays:
但是如果将这两个 NumPy 矩阵转换为数组,则此操作将失败:
>>> 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)
though using the NP.dotsyntax works with arrays; this operations works like matrix multiplication:
尽管使用NP.dot语法适用于数组;此操作的工作原理类似于矩阵乘法:
>> NP.dot(a1, a2t)
array([[127, 84, 85, 89],
[218, 139, 142, 173],
[226, 157, 136, 103],
[352, 197, 214, 393]])
so do you ever need a NumPy matrix? ie, will a NumPy array suffice for linear algebra computation (provided you know the correct syntax, ie, NP.dot)?
所以你需要一个 NumPy 矩阵吗?即,NumPy 数组是否足以进行线性代数计算(前提是您知道正确的语法,即 NP.dot)?
the rule seems to be that if the arguments (arrays) have shapes (m x n) compatible with the a given linear algebra operation, then you are ok, otherwise, NumPy throws.
规则似乎是,如果参数(数组)的形状(mxn)与给定的线性代数运算兼容,那么你没问题,否则,NumPy 抛出。
the only exception i have come across (there are likely others) is calculating matrix inverse.
我遇到的唯一例外(可能还有其他例外)是计算矩阵逆。
below are snippets in which i have called a pure linear algebra operation (in fact, from Numpy's Linear Algebra module) and passed in a NumPy array
下面是我调用纯线性代数运算(实际上,来自 Numpy 的线性代数模块)并传入 NumPy 数组的片段
determinantof an array:
数组的行列式:
>>> 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
eigenvectors/eigenvaluepairs:
特征向量/特征值对:
>>> 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 ]]))
matrix norm:
矩阵范数:
>>>> LA.norm(m)
22.0227
qr factorization:
qr 分解:
>>> 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.]]))
matrix rank:
矩阵等级:
>>> 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
matrix condition:
矩阵条件:
>>> a1 = NP.random.randint(1, 10, 12).reshape(4, 3)
>>> LA.cond(a1)
5.7093446189400954
inversionrequires a NumPy matrixthough:
反演需要一个 NumPy矩阵:
>>> 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'
but the Moore-Penrose pseudoinverseseems to works just fine
但摩尔-彭罗斯伪逆似乎工作得很好
>>> 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]])
回答by Bitwise
This trickcould be what you are looking for. It is a kind of simple operator overload.
这个技巧可能就是你要找的。它是一种简单的运算符重载。
You can then use something like the suggested Infix class like this:
然后,您可以使用类似建议的 Infix 类,如下所示:
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
回答by Jadiel de Armas
There is a situation where the dot operator will give different answers when dealing with arrays as with dealing with matrices. For example, suppose the following:
有一种情况,点运算符在处理数组和处理矩阵时会给出不同的答案。例如,假设以下内容:
>>> a=numpy.array([1, 2, 3])
>>> b=numpy.array([1, 2, 3])
Lets convert them into matrices:
让我们将它们转换为矩阵:
>>> am=numpy.mat(a)
>>> bm=numpy.mat(b)
Now, we can see a different output for the two cases:
现在,我们可以看到两种情况的不同输出:
>>> print numpy.dot(a.T, b)
14
>>> print am.T*bm
[[1. 2. 3.]
[2. 4. 6.]
[3. 6. 9.]]
回答by Yong Yang
Reference from http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html
参考来自http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html
..., the use of the numpy.matrixclass is discouraged, since it adds nothing that cannot be accomplished with 2D numpy.ndarrayobjects, and may lead to a confusionof which class is being used. For example,
...,不鼓励使用numpy.matrix类,因为它添加了 2D numpy.ndarray对象无法完成的任何内容,并且可能导致混淆正在使用哪个类。例如,
>>> 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.linalgoperations can be applied equally to numpy.matrixor to 2D numpy.ndarrayobjects.
scipy.linalg操作同样适用于numpy.matrix或 2D numpy.ndarray对象。
回答by Petr Viktorin
In 3.5, Python finally got a matrix multiplication operator. The syntax is a @ b.
在 3.5 中,Python 终于得到了矩阵乘法运算符。语法是a @ b.
回答by cod3monk3y
A pertinent quote from PEP 465 - A dedicated infix operator for matrix multiplication, as mentioned by @petr-viktorin, clarifies the problem the OP was getting at:
正如@petr-viktorin 所提到的,来自PEP 465 的相关引用- 矩阵乘法的专用中缀运算符,阐明了 OP 遇到的问题:
[...] numpy provides two different types with different
__mul__methods. Fornumpy.ndarrayobjects,*performs elementwise multiplication, and matrix multiplication must use a function call (numpy.dot). Fornumpy.matrixobjects,*performs matrix multiplication, and elementwise multiplication requires function syntax. Writing code usingnumpy.ndarrayworks fine. Writing code usingnumpy.matrixalso works fine. But trouble beginsas soon as we try to integrate these two pieces of code together. Code that expects anndarrayand gets amatrix, or vice-versa, may crash or return incorrect results
[...] numpy 提供了两种不同类型的不同
__mul__方法。对于numpy.ndarray对象,*执行元素乘法,矩阵乘法必须使用函数调用 (numpy.dot)。对于numpy.matrix对象,*执行矩阵乘法,元素乘法需要函数语法。使用编写代码numpy.ndarray工作正常。使用编写代码numpy.matrix也可以正常工作。但是一旦我们尝试将这两段代码集成在一起,麻烦就来了。期望 anndarray和得到 a 的代码,matrix反之亦然,可能会崩溃或返回不正确的结果
The introduction of the @infix operator should help to unify and simplify python matrix code.
中@缀运算符的引入应该有助于统一和简化python矩阵代码。
回答by Serenity
Function matmul(since numpy 1.10.1) works fine for both types and return result as a numpy matrix class:
函数matmul(自 numpy 1.10.1 起)适用于两种类型,并将结果作为 numpy 矩阵类返回:
import numpy as np
A = np.mat('1 2 3; 4 5 6; 7 8 9; 10 11 12')
B = np.array(np.mat('1 1 1 1; 1 1 1 1; 1 1 1 1'))
print (A, type(A))
print (B, type(B))
C = np.matmul(A, B)
print (C, type(C))
Output:
输出:
(matrix([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]]), <class 'numpy.matrixlib.defmatrix.matrix'>)
(array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]), <type 'numpy.ndarray'>)
(matrix([[ 6, 6, 6, 6],
[15, 15, 15, 15],
[24, 24, 24, 24],
[33, 33, 33, 33]]), <class 'numpy.matrixlib.defmatrix.matrix'>)
Since python 3.5 as mentioned earlyyou also can use a new matrix multiplication operator @like
由于前面提到的python 3.5,您还可以使用新的矩阵乘法运算符,@例如
C = A @ B
and get the same result as above.
并得到与上面相同的结果。

