我正在尝试在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和行等于nrow,包含浮点数。但是[DTYPE_t,ndim = 2]实际上做了什么?我没有找到任何关于此的文件。
提前感谢您的回答!
编辑:看起来如果我用双倍替换DTYPE_t并注释这两行:
DTYPE = np.float
ctypedef np.float_t DTYPE_t
HOwever,执行仍然很慢。我该怎么做才能加快速度?
答案 0 :(得分:1)
关于你的速度看看@ http://simula.no/research/sc/publications/Simula.SC.578/simula_pdf_file:
尝试对代码进行矢量化也导致性能非常差, 出于同样的原因。矢量化使用切片,切片是 Python对象没有在Cython中实现。
去除代码可能会加快速度。
答案 1 :(得分:1)
这两条线实际上做了什么?
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 ++有一点了解。