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

时间:2015-04-27 08:14:57

标签: python numpy scipy matrix-multiplication sparse-matrix

如果我有numpy.ndarray Ascipy.sparse.csc_matrix B,我该如何处理AB?我可以通过说BAB.dot(A),但另一种方式我只能想到这一点:

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

有更直接的方法吗?

1 个答案:

答案 0 :(得分:3)

您的问题最初让我感到困惑,因为对于我的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

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