Numpy矩阵向量乘法

当我将两个numpy数组的大小(n x n)*(n x 1)相乘时,我得到一个大小(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]
703513 次浏览

简单的解决方案

使用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。


其他的解决方案

也要知道还有其他选择:

  • 如下所述,如果使用python3.5+和numpy v1.10+, @操作符将如您所期望的那样工作:

    >>> print(a @ b)
    array([16, 6, 8])
    
  • 如果你想过量,你可以使用numpy.einsum。文档会让你了解它是如何工作的,但说实话,我并没有完全理解如何使用它,直到阅读这个答案并自己摆弄它。

    >>> np.einsum('ji,i->j', a, b)
    array([16, 6, 8])
    
  • 从2016年年中(numpy 1.10.1)开始,你可以尝试实验性的numpy.matmul,它的工作方式与numpy.dot类似,但有两个主要例外:没有标量乘法,但它适用于矩阵堆栈。

    >>> np.matmul(a, b)
    array([16, 6, 8])
    
  • numpy.inner的功能与numpy.dot 矩阵向量乘法,但表现不同相同,用于矩阵-矩阵和张量乘法(关于numpy实现的内积和点积看这个SO答案之间的区别,请参阅维基百科)。

    >>> 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]])
    
  • 如果你有多个<强> < / >强二维数组dot,你可以考虑np.linalg.multi_dot函数,它简化了许多嵌套的__abc2的语法。注意,这只适用于2D数组(即不适用矩阵向量乘法)。

      >>> 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]])
    

边缘情况的罕见选项

  • 如果你有张量(维数大于或等于1的数组),你可以使用numpy.tensordot和可选参数axes=1:

    >>> np.tensordot(a, b, axes=1)
    array([16,  6,  8])
    
  • 不要使用numpy.vdot如果你有一个复数矩阵,因为矩阵将被平坦化为一个1D数组,那么它将尝试在你的平坦矩阵和向量之间找到复共轭点积(这将失败,因为大小不匹配n*m vs n)。