让我们将矩阵A视为对角矩阵,将矩阵B视为随机矩阵,两者的大小均为N×N。 我们希望使用矩阵A的稀疏属性来优化点积,即点(B,A)。
但是,如果我们使用矩阵A的稀疏性来计算产品,我们就看不到任何优势(而且速度要慢得多)。
import numpy as np
from scipy.sparse import csr_matrix
# Matrix sizes
N = 1000
#-- matrices generation --
A = np.zeros((N,N), dtype=complex)
for i in range(N):
A[i][i] = np.random.rand()
B = np.random.rand(N,N)
#product
%time csr_matrix(B).dot(A)
%time np.dot(B,A)
结果:
CPU时间:用户3.51秒,sys:8毫秒,总计:3.52秒 壁挂时间:3.74秒
CPU时间:用户348 ms,sys:0 ns,总计:348 ms 壁挂时间:230毫秒
如何正确地做到这一点?
答案 0 :(得分:3)
如果矩阵确实稀疏,则向右,稀疏点更快。但是你不能只是将数组抛入csr_matrix.dot
函数。
In [68]: N=1000
In [69]: from scipy import sparse
In [70]: A=np.eye(N) # the diagonal is more interesting than all zeros
In [71]: B=np.random.rand(N,N)
基础案例 - 密集矩阵产品
In [72]: timeit np.dot(B,A)
10 loops, best of 3: 98.8 ms per loop
对于所有相同大小的数组(例如dot(B,B)
,dot(A,A)
),此时间相同。
从两者中制作稀疏矩阵。 As
有很多零,Bs
没有,但格式稀疏
In [73]: As=sparse.csr_matrix(A)
In [74]: Bs=sparse.csr_matrix(B)
请注意转换时间;它们不是微不足道的
In [101]: timeit sparse.csr_matrix(A)
100 loops, best of 3: 13.8 ms per loop
In [102]: timeit sparse.csr_matrix(B)
10 loops, best of 3: 50.1 ms per loop
使用csr矩阵的Matrix产品可以更快。我将使用Bs.dot(As)
表单,因为它更清晰。 Bs*As
和np.dot(Bs,As)
是等效的。但请勿尝试np.dot(Bs,A)
In [107]: timeit Bs.dot(As)
100 loops, best of 3: 19 ms per loop
In [112]: timeit sparse.csr_matrix(B).dot(sparse.csr_matrix(A)).A
10 loops, best of 3: 94.1 ms per loop
明显优于密集版本,但如果我们包含转换时间则稍微好一些。
但请注意,时间差异很大,取决于矩阵的稀疏性
In [108]: timeit As.dot(Bs)
100 loops, best of 3: 10 ms per loop
In [109]: timeit As.dot(B)
100 loops, best of 3: 5.82 ms per loop
In [110]: timeit As.dot(As)
1000 loops, best of 3: 215 µs per loop
In [111]: timeit Bs.dot(Bs)
1 loop, best of 3: 3.83 s per loop
答案 1 :(得分:2)
差异源于你在时间(次要影响)期间将B
转换为稀疏矩阵的事实,更糟糕的是,dot
并未意识到A
稀疏。如果您要在点积之前进行转换,则稀疏点积实际上更快:
import numpy as np
from scipy.sparse import csr_matrix
# Matrix sizes
N = 1000
#-- matrices generation --
A = np.zeros((N,N), dtype=complex)
for i in range(N):
A[i][i] = np.random.rand()
B = np.random.rand(N,N)
Asparse = csr_matrix(A)
Bsparse = csr_matrix(B)
%timeit np.dot(B, A)
%timeit csr_matrix(B).dot(A)
%timeit Bsparse.dot(A)
%timeit csr_matrix.dot(B, Asparse)
%timeit csr_matrix.dot(Bsparse, Asparse)
给出:
np.dot(B, A)
:1循环,最佳3:414 ms每循环
csr_matrix(B).dot(A)
:1循环,最佳3:2.22秒每循环
Bsparse.dot(A)
:1循环,最佳3:每循环2.17秒
csr_matrix.dot(B, Asparse)
:10个循环,最佳3:32.5 ms每循环
csr_matrix.dot(Bsparse, Asparse)
:10个循环,最好是每个循环3:28毫秒
正如您所看到的,稀疏点产品在A
处于稀疏矩阵格式且使dot
意识到这一事实的所有情况下都快得多,A
是稀疏的。在您的计时中,该函数实际上将B
转换为稀疏格式,然后转换为具有密集矩阵A
的点积。