【问题标题】:Most efficient way of accessing non-zero values in row/column in scipy.sparse matrix在 scipy.sparse 矩阵中访问行/列中非零值的最有效方法
【发布时间】:2017-04-20 10:50:39
【问题描述】:

CSR 格式访问scipy.sparse 矩阵A 的行row 或列col 中的所有非零值的最快或最不冗长的方法是什么?

以其他格式(例如,COO)会更有效吗?

现在,我使用以下内容:

A[row, A[row, :].nonzero()[1]]

A[A[:, col].nonzero()[0], col]

【问题讨论】:

    标签: python scipy sparse-matrix


    【解决方案1】:

    对于这样的问题,了解不同格式的底层数据结构是值得的:

    In [672]: A=sparse.csr_matrix(np.arange(24).reshape(4,6))
    In [673]: A.data
    Out[673]: 
    array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
           18, 19, 20, 21, 22, 23], dtype=int32)
    In [674]: A.indices
    Out[674]: array([1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5], dtype=int32)
    In [675]: A.indptr
    Out[675]: array([ 0,  5, 11, 17, 23], dtype=int32)
    

    一行的data 值是A.data 中的一个切片,但识别该切片需要A.indptr 的一些知识(见下文)

    对于coo

    In [676]: Ac=A.tocoo()
    In [677]: Ac.data
    Out[677]: 
    array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
           18, 19, 20, 21, 22, 23], dtype=int32)
    In [678]: Ac.row
    Out[678]: array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3], dtype=int32)
    In [679]: Ac.col
    Out[679]: array([1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5], dtype=int32)
    

    请注意,A.nonzeros() 转换为 coo 并返回 rowcol 属性(或多或少 - 查看其代码)。

    对于lil 格式;数据按行存储在列表中:

    In [680]: Al=A.tolil()
    In [681]: Al.data
    Out[681]: 
    array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17],
           [18, 19, 20, 21, 22, 23]], dtype=object)
    In [682]: Al.rows
    Out[682]: 
    array([[1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5],
           [0, 1, 2, 3, 4, 5]], dtype=object)
    

    ================

    选择一行A 有效,但根据我的经验,这往往有点慢,部分原因是它必须创建一个新的csr 矩阵。此外,您的表达方式似乎比需要的要冗长。

    看看我的第一行有一个 0 元素(其他的太密集了):

    In [691]: A[0, A[0,:].nonzero()[1]].A
    Out[691]: array([[1, 2, 3, 4, 5]], dtype=int32)
    

    整行,表示为密集数组是:

    In [692]: A[0,:].A
    Out[692]: array([[0, 1, 2, 3, 4, 5]], dtype=int32)
    

    但该行的data 属性与您的选择相同

    In [693]: A[0,:].data
    Out[693]: array([1, 2, 3, 4, 5], dtype=int32)
    

    并使用lil 格式

    In [694]: Al.data[0]
    Out[694]: [1, 2, 3, 4, 5]
    

    A[0,:].tocoo() 不添加任何内容。

    在选择列时直接访问csrlil 的属性并不是很好。因为csc 更好,或者转置的lil

    indptr 的帮助下直接访问csr data 将是:

    In [697]: i=0; A.data[A.indptr[i]:A.indptr[i+1]]
    Out[697]: array([1, 2, 3, 4, 5], dtype=int32)
    

    使用csr 格式的计算通常像这样遍历indptr,获取每一行的值 - 但它们在编译代码中执行此操作。

    最近的一个相关话题,逐行求非零元素的乘积: Multiplying column elements of sparse Matrix

    在那里我发现使用indptrreduceat 相当快。

    处理稀疏矩阵的另一个工具是乘法

    In [708]: (sparse.csr_matrix(np.array([1,0,0,0])[None,:])*A)
    Out[708]: 
    <1x6 sparse matrix of type '<class 'numpy.int32'>'
        with 5 stored elements in Compressed Sparse Row format>
    

    csr 实际上用这种乘法运算 sum。而且如果我没记错的话,它实际上是这样执行A[0,:]

    Sparse matrix slicing using list of int

    【讨论】:

    • 我不知道.A 属性(它简化了我的np.asarray.toarray().todense() 在我的代码的其他部分混乱)。 .data 属性确实给了我我需要的东西。也感谢有关.indptr 的提示!
    • 我投票得最高的答案是一个更加晦涩的属性M.A1,它将matrix 转换为一维数组stackoverflow.com/questions/3337301/numpy-matrix-to-array/…
    猜你喜欢
    • 2015-08-30
    • 2017-02-02
    • 2011-10-14
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    相关资源
    最近更新 更多