快速累积和和功率运算符

问题描述 投票:0回答:2

我有一个预测算法,使用以下代码处理时间序列趋势直到给定的范围:

import numpy as np
horizon = 91
phi = 0.2
trend = -0.004
trend_up_to_horizon = np.cumsum(phi ** np.arange(horizon) + 1) * self.trend

在此示例中,前两个trend_up_horizon值为:

array([-0.008 , -0.0128])

是否有一种计算速度更快的方法来实现这一目标?目前这需要很长时间,因为我猜使用np.cumsum方法和**运算符是昂贵的。

谢谢你的帮助

python numpy cumulative-sum
2个回答
1
投票

你可以使用Cython让它快一点,但它并不多

在你的基本%timeit上运行np.cumsum(phi ** np.arange(horizon) + 1) * trend说我的笔记本电脑需要17.5μs,这并不多

一个等效的Cython版本是:

import numpy as np
cimport numpy as np
cimport cython

@cython.boundscheck(False)
def do_cumsum(size_t horizon, double phi, double trend):
    cdef np.ndarray[double, ndim=1] out = np.empty(horizon, dtype=np.float)
    cdef double csum = 0
    cdef int i

    for i in range(horizon):
        csum += phi ** i + 1
        out[i] = csum * trend

    return out

这将do_cumsum(horizon, phi, trend)的时间减少到6.9μs,而如果我切换到单精度/ 32位浮点数,这将减少到4.5μs

也就是说,微秒并不多,你可能最好把你的努力集中在其他地方


2
投票

你可以更快地完成这项操作。正如您已经假设的那样(不必要的)电力运营商是这里的主要问题。

除了那个Numpy没有特殊的power(float64,int64)实现,其中指数是一个小的正整数。相反,Numpy总是计算功率(float64,float64),这是一项复杂得多的任务。

Numba和Numexpr有一个特殊的简单案例功能实现(float64,int64),所以让我们在第一步尝试这个。

第一种方法

import numpy as np
import numba as nb

horizon = 91
phi = 0.2
trend = -0.004

@nb.njit()
def pow_cumsum(horizon,phi,trend):
    out=np.empty(horizon)
    csum=0.
    for i in range(horizon):
        csum+=phi**i+1
        out[i]=csum*trend
    return out

如前所述,直接计算功率是不必要的,可以重写算法以完全避免这种情况。

第二种方法

@nb.njit()
def pow_cumsum_2(horizon,phi,trend):
    out=np.empty(horizon)

    out[0]=2.*trend
    TMP=2.
    val=phi
    for i in range(horizon-1):
        TMP=(val+1+TMP)
        out[i+1]=TMP*trend
        val*=phi
    return out

计时

%timeit np.cumsum(phi ** np.arange(horizon) + 1) * trend
7.44 µs ± 89.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit pow_cumsum(horizon,phi,trend)
882 ns ± 4.91 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit pow_cumsum_2(horizon,phi,trend)
559 ns ± 3.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
© www.soinside.com 2019 - 2024. All rights reserved.