【问题标题】:How to perform a rolling sum along a matrix axis?如何沿矩阵轴执行滚动求和?
【发布时间】:2014-10-21 11:14:12
【问题描述】:

给定矩阵XT 行和列k

T = 50
H = 10
k = 5 
X = np.arange(T).reshape(T,1)*np.ones((T,k))

如何以延迟H沿行轴执行X的滚动累积和?

Xcum = np.zeros((T-H,k))
for t in range(H,T):
    Xcum[t-H,:] = np.sum( X[t-H:t,:], axis=0 )

注意,根据广播/矢量化最佳实践,最好避免跨步和卷积。

【问题讨论】:

  • 你检查np.cumsum()了吗?
  • 是的,找不到“滚动”部分的答案。
  • 为什么“广播/矢量化”最佳实践可以排除罢工?
  • strides 可以是“最佳实践”。这是个人观点,我认为 strides 是一种“深入了解”的解决方案。

标签: python numpy scipy vectorization array-broadcasting


【解决方案1】:

听起来您想要以下内容:

import scipy.signal
scipy.signal.convolve2d(X, np.ones((H,1)), mode='valid')

这当然使用卷积,但问题,如前所述,是卷积运算。广播会导致更慢/内存密集型算法。

【讨论】:

    【解决方案2】:

    您实际上缺少滚动总和的最后一行,这将是正确的输出:

    Xcum = np.zeros((T-H+1, k))
    for t in range(H, T+1):
        Xcum[t-H, :] = np.sum(X[t-H:t, :], axis=0)
    

    如果您需要仅使用 numpy 在任意轴上执行此操作,最简单的方法是沿该轴执行 np.cumsum,然后将结果计算为两个切片的差异。使用您的示例数组和轴:

    temp = np.cumsum(X, axis=0)
    Xcum = np.empty((T-H+1, k))
    Xcum[0] = temp[H-1]
    Xcum[1:] = temp[H:] - temp[:-H]
    

    另一种选择是使用 pandas 及其 rolling_sum 函数,它显然可以根据您的需要在二维数组上工作:

    import pandas as pd
    Xcum = pd.rolling_sum(X, 10)[9:] # first 9 entries are NaN
    

    【讨论】:

      【解决方案3】:

      这是一个跨步的解决方案。我知道这不是你想要的,但我想知道它是如何比较的。

      def foo2(X):
          temp = np.lib.stride_tricks.as_strided(X, shape=(H,T-H+1,k), 
              strides=(k*8,)+X.strides))
          # return temp.sum(0)
          return np.einsum('ijk->jk', temp)
      

      这次是 35 us,而 Jaime 的 cumsum 解决方案是 22 us。 einsumsum(0) 快​​一点。 temp 使用 X 的数据,因此没有内存损失。但更难理解。

      【讨论】:

      • 对于大窗口,这将重做很多工作...当您将窗口滑动一个位置时,最佳算法会从最后一个窗口总和中减去从左侧出来的项目窗口,并添加从右侧进入的窗口。如果您将解决方案的时间设置为较小的 H 值,您应该会看到与 cumsum 相比,您的时间有所改善。
      猜你喜欢
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      • 2018-06-04
      • 2014-10-09
      相关资源
      最近更新 更多