在处理矩阵时,numpy 文档推荐使用数组而不是矩阵。但是,与 octave (我最近一直在使用)不同,* 不执行矩阵乘法,需要使用函数 Matrix/multipy ()。我觉得这使得代码非常不可读。
有人赞同我的观点,并找到了解决办法吗?
避免使用 matrix类的主要原因是: a)它本身是二维的,b)与“普通”数组相比有额外的开销。如果你所做的一切都是线性代数,那么无论如何,请随意使用矩阵类... 个人认为它更多的麻烦比它的价值,虽然。
matrix
对于数组(在 Python 3.5之前) ,使用 dot而不是 matrixmultiply。
dot
matrixmultiply
例如。
import numpy as np x = np.arange(9).reshape((3,3)) y = np.arange(3) print np.dot(x,y)
或者在 numpy 的新版本中,只需使用 x.dot(y)
x.dot(y)
就我个人而言,我发现它比意味着矩阵乘法的 *操作员更具可读性... ..。
*
对于 Python 3.5中的数组,使用 x @ y。
x @ y
对于 笨蛋 数组和 NumPy 矩阵的操作,需要知道的关键事项是:
NumPy 矩阵是 NumPy 数组的 子类
NumPy 数组操作是 元素方面(一旦广播被计算在内)
NumPy 矩阵操作遵循线性代数的一般规则
一些代码片段来说明:
>>> 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]])
但是如果这两个 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)
虽然使用 < em > NP.dot 语法可以与 数组一起工作,但是这种操作的工作方式类似于矩阵乘法:
>> NP.dot(a1, a2t) array([[127, 84, 85, 89], [218, 139, 142, 173], [226, 157, 136, 103], [352, 197, 214, 393]])
你需要一个 NumPy 矩阵吗?例如,NumPy 数组是否足以进行线性代数计算(如果您知道正确的语法,例如 NP.dot) ?
规则似乎是,如果参数(数组)的形状(m x n)与给定的线性代数操作兼容,那么就可以了,否则,NumPy 抛出。
我遇到的唯一例外(可能还有其他例外)是 计算矩阵的逆矩阵。
下面是我调用纯线性代数运算(事实上,来自 NumPy 的线性代数模块)并在 NumPy 数组中传递的片段
数组的行列式:
>>> 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
特征向量/特征值 强 > 对:
>>> 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 ]]))
矩阵 范围:
>>>> LA.norm(m) 22.0227
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.]]))
矩阵 军衔:
>>> 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
矩阵 环境监察及审核:
>>> a1 = NP.random.randint(1, 10, 12).reshape(4, 3) >>> LA.cond(a1) 5.7093446189400954
倒置 需要一个 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'
但是 摩尔-彭罗斯伪逆看起来运行得很好
>>> 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]])
这个技巧 可能就是你要找的,它是一种简单的运算符重载。
然后您可以像下面这样使用建议的 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
有一种情况,点运算符在处理数组时会给出与处理矩阵时不同的答案。例如,假设如下:
>>> a=numpy.array([1, 2, 3]) >>> b=numpy.array([1, 2, 3])
让我们把它们转换成矩阵:
>>> am=numpy.mat(a) >>> bm=numpy.mat(b)
现在,我们可以看到这两种情况的不同输出:
>>> print numpy.dot(a.T, b) 14 >>> print am.T*bm [[1. 2. 3.] [2. 4. 6.] [3. 6. 9.]]
来自 http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html的参考文献
... ,使用的 Numpy.Matrix类是 气馁,因为它没有增加什么不能完成的二维 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])
Linalg 操作可以同样应用于 Numpy.Matrix或2D Numpy Ndarray对象。
在3.5中,Python 最后是 找了个矩阵乘法,语法是 a @ b。
a @ b
正如@petr-viktorin 提到的,来自 PEP 465-一个专用于矩阵乘法的中缀操作器的一段相关引文澄清了 OP 所面临的问题:
Numpy 提供了两种不同类型的 __mul__方法。对于 numpy.ndarray对象,*执行元素乘法,而矩阵乘法必须使用函数调用(numpy.dot)。对于 numpy.matrix对象,*执行矩阵乘法,而且元素乘需要函数语法。使用 numpy.ndarray编写代码效果很好。使用 numpy.matrix编写代码也可以很好地工作。只要我们尝试将这两段代码集成在一起,就可以使用 numpy.ndarray0。期望获得 ndarray并获得 matrix的代码,或者反过来,可能会崩溃或返回不正确的结果
__mul__
numpy.ndarray
numpy.dot
numpy.matrix
ndarray
@中缀操作符的引入应该有助于统一和简化 python 矩阵代码。
@
函数 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))
产出:
(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'>)
因为 python 3.5就像 之前提到过一样,你也可以使用一个新的矩阵乘法操作符,比如
C = A @ B
并得到与上述相同的结果。