BIG EDIT:
=====
为了清楚起见,我删除旧的结果并将其替换为最近的结果。问题仍然是:我是否正确使用Cython和Numba,以及可以对代码进行哪些改进? (我有一个更新,更简单的临时IPython笔记本,包含所有代码和结果here)
我想我弄清楚为什么Cython,Numba和CPython之间最初没有区别:这是因为我喂它们
numpy数组作为输入:
x = np.asarray([x_i*np.random.randint(8,12)/10 for x_i in range(n)])
而不是列表:
x = [x_i*random.randint(8,12)/10 for x_i in range(n)]
我用显式循环替换了zip()
函数,然而,它并没有产生太大的影响。代码是:
def py_lstsqr(x, y):
""" Computes the least-squares solution to a linear matrix equation. """
len_x = len(x)
x_avg = sum(x)/len_x
y_avg = sum(y)/len(y)
var_x = 0
cov_xy = 0
for i in range(len_x):
temp = (x[i] - x_avg)
var_x += temp**2
cov_xy += temp*(y[i] - y_avg)
slope = cov_xy / var_x
y_interc = y_avg - slope*x_avg
return (slope, y_interc)
%load_ext cythonmagic
%%cython
def cy_lstsqr(x, y):
""" Computes the least-squares solution to a linear matrix equation. """
cdef double x_avg, y_avg, var_x, cov_xy,\
slope, y_interc, x_i, y_i
cdef int len_x
len_x = len(x)
x_avg = sum(x)/len_x
y_avg = sum(y)/len(y)
var_x = 0
cov_xy = 0
for i in range(len_x):
temp = (x[i] - x_avg)
var_x += temp**2
cov_xy += temp*(y[i] - y_avg)
slope = cov_xy / var_x
y_interc = y_avg - slope*x_avg
return (slope, y_interc)
from numba import jit
@jit
def numba_lstsqr(x, y):
""" Computes the least-squares solution to a linear matrix equation. """
len_x = len(x)
x_avg = sum(x)/len_x
y_avg = sum(y)/len(y)
var_x = 0
cov_xy = 0
for i in range(len_x):
temp = (x[i] - x_avg)
var_x += temp**2
cov_xy += temp*(y[i] - y_avg)
slope = cov_xy / var_x
y_interc = y_avg - slope*x_avg
return (slope, y_interc)
答案 0 :(得分:2)
以下是我认为Numba正在发生的事情:
Numba在Numpy
阵列上工作。没有其他的。其他一切与Numba
无关。
zip
返回Numba无法看到的任意项的迭代器。因此,Numba无法进行太多的编译。
使用for i in range(...)
循环索引可能会产生更好的结果并允许更强大的类型推断。
答案 1 :(得分:0)
使用内置sum()可能会导致问题。
这里的线性回归代码在Numba中运行得更快:
@numba.jit
def ols(x, y):
"""Simple OLS for two data sets."""
M = x.size
x_sum = 0.
y_sum = 0.
x_sq_sum = 0.
x_y_sum = 0.
for i in range(M):
x_sum += x[i]
y_sum += y[i]
x_sq_sum += x[i] ** 2
x_y_sum += x[i] * y[i]
slope = (M * x_y_sum - x_sum * y_sum) / (M * x_sq_sum - x_sum**2)
intercept = (y_sum - slope * x_sum) / M
return slope, intercept