簡體   English   中英

塊矩陣乘積-稀疏矩陣

[英]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*Asnp.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM