我有兩個密集矩陣,甲 [200000,10],乙 [10,100000]。我需要將它們相乘得到矩陣C。我不能直接這樣做,因爲生成的矩陣不適合內存。而且,我只需要矩陣中的幾個元素,比如元素總數的1-2%。我有第三個矩陣W [200000,100000]這是稀疏的,並有正好在我感興趣的矩陣C這些地方非零元素。 有沒有辦法使用W作爲一個「掩碼」,以便產生的矩陣C將是稀疏的,將只包含所需的元素?兩個陣列之間執行矩陣乘法並得到導致僅在掩蔽的地方
回答
由於矩陣乘法只是一個點乘積表,我們可以用向量化的方式執行我們需要的特定點乘積。
import numpy as np
import scipy as sp
iX, iY = sp.nonzero(W)
values = np.sum(A[iX]*B[:, iY].T, axis=-1) #batched dot product
C = sp.sparse.coo_matrix(values, np.asarray([iX,iY]).T)
首先,得到W中非零位的索引,然後通過將A中的第i行與B中的第j列相乘,得到結果矩陣的(i,j)
元素,並保存結果作爲元組(i,j,res)
而不是將其保存爲矩陣(這是保存稀疏矩陣的正確方法)。
如果你多了一點你的答案,我相信這是解決這個問題的正確方法。 –
這當然是一個可能的解決方案。但是,它將包括迭代200多個元素(200000x100000的1%)。我更喜歡矢量化解決方案(如果有的話) – tokarev
如果在W中只有零個元素的完整行,那麼可以將A中的對應行置零,如果您有完整的只有零的列,則相同 - 您可以將零B中的相應元素 - 然後使用'scipy.sparse'來乘以矩陣。 –
下面是使用np.einsum
用於矢量化溶液中的一種方法 -
from scipy import sparse
from scipy.sparse import coo_matrix
# Get row, col for the output array
r,c,_= sparse.find(W)
# Get the sum-reduction using valid rows and corresponding cols from A, B
out = np.einsum('ij,ji->i',A[r],B[:,c])
# Store as sparse matrix
out_sparse = coo_matrix((out, (r, c)), shape=W.shape)
樣品運行 -
1)輸入:
In [168]: A
Out[168]:
array([[4, 6, 1, 1, 1],
[0, 8, 1, 3, 7],
[2, 8, 3, 2, 2],
[3, 4, 1, 6, 3]])
In [169]: B
Out[169]:
array([[5, 2, 4],
[2, 1, 3],
[7, 7, 2],
[5, 7, 5],
[8, 5, 0]])
In [176]: W
Out[176]:
<4x3 sparse matrix of type '<type 'numpy.bool_'>'
with 5 stored elements in Compressed Sparse Row format>
In [177]: W.toarray()
Out[177]:
array([[ True, False, False],
[False, False, False],
[ True, True, False],
[ True, False, True]], dtype=bool)
2)使用密集陣列,以直接執行計算並稍後驗證結果:
In [171]: (A.dot(B))*W.toarray()
Out[171]:
array([[52, 0, 0],
[ 0, 0, 0],
[73, 57, 0],
[84, 0, 56]])
3)使用所提出的代碼,並獲得稀疏矩陣輸出:
In [172]: # Using proposed codes
...: r,c,_= sparse.find(W)
...: out = np.einsum('ij,ji->i',A[r],B[:,c])
...: out_sparse = coo_matrix((out, (r, c)), shape=W.shape)
...:
4)通過轉換爲密/陣列版本和檢查免受直接版本最後驗證結果 -
In [173]: out_sparse.toarray()
Out[173]:
array([[52, 0, 0],
[ 0, 0, 0],
[73, 57, 0],
[84, 0, 56]])
- 1. 稀疏矩陣乘法執行時間
- 2. 並行矩陣乘法
- 3. 矩陣序列的矩陣乘法
- 4. 比較兩個矩陣之間的行
- 5. 超過掩蔽陣列的子陣列有效地平均
- 6. Java中的並行矩陣乘法6
- 7. 並行乘以小矩陣
- 8. Python矩陣乘法; numpy的陣列
- 9. 矩陣乘法
- 10. 矩陣乘法
- 11. 分而治之矩陣乘法與經典矩陣乘法執行相同數量的加法/減法嗎?
- 12. 在矩陣中添加行與矩陣之間的矩陣
- 13. 矩陣乘法和系列
- 14. Numpy 3D陣列矩陣乘法函數
- 15. 矩陣的乘法
- 16. 的矩陣乘法
- 17. Matlab 2x2矩陣的陣列和逐元矩陣/向量乘法
- 18. LDL的Numpy陣列乘法對稱矩陣的分解乘法
- 19. 矩陣行與另一個列的乘法的快速方式
- 20. C++矩陣乘法行列數
- 21. 使用CUDA進行矩陣乘法,執行時間很長
- 22. OpenGL矩陣乘法導致奇數浮點行爲
- 23. MATLAB:乘法2D矩陣與3D矩陣單元陣列
- 24. 矩陣(scipy稀疏) - 矩陣(密集; numpy陣列)乘法效率
- 25. 執行矩陣之間的成對迴歸分析在兩個列表
- 26. CUBLAS矩陣乘法
- 27. 矩陣乘法alglib
- 28. 乘法矩陣Matlab
- 29. 塊矩陣乘法
- 30. Accord.NET矩陣乘法
在那裏很好的使用'sp.nonzero'!可能是更快的選擇。你介意我在帖子中提到它嗎? :) – Divakar
'sp.nonzero'和'sp.find'幾乎相同 - 返回'coo'格式的屬性。 'find'也只返回'data'屬性。如果'W'已經是'coo',則直接使用它的'row'和'col'屬性。 – hpaulj
'scipy.nonzero'是'np.nonzero',它又轉向'W.nonzero'。在進一步的檢查中,'sparse.find'比較慢,因爲它通過'csr'格式進行一次往返以對重複進行求和。 'iX,iY = W.row,W.col'甚至更快(如果W已經是coo)。 – hpaulj