NumPy矩阵向量乘法

284
当我用大小分别为(n x n)*(n x 1)的两个numpy数组相乘时,我得到一个大小为(n x n)的矩阵。按照通常的矩阵乘法规则,期望一个(n x 1)向量,但是我无法找到有关Python中Numpy模块如何处理它的任何信息。问题在于我不想手动实现它以保持程序速度。以下是示例代码:
a = np.array([[5, 1, 3], [1, 1, 1], [1, 2, 1]])
b = np.array([1, 2, 3])

print a*b
   >>
   [[5 2 9]
   [1 2 3]
   [1 4 3]]

我想要的是:

print a*b
   >>
   [16 6 8]
1个回答

459

最简单的解决方案

使用numpy.dota.dot(b)。请参阅此处的文档。

>>> a = np.array([[ 5, 1 ,3], 
                  [ 1, 1 ,1], 
                  [ 1, 2 ,1]])
>>> b = np.array([1, 2, 3])
>>> print a.dot(b)
array([16, 6, 8])

这是因为numpy数组不是矩阵,而标准运算符*, +, -, /对数组的操作是逐元素进行的。
请注意,虽然您可以使用numpy.matrix(截至2021年初),其中*将被视为标准矩阵乘法,但是numpy.matrix已被弃用,并可能在未来的版本中被删除。请参见其文档中的说明(如下所示):

即使是线性代数,也不再建议使用此类。请改用常规数组。该类可能会在未来被删除。

感谢@HopeKing。


其他解决方案

还有其他选项:

  • As noted below, if using python3.5+ and numpy v1.10+, the @ operator works as you'd expect:

    >>> print(a @ b)
    array([16, 6, 8])
    
  • If you want overkill, you can use numpy.einsum. The documentation will give you a flavor for how it works, but honestly, I didn't fully understand how to use it until reading this answer and just playing around with it on my own.

    >>> np.einsum('ji,i->j', a, b)
    array([16, 6, 8])
    
  • As of mid 2016 (numpy 1.10.1), you can try the experimental numpy.matmul, which works like numpy.dot with two major exceptions: no scalar multiplication but it works with stacks of matrices.

    >>> np.matmul(a, b)
    array([16, 6, 8])
    
  • numpy.inner functions the same way as numpy.dot for matrix-vector multiplication but behaves differently for matrix-matrix and tensor multiplication (see Wikipedia regarding the differences between the inner product and dot product in general or see this SO answer regarding numpy's implementations).

    >>> np.inner(a, b)
    array([16, 6, 8])
    
    # Beware using for matrix-matrix multiplication though!
    >>> b = a.T
    >>> np.dot(a, b)
    array([[35,  9, 10],
           [ 9,  3,  4],
           [10,  4,  6]])
    >>> np.inner(a, b) 
    array([[29, 12, 19],
           [ 7,  4,  5],
           [ 8,  5,  6]])
    
  • If you have multiple 2D arrays to dot together, you may consider the np.linalg.multi_dot function, which simplifies the syntax of many nested np.dots. Note that this only works with 2D arrays (i.e. not for matrix-vector multiplication).

      >>> np.dot(np.dot(a, a.T), a).dot(a.T)
      array([[1406,  382,  446],
             [ 382,  106,  126],
             [ 446,  126,  152]])
      >>> np.linalg.multi_dot((a, a.T, a, a.T))
      array([[1406,  382,  446],
             [ 382,  106,  126],
             [ 446,  126,  152]])
    

边缘情况的罕见选项

  • If you have tensors (arrays of dimension greater than or equal to one), you can use numpy.tensordot with the optional argument axes=1:

    >>> np.tensordot(a, b, axes=1)
    array([16,  6,  8])
    
  • Don't use numpy.vdot if you have a matrix of complex numbers, as the matrix will be flattened to a 1D array, then it will try to find the complex conjugate dot product between your flattened matrix and vector (which will fail due to a size mismatch n*m vs n).


7
重要提示:为了更好地使用,请避免使用numpy矩阵,选择使用数组。从文档中可以看到:“即使是用于线性代数,也不再建议使用此类。请改用常规数组。该类可能在将来被移除。”参见stackoverflow.com/a/61156350/6043669。 - HopeKing
3
优秀的回答 wflynny - Xinthral
1
你可能比我更能在这里给出更好的答案:https://mattermodeling.stackexchange.com/a/8474/5 - Nike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接