如何正确地将一个scipy.sparse CSR矩阵传递给cython函数?

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

你想快速访问这个矩阵的值吗?也许更好的方法是传递一个 coo_matrix 并使用属性 rowcoldata 来仅访问非零值,使用 Cython 中的 1-D 数组缓冲区来提供最快的访问速度... - Saullo G. P. Castro
那正是我想要的。您能否给我一个如何做到这一点的例子? - vgoklani
根据csr文档,组件数组为data, indices, indptrcoo数组中的data, row, col更易于理解,但在大多数数学运算中,csr数组更受青睐。 - hpaulj
3个回答

6

这里有一个例子,展示了如何使用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]

3

在 @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]

indptr的长度与data不同,因此不能在同一个循环中打印。

如果要像coo一样显示csr数据,则可以使用以下迭代行进行自己的转换:

    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函数。

查看此页面以了解如何传递参数而不进行强制转换的说明。


准确地说,我应该使用什么类型来表示scipy.sparse矩阵?你在示例中定义的类型是numpy矩阵。 - vgoklani
CSR矩阵使用三个numpy数组(data、indices和indptr)表示,并且这些数组是可访问的。在这里,我们将这些数组作为CSR矩阵的代表传递给我们的cython函数。您可以在cython函数内部高效地从这些数组中重构CSR矩阵。 - SKV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接