实例化大型稀疏矩阵以进行赋值操作

时间:2019-12-23 19:10:27

标签: python matlab numpy scipy sparse-matrix

如果我想实例化一个大型布尔稀疏矩阵,以便以后在某些索引处分配值,那么初始化它的最佳方法是什么?

例如,如果我想在MATLAB上用10000个填充元素初始化20000000 X 7000逻辑稀疏矩阵(不提及非零元素的位置),我将使用以下语法:

Matrix=logical(sparse([],[],[],20000000,7000,10000))

我以后分配非零值没有速度限制。

在Python上,如果我将其初始化为CSR矩阵,则矩阵的创建非常快。

Matrix=csr_matrix((20000000, 7000), dtype=bool)

CPU times: user 860 µs, sys: 2.43 ms, total: 3.29 ms
Wall time: 9.72 ms

但是,当我无法有效地将值分配给CSR_Matrix时,操作将非常缓慢,并且您会看到内置警告。

如果我尝试将其初始化为LIL矩阵:

Matrix=lil_matrix((20000000, 7000), dtype=bool)

CPU times: user 12.4 s, sys: 624 ms, total: 13 s
Wall time: 13 s

或将csr_matrix转换为lil_matrix:

Matrix=csr_matrix((20000000, 7000), dtype=bool)
Matrix=Matrix.tolil()

CPU times: user 26.8 s, sys: 734 ms, total: 27.5 s
Wall time: 27.5 s

初始化需要花费更多时间。

是否有任何方法可以加快LIL矩阵的初始化?如果不是,我可以使用哪种稀疏矩阵格式来加快将非零元素分配给此类矩阵的速度?

2 个答案:

答案 0 :(得分:1)

如果您需要常规的增量索引访问,则dok_matrix可能是最好的选择。

在转换为csc,csr(代数运算通常需要)之类的东西之前,通常将其用于构造(在某些情况下可能会发光)。

编辑:以下大多数内容集中于初始化+填充+之后需要执行的操作所需的累积时间。

就您的情况而言:dok_matrix的初始化应该非常即时

...

  

允许对单个元素进行有效的O(1)访问。不允许重复。构造完成后可以有效地转换为coo_matrix。

话虽如此,这还取决于您的工作流程和省略的代码。给定某种结构(python-)无环任务相关的工作流肯定可以击败一般(python-)循环一次添加一个元素。通常,这涉及coo_matrix

在某些工作流程中,您没有任何初始化时间,因为您没有创建先验矩阵,而是仅在一批创建矩阵之前收集所需的一切。不确定如何将其放入您的计算模型(这有点奇怪:初始化时间受限制;进一步的使用是免费

答案 1 :(得分:1)

相当多年前,我使用了MATLAB稀疏模型。那时,您使用

创建了一个稀疏矩阵
S = sparse(i,j,v,m,n)

其中i,j,v,其中矩阵标识了所有个非零值。不存在为更多的非零预分配“空间”的额外nz参数。

scipy中,等价于

S = sparse.csc_matrix((v, (i,j)), m, n)

同样,v,i,j是完全定义的数组。没有任何nz预分配选项。实际上,考虑到属性的存储方式,我看不到预分配如何工作或有益。

您发现,尝试使用csc/csr格式定义非零值很慢,并且会产生警告。 lil/dok旨在使迭代加法更快。

csr的创建时间取决于初始非零值的数量,而仅取决于形状(indptr数组的大小取决于行数)。通常,我们不用担心lil的初始化时间,但是有了20000000行,我知道为什么会花时间。它必须创建两个带有空列表元素的dtype数组。

无论如何,请尝试避免使用增量定义。从您的源创建i,j,v数组,然后构建矩阵。