【发布时间】: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 的第二维与一维数组不同。