2015-04-15 56 views
4

我有一個非常大的csr稀疏矩陣M。我想要得到矩陣的點積(M.dot(M.T)),並且在結果矩陣R中每行最多隻保留N。問題是dot產品M.dot(M.T)產生了MemoryError。所以我創建了點函數的修改實現,看起來像:每個結果行只保留N-max值的稀疏矩陣點積

def dot_with_top(m1, m2, top=None): 
    if top is not None and top > 0: 
     res_rows = [] 
     for row_id in xrange(m1.shape[0]): 

      row = m1[row_id] 
      if row.nnz > 0: 
       res_row = m1[row_id].dot(m2) 
       if res_row.nnz > top: 
        args_ids = np.argsort(res_row.data)[-top:] 
        data = res_row.data[args_ids] 
        cols = res_row.indices[args_ids] 
        res_rows.append(csr_matrix((data, (np.zeros(top), cols)), shape=res_row.shape)) 
       else: 
        res_rows.append(res_row) 
      else: 
       res_rows.append(csr_matrix((1, m1.shape[0]))) 
     return sparse.vstack(res_rows, 'csr') 
    return m1.dot(m2) 

它工作正常,但它有點慢。是否有可能使這個計算更快,或者你可能知道一些已經存在的方法可以更快地執行它?

+0

看起來您正在嘗試計算某些高維稀疏數據集的協方差矩陣。你打算如何使用它?根據您的最終目標是什麼,可能有辦法避免必須明確計算協方差矩陣。 –

+0

@ali_m我正在計算基於項目的協同過濾需求的餘弦相似度矩陣。根據該方法,我只需要每個項目最多30個元素。 –

+1

您是否可以將其更改爲一次處理多行塊,而不僅僅是一個?使用1000行的10個步驟應該快於10,000步。 – hpaulj

回答

1

您可以在函數中的行數上實現循環,並使用multiprocessing.Pool()對象調用此函數。 這將並行執行你的循環,並應該添加一個不錯的加速。

例子:

from multiprocessing import Pool 

def f(row_id): 
# define here your function inside the loop 
    return vstack(res_rows, 'csr') 

if __name__ == '__main__': 
    p = Pool(4) # if you have 4 cores in your processor 
    p.map(f, xrange(m1.shape[0])) 

來源:https://docs.python.org/2/library/multiprocessing.html#using-a-pool-of-workers

注意一些Python實現的功能已經使用多(在numpy的常見),所以你應該檢查時您的腳本執行前執行處理器活動此解決方案。

+1

每個過程都需要巨大的M'矩陣(對於點積)的副本。這是內存昂貴的解決方案。 –

+0

我已經實現了這一點。我有兩個20GB的陣列,必須做餘弦距離(所以你可以使用它的點)。我將很快向scipy發送拉請求。給我幾個小時 - 我會粘貼它。 – Run2