直接构造稀疏CSR矩阵与使用COO tocsr()-Scipy

时间:2019-01-16 22:09:31

标签: python numpy scipy sparse-matrix

我的目标是非常快速地建立稀疏的CSR矩阵。目前,它是我过程中的主要瓶颈,我已经通过相对快速地构建coo矩阵,然后使用tocsr()对其进行了优化。

但是,我想直接构造csr矩阵必须更快吗?

我有一个非常特殊的稀疏矩阵格式,它也很大(即100000x50000的量级)。我已经在网上查看了其他答案,但大多数都没有解决我的问题。

稀疏矩阵结构:

稀疏矩阵H由大小为N的W个列表组成,或者由大小为NxW的初始数组建立,将其称为A。沿着对角线,大小为N的列表重复N次。因此,对于H的前N行,重复A [:,0],但每行沿N步滑动。

与COO.tocsr()的比较

当我按比例放大N和W并首先建立COO矩阵,然后运行tocsr()时,实际上比直接建立CSR矩阵要快。我不确定为什么会这样吗?我想知道是否可以通过某种方式利用稀疏矩阵H的结构?由于其中存在许多重复元素。

代码示例

这是一个代码示例,用于可视化小样本情况下发生的情况:

from scipy.sparse import linalg, dok_matrix, coo_matrix, csr_matrix
import numpy as np
import matplotlib.pyplot as plt

def test_csr(testdata):
    indices = [x for _ in range(W-1) for x in range(N**2)]
    ptrs = [N*(i) for i in range(N*(W-1))]
    ptrs.append(len(indices))

    data = []
    # loop along the first axis
    for i in range(W-1):
        vec = testdata[:,i].squeeze()

        # repeat vector N times
        for i in range(N):
            data.extend(vec)

    Hshape = ((N*(W-1), N**2))
    H = csr_matrix((data, indices, ptrs), shape=Hshape)
    return H

N = 4
W = 8

testdata = np.random.randn(N,W)
print(testdata.shape)
H = test_csr(testdata)
plt.imshow(H.toarray(), cmap='jet')
plt.show()

Figure that shows the repeating structure of the sparse matrix

1 个答案:

答案 0 :(得分:0)

看起来您的输出仅具有测试数据的前W-1行。我不确定这是否是故意的。我的解决方案假定您要使用所有testdata

构造COO矩阵时,是否还在以类似方式构造索引和数据?

可能会加快构建csr_matrix的一件事是使用内置的numpy函数为csr_matrix生成数据,而不是python循环和数组。我希望这可以显着提高生成索引的速度。您可以根据矩阵的大小将dtype调整为其他类型的int。

N = 4
W = 8
testdata = np.random.randn(N,W)

ptrs = N*np.arange(W*N+1,dtype='int')
indices =  np.tile(np.arange(N*N,dtype='int'),W)
data = np.tile(testdata,N).flatten()

Hshape = ((N*W, N**2))
H = csr_matrix((data, indices, ptrs), shape=Hshape)

另一种可能性是首先构造大数组,然后一次定义每个N垂直列块。这意味着在将原始数据放入稀疏矩阵之前,无需复制大量数据。但是,转换矩阵类型可能会很慢。

N = 4
W = 8
testdata = np.random.randn(N,W)

Hshape = ((N*W, N**2))
H = sp.sparse.lol_matrix(Hshape)

for j in range(N): 
    H[N*np.arange(W)+j,N*j:N*(j+1)] = testdata.T

H = H.tocsc()