【问题标题】:How to properly pass a scipy.sparse CSR matrix to a cython function?如何正确地将 scipy.sparse CSR 矩阵传递给 cython 函数?
【发布时间】:2014-10-07 08:15:19
【问题描述】:

我需要将 scipy.sparse CSR 矩阵传递给 cython 函数。如何指定类型,就像一个 numpy 数组一样?

【问题讨论】:

  • 你想快速访问这个矩阵的值吗?也许最好传递coo_matrix 并使用属性rowcoldata 仅访问非零值,使用 Cython 中的一维数组缓冲区为您提供最快的访问。 .
  • 这正是我想要的。你能给我一个例子来说明如何做到这一点。
  • 根据csr 文档,组件数组是data, indices, indptrcoo 数组,data, row, col 更容易理解,但csr 是大多数数学运算的首选。

标签: python numpy scipy cython sparse-matrix


【解决方案1】:

基于@SaulloCastro 的回答,将此函数添加到.pyx 文件以显示csr 矩阵的属性:

def print_csr(m):
    cdef np.ndarray[cINT32, ndim=1] indices, indptr
    cdef np.ndarray[cDOUBLE, ndim=1] data
    cdef int i
    if not isinstance(m, csr_matrix):
        m = csr_matrix(m)
    indices = m.indices.astype(np.int32)
    indptr = m.indptr.astype(np.int32)
    data = m.data.astype(np.float64)
    print indptr
    for i in range(np.shape(data)[0]):
        print indices[i], data[i]

indptrdata的长度不同,所以不能在同一个循环中打印。

要显示csr 之类的coo 数据,您可以使用这些迭代行进行自己的转换:

    for i in range(np.shape(indptr)[0]-1):
        for j in range(indptr[i], indptr[i+1]):
            print i, indices[j], data[j]

我假设您知道如何设置和编译 pyx 文件。

另外,您的cython 函数对矩阵有何假设?它知道csr 格式吗? coo 格式?

或者您的cython 函数是否需要一个常规的numpy 数组?在这种情况下,我们将走上兔子之路。您只需要将稀疏矩阵转换为数组:x.toarray()(或简称x.A)。

【讨论】:

    【解决方案2】:

    如果你想直接访问数据(不复制)你需要在函数参数中指定类型:

    import numpy as np
    cimport numpy as np
    
    #cython: boundscheck=False
    #cython: wraparound=False
    def some_cython_func(np.ndarray[np.double_t] data, np.ndarray[int] indices, np.ndarray[int] indptr):
        #body of of the function
    

    然后你可以调用这个函数使用

    some_cython_func(M.data, M.indices, M.indptr)
    

    其中M 是您的CSRCSC 函数。

    请参阅 this page 以了解不强制转换传递参数的说明。

    【讨论】:

    • 没错,那么我应该为 scipy.sparse 矩阵使用什么类型?您在示例中定义的类型是一个 numpy 矩阵。
    • CSR 矩阵使用三个可访问的 numpy 数组(数据、索引和 indptr)表示。在这里,我们将这些数组作为 CSR 矩阵的代表传递给我们的 cython 函数。您可以从这些数组有效地重建 cython 函数内部的 CSR 矩阵。
    【解决方案3】:

    下面是一个示例,说明如何使用属性rowcoldata 快​​速访问coo_matrix 中的数据。该示例的目的只是展示如何声明数据类型和创建缓冲区(还添加编译器指令,通常会给您带来相当大的提升)...

    #cython: boundscheck=False
    #cython: wraparound=False
    #cython: cdivision=True
    #cython: nonecheck=False
    
    import numpy as np
    from scipy.sparse import coo_matrix
    cimport numpy as np
    
    ctypedef np.int32_t cINT32
    ctypedef np.double_t cDOUBLE
    
    def print_sparse(m):
        cdef np.ndarray[cINT, ndim=1] row, col
        cdef np.ndarray[cDOUBLE, ndim=1] data
        cdef int i
        if not isinstance(m, coo_matrix):
            m = coo_matrix(m)
        row = m.row.astype(np.int32)
        col = m.col.astype(np.int32)
        data = m.data.astype(np.float64)
        for i in range(np.shape(data)[0]):
            print row[i], col[i], data[i]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-05
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多