【发布时间】:2014-11-12 00:25:50
【问题描述】:
我有一个 python 脚本,作为进化优化算法的一部分,我正在评估数千次偏导数。我已经逐行完成了配置文件,这种偏导数计算占用了大部分运行时间。我正在使用scipy.optimize.approx_fprime 计算偏导数,并尝试在 cython 中重写它,但没有取得多大成功。
逐行配置文件如下。我的scipy.optimize.approx_fprime 的cythonized 版本简称为approx_fprime。
Line # Hits Time Per Hit % Time Line Contents
==============================================================
84 @profile
100 1500 14889652 9926.4 25.3 df1 = approx_fprime(inp_nom,evaluate1,epsilon)
101 1500 14939889 9959.9 25.4 df2 = scipy.optimize.approx_fprime(inp_upp,evaluate1,epsilon)
下面是我的 cython 文件。
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False) # turn of bounds-checking for entire function
def approx_fprime(np.ndarray xk, f, double epsilon, *args):
# From scipy.optimize.approx_fprime
f0 = f(*((xk,) + args))
cdef np.ndarray grad = np.zeros((len(xk),), float)
cdef np.ndarray ei = np.zeros((len(xk),), float)
cdef np.ndarray d = epsilon * ei
for k in xrange(len(xk)):
ei[k] = 1.0
grad[k] = (f(*((xk + d,) + args)) - f0) / d[k]
ei[k] = 0.0
return grad
我已尝试放入所有相关的类型声明,并确保它与 numpy.但最终,正如他们所说,证据就在布丁中。这个版本并不比 scipy 版本快。该函数只有几个变量,所以它不是一个巨大的计算,并且可能只有一次迭代中增量改进的空间。但是,该函数会被一遍又一遍地调用,因为它用于进化优化算法,所以我期待/希望将性能提升数倍增加会有很大的回报。
那里的 cython 专家可以看看这段代码并帮助我弄清楚我是否走在正确的轨道上,或者这只是一个傻瓜的差事吗?
谢谢!
【问题讨论】:
-
在 Cython 中成功的关键是自己做数学,而不是依赖于 numpy 对象和函数,即使它们是矢量化的。您可能需要在循环中将 f() 应用于数组的各个元素。我不是 Cython 专家,我最近学到了一些知识,以便为巨大的矩阵制作自定义距离矩阵函数。这是我的主题:stackoverflow.com/questions/25213603/… 接受的答案对我理解事情的运作方式有很大帮助。问题有所不同,但您可能仍会发现它很有用。
-
我也不是 Cython 专家,但我知道评估数值导数(例如您在此处尝试评估)通常比评估分析导数要昂贵得多。有什么方法可以找到函数的导数并替换它们?我不知道您要解决的问题以及这是否可行。
-
您可能会发现pyautodiff 很有帮助。它使用 Theano,它可以在 GPU 上运行,并且你将它传递给 numpy 类型。