【问题标题】:Differences between array class and matrix class in numpy for matrix operationnumpy中用于矩阵运算的数组类和矩阵类的区别
【发布时间】:2017-01-25 10:34:07
【问题描述】:

我尝试用 Numpy 做矩阵点积和转置,我发现数组可以做矩阵可以做的很多事情,例如点积、点积和转置。

当我必须创建一个矩阵时,我必须先创建一个数组。

示例:

import numpy as np

array = np.ones([3,1]) 

matrix = np.matrix(array)

由于我可以在数组类型中进行矩阵转置和点积,因此我不必将数组转换为矩阵来进行矩阵运算。

例如,以下行是有效的,其中 A 是一个 ndarray

dot_product = np.dot(A.T, A ) 

前面的矩阵运算可以用matrix类变量A来表示

dot_product = A.T * A  

运算符 * 与 ndarray 的逐点乘积完全相同。因此,它使 ndarraymatrix 几乎无法区分并引起混淆。

混淆是一个严重的问题,正如REP465中所说的

使用 numpy.matrix 编写代码也可以正常工作。但麻烦开始于 只要我们尝试将这两段代码集成在一起。代码 需要一个 ndarray 并获得一个矩阵,反之亦然,可能会崩溃或 返回不正确的结果。跟踪期望的功能 哪些类型作为输入,哪些类型作为输出返回,然后 一直来回转换,非常麻烦 不可能在任何规模上都正确。

如果我们坚持ndarray,弃用matrix,用.inverse()、.hermitian()、outerproduct等矩阵运算方法支持ndarray,那会很诱人()等,在未来。

我仍然必须使用 matrix 类的主要原因是它将一维数组作为二维数组处理,所以我可以转置它。

到目前为止,我如何转置一维数组非常不方便,因为大小为 n 的一维数组的形状为 (n,) 而不是 (1,n)。例如,如果我必须做两个数组的内积:

A = [[1,1,1],[2,2,2].[3,3,3]] 

B = [[1,2,3],[1,2,3],[1,2,3]]

np.dot(A,B) 工作正常,但如果

B = [1,1,1] 

,它的转置仍然是一个行向量。

当输入变量的维度未知时,我必须处理这个异常。

我希望这可以帮助一些遇到同样麻烦的人,并希望知道是否有更好的方法来处理像 Matlab 中的矩阵运算,尤其是一维数组。谢谢。

【问题讨论】:

    标签: python arrays matlab numpy


    【解决方案1】:

    您的第一个示例是列向量:

    In [258]: x = np.arange(3).reshape(3,1)
    In [259]: x
    Out[259]: 
    array([[0],
           [1],
           [2]])
    In [260]: xm = np.matrix(x)
    

    dot 产生内积,维度操作为:(1,2),(2,1)=>(1,1)

    In [261]: np.dot(x.T, x)
    Out[261]: array([[5]])
    

    矩阵乘积做同样的事情:

    In [262]: xm.T * xm
    Out[262]: matrix([[5]])
    

    (同样的一维数组产生一个标量值,np.dot([0,1,2],[0,1,2]) # 5

    数组的元素乘法产生外积(np.outer(x, x)np.dot(x,x.T) 也是如此)

    In [263]: x.T * x
    Out[263]: 
    array([[0, 0, 0],
           [0, 1, 2],
           [0, 2, 4]])
    

    对于ndarray* 是元素智能乘法(MATLAB 的.*,但添加了广播)。对于matrix 的元素乘法,请使用np.multiply(xm,xm)。 (scipy稀疏矩阵有乘法,X.multiply(other)

    您引用了添加 @ 运算符 (matmul) 的 PEP。这与np.tensordotnp.einsum 一样可以处理更大维数的数组以及其他产品组合。这些对np.matrix 没有意义,因为它仅限于 2d。

    使用您的 3x3 AB

    In [273]: np.dot(A,B)
    Out[273]: 
    array([[ 3,  6,  9],
           [ 6, 12, 18],
           [ 9, 18, 27]])
    In [274]: C=np.array([1,1,1])
    In [281]: np.dot(A,np.array([1,1,1]))
    Out[281]: array([3, 6, 9])
    

    这实际上是对每一行求和。 np.dot(A,np.array([1,1,1])[:,None]) 做同样的事情,但返回一个 (3,1) 数组。

    np.matrix 是多年前创建的,目的是让numpy(实际上是它的前身之一)感觉更像 MATLAB。一个关键特性是它仅限于 2d。这就是 MATLAB 在 1990 年代的样子。 np.matrix 和 MATLAB 没有一维数组;相反,它们有单列或单行矩阵。

    如果ndarrays 可以是 1d(甚至 0d)这一事实是一个问题,那么添加第二维的方法有很多。我更喜欢[None,:] 类型的语法,但reshape 也很有用。 ndmin=2np.atleast_2dnp.expand_dims 也可以。

    np.sum 和其他减少维度的操作有一个keepdims=True 参数来解决这个问题。新的@ 提供了矩阵乘法的运算符语法。据我所知,np.matrix 类没有任何自己的编译代码。

    ============

    np.matrix实现*的方法使用np.dot

     def __mul__(self, other):
        if isinstance(other, (N.ndarray, list, tuple)) :
            # This promotes 1-D vectors to row vectors
            return N.dot(self, asmatrix(other))
        if isscalar(other) or not hasattr(other, '__rmul__') :
            return N.dot(self, other)
        return NotImplemented
    

    【讨论】:

    • 谢谢,这真的很有帮助。我认为我们可以说矩阵类应该被弃用,因为 ndarray 似乎更通用?
    猜你喜欢
    • 1970-01-01
    • 2017-09-26
    • 2019-10-08
    • 2013-08-18
    • 2016-02-07
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多