在Python中向量化重复数学函数

Pyt*_*ner 2 python numpy vectorization mathematical-expressions

我有这种形式的数学函数,$f(x)=\sum_{j=0}^N x^j * \sin(j*x)$希望在中高效地进行计算Python。N约为100。对于巨大矩阵的所有条目x,该函数f评估了数千次,因此我想提高性能(分析器表明f的计算大部分时间都花在了计算上)。为了避免在函数f的定义中出现循环,我写了:

def f(x)
    J=np.arange(0,N+1)
    return sum(x**J*np.sin(j*x))
Run Code Online (Sandbox Code Playgroud)

问题是,如果要对矩阵的所有条目求值该函数,则需要先使用numpy.vectorize,但据我所知,这不一定比for循环快。

有没有一种有效的方法来执行这种类型的计算?

Peq*_*que 5

欢迎来到麻袋溢出!^^

好吧,计算something ** 100是一件严肃的事情。但是请注意,在声明数组时J,如何强制函数x, x^2, x^3, x^4, ...独立进行计算(依此类推)。

让我们以这个函数为例(您正在使用的函数):

def powervector(x, n):
    return x ** np.arange(0, n)
Run Code Online (Sandbox Code Playgroud)

现在,这另一个函数甚至不使用NumPy:

def power(x, n):
    result = [1., x]
    aux = x
    for i in range(2, n):
        aux *= x               
        result.append(aux)
    return result
Run Code Online (Sandbox Code Playgroud)

现在,让我们验证他们两个都计算相同的东西:

In []: sum(powervector(1.1, 10))
Out[]: 15.937424601000005

In []: sum(power(1.1, 10))
Out[]: 15.937424601000009
Run Code Online (Sandbox Code Playgroud)

很酷,现在让我们比较两者的性能(在iPython中):

In [36]: %timeit sum(powervector(1.1, 10))
The slowest run took 20.42 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 3.52 µs per loop

In [37]: %timeit sum(power(1.1, 10))
The slowest run took 5.28 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 1.13 µs per loop
Run Code Online (Sandbox Code Playgroud)

由于您没有计算的所有幂x,因此它速度更快,因为您知道这一点x ^ N == (x ^ N - 1) * x并可以利用它。

您可以使用它来查看您的性能是否有所提高。当然,您可以更改power()为将NumPy向量用作输出。您也可以看看Numba,它很容易尝试,并且可能也会提高性能。

如您所见,这仅是有关如何改善问题的一部分的提示。我敢打赌,还有其他几种方法可以进一步改善您的代码!:-)

编辑

看起来Numba可能不是一个坏主意……只需添加@numba.jit装饰器即可:

@numba.jit
def powernumba(x, n):
    result = [1., x]
    aux = x
    for i in range(2, n):
        aux *= x               
        result.append(aux)
    return result
Run Code Online (Sandbox Code Playgroud)

然后:

In [52]: %timeit sum(power(1.1, 100))
100000 loops, best of 3: 7.67 µs per loop

In [51]: %timeit sum(powernumba(1.1, 100))
The slowest run took 5.64 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 2.64 µs per loop
Run Code Online (Sandbox Code Playgroud)

看来Numba可以在那做一些魔术。;-)