[英]Numpy matrix product - sparse matrices
讓我們考慮矩陣A為對角矩陣,矩陣B為隨機矩陣,兩者的大小均為N xN。我們想使用矩陣A的稀疏屬性來優化點積,即dot(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 s,系統:8毫秒,總計:3.52 s掛牆時間:3.74 s
CPU時間:用戶348 ms,sys:0 ns,總計:348 ms掛牆時間:230 ms
如何正確做?
如果矩陣確實很稀疏,那么正確執行,稀疏點會更快。 但是您不能只將數組放入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矩陣的矩陣乘積可以更快。 我將使用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
差異源於您在定時(微小影響)將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 s
Bsparse.dot(A)
:1個循環,每個循環最好3:2.17 s
csr_matrix.dot(B, Asparse)
:10個循環,最好3個:每個循環32.5毫秒
csr_matrix.dot(Bsparse, Asparse)
:10個循環,最佳3:每個循環28毫秒
如您所見,在所有A
都為稀疏矩陣格式的情況下,稀疏點乘積要快得多,這使dot
意識到A
是稀疏的事實。 在您的時間安排中,該函數實際上是將B
轉換為稀疏格式,然后將其轉換為具有密集矩陣A
的點積。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.