Cython编译报错:Buffer types仅允许作为函数局部变量的解决咨询
Cython生成Mini Batch函数编译错误解决
错误原因
Cython语法规则明确:带具体类型、维度标注的np.ndarray[DTYPE_t, ndim=2]这类buffer类型,仅允许作为函数内部的局部变量使用,不能直接作为函数的输入参数。你直接在函数参数中使用该标注,触发了编译检查报错。
解决方法
提供两种可行的修正方案,任选其一即可:
方案1:参数用通用np.ndarray,内部声明带类型的局部变量
将函数参数改为无类型约束的np.ndarray,在函数内部把参数赋值给带具体类型、维度标注的局部变量,后续逻辑保持不变:
import numpy as np cimport cython cimport numpy as np ctypedef np.float64_t DTYPE_t @cython.boundscheck(False) def create_mini_batches(np.ndarray X, np.ndarray y, int batch_size): # 内部声明带类型和维度的局部变量 cdef np.ndarray[DTYPE_t, ndim=2] X_arr = X cdef np.ndarray[DTYPE_t, ndim=2] y_arr = y cdef int m cdef int num_of_batch # 改用int类型,避免浮点精度问题 cdef np.ndarray[DTYPE_t, ndim=2] shuffle_X cdef np.ndarray[DTYPE_t, ndim=2] shuffle_y cdef list permutation # 修正原错误的int类型声明 X_arr, y_arr = X_arr.T, y_arr.T m = X_arr.shape[0] num_of_batch = m // batch_size permutation = list(np.random.permutation(m)) shuffle_X = X_arr[permutation, :] shuffle_y = y_arr[permutation, :] for t in range(num_of_batch): mini_x = shuffle_X[t * batch_size: (t + 1) * batch_size, :] mini_y = shuffle_y[t * batch_size: (t + 1) * batch_size, :] yield (mini_x.T, mini_y.T) if m % batch_size != 0: mini_x = shuffle_X[num_of_batch * batch_size: , :] mini_y = shuffle_y[num_of_batch * batch_size: , :] yield (mini_x.T, mini_y.T)
方案2:使用内存视图(Memoryview)作为参数类型
内存视图是Cython中推荐的numpy数组传递方式,既支持类型标注,又能获得更好的性能优化:
import numpy as np cimport cython cimport numpy as np ctypedef np.float64_t DTYPE_t @cython.boundscheck(False) def create_mini_batches(DTYPE_t[:, ::1] X, DTYPE_t[:, ::1] y, int batch_size): cdef int m cdef int num_of_batch # 将内存视图转换为numpy数组进行转置等操作 cdef np.ndarray[DTYPE_t, ndim=2] X_arr = np.asarray(X).T cdef np.ndarray[DTYPE_t, ndim=2] y_arr = np.asarray(y).T m = X_arr.shape[0] num_of_batch = m // batch_size cdef list permutation = list(np.random.permutation(m)) cdef np.ndarray[DTYPE_t, ndim=2] shuffle_X = X_arr[permutation, :] cdef np.ndarray[DTYPE_t, ndim=2] shuffle_y = y_arr[permutation, :] for t in range(num_of_batch): mini_x = shuffle_X[t * batch_size: (t + 1) * batch_size, :] mini_y = shuffle_y[t * batch_size: (t + 1) * batch_size, :] yield (mini_x.T, mini_y.T) if m % batch_size != 0: mini_x = shuffle_X[num_of_batch * batch_size: , :] mini_y = shuffle_y[num_of_batch * batch_size: , :] yield (mini_x.T, mini_y.T)
额外说明:原代码中num_of_batch声明为double不合理,它是整数除法结果,改用int类型更合适;permutation之前错误声明为int,实际是list类型,也需修正。
内容的提问来源于stack exchange,提问作者Jeremy Koay
相关产品推荐
相关产品推荐

