我正在尝试编写Cython代码来转储密集的特征矩阵,目标向量对比libsvm格式更快,而不是sklearn的内置代码。我收到一个编译错误,抱怨将目标向量(一个整齐的int数组)传递给相关的c函数的类型问题。
以下是代码:
import numpy as np
cimport numpy as np
cimport cython
cdef extern from "cdump.h":
int filedump( double features[], int numexemplars, int numfeats, int target[], char* outfname)
@cython.boundscheck(False)
@cython.wraparound(False)
def fastdumpdense_libsvmformat(np.ndarray[np.double_t,ndim=2] X, y, outfname):
if X.shape[0] != len(y):
raise ValueError("X and y need to have the same number of points")
cdef int numexemplars = X.shape[0]
cdef int numfeats = X.shape[1]
cdef bytes py_bytes = outfname.encode()
cdef char* outfnamestr = py_bytes
cdef np.ndarray[np.double_t, ndim=2, mode="c"] X_c
cdef np.ndarray[np.int_t, ndim=1, mode="c"] y_c
X_c = np.ascontiguousarray(X, dtype=np.double)
y_c = np.ascontiguousarray(y, dtype=np.int)
retval = filedump( &X_c[0,0], numexemplars, numfeats, &y_c[0], outfnamestr)
return retval
当我尝试使用distutils编译此代码时,我收到错误
cythoning fastdump_svm.pyx to fastdump_svm.cpp
Error compiling Cython file:
------------------------------------------------------------ ...
cdef np.ndarray[np.double_t, ndim=2, mode="c"] X_c
cdef np.ndarray[np.int_t, ndim=1, mode="c"] y_c
X_c = np.ascontiguousarray(X, dtype=np.double)
y_c = np.ascontiguousarray(y, dtype=np.int)
retval = filedump( &X_c[0,0], numexemplars, numfeats, &y_c[0], outfnamestr)
^
------------------------------------------------------------
fastdump_svm.pyx:24:58: Cannot assign type 'int_t *' to 'int *'
知道如何修复此错误吗?我最初遵循传递y_c.data的范例,这有效,但这显然不是推荐的方式。
答案 0 :(得分:3)
问题是numpy.int_t
与int
不同,您可以通过打开sizeof(numpy.int_t)
和sizeof(int)
来轻松检查此内容。
int
是一个c int,由c标准定义为至少16位,但它在我的机器上是32位。 numpy.int_t
通常是32位或64位,具体取决于您是否使用32位或64位版本的numpy,但当然有一些例外(可能对于Windows用户)。如果你想知道哪个numpy dtype与你的c_int匹配,你可以np.dtype(cytpes.c_int)
。
所以要将你的numpy数组传递给c代码,你可以这样做:
import ctypes
cdef np.ndarray[int, ndim=1, mode="c"] y_c
y_c = np.ascontiguousarray(y, dtype=ctypes.c_int)
retval = filedump( &X_c[0,0], numexemplars, numfeats, &y_c[0], outfnamestr)
答案 1 :(得分:3)
启动numpy数组以匹配计算机上的C dtype=np.dtype("i")
时,也可以使用int
。
cdef int [:] y_c
c_array = np.ascontiguousarray(y, dtype=np.dtype("i"))