scipy.linalg.block_diag vs scipy.sparse.block_diag在效率方面

时间:2018-04-06 10:31:35

标签: numpy scipy sparse-matrix coding-efficiency

我对scipy构建块对角矩阵的方式有疑问。我期望创建一个稀疏块对角矩阵比创建一个密集矩阵(由于稀疏压缩)更快更有效。但事实证明情况并非如此(或者我使用了一些效率低下的方法):

from timeit import default_timer as timer

import numpy as np
from scipy.sparse import block_diag as bd_sp
from scipy.linalg import block_diag as bd_la

m = [np.identity(1)] * 10000

before = timer()
res = bd_sp(m)
timer()-before
#takes 33.79 secs

before = timer()
res = bd_la(*m)
timer()-before
#takes 0.069 secs

我错过了什么?提前感谢您的回复。

1 个答案:

答案 0 :(得分:0)

In [625]: [np.identity(1)*i for i in range(1,5)]
Out[625]: [array([[1.]]), array([[2.]]), array([[3.]]), array([[4.]])]
In [626]: sparse.block_diag(_)
Out[626]: 
<4x4 sparse matrix of type '<class 'numpy.float64'>'
    with 4 stored elements in COOrdinate format>
In [627]: _.A
Out[627]: 
array([[1., 0., 0., 0.],
       [0., 2., 0., 0.],
       [0., 0., 3., 0.],
       [0., 0., 0., 4.]])

block_diag使用bmat加入元素。 bmat从所有元素生成coo个矩阵,并将其属性与偏移量组合在一起,并生成一个新的coo矩阵。代码是可读的Python。

构建自己的data, row, col数组可能更有效。 block_diag是一种方便,适用于组合几个大型矩阵,但在组合许多小型矩阵时效率不高。

linalg函数也是Python(非常简短)。如果创建一个正确形状的out数组,并插入带有切片索引的块。这是一种高效的密集阵列解决方案。大多数艰苦工作都是在编译的numpy代码中完成的。

在进行矩阵乘法(和相关的linalg求解器)时,稀疏矩阵可以更快。对于大多数其他操作,包括初始化,它们比等效密集代码慢。当问题太大时,它们也很有价值。