scipy.sparse的哪种格式最适合这种类型的矩阵生成和使用?

时间:2015-09-05 00:35:14

标签: python scipy vectorization sparse-matrix

我有一个数据文件,它编码有关大型稀疏布尔矩阵的非零元素的信息。该矩阵不具有任何特定结构,即它不是对角线或块等。文件的每一行确定一个元素。现在我使用以下循环来填充矩阵:

from scipy.sparse import dok_matrix

nRows = 30000
nCols = 600000

data = dok_matrix((nRows,nCols), dtype=np.int8)

with open('input.txt','r') as fraw:
    for line in fraw:
        ## Figure out iRow and iCol to set to 1 from line
        data[iRow,iCol] = 1

这很有效,但速度很慢。是否有不同类型的scipy.sparse矩阵更优化?

'最优'表示矩阵生成和矩阵的行和列块的访问速度,例如矩阵。矢量操作如

someRows = data[rowIndex1:rowIndex2,]
someColumns = data[,colIndex1:colIndex2]

如果内存比速度更重要,答案是否会改变?

THX

1 个答案:

答案 0 :(得分:2)

对于像dok这样的增量添加,它就像它一样好。它实际上是一个将值存储在元组中的字典:(iRow,iCol)。所以存储和获取取决于Python的基本效率。

唯一适合增量添加的是lil,它将数据存储为2个列表列表。

另一种方法是在3个列表中收集数据,并在最后构建矩阵。一个开头是coo及其(data,(i,j))输入法。

numpygenfromtxt的文件加载密集loadtxt数组。这两个人一行一行地读取文件,在列表列表中收集值,最后创建数组。

如果您只是阅读文件并解析值,速度会是什么样的 - 而不保存dok的任何内容?这样可以让您了解将数据添加到矩阵实际花费了多少时间。

另一种可能性是将值直接存储到通用字典中,并使用它来创建dok

In [60]: adict=dict()

In [61]: for i in np.random.randint(1000,size=(2000,)):
    adict[(i,i)]=1
   ....:     

In [62]: dd=sparse.dok_matrix((1000,1000),dtype=np.int8)

In [63]: dd.update(adict)

In [64]: dd.A
Out[64]: 
array([[1, 0, 0, ..., 0, 0, 0],
       [0, 1, 0, ..., 0, 0, 0],
       [0, 0, 1, ..., 0, 0, 0],
       ..., 
       [0, 0, 0, ..., 1, 0, 0],
       [0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 0, 1]], dtype=int8)

这比直接更新dok快得多。

In [66]: %%timeit 
for i in np.random.randint(1000,size=(2000,)):
    adict[(i,i)]=1
dd.update(adict)
   ....: 
1000 loops, best of 3: 1.32 ms per loop

In [67]: %%timeit 
for i in np.random.randint(1000,size=(2000,)):
    dd[i,i]=1
   ....: 
10 loops, best of 3: 35.6 ms per loop

更新我未考虑的dok时必须有一些开销。

我刚刚意识到我之前曾建议使用此update方法:

https://stackoverflow.com/a/27771335/901925 Why are lil_matrix and dok_matrix so slow compared to common dict of dicts?