我有一个数据文件,它编码有关大型稀疏布尔矩阵的非零元素的信息。该矩阵不具有任何特定结构,即它不是对角线或块等。文件的每一行确定一个元素。现在我使用以下循环来填充矩阵:
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
答案 0 :(得分:2)
对于像dok
这样的增量添加,它就像它一样好。它实际上是一个将值存储在元组中的字典:(iRow,iCol)
。所以存储和获取取决于Python的基本效率。
唯一适合增量添加的是lil
,它将数据存储为2个列表列表。
另一种方法是在3个列表中收集数据,并在最后构建矩阵。一个开头是coo
及其(data,(i,j))
输入法。
从numpy
或genfromtxt
的文件加载密集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?