![](/img/trans.png)
[英]Matrix (scipy sparse) - Matrix (dense; numpy array) multiplication efficiency
[英]How to do efficient matrix multiplication between a dense numpy matrix and a sparse scipy vector?
使用@
將稀疏的矢量向量與稀疏的numpy矩陣相乘效率極低。 似乎它根本沒有利用向量的稀疏性。
說我們有
A = np.eye(5000)
x = np.eye(5000)[333]
x = scipy.sparse.coo_matrix(x).T # make it a sparse vector
然后使用@
產生乘法:
%timeit A @ x
8 ms ± 78.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
讓我們自己編寫一個非常糟糕的稀疏乘法:
def mult_dense_with_sparse(A, x):
return (A[:,x.nonzero()[0]] @ x.toarray()[x.nonzero()[0]]).T[0]
瞧瞧:
%timeit mult_dense_with_sparse(A, x)
50.3 µs ± 45.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
快很多 ! 即使此實現首先通過再次添加所有零來創建密集向量,然后再次刪除所有零...所以我想知道,如果不是@
,我如何才能將密集的numpy矩陣與稀疏的scipy向量有效相乘? 這樣的基本操作當然是科學的一部分嗎?
編輯:在其他問題中提供的解決方案沒有幫助,因為它與@
一樣低效:
%timeit scipy.sparse.csr_matrix.dot(A, x)
7.97 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
在響應程序Hameer Abbasi中編輯2:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
101 @profile
102 def ratio(self, n):
103 80 51.0 0.6 0.0 s = n + 1
104 80 11401854.0 142523.2 16.1 self.sfpc = self.scolPCA(s) # sparse first principal component
106 80 351898.0 4398.7 0.5 wSums = (self.signals[:,self.sfpc.nonzero()[0]] @ self.sfpc.toarray()[self.sfpc.nonzero()[0]]).T[0]
108 80 56487433.0 706092.9 79.7 wSums = self.sfpc.T.dot(self.signals.T)[0]
110 80 2521189.0 31514.9 3.6 self.Flag, self.threshold, self.incline, self.deltaVar = self.actFunctOpt(list(wSums))
111 80 160.0 2.0 0.0 return self.deltaVar / (2 + s)
在這里,您可以看到我們的“ hack”花費了此功能約0.5%的時間,而使用dot
花費了此功能約79.7%的時間。
在您的示例中, A
的類型為np.ndarray
, x
的類型為scipy.sparse.coo_matrix
。
如果您正在尋找最簡單的答案來加快速度,請按以下步驟進行:
import numpy as np
import scipy.sparse as sps
A = np.random.rand(5000, 5000)
v = np.zeros((5000, 1))
v[333] = 1
v_s = sps.csc_matrix(v)
%timeit v_s.T.dot(A).T # 46.6 µs ± 1.11 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit A @ v # 6.75 ms ± 29.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
但是,如果您想讓這個問題的答案更復雜:當前,由於有bug ,運算符@
不支持NumPy數組的重載。 此外, scipy.sparse.coo_matrix
甚至都不會嘗試覆蓋@
,並且scipy.sparse.csr_matrix
矩陣乘法更快( coo_matrix
都將首先轉換為csr_matrix
進行乘法)。
因此,發生的事情是NumPy將您的稀疏矢量轉換為NumPy數組,然后執行密集乘法。
但是, csr_matrix.dot
存在並且支持與密集的NumPy數組相乘。 因此,我們使用屬性A @ B = (BT @ AT).T
以及csc_matrix.T
生成csr_matrix
來生成上述優化代碼的事實。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.