密集数组与稀疏矩阵的右乘

Right multiplication of a dense array with a sparse matrix

如果我有一个numpy.ndarrayA和一个scipy.sparse.csc_matrixB,我该如何取AB?我可以通过说 B.dot(A) 来做 BA,但另一方面我只能想到这个:

B.T.dot(A.T).T

有更直接的方法吗?

你的问题最初让我感到困惑,因为对于我的 scipy 版本,A.dot(B)np.dot(A, B) 都可以正常工作;稀疏矩阵的 .dot 方法简单地覆盖了 np.dot。然而,这个功能似乎是在 this pull request 中添加的,并且在早于 0.14.0 的 scipy 版本中不存在。我猜你有这些旧版本之一。

测试数据如下:

import numpy as np
from scipy import sparse

A = np.random.randn(1000, 2000)
B = sparse.rand(2000, 3000, format='csr')

对于 scipy >= 0.14.0 的版本,您可以简单地使用:

C = A.dot(B)
C = np.dot(A, B)

对于版本 < 0.14.0,这两个都会引发 ValueError:

In [6]: C = A.dot(B)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-7fbaa337fd94> in <module>()
----> 1 C = A.dot(B)

ValueError: Cannot find a common data type.

相反,您可以使用以下之一:

# your original solution
%timeit B.T.dot(A.T).T
# 10 loops, best of 3: 93.1 ms per loop

# post-multiply A by B
%timeit B.__rmul__(A)
# 10 loops, best of 3: 91.9 ms per loop

正如你所看到的,基本上没有性能差异,虽然我个人认为第二个版本更具可读性。


更新:

正如@shaoyl85 刚刚指出的,可以只使用 * 运算符而不是直接调用 __rmul__() 方法:

# equivalent to B.__rmul__(A)
C = A * B

在确定 * 运算符的行为时,矩阵似乎比 ndarray 具有更高的优先级。对于我们这些更习惯于 ndarrays 行为的人来说,这是一个潜在的问题(其中 * 表示逐元素乘法)。