我需要将一个scipy.sparse CSR矩阵传递给cython函数。我该如何指定类型,就像为numpy数组指定类型一样?
这里有一个例子,展示了如何使用row
、col
和data
属性快速访问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]
在 @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
)。
如果您想直接访问数据(不进行复制),则需要在函数参数中指定类型:
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
是你的CSR
或CSC
函数。
查看此页面以了解如何传递参数而不进行强制转换的说明。
coo_matrix
并使用属性row
、col
和data
来仅访问非零值,使用 Cython 中的 1-D 数组缓冲区来提供最快的访问速度... - Saullo G. P. Castrocsr
文档,组件数组为data, indices, indptr
。coo
数组中的data, row, col
更易于理解,但在大多数数学运算中,csr
数组更受青睐。 - hpaulj