2016-07-26 73 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é(用户,项目)。 –