有没有更快的方法从 scipy.sparse.dok_matrix 中提取 row/column 子矩阵?
Is there a faster way of extracting row/column submatrices from scipy.sparse.dok_matrix?
我正在使用 numpy
的 dok_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
问题:
- 如果
rowIndsINeed
包含大部分原始索引,是否有更快的提取子矩阵的方法?
- 如果相反,即
rowIndsINeed
相对较短怎么办?
- 如果我提取列而不是行,#1 或 2 的答案会改变吗?
- 我应该将
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
我正在使用 numpy
的 dok_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
问题:
- 如果
rowIndsINeed
包含大部分原始索引,是否有更快的提取子矩阵的方法? - 如果相反,即
rowIndsINeed
相对较短怎么办? - 如果我提取列而不是行,#1 或 2 的答案会改变吗?
- 我应该将
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