【问题标题】:Cython error message: Buffer has wrong number of dimensions (expected 1, got 2)Cython 错误消息:缓冲区的维数错误(预期为 1,得到 2)
【发布时间】:2012-04-12 00:29:12
【问题描述】:

出于学习目的,我正在尝试在 Cython 中编写最小二乘估计器。我得到了这个基本版本:

import cython
import numpy as np
from scipy.linalg import inv
cimport numpy as np


def ols_c(np.ndarray x, np.ndarray y):
  cdef int nrowx = x.shape[0]
  cdef int ncolx = x.shape[1]
  cdef np.ndarray beta = np.zeros([ncolx,1], dtype=float) 
  cdef np.ndarray a1 = np.zeros([ncolx, ncolx], dtype=float)
  cdef np.ndarray a2 = np.zeros([ncolx, nrowx], dtype=float)
  a1 = inv(np.dot(x.T,x))
  a2 = np.dot(a1,x.T)
  beta = np.dot(a2,y)
  return(beta)

比这个 Numpy 版本稍慢:

import numpy as np
from scipy.linalg import inv

def ols(x,y):
  a1 = inv(np.dot(x.T,x))
  a2 = np.dot(a1,x.T)
  beta = np.dot(a2,y)
  return(beta)

我猜这可能是由于数组索引效率低下。根据网上的教程,我修改了基本的 Cython 版本,如下所示:

import cython
import numpy as np
from scipy.linalg import inv
cimport numpy as np
DTYPE = np.float
ctypedef np.float_t DTYPE_t


def ols_c(np.ndarray[DTYPE_t, ndim=2] x, np.ndarray[DTYPE_t, ndim=1] y):
  cdef int nrowx = x.shape[0]
  cdef int ncolx = x.shape[1]
  cdef np.ndarray[DTYPE_t, ndim=1] beta = np.zeros([ncolx,1], dtype=float) 
  cdef np.ndarray[DTYPE_t, ndim=2] a1 = np.zeros([ncolx, ncolx], dtype=float)
  cdef np.ndarray[DTYPE_t, ndim=2] a2 = np.zeros([ncolx, nrowx], dtype=float)
  a1 = inv(np.dot(x.T,x))
  a2 = np.dot(a1,x.T)
  beta = np.dot(a2,y)
  return(beta)

但现在它不起作用,我收到以下错误消息:

ValueError: Buffer has wrong number of dimensions (expected 1, got 2)

是什么导致了这个错误?我还有一些其他问题:

这两行实际上是做什么的?

DTYPE = np.float
ctypedef np.float_t DTYPE_t

另外,如果我理解正确键入此 cdef np.ndarray[DTYPE_t, ndim=2] x = np.zeros([ncol, nrow], dtype=float) 创建一个二维数组 x ,其列数相等到 ncol 和 row 等于 nrow,包含浮点数。但是 [DTYPE_t, ndim=2] 实际上做了什么?我还没有找到任何关于此的文档。

提前感谢您的回答!

编辑:看起来如果我用 double 替换 DTYPE_t 并注释这两行:

DTYPE = np.float
ctypedef np.float_t DTYPE_t

但是,执行仍然很慢。我可以做些什么来加快速度?

【问题讨论】:

  • 哪一行导致异常?我看到一个潜在的问题 - beta 被定义为一维,但它的值是二维的(大小为 1 的维度仍然算作维度)
  • 感谢您的回答。我将 beta 定义为一维,因为它是一个向量,这是错误的吗?我以为 ndim=1 用于只有一个轴的对象,ndim=2 用于二维数组,ndim=3 用于 3 维数组,等等……
  • 您分配给 beta 的值 np.zeros([ncolx,1]) 实际上是一个二维数组。具有长度为 1 的第二维与一维数组不同。

标签: arrays numpy cython


【解决方案1】:

关于你的速度看看@http://simula.no/research/sc/publications/Simula.SC.578/simula_pdf_file

尝试向量化代码也导致性能很差, 出于同样的原因。矢量化使用切片,切片是 未在 Cython 中实现的 Python 对象。

DeVectorizing 您的代码可能会加快速度。

【讨论】:

  • 感谢您的回答。那么在使用 cython 的时候,做点积之类的不是天意?
【解决方案2】:

这两行实际上是做什么的?

DTYPE = np.float
ctypedef np.float_t DTYPE_t

它将np.float (Python-) 类型分配给名为DTYPE 的变量并声明一个C 类型定义(ctypedef)。

在 Cython 中使用 ctypedef 关键字将使其在编译后的 Cython 代码中添加具有给定类型的 C/C++ typedef 语句。

typedef-fed 类型等于定义它的类型,但是当给它一个其他类型的值时编译器会警告你(即使它是它定义的类型)。

在使用 Cython 时,你应该对 C 或 C++ 有一点了解。

【讨论】:

  • 感谢您的回答。但是,我不明白您所说的«declares a C type definition»是什么意思以及它为什么有用。
猜你喜欢
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 2011-12-28
  • 2022-08-07
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多