有没有更快的方法从 scipy.sparse.dok_matrix 中提取 row/column 子矩阵?

Is there a faster way of extracting row/column submatrices from scipy.sparse.dok_matrix?

我正在使用 numpydok_matrix 稀疏矩阵和 Matlab 风格,需要提取行或列的块,例如

import numpy as np
from scipy.sparse import dok_matrix
#
# Boolean data matrix X created here
#
print X.shape   #(24000, 110000)
# Size below is approx but shows I need need most of the original rows
rowIndsINeed = np.zeros(22000)  
#
# Populate rowIndsINeed here
#
Xsubmat = X[rowIndsINeed,]  # this is slooooow

问题:

  1. 如果 rowIndsINeed 包含大部分原始索引,是否有更快的提取子矩阵的方法?
  2. 如果相反,即 rowIndsINeed 相对较短怎么办?
  3. 如果我提取列而不是行,#1 或 2 的答案会改变吗?
  4. 我应该将 X 转换为其他稀疏格式吗?它没有任何方便的结构,即它不是块或对角线等。我还需要进行其他块操作,如 "find all rows/columns with number of 1's above N"、"find the number of common 0's/1's in rows/columns k1 and k2" 等。

以防万一,我 运行 在具有 11GB RAM 的 RedHat 6 机器上

构造样本随机矩阵:

In [130]: M=sparse.rand(100,100,.1,format='dok')
In [131]: M
Out[131]: 
<100x100 sparse matrix of type '<class 'numpy.float64'>'
    with 1000 stored elements in Dictionary Of Keys format>
In [132]: M[0,:]
Out[132]: 
<1x100 sparse matrix of type '<class 'numpy.float64'>'
    with 6 stored elements in Dictionary Of Keys format>

像你这样的索引:

In [133]: idx=np.zeros((80,),int)
In [134]: M[idx,]
Out[134]: 
<80x100 sparse matrix of type '<class 'numpy.float64'>'
    with 480 stored elements in Dictionary Of Keys format>

它返回了一个矩阵,其中包含第 0 行的 80 个副本(80*6=480 个非零元素)。

这听起来不是很有用。

但是让我们尝试一些时间:

In [142]: timeit M[idx,]
100 loops, best of 3: 13.2 ms per loop
In [143]: timeit M.tocsr()[idx,]
100 loops, best of 3: 2.33 ms per loop
In [144]: timeit M.tocsc()[idx,]
100 loops, best of 3: 2.87 ms per loop
In [145]: timeit M.tolil()[idx,]
100 loops, best of 3: 4.39 ms per loop
In [146]: %%timeit m1=M.tocsr()
   .....: m1[idx,]
   .....: 
1000 loops, best of 3: 691 µs per loop

因此转换为 csr 可以显着提高速度,特别是如果您可以在执行其他操作之前进行一次转换。

您可以对其他操作进行类似的测试。

如果您的目标是 select M 的前 80 行,请使用:

In [182]: timeit M[np.arange(80),:]
100 loops, best of 3: 15.1 ms per loop
In [183]: timeit M[np.arange(100)<80,:]
100 loops, best of 3: 15 ms per loop
In [184]: timeit M[:80,:]
100 loops, best of 3: 5.63 ms per loop