【问题标题】:Diagonal sparse matrix obtained from a sparse coo_matrix从稀疏 coo_matrix 获得的对角稀疏矩阵
【发布时间】:2015-01-16 03:50:35
【问题描述】:

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

A = M + M.T - D

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

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

【问题讨论】:

    标签: python scipy sparse-matrix


    【解决方案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.col (sparse/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 格式时相加。因此,您可以将Mrow, col, data 数组与M.T 的数组堆叠在一起(请参阅M.transpose 了解它们的构造方式),以及D 的掩码值。 (或者可以从MM.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() 
    

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

    【讨论】:

    • 太棒了!感谢您详细而准确的回答。
    【解决方案2】:

    你可能想要

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

    这仍然会构建一个 M 大小的一维数组作为中间步骤,但这可能不会那么糟糕。

    【讨论】:

    • 我会保留D 的默认dia 格式,并让sparse 在添加过程中对其进行转换。 M+M.Tcsr,这是数学的最佳格式。
    猜你喜欢
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2018-01-19
    • 1970-01-01
    • 2011-03-07
    • 2015-07-22
    相关资源
    最近更新 更多