如何避免稀疏到稠密的矩阵转换

时间:2018-10-07 02:54:41

标签: python numpy scipy sparse-matrix

我有一个简单的代码,可以在Numpy / Scipy中处理稀疏矩阵,其代码如下所示:

import numpy as np
import scipy as sp
from scipy.sparse import csr_matrix as sparse
from scipy.sparse import vstack
from scipy.linalg import toeplitz

N = 100
d4 = np.array([-22/24, 17/24, 9/24 ,-5/24, 1/24])
s4 = np.array([1/24,-9/8,9/8,-1/24])
n = len(s4)
r4 = sparse((s4, (np.zeros(n), np.arange(n))), shape=[1, N+1])
c4 = sparse(([s4[0]], ([0], [0])), shape=[N-2, 1])
lnd = len(d4)
rd4 = sparse((d4, (np.zeros(lnd), np.arange(lnd))), shape=[1, N+1])
D = sparse(np.concatenate((rd4.todense(), toeplitz(c4.todense(),r4.todense()), np.fliplr(rd4.todense()))))

我想删除从sparsedense的转换,但是不知道如何在不进行转换的情况下替换toeplitz函数和fliplr。现在我有这个:

D = vstack([rd4, sparse(toeplitz(c4.todense(),r4.todense())), sparse(np.fliplr(rd4.todense()))])

当然,我可以使用非稀疏矩阵并在最后进行转换,但是我希望始终使用稀疏矩阵。还有更好的主意吗?

1 个答案:

答案 0 :(得分:1)

以下是使用scipy.sparse.diags的方法。 diagsspdiags类似,但更加方便。

>>> import numpy as np
>>> from scipy import sparse, linalg
>>> 
>>> a = sparse.csr_matrix(np.random.randint(-50, 10, (1, 10)).clip(0, None))
>>> b = sparse.csr_matrix(np.random.randint(-50, 10, (1, 10)).clip(0, None))

此示例包含行向量,对于列向量,可以将其强制转换为csc,然后以相同的方式进行。

>>> # dense method for reference
>>> d_toepl = linalg.toeplitz(a.A, b.A)
>>> 
>>> idx = b.indices[0] == 0 # make sure first element of b is ignored
>>> vals, offs = np.r_[a.data, b.data[idx:]], np.r_[-a.indices, b.indices[idx:]]
>>> N = max(a.shape[1], b.shape[1])
>>> dtype = (a[0, ...] + b[0, ...]).dtype
>>> 
>>> s_toepl = sparse.diags(vals, offs, (N, N), dtype=dtype)
>>> 
>>> np.all(d_toepl == s_toepl)
True

fliplr可以通过建立索引来完成。小陷阱:目前并非所有的稀疏矩阵类都支持索引编制,您可能必须强制转换。

>>> np.all(np.fliplr(d_toepl) == s_toepl.tocsr()[:, ::-1])
True