【问题标题】:Can the cumsum function in NumPy decay while adding?NumPy 中的 cumsum 函数在添加时会衰减吗?
【发布时间】:2015-05-09 00:29:17
【问题描述】:

我有一个值数组a = (2,3,0,0,4,3)

y=0
for x in a:
  y = (y+x)*.95

有什么方法可以在numpy 中使用cumsum 并在添加下一个值之前对每一行应用0.95 衰减?

【问题讨论】:

    标签: python arrays numpy cumsum


    【解决方案1】:

    您要求一个简单的IIR Filter。 Scipy 的lfilter() 就是为此而生的:

    import numpy as np
    from scipy.signal import lfilter
    
    data = np.array([2, 3, 0, 0, 4, 3], dtype=float)  # lfilter wants floats
    
    # Conventional approach:
    result_conv = []
    last_value = 0
    for elmt in data:
        last_value = (last_value + elmt)*.95
        result_conv.append(last_value)
    
    # IIR Filter:
    result_IIR = lfilter([.95], [1, -.95], data)
    
    if np.allclose(result_IIR, result_conv, 1e-12):
        print("Values are equal.")
    

    【讨论】:

    • 我会考虑在这里改用xx = np.array([2, 3, 0, 0, 4, 3], dtype=np.float64)
    • 有效点。我重新运行了我的代码,似乎来自lfilter() 的投诉来自另一个问题。
    【解决方案2】:

    如果您只处理一维数组,那么缺少 scipy 便利或为 numpy 编写自定义 reduce ufunc,那么在 Python 3.3+ 中,您可以使用 itertools.accumulate,例如:

    from itertools import accumulate
    
    a = (2,3,0,0,4,3)
    y = list(accumulate(a, lambda x,y: (x+y)*0.95))
    # [2, 4.75, 4.5125, 4.286875, 7.87253125, 10.3289046875]
    

    【讨论】:

      【解决方案3】:

      Numba 提供了一种简单的方法来vectorize 一个函数,创建一个universal function(从而提供ufunc.accumulate):

      import numpy
      from numba import vectorize, float64
      
      @vectorize([float64(float64, float64)])
      def f(x, y):
          return 0.95 * (x + y)
      
      >>> a = numpy.array([2, 3, 0, 0, 4, 3])
      >>> f.accumulate(a)
      array([  2.        ,   4.75      ,   4.5125    ,   4.286875  ,
               7.87253125,  10.32890469])
      

      【讨论】:

        【解决方案4】:

        我不认为仅在 NumPy 中不使用循环就可以轻松完成此操作。

        一个基于数组的想法是计算矩阵 M_ij = .95**i * a[N-j](其中 N 是 a 中的元素数)。您正在寻找的数字是通过对角求和条目(使用 i-j 常数)找到的。因此,您可以使用多个numpy.diagonal(…).sum()

        您概述的旧算法更清晰,可能已经相当快(否则您可以使用 Cython)。

        在没有单个循环的情况下通过 NumPy 做你想做的事对我来说听起来像是魔法。向任何能做到这一点的人致敬。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-30
          相关资源
          最近更新 更多