从稀疏的coo_matrix获得的对角稀疏矩阵

时间:2015-01-14 19:23:50

标签: python scipy sparse-matrix

我使用M格式在Python中构建了一些稀疏矩阵coo_matrix。我想找到一种有效的计算方法:

A = M + M.T - D

其中DM对其对角线的限制(M可能非常大)。我无法在保持D格式的同时找到有效构建coo_matrix的方法。有什么想法吗?

可以D = scipy.sparse.spdiags(coo_matrix.diagonal(M),0,M.shape[0],M.shape[0])成为解决方案吗?

2 个答案:

答案 0 :(得分:1)

我想出了一个更快的coo对角线:

msk = M.row==M.col
D1 = sparse.coo_matrix((M.data[msk],(M.row[msk],M.col[msk])),shape=M.shape)

sparse.tril将此方法与mask = A.row + k >= A.colsparse/extract.py

一起使用

有时(100,100)M(和M1 = M.tocsr()

In [303]: timeit msk=M.row==M.col; D1=sparse.coo_matrix((M.data[msk],(M.row[msk],M.col[msk])),shape=M.shape)
10000 loops, best of 3: 115 µs per loop

In [305]: timeit D=sparse.diags(M.diagonal(),0)
1000 loops, best of 3: 358 µs per loop

所以coo获得区域的方法很快,至少对于这个小而且非常稀疏的矩阵(在对角线上只有1次)

如果我从csr表单开始,则diags会更快。这是因为.diagonalcsr格式运行:

In [306]: timeit D=sparse.diags(M1.diagonal(),0)
10000 loops, best of 3: 176 µs per loop

但创建D只是整体计算的一小部分。再次,使用M1更快。总和以csr格式完成。

In [307]: timeit M+M.T-D
1000 loops, best of 3: 1.35 ms per loop

In [308]: timeit M1+M1.T-D
1000 loops, best of 3: 1.11 ms per loop

完成整个过程的另一种方法是利用coo允许重复i,j值的事实,这些值将在转换为csr格式时求和。因此,您可以将row, col, data的{​​{1}}数组与M的数组(请参阅M.T,了解这些数组的构建方式)以及M.transpose的屏蔽值进行叠加。 (或掩盖的对角线可以从DM

中删除

例如:

M.T
所写的

def MplusMT(M): msk=M.row!=M.col; data=np.concatenate([M.data, M.data[msk]]) rows=np.concatenate([M.row, M.col[msk]]) cols=np.concatenate([M.col, M.row[msk]]) MM=sparse.coo_matrix((data, (rows, cols)), shape=M.shape) return MM # alt version with a more explicit D # msk=M.row==M.col; # data=np.concatenate([M.data, M.data,-M.data[msk]]) 非常快,因为它只是在进行数组连接,而不是求和。为此,我们必须将其转换为MplusMT矩阵。

csr

需要更长的时间。在我的有限测试中,这种方法仍然比MplusMT(M).tocsr() 快2倍以上。因此,它是构建复杂稀疏矩阵的潜在工具。

答案 1 :(得分:0)

你可能想要

from scipy.sparse import diags
D = diags(M.diagonal(), 0, format='coo')

这仍然会构建一个M-size 1d数组作为中间步骤,但这可能不会那么糟糕。