2016-07-26 60 views
1

我正在使用推薦系統,但我正在努力處理scipy稀疏矩陣的訪問時間。在稀疏矩陣中高效地訪問

在這種情況下,我正在實施TrustSVD,所以我需要一個有效的結構來以列和行(CSR,CSC)進行操作。我曾考慮過使用結構,字典,但是無論如何,這總是太慢,特別是與numpy矩陣操作相比。

for u, j in zip(*ratings.nonzero()): 
    items_rated_by_u = ratings[u, :].nonzero()[1] 
    users_who_rated_j = ratings[:, j].nonzero()[0] 
    # More code... 

附加: 每個循環大約需要0.033s,所以通過35000個收視率一次迭代意味着等待每次迭代(SGD)和最少的,我們正在談論的8小時25次迭代19分鐘。此外,在這裏我只是談論訪問,如果包含分解部分,則需要大約2天。

+0

您正在使用的矩陣帶狀?如果是這樣,利用這可能是非常有幫助的。如果不是,列表實現列表又如何呢?對於m×n矩陣,這具有訪問時間〜log(n),並且具有相當高的空間。 –

+0

我懷疑你需要矩陣的兩個版本(一個是轉置),並且需要直接訪問底層的數據結構。 – hpaulj

+0

不,矩陣沒有綁定。評分均勻分散在矩陣中(實際上一些項目往往比其他項目更有價值,但在此不重要)。另一件事是使用這種雙重或預先計算的結構交易記憶來提高速度。但我注意到稀疏矩陣也很慢,所以我想使用兩個數組字典(每個軸一個)。你有沒有更快的解決方案? –

回答

2

當你編制一個稀疏矩陣的索引時,特別是只需要一個行或一列,它不僅需要選擇值,還必須構造一個新的稀疏矩陣。構建是在編譯代碼中完成的,但是大部分稀疏構造都是純Python。 nonzero()[1]構造需要將矩陣轉換爲coo格式並選取rowcol屬性(查看其代碼)。

我想你可以通過看rows屬性lil格式的,或者其轉更快訪問你行的列:

In [418]: sparse.lil_matrix(np.matrix('0,1,0;1,0,0;0,1,1')) 
Out[418]: 
<3x3 sparse matrix of type '<class 'numpy.int32'>' 
    with 4 stored elements in LInked List format> 
In [419]: M=sparse.lil_matrix(np.matrix('0,1,0;1,0,0;0,1,1')) 
In [420]: M.A 
Out[420]: 
array([[0, 1, 0], 
     [1, 0, 0], 
     [0, 1, 1]], dtype=int32) 
In [421]: M.rows 
Out[421]: array([[1], [0], [1, 2]], dtype=object) 
In [422]: M[1,:].nonzero()[1] 
Out[422]: array([0], dtype=int32) 
In [423]: M[2,:].nonzero()[1] 
Out[423]: array([1, 2], dtype=int32) 
In [424]: M.T.rows 
Out[424]: array([[1], [0, 2], [2]], dtype=object) 

你也可以在csr格式訪問這些值,但它是一個有點更復雜

In [425]: M.tocsr().indices 
Out[425]: array([1, 0, 1, 2], dtype=int32) 
+0

非常感謝。這加快了代碼的x2-2.5,所以最終的解決方案是加上每個軸的caché(用戶,項目)。 –