密集数组与稀疏矩阵的右乘
Right multiplication of a dense array with a sparse matrix
如果我有一个numpy.ndarray
A
和一个scipy.sparse.csc_matrix
B
,我该如何取A
点B
?我可以通过说 B.dot(A)
来做 B
点 A
,但另一方面我只能想到这个:
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 行为的人来说,这是一个潜在的问题(其中 *
表示逐元素乘法)。
如果我有一个numpy.ndarray
A
和一个scipy.sparse.csc_matrix
B
,我该如何取A
点B
?我可以通过说 B.dot(A)
来做 B
点 A
,但另一方面我只能想到这个:
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 行为的人来说,这是一个潜在的问题(其中 *
表示逐元素乘法)。