【发布时间】:2015-11-16 20:10:42
【问题描述】:
我正在尝试使用 Theano 来加速已经在 numpy 中实现的代码,该代码对数组中的元素求和。在 numpy 中,函数如下所示
import numpy as np
def numpy_fn(k0, kN, x):
output = np.zeros_like(x)
for k in range(k0, kN+1):
output += k*x
return output
有一个示例调用
>>> numpy_fn(1, 3, np.arange(10))
array([ 0., 6., 12., 18., 24., 30., 36., 42., 48., 54.])
上述函数的theano等价物是
import theano
import theano.tensor as tt
k = tt.scalar('k')
k0 = tt.scalar('k0')
kN = tt.scalar('kN')
x = tt.vector('x')
def fn(k, sumtodate):
return sumtodate + k*x
rslt, updt = theano.scan(fn=fn,
outputs_info=tt.zeros_like(x),
sequences=tt.arange(k0, kN+1))
theano_fn = theano.function(inputs=[k0, kN, x],
outputs=rslt[-1])
调用时,会给出正确的输出
theano_fn(1, 3, np.arange(10))
array([ 0., 6., 12., 18., 24., 30., 36., 42., 48., 54.])
但是,当我对这两者进行基准测试时,numpy 函数在我的计算机上的速度超过了 theano 的三倍。
%timeit theano_fn(1, 1000, np.ones(10000))
10 loops, best of 3: 21.5 ms per loop
%timeit numpy_fn(1, 1000, np.ones(10000))
100 loops, best of 3: 7.9 ms per loop
既然theano把outerloop转成C,那它不应该比Python快吗?有什么办法可以加快 theano 代码的速度?
编辑:
我知道 numpy 中的粗略代码可以使用求和进行优化,但我想采用 theano 路线的原因是因为我对输出更新可以是k 的任何通用函数的情况感兴趣和x,说
output += x**k
output += exp(k*x)
output += (x-k)**2
output += k*x 只是说明这一点的一个具体例子。使用数学符号我试图实现的是快速求和\sum_{k=k0}^{kN} f(k, x),其中k0 和kN 是整数,x 是向量,f 可以是k 和x 就像上面给出的一样。
import numpy as np
def f(k, x):
return x**k
def numpy_fn(k0, kN, x):
output = np.zeros_like(x)
for k in range(k0, kN+1):
output += f(k, x)
return output
我希望通过使用 theano,我将能够优化外循环,并获得比粗暴的 numpy 解决方案更快的解决方案。
【问题讨论】:
-
我还没有深入研究 Numpy,但我会说我更喜欢 Numpy 代码而不是来自 theano 的代码 - 更容易阅读 - 也许 Python 在阅读 Theano 代码时更难: -)