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

sha*_*l85 5 python numpy scipy sparse-matrix matrix-multiplication

如果我有a numpy.ndarray A和a scipy.sparse.csc_matrix B,我怎么拿AB?我可以做BAB.dot(A),但其他办法,我只能想到这一点:

B.T.dot(A.T).T
Run Code Online (Sandbox Code Playgroud)

有没有更直接的方法来做到这一点?

ali*_*i_m 3

你的问题最初让我感到困惑,因为对于我的 scipy 版本,A.dot(B)两者np.dot(A, B)都工作正常;.dot稀疏矩阵的方法只是覆盖np.dot. 然而,这个功能似乎是在此拉取请求中添加的中添加的,并且在 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')
Run Code Online (Sandbox Code Playgroud)

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

C = A.dot(B)
C = np.dot(A, B)
Run Code Online (Sandbox Code Playgroud)

对于 < 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.
Run Code Online (Sandbox Code Playgroud)

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

# 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
Run Code Online (Sandbox Code Playgroud)

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


更新:

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

# equivalent to B.__rmul__(A)
C = A * B
Run Code Online (Sandbox Code Playgroud)

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