在1D NumPy阵列上滑动标准偏差

时间:2016-11-23 20:05:41

标签: python performance numpy iteration vectorization

假设您有一个数组并且想要创建另一个数组,其值连续等于第一个数组的10个元素的标准偏差。在for循环的帮助下,它可以像下面的代码一样轻松编写。我想要做的是避免使用for循环来缩短执行时间。有什么建议吗?

Code
a = np.arange(20)
b = np.empty(11)
for i in range(11):
    b[i] = np.std(a[i:i+10])

2 个答案:

答案 0 :(得分:3)

您可以创建一个带有np.lib.stride_tricks.as_strided的滑动窗口的2D数组,这些窗口将是对给定1D数组的视图,因此不会占用更多内存。然后,只需沿第二个轴(轴= 1)使用np.std以矢量化的方式获得最终结果,就像这样 -

W = 10 # Window size
nrows = a.size - W + 1
n = a.strides[0]
a2D = np.lib.stride_tricks.as_strided(a,shape=(nrows,W),strides=(n,n))
out = np.std(a2D, axis=1)

运行时测试

功能定义 -

def original_app(a, W):
    b = np.empty(a.size-W+1)
    for i in range(b.size):
        b[i] = np.std(a[i:i+W])
    return b

def vectorized_app(a, W):
    nrows = a.size - W + 1
    n = a.strides[0]
    a2D = np.lib.stride_tricks.as_strided(a,shape=(nrows,W),strides=(n,n))
    return np.std(a2D,1)

计时和验证 -

In [460]: # Inputs
     ...: a = np.arange(10000)
     ...: W = 10
     ...: 

In [461]: np.allclose(original_app(a, W), vectorized_app(a, W))
Out[461]: True

In [462]: %timeit original_app(a, W)
1 loops, best of 3: 522 ms per loop

In [463]: %timeit vectorized_app(a, W)
1000 loops, best of 3: 1.33 ms per loop

所以,围绕 400x 加速!

答案 1 :(得分:0)

不是那么花哨,但没有循环的代码会是这样的:

a = np.arange(20)
b = [a[i:i+10].std() for i in range(len(a)-10)]